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/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
- // console.log('fallthrough varString', varString)
213
- // console.log('fallthrough valueObject', valueObject)
214
- // console.log('fullObject', fullObject)
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, o, x, pathValue) => {
233
- return this.getValueFromSelf(varString, o, x, pathValue)
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) => this.renderMatches(valueObject, matches, 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 property:', valueObject.value)
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
- // console.log('variableStrings', variableStrings)
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
- const newValue = cleanVariable(deepVariable, this.variableSyntax)
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('getValueFromSource caller', caller)
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('getValueFromSource propertyString', propertyString)
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(`>>>>> getValueFromSource() call - ${caller}`)
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
- // console.log('found', found)
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(variableString, this.options, this.config, valueObject).then((val) => {
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
- const cleanV = cleanVariable(propertyString, this.variableSyntax)
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
- if (valueCount.length === 1) {
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 ${propertyString} from "${valueObject.originalSource}" at path ${valueObject.path ? `"${arrayToJsonPath(valueObject.path)}"` : 'na'}
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 getValueFromSource with args')
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 getValueFromSource')
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 getValueFromSource again
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
- // console.log('MAKE DEEP', variable)
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
@@ -23,6 +23,7 @@ Example: \${env:MY_ENV_VAR}
23
23
  }
24
24
 
25
25
  module.exports = {
26
+ type: 'env',
26
27
  match: envRefSyntax,
27
28
  resolver: getValueFromEnv
28
29
  }
@@ -294,6 +294,8 @@ async function getGitRemote(name = 'origin') {
294
294
 
295
295
  module.exports = function createGitResolver(cwd) {
296
296
  return {
297
+ type: 'git',
298
+ prefix: 'git',
297
299
  match: gitVariableSyntax,
298
300
  resolver: createResolver(cwd)
299
301
  }
@@ -10,6 +10,7 @@ function getValueFromNumber(variableString) {
10
10
  }
11
11
 
12
12
  module.exports = {
13
+ type: 'number',
13
14
  match: isNumberVariable,
14
15
  resolver: getValueFromNumber
15
16
  }
@@ -13,6 +13,8 @@ function getValueFromOptions(variableString, options) {
13
13
  }
14
14
 
15
15
  module.exports = {
16
+ type: 'options',
17
+ prefix: 'opt',
16
18
  match: optRefSyntax,
17
19
  resolver: getValueFromOptions
18
20
  }
@@ -61,11 +61,12 @@ class PromiseTracker {
61
61
  }
62
62
  // console.log('SET PROMISE', nameSpacedVariable)
63
63
 
64
- promise.waitList = `${variable} waited on by: ${specifier} ${nameSpacedVariable}`
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