-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
162 lines (125 loc) · 3.05 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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Copyright 2019 SmugMug, Inc.
// Licensed under the terms of the MIT license. Please see LICENSE file in the project root for terms.
var assert = require('assert');
var extend = require('deap');
var match = require('minimatch');
var path = require('path');
var glob = require('glob');
var fs = require('fs');
/**
* @param {String} dirname
* @constructor
*/
function Config(dirname) {
assert(dirname, 'Config directory is required');
if (!(this instanceof Config)) {
return new Config(dirname);
}
this.dirname = dirname;
this._envs = [];
this._revs = [];
}
Config.prototype = {};
/**
* Plugins
*/
Config.prototype.env = require('./lib/env');
Config.prototype.ms = require('./lib/ms');
/**
* Define the method used to parse config files.
* You may override this method with another function
* that accepts source text and a reviver function
* with the same signature as JSON.parse expects.
* @param {String} text
* @param {Function} reviver
* @type {Function}
*/
Config.prototype.parse = JSON.parse;
/**
* Define the glob pattern used for finding config files.
* @type {String}
*/
Config.prototype.pattern = '**/*.json';
/**
* Load and return the compiled config.
* @returns {Object}
*/
Config.prototype.load = function () {
return this.process(this.files());
};
/**
* Add an environment or reviver to the appropriate stack.
* @param {String|Function} foo
* @public
*/
Config.prototype.use = function (foo) {
if (typeof foo === 'function') {
this._revs.push(foo);
} else if (typeof foo === 'string') {
this._envs.push(foo);
}
};
/**
* Return the list of files that currently apply to this config
* based on the registered environments.
* @returns {Array.<String>}
*/
Config.prototype.files = function () {
var array = [];
var files = glob.sync(this.pattern, {
cwd: this.dirname
});
this._envs.forEach(function (env) {
files.filter(function (file) {
return array.indexOf(file) === -1;
}).filter(function (file) {
return match(env, removeExtension(file));
}).forEach(function (file) {
array.push(file);
});
});
return array;
};
/**
* Creates a new config object from `files`.
* @param {Array.<String>} files
* @returns {Object}
*/
Config.prototype.process = function (files) {
var source;
var config;
var i;
var obj = {};
for (i = 0; i < files.length; i++) {
source = fs.readFileSync(path.join(this.dirname, files[i]), 'utf8');
config = this.parse(source, this.reviver());
extend(obj, config);
}
return obj;
};
/**
* Creates a reviver function from the registered revivers.
* @returns {Function}
*/
Config.prototype.reviver = function () {
var revs = this._revs;
return function (key, val) {
var i;
for (i = 0; i < revs.length; i++) {
val = revs[i](key, val);
}
return val;
};
};
/**
* Returns `str` with the extension part removed
* @param {String} str
* @returns {String}
*/
function removeExtension(str) {
return str.slice(0, -1 * path.extname(str).length);
}
/**
* @module Config
*/
module.exports = Config;