configorama 0.6.4 → 0.6.6
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 +211 -12
- package/cli.js +10 -3
- package/index.d.ts +45 -0
- package/package.json +12 -3
- package/src/index.js +9 -5
- package/src/main.js +387 -96
- package/src/parsers/esm.js +69 -0
- package/src/parsers/index.js +3 -1
- package/src/parsers/ini.js +51 -0
- package/src/parsers/ini.test.js +133 -0
- package/src/parsers/json5.js +1 -0
- package/src/parsers/typescript.js +154 -0
- package/src/parsers/yaml.test.js +1 -1
- package/src/resolvers/valueFromCron.js +252 -0
- package/src/resolvers/valueFromCron.test.js +132 -0
- package/src/resolvers/valueFromEval.js +37 -0
- package/src/resolvers/valueFromEval.test.js +44 -0
- package/src/resolvers/valueFromGit.js +6 -4
- package/src/types.d.ts +112 -0
- package/src/utils/cleanVariable.js +67 -3
- package/src/utils/createEditorLink.js +23 -0
- package/src/utils/find-nested-variables.js +10 -1
- package/src/utils/logs.js +2 -1
- package/src/utils/parse.js +40 -0
- package/src/utils/resolveAlias.js +152 -0
- package/src/utils/resolveAlias.test.js +98 -0
- package/src/utils/resolveAliasOld.js +65 -0
- package/src/utils/textUtils.js +2 -2
package/src/main.js
CHANGED
|
@@ -13,16 +13,20 @@ const findUp = require('find-up')
|
|
|
13
13
|
const traverse = require('traverse')
|
|
14
14
|
const dotProp = require('dot-prop')
|
|
15
15
|
const chalk = require('./utils/chalk')
|
|
16
|
+
const { resolveAlias } = require('./utils/resolveAlias')
|
|
16
17
|
|
|
17
18
|
/* Default Value resolvers */
|
|
18
19
|
const getValueFromString = require('./resolvers/valueFromString')
|
|
19
20
|
const getValueFromNumber = require('./resolvers/valueFromNumber')
|
|
20
21
|
const getValueFromEnv = require('./resolvers/valueFromEnv')
|
|
21
22
|
const getValueFromOptions = require('./resolvers/valueFromOptions')
|
|
23
|
+
const getValueFromCron = require('./resolvers/valueFromCron')
|
|
24
|
+
const getValueFromEval = require('./resolvers/valueFromEval')
|
|
22
25
|
const createGitResolver = require('./resolvers/valueFromGit')
|
|
23
26
|
/* Default File Parsers */
|
|
24
27
|
const YAML = require('./parsers/yaml')
|
|
25
28
|
const TOML = require('./parsers/toml')
|
|
29
|
+
const INI = require('./parsers/ini')
|
|
26
30
|
/* functions */
|
|
27
31
|
const md5Function = require('./functions/md5')
|
|
28
32
|
|
|
@@ -44,14 +48,15 @@ const {
|
|
|
44
48
|
const { parseFileContents } = require('./utils/parse')
|
|
45
49
|
const { splitCsv } = require('./utils/splitCsv')
|
|
46
50
|
const { replaceAll } = require('./utils/replaceAll')
|
|
47
|
-
const {
|
|
51
|
+
const { getTextAfterOccurrence, findNestedVariable } = require('./utils/textUtils')
|
|
48
52
|
const { getFallbackString, verifyVariable } = require('./utils/variableUtils')
|
|
49
53
|
const { encodeUnknown, decodeUnknown } = require('./utils/unknownValues')
|
|
50
54
|
const { mergeByKeys } = require('./utils/mergeByKeys')
|
|
51
55
|
const { arrayToJsonPath } = require('./utils/arrayToJsonPath')
|
|
52
56
|
const { findNestedVariables } = require('./utils/find-nested-variables')
|
|
53
|
-
const { makeBox } = require('@davidwells/box-logger')
|
|
57
|
+
const { makeBox, makeStackedBoxes } = require('@davidwells/box-logger')
|
|
54
58
|
const { logHeader } = require('./utils/logs')
|
|
59
|
+
const { createEditorLink } = require('./utils/createEditorLink')
|
|
55
60
|
/**
|
|
56
61
|
* Maintainer's notes:
|
|
57
62
|
*
|
|
@@ -70,7 +75,8 @@ const deepRefSyntax = RegExp(/(\${)?deep:\d+(\.[^}]+)*()}?/)
|
|
|
70
75
|
const deepIndexReplacePattern = new RegExp(/^deep:|(\.[^}]+)*$/g)
|
|
71
76
|
const deepIndexPattern = /deep\:(\d*)/
|
|
72
77
|
const deepPrefixReplacePattern = /(?:^deep:)\d+\.?/g
|
|
73
|
-
const fileRefSyntax = RegExp(/^file\((~?[
|
|
78
|
+
const fileRefSyntax = RegExp(/^file\((~?[@\{\}\:\$a-zA-Z0-9._\-\/,'" ]+?)\)/g)
|
|
79
|
+
const textRefSyntax = RegExp(/^text\((~?[@\{\}\:\$a-zA-Z0-9._\-\/,'" ]+?)\)/g)
|
|
74
80
|
// TODO update file regex ^file\((~?[a-zA-Z0-9._\-\/, ]+?)\)
|
|
75
81
|
// To match file(asyncValue.js, lol) input params
|
|
76
82
|
const envRefSyntax = RegExp(/^env:/g)
|
|
@@ -104,8 +110,6 @@ class Configorama {
|
|
|
104
110
|
if (opts && !opts.sync) {
|
|
105
111
|
handleSignalEvents()
|
|
106
112
|
}
|
|
107
|
-
|
|
108
|
-
const showFoundVariables = opts && opts.dynamicArgs && (opts.dynamicArgs.list || opts.dynamicArgs.info)
|
|
109
113
|
|
|
110
114
|
const options = opts || {}
|
|
111
115
|
// Set opts to pass into JS file calls
|
|
@@ -148,24 +152,16 @@ class Configorama {
|
|
|
148
152
|
const fileDirectory = path.dirname(path.resolve(fileOrObject))
|
|
149
153
|
const fileType = path.extname(fileOrObject)
|
|
150
154
|
|
|
151
|
-
// Parse file contents using extracted function
|
|
152
|
-
const configObject = parseFileContents(
|
|
153
|
-
fileContents,
|
|
154
|
-
fileType,
|
|
155
|
-
fileOrObject,
|
|
156
|
-
varRegex,
|
|
157
|
-
this.opts
|
|
158
|
-
)
|
|
159
|
-
|
|
160
155
|
this.configFilePath = fileOrObject
|
|
161
|
-
//
|
|
162
|
-
this.
|
|
156
|
+
// Set configFileType
|
|
157
|
+
this.configFileType = fileType
|
|
163
158
|
// Keep a copy of the original file contents
|
|
164
159
|
this.originalString = fileContents
|
|
165
|
-
// Keep a copy
|
|
166
|
-
this.originalConfig = cloneDeep(configObject)
|
|
167
160
|
// Set configPath for file references
|
|
168
161
|
this.configPath = fileDirectory
|
|
162
|
+
// Initialize config as null - will be populated in init
|
|
163
|
+
this.config = null
|
|
164
|
+
this.originalConfig = null
|
|
169
165
|
}
|
|
170
166
|
|
|
171
167
|
// Track promise resolution
|
|
@@ -187,6 +183,23 @@ class Configorama {
|
|
|
187
183
|
* ${opt:other, "fallbackValue"}
|
|
188
184
|
*/
|
|
189
185
|
getValueFromOptions,
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Cron expressions
|
|
189
|
+
* Usage:
|
|
190
|
+
* ${cron(every minute)}
|
|
191
|
+
* ${cron(weekdays)}
|
|
192
|
+
* ${cron(at 9:30)}
|
|
193
|
+
*/
|
|
194
|
+
getValueFromCron,
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Eval expressions
|
|
198
|
+
* Usage:
|
|
199
|
+
* ${eval(${self:valueTwo} > ${self:valueOne})}
|
|
200
|
+
*/
|
|
201
|
+
getValueFromEval,
|
|
202
|
+
|
|
190
203
|
/**
|
|
191
204
|
* Self references
|
|
192
205
|
* Usage:
|
|
@@ -218,6 +231,16 @@ class Configorama {
|
|
|
218
231
|
},
|
|
219
232
|
},
|
|
220
233
|
|
|
234
|
+
|
|
235
|
+
{
|
|
236
|
+
type: 'text',
|
|
237
|
+
prefix: 'text',
|
|
238
|
+
match: textRefSyntax,
|
|
239
|
+
resolver: (varString, o, x, pathValue) => {
|
|
240
|
+
return this.getValueFromFile(varString, { asRawText: true })
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
|
|
221
244
|
// Git refs
|
|
222
245
|
createGitResolver(this.configPath),
|
|
223
246
|
/* Internal Resolvers */
|
|
@@ -264,6 +287,7 @@ class Configorama {
|
|
|
264
287
|
return deeperExists
|
|
265
288
|
}
|
|
266
289
|
}
|
|
290
|
+
// console.log('fallthrough fullObject', fullObject)
|
|
267
291
|
/* is simple ${whatever} reference in same file */
|
|
268
292
|
const startOf = varString.split('.')
|
|
269
293
|
return fullObject[startOf[0]]
|
|
@@ -288,8 +312,9 @@ class Configorama {
|
|
|
288
312
|
this.variableTypes = this.variableTypes.concat(fallThroughSelfMatcher)
|
|
289
313
|
|
|
290
314
|
// const variablesKnownTypes = new RegExp(`^(${this.variableTypes.map((v) => v.prefix || v.type).join('|')}):`)
|
|
291
|
-
const variablesKnownTypes = combineRegexes(
|
|
292
|
-
|
|
315
|
+
const variablesKnownTypes = combineRegexes(
|
|
316
|
+
this.variableTypes.filter((v) => v.type !== 'string').map((v) => v.match)
|
|
317
|
+
)
|
|
293
318
|
this.variablesKnownTypes = variablesKnownTypes
|
|
294
319
|
|
|
295
320
|
// this.allPatterns = combineRegexes(...this.variableTypes.map((v) => v.match))
|
|
@@ -410,6 +435,49 @@ class Configorama {
|
|
|
410
435
|
this.functions = Object.assign({}, this.functions, options.functions)
|
|
411
436
|
}
|
|
412
437
|
|
|
438
|
+
this.deep = []
|
|
439
|
+
this.leaves = []
|
|
440
|
+
this.callCount = 0
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
initialCall(func) {
|
|
444
|
+
this.deep = []
|
|
445
|
+
this.tracker.start()
|
|
446
|
+
return func().finally(() => {
|
|
447
|
+
this.tracker.stop()
|
|
448
|
+
this.deep = []
|
|
449
|
+
})
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Populate all variables in the service, conveniently remove and restore the service attributes
|
|
454
|
+
* that confuse the population methods.
|
|
455
|
+
* @param cliOpts An options hive to use for ${opt:...} variables.
|
|
456
|
+
* @returns {Promise.<TResult>|*} A promise resolving to the populated service.
|
|
457
|
+
*/
|
|
458
|
+
async init(cliOpts) {
|
|
459
|
+
this.options = cliOpts || {}
|
|
460
|
+
const configoramaOpts = this.opts
|
|
461
|
+
|
|
462
|
+
const showFoundVariables = configoramaOpts && configoramaOpts.dynamicArgs && (configoramaOpts.dynamicArgs.list || configoramaOpts.dynamicArgs.info)
|
|
463
|
+
|
|
464
|
+
// If we have a file path but no config yet, parse it now
|
|
465
|
+
if (this.configFilePath && !this.config) {
|
|
466
|
+
const configObject = await parseFileContents(
|
|
467
|
+
this.originalString,
|
|
468
|
+
this.configFileType,
|
|
469
|
+
this.configFilePath,
|
|
470
|
+
this.variableSyntax,
|
|
471
|
+
this.opts
|
|
472
|
+
)
|
|
473
|
+
this.configFileContents = ''
|
|
474
|
+
if (VERBOSE || showFoundVariables) {
|
|
475
|
+
this.configFileContents = fs.readFileSync(this.configFilePath, 'utf8')
|
|
476
|
+
}
|
|
477
|
+
this.config = configObject
|
|
478
|
+
this.originalConfig = cloneDeep(configObject)
|
|
479
|
+
}
|
|
480
|
+
|
|
413
481
|
if (VERBOSE) {
|
|
414
482
|
logHeader('Config Input before processing')
|
|
415
483
|
console.log()
|
|
@@ -417,10 +485,14 @@ class Configorama {
|
|
|
417
485
|
console.log()
|
|
418
486
|
}
|
|
419
487
|
|
|
488
|
+
const variableSyntax = this.variableSyntax
|
|
489
|
+
const variablesKnownTypes = this.variablesKnownTypes
|
|
490
|
+
|
|
420
491
|
if (VERBOSE || showFoundVariables) {
|
|
421
492
|
const foundVariables = []
|
|
422
493
|
const variableData = {}
|
|
423
494
|
let matchCount = 1
|
|
495
|
+
// console.log('this.originalConfig', this.originalConfig)
|
|
424
496
|
traverse(this.originalConfig).forEach(function (rawValue) {
|
|
425
497
|
if (typeof rawValue === 'string' && rawValue.match(variableSyntax)) {
|
|
426
498
|
const configValuePath = this.path.join('.')
|
|
@@ -452,45 +524,63 @@ class Configorama {
|
|
|
452
524
|
resolveOrder: [],
|
|
453
525
|
resolveDetails: nested,
|
|
454
526
|
}
|
|
455
|
-
|
|
527
|
+
let defaultValueIsVar = false
|
|
456
528
|
function calculateResolveOrder(item) {
|
|
457
529
|
if (item && item.fallbackValues) {
|
|
458
530
|
let hasResolvedFallback
|
|
531
|
+
// console.log('item.fallbackValues', item.fallbackValues)
|
|
459
532
|
const order = ([item.valueBeforeFallback]).concat(item.fallbackValues.map((f, i) => {
|
|
533
|
+
// console.log('f', f)
|
|
460
534
|
if (f.fallbackValues) {
|
|
461
535
|
const [nestedOrder, nestedResolvedFallback] = calculateResolveOrder(f)
|
|
536
|
+
// console.log('nestedOrder', nestedOrder)
|
|
537
|
+
// console.log('nestedResolvedFallback', nestedResolvedFallback)
|
|
462
538
|
if (!hasResolvedFallback && nestedResolvedFallback) {
|
|
463
539
|
hasResolvedFallback = nestedResolvedFallback
|
|
464
540
|
}
|
|
465
541
|
return nestedOrder // Return just the order part
|
|
466
542
|
}
|
|
543
|
+
|
|
467
544
|
if (!hasResolvedFallback && f.isResolvedFallback) {
|
|
468
545
|
hasResolvedFallback = f.stringValue
|
|
469
546
|
}
|
|
547
|
+
if (f.isResolvedFallback) {
|
|
548
|
+
hasResolvedFallback = f.stringValue
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
if (!hasResolvedFallback && f.isVariable) {
|
|
552
|
+
defaultValueIsVar = f
|
|
553
|
+
}
|
|
554
|
+
// console.log('hasResolvedFallback', hasResolvedFallback)
|
|
470
555
|
return `${f.stringValue || f.variable}${f.isResolvedFallback ? ' (Resolved default fallback)' : ''}`
|
|
471
556
|
})).flat()
|
|
472
557
|
|
|
473
558
|
return [order, hasResolvedFallback]
|
|
474
559
|
}
|
|
475
|
-
return [[item.variable],
|
|
560
|
+
return [[item.variable], undefined] // Return array instead of just the value
|
|
476
561
|
}
|
|
477
562
|
|
|
478
563
|
const [resolveOrder, hasResolvedFallback] = calculateResolveOrder(lastItem)
|
|
479
564
|
varData.resolveOrder = resolveOrder
|
|
480
565
|
|
|
481
|
-
if (
|
|
482
|
-
varData.
|
|
566
|
+
if (defaultValueIsVar) {
|
|
567
|
+
varData.defaultValueIsVar = defaultValueIsVar
|
|
483
568
|
}
|
|
484
569
|
|
|
570
|
+
// console.log('hasResolvedFallback', hasResolvedFallback)
|
|
571
|
+
if (typeof hasResolvedFallback !== 'undefined') {
|
|
572
|
+
varData.defaultValue = hasResolvedFallback
|
|
573
|
+
}
|
|
485
574
|
|
|
486
|
-
|
|
575
|
+
// console.log('varData.defaultValue', varData.defaultValue)
|
|
576
|
+
if (typeof varData.defaultValue === 'undefined') {
|
|
487
577
|
varData.isRequired = true
|
|
488
578
|
}
|
|
489
579
|
|
|
490
|
-
|
|
491
580
|
if (varData.resolveOrder.length > 1) {
|
|
492
581
|
varData.hasFallback = true
|
|
493
582
|
}
|
|
583
|
+
//console.log('varData', varData)
|
|
494
584
|
|
|
495
585
|
variableData[key] = (variableData[key] || []).concat(varData)
|
|
496
586
|
|
|
@@ -498,7 +588,6 @@ class Configorama {
|
|
|
498
588
|
}
|
|
499
589
|
})
|
|
500
590
|
|
|
501
|
-
|
|
502
591
|
if (!foundVariables.length) {
|
|
503
592
|
logHeader('No Variables Found in Config')
|
|
504
593
|
if (this.configFilePath) {
|
|
@@ -545,20 +634,35 @@ class Configorama {
|
|
|
545
634
|
}
|
|
546
635
|
|
|
547
636
|
logHeader('Variable Details')
|
|
637
|
+
|
|
638
|
+
const lines = this.configFileContents.split('\n')
|
|
639
|
+
// console.log('lines', lines)
|
|
548
640
|
|
|
549
641
|
const indent = ''
|
|
550
|
-
varKeys.
|
|
642
|
+
const boxes = varKeys.map((key, i) => {
|
|
551
643
|
const variableInstances = variableData[key]
|
|
644
|
+
// console.log('variableInstances', variableInstances)
|
|
552
645
|
|
|
553
646
|
const firstInstance = variableInstances[0]
|
|
554
647
|
|
|
555
648
|
let requiredText = ''
|
|
556
649
|
let defaultValueSrc = ''
|
|
557
|
-
if (
|
|
650
|
+
if (typeof firstInstance.defaultValue === 'undefined') {
|
|
558
651
|
// console.log('no default value', firstInstance)
|
|
652
|
+
|
|
653
|
+
let dotPropArr = []
|
|
654
|
+
if (firstInstance.defaultValueIsVar && (
|
|
655
|
+
firstInstance.defaultValueIsVar.varType === 'self:' ||
|
|
656
|
+
firstInstance.defaultValueIsVar.varType === 'dot.prop'
|
|
657
|
+
)) {
|
|
658
|
+
dotPropArr = [firstInstance.defaultValueIsVar]
|
|
659
|
+
}
|
|
559
660
|
/* Check if the fallback variable is a self reference */
|
|
560
661
|
const hasDotPropOrSelf = variableInstances.reduce((acc, v) => {
|
|
561
|
-
const dotProp = v.resolveDetails.find((d) =>
|
|
662
|
+
const dotProp = v.resolveDetails.find((d) => {
|
|
663
|
+
// console.log('d', d)
|
|
664
|
+
return d.varType === 'dot.prop'
|
|
665
|
+
})
|
|
562
666
|
if (dotProp) {
|
|
563
667
|
acc.push(dotProp)
|
|
564
668
|
}
|
|
@@ -567,10 +671,12 @@ class Configorama {
|
|
|
567
671
|
acc.push(v.resolveDetails[0])
|
|
568
672
|
}
|
|
569
673
|
return acc
|
|
570
|
-
},
|
|
674
|
+
}, dotPropArr)
|
|
571
675
|
// console.log('hasDotPropOrSelf', hasDotPropOrSelf)
|
|
676
|
+
|
|
572
677
|
if (!hasDotPropOrSelf.length) {
|
|
573
|
-
|
|
678
|
+
const debug = (false) ? JSON.stringify(firstInstance, null, 2) : ''
|
|
679
|
+
requiredText = `[Required Variable] ${debug}`
|
|
574
680
|
} else {
|
|
575
681
|
const fallBackValues = variableInstances.filter((v) => v.resolveDetails.find((d) => d.hasFallback)).map((v) => v.resolveDetails)
|
|
576
682
|
// console.log('fallBackValues', fallBackValues)
|
|
@@ -589,6 +695,9 @@ class Configorama {
|
|
|
589
695
|
// truncate niceString to 100 characters
|
|
590
696
|
const truncatedString = niceString.length > 100 ? niceString.substring(0, 90) + '...' : niceString
|
|
591
697
|
firstInstance.defaultValue = truncatedString
|
|
698
|
+
} else {
|
|
699
|
+
deepLog('Missing default var', firstInstance)
|
|
700
|
+
throw new Error(`Variable misconfiguration at ${firstInstance.variable}\n\n"${hasDotPropOrSelf[0].variable}" resolves to undefined value.\n`)
|
|
592
701
|
}
|
|
593
702
|
}
|
|
594
703
|
//this.originalConfig[key] = undefined
|
|
@@ -601,14 +710,16 @@ class Configorama {
|
|
|
601
710
|
const keyChalk = chalk.whiteBright
|
|
602
711
|
const valueChalk = chalk.hex(VALUE_HEX)
|
|
603
712
|
|
|
604
|
-
if (firstInstance.defaultValue) {
|
|
605
|
-
|
|
713
|
+
if (typeof firstInstance.defaultValue !== 'undefined') {
|
|
714
|
+
// console.log('firstInstance.defaultValue', firstInstance.defaultValue)
|
|
715
|
+
const defaultValueRender = firstInstance.defaultValue === '' ? '""' : firstInstance.defaultValue
|
|
716
|
+
const defaultValueText = `${indent}${keyChalk(`Default value:`.padEnd(titleText.length, ' '))}`
|
|
606
717
|
// ensure padding is even
|
|
607
|
-
varMsg += `${defaultValueText} ${valueChalk(
|
|
718
|
+
varMsg += `${defaultValueText} ${valueChalk(defaultValueRender)}`
|
|
608
719
|
}
|
|
609
720
|
|
|
610
|
-
if(defaultValueSrc) {
|
|
611
|
-
varMsg += `\n${indent}${keyChalk('
|
|
721
|
+
if (defaultValueSrc) {
|
|
722
|
+
varMsg += `\n${indent}${keyChalk('Default value path:'.padEnd(titleText.length, ' '))} `
|
|
612
723
|
varMsg += `${valueChalk(defaultValueSrc)}`
|
|
613
724
|
}
|
|
614
725
|
|
|
@@ -620,26 +731,34 @@ class Configorama {
|
|
|
620
731
|
|
|
621
732
|
let locationRender = valueChalk(variableInstances[0].path)
|
|
622
733
|
|
|
623
|
-
let locationLabel = `${indent}${keyChalk('
|
|
734
|
+
let locationLabel = `${indent}${keyChalk('Path:'.padEnd(titleText.length, ' '))}`
|
|
624
735
|
if (variableInstances.length > 1) {
|
|
625
736
|
locationRender = `\n${variableInstances.map((v) => valueChalk(`${indent}- ${v.path}`)).join('\n')}`
|
|
626
|
-
const locationLabelText = `${indent}${keyChalk('
|
|
737
|
+
const locationLabelText = `${indent}${keyChalk('Paths:')}`
|
|
627
738
|
locationLabel = locationLabelText
|
|
628
739
|
}
|
|
629
740
|
|
|
630
741
|
varMsg += `\n${locationLabel} ${locationRender}`
|
|
742
|
+
|
|
743
|
+
// find the match in our lines
|
|
744
|
+
const line = lines.findIndex((line) => line.includes(key))
|
|
745
|
+
const lineNumber = line + 1
|
|
631
746
|
|
|
632
747
|
// console.log(` ${chalk.bold(key)}`)
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
if(i < varKeys.length - 1) {
|
|
640
|
-
//console.log()
|
|
748
|
+
return {
|
|
749
|
+
text: varMsg,
|
|
750
|
+
title: {
|
|
751
|
+
left: `▶ ${lineNumber ? createEditorLink(this.configFilePath, lineNumber, 1, key) : key}`,
|
|
752
|
+
right: lineNumber ? createEditorLink(this.configFilePath, lineNumber, 1, `Line: ${lineNumber}`, 'gray') : '',
|
|
753
|
+
},
|
|
641
754
|
}
|
|
642
755
|
})
|
|
756
|
+
|
|
757
|
+
console.log(makeStackedBoxes(boxes, {
|
|
758
|
+
borderColor: 'gray',
|
|
759
|
+
minWidth: 120,
|
|
760
|
+
borderStyle: 'bold',
|
|
761
|
+
}))
|
|
643
762
|
}
|
|
644
763
|
|
|
645
764
|
/* Exit early if list or info flag is set */
|
|
@@ -648,33 +767,11 @@ class Configorama {
|
|
|
648
767
|
}
|
|
649
768
|
}
|
|
650
769
|
|
|
651
|
-
this.deep = []
|
|
652
|
-
this.callCount = 0
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
initialCall(func) {
|
|
656
|
-
this.deep = []
|
|
657
|
-
this.tracker.start()
|
|
658
|
-
return func().finally(() => {
|
|
659
|
-
this.tracker.stop()
|
|
660
|
-
this.deep = []
|
|
661
|
-
})
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
/**
|
|
665
|
-
* Populate all variables in the service, conveniently remove and restore the service attributes
|
|
666
|
-
* that confuse the population methods.
|
|
667
|
-
* @param cliOpts An options hive to use for ${opt:...} variables.
|
|
668
|
-
* @returns {Promise.<TResult>|*} A promise resolving to the populated service.
|
|
669
|
-
*/
|
|
670
|
-
init(cliOpts) {
|
|
671
|
-
this.options = cliOpts || {}
|
|
672
|
-
const configoramaOpts = this.opts
|
|
673
770
|
const originalConfig = this.originalConfig
|
|
674
771
|
|
|
675
772
|
/* If no variables found just return early */
|
|
676
773
|
if (this.originalString && !this.originalString.match(this.variableSyntax)) {
|
|
677
|
-
return Promise.resolve(originalConfig)
|
|
774
|
+
return Promise.resolve(this.originalConfig)
|
|
678
775
|
}
|
|
679
776
|
|
|
680
777
|
const useDotEnv = this.originalConfig.useDotenv || this.originalConfig.useDotEnv
|
|
@@ -707,18 +804,28 @@ class Configorama {
|
|
|
707
804
|
// console.log('Final Config', this.config)
|
|
708
805
|
const transform = this.runFunction.bind(this)
|
|
709
806
|
const varSyntax = this.variableSyntax
|
|
807
|
+
const leaves = this.leaves
|
|
808
|
+
// console.log('leaves two', leaves)
|
|
710
809
|
// Traverse resolved object and run functions
|
|
711
810
|
// console.log('this.config', this.config)
|
|
712
811
|
traverse(this.config).forEach(function (rawValue) {
|
|
713
812
|
/* Pass through unknown variables */
|
|
714
813
|
if (!configoramaOpts.allowUndefinedValues && typeof rawValue === 'undefined') {
|
|
715
814
|
const configValuePath = this.path.join('.')
|
|
815
|
+
console.log(this.path)
|
|
716
816
|
const ogValue = dotProp.get(originalConfig, configValuePath)
|
|
717
817
|
const varDisplay = ogValue ? `"${ogValue}" variable` : 'variable'
|
|
818
|
+
|
|
819
|
+
const leaf = leaves.find((l) => l.path.join('.') === configValuePath)
|
|
820
|
+
// if (leaf) {
|
|
821
|
+
// deepLog('leaf', leaf)
|
|
822
|
+
// }
|
|
718
823
|
const errorMessage = `
|
|
719
|
-
|
|
720
|
-
"${configValuePath}" resolved to "undefined"
|
|
721
|
-
|
|
824
|
+
Config error:\n
|
|
825
|
+
Path "${configValuePath}" resolved to "undefined".\n
|
|
826
|
+
Verify the ${varDisplay} in config at "${configValuePath}".\n
|
|
827
|
+
${leaf ? `See:\n ${leaf.originalValuePath}: ${leaf.originalSource} ` : ''}
|
|
828
|
+
${leaf && leaf.isFileRef ? `\n The error could be deeper in the referenced file at ${configValuePath.replace(leaf.originalValuePath, '').replace(/^\./, '')} key.\n` : ''}`
|
|
722
829
|
throw new Error(errorMessage)
|
|
723
830
|
}
|
|
724
831
|
if (typeof rawValue === 'string') {
|
|
@@ -742,6 +849,13 @@ class Configorama {
|
|
|
742
849
|
}
|
|
743
850
|
}
|
|
744
851
|
|
|
852
|
+
/* fix for file(JS-ref.js, raw) to keep parens and inline code */
|
|
853
|
+
const OPEN_PAREN_PLACEHOLDER_PATTERN = /__PH_PAREN_OPEN__/g
|
|
854
|
+
if (rawValue.match(OPEN_PAREN_PLACEHOLDER_PATTERN)) {
|
|
855
|
+
rawValue = rawValue.replace(OPEN_PAREN_PLACEHOLDER_PATTERN, '(')
|
|
856
|
+
this.update(rawValue)
|
|
857
|
+
}
|
|
858
|
+
|
|
745
859
|
/* Allow for unknown variables to pass through */
|
|
746
860
|
if (rawValue.match(/>passthrough/)) {
|
|
747
861
|
const newValues = decodeUnknown(rawValue)
|
|
@@ -783,7 +897,7 @@ class Configorama {
|
|
|
783
897
|
var hasFunc = funcRegex.exec(variableString)
|
|
784
898
|
// TODO finish Function handling. Need to move this down below resolver to resolve inner refs first
|
|
785
899
|
// console.log('hasFunc', hasFunc)
|
|
786
|
-
if (!hasFunc) {
|
|
900
|
+
if (!hasFunc || hasFunc && (hasFunc[1] === 'cron' || hasFunc[1] === 'eval')) {
|
|
787
901
|
return variableString
|
|
788
902
|
}
|
|
789
903
|
// test for object
|
|
@@ -881,12 +995,23 @@ class Configorama {
|
|
|
881
995
|
value: current,
|
|
882
996
|
}
|
|
883
997
|
const thePath = leaf.path.length > 1 ? leaf.path.join('.') : leaf.path[0]
|
|
998
|
+
// console.log('thePath', thePath)
|
|
999
|
+
// console.log('this.originalConfig', this.originalConfig)
|
|
884
1000
|
let originalValue = dotProp.get(this.originalConfig, thePath)
|
|
885
1001
|
// TODO @DWELLS make recursive
|
|
886
1002
|
if (!originalValue) {
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
1003
|
+
// Recurse up the tree until we find a value
|
|
1004
|
+
let currentPathArray = leaf.path.slice(0, -1)
|
|
1005
|
+
while (currentPathArray.length > 0 && !originalValue) {
|
|
1006
|
+
const currentPath = currentPathArray.length > 1 ? currentPathArray.join('.') : currentPathArray[0]
|
|
1007
|
+
// console.log('checking parent path:', currentPath)
|
|
1008
|
+
originalValue = dotProp.get(this.originalConfig, currentPath)
|
|
1009
|
+
if (typeof originalValue !== 'undefined') {
|
|
1010
|
+
leaf.originalValuePath = currentPath
|
|
1011
|
+
leaf.currentConfig = this.config
|
|
1012
|
+
}
|
|
1013
|
+
currentPathArray = currentPathArray.slice(0, -1)
|
|
1014
|
+
}
|
|
890
1015
|
}
|
|
891
1016
|
leaf.originalSource = originalValue
|
|
892
1017
|
if (originalValue && isString(originalValue)) {
|
|
@@ -913,11 +1038,27 @@ class Configorama {
|
|
|
913
1038
|
*/
|
|
914
1039
|
populateVariables(properties) {
|
|
915
1040
|
// console.log('properties', properties)
|
|
916
|
-
|
|
1041
|
+
let variables = properties.filter((property) => {
|
|
917
1042
|
// Initial check if value has variable string in it
|
|
918
1043
|
return isString(property.value) && property.value.match(this.variableSyntax)
|
|
919
1044
|
})
|
|
920
1045
|
|
|
1046
|
+
/*
|
|
1047
|
+
console.log(`variables at call count ${this.callCount}`, variables)
|
|
1048
|
+
/** */
|
|
1049
|
+
|
|
1050
|
+
/* Exclude git messages from being processed */
|
|
1051
|
+
// Was failing on git msgs like "xyz cron:pattern to cron(pattern) for improved clarity"
|
|
1052
|
+
if (this.callCount > 1) {
|
|
1053
|
+
// filter out git vars
|
|
1054
|
+
variables = variables.filter(property => {
|
|
1055
|
+
if (property.originalSource && typeof property.originalSource === 'string') {
|
|
1056
|
+
return !property.originalSource.startsWith('${git:')
|
|
1057
|
+
}
|
|
1058
|
+
return true
|
|
1059
|
+
})
|
|
1060
|
+
}
|
|
1061
|
+
|
|
921
1062
|
return map(variables, (valueObject) => {
|
|
922
1063
|
// console.log('valueObject', valueObject)
|
|
923
1064
|
return this.populateValue(valueObject, false, '_populateVariables').then((populated) => {
|
|
@@ -959,6 +1100,7 @@ class Configorama {
|
|
|
959
1100
|
}
|
|
960
1101
|
|
|
961
1102
|
const leaves = this.getProperties(objectToPopulate, true, objectToPopulate)
|
|
1103
|
+
this.leaves = leaves
|
|
962
1104
|
// console.log('leaves', leaves)
|
|
963
1105
|
const populations = this.populateVariables(leaves)
|
|
964
1106
|
// console.log("FILL LEAVES", populations)
|
|
@@ -1302,7 +1444,19 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1302
1444
|
|
|
1303
1445
|
if (property && typeof property === 'string') {
|
|
1304
1446
|
// console.log('property', property)
|
|
1305
|
-
|
|
1447
|
+
let prop = cleanVariable(
|
|
1448
|
+
property,
|
|
1449
|
+
this.variableSyntax,
|
|
1450
|
+
true,
|
|
1451
|
+
`populateVariable string ${this.callCount}`,
|
|
1452
|
+
// true // recursive
|
|
1453
|
+
)
|
|
1454
|
+
|
|
1455
|
+
// Double processing needed for `${eval(${self:three} > ${self:four})}`
|
|
1456
|
+
if (prop.startsWith('${')) {
|
|
1457
|
+
prop = cleanVariable(prop, this.variableSyntax, true, `populateVariable string ${this.callCount}`)
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1306
1460
|
// console.log('prop', prop)
|
|
1307
1461
|
if (property.match(/^> function /g) && prop) {
|
|
1308
1462
|
// console.log('func prop', property)
|
|
@@ -1341,7 +1495,10 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1341
1495
|
}
|
|
1342
1496
|
*/
|
|
1343
1497
|
// Does not match file refs with nested vars + args
|
|
1344
|
-
|
|
1498
|
+
// @TODO fix this for eval refs
|
|
1499
|
+
// console.log('prop', prop)
|
|
1500
|
+
// console.log('func', func)
|
|
1501
|
+
if (!prop.match(fileRefSyntax) && !prop.match(getValueFromEval.match) && func) {
|
|
1345
1502
|
// console.log('IS FUNCTION')
|
|
1346
1503
|
/* if matches function signature like ${merge('foo', 'bar')}
|
|
1347
1504
|
rewrite the variable to run the function after inputs resolved
|
|
@@ -1492,7 +1649,7 @@ Missing Value ${missingValue} - ${matchedString}
|
|
|
1492
1649
|
if (filters) {
|
|
1493
1650
|
const string = cleanVariable(propertyString, this.variableSyntax, true, `getValueFromSrc filter ${this.callCount}`)
|
|
1494
1651
|
// console.log('string', string)
|
|
1495
|
-
const deeperValue =
|
|
1652
|
+
const deeperValue = getTextAfterOccurrence(string, variableString)
|
|
1496
1653
|
// console.log('deeperValue', deeperValue)
|
|
1497
1654
|
// console.log('filters', filters)
|
|
1498
1655
|
// console.log('variableString', variableString)
|
|
@@ -1845,15 +2002,19 @@ Unable to resolve configuration variable
|
|
|
1845
2002
|
return res
|
|
1846
2003
|
})
|
|
1847
2004
|
}
|
|
1848
|
-
getValueFromFile(variableString) {
|
|
2005
|
+
async getValueFromFile(variableString, options) {
|
|
2006
|
+
const opts = options || {}
|
|
2007
|
+
const syntax = opts.asRawText ? textRefSyntax : fileRefSyntax
|
|
1849
2008
|
// console.log('From file', `"${variableString}"`)
|
|
1850
|
-
let matchedFileString = variableString.match(
|
|
2009
|
+
let matchedFileString = variableString.match(syntax)[0]
|
|
1851
2010
|
// console.log('matchedFileString', matchedFileString)
|
|
1852
2011
|
|
|
1853
|
-
// Get function input params if any supplied
|
|
1854
|
-
|
|
2012
|
+
// Get function input params if any supplied https://regex101.com/r/qlNFVm/1
|
|
2013
|
+
// var funcParamsRegex = /(\w+)\s*\(((?:[^()]+)*)?\s*\)\s*/g
|
|
2014
|
+
var funcParamsRegex = /(\w+)\s*\(((?:[^()]+)*)?\s*\)/g
|
|
2015
|
+
// tighter (?<![.\w-])\b(\w+)\s*\(((?:[^()]+)*)?\s*\)\s*
|
|
1855
2016
|
var hasParams = funcParamsRegex.exec(matchedFileString)
|
|
1856
|
-
|
|
2017
|
+
|
|
1857
2018
|
let argsToPass = []
|
|
1858
2019
|
if (hasParams) {
|
|
1859
2020
|
const splitter = splitCsv(hasParams[2])
|
|
@@ -1861,6 +2022,7 @@ Unable to resolve configuration variable
|
|
|
1861
2022
|
const cleanArg = trim(arg).replace(/^'|"/, '').replace(/'|"$/, '')
|
|
1862
2023
|
return cleanArg
|
|
1863
2024
|
})
|
|
2025
|
+
// console.log('argsFound', argsFound)
|
|
1864
2026
|
|
|
1865
2027
|
// If function has more arguments than file path
|
|
1866
2028
|
if (argsFound.length && argsFound.length > 1) {
|
|
@@ -1873,10 +2035,14 @@ Unable to resolve configuration variable
|
|
|
1873
2035
|
// console.log('argsToPass', argsToPass)
|
|
1874
2036
|
|
|
1875
2037
|
const relativePath = trimSurroundingQuotes(
|
|
1876
|
-
matchedFileString.replace(
|
|
2038
|
+
matchedFileString.replace(syntax, (match, varName) => varName.trim()).replace('~', os.homedir()),
|
|
1877
2039
|
)
|
|
1878
2040
|
|
|
1879
|
-
|
|
2041
|
+
// Resolve alias if the path contains alias syntax
|
|
2042
|
+
const resolvedPath = resolveAlias(relativePath, this.configPath)
|
|
2043
|
+
// console.log('resolvedPath', resolvedPath)
|
|
2044
|
+
|
|
2045
|
+
let fullFilePath = path.isAbsolute(resolvedPath) ? resolvedPath : path.join(this.configPath, resolvedPath)
|
|
1880
2046
|
|
|
1881
2047
|
// console.log('fullFilePath', fullFilePath)
|
|
1882
2048
|
|
|
@@ -1885,13 +2051,13 @@ Unable to resolve configuration variable
|
|
|
1885
2051
|
fullFilePath = fs.realpathSync(fullFilePath)
|
|
1886
2052
|
|
|
1887
2053
|
// Only match files that are relative
|
|
1888
|
-
} else if (
|
|
2054
|
+
} else if (resolvedPath.match(/\.\//)) {
|
|
1889
2055
|
// TODO test higher parent refs
|
|
1890
|
-
const cleanName = path.basename(
|
|
2056
|
+
const cleanName = path.basename(resolvedPath)
|
|
1891
2057
|
fullFilePath = findUp.sync(cleanName, { cwd: this.configPath })
|
|
1892
2058
|
}
|
|
1893
2059
|
|
|
1894
|
-
let fileExtension =
|
|
2060
|
+
let fileExtension = resolvedPath.split('.')
|
|
1895
2061
|
|
|
1896
2062
|
fileExtension = fileExtension[fileExtension.length - 1]
|
|
1897
2063
|
|
|
@@ -1916,8 +2082,16 @@ ${logLines}
|
|
|
1916
2082
|
|
|
1917
2083
|
let valueToPopulate
|
|
1918
2084
|
|
|
2085
|
+
const variableFileContents = fs.readFileSync(fullFilePath, 'utf-8')
|
|
2086
|
+
|
|
2087
|
+
/* handle case for referencing raw JS files to inline them */
|
|
2088
|
+
if (argsToPass.length && (argsToPass && argsToPass[0] && argsToPass[0].toLowerCase() === 'raw') || opts.asRawText) {
|
|
2089
|
+
valueToPopulate = variableFileContents.replace(/\(/g, '__PH_PAREN_OPEN__')
|
|
2090
|
+
return Promise.resolve(valueToPopulate)
|
|
2091
|
+
}
|
|
2092
|
+
|
|
1919
2093
|
// Process JS files
|
|
1920
|
-
if (fileExtension === 'js') {
|
|
2094
|
+
if (fileExtension === 'js' || fileExtension === 'cjs') {
|
|
1921
2095
|
const jsFile = require(fullFilePath)
|
|
1922
2096
|
let returnValueFunction = jsFile
|
|
1923
2097
|
// TODO change how exported functions are referenced
|
|
@@ -1941,7 +2115,7 @@ Check if your javascript is exporting a function that returns a value.`
|
|
|
1941
2115
|
config: this.config,
|
|
1942
2116
|
opts: this.opts,
|
|
1943
2117
|
}
|
|
1944
|
-
|
|
2118
|
+
|
|
1945
2119
|
valueToPopulate = returnValueFunction.call(jsFile, valueForFunction, ...argsToPass)
|
|
1946
2120
|
|
|
1947
2121
|
return Promise.resolve(valueToPopulate).then((valueToPopulateResolved) => {
|
|
@@ -1963,10 +2137,116 @@ Check if your javascript is returning the correct data.`
|
|
|
1963
2137
|
})
|
|
1964
2138
|
}
|
|
1965
2139
|
|
|
1966
|
-
|
|
1967
|
-
|
|
2140
|
+
if (fileExtension === 'ts') {
|
|
2141
|
+
const { executeTypeScriptFile } = require('./parsers/typescript')
|
|
2142
|
+
let returnValueFunction
|
|
2143
|
+
const variableArray = variableString.split(':')
|
|
2144
|
+
|
|
2145
|
+
try {
|
|
2146
|
+
const tsFile = await executeTypeScriptFile(fullFilePath, { dynamicArgs: () => argsToPass })
|
|
2147
|
+
// console.log('fullFilePath', fullFilePath)
|
|
2148
|
+
// console.log('tsFile', tsFile)
|
|
2149
|
+
returnValueFunction = tsFile.config || tsFile.default || tsFile
|
|
2150
|
+
|
|
2151
|
+
if (variableArray[1]) {
|
|
2152
|
+
let tsModule = variableArray[1]
|
|
2153
|
+
tsModule = tsModule.split('.')[0]
|
|
2154
|
+
returnValueFunction = tsFile[tsModule]
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2157
|
+
if (typeof returnValueFunction !== 'function') {
|
|
2158
|
+
const errorMessage = `Invalid variable syntax when referencing file "${relativePath}".
|
|
2159
|
+
Check if your TypeScript is exporting a function that returns a value.`
|
|
2160
|
+
return Promise.reject(new Error(errorMessage))
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
const valueForFunction = {
|
|
2164
|
+
originalConfig: this.originalConfig,
|
|
2165
|
+
config: this.config,
|
|
2166
|
+
opts: this.opts,
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
valueToPopulate = returnValueFunction.call(tsFile, valueForFunction, ...argsToPass)
|
|
2170
|
+
|
|
2171
|
+
return Promise.resolve(valueToPopulate).then((valueToPopulateResolved) => {
|
|
2172
|
+
let deepProperties = variableString.replace(matchedFileString, '')
|
|
2173
|
+
deepProperties = deepProperties.slice(1).split('.')
|
|
2174
|
+
deepProperties.splice(0, 1)
|
|
2175
|
+
// Trim prop keys for starting/trailing spaces
|
|
2176
|
+
deepProperties = deepProperties.map((prop) => {
|
|
2177
|
+
return trim(prop)
|
|
2178
|
+
})
|
|
2179
|
+
return this.getDeeperValue(deepProperties, valueToPopulateResolved).then((deepValueToPopulateResolved) => {
|
|
2180
|
+
if (typeof deepValueToPopulateResolved === 'undefined') {
|
|
2181
|
+
const errorMessage = `Invalid variable syntax when referencing file "${relativePath}".
|
|
2182
|
+
Check if your TypeScript is returning the correct data.`
|
|
2183
|
+
return Promise.reject(new Error(errorMessage))
|
|
2184
|
+
}
|
|
2185
|
+
return Promise.resolve(deepValueToPopulateResolved)
|
|
2186
|
+
})
|
|
2187
|
+
})
|
|
2188
|
+
} catch (err) {
|
|
2189
|
+
return Promise.reject(new Error(`Error processing TypeScript file: ${err.message}`))
|
|
2190
|
+
}
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
if (fileExtension === 'mjs' || fileExtension === 'esm') {
|
|
2194
|
+
const { executeESMFile } = require('./parsers/esm')
|
|
2195
|
+
let returnValueFunction
|
|
2196
|
+
const variableArray = variableString.split(':')
|
|
2197
|
+
|
|
2198
|
+
try {
|
|
2199
|
+
const esmFile = await executeESMFile(fullFilePath, { dynamicArgs: () => argsToPass })
|
|
2200
|
+
// console.log('ESM fullFilePath', fullFilePath)
|
|
2201
|
+
// console.log('ESM esmFile', esmFile, 'type:', typeof esmFile)
|
|
2202
|
+
returnValueFunction = esmFile.config || esmFile.default || esmFile
|
|
2203
|
+
|
|
2204
|
+
if (variableArray[1]) {
|
|
2205
|
+
let esmModule = variableArray[1]
|
|
2206
|
+
esmModule = esmModule.split('.')[0]
|
|
2207
|
+
returnValueFunction = esmFile[esmModule]
|
|
2208
|
+
}
|
|
2209
|
+
|
|
2210
|
+
if (typeof returnValueFunction !== 'function') {
|
|
2211
|
+
const errorMessage = `Invalid variable syntax when referencing file "${relativePath}".
|
|
2212
|
+
Check if your ESM is exporting a function that returns a value.`
|
|
2213
|
+
return Promise.reject(new Error(errorMessage))
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
const valueForFunction = {
|
|
2217
|
+
originalConfig: this.originalConfig,
|
|
2218
|
+
config: this.config,
|
|
2219
|
+
opts: this.opts,
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
valueToPopulate = returnValueFunction.call(esmFile, valueForFunction, ...argsToPass)
|
|
2223
|
+
|
|
2224
|
+
return Promise.resolve(valueToPopulate).then((valueToPopulateResolved) => {
|
|
2225
|
+
let deepProperties = variableString.replace(matchedFileString, '')
|
|
2226
|
+
deepProperties = deepProperties.slice(1).split('.')
|
|
2227
|
+
deepProperties.splice(0, 1)
|
|
2228
|
+
// Trim prop keys for starting/trailing spaces
|
|
2229
|
+
deepProperties = deepProperties.map((prop) => {
|
|
2230
|
+
return trim(prop)
|
|
2231
|
+
})
|
|
2232
|
+
return this.getDeeperValue(deepProperties, valueToPopulateResolved).then((deepValueToPopulateResolved) => {
|
|
2233
|
+
if (typeof deepValueToPopulateResolved === 'undefined') {
|
|
2234
|
+
const errorMessage = `Invalid variable syntax when referencing file "${relativePath}".
|
|
2235
|
+
Check if your ESM is returning the correct data.`
|
|
2236
|
+
return Promise.reject(new Error(errorMessage))
|
|
2237
|
+
}
|
|
2238
|
+
return Promise.resolve(deepValueToPopulateResolved)
|
|
2239
|
+
})
|
|
2240
|
+
})
|
|
2241
|
+
} catch (err) {
|
|
2242
|
+
return Promise.reject(new Error(`Error processing ESM file: ${err.message}`))
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
// Process everything except JS, TS, and ESM
|
|
2247
|
+
if (fileExtension !== 'js' && fileExtension !== 'ts' && fileExtension !== 'mjs' && fileExtension !== 'esm') {
|
|
1968
2248
|
/* Read initial file */
|
|
1969
|
-
valueToPopulate =
|
|
2249
|
+
valueToPopulate = variableFileContents
|
|
1970
2250
|
|
|
1971
2251
|
// File reference has :subKey lookup. Must dig deeper
|
|
1972
2252
|
if (matchedFileString !== variableString) {
|
|
@@ -1976,6 +2256,9 @@ Check if your javascript is returning the correct data.`
|
|
|
1976
2256
|
if (fileExtension === 'toml') {
|
|
1977
2257
|
valueToPopulate = JSON.stringify(TOML.parse(valueToPopulate))
|
|
1978
2258
|
}
|
|
2259
|
+
if (fileExtension === 'ini') {
|
|
2260
|
+
valueToPopulate = INI.toJson(valueToPopulate)
|
|
2261
|
+
}
|
|
1979
2262
|
// console.log('deep', variableString)
|
|
1980
2263
|
// console.log('matchedFileString', matchedFileString)
|
|
1981
2264
|
let deepProperties = variableString.replace(matchedFileString, '')
|
|
@@ -1998,11 +2281,17 @@ Please use ":" to reference sub properties`
|
|
|
1998
2281
|
return Promise.resolve(valueToPopulate)
|
|
1999
2282
|
}
|
|
2000
2283
|
|
|
2284
|
+
if (fileExtension === 'ini') {
|
|
2285
|
+
valueToPopulate = INI.parse(valueToPopulate)
|
|
2286
|
+
return Promise.resolve(valueToPopulate)
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2001
2289
|
if (fileExtension === 'json') {
|
|
2002
2290
|
valueToPopulate = JSON.parse(valueToPopulate)
|
|
2003
2291
|
return Promise.resolve(valueToPopulate)
|
|
2004
2292
|
}
|
|
2005
2293
|
}
|
|
2294
|
+
console.log('fall thru', valueToPopulate)
|
|
2006
2295
|
return Promise.resolve(valueToPopulate)
|
|
2007
2296
|
}
|
|
2008
2297
|
getVariableFromDeep(variableString) {
|
|
@@ -2140,6 +2429,8 @@ Please use ":" to reference sub properties`
|
|
|
2140
2429
|
varType = 'file'
|
|
2141
2430
|
} else if (variableString.match(deepRefSyntax)) {
|
|
2142
2431
|
varType = 'deep'
|
|
2432
|
+
} else if (variableString.match(textRefSyntax)) {
|
|
2433
|
+
varType = 'text'
|
|
2143
2434
|
}
|
|
2144
2435
|
if (!isValidValue(valueToPopulate)) {
|
|
2145
2436
|
// console.log("MISSING", variableString)
|