-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
104 lines (84 loc) · 2.92 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/**
* Configuration
*
* - Default config options will be loaded from `/config/defaults.json`. Also it
* will be used as reference for the Type the values should have.
*
* - Environment specific overrides are optional, using `/config/{NODE_ENV}.json`.
*
* - Environment Variables also can be used to override options (recommended for
* production).
* + Var names should be CONSTANT_CASE.
* + e.g.: `mongoUrl` => `MONGO_URL`
* + Scoped variables e.g.: `notifications.url` => `NOTIFICATIONS_URL`
* + `Arrays`s should be strings separated by commas.
* + e.g.: `"staff": ["[email protected]", "[email protected]"]` => `STAFF="[email protected],[email protected]"`
* + `Boolean`s should be `true` or `false` as strings.
* + e.g.: `"rssEnabled": false` => `RSS_ENABLED="false"`
* + Var Types are casted using `./cast-string.js`
**/
var path = require('path')
var fs = require('fs')
var typeOf = require('component-type')
var changeCase = require('change-case')
var objForEach = require('./lib/obj-for-each')
var castFromString = require('./lib/cast-from-string')
var env = process.env
module.exports = loadConfig
function loadConfig (opts) {
opts = opts || {}
var options = {}
options.environment = opts.environment || env.NODE_ENV || 'development'
options.path = opts.path || path.join(process.cwd(), 'config')
if (!options.defaultsPath) {
options.defaultsPath = path.join(options.path, 'defaults.json')
}
if (!options.currentPath) {
options.currentPath = path.join(options.path, options.environment + '.json')
}
if (!fs.existsSync(options.defaultsPath)) {
throw new Error(options.defaultsPath + ' file not found.')
}
var defaultConfig = require(options.defaultsPath)
var currentConfig = fs.existsSync(options.currentPath)
? require(options.currentPath)
: {}
var config = {}
objForEach(defaultConfig, parse)
function parse (val, key, scope) {
var s = scope ? scope.slice(0) : []
var c = get(config, s)
var newVal
if (typeOf(val) === 'object' && JSON.stringify(val) !== '{}') {
c[key] = {}
objForEach(val, parse, s.concat(key))
return
}
var envKey = s.concat(key).map(changeCase.constantCase).join('_')
if (process.env.hasOwnProperty(envKey)) {
try {
newVal = castFromString(process.env[envKey], typeOf(val))
} catch (e) {
throw new Error('There was an error when parsing ENV "' + envKey + '": ' + e)
}
c[key] = newVal
return
}
var local = get(currentConfig, s)
if (local && local.hasOwnProperty(key)) {
newVal = local[key]
if (typeOf(val) !== typeOf(newVal)) {
throw new Error('Invalid value for key "' + key + '" on "' + path.basename(options.currentPath) + '": ' + '". Should be "' + typeOf(val) + '".')
}
c[key] = newVal
return
}
c[key] = val
}
return config
}
function get (obj, scope) {
var c = obj
if (scope) scope.forEach(function (k) { c = c ? c[k] : null })
return c
}