configorama 0.5.2 → 0.5.4
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/README.md +63 -21
- package/cli.js +29 -3
- package/package.json +2 -2
- package/src/main.js +211 -50
- package/src/resolvers/valueFromEnv.js +1 -0
- package/src/resolvers/valueFromGit.js +2 -0
- package/src/resolvers/valueFromNumber.js +1 -0
- package/src/resolvers/valueFromOptions.js +2 -0
- package/src/utils/PromiseTracker.js +3 -2
- package/src/utils/cleanVariable.js +30 -2
- package/src/utils/cleanVariable.test.js +98 -0
- package/src/utils/find-nested-variables.js +227 -0
- package/src/utils/find-nested-variables.test.js +99 -0
- package/src/utils/splitByComma.js +57 -45
- package/src/utils/splitByComma.test.js +84 -0
package/src/main.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
const os = require('os')
|
|
2
2
|
const path = require('path')
|
|
3
3
|
const fs = require('fs')
|
|
4
|
+
/*
|
|
5
|
+
console.log = () => {}
|
|
6
|
+
// process.exit(1)
|
|
7
|
+
/** */
|
|
8
|
+
|
|
4
9
|
const promiseFinallyShim = require('promise.prototype.finally').shim()
|
|
5
10
|
// @TODO only import lodash we need
|
|
6
11
|
|
|
@@ -42,7 +47,7 @@ const { getFallbackString, verifyVariable } = require('./utils/variableUtils')
|
|
|
42
47
|
const { encodeUnknown, decodeUnknown } = require('./utils/unknownValues')
|
|
43
48
|
const { mergeByKeys } = require('./utils/mergeByKeys')
|
|
44
49
|
const { arrayToJsonPath } = require('./utils/arrayToJsonPath')
|
|
45
|
-
|
|
50
|
+
const { findNestedVariables } = require('./utils/find-nested-variables')
|
|
46
51
|
/**
|
|
47
52
|
* Maintainer's notes:
|
|
48
53
|
*
|
|
@@ -74,6 +79,7 @@ const base64WrapperRegex = /\[_\[([A-Za-z0-9+/=\s]*)\]_\]/g
|
|
|
74
79
|
const logLines = '─────────────────────────────────────────────────'
|
|
75
80
|
|
|
76
81
|
let DEBUG = process.argv.includes('--debug') ? true : false
|
|
82
|
+
let VERBOSE = process.argv.includes('--verbose') ? true : false
|
|
77
83
|
// DEBUG = true
|
|
78
84
|
|
|
79
85
|
const ENABLE_FUNCTIONS = true
|
|
@@ -105,6 +111,7 @@ class Configorama {
|
|
|
105
111
|
} else if (variableSyntax instanceof RegExp) {
|
|
106
112
|
varRegex = variableSyntax
|
|
107
113
|
}
|
|
114
|
+
// console.log('varRegex', varRegex)
|
|
108
115
|
this.variableSyntax = varRegex
|
|
109
116
|
|
|
110
117
|
// Set initial config object to populate
|
|
@@ -130,8 +137,18 @@ class Configorama {
|
|
|
130
137
|
this.opts
|
|
131
138
|
)
|
|
132
139
|
|
|
140
|
+
if (VERBOSE) {
|
|
141
|
+
console.log('───────────── Input Config ──────────────────────')
|
|
142
|
+
console.log()
|
|
143
|
+
deepLog(configObject)
|
|
144
|
+
console.log()
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
this.configFilePath = fileOrObject
|
|
133
148
|
// set config objects
|
|
134
149
|
this.config = configObject
|
|
150
|
+
// Keep a copy of the original file contents
|
|
151
|
+
this.originalString = fileContents
|
|
135
152
|
// Keep a copy
|
|
136
153
|
this.originalConfig = cloneDeep(configObject)
|
|
137
154
|
// Set configPath for file references
|
|
@@ -165,6 +182,8 @@ class Configorama {
|
|
|
165
182
|
* // or ${self:otherKeyInConfig}
|
|
166
183
|
*/
|
|
167
184
|
{
|
|
185
|
+
type: 'self',
|
|
186
|
+
prefix: 'self',
|
|
168
187
|
match: selfRefSyntax,
|
|
169
188
|
resolver: (varString, o, x, pathValue) => {
|
|
170
189
|
return this.getValueFromSelf(varString, o, x, pathValue)
|
|
@@ -177,6 +196,8 @@ class Configorama {
|
|
|
177
196
|
* ${file(pathToFile.yml), "fallbackValue"}
|
|
178
197
|
*/
|
|
179
198
|
{
|
|
199
|
+
type: 'file',
|
|
200
|
+
prefix: 'file',
|
|
180
201
|
match: fileRefSyntax,
|
|
181
202
|
resolver: (varString, o, x, pathValue) => {
|
|
182
203
|
// console.log('pathValue getValueFromFile', pathValue)
|
|
@@ -197,8 +218,10 @@ class Configorama {
|
|
|
197
218
|
getValueFromString,
|
|
198
219
|
/* Resolve deep references */
|
|
199
220
|
{
|
|
221
|
+
type: 'deep',
|
|
200
222
|
match: deepRefSyntax,
|
|
201
|
-
resolver: (varString) => {
|
|
223
|
+
resolver: (varString, o, x, pathValue) => {
|
|
224
|
+
// console.log('>>>>>getValueFromDeep', varString)
|
|
202
225
|
return this.getValueFromDeep(varString)
|
|
203
226
|
},
|
|
204
227
|
},
|
|
@@ -208,10 +231,13 @@ class Configorama {
|
|
|
208
231
|
|
|
209
232
|
/* Nicer self: references. Match key in object */
|
|
210
233
|
const fallThroughSelfMatcher = {
|
|
234
|
+
type: 'fallthrough',
|
|
211
235
|
match: (varString, fullObject, valueObject) => {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
236
|
+
/*
|
|
237
|
+
console.log('fallthrough varString', varString)
|
|
238
|
+
console.log('fallthrough valueObject', valueObject)
|
|
239
|
+
console.log('fullObject', fullObject)
|
|
240
|
+
/** */
|
|
215
241
|
/* its file ref so we need to shift lookup for self in nested files */
|
|
216
242
|
if (valueObject.isFileRef) {
|
|
217
243
|
const exists = dotProp.get(fullObject, varString)
|
|
@@ -229,8 +255,14 @@ class Configorama {
|
|
|
229
255
|
const startOf = varString.split('.')
|
|
230
256
|
return fullObject[startOf[0]]
|
|
231
257
|
},
|
|
232
|
-
resolver: (varString,
|
|
233
|
-
|
|
258
|
+
resolver: (varString, options, config, pathValue) => {
|
|
259
|
+
/*
|
|
260
|
+
console.log('fallthrough resolver', varString)
|
|
261
|
+
console.log('fallthrough options', options)
|
|
262
|
+
console.log('fallthrough config', config)
|
|
263
|
+
console.log('fallthrough pathValue', pathValue)
|
|
264
|
+
/** */
|
|
265
|
+
return this.getValueFromSelf(varString, options, config, pathValue)
|
|
234
266
|
},
|
|
235
267
|
}
|
|
236
268
|
|
|
@@ -242,6 +274,9 @@ class Configorama {
|
|
|
242
274
|
/* attach self matcher last */
|
|
243
275
|
this.variableTypes = this.variableTypes.concat(fallThroughSelfMatcher)
|
|
244
276
|
|
|
277
|
+
this.variablesKnownTypes = new RegExp(`^(${this.variableTypes.map((v) => v.prefix || v.type).join('|')}):`)
|
|
278
|
+
// console.log('this.variablesKnownTypes', this.variablesKnownTypes)
|
|
279
|
+
// process.exit(1)
|
|
245
280
|
// Additional filters on values. ${thing | filterFunction}
|
|
246
281
|
this.filters = {
|
|
247
282
|
capitalize: (val) => {
|
|
@@ -345,6 +380,10 @@ class Configorama {
|
|
|
345
380
|
return Object.keys(o).reduce((c, k) => ((c[k.toUpperCase()] = o[k]), c), {}) // eslint-disable-line
|
|
346
381
|
},
|
|
347
382
|
md5: md5Function,
|
|
383
|
+
// ServiceName@${replace(${ self : version }, /\\./gi, - )}
|
|
384
|
+
// replace: (value, search, replace) => {
|
|
385
|
+
// return value.replace(search, replace)
|
|
386
|
+
// },
|
|
348
387
|
}
|
|
349
388
|
|
|
350
389
|
// Apply user defined functions
|
|
@@ -375,6 +414,13 @@ class Configorama {
|
|
|
375
414
|
this.options = cliOpts || {}
|
|
376
415
|
const configoramaOpts = this.opts
|
|
377
416
|
const originalConfig = this.originalConfig
|
|
417
|
+
|
|
418
|
+
/* If no variables found just return early */
|
|
419
|
+
if (this.originalString && !this.originalString.match(this.variableSyntax)) {
|
|
420
|
+
return Promise.resolve(originalConfig)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/* Parse variables */
|
|
378
424
|
return this.initialCall(() => {
|
|
379
425
|
return Promise.resolve()
|
|
380
426
|
.then(() => {
|
|
@@ -403,7 +449,7 @@ class Configorama {
|
|
|
403
449
|
// console.log('RAW FUNCTION', rawFunction)
|
|
404
450
|
const funcString = rawValue.replace(/> function /g, '')
|
|
405
451
|
// console.log('funcString', funcString)
|
|
406
|
-
const func = cleanVariable(funcString, varSyntax, true)
|
|
452
|
+
const func = cleanVariable(funcString, varSyntax, true, `init ${this.callCount}`)
|
|
407
453
|
const funcVal = transform(func)
|
|
408
454
|
const hasObjectRef = rawValue.match(/\.\S*$/)
|
|
409
455
|
if (hasObjectRef && typeof funcVal === 'object') {
|
|
@@ -440,6 +486,12 @@ class Configorama {
|
|
|
440
486
|
if (this.mergeKeys && this.config) {
|
|
441
487
|
this.config = mergeByKeys(this.config, '', this.mergeKeys)
|
|
442
488
|
}
|
|
489
|
+
if (VERBOSE) {
|
|
490
|
+
console.log('───────────── Resolved Config ───────────────────')
|
|
491
|
+
console.log()
|
|
492
|
+
deepLog(this.config)
|
|
493
|
+
console.log()
|
|
494
|
+
}
|
|
443
495
|
return this.config
|
|
444
496
|
})
|
|
445
497
|
})
|
|
@@ -484,7 +536,7 @@ class Configorama {
|
|
|
484
536
|
let replaceVal = funcValue
|
|
485
537
|
if (typeof funcValue === 'string') {
|
|
486
538
|
const replaceIt = variableString.replace(hasFunc[0], funcValue)
|
|
487
|
-
replaceVal = cleanVariable(replaceIt, this.variableSyntax, true)
|
|
539
|
+
replaceVal = cleanVariable(replaceIt, this.variableSyntax, true, `runFunction ${this.callCount}`)
|
|
488
540
|
}
|
|
489
541
|
|
|
490
542
|
// If wrapped in outer function, recurse
|
|
@@ -560,7 +612,7 @@ class Configorama {
|
|
|
560
612
|
}
|
|
561
613
|
leaf.originalSource = originalValue
|
|
562
614
|
if (originalValue && isString(originalValue)) {
|
|
563
|
-
const varString = cleanVariable(originalValue, this.variableSyntax)
|
|
615
|
+
const varString = cleanVariable(originalValue, this.variableSyntax, true, `getProperties ${this.callCount}`)
|
|
564
616
|
if (varString.match(fileRefSyntax)) {
|
|
565
617
|
leaf.isFileRef = true
|
|
566
618
|
}
|
|
@@ -664,7 +716,7 @@ class Configorama {
|
|
|
664
716
|
// console.log('match', match)
|
|
665
717
|
return {
|
|
666
718
|
match: match,
|
|
667
|
-
variable: cleanVariable(match, this.variableSyntax),
|
|
719
|
+
variable: cleanVariable(match, this.variableSyntax, true, `getMatches ${this.callCount}`),
|
|
668
720
|
}
|
|
669
721
|
})
|
|
670
722
|
}
|
|
@@ -675,9 +727,9 @@ class Configorama {
|
|
|
675
727
|
* @returns {Promise[]} Promises for the eventual populated values of the given matches
|
|
676
728
|
*/
|
|
677
729
|
populateMatches(matches, valueObject, root) {
|
|
678
|
-
// console.log('matches', matches)
|
|
730
|
+
// console.log('populateMatches matches', matches)
|
|
679
731
|
return map(matches, (match) => {
|
|
680
|
-
return this.splitAndGet(match.variable, valueObject, root)
|
|
732
|
+
return this.splitAndGet(match.variable, valueObject, root, match.match)
|
|
681
733
|
})
|
|
682
734
|
}
|
|
683
735
|
/**
|
|
@@ -735,7 +787,10 @@ class Configorama {
|
|
|
735
787
|
}
|
|
736
788
|
const populations = this.populateMatches(matches, valueObject, root)
|
|
737
789
|
return Promise.all(populations)
|
|
738
|
-
.then((results) =>
|
|
790
|
+
.then((results) => {
|
|
791
|
+
// console.log('populateMatches results', results)
|
|
792
|
+
return this.renderMatches(valueObject, matches, results)
|
|
793
|
+
})
|
|
739
794
|
.then((result) => {
|
|
740
795
|
// console.log('renderMatches result', result)
|
|
741
796
|
if (root && isArray(matches)) {
|
|
@@ -762,7 +817,7 @@ class Configorama {
|
|
|
762
817
|
* @param property The original property string the given variable was extracted from
|
|
763
818
|
* @returns {Promise} A promise resolving to the final value of the given variable
|
|
764
819
|
*/
|
|
765
|
-
splitAndGet(variable, valueObject, root) {
|
|
820
|
+
splitAndGet(variable, valueObject, root, originalVar) {
|
|
766
821
|
if (DEBUG) {
|
|
767
822
|
console.log('>>>>>>>> Split and Get', variable)
|
|
768
823
|
console.log('valueObject', valueObject)
|
|
@@ -775,19 +830,20 @@ class Configorama {
|
|
|
775
830
|
// valueObject.value = `> function ${valueObject.value}`
|
|
776
831
|
}*/
|
|
777
832
|
|
|
778
|
-
const parts = splitByComma(variable)
|
|
833
|
+
const parts = splitByComma(variable, this.variableSyntax)
|
|
779
834
|
if (DEBUG) {
|
|
780
835
|
console.log('parts', parts)
|
|
781
836
|
console.log('parts variable:', variable)
|
|
782
|
-
console.log('parts
|
|
837
|
+
console.log('parts originalVar:', originalVar)
|
|
838
|
+
console.log('parts property:', valueObject)
|
|
783
839
|
console.log('All parts:', parts)
|
|
784
840
|
console.log('-----')
|
|
785
841
|
}
|
|
786
842
|
if (parts.length <= 1) {
|
|
787
|
-
return this.getValueFromSource(parts[0], valueObject, 'splitAndGet')
|
|
843
|
+
return this.getValueFromSource(parts[0], valueObject, 'splitAndGet', originalVar)
|
|
788
844
|
}
|
|
789
845
|
// More than 2 parts, so we need to overwrite
|
|
790
|
-
return this.overwrite(parts, valueObject)
|
|
846
|
+
return this.overwrite(parts, valueObject, originalVar)
|
|
791
847
|
}
|
|
792
848
|
/**
|
|
793
849
|
* Populate a given property, given the matched string to replace and the value to replace the
|
|
@@ -934,7 +990,7 @@ class Configorama {
|
|
|
934
990
|
missingValue = this.deep[i]
|
|
935
991
|
}
|
|
936
992
|
|
|
937
|
-
const cleanVar = cleanVariable(property, this.variableSyntax)
|
|
993
|
+
const cleanVar = cleanVariable(property, this.variableSyntax, true, `populateVariable fallback ${this.callCount}`)
|
|
938
994
|
const cleanVarNoFilters = cleanVar.split('|')[0]
|
|
939
995
|
const splitVars = splitByComma(cleanVarNoFilters)
|
|
940
996
|
const nestedVar = findNestedVariable(splitVars, valueObject.originalSource)
|
|
@@ -966,7 +1022,7 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
966
1022
|
|
|
967
1023
|
if (property && typeof property === 'string') {
|
|
968
1024
|
// console.log('property', property)
|
|
969
|
-
const prop = cleanVariable(property, this.variableSyntax)
|
|
1025
|
+
const prop = cleanVariable(property, this.variableSyntax, true, `populateVariable string ${this.callCount}`)
|
|
970
1026
|
// console.log('prop', prop)
|
|
971
1027
|
if (property.match(/^> function /g) && prop) {
|
|
972
1028
|
// console.log('func prop', property)
|
|
@@ -1070,25 +1126,49 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1070
1126
|
* @returns {Promise.<TResult>|*} A promise resolving to the first validly populating variable
|
|
1071
1127
|
* in the given variable strings string.
|
|
1072
1128
|
*/
|
|
1073
|
-
overwrite(variableStrings, valueObject) {
|
|
1129
|
+
overwrite(variableStrings, valueObject, originalVar) {
|
|
1074
1130
|
const propertyString = valueObject.value
|
|
1075
|
-
|
|
1131
|
+
/*
|
|
1132
|
+
console.log('overwrite variableStrings', variableStrings)
|
|
1133
|
+
console.log('overwrite valueObject', valueObject)
|
|
1134
|
+
console.log('overwrite originalVar', originalVar)
|
|
1135
|
+
// process.exit(1)
|
|
1136
|
+
/** */
|
|
1137
|
+
|
|
1138
|
+
if (variableStrings.length === 2) {
|
|
1139
|
+
const firstValue = variableStrings[0]
|
|
1140
|
+
const secondValue = variableStrings[1]
|
|
1141
|
+
if (
|
|
1142
|
+
isString(firstValue) && firstValue.match(this.variablesKnownTypes)
|
|
1143
|
+
&& isString(secondValue) && !secondValue.match(this.variablesKnownTypes) && !secondValue.match(this.variableSyntax)
|
|
1144
|
+
) {
|
|
1145
|
+
if (!isSurroundedByQuotes(secondValue) && !/^-?\d+(\.\d+)?$/.test(secondValue) && !startsWithQuotedPipe(secondValue)) {
|
|
1146
|
+
variableStrings = [firstValue, ensureQuote(secondValue)]
|
|
1147
|
+
}
|
|
1148
|
+
// console.log('new overwrite variableStrings', variableStrings)
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1076
1152
|
// console.log('propertyString', typeof propertyString)
|
|
1077
1153
|
const variableValues = variableStrings.map((variableString) => {
|
|
1078
1154
|
// This runs on nested variable resolution
|
|
1079
1155
|
return this.getValueFromSource(variableString, valueObject, 'overwrite')
|
|
1080
1156
|
})
|
|
1157
|
+
|
|
1081
1158
|
// console.log('variableValues', variableValues)
|
|
1082
1159
|
return Promise.all(variableValues).then((values) => {
|
|
1083
1160
|
let deepPropertyStr = propertyString
|
|
1084
1161
|
let deepProperties = 0
|
|
1162
|
+
// console.log('overwrite values', valuesToUse)
|
|
1085
1163
|
values.forEach((value, index) => {
|
|
1086
1164
|
// console.log('───────────────────────────────> value', value)
|
|
1087
1165
|
if (isString(value) && value.match(this.variableSyntax)) {
|
|
1088
1166
|
deepProperties += 1
|
|
1089
1167
|
// console.log('makeDeepVariable overwrite', value)
|
|
1090
|
-
const deepVariable = this.makeDeepVariable(value)
|
|
1091
|
-
|
|
1168
|
+
const deepVariable = this.makeDeepVariable(value, 'via overwrite')
|
|
1169
|
+
// console.log('deepVariable', deepVariable)
|
|
1170
|
+
const newValue = cleanVariable(deepVariable, this.variableSyntax, true, `overwrite ${this.callCount}`)
|
|
1171
|
+
// console.log(`overwrite newValue ${variableStrings[index]}`, newValue)
|
|
1092
1172
|
// console.log('variableStrings', variableStrings)
|
|
1093
1173
|
deepPropertyStr = deepPropertyStr.replace(variableStrings[index], newValue)
|
|
1094
1174
|
// console.log('deepPropertyString', deepPropertyStr)
|
|
@@ -1104,11 +1184,11 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1104
1184
|
* @param variableString The variable string to retrieve a value for.
|
|
1105
1185
|
* @returns {Promise.<TResult>|*} A promise resolving to the given variables value.
|
|
1106
1186
|
*/
|
|
1107
|
-
getValueFromSource(variableString, valueObject, caller) {
|
|
1108
|
-
// console.log('
|
|
1187
|
+
getValueFromSource(variableString, valueObject, caller, originalVar) {
|
|
1188
|
+
// console.log('getValueFromSrc caller', caller)
|
|
1109
1189
|
const propertyString = valueObject.value
|
|
1110
1190
|
const pathValue = valueObject.path
|
|
1111
|
-
// console.log('
|
|
1191
|
+
// console.log('getValueFromSrc propertyString', propertyString)
|
|
1112
1192
|
// console.log(`tracker contains ${variableString}`, this.tracker.contains(variableString))
|
|
1113
1193
|
if (this.tracker.contains(variableString)) {
|
|
1114
1194
|
// console.log('try to get', variableString)
|
|
@@ -1118,7 +1198,7 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1118
1198
|
let newHasFilter
|
|
1119
1199
|
// Else lookup value from various sources
|
|
1120
1200
|
if (DEBUG) {
|
|
1121
|
-
console.log(`>>>>>
|
|
1201
|
+
console.log(`>>>>> getValueFromSrc() call - ${caller}`)
|
|
1122
1202
|
console.log('variableString:', variableString)
|
|
1123
1203
|
console.log('propertyString:', propertyString)
|
|
1124
1204
|
console.log('pathValue:', pathValue)
|
|
@@ -1130,7 +1210,7 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1130
1210
|
let promiseKey
|
|
1131
1211
|
// TODO match () or pipes |
|
|
1132
1212
|
if (filters) {
|
|
1133
|
-
const string = cleanVariable(propertyString, this.variableSyntax, true)
|
|
1213
|
+
const string = cleanVariable(propertyString, this.variableSyntax, true, `getValueFromSrc filter ${this.callCount}`)
|
|
1134
1214
|
// console.log('string', string)
|
|
1135
1215
|
const deeperValue = getTextAfterOccurance(string, variableString)
|
|
1136
1216
|
// console.log('deeperValue', deeperValue)
|
|
@@ -1163,27 +1243,49 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1163
1243
|
}
|
|
1164
1244
|
|
|
1165
1245
|
let resolverFunction
|
|
1246
|
+
let resolverType
|
|
1166
1247
|
/* Loop over variables and set getterFunction when match found. */
|
|
1167
1248
|
const found = this.variableTypes.some((r, i) => {
|
|
1168
1249
|
if (r.match instanceof RegExp && variableString.match(r.match)) {
|
|
1169
1250
|
// set resolver function
|
|
1170
1251
|
resolverFunction = r.resolver
|
|
1252
|
+
resolverType = r.type || 'unknown'
|
|
1171
1253
|
return true
|
|
1172
1254
|
} else if (typeof r.match === 'function') {
|
|
1173
1255
|
// TODO finalize match API
|
|
1174
1256
|
if (r.match(variableString, this.config, valueObject)) {
|
|
1175
1257
|
// set resolver function
|
|
1176
1258
|
resolverFunction = r.resolver
|
|
1259
|
+
resolverType = r.type || 'unknown'
|
|
1177
1260
|
return true
|
|
1178
1261
|
}
|
|
1179
1262
|
}
|
|
1180
1263
|
return false
|
|
1181
1264
|
})
|
|
1182
|
-
|
|
1265
|
+
/*
|
|
1266
|
+
// console.log('found variable resolver', found)
|
|
1267
|
+
// console.log('resolverFunction', resolverFunction)
|
|
1268
|
+
/** */
|
|
1183
1269
|
|
|
1184
1270
|
if (found && resolverFunction) {
|
|
1271
|
+
/*
|
|
1272
|
+
console.log(`----------Resolver [${resolverType}]----------------------`)
|
|
1273
|
+
console.log(`Resolver TYPE [${resolverType}]`, caller)
|
|
1274
|
+
console.log('WITH INPUTS ▼')
|
|
1275
|
+
console.log('variableString: ', variableString)
|
|
1276
|
+
console.log('this.options: ', this.options)
|
|
1277
|
+
console.log('this.config: ', this.config)
|
|
1278
|
+
console.log('valueObject: ', valueObject)
|
|
1279
|
+
// process.exit(1)
|
|
1280
|
+
/** */
|
|
1185
1281
|
// TODO finalize resolverFunction API
|
|
1186
|
-
const valuePromise = resolverFunction(
|
|
1282
|
+
const valuePromise = resolverFunction(
|
|
1283
|
+
variableString,
|
|
1284
|
+
this.options,
|
|
1285
|
+
this.config,
|
|
1286
|
+
valueObject,
|
|
1287
|
+
|
|
1288
|
+
).then((val) => {
|
|
1187
1289
|
// console.log('VALUE', val)
|
|
1188
1290
|
if (
|
|
1189
1291
|
val === null ||
|
|
@@ -1191,8 +1293,11 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1191
1293
|
/* match deep refs as empty {}, they need resolving via functions */
|
|
1192
1294
|
(typeof val === 'object' && isEmpty(val) && variableString.match(/deep\:/))
|
|
1193
1295
|
) {
|
|
1296
|
+
|
|
1297
|
+
const cleanV = cleanVariable(propertyString, this.variableSyntax, true, `getValueFromSrc resolverFunction ${this.callCount}`)
|
|
1194
1298
|
// console.log('variableString', variableString)
|
|
1195
|
-
|
|
1299
|
+
// console.log('cleanV', cleanV)
|
|
1300
|
+
// console.log('nestedVars', nestedVars)
|
|
1196
1301
|
const valueCount = splitByComma(cleanV)
|
|
1197
1302
|
|
|
1198
1303
|
if (variableString.match(/deep\:/)) {
|
|
@@ -1206,18 +1311,29 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1206
1311
|
// console.log('deepIndexValue', deepIndexValue)
|
|
1207
1312
|
// console.log('FINAL', `${deepIndexValue}.${deepRef}`)
|
|
1208
1313
|
if (deepIndexValue) {
|
|
1314
|
+
// console.log('> RESOLVER RETURN newValue 1', `${deepIndexValue}.${deepRef}`)
|
|
1209
1315
|
return Promise.resolve(`${deepIndexValue}.${deepRef}`)
|
|
1210
1316
|
}
|
|
1211
1317
|
}
|
|
1212
1318
|
}
|
|
1319
|
+
// console.log('valueCount', valueCount)
|
|
1213
1320
|
// TODO throw on empty values?
|
|
1214
1321
|
// No fallback value found AND this is undefined, throw error
|
|
1215
|
-
|
|
1322
|
+
const nestedVars = findNestedVariables(propertyString, this.variableSyntax)
|
|
1323
|
+
// console.log('nestedVars', nestedVars)
|
|
1324
|
+
const noNestedVars = nestedVars.length < 2
|
|
1325
|
+
if (valueCount.length === 1 && noNestedVars) {
|
|
1326
|
+
const configFilePath = (this.configFilePath) ? ` in ${this.configFilePath}` : ''
|
|
1216
1327
|
throw new Error(`
|
|
1217
|
-
Unable to resolve variable
|
|
1328
|
+
Unable to resolve configuration variable
|
|
1329
|
+
|
|
1330
|
+
Value "${propertyString}"
|
|
1331
|
+
From "${valueObject.originalSource}"
|
|
1332
|
+
At location ${valueObject.path ? `"${arrayToJsonPath(valueObject.path)}"` : 'na'}${configFilePath}
|
|
1218
1333
|
\nFix this reference, your inputs and/or provide a valid fallback value.
|
|
1219
1334
|
\nExample of setting a fallback value: \${${variableString}, "fallbackValue"\}\n`)
|
|
1220
1335
|
}
|
|
1336
|
+
// console.log('> RESOLVER RETURN newValue 2', val)
|
|
1221
1337
|
// no value resolved but fallback value exists, keep moving on
|
|
1222
1338
|
return Promise.resolve(val)
|
|
1223
1339
|
}
|
|
@@ -1230,6 +1346,8 @@ Unable to resolve variable ${propertyString} from "${valueObject.originalSource}
|
|
|
1230
1346
|
/** */
|
|
1231
1347
|
// No filters found. return value
|
|
1232
1348
|
if (!newHasFilter) {
|
|
1349
|
+
// console.log('no newHasFilter', val, valueObject)
|
|
1350
|
+
// console.log('> RESOLVER RETURN newValue 3', val, originalVar)
|
|
1233
1351
|
return Promise.resolve(val)
|
|
1234
1352
|
}
|
|
1235
1353
|
|
|
@@ -1260,6 +1378,7 @@ Unable to resolve variable ${propertyString} from "${valueObject.originalSource}
|
|
|
1260
1378
|
// add filters to deep references if filter is used
|
|
1261
1379
|
const deepValueWithFilters = newHasFilter[1] ? val.replace(/}$/, ` ${allFilters}}`) : val
|
|
1262
1380
|
// console.log('deepValueWithFilters', deepValueWithFilters)
|
|
1381
|
+
// console.log('RESOLVER RETURN newValue 4', deepValueWithFilters)
|
|
1263
1382
|
return Promise.resolve(deepValueWithFilters)
|
|
1264
1383
|
}
|
|
1265
1384
|
/* Loop over filters used and produce new value */
|
|
@@ -1271,15 +1390,18 @@ Unable to resolve variable ${propertyString} from "${valueObject.originalSource}
|
|
|
1271
1390
|
}
|
|
1272
1391
|
if (c.args) {
|
|
1273
1392
|
this.filterCache[pathValue] = (this.filterCache[pathValue] || []).concat(c.filterName)
|
|
1274
|
-
return c.filter(theValue, ...c.args, 'from
|
|
1393
|
+
return c.filter(theValue, ...c.args, 'from getValueFromSrc with args')
|
|
1275
1394
|
}
|
|
1276
1395
|
this.filterCache[pathValue] = (this.filterCache[pathValue] || []).concat(c.filterName)
|
|
1277
|
-
return c.filter(theValue, 'from
|
|
1396
|
+
return c.filter(theValue, 'from getValueFromSrc')
|
|
1278
1397
|
}, val)
|
|
1279
|
-
// console.log('newValue', newValue)
|
|
1280
|
-
|
|
1398
|
+
// console.log('> RESOLVER RETURN newValue', newValue)
|
|
1399
|
+
// console.log('> RESOLVER RETURN newValue 5', newValue)
|
|
1281
1400
|
return Promise.resolve(newValue)
|
|
1282
1401
|
})
|
|
1402
|
+
|
|
1403
|
+
// console.log('valuePromise', valuePromise)
|
|
1404
|
+
// console.log(`----------End Resolver [${resolverType}]-------------------`)
|
|
1283
1405
|
// console.log('newHasFilter', newHasFilter)
|
|
1284
1406
|
// TODO do something with func here?
|
|
1285
1407
|
return this.tracker.add(variableString, valuePromise, propertyString, newHasFilter, promiseKey)
|
|
@@ -1288,9 +1410,9 @@ Unable to resolve variable ${propertyString} from "${valueObject.originalSource}
|
|
|
1288
1410
|
/* fall through case with self refs */
|
|
1289
1411
|
if (variableString) {
|
|
1290
1412
|
// console.log('before clean propertyString', propertyString, variableString)
|
|
1291
|
-
const clean = cleanVariable(propertyString, this.variableSyntax)
|
|
1413
|
+
const clean = cleanVariable(propertyString, this.variableSyntax, true, `getValueFromSrc self ${this.callCount}`)
|
|
1292
1414
|
// TODO @DWELLS cleanVariable makes fallback values with spaces have no spaces
|
|
1293
|
-
// console.log('cleanVariable', clean)
|
|
1415
|
+
// console.log('AFTER cleanVariable', clean)
|
|
1294
1416
|
const cleanClean = clean.split('|')[0]
|
|
1295
1417
|
// console.log('cleanCleanVariable', cleanClean)
|
|
1296
1418
|
if (funcRegex.exec(cleanClean)) {
|
|
@@ -1342,7 +1464,7 @@ Unable to resolve variable ${propertyString} from "${valueObject.originalSource}
|
|
|
1342
1464
|
return this.tracker.add(fallbackValue, valuePromise, propertyString, newHasFilter)
|
|
1343
1465
|
}
|
|
1344
1466
|
|
|
1345
|
-
// has fallback but needs deeper lookup. Call
|
|
1467
|
+
// has fallback but needs deeper lookup. Call getValueFromSrc again
|
|
1346
1468
|
if (fallbackValue) {
|
|
1347
1469
|
if (DEBUG) console.log('fallbackValue', fallbackValue)
|
|
1348
1470
|
// console.log('fallbackValue', fallbackValue)
|
|
@@ -1587,7 +1709,7 @@ Please use ":" to reference sub properties`
|
|
|
1587
1709
|
// const index = this.getDeepIndex(variableString)
|
|
1588
1710
|
/*
|
|
1589
1711
|
console.log('FIND INDEX', index)
|
|
1590
|
-
console.log(this.deep)
|
|
1712
|
+
console.log(this.deep, this.deep[index])
|
|
1591
1713
|
/** */
|
|
1592
1714
|
return this.deep[index]
|
|
1593
1715
|
}
|
|
@@ -1600,14 +1722,13 @@ Please use ":" to reference sub properties`
|
|
|
1600
1722
|
console.log('getValueFromDeep variable', variable)
|
|
1601
1723
|
/** */
|
|
1602
1724
|
let ret = this.populateValue({ value: variable }, undefined, 'getValueFromDeep')
|
|
1603
|
-
// console.log('variable ret', ret)
|
|
1604
1725
|
if (deepRef.length) {
|
|
1605
1726
|
// if there is a deep reference remaining
|
|
1606
1727
|
ret = ret.then((result) => {
|
|
1607
1728
|
// console.log('DEEP RESULT', result)
|
|
1608
1729
|
if (isString(result.value) && result.value.match(this.variableSyntax)) {
|
|
1609
1730
|
// console.log('makeDeepVariable getValueFromDeep', result.value)
|
|
1610
|
-
const deepVariable = this.makeDeepVariable(result.value)
|
|
1731
|
+
const deepVariable = this.makeDeepVariable(result.value, 'via getValueFromDeep')
|
|
1611
1732
|
return Promise.resolve(appendDeepVariable(deepVariable, deepRef))
|
|
1612
1733
|
}
|
|
1613
1734
|
return this.getDeeperValue(deepRef.split('.'), result.value)
|
|
@@ -1615,8 +1736,8 @@ Please use ":" to reference sub properties`
|
|
|
1615
1736
|
}
|
|
1616
1737
|
return ret
|
|
1617
1738
|
}
|
|
1618
|
-
makeDeepVariable(variable) {
|
|
1619
|
-
//
|
|
1739
|
+
makeDeepVariable(variable, caller) {
|
|
1740
|
+
// variable = variable.replace("dev", '"dev"')
|
|
1620
1741
|
let index = this.deep.findIndex((item) => variable === item)
|
|
1621
1742
|
if (index < 0) {
|
|
1622
1743
|
// console.log('this.deep.push', variable)
|
|
@@ -1624,11 +1745,18 @@ Please use ":" to reference sub properties`
|
|
|
1624
1745
|
}
|
|
1625
1746
|
// console.log("makeDeepVariable SET INDEX", index)
|
|
1626
1747
|
const variableContainer = variable.match(this.variableSyntax)[0]
|
|
1627
|
-
const variableString = cleanVariable(variableContainer, this.variableSyntax)
|
|
1748
|
+
const variableString = cleanVariable(variableContainer, this.variableSyntax, true, `makeDeepVariable ${this.callCount}`)
|
|
1628
1749
|
const deepVar = variableContainer.replace(variableString, `deep:${index}`)
|
|
1750
|
+
/*
|
|
1751
|
+
console.log('MAKE DEEP', variable, caller)
|
|
1752
|
+
console.log('this.deep', this.deep)
|
|
1753
|
+
console.log('variableContainer', variable)
|
|
1754
|
+
console.log('variableString', variableString)
|
|
1755
|
+
console.log('deepVar', deepVar)
|
|
1756
|
+
// process.exit(1)
|
|
1757
|
+
/** */
|
|
1629
1758
|
// TODO debugging space removal. Seems like this helps
|
|
1630
1759
|
// const deepVar = variableContainer.replace(/\s/g, '').replace(variableString, `deep:${index}`)
|
|
1631
|
-
|
|
1632
1760
|
return deepVar
|
|
1633
1761
|
}
|
|
1634
1762
|
/**
|
|
@@ -1689,7 +1817,7 @@ Please use ":" to reference sub properties`
|
|
|
1689
1817
|
}
|
|
1690
1818
|
if (typeof reducedValue === 'string' && reducedValue.match(this.variableSyntax)) {
|
|
1691
1819
|
// console.log('makeDeepVariable reducedValue', reducedValue)
|
|
1692
|
-
reducedValue = this.makeDeepVariable(reducedValue)
|
|
1820
|
+
reducedValue = this.makeDeepVariable(reducedValue, 'via getDeeperValue')
|
|
1693
1821
|
}
|
|
1694
1822
|
}
|
|
1695
1823
|
// console.log('fin', reducedValue)
|
|
@@ -1726,4 +1854,37 @@ Please use ":" to reference sub properties`
|
|
|
1726
1854
|
}
|
|
1727
1855
|
}
|
|
1728
1856
|
|
|
1857
|
+
function ensureQuote(value, open = '"', close) {
|
|
1858
|
+
let i = -1
|
|
1859
|
+
const result = []
|
|
1860
|
+
const end = close || open
|
|
1861
|
+
if (typeof value === 'string') {
|
|
1862
|
+
return startChar(value, open) + value + endChar(value, end)
|
|
1863
|
+
}
|
|
1864
|
+
while (++i < value.length) {
|
|
1865
|
+
result[i] = startChar(value[i], open) + value[i] + endChar(value[i], end)
|
|
1866
|
+
}
|
|
1867
|
+
return result
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
function startChar(str, char) {
|
|
1871
|
+
return (str[0] === char) ? '' : char
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
function endChar(str, char) {
|
|
1875
|
+
return (str[str.length -1] === char) ? '' : char
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
function isSurroundedByQuotes(str) {
|
|
1879
|
+
if (!str || str.length < 2) return false
|
|
1880
|
+
const firstChar = str[0]
|
|
1881
|
+
const lastChar = str[str.length - 1]
|
|
1882
|
+
return (firstChar === "'" && lastChar === "'") || (firstChar === '"' && lastChar === '"')
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
function startsWithQuotedPipe(str) {
|
|
1886
|
+
// Matches either 'xyz' | or "xyz" |
|
|
1887
|
+
return /^(['"])(.*?)\1\s*\|/.test(str)
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1729
1890
|
module.exports = Configorama
|
|
@@ -61,11 +61,12 @@ class PromiseTracker {
|
|
|
61
61
|
}
|
|
62
62
|
// console.log('SET PROMISE', nameSpacedVariable)
|
|
63
63
|
|
|
64
|
-
promise.waitList =
|
|
64
|
+
promise.waitList = `Var [${variable}] waited on by: ${specifier}. key: ${nameSpacedVariable}`
|
|
65
65
|
promise.state = 'pending'
|
|
66
66
|
promise.then( // creates a promise with the following effects but that we otherwise ignore
|
|
67
67
|
() => { promise.state = 'resolved' },
|
|
68
|
-
() => { promise.state = 'rejected' }
|
|
68
|
+
() => { promise.state = 'rejected' }
|
|
69
|
+
)
|
|
69
70
|
|
|
70
71
|
this.promiseList.push(promise)
|
|
71
72
|
|