Skip to content

Commit

Permalink
refactor(app): Extract utils and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
yugal-dream11 committed Jul 17, 2019
1 parent 9cb040b commit 39821eb
Show file tree
Hide file tree
Showing 18 changed files with 1,398 additions and 1,129 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ A simple configuration manager for typescript based projects.
npm i node-config-ts
```

2. Add a `postinstall` step in ``package.json``
2. Add a `postinstall` step in `package.json`

```json
{
Expand Down
3 changes: 1 addition & 2 deletions bin/cli
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
#!/usr/bin/env node

require('../src/createTypeAndJS')
require('../src/createTypeAndJS.js')
4 changes: 2 additions & 2 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Created by tushar on 30/12/17.
*/
import {createMergedConfig} from './src/createMergedConfig'

import {mergeAllConfigs} from './src/mergeAllConfigs'
export const config: Config = mergeAllConfigs(process)
export const config: Config = createMergedConfig(process)
11 changes: 11 additions & 0 deletions src/checkIfDefaultJson.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as fs from 'fs'
import * as path from 'path'
import {NonConfigEnv} from './configPaths'

/**
* Check if given path has default.json
*/
export const checkIfDefaultJson = <T extends NonConfigEnv>(
process: T,
p: string
) => fs.existsSync(path.resolve(process.cwd(), p))
2 changes: 1 addition & 1 deletion src/configPaths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const configPaths = <T extends NonConfigEnv>(
process.cwd(),
subDir,
`${baseDIR}/deployment/${process.env['DEPLOYMENT'] ||
DEFAULT_FILENAME}.json`
DEFAULT_FILENAME}.json`
)
const userConfig = path.resolve(
process.cwd(),
Expand Down
34 changes: 34 additions & 0 deletions src/createMergedConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as glob from 'glob'
import {baseConfigPath} from './baseConfigPath'
import {mergeFileConfigsForPath} from './mergeFileConfigsForPath'
import {checkIfDefaultJson} from './checkIfDefaultJson'
import {NonConfigEnv} from './configPaths'

const baseConfigPathName = baseConfigPath(process)

/**
* Get paths of config folder
*/
export const getAllConfigPath: <T extends NonConfigEnv>(
process: T
) => Array<string> = process =>
glob.sync(`**/${baseConfigPathName}`, {
ignore: ['node_modules/**'],
cwd: process.cwd()
})

/**
* Create merged object of nested configs
*/
export const createMergedConfig: <T extends NonConfigEnv>(
process: T
) => {[k: string]: Config} = process => {
const configPaths = getAllConfigPath(process)
const mergedConfig: {[k: string]: Config} = {}
configPaths.forEach(p => {
if (checkIfDefaultJson(process, p)) {
mergedConfig[p] = mergeFileConfigsForPath(process, p)
}
})
return mergedConfig
}
51 changes: 28 additions & 23 deletions src/createTypeAndJS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,43 @@

import * as fs from 'fs'
import * as path from 'path'
import * as glob from 'glob';
import {mergeFileConfigsForPath} from './mergeFileConfigsForPath'
import {baseConfigPath} from './baseConfigPath'
import {checkIfDefaultJson} from './checkIfDefaultJson'
import {createMergedConfig} from './createMergedConfig'

const JsonToTS = require('json-to-ts')

const typeFile = `index.d.ts`
const jsFile = 'index.js'
const defaultFileContent = ['/* tslint:disable */', '/* eslint-disable */']
const defaultJsContent = 'export const config ='
const defaultTypeFileContent = ['/* tslint:disable */', '/* eslint-disable */']
const defaultJsFileContent =
"import {config as mainConfig} from 'node-config-ts' \n export const config ="

const getJsFileBuffer = (config: Config) => defaultJsContent
.concat(JSON.stringify(config))
const getJsFileBuffer = (p: string) =>
defaultJsFileContent.concat(` mainConfig['${p}']`)

const getTsFileBuffer = (config: Config) => defaultFileContent
.concat(JsonToTS(config, {rootName: 'Config'}))
.concat('export declare const config: Config')
.join('\n')
const getTsFileBuffer = (config: Config) =>
defaultTypeFileContent
.concat(JsonToTS(config, {rootName: 'Config'}))
.concat('export declare const config: Config')
.join('\n')

const baseConfigPathName = baseConfigPath(process)

const generateTypeDefs = () => {
const configPaths = glob.sync(`**/*/${baseConfigPathName}`, {ignore: [
'node_modules/**',
]})
configPaths.forEach((p) => {
const config = mergeFileConfigsForPath(process, p)
if(fs.existsSync(path.resolve(process.cwd(), p))){
fs.writeFileSync(path.resolve(process.cwd(), p, typeFile), getTsFileBuffer(config))
fs.writeFileSync(path.resolve(process.cwd(), p, jsFile), getJsFileBuffer(config))
/**
* Write typedef and js for each path in nested config
*/
export const writeConfigFilesToSystem = () => {
const config = createMergedConfig(process)
Object.keys(config).forEach(p => {
if (checkIfDefaultJson(process, p)) {
fs.writeFileSync(
path.resolve(process.cwd(), p, typeFile),
getTsFileBuffer(config[p])
)
fs.writeFileSync(
path.resolve(process.cwd(), p, jsFile),
getJsFileBuffer(p)
)
}
})
}

generateTypeDefs()
writeConfigFilesToSystem()
3 changes: 1 addition & 2 deletions src/createTypedefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,4 @@ const ts = defaultFileContent
.concat(JsonToTS(config, {rootName: 'Config'}))
.join('\n')


fs.writeFileSync(path.resolve(process.cwd(), baseConfigPath(process), file), ts)
fs.writeFileSync(path.resolve(process.cwd(), baseConfigPath(process), file), ts)
2 changes: 1 addition & 1 deletion src/loadFileConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export type Configurations<T> = {[key in keyof T]: any}
* @param c {Process}
* @return {defaultConfig, envConfig, deploymentConfig, userConfig}
*/
export const readConfigFiles: (obj: any) => any =R.mapObjIndexed(
export const readConfigFiles: (obj: any) => any = R.mapObjIndexed(
R.ifElse(fs.existsSync, require, R.always({}))
)

Expand Down
10 changes: 5 additions & 5 deletions src/mergeAllConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ import {replaceWithEnvVar} from './replaceWithEnvVar'
import {mergeFileConfigs} from './mergeFileConfigs'
import {NonConfigEnv} from './configPaths'

export const getFileConfigsForPath: <T extends NonConfigEnv>(process: T, path: string) => any = R.compose(
export const getFileConfigsForPath: <T extends NonConfigEnv>(
process: T,
path: string
) => any = R.compose(
mergeFileConfigs,
loadFileConfigs
)
/**
* Loads all the configs from files and cli and merges them.
*/
export const mergeAllConfigs = R.converge(R.mergeDeepRight, [
R.converge(replaceWithEnvVar, [
getFileConfigsForPath,
R.identity
]),
R.converge(replaceWithEnvVar, [getFileConfigsForPath, R.identity]),
loadCLIConfigs
])
21 changes: 15 additions & 6 deletions src/mergeFileConfigsForPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,19 @@ import {mergeFileConfigs} from './mergeFileConfigs'
import {configPaths, NonConfigEnv} from './configPaths'
import {readConfigFiles} from './loadFileConfigs'
import {replaceWithEnvVar} from './replaceWithEnvVar'
import {loadCLIConfigs} from './loadCliConfigs'


export const mergeFileConfigsForPath: <T extends NonConfigEnv>(process: T, path: string) => any = R.converge(replaceWithEnvVar, [ R.compose(
mergeFileConfigs,
readConfigFiles,
configPaths
), R.identity])
export const mergeFileConfigsForPath: <T extends NonConfigEnv>(
process: T,
path: string
) => any = R.converge(R.mergeDeepRight, [
R.converge(replaceWithEnvVar, [
R.compose(
mergeFileConfigs,
readConfigFiles,
configPaths
),
R.identity
]),
loadCLIConfigs
])
12 changes: 8 additions & 4 deletions test/configPaths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ describe('config-paths', () => {
cwd: () => '/app/www.bravo.com/server'
}
const actual = configPaths(process, subPath).defaultConfig
const expected = '/app/www.bravo.com/server/test/stub-module/config/default.json'
const expected =
'/app/www.bravo.com/server/test/stub-module/config/default.json'
assert.deepEqual(actual, expected)
})
})
Expand All @@ -45,7 +46,8 @@ describe('config-paths', () => {
cwd: () => '/app/www.bravo.com/server'
}
const actual = configPaths(process, subPath).envConfig
const expected = '/app/www.bravo.com/server/test/stub-module/config/env/production.json'
const expected =
'/app/www.bravo.com/server/test/stub-module/config/env/production.json'

assert.deepEqual(actual, expected)
})
Expand All @@ -65,7 +67,8 @@ describe('config-paths', () => {
cwd: () => '/app/www.bravo.com/server'
}
const actual = configPaths(process, subPath).envConfig
const expected = '/app/www.bravo.com/server/test/stub-module/config/env/default.json'
const expected =
'/app/www.bravo.com/server/test/stub-module/config/env/default.json'

assert.deepEqual(actual, expected)
})
Expand Down Expand Up @@ -138,7 +141,8 @@ describe('config-paths', () => {
cwd: () => '/app/www.bravo.com/server'
}
const actual = configPaths(process, subPath).userConfig
const expected = '/app/www.bravo.com/server/test/stub-module/config/user/root.json'
const expected =
'/app/www.bravo.com/server/test/stub-module/config/user/root.json'

assert.deepEqual(actual, expected)
})
Expand Down
81 changes: 81 additions & 0 deletions test/createMergedConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import {createMergedConfig} from '../src/createMergedConfig'
import * as assert from 'assert'
import * as path from 'path'

describe('createMergedConfig', () => {
it('should return nested config', () => {
const process = {
argv: [],
cwd: () => path.resolve(__dirname, 'stub-module'),
env: {
NODE_ENV: undefined,
MAX_RETRIES: 999
}
}
const actual = createMergedConfig(process)
const expected = {
config: {
type: 'default',
port: 9000,
maxRetries: 999
},
'module-1/config': {
type: 'default-module-1',
maxRetries: 999,
module1Props: 'mod1'
}
}
assert.deepEqual(actual, expected)
})
it('should return nested config for given deployment, env and user', () => {
const process = {
argv: [],
cwd: () => path.resolve(__dirname, 'stub-module'),
env: {
DEPLOYMENT: 'www.example.com',
NODE_ENV: 'production',
USER: 'root',
MAX_RETRIES: 999
}
}
const actual = createMergedConfig(process)
const expected = {
config: {
type: 'user',
port: 9000,
maxRetries: 999
},
'module-1/config': {
type: 'user',
maxRetries: 999,
module1Props: 'mod1-example'
}
}
assert.deepEqual(actual, expected)
})
it('should return nested config with cli option', () => {
const process = {
argv: ['--port', '3000', '--type', 'cli-type'],
cwd: () => path.resolve(__dirname, 'stub-module'),
env: {
NODE_ENV: undefined,
MAX_RETRIES: 999
}
}
const actual = createMergedConfig(process)
const expected = {
config: {
type: 'cli-type',
port: 3000,
maxRetries: 999
},
'module-1/config': {
type: 'cli-type',
maxRetries: 999,
module1Props: 'mod1',
port: 3000
}
}
assert.deepEqual(actual, expected)
})
})
27 changes: 23 additions & 4 deletions test/mergeFileConfigsForPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import * as assert from 'assert'
import {mergeFileConfigsForPath} from '../src/mergeFileConfigsForPath'

describe('mergeConfigsForPath', () => {
const subPath = 'module-1/config'
it('should merge config for given path', () => {
const subPath = 'module-1/config'
const process = {
argv: [],
cwd: () => path.resolve(__dirname, 'stub-module'),
Expand All @@ -18,10 +18,29 @@ describe('mergeConfigsForPath', () => {
const actual = mergeFileConfigsForPath(process, subPath)
const expected = {
type: 'user',
port: 9000,
maxRetries: 999,
module1Props: 'mod1'
module1Props: 'mod1-example'
}
assert.deepEqual(actual, expected)
})
})
it('should add configs from cli', () => {
const process = {
argv: ['--port', '3000', '--type', 'cli-type'],
cwd: () => path.resolve(__dirname, 'stub-module'),
env: {
DEPLOYMENT: 'www.example.com',
NODE_ENV: 'production',
USER: 'root',
MAX_RETRIES: 999
}
}
const actual = mergeFileConfigsForPath(process, subPath)
const expected = {
type: 'cli-type',
maxRetries: 999,
module1Props: 'mod1-example',
port: '3000'
}
assert.deepEqual(actual, expected)
})
})
3 changes: 1 addition & 2 deletions test/stub-module/module-1/config/default.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"type": "default",
"port": 9000,
"type": "default-module-1",
"maxRetries": "@@MAX_RETRIES",
"module1Props": "mod1"
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"type": "deployment"
"module1Props": "mod1-example"
}
2 changes: 1 addition & 1 deletion webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ export const NodeConfigTSPlugin: {
} = R.compose(
setConfigResolver,
setGlobalConfigPlugin
)
) as {(config: Configuration): Configuration}
Loading

0 comments on commit 39821eb

Please sign in to comment.