config 4.2.0 → 4.3.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/LICENSE +1 -1
- package/README.md +1 -1
- package/async.js +7 -2
- package/defer.js +13 -19
- package/lib/config.js +17 -1
- package/lib/defer.js +42 -0
- package/lib/util.js +89 -19
- package/package.json +5 -2
package/LICENSE
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright 2010-
|
|
1
|
+
// Copyright 2010-2026, Loren West and other contributors
|
|
2
2
|
|
|
3
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
4
|
// of this software and associated documentation files (the "Software"), to
|
package/README.md
CHANGED
|
@@ -171,6 +171,6 @@ License
|
|
|
171
171
|
|
|
172
172
|
May be freely distributed under the [MIT license](https://raw.githubusercontent.com/node-config/node-config/master/LICENSE).
|
|
173
173
|
|
|
174
|
-
Copyright (c) 2010-
|
|
174
|
+
Copyright (c) 2010-2026 Loren West
|
|
175
175
|
[and other contributors](https://github.com/node-config/node-config/graphs/contributors)
|
|
176
176
|
|
package/async.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
const asyncSymbol = Symbol('asyncSymbol');
|
|
2
|
+
const { deferConfig } = require('./defer');
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @param promiseOrFunc the promise will determine a property's value once resolved
|
|
6
6
|
* can also be a function to defer which resolves to a promise
|
|
7
7
|
* @returns {Promise} a marked promise to be resolve later using `resolveAsyncConfigs`
|
|
8
|
+
* @deprecated please use async functions with defer
|
|
8
9
|
*/
|
|
9
10
|
function asyncConfig(promiseOrFunc) {
|
|
11
|
+
const { Util } = require('./lib/util.js');
|
|
12
|
+
Util.errorOnce("ASYNC_CONFIG", 'config/async.js is deprecated. Please use async functions with the new defer functionality');
|
|
13
|
+
|
|
10
14
|
if (typeof promiseOrFunc === 'function') { // also acts as deferConfig
|
|
11
15
|
return deferConfig(function (config, original) {
|
|
12
16
|
var release;
|
|
@@ -36,6 +40,7 @@ function asyncConfig(promiseOrFunc) {
|
|
|
36
40
|
* Do not use `config.get` before executing this method, it will freeze the config object
|
|
37
41
|
* @param config the main config object, returned from require('config')
|
|
38
42
|
* @returns {Promise<config>} once all promises are resolved, return the original config object
|
|
43
|
+
* @deprecated please use async functions with defer and Util.resolveAsyncConfigs
|
|
39
44
|
*/
|
|
40
45
|
function resolveAsyncConfigs(config) {
|
|
41
46
|
var promises = [];
|
package/defer.js
CHANGED
|
@@ -1,23 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
function DeferredConfig() {}
|
|
3
|
-
DeferredConfig.prototype.prepare = function() {};
|
|
4
|
-
DeferredConfig.prototype.resolve = function() {};
|
|
1
|
+
const { deferConfig, DeferredConfig } = require('./lib/defer.js');
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(prop, property, {get: function() { return obj.resolve(); }});
|
|
17
|
-
return obj;
|
|
18
|
-
};
|
|
19
|
-
return obj;
|
|
3
|
+
/**
|
|
4
|
+
* @deprecated please use the new callback mechanism
|
|
5
|
+
* @see lib/defer.js
|
|
6
|
+
*/
|
|
7
|
+
module.exports.deferConfig = (...args) => {
|
|
8
|
+
const { Util } = require('./lib/util.js');
|
|
9
|
+
|
|
10
|
+
Util.errorOnce("DEFER_CONFIG", 'node-config now supports config file callbacks in place of deferConfig(), which is deprecated.');
|
|
11
|
+
return deferConfig(...args);
|
|
20
12
|
}
|
|
21
13
|
|
|
22
|
-
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated please use the new callback mechanism
|
|
16
|
+
*/
|
|
23
17
|
module.exports.DeferredConfig = DeferredConfig;
|
package/lib/config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// config.js (c) 2010-
|
|
1
|
+
// config.js (c) 2010-2026 Loren West and other contributors
|
|
2
2
|
// May be freely distributed under the MIT license.
|
|
3
3
|
// For further details and documentation:
|
|
4
4
|
// http://lorenwest.github.com/node-config
|
|
@@ -546,6 +546,22 @@ util.attachProtoDeep = function(toObject, depth) {
|
|
|
546
546
|
return toObject;
|
|
547
547
|
};
|
|
548
548
|
|
|
549
|
+
/**
|
|
550
|
+
* <p>Get a Config Environment Variable Value</p>
|
|
551
|
+
*
|
|
552
|
+
* <p>
|
|
553
|
+
* This method returns the value of the specified config environment variable,
|
|
554
|
+
* including any defaults or overrides.
|
|
555
|
+
* </p>
|
|
556
|
+
*
|
|
557
|
+
* @method getEnv
|
|
558
|
+
* @param varName {String} The environment variable name
|
|
559
|
+
* @return {String} The value of the environment variable
|
|
560
|
+
*/
|
|
561
|
+
util.getEnv = function (varName) {
|
|
562
|
+
return FIRST_LOAD.getEnv(varName);
|
|
563
|
+
}
|
|
564
|
+
|
|
549
565
|
/**
|
|
550
566
|
* Returns a new deep copy of the current config object, or any part of the config if provided.
|
|
551
567
|
*
|
package/lib/defer.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const { isAsyncFunction } = require('node:util/types');
|
|
2
|
+
|
|
3
|
+
// Create a deferredConfig prototype so that we can check for it when reviewing the configs later.
|
|
4
|
+
function DeferredConfig() {}
|
|
5
|
+
DeferredConfig.prototype.prepare = function() {};
|
|
6
|
+
DeferredConfig.prototype.resolve = function() {};
|
|
7
|
+
|
|
8
|
+
// Accept a function that we'll use to resolve this value later and return a 'deferred' configuration value to resolve it later.
|
|
9
|
+
function deferConfig(func) {
|
|
10
|
+
const obj = Object.create(DeferredConfig.prototype);
|
|
11
|
+
obj.prepare = function(config, prop, property) {
|
|
12
|
+
const original = prop[property]._original;
|
|
13
|
+
|
|
14
|
+
if (isAsyncFunction(func)) {
|
|
15
|
+
obj.resolve = async function () {
|
|
16
|
+
const promise = func.call(config, config, original);
|
|
17
|
+
|
|
18
|
+
Object.defineProperty(prop, property, { value: promise });
|
|
19
|
+
Object.defineProperty(prop, property, { value: await promise });
|
|
20
|
+
|
|
21
|
+
return promise;
|
|
22
|
+
}
|
|
23
|
+
} else {
|
|
24
|
+
obj.resolve = function() {
|
|
25
|
+
const value = func.call(config, config, original);
|
|
26
|
+
|
|
27
|
+
Object.defineProperty(prop, property, {value: value});
|
|
28
|
+
|
|
29
|
+
return value;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Object.defineProperty(prop, property, { get: function() { return obj.resolve(); } });
|
|
34
|
+
|
|
35
|
+
return obj;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
return obj;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports.deferConfig = deferConfig;
|
|
42
|
+
module.exports.DeferredConfig = DeferredConfig;
|
package/lib/util.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
// config.js (c) 2010-
|
|
1
|
+
// config.js (c) 2010-2026 Loren West and other contributors
|
|
2
2
|
// May be freely distributed under the MIT license.
|
|
3
3
|
// For further details and documentation:
|
|
4
4
|
// http://lorenwest.github.com/node-config
|
|
5
5
|
|
|
6
6
|
// Dependencies
|
|
7
|
-
const DeferredConfig = require('
|
|
7
|
+
const { deferConfig, DeferredConfig } = require('./defer.js');
|
|
8
|
+
const { resolveAsyncConfigs } = require('../async');
|
|
8
9
|
const Path = require('path');
|
|
9
10
|
const FileSystem = require('fs');
|
|
10
11
|
const OS = require("os");
|
|
11
12
|
|
|
12
13
|
const DEFAULT_CONFIG_DIR = Path.join( process.cwd(), 'config');
|
|
14
|
+
const SEEN_ERRORS = {};
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
* A source in the configSources list
|
|
@@ -301,29 +303,78 @@ class Util {
|
|
|
301
303
|
const propsToSort = Object.keys(prop).filter((property) => prop[property] != null);
|
|
302
304
|
|
|
303
305
|
// Second step is to iterate of the elements in a predictable (sorted) order
|
|
304
|
-
propsToSort.sort()
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
306
|
+
for (let name of propsToSort.sort()) {
|
|
307
|
+
const property = prop[name];
|
|
308
|
+
|
|
309
|
+
if (property.constructor === Object) {
|
|
310
|
+
_iterate(property);
|
|
311
|
+
} else if (property.constructor === Array) {
|
|
312
|
+
property.forEach(function (entry, i) {
|
|
313
|
+
if (entry instanceof DeferredConfig) {
|
|
314
|
+
deferred.push(entry.prepare(config, property, i));
|
|
311
315
|
} else {
|
|
312
|
-
_iterate(
|
|
316
|
+
_iterate(property[i]);
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
} else if (property instanceof DeferredConfig) {
|
|
320
|
+
deferred.push(property.prepare(config, prop, name));
|
|
321
|
+
}
|
|
322
|
+
// else: Nothing to do. Keep the property how it is.
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
_iterate(config);
|
|
327
|
+
|
|
328
|
+
deferred.forEach((defer) => { defer.resolve() });
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Used to resolve configs that have async functions.
|
|
333
|
+
*
|
|
334
|
+
* NOTE: Do not use `config.get` before executing this method, it will freeze the config object
|
|
335
|
+
*
|
|
336
|
+
* This replaces ./async.js, which is deprecated.
|
|
337
|
+
*
|
|
338
|
+
* @param config
|
|
339
|
+
* @returns {Promise<void>}
|
|
340
|
+
*/
|
|
341
|
+
static async resolveAsyncConfigs(config) {
|
|
342
|
+
const promises = [];
|
|
343
|
+
|
|
344
|
+
await resolveAsyncConfigs(config);
|
|
345
|
+
|
|
346
|
+
function _iterate (prop) {
|
|
347
|
+
if (prop == null || prop.constructor === String) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// We put the properties we are going to look it in an array to keep the order predictable
|
|
352
|
+
const propsToSort = Object.keys(prop).filter((property) => prop[property] != null);
|
|
353
|
+
|
|
354
|
+
// Second step is to iterate of the elements in a predictable (sorted) order
|
|
355
|
+
for (let name of propsToSort.sort()) {
|
|
356
|
+
const property = prop[name];
|
|
357
|
+
|
|
358
|
+
if (property.constructor === Object) {
|
|
359
|
+
_iterate(property);
|
|
360
|
+
} else if (property.constructor === Array) {
|
|
361
|
+
for (let entry of property) {
|
|
362
|
+
if (entry instanceof Promise) {
|
|
363
|
+
promises.push(entry);
|
|
364
|
+
} else {
|
|
365
|
+
_iterate(entry);
|
|
313
366
|
}
|
|
314
367
|
}
|
|
315
|
-
} else {
|
|
316
|
-
|
|
317
|
-
deferred.push(prop[property].prepare(config, prop, property));
|
|
318
|
-
}
|
|
319
|
-
// else: Nothing to do. Keep the property how it is.
|
|
368
|
+
} else if (property instanceof Promise) {
|
|
369
|
+
promises.push(property);
|
|
320
370
|
}
|
|
321
|
-
|
|
371
|
+
// else: Nothing to do. Keep the property how it is.
|
|
372
|
+
}
|
|
322
373
|
}
|
|
323
374
|
|
|
324
375
|
_iterate(config);
|
|
325
376
|
|
|
326
|
-
|
|
377
|
+
await Promise.all(promises);
|
|
327
378
|
}
|
|
328
379
|
|
|
329
380
|
/**
|
|
@@ -649,6 +700,21 @@ class Util {
|
|
|
649
700
|
static toObject(config) {
|
|
650
701
|
return JSON.parse(JSON.stringify(config));
|
|
651
702
|
}
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* Send a message to console.error once
|
|
706
|
+
* @param key {string} the subject of the error, used to prevent duplicates
|
|
707
|
+
* @param message {string} helpful message for library users
|
|
708
|
+
* @param [args] {object[]} additional arguments to console.error
|
|
709
|
+
*/
|
|
710
|
+
static errorOnce(key, message, ...args) {
|
|
711
|
+
if (SEEN_ERRORS[key] === undefined) {
|
|
712
|
+
SEEN_ERRORS[key] = true;
|
|
713
|
+
let err = new Error;
|
|
714
|
+
Error.captureStackTrace(err, this.errorOnce);
|
|
715
|
+
console.error(message, ...args, err.stack);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
652
718
|
}
|
|
653
719
|
|
|
654
720
|
/**
|
|
@@ -938,6 +1004,12 @@ class Load {
|
|
|
938
1004
|
throw new Error("Cannot parse config file: '" + fullFilename + "': " + e3);
|
|
939
1005
|
}
|
|
940
1006
|
|
|
1007
|
+
if (typeof configObject == 'function') {
|
|
1008
|
+
let fn = configObject;
|
|
1009
|
+
|
|
1010
|
+
configObject = fn({ defer: deferConfig, util: Util });
|
|
1011
|
+
}
|
|
1012
|
+
|
|
941
1013
|
if (convert) {
|
|
942
1014
|
configObject = convert(configObject);
|
|
943
1015
|
}
|
|
@@ -1158,8 +1230,6 @@ class Load {
|
|
|
1158
1230
|
}
|
|
1159
1231
|
|
|
1160
1232
|
let configDir = env.initParam('NODE_CONFIG_DIR');
|
|
1161
|
-
configDir = configDir && _toAbsolutePath(configDir);
|
|
1162
|
-
|
|
1163
1233
|
let appInstance = env.initParam('NODE_APP_INSTANCE');
|
|
1164
1234
|
let gitCrypt = !env.initParam('CONFIG_SKIP_GITCRYPT');
|
|
1165
1235
|
let parser = _loadParser(env.initParam('NODE_CONFIG_PARSER'), configDir);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "config",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.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>",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"c8": "^10.1.3",
|
|
30
30
|
"coffeescript": "2.2.4",
|
|
31
31
|
"cson": "^3.0.1",
|
|
32
|
+
"faceoff": "^1.3.0",
|
|
32
33
|
"hjson": "^1.2.0",
|
|
33
34
|
"properties": "~1.2.1",
|
|
34
35
|
"request": "^2.88.2",
|
|
@@ -56,6 +57,8 @@
|
|
|
56
57
|
"reporter": "lcov"
|
|
57
58
|
},
|
|
58
59
|
"scripts": {
|
|
59
|
-
"
|
|
60
|
+
"ci": "npm run test && npm run benchmarks",
|
|
61
|
+
"test": "NODE_OPTIONS='--no-experimental-strip-types' c8 node --test",
|
|
62
|
+
"benchmarks": "node --allow-natives-syntax --expose-gc benchmarks/index.js"
|
|
60
63
|
}
|
|
61
64
|
}
|