configorama 0.9.12 → 0.9.14
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 +2067 -392
- package/cli.js +47 -9
- package/index.d.ts +1 -0
- package/package.json +1 -17
- package/src/main.js +39 -27
- package/src/parsers/index.js +3 -1
- package/src/parsers/markdown.js +69 -0
- package/src/parsers/markdown.test.js +132 -0
- package/src/resolvers/valueFromEnv.js +3 -6
- package/src/resolvers/valueFromFile.js +4 -4
- package/src/resolvers/valueFromGit.js +128 -86
- package/src/resolvers/valueFromNumber.js +10 -1
- package/src/resolvers/valueFromOptions.js +3 -7
- package/src/resolvers/valueFromParam.js +2 -1
- package/src/types.d.ts +1 -1
- package/src/utils/handleSignalEvents.js +1 -5
- package/src/utils/lodash.js +91 -37
- package/src/utils/parsing/cloudformationSchema.js +5 -10
- package/src/utils/parsing/getValueAtPath.js +111 -0
- package/src/utils/parsing/getValueAtPath.test.js +152 -0
- package/src/utils/parsing/parse.js +22 -1
- package/src/utils/parsing/preProcess.js +16 -10
- package/src/utils/regex/index.js +6 -9
- package/src/utils/ui/configWizard.js +4 -4
- package/src/utils/validation/warnIfNotFound.js +5 -1
- package/src/utils/variables/cleanVariable.js +1 -24
- package/types/src/main.d.ts +2 -0
- package/types/src/main.d.ts.map +1 -1
- package/types/src/parsers/markdown.d.ts +17 -0
- package/types/src/parsers/markdown.d.ts.map +1 -0
- package/types/src/resolvers/valueFromEnv.d.ts +1 -1
- package/types/src/resolvers/valueFromEnv.d.ts.map +1 -1
- package/types/src/resolvers/valueFromGit.d.ts.map +1 -1
- package/types/src/resolvers/valueFromNumber.d.ts +10 -2
- package/types/src/resolvers/valueFromNumber.d.ts.map +1 -1
- package/types/src/resolvers/valueFromOptions.d.ts.map +1 -1
- package/types/src/resolvers/valueFromParam.d.ts.map +1 -1
- package/types/src/utils/handleSignalEvents.d.ts.map +1 -1
- package/types/src/utils/lodash.d.ts +50 -3
- package/types/src/utils/lodash.d.ts.map +1 -1
- package/types/src/utils/parsing/getValueAtPath.d.ts +18 -0
- package/types/src/utils/parsing/getValueAtPath.d.ts.map +1 -0
- package/types/src/utils/parsing/parse.d.ts.map +1 -1
- package/types/src/utils/parsing/preProcess.d.ts.map +1 -1
- package/types/src/utils/regex/index.d.ts +5 -6
- package/types/src/utils/regex/index.d.ts.map +1 -1
- package/types/src/utils/validation/warnIfNotFound.d.ts +4 -0
- package/types/src/utils/validation/warnIfNotFound.d.ts.map +1 -1
- package/types/src/utils/variables/cleanVariable.d.ts +1 -1
- package/types/src/utils/variables/cleanVariable.d.ts.map +1 -1
- package/src/resolvers/valueFromSelf.js +0 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/* Extract value from object/array using jq-style path syntax */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Parse a jq-style path string into an array of keys/indices
|
|
5
|
+
* @param {string} path - jq-style path like '.foo.bar[0]' or '.["key"]'
|
|
6
|
+
* @returns {(string|number)[]} Array of path segments
|
|
7
|
+
*/
|
|
8
|
+
function parsePath(path) {
|
|
9
|
+
if (!path || typeof path !== 'string') return []
|
|
10
|
+
|
|
11
|
+
path = path.trim()
|
|
12
|
+
|
|
13
|
+
// Handle identity or empty
|
|
14
|
+
if (path === '.' || path === '') return []
|
|
15
|
+
|
|
16
|
+
// Remove leading dot if present
|
|
17
|
+
if (path.startsWith('.')) {
|
|
18
|
+
path = path.slice(1)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const segments = []
|
|
22
|
+
let i = 0
|
|
23
|
+
|
|
24
|
+
while (i < path.length) {
|
|
25
|
+
// Skip leading dots (from chained access like .foo.bar)
|
|
26
|
+
if (path[i] === '.') {
|
|
27
|
+
i++
|
|
28
|
+
continue
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Bracket notation: [0], [-1], ["key"], ['key']
|
|
32
|
+
if (path[i] === '[') {
|
|
33
|
+
const closeIdx = path.indexOf(']', i)
|
|
34
|
+
if (closeIdx === -1) {
|
|
35
|
+
throw new Error(`Unclosed bracket in path: ${path}`)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let content = path.slice(i + 1, closeIdx)
|
|
39
|
+
|
|
40
|
+
// Check if it's a quoted string key
|
|
41
|
+
if ((content.startsWith('"') && content.endsWith('"')) ||
|
|
42
|
+
(content.startsWith("'") && content.endsWith("'"))) {
|
|
43
|
+
segments.push(content.slice(1, -1))
|
|
44
|
+
} else {
|
|
45
|
+
// It's a number index
|
|
46
|
+
const num = Number(content)
|
|
47
|
+
if (!Number.isInteger(num)) {
|
|
48
|
+
throw new Error(`Invalid array index: ${content}`)
|
|
49
|
+
}
|
|
50
|
+
segments.push(num)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
i = closeIdx + 1
|
|
54
|
+
continue
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Regular identifier: read until . or [ or end
|
|
58
|
+
let end = i
|
|
59
|
+
while (end < path.length && path[end] !== '.' && path[end] !== '[') {
|
|
60
|
+
end++
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (end > i) {
|
|
64
|
+
segments.push(path.slice(i, end))
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
i = end
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return segments
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get value from object/array at jq-style path
|
|
75
|
+
* @param {*} data - Object or array to extract from
|
|
76
|
+
* @param {string} path - jq-style path like '.foo.bar[0]'
|
|
77
|
+
* @returns {*} Value at path or undefined if not found
|
|
78
|
+
*/
|
|
79
|
+
function getValueAtPath(data, path) {
|
|
80
|
+
if (data === null || data === undefined) {
|
|
81
|
+
return undefined
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const segments = parsePath(path)
|
|
85
|
+
|
|
86
|
+
// Identity path returns input
|
|
87
|
+
if (segments.length === 0) {
|
|
88
|
+
return data
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let current = data
|
|
92
|
+
|
|
93
|
+
for (const segment of segments) {
|
|
94
|
+
if (current === null || current === undefined) {
|
|
95
|
+
return undefined
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Handle negative array indices
|
|
99
|
+
if (typeof segment === 'number' && segment < 0 && Array.isArray(current)) {
|
|
100
|
+
const idx = current.length + segment
|
|
101
|
+
current = current[idx]
|
|
102
|
+
} else {
|
|
103
|
+
current = current[segment]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return current
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
module.exports = getValueAtPath
|
|
111
|
+
module.exports.parsePath = parsePath
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/* Tests for jq-style path extraction from objects */
|
|
2
|
+
const { test } = require('uvu')
|
|
3
|
+
const assert = require('uvu/assert')
|
|
4
|
+
const getValueAtPath = require('./getValueAtPath')
|
|
5
|
+
|
|
6
|
+
// Basic object key access
|
|
7
|
+
test('getValueAtPath: .foo returns value at key', () => {
|
|
8
|
+
const obj = { foo: 42, bar: 'hello' }
|
|
9
|
+
assert.is(getValueAtPath(obj, '.foo'), 42)
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test('getValueAtPath: . returns entire object', () => {
|
|
13
|
+
const obj = { foo: 42 }
|
|
14
|
+
assert.equal(getValueAtPath(obj, '.'), obj)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
test('getValueAtPath: .foo.bar returns nested value', () => {
|
|
18
|
+
const obj = { foo: { bar: 'nested' } }
|
|
19
|
+
assert.is(getValueAtPath(obj, '.foo.bar'), 'nested')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
test('getValueAtPath: .foo.bar.baz returns deeply nested value', () => {
|
|
23
|
+
const obj = { foo: { bar: { baz: 123 } } }
|
|
24
|
+
assert.is(getValueAtPath(obj, '.foo.bar.baz'), 123)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
// Array index access
|
|
28
|
+
test('getValueAtPath: .[0] returns first array element', () => {
|
|
29
|
+
const arr = ['a', 'b', 'c']
|
|
30
|
+
assert.is(getValueAtPath(arr, '.[0]'), 'a')
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('getValueAtPath: .[2] returns third array element', () => {
|
|
34
|
+
const arr = ['a', 'b', 'c']
|
|
35
|
+
assert.is(getValueAtPath(arr, '.[2]'), 'c')
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('getValueAtPath: .[-1] returns last array element', () => {
|
|
39
|
+
const arr = ['a', 'b', 'c']
|
|
40
|
+
assert.is(getValueAtPath(arr, '.[-1]'), 'c')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('getValueAtPath: .[-2] returns second to last element', () => {
|
|
44
|
+
const arr = ['a', 'b', 'c']
|
|
45
|
+
assert.is(getValueAtPath(arr, '.[-2]'), 'b')
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
// Mixed object and array access
|
|
49
|
+
test('getValueAtPath: .foo[0] returns first element of array at key', () => {
|
|
50
|
+
const obj = { foo: [1, 2, 3] }
|
|
51
|
+
assert.is(getValueAtPath(obj, '.foo[0]'), 1)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('getValueAtPath: .foo[0].bar returns nested object in array', () => {
|
|
55
|
+
const obj = { foo: [{ bar: 'first' }, { bar: 'second' }] }
|
|
56
|
+
assert.is(getValueAtPath(obj, '.foo[0].bar'), 'first')
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test('getValueAtPath: .[0].name returns property of first array element', () => {
|
|
60
|
+
const arr = [{ name: 'JSON' }, { name: 'XML' }]
|
|
61
|
+
assert.is(getValueAtPath(arr, '.[0].name'), 'JSON')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test('getValueAtPath: complex nested path', () => {
|
|
65
|
+
const obj = {
|
|
66
|
+
users: [
|
|
67
|
+
{ name: 'Alice', addresses: [{ city: 'NYC' }] },
|
|
68
|
+
{ name: 'Bob', addresses: [{ city: 'LA' }, { city: 'SF' }] }
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
assert.is(getValueAtPath(obj, '.users[1].addresses[1].city'), 'SF')
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
// Bracket notation for object keys
|
|
75
|
+
test('getValueAtPath: .["foo"] returns value at key', () => {
|
|
76
|
+
const obj = { foo: 42 }
|
|
77
|
+
assert.is(getValueAtPath(obj, '.["foo"]'), 42)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
test('getValueAtPath: .["foo-bar"] returns value at hyphenated key', () => {
|
|
81
|
+
const obj = { 'foo-bar': 'works' }
|
|
82
|
+
assert.is(getValueAtPath(obj, '.["foo-bar"]'), 'works')
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test('getValueAtPath: .["foo.bar"] returns value at key with dot', () => {
|
|
86
|
+
const obj = { 'foo.bar': 'dotted' }
|
|
87
|
+
assert.is(getValueAtPath(obj, '.["foo.bar"]'), 'dotted')
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
// Edge cases
|
|
91
|
+
test('getValueAtPath: missing key returns undefined', () => {
|
|
92
|
+
const obj = { foo: 42 }
|
|
93
|
+
assert.is(getValueAtPath(obj, '.bar'), undefined)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
test('getValueAtPath: out of bounds array index returns undefined', () => {
|
|
97
|
+
const arr = ['a', 'b']
|
|
98
|
+
assert.is(getValueAtPath(arr, '.[10]'), undefined)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
test('getValueAtPath: path through null returns undefined', () => {
|
|
102
|
+
const obj = { foo: null }
|
|
103
|
+
assert.is(getValueAtPath(obj, '.foo.bar'), undefined)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
test('getValueAtPath: path through undefined returns undefined', () => {
|
|
107
|
+
const obj = {}
|
|
108
|
+
assert.is(getValueAtPath(obj, '.foo.bar'), undefined)
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
test('getValueAtPath: empty path returns input', () => {
|
|
112
|
+
const obj = { foo: 42 }
|
|
113
|
+
assert.equal(getValueAtPath(obj, ''), obj)
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test('getValueAtPath: null input returns undefined', () => {
|
|
117
|
+
assert.is(getValueAtPath(null, '.foo'), undefined)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
test('getValueAtPath: without leading dot still works', () => {
|
|
121
|
+
const obj = { foo: { bar: 42 } }
|
|
122
|
+
assert.is(getValueAtPath(obj, 'foo.bar'), 42)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
// Whitespace handling
|
|
126
|
+
test('getValueAtPath: handles whitespace in path', () => {
|
|
127
|
+
const obj = { foo: 42 }
|
|
128
|
+
assert.is(getValueAtPath(obj, ' .foo '), 42)
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
// Error handling for malformed input
|
|
132
|
+
test('getValueAtPath: throws on malformed array index with trailing characters', () => {
|
|
133
|
+
const arr = ['a', 'b', 'c']
|
|
134
|
+
assert.throws(() => getValueAtPath(arr, '.[42abc]'), /Invalid array index/)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
test('getValueAtPath: throws on malformed array index with leading characters', () => {
|
|
138
|
+
const arr = ['a', 'b', 'c']
|
|
139
|
+
assert.throws(() => getValueAtPath(arr, '.[abc42]'), /Invalid array index/)
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
test('getValueAtPath: throws on non-numeric array index', () => {
|
|
143
|
+
const arr = ['a', 'b', 'c']
|
|
144
|
+
assert.throws(() => getValueAtPath(arr, '.[abc]'), /Invalid array index/)
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
test('getValueAtPath: throws on decimal array index', () => {
|
|
148
|
+
const arr = ['a', 'b', 'c']
|
|
149
|
+
assert.throws(() => getValueAtPath(arr, '.[1.5]'), /Invalid array index/)
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
test.run()
|
|
@@ -66,6 +66,27 @@ function parseFileContents({ contents, filePath, varRegex, dynamicArgs }) {
|
|
|
66
66
|
// .tf and .hcl files need HCL parsing
|
|
67
67
|
configObject = HCL.parse(contents, path.basename(filePath))
|
|
68
68
|
}
|
|
69
|
+
} else if (fileType.match(/\.(md|mdx|markdown|mdown|mkdn|mkd|mdwn|markdn|mdtxt|mdtext)/i)) {
|
|
70
|
+
const { extractFrontmatter } = require('../../parsers/markdown')
|
|
71
|
+
const { frontmatterContent, content, format } = extractFrontmatter(contents)
|
|
72
|
+
|
|
73
|
+
if (!frontmatterContent) {
|
|
74
|
+
configObject = {}
|
|
75
|
+
} else if (format === 'toml') {
|
|
76
|
+
configObject = TOML.parse(frontmatterContent)
|
|
77
|
+
} else if (format === 'json') {
|
|
78
|
+
configObject = JSON5.parse(frontmatterContent)
|
|
79
|
+
} else {
|
|
80
|
+
const ymlText = YAML.preProcess(frontmatterContent)
|
|
81
|
+
configObject = YAML.parse(ymlText)
|
|
82
|
+
}
|
|
83
|
+
const bodyContent = content.replace(/^\n+|\n+$/g, '')
|
|
84
|
+
if (configObject.hasOwnProperty('_content')) {
|
|
85
|
+
console.warn('configorama: frontmatter key "_content" conflicts with reserved body content key. Body stored as "_body" instead.')
|
|
86
|
+
configObject._body = bodyContent
|
|
87
|
+
} else {
|
|
88
|
+
configObject._content = bodyContent
|
|
89
|
+
}
|
|
69
90
|
// TODO detect js syntax and use appropriate parser
|
|
70
91
|
} else if (fileType.match(/\.(js|cjs)/i)) {
|
|
71
92
|
let jsFile
|
|
@@ -82,7 +103,7 @@ function parseFileContents({ contents, filePath, varRegex, dynamicArgs }) {
|
|
|
82
103
|
configObject = jsFile(jsArgs)
|
|
83
104
|
}
|
|
84
105
|
} catch (err) {
|
|
85
|
-
throw
|
|
106
|
+
throw err
|
|
86
107
|
}
|
|
87
108
|
} else if (fileType.match(/\.(ts|tsx|mts|cts)/i)) {
|
|
88
109
|
try {
|
|
@@ -145,6 +145,11 @@ function preProcess(configObject, variableSyntax, variableTypes, options = {}) {
|
|
|
145
145
|
|
|
146
146
|
// Comparison operators for detecting string comparison context
|
|
147
147
|
const comparisonOps = ['===', '!==', '==', '!=']
|
|
148
|
+
// Pre-compile "preceded by string+op" patterns to avoid regex compilation per bare ref
|
|
149
|
+
const precededByPatterns = comparisonOps.map(op => {
|
|
150
|
+
const escaped = op.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
151
|
+
return new RegExp(`["'][^"']*["']\\s*${escaped}\\s*$`)
|
|
152
|
+
})
|
|
148
153
|
|
|
149
154
|
// Find and replace bare refs, skipping those inside ${...} or quoted strings
|
|
150
155
|
// Only quote bare refs that are in string comparison context
|
|
@@ -171,18 +176,14 @@ function preProcess(configObject, variableSyntax, variableTypes, options = {}) {
|
|
|
171
176
|
const afterRef = fullContent.substring(matchEnd).trimStart()
|
|
172
177
|
const beforeRef = fullContent.substring(0, matchStart).trimEnd()
|
|
173
178
|
|
|
174
|
-
const isComparedToString = comparisonOps.some(op => {
|
|
179
|
+
const isComparedToString = comparisonOps.some((op, idx) => {
|
|
175
180
|
// Check if followed by: op "string"
|
|
176
181
|
if (afterRef.startsWith(op)) {
|
|
177
182
|
const afterOp = afterRef.substring(op.length).trimStart()
|
|
178
183
|
return afterOp.startsWith('"') || afterOp.startsWith("'")
|
|
179
184
|
}
|
|
180
185
|
// Check if preceded by: "string" op
|
|
181
|
-
|
|
182
|
-
const pattern = new RegExp(`["'][^"']*["']\\s*${o.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*$`)
|
|
183
|
-
if (pattern.test(beforeRef)) return true
|
|
184
|
-
}
|
|
185
|
-
return false
|
|
186
|
+
return precededByPatterns.some(p => p.test(beforeRef))
|
|
186
187
|
})
|
|
187
188
|
|
|
188
189
|
// Replace with var ref - quoted if string comparison, unquoted otherwise
|
|
@@ -367,11 +368,16 @@ function preProcess(configObject, variableSyntax, variableTypes, options = {}) {
|
|
|
367
368
|
*/
|
|
368
369
|
function traverseAndFix(obj) {
|
|
369
370
|
if (typeof obj === 'string') {
|
|
370
|
-
//
|
|
371
|
-
const
|
|
372
|
-
const
|
|
371
|
+
// Early exits: skip expensive processing when patterns are absent
|
|
372
|
+
const hasHelp = obj.indexOf('help(') !== -1
|
|
373
|
+
const hasEvalOrIf = obj.indexOf('if(') !== -1 || obj.indexOf('eval(') !== -1
|
|
374
|
+
const hasComma = obj.indexOf(',') !== -1
|
|
375
|
+
|
|
376
|
+
const withHelpEscaped = hasHelp ? escapeHelpVariables(obj) : obj
|
|
377
|
+
const withBareRefsConverted = hasEvalOrIf ? convertBareRefsInIf(withHelpEscaped) : withHelpEscaped
|
|
373
378
|
// Skip fallback fixing for object configs (they handle bare refs differently)
|
|
374
|
-
|
|
379
|
+
if (skipFallbackFix || !hasComma) return withBareRefsConverted
|
|
380
|
+
return fixFallbacksInString(withBareRefsConverted)
|
|
375
381
|
}
|
|
376
382
|
|
|
377
383
|
if (Array.isArray(obj)) {
|
package/src/utils/regex/index.js
CHANGED
|
@@ -2,11 +2,6 @@
|
|
|
2
2
|
* Shared regex patterns and utilities
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
// Legacy regex patterns (can't handle nested parentheses properly)
|
|
6
|
-
const funcRegexSimple = /(\w+)\s*\(((?:[^()]+)*)?\s*\)\s*/
|
|
7
|
-
const funcStartOfLineRegex = /^(\w+)\s*\(((?:[^()]+)*)?\s*\)\s*/
|
|
8
|
-
const subFunctionRegex = /(\w+):(\w+)\s*\(((?:[^()]+)*)?\s*\)\s*/
|
|
9
|
-
|
|
10
5
|
/**
|
|
11
6
|
* Parse a function call with balanced parentheses support
|
|
12
7
|
* Returns a regex-exec-like array: [fullMatch, funcName, args] with index and input properties
|
|
@@ -93,13 +88,15 @@ function combineRegexes(regexes) {
|
|
|
93
88
|
return new RegExp(`(${patterns.join('|')})`)
|
|
94
89
|
}
|
|
95
90
|
|
|
91
|
+
const fileRefSyntax = /^file\((~?[@\{\}\:\$a-zA-Z0-9._\-\/\\%,'" =+]+?)\)/g
|
|
92
|
+
const textRefSyntax = /^text\((~?[@\{\}\:\$a-zA-Z0-9._\-\/\\%,'" =+]+?)\)/g
|
|
93
|
+
|
|
96
94
|
module.exports = {
|
|
97
95
|
funcRegex,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
subFunctionRegex,
|
|
96
|
+
fileRefSyntax,
|
|
97
|
+
textRefSyntax,
|
|
101
98
|
combineRegexes,
|
|
102
99
|
parseFunctionCall,
|
|
103
|
-
//
|
|
100
|
+
// Alias used by valueFromGit
|
|
104
101
|
functionRegex: funcRegex
|
|
105
102
|
}
|
|
@@ -541,7 +541,7 @@ async function runConfigWizard(metadata, originalConfig = {}, configFilePath = '
|
|
|
541
541
|
|
|
542
542
|
if (p.isCancel(value)) {
|
|
543
543
|
p.cancel('Setup cancelled')
|
|
544
|
-
|
|
544
|
+
throw new Error('Setup cancelled')
|
|
545
545
|
}
|
|
546
546
|
|
|
547
547
|
userInputs.options[varInfo.cleanName] = value || varInfo.defaultValue
|
|
@@ -595,7 +595,7 @@ async function runConfigWizard(metadata, originalConfig = {}, configFilePath = '
|
|
|
595
595
|
|
|
596
596
|
if (p.isCancel(value)) {
|
|
597
597
|
p.cancel('Setup cancelled')
|
|
598
|
-
|
|
598
|
+
throw new Error('Setup cancelled')
|
|
599
599
|
}
|
|
600
600
|
|
|
601
601
|
userInputs.env[varInfo.cleanName] = value || varInfo.resolvedValue || varInfo.defaultValue
|
|
@@ -637,7 +637,7 @@ async function runConfigWizard(metadata, originalConfig = {}, configFilePath = '
|
|
|
637
637
|
|
|
638
638
|
if (p.isCancel(value)) {
|
|
639
639
|
p.cancel('Setup cancelled')
|
|
640
|
-
|
|
640
|
+
throw new Error('Setup cancelled')
|
|
641
641
|
}
|
|
642
642
|
|
|
643
643
|
userInputs.self[varInfo.cleanName] = value || varInfo.defaultValue
|
|
@@ -679,7 +679,7 @@ async function runConfigWizard(metadata, originalConfig = {}, configFilePath = '
|
|
|
679
679
|
|
|
680
680
|
if (p.isCancel(value)) {
|
|
681
681
|
p.cancel('Setup cancelled')
|
|
682
|
-
|
|
682
|
+
throw new Error('Setup cancelled')
|
|
683
683
|
}
|
|
684
684
|
|
|
685
685
|
userInputs.dotProp[varInfo.cleanName] = value || varInfo.defaultValue
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Warns if a variable value is not found during resolution
|
|
3
3
|
*/
|
|
4
|
-
const isEmpty = require('lodash
|
|
4
|
+
const { isEmpty } = require('../lodash')
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @param {*} val
|
|
8
|
+
* @returns {boolean}
|
|
9
|
+
*/
|
|
6
10
|
function isValidValue(val) {
|
|
7
11
|
if (val !== null && typeof val === 'object' && (val.hasOwnProperty('__internal_only_flag') || val.hasOwnProperty('__internal_metadata'))) {
|
|
8
12
|
return false
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { findNestedVariables } = require('./findNestedVariables')
|
|
2
|
-
const { functionRegex } = require('../regex')
|
|
2
|
+
const { functionRegex, fileRefSyntax } = require('../regex')
|
|
3
3
|
|
|
4
4
|
const DEBUG = false
|
|
5
5
|
/**
|
|
@@ -8,8 +8,6 @@ const DEBUG = false
|
|
|
8
8
|
* @param match The variable match instance variable part
|
|
9
9
|
* @returns {string} The cleaned variable match
|
|
10
10
|
*/
|
|
11
|
-
|
|
12
|
-
const fileRefSyntax = RegExp(/^file\((~?[a-zA-Z0-9._\-\/,'" ]+?)\)/g)
|
|
13
11
|
module.exports = function cleanVariable(
|
|
14
12
|
match,
|
|
15
13
|
variableSyntax,
|
|
@@ -60,27 +58,6 @@ module.exports = function cleanVariable(
|
|
|
60
58
|
console.log(`Clean output [${caller}]`, clean)
|
|
61
59
|
}
|
|
62
60
|
return clean
|
|
63
|
-
|
|
64
|
-
// Support for simple variable cleaning with no space tweaks
|
|
65
|
-
if (simple) {
|
|
66
|
-
return clean
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Support for function matches that dont need space alterations
|
|
70
|
-
if (!clean.match(fileRefSyntax) && functionRegex.exec(clean)) {
|
|
71
|
-
return clean
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// If file ref, add spaces after commas
|
|
75
|
-
// Special case for file(thing, arg, argTwo)
|
|
76
|
-
if (clean.match(fileRefSyntax)) {
|
|
77
|
-
// replace spaces before and after commas
|
|
78
|
-
return clean.replace(/\s*,\s*/g, ', ')
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return clean.replace(/\s+(?=([^"']*"[^"']*")*[^"']*$)/g, '')
|
|
82
|
-
// ^ trim White Space OutSide Quotes https://regex101.com/r/BuBNPN/1
|
|
83
|
-
// Needed for fallback values with spaces. ${empty, 'fallback value with space'}
|
|
84
61
|
}
|
|
85
62
|
|
|
86
63
|
|
package/types/src/main.d.ts
CHANGED
|
@@ -57,6 +57,8 @@ declare class Configorama {
|
|
|
57
57
|
init(cliOpts: any): Promise<any>;
|
|
58
58
|
options: any;
|
|
59
59
|
configFileContents: string;
|
|
60
|
+
_markdownContent: any;
|
|
61
|
+
_markdownContentKey: string;
|
|
60
62
|
/**
|
|
61
63
|
* Collect metadata about all variables found in the configuration
|
|
62
64
|
* @returns {object} Metadata object containing variables, fileRefs, and summary
|
package/types/src/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/main.js"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/main.js"],"names":[],"mappings":";AA0GA;IACE,0CA2dC;IAndC,cAcW;IAuBX,gBAAqB;IAErB,mCAAoC;IAEpC,sBAAwB;IACxB,qBAAuB;IAGvB,uBAA4B;IAsB5B,uBAAoC;IAIpC,kBAAqC;IACrC,kBAAqC;IAErC,yBAA+F;IAC/F,yBAAuD;IACvD,kCAAyE;IAKvE,uBAAgD;IAKhD,YAAuB;IAEvB,oBAA0C;IAE1C,gBAAoD;IAOpD,uBAAkC;IAElC,uBAA8B;IAE9B,uBAAkC;IASpC,wBAAmC;IAGnC,mBAqHC;IAwED,4BAA8C;IAG9C,iCAAkC;IAalC,aA2EC;IAUD,oBAEC;IAGD,eAiDC;IAOD,YAAc;IACd,cAAgB;IAChB,kBAAkB;IAGpB;;;;OAIG;IACH,0BAHW,MAAM,GACJ,OAAO,CAQnB;IAED;;;;OAIG;IACH,6BAHW,MAAM,GACJ,MAAM,GAAC,IAAI,CAOvB;IAED;;;;OAIG;IACH,gCAHW,MAAM,GACJ,OAAO,CA2BnB;IAKD;;;;;OAKG;IACH,oBAFa,OAAO,CAAC,GAAG,CAAC,CA6vBxB;IA1vBC,aAA4B;IAc1B,2BAA4B;IAmB1B,sBAA0C;IAC1C,4BAAkC;IA0tBxC;;;OAGG;IACH,2BAFa,MAAM,CA6alB;IAvBC;;;;;;;;;;;;;;;MAoBC;IAIH;;;;OAIG;IACH,uCAFa,OAAO,CAAC,GAAG,CAAC,CAIxB;IACD,+CAsBC;IAKD;;;;;;;;;;;;;;;;;;;OAmBG;IACH;;;;;;;;;;;OAWG;IACH,mFAHa;;;;cAZC,QAAQ;;;;eACR,IAAI,GAAC,MAAM,SAAO;OAWD,CA6E9B;IACD;;;OAGG;IACH;;;;;OAKG;IACH,oCAHa,OAAO,CAAC;;;;cAjGP,QAAQ;;;;eACR,IAAI,GAAC,MAAM,SAAO;OAgGgB,CAAC,EAAE,CA6BlD;IACD;;;;;OAKG;IACH,iDAFa,OAAO,CAAC,IAAI,CAAC,CAWzB;IAID;;;;;OAKG;IACH;;;;OAIG;IACH,2BAFa,eAAc;;;;;;;;;;OAAa,CAavC;IACD;;;;;OAKG;IACH,yBAHW;;;;;;;;;;OAAa,gCACX,cAAS,CAOrB;IACD;;;;;;OAMG;IACH,6DAFa,GAAC,CAiLb;IAKD;;;;;;;OAOG;IACH,yDAHa,OAAO,CAAC,GAAG,CAAC,CAiCxB;IACD;;;;OAIG;IAOH;;;;;;OAMG;IACH,wFA2BC;IACD;;;;;;;;;;;OAWG;IACH,8BARG;QAAyB,KAAK,EAAtB,GAAG;QACoB,IAAI,GAA3B,MAAM,EAAE;QACa,cAAc,GAAnC,MAAM;QACc,iBAAiB;KAC7C,6CAEU;QAAC,KAAK,EAAE,GAAG,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,iBAAiB,CAAC,QAAQ;QAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAC,CAsa9J;IAID;;;;;;;;OAQG;IACH,qEAHa,OAAO,CAAC,GAAG,CAAC,CAoExB;IAKD;;;;;;;OAOG;IACH,0FAFa,OAAO,CAAC,GAAG,CAAC,CAiiBxB;IACD,+EA+BC;IACD,yDAiBC;IACD,oEA6BC;IAKD,8CAQC;IACD,kDAyBC;IACD;;;;;;;;;;;;;OAaG;IACH,wEAoDC;IAKD,4BAOC;IACD,sCAqEC;CACF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract frontmatter and body content from a markdown file
|
|
3
|
+
* @param {string} fileContents - Full file contents
|
|
4
|
+
* @returns {{ frontmatterContent: string|null, content: string, format: 'yaml'|'toml'|'json'|null }}
|
|
5
|
+
*/
|
|
6
|
+
export function extractFrontmatter(fileContents: string): {
|
|
7
|
+
frontmatterContent: string | null;
|
|
8
|
+
content: string;
|
|
9
|
+
format: "yaml" | "toml" | "json" | null;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Detect frontmatter syntax format from raw content
|
|
13
|
+
* @param {string} rawFrontmatter - Raw frontmatter string (without delimiters)
|
|
14
|
+
* @returns {'yaml'|'toml'|'json'} Detected format
|
|
15
|
+
*/
|
|
16
|
+
export function detectSyntax(rawFrontmatter: string): "yaml" | "toml" | "json";
|
|
17
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../src/parsers/markdown.js"],"names":[],"mappings":"AAkBA;;;;GAIG;AACH,iDAHW,MAAM,GACJ;IAAE,kBAAkB,EAAE,MAAM,GAAC,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,GAAC,MAAM,GAAC,MAAM,GAAC,IAAI,CAAA;CAAE,CA0CnG;AA7DD;;;;GAIG;AACH,6CAHW,MAAM,GACJ,MAAM,GAAC,MAAM,GAAC,MAAM,CAWhC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
declare const envRefSyntax: RegExp;
|
|
2
|
-
declare function getValueFromEnv(variableString: any): Promise<string
|
|
2
|
+
declare function getValueFromEnv(variableString: any): Promise<string>;
|
|
3
3
|
export declare let type: string;
|
|
4
4
|
export declare let source: string;
|
|
5
5
|
export declare let syntax: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"valueFromEnv.d.ts","sourceRoot":"","sources":["../../../src/resolvers/valueFromEnv.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"valueFromEnv.d.ts","sourceRoot":"","sources":["../../../src/resolvers/valueFromEnv.js"],"names":[],"mappings":"AAGA,mCAAqC;AAErC,uEAcC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"valueFromGit.d.ts","sourceRoot":"","sources":["../../../src/resolvers/valueFromGit.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"valueFromGit.d.ts","sourceRoot":"","sources":["../../../src/resolvers/valueFromGit.js"],"names":[],"mappings":"AA2XiB;;;;;;;;EAUhB"}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @param {string} variableString
|
|
3
|
+
* @returns {boolean}
|
|
4
|
+
*/
|
|
5
|
+
declare function isNumberVariable(variableString: string): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* @param {string} variableString
|
|
8
|
+
* @returns {Promise<number>}
|
|
9
|
+
*/
|
|
10
|
+
declare function getValueFromNumber(variableString: string): Promise<number>;
|
|
3
11
|
export declare let type: string;
|
|
4
12
|
export declare let internal: boolean;
|
|
5
13
|
export { isNumberVariable as match, getValueFromNumber as resolver };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"valueFromNumber.d.ts","sourceRoot":"","sources":["../../../src/resolvers/valueFromNumber.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"valueFromNumber.d.ts","sourceRoot":"","sources":["../../../src/resolvers/valueFromNumber.js"],"names":[],"mappings":"AAGA;;;GAGG;AACH,kDAHW,MAAM,GACJ,OAAO,CAQnB;AAED;;;GAGG;AACH,oDAHW,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAI3B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"valueFromOptions.d.ts","sourceRoot":"","sources":["../../../src/resolvers/valueFromOptions.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"valueFromOptions.d.ts","sourceRoot":"","sources":["../../../src/resolvers/valueFromOptions.js"],"names":[],"mappings":"AAEA,mCAAqC;AAErC,sFAIC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"valueFromParam.d.ts","sourceRoot":"","sources":["../../../src/resolvers/valueFromParam.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"valueFromParam.d.ts","sourceRoot":"","sources":["../../../src/resolvers/valueFromParam.js"],"names":[],"mappings":"AAEA,qCAAyC;AAEzC;;;;;;;;;;GAUG;AACH,mDALW,MAAM,gCAGJ,OAAO,CAAC,GAAG,CAAC,CAqExB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handleSignalEvents.d.ts","sourceRoot":"","sources":["../../../src/utils/handleSignalEvents.js"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"handleSignalEvents.d.ts","sourceRoot":"","sources":["../../../src/utils/handleSignalEvents.js"],"names":[],"mappings":";AAGA,4CAgDC"}
|
|
@@ -1,4 +1,51 @@
|
|
|
1
|
-
export
|
|
2
|
-
export function
|
|
3
|
-
export
|
|
1
|
+
export const isArray: (arg: any) => arg is any[];
|
|
2
|
+
export function isString(val: any): val is string;
|
|
3
|
+
export function isNumber(val: any): boolean;
|
|
4
|
+
export function isObject(val: any): boolean;
|
|
5
|
+
export function isDate(val: any): val is Date;
|
|
6
|
+
export function isRegExp(val: any): val is RegExp;
|
|
7
|
+
export function isFunction(val: any): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* @param {*} val
|
|
10
|
+
* @returns {boolean}
|
|
11
|
+
*/
|
|
12
|
+
export function isEmpty(val: any): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* @param {string} string - String to trim
|
|
15
|
+
* @param {string} [chars] - Characters to trim (defaults to whitespace)
|
|
16
|
+
* @returns {string}
|
|
17
|
+
*/
|
|
18
|
+
export function trim(string: string, chars?: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} str
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*/
|
|
23
|
+
export function capitalize(str: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* @param {*[]} arr
|
|
26
|
+
* @param {Function} fn
|
|
27
|
+
* @returns {*[]}
|
|
28
|
+
*/
|
|
29
|
+
export function map(arr: any[], fn: Function): any[];
|
|
30
|
+
/**
|
|
31
|
+
* @param {Object} obj
|
|
32
|
+
* @param {Function} fn
|
|
33
|
+
* @returns {Object}
|
|
34
|
+
*/
|
|
35
|
+
export function mapValues(obj: any, fn: Function): any;
|
|
36
|
+
/**
|
|
37
|
+
* @param {Object} object - Target object
|
|
38
|
+
* @param {string|string[]} path - Dot-delimited path or array of keys
|
|
39
|
+
* @param {*} value - Value to set
|
|
40
|
+
* @returns {Object} The mutated object
|
|
41
|
+
*/
|
|
42
|
+
export function set(object: any, path: string | string[], value: any): any;
|
|
43
|
+
export declare function split(str: any, sep: any): string[];
|
|
44
|
+
export declare let assign: {
|
|
45
|
+
<T extends {}, U>(target: T, source: U): T & U;
|
|
46
|
+
<T extends {}, U, V>(target: T, source1: U, source2: V): T & U & V;
|
|
47
|
+
<T extends {}, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W;
|
|
48
|
+
(target: object, ...sources: any[]): any;
|
|
49
|
+
};
|
|
50
|
+
export { camelCase, kebabCase, cloneDeep };
|
|
4
51
|
//# sourceMappingURL=lodash.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lodash.d.ts","sourceRoot":"","sources":["../../../src/utils/lodash.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lodash.d.ts","sourceRoot":"","sources":["../../../src/utils/lodash.js"],"names":[],"mappings":"AACA,iDAA6B;AAC7B,kDAAiD;AACjD,4CAAgE;AAChE,4CAAgE;AAChE,8CAA2C;AAC3C,kDAA+C;AAC/C,8CAAqD;AAErD;;;GAGG;AACH,6BAHW,GAAC,GACC,OAAO,CAQnB;AAmFD;;;;GAIG;AACH,6BAJW,MAAM,UACN,MAAM,GACJ,MAAM,CA8BlB;AA7GD;;;GAGG;AACH,gCAHW,MAAM,GACJ,MAAM,CAMlB;AAED;;;;GAIG;AACH,yBAJW,GAAC,EAAE,iBAED,GAAC,EAAE,CAKf;AAED;;;;GAIG;AACH,uDAQC;AAED;;;;;GAKG;AACH,uCAJW,MAAM,GAAC,MAAM,EAAE,SACf,GAAC,OAiCX;AAqDQ,4DAAoC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export = getValueAtPath;
|
|
2
|
+
/**
|
|
3
|
+
* Get value from object/array at jq-style path
|
|
4
|
+
* @param {*} data - Object or array to extract from
|
|
5
|
+
* @param {string} path - jq-style path like '.foo.bar[0]'
|
|
6
|
+
* @returns {*} Value at path or undefined if not found
|
|
7
|
+
*/
|
|
8
|
+
declare function getValueAtPath(data: any, path: string): any;
|
|
9
|
+
declare namespace getValueAtPath {
|
|
10
|
+
export { parsePath };
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Parse a jq-style path string into an array of keys/indices
|
|
14
|
+
* @param {string} path - jq-style path like '.foo.bar[0]' or '.["key"]'
|
|
15
|
+
* @returns {(string|number)[]} Array of path segments
|
|
16
|
+
*/
|
|
17
|
+
declare function parsePath(path: string): (string | number)[];
|
|
18
|
+
//# sourceMappingURL=getValueAtPath.d.ts.map
|