config 3.3.11 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/async.js +5 -6
- package/lib/config.js +62 -54
- package/package.json +16 -3
- package/parser.js +8 -69
package/async.js
CHANGED
|
@@ -41,12 +41,11 @@ function resolveAsyncConfigs(config) {
|
|
|
41
41
|
var promises = [];
|
|
42
42
|
var resolvers = [];
|
|
43
43
|
(function iterate(prop) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (Object.hasOwnProperty.call(prop, property) && prop[property] != null) {
|
|
47
|
-
propsToSort.push(property);
|
|
48
|
-
}
|
|
44
|
+
if (prop.constructor === String) {
|
|
45
|
+
return;
|
|
49
46
|
}
|
|
47
|
+
|
|
48
|
+
var propsToSort = Object.keys(prop).filter((property) => prop[property] != null);
|
|
50
49
|
propsToSort.sort().forEach(function(property) {
|
|
51
50
|
if (prop[property].constructor === Object) {
|
|
52
51
|
iterate(prop[property]);
|
|
@@ -54,7 +53,7 @@ function resolveAsyncConfigs(config) {
|
|
|
54
53
|
else if (prop[property].constructor === Array) {
|
|
55
54
|
prop[property].forEach(iterate);
|
|
56
55
|
}
|
|
57
|
-
else if (prop[property]
|
|
56
|
+
else if (prop[property].async === asyncSymbol) {
|
|
58
57
|
resolvers.push(prop[property].prepare(config, prop, property));
|
|
59
58
|
promises.push(prop[property]);
|
|
60
59
|
}
|
package/lib/config.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const DeferredConfig = require('../defer').DeferredConfig;
|
|
8
8
|
const RawConfig = require('../raw').RawConfig;
|
|
9
9
|
let Parser = require('../parser');
|
|
10
|
-
const Utils = require('util');
|
|
11
10
|
const Path = require('path');
|
|
12
11
|
const FileSystem = require('fs');
|
|
13
12
|
|
|
@@ -415,6 +414,29 @@ util.makeImmutable = function(object, property, value) {
|
|
|
415
414
|
// Create a proxy, to capture user updates of configuration options, and throw an exception for awareness, as per:
|
|
416
415
|
// https://github.com/lorenwest/node-config/issues/514
|
|
417
416
|
value = new Proxy(util.makeImmutable(value), {
|
|
417
|
+
get(target, property, receiver) {
|
|
418
|
+
// Config's own defined prototype properties and methods (e.g., `get`, `has`, etc.)
|
|
419
|
+
const ownProps = [
|
|
420
|
+
...Object.getOwnPropertyNames(Config.prototype),
|
|
421
|
+
...Object.getOwnPropertyNames(target),
|
|
422
|
+
]
|
|
423
|
+
|
|
424
|
+
// Bypass proxy receiver for properties directly on the target (e.g., RegExp.prototype.source)
|
|
425
|
+
// or properties that are not functions to prevent errors related to internal object methods.
|
|
426
|
+
if (ownProps.includes(property) || (property in target && typeof target[property] !== 'function')) {
|
|
427
|
+
return Reflect.get(target, property);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Otherwise, use the proxy receiver to handle the property access
|
|
431
|
+
const ref = Reflect.get(target, property, receiver);
|
|
432
|
+
|
|
433
|
+
// Binds the method's `this` context to the target object (e.g., Date.prototype.toISOString)
|
|
434
|
+
// to ensure it behaves correctly when called on the proxy.
|
|
435
|
+
if (typeof ref === 'function') {
|
|
436
|
+
return ref.bind(target);
|
|
437
|
+
}
|
|
438
|
+
return ref;
|
|
439
|
+
},
|
|
418
440
|
set (target, name) {
|
|
419
441
|
const message = (Reflect.has(target, name) ? 'update' : 'add');
|
|
420
442
|
// Notify the user.
|
|
@@ -494,15 +516,14 @@ util.getOption = function(options, optionName, defaultValue) {
|
|
|
494
516
|
* (hostname)-(deployment).EXT
|
|
495
517
|
* local.EXT
|
|
496
518
|
* local-(deployment).EXT
|
|
497
|
-
* runtime.json
|
|
498
519
|
* </pre>
|
|
499
520
|
*
|
|
500
521
|
* <p>
|
|
501
|
-
* EXT can be yml, yaml, coffee, iced, json, cson or js signifying the file type.
|
|
522
|
+
* EXT can be yml, yaml, coffee, iced, json, jsonc, cson or js signifying the file type.
|
|
502
523
|
* yaml (and yml) is in YAML format, coffee is a coffee-script, iced is iced-coffee-script,
|
|
503
|
-
* json is in JSON format,
|
|
504
|
-
* (http://en.wikipedia.org/wiki/.properties), and js is a javascript
|
|
505
|
-
* require()'d with module.exports being the config object.
|
|
524
|
+
* json is in JSON format, jsonc is in JSONC format, cson is in CSON format, properties is
|
|
525
|
+
* in .properties format (http://en.wikipedia.org/wiki/.properties), and js is a javascript
|
|
526
|
+
* executable file that is require()'d with module.exports being the config object.
|
|
506
527
|
* </p>
|
|
507
528
|
*
|
|
508
529
|
* <p>
|
|
@@ -524,11 +545,6 @@ util.getOption = function(options, optionName, defaultValue) {
|
|
|
524
545
|
* </p>
|
|
525
546
|
*
|
|
526
547
|
* <p>
|
|
527
|
-
* The runtime.json file contains configuration changes made at runtime either
|
|
528
|
-
* manually, or by the application setting a configuration value.
|
|
529
|
-
* </p>
|
|
530
|
-
*
|
|
531
|
-
* <p>
|
|
532
548
|
* If the $NODE_APP_INSTANCE environment variable (or --NODE_APP_INSTANCE
|
|
533
549
|
* command line parameter) is set, then files with this appendage will be loaded.
|
|
534
550
|
* See the Multiple Application Instances section of the main documentation page
|
|
@@ -577,9 +593,6 @@ util.loadFileConfigs = function(configDir, options) {
|
|
|
577
593
|
APP_INSTANCE = util.initParam('NODE_APP_INSTANCE');
|
|
578
594
|
CONFIG_SKIP_GITCRYPT = util.initParam('CONFIG_SKIP_GITCRYPT');
|
|
579
595
|
|
|
580
|
-
// This is for backward compatibility
|
|
581
|
-
const runtimeFilename = util.initParam('NODE_CONFIG_RUNTIME_JSON', Path.join(dir , 'runtime.json') );
|
|
582
|
-
|
|
583
596
|
NODE_CONFIG_PARSER = util.initParam('NODE_CONFIG_PARSER');
|
|
584
597
|
if (NODE_CONFIG_PARSER) {
|
|
585
598
|
try {
|
|
@@ -638,12 +651,15 @@ util.loadFileConfigs = function(configDir, options) {
|
|
|
638
651
|
let resolutionIndex = 1;
|
|
639
652
|
const extNames = Parser.getFilesOrder();
|
|
640
653
|
baseNames.forEach(function(baseName) {
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
654
|
+
const fileNames = [baseName];
|
|
655
|
+
if (APP_INSTANCE) {
|
|
656
|
+
fileNames.push(baseName + '-' + APP_INSTANCE);
|
|
657
|
+
}
|
|
658
|
+
fileNames.forEach(function(fileName) {
|
|
659
|
+
extNames.forEach(function(extName) {
|
|
660
|
+
allowedFiles[fileName + '.' + extName] = resolutionIndex++;
|
|
661
|
+
});
|
|
662
|
+
})
|
|
647
663
|
});
|
|
648
664
|
|
|
649
665
|
const locatedFiles = util.locateMatchingFiles(dir, allowedFiles);
|
|
@@ -703,10 +719,6 @@ util.loadFileConfigs = function(configDir, options) {
|
|
|
703
719
|
const customEnvVars = util.getCustomEnvVars(dir, extNames);
|
|
704
720
|
util.extendDeep(config, customEnvVars);
|
|
705
721
|
|
|
706
|
-
// Extend the original config with the contents of runtime.json (backwards compatibility)
|
|
707
|
-
const runtimeJson = util.parseFile(runtimeFilename) || {};
|
|
708
|
-
util.extendDeep(config, runtimeJson);
|
|
709
|
-
|
|
710
722
|
util.resolveDeferredConfigs(config);
|
|
711
723
|
|
|
712
724
|
// Return the configuration object
|
|
@@ -726,19 +738,18 @@ util.loadFileConfigs = function(configDir, options) {
|
|
|
726
738
|
*/
|
|
727
739
|
util.locateMatchingFiles = function(configDirs, allowedFiles) {
|
|
728
740
|
return configDirs.split(Path.delimiter)
|
|
741
|
+
.filter(Boolean)
|
|
729
742
|
.reduce(function(files, configDir) {
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
});
|
|
738
|
-
}
|
|
739
|
-
catch(e) {}
|
|
740
|
-
return files;
|
|
743
|
+
configDir = _toAbsolutePath(configDir);
|
|
744
|
+
try {
|
|
745
|
+
FileSystem.readdirSync(configDir)
|
|
746
|
+
.filter(file => allowedFiles[file])
|
|
747
|
+
.forEach(function(file) {
|
|
748
|
+
files.push([allowedFiles[file], Path.join(configDir, file)]);
|
|
749
|
+
});
|
|
741
750
|
}
|
|
751
|
+
catch(e) {}
|
|
752
|
+
return files;
|
|
742
753
|
}, [])
|
|
743
754
|
.sort(function(a, b) { return a[0] - b[0]; })
|
|
744
755
|
.map(function(file) { return file[1]; });
|
|
@@ -749,16 +760,12 @@ util.resolveDeferredConfigs = function (config) {
|
|
|
749
760
|
const deferred = [];
|
|
750
761
|
|
|
751
762
|
function _iterate (prop) {
|
|
763
|
+
if (prop.constructor === String) {
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
752
766
|
|
|
753
767
|
// We put the properties we are going to look it in an array to keep the order predictable
|
|
754
|
-
const propsToSort = [];
|
|
755
|
-
|
|
756
|
-
// First step is to put the properties of interest in an array
|
|
757
|
-
for (const property in prop) {
|
|
758
|
-
if (Object.hasOwnProperty.call(prop, property) && prop[property] != null) {
|
|
759
|
-
propsToSort.push(property);
|
|
760
|
-
}
|
|
761
|
-
}
|
|
768
|
+
const propsToSort = Object.keys(prop).filter((property) => prop[property] != null);
|
|
762
769
|
|
|
763
770
|
// Second step is to iterate of the elements in a predictable (sorted) order
|
|
764
771
|
propsToSort.sort().forEach(function (property) {
|
|
@@ -798,7 +805,7 @@ util.resolveDeferredConfigs = function (config) {
|
|
|
798
805
|
* .js = File to run that has a module.exports containing the config object
|
|
799
806
|
* .coffee = File to run that has a module.exports with coffee-script containing the config object
|
|
800
807
|
* .iced = File to run that has a module.exports with iced-coffee-script containing the config object
|
|
801
|
-
* All other supported file types (yaml, toml, json, cson, hjson, json5, properties, xml)
|
|
808
|
+
* All other supported file types (yaml, toml, json, jsonc, cson, hjson, json5, properties, xml)
|
|
802
809
|
* are parsed with util.parseString.
|
|
803
810
|
*
|
|
804
811
|
* If the file doesn't exist, a null will be returned. If the file can't be
|
|
@@ -873,7 +880,8 @@ util.parseFile = function(fullFilename, options) {
|
|
|
873
880
|
*
|
|
874
881
|
* The format determines the parser to use.
|
|
875
882
|
*
|
|
876
|
-
* json =
|
|
883
|
+
* json = Parsed with a JSON5 parser
|
|
884
|
+
* jsonc = Parsed with a JSON5 parser
|
|
877
885
|
* yaml (or yml) = Parsed with a YAML parser
|
|
878
886
|
* toml = Parsed with a TOML parser
|
|
879
887
|
* cson = Parsed with a CSON parser
|
|
@@ -1003,12 +1011,12 @@ util.cloneDeep = function cloneDeep(parent, depth, circular, prototype) {
|
|
|
1003
1011
|
return parent;
|
|
1004
1012
|
}
|
|
1005
1013
|
|
|
1006
|
-
if (
|
|
1014
|
+
if (Array.isArray(parent)) {
|
|
1007
1015
|
child = [];
|
|
1008
|
-
} else if (
|
|
1016
|
+
} else if (parent instanceof RegExp) {
|
|
1009
1017
|
child = new RegExp(parent.source, util.getRegExpFlags(parent));
|
|
1010
1018
|
if (parent.lastIndex) child.lastIndex = parent.lastIndex;
|
|
1011
|
-
} else if (
|
|
1019
|
+
} else if (parent instanceof Date) {
|
|
1012
1020
|
child = new Date(parent.getTime());
|
|
1013
1021
|
} else if (useBuffer && Buffer.isBuffer(parent)) {
|
|
1014
1022
|
child = Buffer.alloc(parent.length);
|
|
@@ -1278,11 +1286,9 @@ util.diffDeep = function(object1, object2, depth) {
|
|
|
1278
1286
|
* @param depth {integer} An optional depth to prevent recursion. Default: 20.
|
|
1279
1287
|
* @return {object} The altered mergeInto object is returned
|
|
1280
1288
|
*/
|
|
1281
|
-
util.extendDeep = function(mergeInto) {
|
|
1289
|
+
util.extendDeep = function(mergeInto, ...vargs) {
|
|
1282
1290
|
|
|
1283
1291
|
// Initialize
|
|
1284
|
-
const t = this;
|
|
1285
|
-
const vargs = Array.prototype.slice.call(arguments, 1);
|
|
1286
1292
|
let depth = vargs.pop();
|
|
1287
1293
|
if (typeof(depth) != 'number') {
|
|
1288
1294
|
vargs.push(depth);
|
|
@@ -1458,8 +1464,11 @@ util.toObject = function(config) {
|
|
|
1458
1464
|
|
|
1459
1465
|
// Run strictness checks on NODE_ENV and NODE_APP_INSTANCE and throw an error if there's a problem.
|
|
1460
1466
|
util.runStrictnessChecks = function (config) {
|
|
1461
|
-
|
|
1467
|
+
if (util.initParam('SUPPRESS_STRICTNESS_CHECK')) {
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1462
1470
|
|
|
1471
|
+
const sources = config.util.getConfigSources();
|
|
1463
1472
|
const sourceFilenames = sources.map(function (src) {
|
|
1464
1473
|
return Path.basename(src.name);
|
|
1465
1474
|
});
|
|
@@ -1514,8 +1523,7 @@ function _toAbsolutePath (configDir) {
|
|
|
1514
1523
|
// Instantiate and export the configuration
|
|
1515
1524
|
const config = module.exports = new Config();
|
|
1516
1525
|
|
|
1517
|
-
// copy
|
|
1518
|
-
util.stripComments = Parser.stripComments;
|
|
1526
|
+
// copy method to util for backwards compatibility
|
|
1519
1527
|
util.stripYamlComments = Parser.stripYamlComments;
|
|
1520
1528
|
|
|
1521
1529
|
// Produce warnings if the configuration is empty
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "config",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"main": "./lib/config.js",
|
|
5
5
|
"description": "Configuration control for production node deployments",
|
|
6
6
|
"author": "Loren West <open_source@lorenwest.com>",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"cson": "^3.0.1",
|
|
31
31
|
"hjson": "^1.2.0",
|
|
32
32
|
"js-yaml": "^3.2.2",
|
|
33
|
+
"nyc": "^15.1.0",
|
|
33
34
|
"properties": "~1.2.1",
|
|
34
35
|
"semver": "5.3.0",
|
|
35
36
|
"toml": "^2.0.6",
|
|
@@ -44,9 +45,21 @@
|
|
|
44
45
|
"url": "http://github.com/node-config/node-config.git"
|
|
45
46
|
},
|
|
46
47
|
"engines": {
|
|
47
|
-
"node": ">=
|
|
48
|
+
"node": ">= 20.0.0"
|
|
49
|
+
},
|
|
50
|
+
"nyc": {
|
|
51
|
+
"include": [
|
|
52
|
+
"*.js",
|
|
53
|
+
"lib/**/*.js"
|
|
54
|
+
],
|
|
55
|
+
"extension": [
|
|
56
|
+
".js"
|
|
57
|
+
],
|
|
58
|
+
"report-dir": "./coverage",
|
|
59
|
+
"reporter": "lcov"
|
|
48
60
|
},
|
|
49
61
|
"scripts": {
|
|
50
|
-
"test": "
|
|
62
|
+
"test": "nyc vows test/*.js --spec",
|
|
63
|
+
"vows": "nyc vows"
|
|
51
64
|
}
|
|
52
65
|
}
|
package/parser.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// External libraries are lazy-loaded only if these file types exist.
|
|
2
|
-
const util = require("util");
|
|
3
2
|
|
|
4
3
|
// webpack can't solve dynamic module
|
|
5
4
|
// @see https://github.com/node-config/node-config/issues/755
|
|
@@ -61,7 +60,7 @@ Parser.xmlParser = function(filename, content) {
|
|
|
61
60
|
Parser.jsParser = function(filename, content) {
|
|
62
61
|
var configObject = require(filename);
|
|
63
62
|
|
|
64
|
-
if (configObject.__esModule &&
|
|
63
|
+
if (configObject.__esModule && isObject(configObject.default)) {
|
|
65
64
|
return configObject.default
|
|
66
65
|
}
|
|
67
66
|
return configObject;
|
|
@@ -209,72 +208,6 @@ Parser.propertiesParser = function(filename, content) {
|
|
|
209
208
|
return PPARSER.parse(content, { namespaces: true, variables: true, sections: true });
|
|
210
209
|
};
|
|
211
210
|
|
|
212
|
-
/**
|
|
213
|
-
* Strip all Javascript type comments from the string.
|
|
214
|
-
*
|
|
215
|
-
* The string is usually a file loaded from the O/S, containing
|
|
216
|
-
* newlines and javascript type comments.
|
|
217
|
-
*
|
|
218
|
-
* Thanks to James Padolsey, and all who contributed to this implementation.
|
|
219
|
-
* http://james.padolsey.com/javascript/javascript-comment-removal-revisted/
|
|
220
|
-
*
|
|
221
|
-
* @protected
|
|
222
|
-
* @method stripComments
|
|
223
|
-
* @param fileStr {string} The string to strip comments from
|
|
224
|
-
* @param stringRegex {RegExp} Optional regular expression to match strings that
|
|
225
|
-
* make up the config file
|
|
226
|
-
* @return {string} The string with comments stripped.
|
|
227
|
-
*/
|
|
228
|
-
Parser.stripComments = function(fileStr, stringRegex) {
|
|
229
|
-
stringRegex = stringRegex || /"((?:[^"\\]|\\.)*)"/g;
|
|
230
|
-
|
|
231
|
-
var uid = '_' + +new Date(),
|
|
232
|
-
primitives = [],
|
|
233
|
-
primIndex = 0;
|
|
234
|
-
|
|
235
|
-
return (
|
|
236
|
-
fileStr
|
|
237
|
-
|
|
238
|
-
/* Remove strings */
|
|
239
|
-
.replace(stringRegex, function(match){
|
|
240
|
-
primitives[primIndex] = match;
|
|
241
|
-
return (uid + '') + primIndex++;
|
|
242
|
-
})
|
|
243
|
-
|
|
244
|
-
/* Remove Regexes */
|
|
245
|
-
.replace(/([^\/])(\/(?!\*|\/)(\\\/|.)+?\/[gim]{0,3})/g, function(match, $1, $2){
|
|
246
|
-
primitives[primIndex] = $2;
|
|
247
|
-
return $1 + (uid + '') + primIndex++;
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
/*
|
|
251
|
-
- Remove single-line comments that contain would-be multi-line delimiters
|
|
252
|
-
E.g. // Comment /* <--
|
|
253
|
-
- Remove multi-line comments that contain would be single-line delimiters
|
|
254
|
-
E.g. /* // <--
|
|
255
|
-
*/
|
|
256
|
-
.replace(/\/\/.*?\/?\*.+?(?=\n|\r|$)|\/\*[\s\S]*?\/\/[\s\S]*?\*\//g, '')
|
|
257
|
-
|
|
258
|
-
/*
|
|
259
|
-
Remove single and multi-line comments,
|
|
260
|
-
no consideration of inner-contents
|
|
261
|
-
*/
|
|
262
|
-
.replace(/\/\/.+?(?=\n|\r|$)|\/\*[\s\S]+?\*\//g, '')
|
|
263
|
-
|
|
264
|
-
/*
|
|
265
|
-
Remove multi-line comments that have a replaced ending (string/regex)
|
|
266
|
-
Greedy, so no inner strings/regexes will stop it.
|
|
267
|
-
*/
|
|
268
|
-
.replace(RegExp('\\/\\*[\\s\\S]+' + uid + '\\d+', 'g'), '')
|
|
269
|
-
|
|
270
|
-
/* Bring back strings & regexes */
|
|
271
|
-
.replace(RegExp(uid + '(\\d+)', 'g'), function(match, n){
|
|
272
|
-
return primitives[n];
|
|
273
|
-
})
|
|
274
|
-
);
|
|
275
|
-
|
|
276
|
-
};
|
|
277
|
-
|
|
278
211
|
/**
|
|
279
212
|
* Strip YAML comments from the string
|
|
280
213
|
*
|
|
@@ -314,7 +247,7 @@ Parser.numberParser = function(filename, content) {
|
|
|
314
247
|
return Number.isNaN(numberValue) ? undefined : numberValue;
|
|
315
248
|
};
|
|
316
249
|
|
|
317
|
-
var order = ['js', 'cjs', 'ts', 'json', 'json5', 'hjson', 'toml', 'coffee', 'iced', 'yaml', 'yml', 'cson', 'properties', 'xml',
|
|
250
|
+
var order = ['js', 'cjs', 'mjs', 'ts', 'json', 'jsonc', 'json5', 'hjson', 'toml', 'coffee', 'iced', 'yaml', 'yml', 'cson', 'properties', 'xml',
|
|
318
251
|
'boolean', 'number'];
|
|
319
252
|
var definitions = {
|
|
320
253
|
cjs: Parser.jsParser,
|
|
@@ -324,7 +257,9 @@ var definitions = {
|
|
|
324
257
|
iced: Parser.icedParser,
|
|
325
258
|
js: Parser.jsParser,
|
|
326
259
|
json: Parser.jsonParser,
|
|
260
|
+
jsonc: Parser.jsonParser,
|
|
327
261
|
json5: Parser.json5Parser,
|
|
262
|
+
mjs: Parser.jsParser,
|
|
328
263
|
properties: Parser.propertiesParser,
|
|
329
264
|
toml: Parser.tomlParser,
|
|
330
265
|
ts: Parser.tsParser,
|
|
@@ -366,3 +301,7 @@ Parser.setFilesOrder = function(name, newIndex) {
|
|
|
366
301
|
}
|
|
367
302
|
return order;
|
|
368
303
|
};
|
|
304
|
+
|
|
305
|
+
function isObject(arg) {
|
|
306
|
+
return (arg !== null) && (typeof arg === 'object');
|
|
307
|
+
}
|