UNPKG

2.44 kBJavaScriptView Raw
1var asyncSymbol = Symbol('asyncSymbol');
2var deferConfig = require('./defer').deferConfig;
3
4/**
5 * @param promiseOrFunc the promise will determine a property's value once resolved
6 * can also be a function to defer which resolves to a promise
7 * @returns {Promise} a marked promise to be resolve later using `resolveAsyncConfigs`
8 */
9function asyncConfig(promiseOrFunc) {
10 if (typeof promiseOrFunc === 'function') { // also acts as deferConfig
11 return deferConfig(function (config, original) {
12 var release;
13 function registerRelease(resolve) { release = resolve; }
14 function callFunc() { return promiseOrFunc.call(config, config, original); }
15 var promise = asyncConfig(new Promise(registerRelease).then(callFunc));
16 promise.release = release;
17 return promise;
18 });
19 }
20 var promise = promiseOrFunc;
21 promise.async = asyncSymbol;
22 promise.prepare = function(config, prop, property) {
23 if (promise.release) {
24 promise.release();
25 }
26 return function() {
27 return promise.then(function(value) {
28 Object.defineProperty(prop, property, {value: value});
29 });
30 };
31 };
32 return promise;
33}
34
35/**
36 * Do not use `config.get` before executing this method, it will freeze the config object
37 * @param config the main config object, returned from require('config')
38 * @returns {Promise<config>} once all promises are resolved, return the original config object
39 */
40function resolveAsyncConfigs(config) {
41 var promises = [];
42 var resolvers = [];
43 (function iterate(prop) {
44 var propsToSort = [];
45 for (var property in prop) {
46 if (prop.hasOwnProperty(property) && prop[property] != null) {
47 propsToSort.push(property);
48 }
49 }
50 propsToSort.sort().forEach(function(property) {
51 if (prop[property].constructor === Object) {
52 iterate(prop[property]);
53 }
54 else if (prop[property].constructor === Array) {
55 prop[property].forEach(iterate);
56 }
57 else if (prop[property] && prop[property].async === asyncSymbol) {
58 resolvers.push(prop[property].prepare(config, prop, property));
59 promises.push(prop[property]);
60 }
61 });
62 })(config);
63 return Promise.all(promises).then(function() {
64 resolvers.forEach(function(resolve) { resolve(); });
65 return config;
66 });
67}
68
69module.exports.asyncConfig = asyncConfig;
70module.exports.resolveAsyncConfigs = resolveAsyncConfigs;