configorama 0.5.1 → 0.5.3
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 +1 -0
- package/package.json +14 -14
- package/src/main.js +197 -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
|
*
|
|
@@ -105,6 +110,7 @@ class Configorama {
|
|
|
105
110
|
} else if (variableSyntax instanceof RegExp) {
|
|
106
111
|
varRegex = variableSyntax
|
|
107
112
|
}
|
|
113
|
+
// console.log('varRegex', varRegex)
|
|
108
114
|
this.variableSyntax = varRegex
|
|
109
115
|
|
|
110
116
|
// Set initial config object to populate
|
|
@@ -130,8 +136,11 @@ class Configorama {
|
|
|
130
136
|
this.opts
|
|
131
137
|
)
|
|
132
138
|
|
|
139
|
+
this.configFilePath = fileOrObject
|
|
133
140
|
// set config objects
|
|
134
141
|
this.config = configObject
|
|
142
|
+
// Keep a copy of the original file contents
|
|
143
|
+
this.originalString = fileContents
|
|
135
144
|
// Keep a copy
|
|
136
145
|
this.originalConfig = cloneDeep(configObject)
|
|
137
146
|
// Set configPath for file references
|
|
@@ -165,6 +174,8 @@ class Configorama {
|
|
|
165
174
|
* // or ${self:otherKeyInConfig}
|
|
166
175
|
*/
|
|
167
176
|
{
|
|
177
|
+
type: 'self',
|
|
178
|
+
prefix: 'self',
|
|
168
179
|
match: selfRefSyntax,
|
|
169
180
|
resolver: (varString, o, x, pathValue) => {
|
|
170
181
|
return this.getValueFromSelf(varString, o, x, pathValue)
|
|
@@ -177,6 +188,8 @@ class Configorama {
|
|
|
177
188
|
* ${file(pathToFile.yml), "fallbackValue"}
|
|
178
189
|
*/
|
|
179
190
|
{
|
|
191
|
+
type: 'file',
|
|
192
|
+
prefix: 'file',
|
|
180
193
|
match: fileRefSyntax,
|
|
181
194
|
resolver: (varString, o, x, pathValue) => {
|
|
182
195
|
// console.log('pathValue getValueFromFile', pathValue)
|
|
@@ -197,8 +210,10 @@ class Configorama {
|
|
|
197
210
|
getValueFromString,
|
|
198
211
|
/* Resolve deep references */
|
|
199
212
|
{
|
|
213
|
+
type: 'deep',
|
|
200
214
|
match: deepRefSyntax,
|
|
201
|
-
resolver: (varString) => {
|
|
215
|
+
resolver: (varString, o, x, pathValue) => {
|
|
216
|
+
// console.log('>>>>>getValueFromDeep', varString)
|
|
202
217
|
return this.getValueFromDeep(varString)
|
|
203
218
|
},
|
|
204
219
|
},
|
|
@@ -208,10 +223,13 @@ class Configorama {
|
|
|
208
223
|
|
|
209
224
|
/* Nicer self: references. Match key in object */
|
|
210
225
|
const fallThroughSelfMatcher = {
|
|
226
|
+
type: 'fallthrough',
|
|
211
227
|
match: (varString, fullObject, valueObject) => {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
228
|
+
/*
|
|
229
|
+
console.log('fallthrough varString', varString)
|
|
230
|
+
console.log('fallthrough valueObject', valueObject)
|
|
231
|
+
console.log('fullObject', fullObject)
|
|
232
|
+
/** */
|
|
215
233
|
/* its file ref so we need to shift lookup for self in nested files */
|
|
216
234
|
if (valueObject.isFileRef) {
|
|
217
235
|
const exists = dotProp.get(fullObject, varString)
|
|
@@ -229,8 +247,14 @@ class Configorama {
|
|
|
229
247
|
const startOf = varString.split('.')
|
|
230
248
|
return fullObject[startOf[0]]
|
|
231
249
|
},
|
|
232
|
-
resolver: (varString,
|
|
233
|
-
|
|
250
|
+
resolver: (varString, options, config, pathValue) => {
|
|
251
|
+
/*
|
|
252
|
+
console.log('fallthrough resolver', varString)
|
|
253
|
+
console.log('fallthrough options', options)
|
|
254
|
+
console.log('fallthrough config', config)
|
|
255
|
+
console.log('fallthrough pathValue', pathValue)
|
|
256
|
+
/** */
|
|
257
|
+
return this.getValueFromSelf(varString, options, config, pathValue)
|
|
234
258
|
},
|
|
235
259
|
}
|
|
236
260
|
|
|
@@ -242,6 +266,9 @@ class Configorama {
|
|
|
242
266
|
/* attach self matcher last */
|
|
243
267
|
this.variableTypes = this.variableTypes.concat(fallThroughSelfMatcher)
|
|
244
268
|
|
|
269
|
+
this.variablesKnownTypes = new RegExp(`^(${this.variableTypes.map((v) => v.prefix || v.type).join('|')}):`)
|
|
270
|
+
// console.log('this.variablesKnownTypes', this.variablesKnownTypes)
|
|
271
|
+
// process.exit(1)
|
|
245
272
|
// Additional filters on values. ${thing | filterFunction}
|
|
246
273
|
this.filters = {
|
|
247
274
|
capitalize: (val) => {
|
|
@@ -345,6 +372,10 @@ class Configorama {
|
|
|
345
372
|
return Object.keys(o).reduce((c, k) => ((c[k.toUpperCase()] = o[k]), c), {}) // eslint-disable-line
|
|
346
373
|
},
|
|
347
374
|
md5: md5Function,
|
|
375
|
+
// ServiceName@${replace(${ self : version }, /\\./gi, - )}
|
|
376
|
+
// replace: (value, search, replace) => {
|
|
377
|
+
// return value.replace(search, replace)
|
|
378
|
+
// },
|
|
348
379
|
}
|
|
349
380
|
|
|
350
381
|
// Apply user defined functions
|
|
@@ -375,6 +406,13 @@ class Configorama {
|
|
|
375
406
|
this.options = cliOpts || {}
|
|
376
407
|
const configoramaOpts = this.opts
|
|
377
408
|
const originalConfig = this.originalConfig
|
|
409
|
+
|
|
410
|
+
/* If no variables found just return early */
|
|
411
|
+
if (this.originalString && !this.originalString.match(this.variableSyntax)) {
|
|
412
|
+
return Promise.resolve(originalConfig)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/* Parse variables */
|
|
378
416
|
return this.initialCall(() => {
|
|
379
417
|
return Promise.resolve()
|
|
380
418
|
.then(() => {
|
|
@@ -403,7 +441,7 @@ class Configorama {
|
|
|
403
441
|
// console.log('RAW FUNCTION', rawFunction)
|
|
404
442
|
const funcString = rawValue.replace(/> function /g, '')
|
|
405
443
|
// console.log('funcString', funcString)
|
|
406
|
-
const func = cleanVariable(funcString, varSyntax, true)
|
|
444
|
+
const func = cleanVariable(funcString, varSyntax, true, `init ${this.callCount}`)
|
|
407
445
|
const funcVal = transform(func)
|
|
408
446
|
const hasObjectRef = rawValue.match(/\.\S*$/)
|
|
409
447
|
if (hasObjectRef && typeof funcVal === 'object') {
|
|
@@ -484,7 +522,7 @@ class Configorama {
|
|
|
484
522
|
let replaceVal = funcValue
|
|
485
523
|
if (typeof funcValue === 'string') {
|
|
486
524
|
const replaceIt = variableString.replace(hasFunc[0], funcValue)
|
|
487
|
-
replaceVal = cleanVariable(replaceIt, this.variableSyntax, true)
|
|
525
|
+
replaceVal = cleanVariable(replaceIt, this.variableSyntax, true, `runFunction ${this.callCount}`)
|
|
488
526
|
}
|
|
489
527
|
|
|
490
528
|
// If wrapped in outer function, recurse
|
|
@@ -560,7 +598,7 @@ class Configorama {
|
|
|
560
598
|
}
|
|
561
599
|
leaf.originalSource = originalValue
|
|
562
600
|
if (originalValue && isString(originalValue)) {
|
|
563
|
-
const varString = cleanVariable(originalValue, this.variableSyntax)
|
|
601
|
+
const varString = cleanVariable(originalValue, this.variableSyntax, true, `getProperties ${this.callCount}`)
|
|
564
602
|
if (varString.match(fileRefSyntax)) {
|
|
565
603
|
leaf.isFileRef = true
|
|
566
604
|
}
|
|
@@ -664,7 +702,7 @@ class Configorama {
|
|
|
664
702
|
// console.log('match', match)
|
|
665
703
|
return {
|
|
666
704
|
match: match,
|
|
667
|
-
variable: cleanVariable(match, this.variableSyntax),
|
|
705
|
+
variable: cleanVariable(match, this.variableSyntax, true, `getMatches ${this.callCount}`),
|
|
668
706
|
}
|
|
669
707
|
})
|
|
670
708
|
}
|
|
@@ -675,9 +713,9 @@ class Configorama {
|
|
|
675
713
|
* @returns {Promise[]} Promises for the eventual populated values of the given matches
|
|
676
714
|
*/
|
|
677
715
|
populateMatches(matches, valueObject, root) {
|
|
678
|
-
// console.log('matches', matches)
|
|
716
|
+
// console.log('populateMatches matches', matches)
|
|
679
717
|
return map(matches, (match) => {
|
|
680
|
-
return this.splitAndGet(match.variable, valueObject, root)
|
|
718
|
+
return this.splitAndGet(match.variable, valueObject, root, match.match)
|
|
681
719
|
})
|
|
682
720
|
}
|
|
683
721
|
/**
|
|
@@ -735,7 +773,10 @@ class Configorama {
|
|
|
735
773
|
}
|
|
736
774
|
const populations = this.populateMatches(matches, valueObject, root)
|
|
737
775
|
return Promise.all(populations)
|
|
738
|
-
.then((results) =>
|
|
776
|
+
.then((results) => {
|
|
777
|
+
// console.log('populateMatches results', results)
|
|
778
|
+
return this.renderMatches(valueObject, matches, results)
|
|
779
|
+
})
|
|
739
780
|
.then((result) => {
|
|
740
781
|
// console.log('renderMatches result', result)
|
|
741
782
|
if (root && isArray(matches)) {
|
|
@@ -762,7 +803,7 @@ class Configorama {
|
|
|
762
803
|
* @param property The original property string the given variable was extracted from
|
|
763
804
|
* @returns {Promise} A promise resolving to the final value of the given variable
|
|
764
805
|
*/
|
|
765
|
-
splitAndGet(variable, valueObject, root) {
|
|
806
|
+
splitAndGet(variable, valueObject, root, originalVar) {
|
|
766
807
|
if (DEBUG) {
|
|
767
808
|
console.log('>>>>>>>> Split and Get', variable)
|
|
768
809
|
console.log('valueObject', valueObject)
|
|
@@ -775,19 +816,20 @@ class Configorama {
|
|
|
775
816
|
// valueObject.value = `> function ${valueObject.value}`
|
|
776
817
|
}*/
|
|
777
818
|
|
|
778
|
-
const parts = splitByComma(variable)
|
|
819
|
+
const parts = splitByComma(variable, this.variableSyntax)
|
|
779
820
|
if (DEBUG) {
|
|
780
821
|
console.log('parts', parts)
|
|
781
822
|
console.log('parts variable:', variable)
|
|
782
|
-
console.log('parts
|
|
823
|
+
console.log('parts originalVar:', originalVar)
|
|
824
|
+
console.log('parts property:', valueObject)
|
|
783
825
|
console.log('All parts:', parts)
|
|
784
826
|
console.log('-----')
|
|
785
827
|
}
|
|
786
828
|
if (parts.length <= 1) {
|
|
787
|
-
return this.getValueFromSource(parts[0], valueObject, 'splitAndGet')
|
|
829
|
+
return this.getValueFromSource(parts[0], valueObject, 'splitAndGet', originalVar)
|
|
788
830
|
}
|
|
789
831
|
// More than 2 parts, so we need to overwrite
|
|
790
|
-
return this.overwrite(parts, valueObject)
|
|
832
|
+
return this.overwrite(parts, valueObject, originalVar)
|
|
791
833
|
}
|
|
792
834
|
/**
|
|
793
835
|
* Populate a given property, given the matched string to replace and the value to replace the
|
|
@@ -934,7 +976,7 @@ class Configorama {
|
|
|
934
976
|
missingValue = this.deep[i]
|
|
935
977
|
}
|
|
936
978
|
|
|
937
|
-
const cleanVar = cleanVariable(property, this.variableSyntax)
|
|
979
|
+
const cleanVar = cleanVariable(property, this.variableSyntax, true, `populateVariable fallback ${this.callCount}`)
|
|
938
980
|
const cleanVarNoFilters = cleanVar.split('|')[0]
|
|
939
981
|
const splitVars = splitByComma(cleanVarNoFilters)
|
|
940
982
|
const nestedVar = findNestedVariable(splitVars, valueObject.originalSource)
|
|
@@ -966,7 +1008,7 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
966
1008
|
|
|
967
1009
|
if (property && typeof property === 'string') {
|
|
968
1010
|
// console.log('property', property)
|
|
969
|
-
const prop = cleanVariable(property, this.variableSyntax)
|
|
1011
|
+
const prop = cleanVariable(property, this.variableSyntax, true, `populateVariable string ${this.callCount}`)
|
|
970
1012
|
// console.log('prop', prop)
|
|
971
1013
|
if (property.match(/^> function /g) && prop) {
|
|
972
1014
|
// console.log('func prop', property)
|
|
@@ -1070,25 +1112,49 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1070
1112
|
* @returns {Promise.<TResult>|*} A promise resolving to the first validly populating variable
|
|
1071
1113
|
* in the given variable strings string.
|
|
1072
1114
|
*/
|
|
1073
|
-
overwrite(variableStrings, valueObject) {
|
|
1115
|
+
overwrite(variableStrings, valueObject, originalVar) {
|
|
1074
1116
|
const propertyString = valueObject.value
|
|
1075
|
-
|
|
1117
|
+
/*
|
|
1118
|
+
console.log('overwrite variableStrings', variableStrings)
|
|
1119
|
+
console.log('overwrite valueObject', valueObject)
|
|
1120
|
+
console.log('overwrite originalVar', originalVar)
|
|
1121
|
+
// process.exit(1)
|
|
1122
|
+
/** */
|
|
1123
|
+
|
|
1124
|
+
if (variableStrings.length === 2) {
|
|
1125
|
+
const firstValue = variableStrings[0]
|
|
1126
|
+
const secondValue = variableStrings[1]
|
|
1127
|
+
if (
|
|
1128
|
+
isString(firstValue) && firstValue.match(this.variablesKnownTypes)
|
|
1129
|
+
&& isString(secondValue) && !secondValue.match(this.variablesKnownTypes) && !secondValue.match(this.variableSyntax)
|
|
1130
|
+
) {
|
|
1131
|
+
if (!isSurroundedByQuotes(secondValue) && !/^-?\d+(\.\d+)?$/.test(secondValue) && !startsWithQuotedPipe(secondValue)) {
|
|
1132
|
+
variableStrings = [firstValue, ensureQuote(secondValue)]
|
|
1133
|
+
}
|
|
1134
|
+
// console.log('new overwrite variableStrings', variableStrings)
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1076
1138
|
// console.log('propertyString', typeof propertyString)
|
|
1077
1139
|
const variableValues = variableStrings.map((variableString) => {
|
|
1078
1140
|
// This runs on nested variable resolution
|
|
1079
1141
|
return this.getValueFromSource(variableString, valueObject, 'overwrite')
|
|
1080
1142
|
})
|
|
1143
|
+
|
|
1081
1144
|
// console.log('variableValues', variableValues)
|
|
1082
1145
|
return Promise.all(variableValues).then((values) => {
|
|
1083
1146
|
let deepPropertyStr = propertyString
|
|
1084
1147
|
let deepProperties = 0
|
|
1148
|
+
// console.log('overwrite values', valuesToUse)
|
|
1085
1149
|
values.forEach((value, index) => {
|
|
1086
1150
|
// console.log('───────────────────────────────> value', value)
|
|
1087
1151
|
if (isString(value) && value.match(this.variableSyntax)) {
|
|
1088
1152
|
deepProperties += 1
|
|
1089
1153
|
// console.log('makeDeepVariable overwrite', value)
|
|
1090
|
-
const deepVariable = this.makeDeepVariable(value)
|
|
1091
|
-
|
|
1154
|
+
const deepVariable = this.makeDeepVariable(value, 'via overwrite')
|
|
1155
|
+
// console.log('deepVariable', deepVariable)
|
|
1156
|
+
const newValue = cleanVariable(deepVariable, this.variableSyntax, true, `overwrite ${this.callCount}`)
|
|
1157
|
+
// console.log(`overwrite newValue ${variableStrings[index]}`, newValue)
|
|
1092
1158
|
// console.log('variableStrings', variableStrings)
|
|
1093
1159
|
deepPropertyStr = deepPropertyStr.replace(variableStrings[index], newValue)
|
|
1094
1160
|
// console.log('deepPropertyString', deepPropertyStr)
|
|
@@ -1104,11 +1170,11 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1104
1170
|
* @param variableString The variable string to retrieve a value for.
|
|
1105
1171
|
* @returns {Promise.<TResult>|*} A promise resolving to the given variables value.
|
|
1106
1172
|
*/
|
|
1107
|
-
getValueFromSource(variableString, valueObject, caller) {
|
|
1108
|
-
// console.log('
|
|
1173
|
+
getValueFromSource(variableString, valueObject, caller, originalVar) {
|
|
1174
|
+
// console.log('getValueFromSrc caller', caller)
|
|
1109
1175
|
const propertyString = valueObject.value
|
|
1110
1176
|
const pathValue = valueObject.path
|
|
1111
|
-
// console.log('
|
|
1177
|
+
// console.log('getValueFromSrc propertyString', propertyString)
|
|
1112
1178
|
// console.log(`tracker contains ${variableString}`, this.tracker.contains(variableString))
|
|
1113
1179
|
if (this.tracker.contains(variableString)) {
|
|
1114
1180
|
// console.log('try to get', variableString)
|
|
@@ -1118,7 +1184,7 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1118
1184
|
let newHasFilter
|
|
1119
1185
|
// Else lookup value from various sources
|
|
1120
1186
|
if (DEBUG) {
|
|
1121
|
-
console.log(`>>>>>
|
|
1187
|
+
console.log(`>>>>> getValueFromSrc() call - ${caller}`)
|
|
1122
1188
|
console.log('variableString:', variableString)
|
|
1123
1189
|
console.log('propertyString:', propertyString)
|
|
1124
1190
|
console.log('pathValue:', pathValue)
|
|
@@ -1130,7 +1196,7 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1130
1196
|
let promiseKey
|
|
1131
1197
|
// TODO match () or pipes |
|
|
1132
1198
|
if (filters) {
|
|
1133
|
-
const string = cleanVariable(propertyString, this.variableSyntax, true)
|
|
1199
|
+
const string = cleanVariable(propertyString, this.variableSyntax, true, `getValueFromSrc filter ${this.callCount}`)
|
|
1134
1200
|
// console.log('string', string)
|
|
1135
1201
|
const deeperValue = getTextAfterOccurance(string, variableString)
|
|
1136
1202
|
// console.log('deeperValue', deeperValue)
|
|
@@ -1163,27 +1229,49 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1163
1229
|
}
|
|
1164
1230
|
|
|
1165
1231
|
let resolverFunction
|
|
1232
|
+
let resolverType
|
|
1166
1233
|
/* Loop over variables and set getterFunction when match found. */
|
|
1167
1234
|
const found = this.variableTypes.some((r, i) => {
|
|
1168
1235
|
if (r.match instanceof RegExp && variableString.match(r.match)) {
|
|
1169
1236
|
// set resolver function
|
|
1170
1237
|
resolverFunction = r.resolver
|
|
1238
|
+
resolverType = r.type || 'unknown'
|
|
1171
1239
|
return true
|
|
1172
1240
|
} else if (typeof r.match === 'function') {
|
|
1173
1241
|
// TODO finalize match API
|
|
1174
1242
|
if (r.match(variableString, this.config, valueObject)) {
|
|
1175
1243
|
// set resolver function
|
|
1176
1244
|
resolverFunction = r.resolver
|
|
1245
|
+
resolverType = r.type || 'unknown'
|
|
1177
1246
|
return true
|
|
1178
1247
|
}
|
|
1179
1248
|
}
|
|
1180
1249
|
return false
|
|
1181
1250
|
})
|
|
1182
|
-
|
|
1251
|
+
/*
|
|
1252
|
+
// console.log('found variable resolver', found)
|
|
1253
|
+
// console.log('resolverFunction', resolverFunction)
|
|
1254
|
+
/** */
|
|
1183
1255
|
|
|
1184
1256
|
if (found && resolverFunction) {
|
|
1257
|
+
/*
|
|
1258
|
+
console.log(`----------Resolver [${resolverType}]----------------------`)
|
|
1259
|
+
console.log(`Resolver TYPE [${resolverType}]`, caller)
|
|
1260
|
+
console.log('WITH INPUTS ▼')
|
|
1261
|
+
console.log('variableString: ', variableString)
|
|
1262
|
+
console.log('this.options: ', this.options)
|
|
1263
|
+
console.log('this.config: ', this.config)
|
|
1264
|
+
console.log('valueObject: ', valueObject)
|
|
1265
|
+
// process.exit(1)
|
|
1266
|
+
/** */
|
|
1185
1267
|
// TODO finalize resolverFunction API
|
|
1186
|
-
const valuePromise = resolverFunction(
|
|
1268
|
+
const valuePromise = resolverFunction(
|
|
1269
|
+
variableString,
|
|
1270
|
+
this.options,
|
|
1271
|
+
this.config,
|
|
1272
|
+
valueObject,
|
|
1273
|
+
|
|
1274
|
+
).then((val) => {
|
|
1187
1275
|
// console.log('VALUE', val)
|
|
1188
1276
|
if (
|
|
1189
1277
|
val === null ||
|
|
@@ -1191,8 +1279,11 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1191
1279
|
/* match deep refs as empty {}, they need resolving via functions */
|
|
1192
1280
|
(typeof val === 'object' && isEmpty(val) && variableString.match(/deep\:/))
|
|
1193
1281
|
) {
|
|
1282
|
+
|
|
1283
|
+
const cleanV = cleanVariable(propertyString, this.variableSyntax, true, `getValueFromSrc resolverFunction ${this.callCount}`)
|
|
1194
1284
|
// console.log('variableString', variableString)
|
|
1195
|
-
|
|
1285
|
+
// console.log('cleanV', cleanV)
|
|
1286
|
+
// console.log('nestedVars', nestedVars)
|
|
1196
1287
|
const valueCount = splitByComma(cleanV)
|
|
1197
1288
|
|
|
1198
1289
|
if (variableString.match(/deep\:/)) {
|
|
@@ -1206,18 +1297,29 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1206
1297
|
// console.log('deepIndexValue', deepIndexValue)
|
|
1207
1298
|
// console.log('FINAL', `${deepIndexValue}.${deepRef}`)
|
|
1208
1299
|
if (deepIndexValue) {
|
|
1300
|
+
// console.log('> RESOLVER RETURN newValue 1', `${deepIndexValue}.${deepRef}`)
|
|
1209
1301
|
return Promise.resolve(`${deepIndexValue}.${deepRef}`)
|
|
1210
1302
|
}
|
|
1211
1303
|
}
|
|
1212
1304
|
}
|
|
1305
|
+
// console.log('valueCount', valueCount)
|
|
1213
1306
|
// TODO throw on empty values?
|
|
1214
1307
|
// No fallback value found AND this is undefined, throw error
|
|
1215
|
-
|
|
1308
|
+
const nestedVars = findNestedVariables(propertyString, this.variableSyntax)
|
|
1309
|
+
// console.log('nestedVars', nestedVars)
|
|
1310
|
+
const noNestedVars = nestedVars.length < 2
|
|
1311
|
+
if (valueCount.length === 1 && noNestedVars) {
|
|
1312
|
+
const configFilePath = (this.configFilePath) ? ` in ${this.configFilePath}` : ''
|
|
1216
1313
|
throw new Error(`
|
|
1217
|
-
Unable to resolve variable
|
|
1314
|
+
Unable to resolve configuration variable
|
|
1315
|
+
|
|
1316
|
+
Value "${propertyString}"
|
|
1317
|
+
From "${valueObject.originalSource}"
|
|
1318
|
+
At location ${valueObject.path ? `"${arrayToJsonPath(valueObject.path)}"` : 'na'}${configFilePath}
|
|
1218
1319
|
\nFix this reference, your inputs and/or provide a valid fallback value.
|
|
1219
1320
|
\nExample of setting a fallback value: \${${variableString}, "fallbackValue"\}\n`)
|
|
1220
1321
|
}
|
|
1322
|
+
// console.log('> RESOLVER RETURN newValue 2', val)
|
|
1221
1323
|
// no value resolved but fallback value exists, keep moving on
|
|
1222
1324
|
return Promise.resolve(val)
|
|
1223
1325
|
}
|
|
@@ -1230,6 +1332,8 @@ Unable to resolve variable ${propertyString} from "${valueObject.originalSource}
|
|
|
1230
1332
|
/** */
|
|
1231
1333
|
// No filters found. return value
|
|
1232
1334
|
if (!newHasFilter) {
|
|
1335
|
+
// console.log('no newHasFilter', val, valueObject)
|
|
1336
|
+
// console.log('> RESOLVER RETURN newValue 3', val, originalVar)
|
|
1233
1337
|
return Promise.resolve(val)
|
|
1234
1338
|
}
|
|
1235
1339
|
|
|
@@ -1260,6 +1364,7 @@ Unable to resolve variable ${propertyString} from "${valueObject.originalSource}
|
|
|
1260
1364
|
// add filters to deep references if filter is used
|
|
1261
1365
|
const deepValueWithFilters = newHasFilter[1] ? val.replace(/}$/, ` ${allFilters}}`) : val
|
|
1262
1366
|
// console.log('deepValueWithFilters', deepValueWithFilters)
|
|
1367
|
+
// console.log('RESOLVER RETURN newValue 4', deepValueWithFilters)
|
|
1263
1368
|
return Promise.resolve(deepValueWithFilters)
|
|
1264
1369
|
}
|
|
1265
1370
|
/* Loop over filters used and produce new value */
|
|
@@ -1271,15 +1376,18 @@ Unable to resolve variable ${propertyString} from "${valueObject.originalSource}
|
|
|
1271
1376
|
}
|
|
1272
1377
|
if (c.args) {
|
|
1273
1378
|
this.filterCache[pathValue] = (this.filterCache[pathValue] || []).concat(c.filterName)
|
|
1274
|
-
return c.filter(theValue, ...c.args, 'from
|
|
1379
|
+
return c.filter(theValue, ...c.args, 'from getValueFromSrc with args')
|
|
1275
1380
|
}
|
|
1276
1381
|
this.filterCache[pathValue] = (this.filterCache[pathValue] || []).concat(c.filterName)
|
|
1277
|
-
return c.filter(theValue, 'from
|
|
1382
|
+
return c.filter(theValue, 'from getValueFromSrc')
|
|
1278
1383
|
}, val)
|
|
1279
|
-
// console.log('newValue', newValue)
|
|
1280
|
-
|
|
1384
|
+
// console.log('> RESOLVER RETURN newValue', newValue)
|
|
1385
|
+
// console.log('> RESOLVER RETURN newValue 5', newValue)
|
|
1281
1386
|
return Promise.resolve(newValue)
|
|
1282
1387
|
})
|
|
1388
|
+
|
|
1389
|
+
// console.log('valuePromise', valuePromise)
|
|
1390
|
+
// console.log(`----------End Resolver [${resolverType}]-------------------`)
|
|
1283
1391
|
// console.log('newHasFilter', newHasFilter)
|
|
1284
1392
|
// TODO do something with func here?
|
|
1285
1393
|
return this.tracker.add(variableString, valuePromise, propertyString, newHasFilter, promiseKey)
|
|
@@ -1288,9 +1396,9 @@ Unable to resolve variable ${propertyString} from "${valueObject.originalSource}
|
|
|
1288
1396
|
/* fall through case with self refs */
|
|
1289
1397
|
if (variableString) {
|
|
1290
1398
|
// console.log('before clean propertyString', propertyString, variableString)
|
|
1291
|
-
const clean = cleanVariable(propertyString, this.variableSyntax)
|
|
1399
|
+
const clean = cleanVariable(propertyString, this.variableSyntax, true, `getValueFromSrc self ${this.callCount}`)
|
|
1292
1400
|
// TODO @DWELLS cleanVariable makes fallback values with spaces have no spaces
|
|
1293
|
-
// console.log('cleanVariable', clean)
|
|
1401
|
+
// console.log('AFTER cleanVariable', clean)
|
|
1294
1402
|
const cleanClean = clean.split('|')[0]
|
|
1295
1403
|
// console.log('cleanCleanVariable', cleanClean)
|
|
1296
1404
|
if (funcRegex.exec(cleanClean)) {
|
|
@@ -1342,7 +1450,7 @@ Unable to resolve variable ${propertyString} from "${valueObject.originalSource}
|
|
|
1342
1450
|
return this.tracker.add(fallbackValue, valuePromise, propertyString, newHasFilter)
|
|
1343
1451
|
}
|
|
1344
1452
|
|
|
1345
|
-
// has fallback but needs deeper lookup. Call
|
|
1453
|
+
// has fallback but needs deeper lookup. Call getValueFromSrc again
|
|
1346
1454
|
if (fallbackValue) {
|
|
1347
1455
|
if (DEBUG) console.log('fallbackValue', fallbackValue)
|
|
1348
1456
|
// console.log('fallbackValue', fallbackValue)
|
|
@@ -1587,7 +1695,7 @@ Please use ":" to reference sub properties`
|
|
|
1587
1695
|
// const index = this.getDeepIndex(variableString)
|
|
1588
1696
|
/*
|
|
1589
1697
|
console.log('FIND INDEX', index)
|
|
1590
|
-
console.log(this.deep)
|
|
1698
|
+
console.log(this.deep, this.deep[index])
|
|
1591
1699
|
/** */
|
|
1592
1700
|
return this.deep[index]
|
|
1593
1701
|
}
|
|
@@ -1600,14 +1708,13 @@ Please use ":" to reference sub properties`
|
|
|
1600
1708
|
console.log('getValueFromDeep variable', variable)
|
|
1601
1709
|
/** */
|
|
1602
1710
|
let ret = this.populateValue({ value: variable }, undefined, 'getValueFromDeep')
|
|
1603
|
-
// console.log('variable ret', ret)
|
|
1604
1711
|
if (deepRef.length) {
|
|
1605
1712
|
// if there is a deep reference remaining
|
|
1606
1713
|
ret = ret.then((result) => {
|
|
1607
1714
|
// console.log('DEEP RESULT', result)
|
|
1608
1715
|
if (isString(result.value) && result.value.match(this.variableSyntax)) {
|
|
1609
1716
|
// console.log('makeDeepVariable getValueFromDeep', result.value)
|
|
1610
|
-
const deepVariable = this.makeDeepVariable(result.value)
|
|
1717
|
+
const deepVariable = this.makeDeepVariable(result.value, 'via getValueFromDeep')
|
|
1611
1718
|
return Promise.resolve(appendDeepVariable(deepVariable, deepRef))
|
|
1612
1719
|
}
|
|
1613
1720
|
return this.getDeeperValue(deepRef.split('.'), result.value)
|
|
@@ -1615,8 +1722,8 @@ Please use ":" to reference sub properties`
|
|
|
1615
1722
|
}
|
|
1616
1723
|
return ret
|
|
1617
1724
|
}
|
|
1618
|
-
makeDeepVariable(variable) {
|
|
1619
|
-
//
|
|
1725
|
+
makeDeepVariable(variable, caller) {
|
|
1726
|
+
// variable = variable.replace("dev", '"dev"')
|
|
1620
1727
|
let index = this.deep.findIndex((item) => variable === item)
|
|
1621
1728
|
if (index < 0) {
|
|
1622
1729
|
// console.log('this.deep.push', variable)
|
|
@@ -1624,11 +1731,18 @@ Please use ":" to reference sub properties`
|
|
|
1624
1731
|
}
|
|
1625
1732
|
// console.log("makeDeepVariable SET INDEX", index)
|
|
1626
1733
|
const variableContainer = variable.match(this.variableSyntax)[0]
|
|
1627
|
-
const variableString = cleanVariable(variableContainer, this.variableSyntax)
|
|
1734
|
+
const variableString = cleanVariable(variableContainer, this.variableSyntax, true, `makeDeepVariable ${this.callCount}`)
|
|
1628
1735
|
const deepVar = variableContainer.replace(variableString, `deep:${index}`)
|
|
1736
|
+
/*
|
|
1737
|
+
console.log('MAKE DEEP', variable, caller)
|
|
1738
|
+
console.log('this.deep', this.deep)
|
|
1739
|
+
console.log('variableContainer', variable)
|
|
1740
|
+
console.log('variableString', variableString)
|
|
1741
|
+
console.log('deepVar', deepVar)
|
|
1742
|
+
// process.exit(1)
|
|
1743
|
+
/** */
|
|
1629
1744
|
// TODO debugging space removal. Seems like this helps
|
|
1630
1745
|
// const deepVar = variableContainer.replace(/\s/g, '').replace(variableString, `deep:${index}`)
|
|
1631
|
-
|
|
1632
1746
|
return deepVar
|
|
1633
1747
|
}
|
|
1634
1748
|
/**
|
|
@@ -1689,7 +1803,7 @@ Please use ":" to reference sub properties`
|
|
|
1689
1803
|
}
|
|
1690
1804
|
if (typeof reducedValue === 'string' && reducedValue.match(this.variableSyntax)) {
|
|
1691
1805
|
// console.log('makeDeepVariable reducedValue', reducedValue)
|
|
1692
|
-
reducedValue = this.makeDeepVariable(reducedValue)
|
|
1806
|
+
reducedValue = this.makeDeepVariable(reducedValue, 'via getDeeperValue')
|
|
1693
1807
|
}
|
|
1694
1808
|
}
|
|
1695
1809
|
// console.log('fin', reducedValue)
|
|
@@ -1726,4 +1840,37 @@ Please use ":" to reference sub properties`
|
|
|
1726
1840
|
}
|
|
1727
1841
|
}
|
|
1728
1842
|
|
|
1843
|
+
function ensureQuote(value, open = '"', close) {
|
|
1844
|
+
let i = -1
|
|
1845
|
+
const result = []
|
|
1846
|
+
const end = close || open
|
|
1847
|
+
if (typeof value === 'string') {
|
|
1848
|
+
return startChar(value, open) + value + endChar(value, end)
|
|
1849
|
+
}
|
|
1850
|
+
while (++i < value.length) {
|
|
1851
|
+
result[i] = startChar(value[i], open) + value[i] + endChar(value[i], end)
|
|
1852
|
+
}
|
|
1853
|
+
return result
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
function startChar(str, char) {
|
|
1857
|
+
return (str[0] === char) ? '' : char
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
function endChar(str, char) {
|
|
1861
|
+
return (str[str.length -1] === char) ? '' : char
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
function isSurroundedByQuotes(str) {
|
|
1865
|
+
if (!str || str.length < 2) return false
|
|
1866
|
+
const firstChar = str[0]
|
|
1867
|
+
const lastChar = str[str.length - 1]
|
|
1868
|
+
return (firstChar === "'" && lastChar === "'") || (firstChar === '"' && lastChar === '"')
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
function startsWithQuotedPipe(str) {
|
|
1872
|
+
// Matches either 'xyz' | or "xyz" |
|
|
1873
|
+
return /^(['"])(.*?)\1\s*\|/.test(str)
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1729
1876
|
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
|
|