Skip to content

Commit

Permalink
Merge branch 'master' into greenkeeper/@types/ramda-0.26.0
Browse files Browse the repository at this point in the history
  • Loading branch information
tusharmath authored Nov 9, 2018
2 parents ca47dc3 + 8c3a9eb commit afe17c7
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 21 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ A simple configuration manager for typescript based projects.
a. [Using Files](#using-files)
b. [Using Environment Variables](#using-environment-variables)
c. [Using Commandline Params](#using-commandline-params)
d. [Custom Config Directory](#custom-config-directory)
4. [Differences With Node Config](#differences-with-node-config)

## Usage
Expand Down Expand Up @@ -55,7 +56,7 @@ A simple configuration manager for typescript based projects.
5. Import and use `node-config-ts`

```typescript
import { config } from 'node-config-ts'
import {config} from 'node-config-ts'

console.log(config) // logs the config data from default.json
```
Expand All @@ -67,8 +68,9 @@ If your project uses [webpack] then with the `NodeConfigTSPlugin` you can easily
[webpack]: https://webpack.js.org

**webpack.config.ts**

```ts
import { NodeConfigTSPlugin } from 'node-config-ts/webpack'
import {NodeConfigTSPlugin} from 'node-config-ts/webpack'

export = NodeConfigTSPlugin({
// .. other stuff
Expand Down Expand Up @@ -137,6 +139,10 @@ export APP_PORT=3000
node server.js // server started with config.port as 3000
```

### Custom Config Directory

By default the base directory for loading configs is `config`. This can be configured using the ENV variable `NODE_CONFIG_TS_DIR`.

### Using commandline params

The command line arguments can override all the configuration params. This is useful when you want to start a node server by passing the port externally —
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
"webpack": "^4.17.1"
},
"scripts": {
"test": "mocha",
"prepublish": "node_modules/.bin/tsc -d",
"test": "mocha --require=ts-node/register test/**.ts",
"prepublishOnly": "node_modules/.bin/tsc -d",
"semantic-release": "semantic-release",
"travis-deploy-once": "travis-deploy-once"
},
Expand Down
20 changes: 20 additions & 0 deletions src/baseConfigPath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Default config directory
*/
const DEFAULT_BASE_DIR = 'config'

type NonConfigTSEnv = {
env: {
NODE_CONFIG_TS_DIR?: string
NODE_ENV?: string
}
}

/**
* Returns the base path for loading the configurations.
*/
export const baseConfigPath = <T extends NonConfigTSEnv>(
process: T
): string => {
return process.env['NODE_CONFIG_TS_DIR'] || DEFAULT_BASE_DIR
}
30 changes: 25 additions & 5 deletions src/configPaths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,45 @@
*/

import * as path from 'path'
import {baseConfigPath} from './baseConfigPath'

const DEFAULT_FILENAME = 'default'

export const configPaths = (process: any) => {
export type ConfigTypes = {
defaultConfig: string
envConfig: string
deploymentConfig: string
userConfig: string
}

export type NonConfigEnv = {
cwd(): string
env: {
NODE_ENV?: string
DEPLOYMENT?: string
USER?: string
NODE_CONFIG_TS_DIR?: string
}
}

export const configPaths = <T extends NonConfigEnv>(process: T): ConfigTypes => {
const baseDIR = baseConfigPath(process)
const defaultConfig = path.resolve(
process.cwd(),
`config/${DEFAULT_FILENAME}.json`
`${baseDIR}/${DEFAULT_FILENAME}.json`
)
const envConfig = path.resolve(
process.cwd(),
`config/env/${process.env['NODE_ENV'] || DEFAULT_FILENAME}.json`
`${baseDIR}/env/${process.env['NODE_ENV'] || DEFAULT_FILENAME}.json`
)
const deploymentConfig = path.resolve(
process.cwd(),
`config/deployment/${process.env['DEPLOYMENT'] || DEFAULT_FILENAME}.json`
`${baseDIR}/deployment/${process.env['DEPLOYMENT'] ||
DEFAULT_FILENAME}.json`
)
const userConfig = path.resolve(
process.cwd(),
`config/user/${process.env['USER'] || DEFAULT_FILENAME}.json`
`${baseDIR}/user/${process.env['USER'] || DEFAULT_FILENAME}.json`
)
return {defaultConfig, envConfig, deploymentConfig, userConfig}
}
4 changes: 3 additions & 1 deletion src/createTypedefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
import * as fs from 'fs'
import * as path from 'path'
import {config} from '../index'
import {baseConfigPath} from './baseConfigPath'

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

const file = `Config.d.ts`
const ts = ['/* tslint:disable */']
.concat(JsonToTS(config, {rootName: 'Config'}))
.join('\n')

fs.writeFileSync(path.resolve(process.cwd(), `config/${file}`), ts)
fs.writeFileSync(path.resolve(process.cwd(), baseConfigPath(process), file), ts)
6 changes: 5 additions & 1 deletion src/loadCliConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
import minimist = require('minimist')
import * as R from 'ramda'

type ProcessArgv = {
argv: string[]
}

/**
* Loads config from the command line
* @param process
* @return {{cliConfig: any}}
*/
export const loadCLIConfigs = (process: any) => {
export const loadCLIConfigs = <T extends ProcessArgv>(process: T) => {
return R.omit(['_'], minimist(process.argv))
}
18 changes: 12 additions & 6 deletions src/loadFileConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,21 @@
*/
import moduleExists = require('module-exists')
import * as R from 'ramda'
import {configPaths} from './configPaths'
import {configPaths, NonConfigEnv, ConfigTypes} from './configPaths'

export type Configurations<T> = {[key in keyof T]: any}

/**
* Loads the configs provided in the {ConfigPaths}
* If no config is found then an empty config is returned.
* @param process {Process}
* @return {defaultConfig, envConfig, deploymentConfig}
* @return {defaultConfig, envConfig, deploymentConfig, userConfig}
*/
export const loadFileConfigs = R.compose(
R.mapObjIndexed(R.ifElse(moduleExists, require, R.always({}))),
configPaths
)
export const loadFileConfigs = <T extends NonConfigEnv>(
process: T
): Configurations<ConfigTypes> => {
const itar: any = R.mapObjIndexed(
R.ifElse(moduleExists, require, R.always({}))
)
return itar(configPaths(process))
}
11 changes: 10 additions & 1 deletion src/replaceWithEnvVar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@ import * as R from 'ramda'

const getVarName = R.replace('@@', '')
const hasEnvVar = R.test(/^@@.*$/)
export const replaceWithEnvVar = <T>(baseConfig: T, process: any) => {

type NodeENV = {
env: {
[key: string]: string
}
}
export const replaceWithEnvVar = <T, P extends NodeENV>(
baseConfig: T,
process: P
): T => {
const itar: any = R.map((value: any) => {
if (R.is(Object, value)) return itar(value)
if (R.is(String, value) && hasEnvVar(value))
Expand Down
26 changes: 26 additions & 0 deletions test/baseConfigPath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Created by tushar on 09/11/18.
*/

import * as assert from 'assert'
import {baseConfigPath} from '../src/baseConfigPath'

describe('baseConfigPath', () => {
it('should read from env variable', () => {
const process = {
env: {NODE_ENV: 'production', NODE_CONFIG_TS_DIR: './main/config'}
}
const actual = baseConfigPath(process)
const expected = './main/config'
assert.strictEqual(actual, expected)
})

it('should read default path', () => {
const process = {
env: {NODE_ENV: 'production'}
}
const actual = baseConfigPath(process)
const expected = 'config'
assert.strictEqual(actual, expected)
})
})
21 changes: 20 additions & 1 deletion test/configPaths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe('config-paths', () => {
})
})

describe('NODE_ENV', () => {
describe('ENV:NODE_ENV', () => {
it('should return actual config path', () => {
const process = {
env: {NODE_ENV: 'production'},
Expand Down Expand Up @@ -88,4 +88,23 @@ describe('config-paths', () => {
assert.deepEqual(actual, expected)
})
})

describe('ENV:NODE_CONFIG_DIR', () => {
it('should set base config dir', () => {
const process = {
env: {NODE_ENV: 'production', NODE_CONFIG_TS_DIR: './/main/config'},
cwd: () => '/root'
}

const actual = configPaths(process)
const expected = {
defaultConfig: '/root/main/config/default.json',
deploymentConfig: '/root/main/config/deployment/default.json',
envConfig: '/root/main/config/env/production.json',
userConfig: '/root/main/config/user/default.json'
}

assert.deepEqual(actual, expected)
})
})
})
4 changes: 2 additions & 2 deletions test/replaceWithEnvVar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe('replaceWithEnvVar', () => {
it('should merge base config with available env variables', () => {
const process = {
env: {
PORT: 5050
PORT: '5050'
}
}
const baseConfig = {
Expand All @@ -23,7 +23,7 @@ describe('replaceWithEnvVar', () => {
it('should merge with deeply nested configs also', () => {
const process = {
env: {
PORT: 5050
PORT: '5050'
}
}
const baseConfig = {
Expand Down

0 comments on commit afe17c7

Please sign in to comment.