* Create a new object patterned after substitutionMap, where: * 1. Terminal string values in substitutionMap are used as keys * 2. To look up values in a key-value store, variables * 3. And parent keys are created as necessary to retain the structure of substitutionMap. * * @protected
(substitutionMap, variables)
| 1319 | * corresponded to a key in `variables` |
| 1320 | */ |
| 1321 | substituteDeep(substitutionMap, variables) { |
| 1322 | const result = {}; |
| 1323 | |
| 1324 | const _substituteVars = (map, vars, pathTo) => { |
| 1325 | for (const prop in map) { |
| 1326 | const value = map[prop]; |
| 1327 | |
| 1328 | if (typeof(value) === 'string') { // We found a leaf variable name |
| 1329 | if (typeof vars[value] !== 'undefined' && vars[value] !== '') { // if the vars provide a value set the value in the result map |
| 1330 | Util.setPath(result, pathTo.concat(prop), vars[value]); |
| 1331 | } |
| 1332 | } else if (Util.isObject(value)) { // work on the subtree, giving it a clone of the pathTo |
| 1333 | if ('__name' in value && '__format' in value && typeof vars[value.__name] !== 'undefined' && vars[value.__name] !== '') { |
| 1334 | let parsedValue; |
| 1335 | try { |
| 1336 | parsedValue = this.parseString(vars[value.__name], value.__format); |
| 1337 | } catch(err) { |
| 1338 | err.message = '__format parser error in ' + value.__name + ': ' + err.message; |
| 1339 | throw err; |
| 1340 | } |
| 1341 | Util.setPath(result, pathTo.concat(prop), parsedValue); |
| 1342 | } else { |
| 1343 | _substituteVars(value, vars, pathTo.concat(prop)); |
| 1344 | } |
| 1345 | } else { |
| 1346 | let msg = "Illegal key type for substitution map at " + pathTo.join('.') + ': ' + typeof(value); |
| 1347 | throw Error(msg); |
| 1348 | } |
| 1349 | } |
| 1350 | }; |
| 1351 | |
| 1352 | _substituteVars(substitutionMap, variables, []); |
| 1353 | return result; |
| 1354 | } |
| 1355 | |
| 1356 | /** |
| 1357 | * Populate a LoadConfig entirely from environment variables. |
no outgoing calls
no test coverage detected