configorama 0.6.18 → 0.7.0
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 +78 -2
- package/cli.js +1 -0
- package/index.d.ts +90 -37
- package/package.json +8 -2
- package/src/index.js +42 -14
- package/src/main.js +135 -62
- package/src/parsers/index.js +10 -0
- package/src/parsers/typescript.js +20 -43
- package/src/parsers/yaml.js +35 -2
- package/src/resolvers/valueFromFile.js +87 -24
- package/src/resolvers/valueFromGit.js +11 -3
- package/src/utils/encoders/js-fixes.js +44 -0
- package/src/utils/parsing/mergeByKeys.js +4 -3
- package/src/utils/parsing/parse.js +4 -2
- package/src/utils/parsing/preProcess.js +42 -25
- package/src/utils/parsing/preProcess.test.js +214 -0
- package/src/utils/paths/getFullFilePath.js +1 -1
- package/src/utils/resolution/preResolveVariable.js +1 -0
- package/src/utils/strings/quoteUtils.js +2 -2
- package/src/utils/strings/splitCsv.js +1 -1
- package/src/utils/ui/logs.js +4 -4
- package/src/utils/validation/warnIfNotFound.js +3 -3
- package/src/utils/variables/findNestedVariables.js +2 -2
- package/src/utils/variables/variableUtils.js +43 -0
- package/src/utils/variables/variableUtils.test.js +38 -1
- package/types/cli.d.ts +3 -0
- package/types/cli.d.ts.map +1 -0
- package/types/src/functions/md5.d.ts +3 -0
- package/types/src/functions/md5.d.ts.map +1 -0
- package/types/src/index.d.ts +100 -0
- package/types/src/index.d.ts.map +1 -0
- package/types/src/main.d.ts +275 -0
- package/types/src/main.d.ts.map +1 -0
- package/types/src/parsers/esm.d.ts +15 -0
- package/types/src/parsers/esm.d.ts.map +1 -0
- package/types/src/parsers/hcl.d.ts +1 -0
- package/types/src/parsers/hcl.d.ts.map +1 -0
- package/types/src/parsers/index.d.ts +18 -0
- package/types/src/parsers/index.d.ts.map +1 -0
- package/types/src/parsers/ini.d.ts +6 -0
- package/types/src/parsers/ini.d.ts.map +1 -0
- package/types/src/parsers/json5.d.ts +10 -0
- package/types/src/parsers/json5.d.ts.map +1 -0
- package/types/src/parsers/toml.d.ts +7 -0
- package/types/src/parsers/toml.d.ts.map +1 -0
- package/types/src/parsers/typescript.d.ts +15 -0
- package/types/src/parsers/typescript.d.ts.map +1 -0
- package/types/src/parsers/yaml.d.ts +45 -0
- package/types/src/parsers/yaml.d.ts.map +1 -0
- package/types/src/resolvers/valueFromCron.d.ts +14 -0
- package/types/src/resolvers/valueFromCron.d.ts.map +1 -0
- package/types/src/resolvers/valueFromEnv.d.ts +8 -0
- package/types/src/resolvers/valueFromEnv.d.ts.map +1 -0
- package/types/src/resolvers/valueFromEval.d.ts +7 -0
- package/types/src/resolvers/valueFromEval.d.ts.map +1 -0
- package/types/src/resolvers/valueFromFile.d.ts +58 -0
- package/types/src/resolvers/valueFromFile.d.ts.map +1 -0
- package/types/src/resolvers/valueFromGit.d.ts +11 -0
- package/types/src/resolvers/valueFromGit.d.ts.map +1 -0
- package/types/src/resolvers/valueFromNumber.d.ts +6 -0
- package/types/src/resolvers/valueFromNumber.d.ts.map +1 -0
- package/types/src/resolvers/valueFromOptions.d.ts +9 -0
- package/types/src/resolvers/valueFromOptions.d.ts.map +1 -0
- package/types/src/resolvers/valueFromSelf.d.ts +1 -0
- package/types/src/resolvers/valueFromSelf.d.ts.map +1 -0
- package/types/src/resolvers/valueFromString.d.ts +6 -0
- package/types/src/resolvers/valueFromString.d.ts.map +1 -0
- package/types/src/sync.d.ts +3 -0
- package/types/src/sync.d.ts.map +1 -0
- package/types/src/utils/PromiseTracker.d.ts +19 -0
- package/types/src/utils/PromiseTracker.d.ts.map +1 -0
- package/types/src/utils/encoders/index.d.ts +2 -0
- package/types/src/utils/encoders/index.d.ts.map +1 -0
- package/types/src/utils/encoders/js-fixes.d.ts +23 -0
- package/types/src/utils/encoders/js-fixes.d.ts.map +1 -0
- package/types/src/utils/encoders/unknown-values.d.ts +18 -0
- package/types/src/utils/encoders/unknown-values.d.ts.map +1 -0
- package/types/src/utils/handleSignalEvents.d.ts +3 -0
- package/types/src/utils/handleSignalEvents.d.ts.map +1 -0
- package/types/src/utils/lodash.d.ts +4 -0
- package/types/src/utils/lodash.d.ts.map +1 -0
- package/types/src/utils/parsing/arrayToJsonPath.d.ts +5 -0
- package/types/src/utils/parsing/arrayToJsonPath.d.ts.map +1 -0
- package/types/src/utils/parsing/cloudformationSchema.d.ts +2 -0
- package/types/src/utils/parsing/cloudformationSchema.d.ts.map +1 -0
- package/types/src/utils/parsing/enrichMetadata.d.ts +17 -0
- package/types/src/utils/parsing/enrichMetadata.d.ts.map +1 -0
- package/types/src/utils/parsing/mergeByKeys.d.ts +5 -0
- package/types/src/utils/parsing/mergeByKeys.d.ts.map +1 -0
- package/types/src/utils/parsing/parse.d.ts +54 -0
- package/types/src/utils/parsing/parse.d.ts.map +1 -0
- package/types/src/utils/parsing/preProcess.d.ts +10 -0
- package/types/src/utils/parsing/preProcess.d.ts.map +1 -0
- package/types/src/utils/paths/filePathUtils.d.ts +32 -0
- package/types/src/utils/paths/filePathUtils.d.ts.map +1 -0
- package/types/src/utils/paths/findLineForKey.d.ts +12 -0
- package/types/src/utils/paths/findLineForKey.d.ts.map +1 -0
- package/types/src/utils/paths/findProjectRoot.d.ts +2 -0
- package/types/src/utils/paths/findProjectRoot.d.ts.map +1 -0
- package/types/src/utils/paths/getFullFilePath.d.ts +25 -0
- package/types/src/utils/paths/getFullFilePath.d.ts.map +1 -0
- package/types/src/utils/paths/resolveAlias.d.ts +14 -0
- package/types/src/utils/paths/resolveAlias.d.ts.map +1 -0
- package/types/src/utils/regex/index.d.ts +14 -0
- package/types/src/utils/regex/index.d.ts.map +1 -0
- package/types/src/utils/resolution/preResolveVariable.d.ts +51 -0
- package/types/src/utils/resolution/preResolveVariable.d.ts.map +1 -0
- package/types/src/utils/strings/bracketMatcher.d.ts +25 -0
- package/types/src/utils/strings/bracketMatcher.d.ts.map +1 -0
- package/types/src/utils/strings/formatFunctionArgs.d.ts +3 -0
- package/types/src/utils/strings/formatFunctionArgs.d.ts.map +1 -0
- package/types/src/utils/strings/quoteUtils.d.ts +31 -0
- package/types/src/utils/strings/quoteUtils.d.ts.map +1 -0
- package/types/src/utils/strings/replaceAll.d.ts +9 -0
- package/types/src/utils/strings/replaceAll.d.ts.map +1 -0
- package/types/src/utils/strings/splitByComma.d.ts +2 -0
- package/types/src/utils/strings/splitByComma.d.ts.map +1 -0
- package/types/src/utils/strings/splitCsv.d.ts +10 -0
- package/types/src/utils/strings/splitCsv.d.ts.map +1 -0
- package/types/src/utils/strings/textUtils.d.ts +15 -0
- package/types/src/utils/strings/textUtils.d.ts.map +1 -0
- package/types/src/utils/ui/chalk.d.ts +70 -0
- package/types/src/utils/ui/chalk.d.ts.map +1 -0
- package/types/src/utils/ui/configWizard.d.ts +67 -0
- package/types/src/utils/ui/configWizard.d.ts.map +1 -0
- package/types/src/utils/ui/createEditorLink.d.ts +11 -0
- package/types/src/utils/ui/createEditorLink.d.ts.map +1 -0
- package/types/src/utils/ui/deep-log.d.ts +3 -0
- package/types/src/utils/ui/deep-log.d.ts.map +1 -0
- package/types/src/utils/ui/logs.d.ts +2 -0
- package/types/src/utils/ui/logs.d.ts.map +1 -0
- package/types/src/utils/validation/warnIfNotFound.d.ts +15 -0
- package/types/src/utils/validation/warnIfNotFound.d.ts.map +1 -0
- package/types/src/utils/variables/appendDeepVariable.d.ts +3 -0
- package/types/src/utils/variables/appendDeepVariable.d.ts.map +1 -0
- package/types/src/utils/variables/cleanVariable.d.ts +3 -0
- package/types/src/utils/variables/cleanVariable.d.ts.map +1 -0
- package/types/src/utils/variables/findNestedVariables.d.ts +23 -0
- package/types/src/utils/variables/findNestedVariables.d.ts.map +1 -0
- package/types/src/utils/variables/getVariableType.d.ts +8 -0
- package/types/src/utils/variables/getVariableType.d.ts.map +1 -0
- package/types/src/utils/variables/variableUtils.d.ts +21 -0
- package/types/src/utils/variables/variableUtils.d.ts.map +1 -0
|
@@ -3,16 +3,27 @@
|
|
|
3
3
|
* and escape variables inside help() filter arguments
|
|
4
4
|
*/
|
|
5
5
|
const { splitByComma } = require('../strings/splitByComma')
|
|
6
|
+
const { extractVariableWrapper } = require('../variables/variableUtils')
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Preprocess config to fix malformed fallback references
|
|
9
10
|
* @param {Object} configObject - The parsed configuration object
|
|
10
11
|
* @param {RegExp} variableSyntax - The variable syntax regex to use
|
|
12
|
+
* @param {Array} [variableTypes] - Array of variable type definitions with type/prefix fields
|
|
11
13
|
* @returns {Object} The preprocessed configuration object
|
|
12
14
|
*/
|
|
13
|
-
function preProcess(configObject, variableSyntax) {
|
|
14
|
-
//
|
|
15
|
-
const
|
|
15
|
+
function preProcess(configObject, variableSyntax, variableTypes) {
|
|
16
|
+
// Extract prefix/suffix from variable syntax for reconstructing variables
|
|
17
|
+
const { prefix: varPrefix, suffix: varSuffix } = variableSyntax
|
|
18
|
+
? extractVariableWrapper(variableSyntax.source)
|
|
19
|
+
: { prefix: '${', suffix: '}' }
|
|
20
|
+
|
|
21
|
+
// Extract reference prefixes from variable types, or use defaults
|
|
22
|
+
const refPrefixes = variableTypes && variableTypes.length > 0
|
|
23
|
+
? variableTypes
|
|
24
|
+
.map(v => (v.prefix || v.type) + ':')
|
|
25
|
+
.filter(p => p !== 'dot.prop:' && p !== 'string:' && p !== 'number:')
|
|
26
|
+
: ['self:', 'opt:', 'env:', 'file:', 'text:', 'deep:']
|
|
16
27
|
|
|
17
28
|
/**
|
|
18
29
|
* Escape variables inside help() filter arguments so main resolver skips them
|
|
@@ -52,31 +63,37 @@ function preProcess(configObject, variableSyntax) {
|
|
|
52
63
|
let changed = true
|
|
53
64
|
|
|
54
65
|
// Keep iterating until no more changes (to handle nested variables)
|
|
66
|
+
const prefixLen = varPrefix.length
|
|
67
|
+
const suffixLen = varSuffix.length
|
|
68
|
+
|
|
55
69
|
while (changed) {
|
|
56
70
|
changed = false
|
|
57
71
|
|
|
58
|
-
// Find innermost
|
|
72
|
+
// Find innermost variable blocks (ones that don't contain other variables)
|
|
59
73
|
let i = 0
|
|
60
74
|
while (i < result.length) {
|
|
61
|
-
if (result
|
|
75
|
+
if (result.substring(i, i + prefixLen) === varPrefix) {
|
|
62
76
|
const start = i
|
|
63
|
-
let
|
|
64
|
-
let j = i +
|
|
65
|
-
|
|
66
|
-
// Find the matching
|
|
67
|
-
while (j < result.length &&
|
|
68
|
-
if (result
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
77
|
+
let depth = 1
|
|
78
|
+
let j = i + prefixLen
|
|
79
|
+
|
|
80
|
+
// Find the matching suffix by counting full prefix/suffix occurrences
|
|
81
|
+
while (j < result.length && depth > 0) {
|
|
82
|
+
if (result.substring(j, j + prefixLen) === varPrefix) {
|
|
83
|
+
depth++
|
|
84
|
+
j += prefixLen
|
|
85
|
+
} else if (result.substring(j, j + suffixLen) === varSuffix) {
|
|
86
|
+
depth--
|
|
87
|
+
if (depth > 0) j += suffixLen
|
|
88
|
+
} else {
|
|
89
|
+
j++
|
|
72
90
|
}
|
|
73
|
-
j++
|
|
74
91
|
}
|
|
75
92
|
|
|
76
|
-
if (
|
|
77
|
-
const end = j
|
|
93
|
+
if (depth === 0) {
|
|
94
|
+
const end = j + suffixLen
|
|
78
95
|
const match = result.substring(start, end)
|
|
79
|
-
const content = result.substring(start +
|
|
96
|
+
const content = result.substring(start + prefixLen, end - suffixLen)
|
|
80
97
|
|
|
81
98
|
// Only process if there's a comma (indicating fallback syntax)
|
|
82
99
|
if (content.includes(',')) {
|
|
@@ -84,10 +101,10 @@ function preProcess(configObject, variableSyntax) {
|
|
|
84
101
|
const parts = splitByComma(content, variableSyntax)
|
|
85
102
|
|
|
86
103
|
if (parts.length > 1) {
|
|
87
|
-
// Check if the first part has nested
|
|
104
|
+
// Check if the first part has nested variables - if so, skip this (process inner ones first)
|
|
88
105
|
const firstPart = parts[0]
|
|
89
|
-
if (firstPart.includes(
|
|
90
|
-
i = start +
|
|
106
|
+
if (firstPart.includes(varPrefix)) {
|
|
107
|
+
i = start + prefixLen // Move past prefix to find inner variables
|
|
91
108
|
continue
|
|
92
109
|
}
|
|
93
110
|
|
|
@@ -101,16 +118,16 @@ function preProcess(configObject, variableSyntax) {
|
|
|
101
118
|
|
|
102
119
|
// Check if this looks like a reference but is not wrapped
|
|
103
120
|
const looksLikeRef = refPrefixes.some(prefix => trimmed.startsWith(prefix))
|
|
104
|
-
const alreadyWrapped = trimmed.startsWith(
|
|
121
|
+
const alreadyWrapped = trimmed.startsWith(varPrefix) && trimmed.endsWith(varSuffix)
|
|
105
122
|
|
|
106
123
|
if (looksLikeRef && !alreadyWrapped) {
|
|
107
|
-
return `
|
|
124
|
+
return ` ${varPrefix}${trimmed}${varSuffix}`
|
|
108
125
|
}
|
|
109
126
|
|
|
110
127
|
return ` ${trimmed}`
|
|
111
128
|
})
|
|
112
129
|
|
|
113
|
-
const replacement =
|
|
130
|
+
const replacement = `${varPrefix}${fixed.join(',')}${varSuffix}`
|
|
114
131
|
if (replacement !== match) {
|
|
115
132
|
result = result.substring(0, start) + replacement + result.substring(end)
|
|
116
133
|
changed = true
|
|
@@ -119,7 +136,7 @@ function preProcess(configObject, variableSyntax) {
|
|
|
119
136
|
}
|
|
120
137
|
}
|
|
121
138
|
|
|
122
|
-
i = start +
|
|
139
|
+
i = start + prefixLen // Move past prefix to continue searching for nested variables
|
|
123
140
|
} else {
|
|
124
141
|
i++
|
|
125
142
|
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// Tests for preProcess utility (fixFallbacksInString)
|
|
2
|
+
|
|
3
|
+
const { test } = require('uvu')
|
|
4
|
+
const assert = require('uvu/assert')
|
|
5
|
+
const preProcess = require('./preProcess')
|
|
6
|
+
|
|
7
|
+
// Default ${} syntax
|
|
8
|
+
const defaultSyntax = /\$\{([ ~:a-zA-Z0-9._\\'",\-\/\(\)]+?)\}/g
|
|
9
|
+
|
|
10
|
+
// Custom syntaxes
|
|
11
|
+
const doubleBraceSyntax = /\$\{\{([ ~:a-zA-Z0-9._\\'",\-\/\(\)]+?)\}\}/g
|
|
12
|
+
const hashSyntax = /\#\{([ ~:a-zA-Z0-9._\\'",\-\/\(\)]+?)\}/g
|
|
13
|
+
const angleSyntax = /\<([ ~:a-zA-Z0-9._\\'",\-\/\(\)]+?)\>/g
|
|
14
|
+
|
|
15
|
+
// Tests for fixFallbacksInString with default ${} syntax
|
|
16
|
+
test('fixFallbacksInString - wraps unwrapped self: fallback', () => {
|
|
17
|
+
const input = { key: '${opt:missing, self:fallback}' }
|
|
18
|
+
const result = preProcess(input, defaultSyntax)
|
|
19
|
+
assert.is(result.key, '${opt:missing, ${self:fallback}}')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
test('fixFallbacksInString - wraps unwrapped env: fallback', () => {
|
|
23
|
+
const input = { key: '${opt:missing, env:FALLBACK}' }
|
|
24
|
+
const result = preProcess(input, defaultSyntax)
|
|
25
|
+
assert.is(result.key, '${opt:missing, ${env:FALLBACK}}')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test('fixFallbacksInString - wraps unwrapped opt: fallback', () => {
|
|
29
|
+
const input = { key: '${self:missing, opt:fallback}' }
|
|
30
|
+
const result = preProcess(input, defaultSyntax)
|
|
31
|
+
assert.is(result.key, '${self:missing, ${opt:fallback}}')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('fixFallbacksInString - wraps unwrapped file: fallback', () => {
|
|
35
|
+
const input = { key: '${opt:missing, file:./config.json}' }
|
|
36
|
+
const result = preProcess(input, defaultSyntax)
|
|
37
|
+
assert.is(result.key, '${opt:missing, ${file:./config.json}}')
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('fixFallbacksInString - leaves already wrapped fallback alone', () => {
|
|
41
|
+
const input = { key: '${opt:missing, ${self:fallback}}' }
|
|
42
|
+
const result = preProcess(input, defaultSyntax)
|
|
43
|
+
assert.is(result.key, '${opt:missing, ${self:fallback}}')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('fixFallbacksInString - leaves string fallback alone', () => {
|
|
47
|
+
const input = { key: '${opt:missing, "default"}' }
|
|
48
|
+
const result = preProcess(input, defaultSyntax)
|
|
49
|
+
assert.is(result.key, '${opt:missing, "default"}')
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
test('fixFallbacksInString - leaves numeric fallback alone', () => {
|
|
53
|
+
const input = { key: '${opt:missing, 42}' }
|
|
54
|
+
const result = preProcess(input, defaultSyntax)
|
|
55
|
+
assert.is(result.key, '${opt:missing, 42}')
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('fixFallbacksInString - handles multiple fallbacks', () => {
|
|
59
|
+
const input = { key: '${opt:missing, self:first, env:second}' }
|
|
60
|
+
const result = preProcess(input, defaultSyntax)
|
|
61
|
+
assert.is(result.key, '${opt:missing, ${self:first}, ${env:second}}')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test('fixFallbacksInString - handles nested variables in primary', () => {
|
|
65
|
+
const input = { key: '${file(./config.${opt:stage}.json), "default"}' }
|
|
66
|
+
const result = preProcess(input, defaultSyntax)
|
|
67
|
+
assert.is(result.key, '${file(./config.${opt:stage}.json), "default"}')
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
// Tests for ${{}} syntax
|
|
71
|
+
test('fixFallbacksInString - ${{}} syntax wraps unwrapped fallback', () => {
|
|
72
|
+
const input = { key: '${{opt:missing, self:fallback}}' }
|
|
73
|
+
const result = preProcess(input, doubleBraceSyntax)
|
|
74
|
+
assert.is(result.key, '${{opt:missing, ${{self:fallback}}}}')
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('fixFallbacksInString - ${{}} syntax leaves wrapped fallback alone', () => {
|
|
78
|
+
const input = { key: '${{opt:missing, ${{self:fallback}}}}' }
|
|
79
|
+
const result = preProcess(input, doubleBraceSyntax)
|
|
80
|
+
assert.is(result.key, '${{opt:missing, ${{self:fallback}}}}')
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test('fixFallbacksInString - ${{}} syntax leaves string fallback alone', () => {
|
|
84
|
+
const input = { key: '${{opt:missing, "default"}}' }
|
|
85
|
+
const result = preProcess(input, doubleBraceSyntax)
|
|
86
|
+
assert.is(result.key, '${{opt:missing, "default"}}')
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// Tests for #{} syntax
|
|
90
|
+
test('fixFallbacksInString - #{} syntax wraps unwrapped fallback', () => {
|
|
91
|
+
const input = { key: '#{opt:missing, self:fallback}' }
|
|
92
|
+
const result = preProcess(input, hashSyntax)
|
|
93
|
+
assert.is(result.key, '#{opt:missing, #{self:fallback}}')
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
test('fixFallbacksInString - #{} syntax leaves wrapped fallback alone', () => {
|
|
97
|
+
const input = { key: '#{opt:missing, #{self:fallback}}' }
|
|
98
|
+
const result = preProcess(input, hashSyntax)
|
|
99
|
+
assert.is(result.key, '#{opt:missing, #{self:fallback}}')
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
test('fixFallbacksInString - #{} syntax handles multiple fallbacks', () => {
|
|
103
|
+
const input = { key: '#{opt:missing, env:FIRST, self:second}' }
|
|
104
|
+
const result = preProcess(input, hashSyntax)
|
|
105
|
+
assert.is(result.key, '#{opt:missing, #{env:FIRST}, #{self:second}}')
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
// Tests for <> syntax
|
|
109
|
+
test('fixFallbacksInString - <> syntax wraps unwrapped fallback', () => {
|
|
110
|
+
const input = { key: '<opt:missing, self:fallback>' }
|
|
111
|
+
const result = preProcess(input, angleSyntax)
|
|
112
|
+
assert.is(result.key, '<opt:missing, <self:fallback>>')
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
test('fixFallbacksInString - <> syntax leaves wrapped fallback alone', () => {
|
|
116
|
+
const input = { key: '<opt:missing, <self:fallback>>' }
|
|
117
|
+
const result = preProcess(input, angleSyntax)
|
|
118
|
+
assert.is(result.key, '<opt:missing, <self:fallback>>')
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
test('fixFallbacksInString - <> syntax leaves string fallback alone', () => {
|
|
122
|
+
const input = { key: '<opt:missing, "default">' }
|
|
123
|
+
const result = preProcess(input, angleSyntax)
|
|
124
|
+
assert.is(result.key, '<opt:missing, "default">')
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
// Edge cases
|
|
128
|
+
test('fixFallbacksInString - handles deeply nested objects', () => {
|
|
129
|
+
const input = {
|
|
130
|
+
level1: {
|
|
131
|
+
level2: {
|
|
132
|
+
key: '${opt:missing, self:fallback}'
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const result = preProcess(input, defaultSyntax)
|
|
137
|
+
assert.is(result.level1.level2.key, '${opt:missing, ${self:fallback}}')
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
test('fixFallbacksInString - handles arrays', () => {
|
|
141
|
+
const input = {
|
|
142
|
+
items: [
|
|
143
|
+
'${opt:one, self:fallback1}',
|
|
144
|
+
'${opt:two, self:fallback2}'
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
const result = preProcess(input, defaultSyntax)
|
|
148
|
+
assert.is(result.items[0], '${opt:one, ${self:fallback1}}')
|
|
149
|
+
assert.is(result.items[1], '${opt:two, ${self:fallback2}}')
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
test('fixFallbacksInString - handles no variable syntax', () => {
|
|
153
|
+
const input = { key: 'just a plain string' }
|
|
154
|
+
const result = preProcess(input, defaultSyntax)
|
|
155
|
+
assert.is(result.key, 'just a plain string')
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
test('fixFallbacksInString - handles null variableSyntax', () => {
|
|
159
|
+
const input = { key: '${opt:missing, self:fallback}' }
|
|
160
|
+
const result = preProcess(input, null)
|
|
161
|
+
// Without syntax, should use defaults
|
|
162
|
+
assert.is(result.key, '${opt:missing, ${self:fallback}}')
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
// Tests with explicit variableTypes
|
|
166
|
+
const defaultVariableTypes = [
|
|
167
|
+
{ type: 'env' },
|
|
168
|
+
{ type: 'options', prefix: 'opt' },
|
|
169
|
+
{ type: 'self', prefix: 'self' },
|
|
170
|
+
{ type: 'file', prefix: 'file' },
|
|
171
|
+
{ type: 'text', prefix: 'text' },
|
|
172
|
+
{ type: 'deep' },
|
|
173
|
+
]
|
|
174
|
+
|
|
175
|
+
test('fixFallbacksInString - uses variableTypes to determine prefixes', () => {
|
|
176
|
+
const input = { key: '${opt:missing, self:fallback}' }
|
|
177
|
+
const result = preProcess(input, defaultSyntax, defaultVariableTypes)
|
|
178
|
+
assert.is(result.key, '${opt:missing, ${self:fallback}}')
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
test('fixFallbacksInString - custom variableTypes with custom prefix', () => {
|
|
182
|
+
const customTypes = [
|
|
183
|
+
{ type: 'ssm', prefix: 'ssm' },
|
|
184
|
+
{ type: 'secret', prefix: 'secret' },
|
|
185
|
+
]
|
|
186
|
+
const input = { key: '${opt:missing, ssm:/path/to/param}' }
|
|
187
|
+
const result = preProcess(input, defaultSyntax, customTypes)
|
|
188
|
+
assert.is(result.key, '${opt:missing, ${ssm:/path/to/param}}')
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
test('fixFallbacksInString - custom variableTypes wraps secret: fallback', () => {
|
|
192
|
+
const customTypes = [
|
|
193
|
+
{ type: 'ssm', prefix: 'ssm' },
|
|
194
|
+
{ type: 'secret', prefix: 'secret' },
|
|
195
|
+
{ type: 'self', prefix: 'self' },
|
|
196
|
+
]
|
|
197
|
+
const input = { key: '${self:missing, secret:API_KEY}' }
|
|
198
|
+
const result = preProcess(input, defaultSyntax, customTypes)
|
|
199
|
+
assert.is(result.key, '${self:missing, ${secret:API_KEY}}')
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
test('fixFallbacksInString - ignores dot.prop and string types in prefixes', () => {
|
|
203
|
+
const typesWithDotProp = [
|
|
204
|
+
{ type: 'env' },
|
|
205
|
+
{ type: 'dot.prop' },
|
|
206
|
+
{ type: 'string' },
|
|
207
|
+
{ type: 'self', prefix: 'self' },
|
|
208
|
+
]
|
|
209
|
+
const input = { key: '${env:MISSING, self:fallback}' }
|
|
210
|
+
const result = preProcess(input, defaultSyntax, typesWithDotProp)
|
|
211
|
+
assert.is(result.key, '${env:MISSING, ${self:fallback}}')
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
test.run()
|
|
@@ -40,7 +40,7 @@ function getFullPath(fileString, cwd) {
|
|
|
40
40
|
* @param {string} matchedFileString - The matched file string (e.g., "file(path/to/file.js)")
|
|
41
41
|
* @param {RegExp} syntax - The regex pattern used to match the file string (e.g., fileRefSyntax or textRefSyntax)
|
|
42
42
|
* @param {string} configPath - The base directory path for resolving relative paths
|
|
43
|
-
* @returns {{fullFilePath: string
|
|
43
|
+
* @returns {{fullFilePath: string, resolvedPath: string, relativePath: string}} - Object containing the resolved full file path, resolved path (after alias resolution), and relative path
|
|
44
44
|
*/
|
|
45
45
|
function resolveFilePathFromMatch(matchedFileString, syntax, configPath) {
|
|
46
46
|
const relativePath = trimSurroundingQuotes(
|
|
@@ -36,6 +36,7 @@ function hasUnresolvedVars(str, variableSyntax) {
|
|
|
36
36
|
* @param {object} context.config - Original config object
|
|
37
37
|
* @param {string} context.configDir - Config file directory
|
|
38
38
|
* @param {RegExp} context.variableSyntax - Variable syntax regex
|
|
39
|
+
* @param {object} [context.options] - CLI options
|
|
39
40
|
* @returns {Promise<*>} Resolved value or undefined if can't pre-resolve
|
|
40
41
|
*/
|
|
41
42
|
async function preResolveSingle(varString, context) {
|
|
@@ -43,8 +43,8 @@ function endChar(str, char) {
|
|
|
43
43
|
/**
|
|
44
44
|
* Ensures a value (string or array of strings) has quotes around it
|
|
45
45
|
* @param {string|string[]} value - The value to quote
|
|
46
|
-
* @param {string} open - Opening quote character (default: '"')
|
|
47
|
-
* @param {string} close - Closing quote character (default: same as open)
|
|
46
|
+
* @param {string} [open] - Opening quote character (default: '"')
|
|
47
|
+
* @param {string} [close] - Closing quote character (default: same as open)
|
|
48
48
|
* @returns {string|string[]} The quoted value(s)
|
|
49
49
|
*/
|
|
50
50
|
function ensureQuote(value, open = '"', close) {
|
|
@@ -5,7 +5,7 @@ const { splitByComma } = require('./splitByComma')
|
|
|
5
5
|
* NOTE: This is a simpler version that delegates to splitByComma for consistency.
|
|
6
6
|
* For advanced use cases with bracket depth tracking and regex protection, use splitByComma directly.
|
|
7
7
|
* @param {string} str - String to split
|
|
8
|
-
* @param {string} splitter - Optional custom splitter (defaults to ',')
|
|
8
|
+
* @param {string} [splitter] - Optional custom splitter (defaults to ',')
|
|
9
9
|
* @returns {string[]} Array of split strings
|
|
10
10
|
*/
|
|
11
11
|
function splitCsv(str, splitter) {
|
package/src/utils/ui/logs.js
CHANGED
|
@@ -2,10 +2,10 @@ const { makeHeader, logHeader : logHeaderBox } = require('@davidwells/box-logger
|
|
|
2
2
|
|
|
3
3
|
function logHeader(message) {
|
|
4
4
|
logHeaderBox({
|
|
5
|
-
content: message,
|
|
6
|
-
|
|
7
|
-
minWidth: 80,
|
|
8
|
-
|
|
5
|
+
content: message,
|
|
6
|
+
borderRight: true,
|
|
7
|
+
minWidth: 80,
|
|
8
|
+
fontStyle: 'bold',
|
|
9
9
|
borderStyle: 'bold',
|
|
10
10
|
borderColor: 'cyanBright',
|
|
11
11
|
})
|
|
@@ -14,9 +14,9 @@ function isValidValue(val) {
|
|
|
14
14
|
* Check if variable resolved to valid value, log warning if not
|
|
15
15
|
* @param {string} variableString - The variable being resolved
|
|
16
16
|
* @param {*} valueToPopulate - The resolved value
|
|
17
|
-
* @param {object} options - Configuration options
|
|
18
|
-
* @param {object} options.patterns - Regex patterns for variable types
|
|
19
|
-
* @param {boolean} options.debug - Whether to log warnings
|
|
17
|
+
* @param {object} [options] - Configuration options
|
|
18
|
+
* @param {object} [options.patterns] - Regex patterns for variable types
|
|
19
|
+
* @param {boolean} [options.debug] - Whether to log warnings
|
|
20
20
|
* @returns {*} The valueToPopulate unchanged
|
|
21
21
|
*/
|
|
22
22
|
function warnIfNotFound(variableString, valueToPopulate, options = {}) {
|
|
@@ -338,10 +338,10 @@ function findNestedVariablesOld(input, regex, variablesKnownTypes, debug = false
|
|
|
338
338
|
|
|
339
339
|
// Replace the `__REPLACED_${iteration - 1}__` with the original match
|
|
340
340
|
matches = matches.map((match, index) => {
|
|
341
|
-
const indexOfReplaced = match.
|
|
341
|
+
const indexOfReplaced = match.fullMatch.match(/__REPLACED_(\d+)__/)
|
|
342
342
|
if (indexOfReplaced) {
|
|
343
343
|
const replacedIndex = parseInt(indexOfReplaced[1])
|
|
344
|
-
match.
|
|
344
|
+
match.fullMatch = match.fullMatch.replace(`__REPLACED_${replacedIndex}__`, matches[replacedIndex].variable)
|
|
345
345
|
match.variable = match.variable.replace(`__REPLACED_${replacedIndex}__`, matches[replacedIndex].variable)
|
|
346
346
|
}
|
|
347
347
|
return match
|
|
@@ -1,3 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract variable prefix/suffix from regex source
|
|
3
|
+
* @param {string} syntaxSource - The regex source string (e.g., '\\$\\{(...)\\}')
|
|
4
|
+
* @returns {{ prefix: string, suffix: string }} The unescaped prefix and suffix
|
|
5
|
+
*/
|
|
6
|
+
function extractVariableWrapper(syntaxSource) {
|
|
7
|
+
// Find first capturing group ( that's not escaped and not a special group (?:, (?=, etc.)
|
|
8
|
+
let openParen = -1
|
|
9
|
+
for (let i = 0; i < syntaxSource.length; i++) {
|
|
10
|
+
if (syntaxSource[i] === '(' && (i === 0 || syntaxSource[i - 1] !== '\\')) {
|
|
11
|
+
// Check if it's a special group like (?:, (?=, (?!, (?<
|
|
12
|
+
if (syntaxSource[i + 1] !== '?') {
|
|
13
|
+
openParen = i
|
|
14
|
+
break
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Find last ) that's not escaped
|
|
20
|
+
let closeParen = -1
|
|
21
|
+
for (let i = syntaxSource.length - 1; i >= 0; i--) {
|
|
22
|
+
if (syntaxSource[i] === ')' && (i === 0 || syntaxSource[i - 1] !== '\\')) {
|
|
23
|
+
closeParen = i
|
|
24
|
+
break
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let escapedPrefix = openParen > 0 ? syntaxSource.substring(0, openParen) : ''
|
|
29
|
+
const escapedSuffix = closeParen >= 0 ? syntaxSource.substring(closeParen + 1) : ''
|
|
30
|
+
|
|
31
|
+
// Strip any leading non-capturing groups like (?:...) from prefix
|
|
32
|
+
escapedPrefix = escapedPrefix.replace(/^\(\?:[^)]*\)/g, '')
|
|
33
|
+
|
|
34
|
+
// Unescape regex escapes: \$ -> $, \{ -> {, \[ -> [, etc.
|
|
35
|
+
const unescape = (s) => s.replace(/\\(.)/g, '$1')
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
prefix: unescape(escapedPrefix) || '${',
|
|
39
|
+
suffix: unescape(escapedSuffix) || '}'
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
1
43
|
/**
|
|
2
44
|
* Get fallback variable string
|
|
3
45
|
* @param {string[]} split - Array from split at comma
|
|
@@ -47,6 +89,7 @@ Remove or update the \${${variableString}} to fix
|
|
|
47
89
|
}
|
|
48
90
|
|
|
49
91
|
module.exports = {
|
|
92
|
+
extractVariableWrapper,
|
|
50
93
|
getFallbackString,
|
|
51
94
|
verifyVariable
|
|
52
95
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { test } = require('uvu')
|
|
2
2
|
const assert = require('uvu/assert')
|
|
3
|
-
const { getFallbackString, verifyVariable } = require('./variableUtils')
|
|
3
|
+
const { extractVariableWrapper, getFallbackString, verifyVariable } = require('./variableUtils')
|
|
4
4
|
|
|
5
5
|
// Tests for getFallbackString
|
|
6
6
|
test('getFallbackString - should reconstruct variable from split array', () => {
|
|
@@ -113,5 +113,42 @@ test('verifyVariable - should match with function and config param', () => {
|
|
|
113
113
|
assert.is(result, true)
|
|
114
114
|
})
|
|
115
115
|
|
|
116
|
+
// Tests for extractVariableWrapper
|
|
117
|
+
test('extractVariableWrapper - standard ${} syntax', () => {
|
|
118
|
+
const result = extractVariableWrapper('\\$\\{([^}]+)\\}')
|
|
119
|
+
assert.equal(result.prefix, '${')
|
|
120
|
+
assert.equal(result.suffix, '}')
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test('extractVariableWrapper - double brace ${{}} syntax', () => {
|
|
124
|
+
const result = extractVariableWrapper('\\$\\{\\{([^}]+)\\}\\}')
|
|
125
|
+
assert.equal(result.prefix, '${{')
|
|
126
|
+
assert.equal(result.suffix, '}}')
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
test('extractVariableWrapper - hash #{} syntax', () => {
|
|
130
|
+
const result = extractVariableWrapper('\\#\\{([^}]+)\\}')
|
|
131
|
+
assert.equal(result.prefix, '#{')
|
|
132
|
+
assert.equal(result.suffix, '}')
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
test('extractVariableWrapper - angle bracket <> syntax', () => {
|
|
136
|
+
const result = extractVariableWrapper('\\<([^>]+)\\>')
|
|
137
|
+
assert.equal(result.prefix, '<')
|
|
138
|
+
assert.equal(result.suffix, '>')
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
test('extractVariableWrapper - double bracket [[]] syntax', () => {
|
|
142
|
+
const result = extractVariableWrapper('\\[\\[([^\\]]+)\\]\\]')
|
|
143
|
+
assert.equal(result.prefix, '[[')
|
|
144
|
+
assert.equal(result.suffix, ']]')
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
test('extractVariableWrapper - strips non-capturing group prefix', () => {
|
|
148
|
+
const result = extractVariableWrapper('(?:prefix)\\$\\{([^}]+)\\}')
|
|
149
|
+
assert.equal(result.prefix, '${')
|
|
150
|
+
assert.equal(result.suffix, '}')
|
|
151
|
+
})
|
|
152
|
+
|
|
116
153
|
// Run all tests
|
|
117
154
|
test.run()
|
package/types/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"md5.d.ts","sourceRoot":"","sources":["../../../src/functions/md5.js"],"names":[],"mappings":"AAOiB,kCAHL,MAAM,GACN,MAAM,CAOjB"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
declare namespace _exports {
|
|
2
|
+
export { ConfigoramaSettings, ConfigoramaResult };
|
|
3
|
+
}
|
|
4
|
+
declare function _exports<T = any>(configPathOrObject: string | any, settings?: ConfigoramaSettings): Promise<T | ConfigoramaResult<T>>;
|
|
5
|
+
declare namespace _exports {
|
|
6
|
+
export { Configorama };
|
|
7
|
+
export function sync<T = any>(configPathOrObject: string | any, settings?: ConfigoramaSettings): T;
|
|
8
|
+
export function analyze(configPathOrObject: string | object, settings?: object): Promise<any>;
|
|
9
|
+
export { parsers as format };
|
|
10
|
+
}
|
|
11
|
+
export = _exports;
|
|
12
|
+
type ConfigoramaSettings = {
|
|
13
|
+
/**
|
|
14
|
+
* - options to populate for ${opt:xyz}. These could be CLI flags
|
|
15
|
+
*/
|
|
16
|
+
options?: {
|
|
17
|
+
[x: string]: any;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* - Regex of variable syntax
|
|
21
|
+
*/
|
|
22
|
+
syntax?: string;
|
|
23
|
+
/**
|
|
24
|
+
* - cwd of config. Needed if raw object passed in instead of file path
|
|
25
|
+
*/
|
|
26
|
+
configDir?: string;
|
|
27
|
+
/**
|
|
28
|
+
* - array of custom variable sources
|
|
29
|
+
*/
|
|
30
|
+
variableSources?: any[];
|
|
31
|
+
/**
|
|
32
|
+
* - Object of custom filters
|
|
33
|
+
*/
|
|
34
|
+
filters?: {
|
|
35
|
+
[x: string]: Function;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* - Object of custom functions
|
|
39
|
+
*/
|
|
40
|
+
functions?: {
|
|
41
|
+
[x: string]: Function;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* - allow unknown variables to pass through without throwing errors
|
|
45
|
+
*/
|
|
46
|
+
allowUnknownVars?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* - allow undefined values to pass through without throwing errors
|
|
49
|
+
*/
|
|
50
|
+
allowUndefinedValues?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* - values passed into .js config files if user using javascript config
|
|
53
|
+
*/
|
|
54
|
+
dynamicArgs?: any | Function;
|
|
55
|
+
/**
|
|
56
|
+
* - return both config and metadata about variables found
|
|
57
|
+
*/
|
|
58
|
+
returnMetadata?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* - keys to merge in arrays of objects
|
|
61
|
+
*/
|
|
62
|
+
mergeKeys?: string[];
|
|
63
|
+
/**
|
|
64
|
+
* - map of file paths to override
|
|
65
|
+
*/
|
|
66
|
+
filePathOverrides?: {
|
|
67
|
+
[x: string]: string;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
type ConfigoramaResult<T = any> = {
|
|
71
|
+
/**
|
|
72
|
+
* - The variable syntax pattern used
|
|
73
|
+
*/
|
|
74
|
+
variableSyntax: RegExp;
|
|
75
|
+
/**
|
|
76
|
+
* - Map of variable types found
|
|
77
|
+
*/
|
|
78
|
+
variableTypes: {
|
|
79
|
+
[x: string]: any;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* - The resolved configuration object
|
|
83
|
+
*/
|
|
84
|
+
config: T;
|
|
85
|
+
/**
|
|
86
|
+
* - The original unresolved configuration
|
|
87
|
+
*/
|
|
88
|
+
originalConfig: any;
|
|
89
|
+
/**
|
|
90
|
+
* - Metadata about variables found and resolved
|
|
91
|
+
*/
|
|
92
|
+
metadata: any;
|
|
93
|
+
/**
|
|
94
|
+
* - Resolution history per path for debugging
|
|
95
|
+
*/
|
|
96
|
+
resolutionHistory: any;
|
|
97
|
+
};
|
|
98
|
+
import Configorama = require("./main");
|
|
99
|
+
import parsers = require("./parsers");
|
|
100
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.js"],"names":[],"mappings":";;;AAwCiB,0BALH,CAAC,4BACJ,MAAM,MAAO,aACb,mBAAmB,GACjB,OAAO,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAiD7C;;;IASqB,qBALR,CAAC,4BACJ,MAAM,MAAO,aACb,mBAAmB,GACjB,CAAC,CAgBb;IAQwB,4CAJb,MAAM,GAAC,MAAM,aACd,MAAM,gBAUhB;;;;;;;;;;;;;;aApHa,MAAM;;;;gBACN,MAAM;;;;;;;;;;;;;;;;;;;;uBAIN,OAAO;;;;2BACP,OAAO;;;;kBACP,cAAe;;;;qBACf,OAAO;;;;gBACP,MAAM,EAAE;;;;;;;;uBAKR,CAAC;;;;oBAED,MAAM;;;;;;;;;;YAEN,CAAC"}
|