configorama 0.6.19 → 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 +72 -51
- 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/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/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
|
@@ -7,7 +7,7 @@ const { splitCsv } = require('../utils/strings/splitCsv')
|
|
|
7
7
|
const { resolveFilePathFromMatch, resolveFilePath } = require('../utils/paths/getFullFilePath')
|
|
8
8
|
const { findNestedVariables } = require('../utils/variables/findNestedVariables')
|
|
9
9
|
const { makeBox } = require('@davidwells/box-logger')
|
|
10
|
-
const { encodeJsSyntax } = require('../utils/encoders/js-fixes')
|
|
10
|
+
const { encodeJsSyntax, decodeJsonInVariable, hasEncodedJson } = require('../utils/encoders/js-fixes')
|
|
11
11
|
|
|
12
12
|
/* File Parsers */
|
|
13
13
|
const YAML = require('../parsers/yaml')
|
|
@@ -15,6 +15,29 @@ const TOML = require('../parsers/toml')
|
|
|
15
15
|
const INI = require('../parsers/ini')
|
|
16
16
|
const JSON5 = require('../parsers/json5')
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Recursively clean encoded JSON from an object
|
|
20
|
+
* @param {*} obj - Object to clean
|
|
21
|
+
* @returns {*} Cleaned object
|
|
22
|
+
*/
|
|
23
|
+
function cleanEncodedJson(obj) {
|
|
24
|
+
if (!obj) return obj
|
|
25
|
+
if (typeof obj === 'string') {
|
|
26
|
+
return decodeJsonInVariable(obj)
|
|
27
|
+
}
|
|
28
|
+
if (Array.isArray(obj)) {
|
|
29
|
+
return obj.map(cleanEncodedJson)
|
|
30
|
+
}
|
|
31
|
+
if (typeof obj === 'object') {
|
|
32
|
+
const cleaned = {}
|
|
33
|
+
for (const key of Object.keys(obj)) {
|
|
34
|
+
cleaned[key] = cleanEncodedJson(obj[key])
|
|
35
|
+
}
|
|
36
|
+
return cleaned
|
|
37
|
+
}
|
|
38
|
+
return obj
|
|
39
|
+
}
|
|
40
|
+
|
|
18
41
|
/**
|
|
19
42
|
* Parse file contents based on file extension
|
|
20
43
|
* @param {string} content - Raw file contents
|
|
@@ -86,6 +109,17 @@ async function getValueFromFile(ctx, variableString, options) {
|
|
|
86
109
|
matchedFileString = argsFound[0]
|
|
87
110
|
argsToPass = argsFound.filter((arg, i) => {
|
|
88
111
|
return i !== 0
|
|
112
|
+
}).map((arg) => {
|
|
113
|
+
// Decode base64-encoded JSON objects passed as args
|
|
114
|
+
if (hasEncodedJson(arg)) {
|
|
115
|
+
const decoded = decodeJsonInVariable(arg)
|
|
116
|
+
try {
|
|
117
|
+
return JSON.parse(decoded)
|
|
118
|
+
} catch (e) {
|
|
119
|
+
return decoded
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return arg
|
|
89
123
|
})
|
|
90
124
|
}
|
|
91
125
|
}
|
|
@@ -137,9 +171,8 @@ async function getValueFromFile(ctx, variableString, options) {
|
|
|
137
171
|
|
|
138
172
|
ctx.fileRefsFound.push(fileRefEntry)
|
|
139
173
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
fileExtension = fileExtension[fileExtension.length - 1].toLowerCase()
|
|
174
|
+
const fileExtParts = resolvedPath.split('.')
|
|
175
|
+
const fileExtension = fileExtParts[fileExtParts.length - 1].toLowerCase()
|
|
143
176
|
|
|
144
177
|
// Validate file exists
|
|
145
178
|
if (!exists) {
|
|
@@ -168,14 +201,14 @@ async function getValueFromFile(ctx, variableString, options) {
|
|
|
168
201
|
const errorMsg = makeBox({
|
|
169
202
|
title: `File Not Found in ${originalVar}`,
|
|
170
203
|
minWidth: '100%',
|
|
171
|
-
|
|
204
|
+
content: `Variable ${variableString} cannot resolve due to missing file.
|
|
172
205
|
|
|
173
206
|
File not found ${fullFilePath}
|
|
174
207
|
|
|
175
208
|
Default fallback value will be used if provided.
|
|
176
209
|
|
|
177
210
|
${JSON.stringify(options.context, null, 2)}`,
|
|
178
|
-
|
|
211
|
+
})
|
|
179
212
|
console.log(errorMsg)
|
|
180
213
|
}
|
|
181
214
|
// TODO maybe reject. YAML does not allow for null/undefined values
|
|
@@ -197,11 +230,17 @@ ${JSON.stringify(options.context, null, 2)}`,
|
|
|
197
230
|
return Promise.resolve(valueToPopulate)
|
|
198
231
|
}
|
|
199
232
|
|
|
233
|
+
// Clean encoded JSON from currentConfig for cleaner context
|
|
234
|
+
const cleanedCurrentConfig = cleanEncodedJson(ctx.config)
|
|
235
|
+
|
|
200
236
|
// Build context for executable files
|
|
201
237
|
const valueForFunction = {
|
|
238
|
+
options: ctx.opts.options || {},
|
|
202
239
|
originalConfig: ctx.originalConfig,
|
|
203
|
-
|
|
204
|
-
|
|
240
|
+
currentConfig: cleanedCurrentConfig,
|
|
241
|
+
argsToPass,
|
|
242
|
+
// maybe helper fns
|
|
243
|
+
// maybe the lib instance itself for nested lookups
|
|
205
244
|
}
|
|
206
245
|
|
|
207
246
|
// Process JS files
|
|
@@ -230,8 +269,14 @@ ${JSON.stringify(options.context, null, 2)}`,
|
|
|
230
269
|
try {
|
|
231
270
|
const tsFile = await executeTypeScriptFile(fullFilePath, { dynamicArgs: () => argsToPass })
|
|
232
271
|
let returnValueFunction = tsFile.config || tsFile.default || tsFile
|
|
233
|
-
|
|
272
|
+
// For default export functions with :property syntax, keep the function and use deep properties
|
|
273
|
+
// For named exports (non-function module), look up the named export
|
|
274
|
+
let includeFirstProperty = false
|
|
275
|
+
if (moduleName && typeof returnValueFunction !== 'function') {
|
|
234
276
|
returnValueFunction = tsFile[moduleName]
|
|
277
|
+
} else if (moduleName && typeof returnValueFunction === 'function') {
|
|
278
|
+
// Default export function with property access - include first property in path
|
|
279
|
+
includeFirstProperty = true
|
|
235
280
|
}
|
|
236
281
|
|
|
237
282
|
return processExecutableFile({
|
|
@@ -243,7 +288,8 @@ ${JSON.stringify(options.context, null, 2)}`,
|
|
|
243
288
|
matchedFileString,
|
|
244
289
|
relativePath,
|
|
245
290
|
fileType: 'TypeScript',
|
|
246
|
-
getDeeperValue: ctx.getDeeperValue
|
|
291
|
+
getDeeperValue: ctx.getDeeperValue,
|
|
292
|
+
includeFirstProperty
|
|
247
293
|
})
|
|
248
294
|
} catch (err) {
|
|
249
295
|
return Promise.reject(new Error(`Error processing TypeScript file: ${err.message}`))
|
|
@@ -257,8 +303,14 @@ ${JSON.stringify(options.context, null, 2)}`,
|
|
|
257
303
|
try {
|
|
258
304
|
const esmFile = await executeESMFile(fullFilePath, { dynamicArgs: () => argsToPass })
|
|
259
305
|
let returnValueFunction = esmFile.config || esmFile.default || esmFile
|
|
260
|
-
|
|
306
|
+
// For default export functions with :property syntax, keep the function and use deep properties
|
|
307
|
+
// For named exports (non-function module), look up the named export
|
|
308
|
+
let includeFirstProperty = false
|
|
309
|
+
if (moduleName && typeof returnValueFunction !== 'function') {
|
|
261
310
|
returnValueFunction = esmFile[moduleName]
|
|
311
|
+
} else if (moduleName && typeof returnValueFunction === 'function') {
|
|
312
|
+
// Default export function with property access - include first property in path
|
|
313
|
+
includeFirstProperty = true
|
|
262
314
|
}
|
|
263
315
|
|
|
264
316
|
return processExecutableFile({
|
|
@@ -270,7 +322,8 @@ ${JSON.stringify(options.context, null, 2)}`,
|
|
|
270
322
|
matchedFileString,
|
|
271
323
|
relativePath,
|
|
272
324
|
fileType: 'ESM',
|
|
273
|
-
getDeeperValue: ctx.getDeeperValue
|
|
325
|
+
getDeeperValue: ctx.getDeeperValue,
|
|
326
|
+
includeFirstProperty
|
|
274
327
|
})
|
|
275
328
|
} catch (err) {
|
|
276
329
|
return Promise.reject(new Error(`Error processing ESM file: ${err.message}`))
|
|
@@ -295,15 +348,15 @@ ${JSON.stringify(options.context, null, 2)}`,
|
|
|
295
348
|
}
|
|
296
349
|
// console.log('deep', variableString)
|
|
297
350
|
// console.log('matchedFileString', matchedFileString)
|
|
298
|
-
|
|
351
|
+
const deepPropertiesStr = variableString.replace(matchedFileString, '')
|
|
299
352
|
// Support both : and . as the separator for sub properties
|
|
300
|
-
const firstChar =
|
|
353
|
+
const firstChar = deepPropertiesStr.substring(0, 1)
|
|
301
354
|
if (firstChar !== ':' && firstChar !== '.') {
|
|
302
355
|
const errorMessage = `Invalid variable syntax when referencing file "${relativePath}" sub properties
|
|
303
|
-
Please use ":" or "." to reference sub properties. ${
|
|
356
|
+
Please use ":" or "." to reference sub properties. ${deepPropertiesStr}`
|
|
304
357
|
return Promise.reject(new Error(errorMessage))
|
|
305
358
|
}
|
|
306
|
-
deepProperties =
|
|
359
|
+
const deepProperties = deepPropertiesStr.slice(1).split('.')
|
|
307
360
|
return ctx.getDeeperValue(deepProperties, valueToPopulate)
|
|
308
361
|
}
|
|
309
362
|
|
|
@@ -360,13 +413,21 @@ function parseModuleReference(variableString, matchedFileString) {
|
|
|
360
413
|
* Extracts deep properties from variable string after file match
|
|
361
414
|
* @param {string} variableString - The full variable string
|
|
362
415
|
* @param {string} matchedFileString - The matched file path portion
|
|
416
|
+
* @param {boolean} [includeFirstProperty=false] - Include first property (for default exports)
|
|
363
417
|
* @returns {string[]} Array of property keys to traverse
|
|
364
418
|
*/
|
|
365
|
-
function extractDeepProperties(variableString, matchedFileString) {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
419
|
+
function extractDeepProperties(variableString, matchedFileString, includeFirstProperty = false) {
|
|
420
|
+
const deepPropertiesStr = variableString.replace(matchedFileString, '')
|
|
421
|
+
if (!deepPropertiesStr || deepPropertiesStr === '') {
|
|
422
|
+
return []
|
|
423
|
+
}
|
|
424
|
+
const deepProperties = deepPropertiesStr.slice(1).split('.')
|
|
425
|
+
// For named exports, skip first property (it's the module name)
|
|
426
|
+
// For default exports, keep all properties
|
|
427
|
+
if (!includeFirstProperty) {
|
|
428
|
+
deepProperties.splice(0, 1)
|
|
429
|
+
}
|
|
430
|
+
return deepProperties.map((prop) => trim(prop)).filter(Boolean)
|
|
370
431
|
}
|
|
371
432
|
|
|
372
433
|
/**
|
|
@@ -381,6 +442,7 @@ function extractDeepProperties(variableString, matchedFileString) {
|
|
|
381
442
|
* @param {string} params.relativePath - Relative file path for errors
|
|
382
443
|
* @param {string} params.fileType - Type of file (javascript/TypeScript/ESM)
|
|
383
444
|
* @param {Function} params.getDeeperValue - Function to resolve nested values
|
|
445
|
+
* @param {boolean} [params.includeFirstProperty=false] - Include first property in path (for default exports)
|
|
384
446
|
* @returns {Promise<any>}
|
|
385
447
|
*/
|
|
386
448
|
async function processExecutableFile({
|
|
@@ -392,7 +454,8 @@ async function processExecutableFile({
|
|
|
392
454
|
matchedFileString,
|
|
393
455
|
relativePath,
|
|
394
456
|
fileType,
|
|
395
|
-
getDeeperValue
|
|
457
|
+
getDeeperValue,
|
|
458
|
+
includeFirstProperty = false
|
|
396
459
|
}) {
|
|
397
460
|
if (typeof returnValueFunction !== 'function') {
|
|
398
461
|
const errorMessage = `Invalid variable syntax when referencing file "${relativePath}".
|
|
@@ -400,10 +463,10 @@ Check if your ${fileType} is exporting a function that returns a value.`
|
|
|
400
463
|
return Promise.reject(new Error(errorMessage))
|
|
401
464
|
}
|
|
402
465
|
|
|
403
|
-
const valueToPopulate = returnValueFunction.call(fileModule,
|
|
466
|
+
const valueToPopulate = returnValueFunction.call(fileModule, ...argsToPass, valueForFunction)
|
|
404
467
|
|
|
405
468
|
return Promise.resolve(valueToPopulate).then((valueToPopulateResolved) => {
|
|
406
|
-
const deepProperties = extractDeepProperties(variableString, matchedFileString)
|
|
469
|
+
const deepProperties = extractDeepProperties(variableString, matchedFileString, includeFirstProperty)
|
|
407
470
|
return getDeeperValue(deepProperties, valueToPopulateResolved).then((deepValueToPopulateResolved) => {
|
|
408
471
|
if (typeof deepValueToPopulateResolved === 'undefined') {
|
|
409
472
|
const errorMessage = `Invalid variable syntax when referencing file "${relativePath}".
|
|
@@ -10,13 +10,19 @@ const { findProjectRoot } = require('../utils/paths/findProjectRoot')
|
|
|
10
10
|
const GIT_PREFIX = 'git'
|
|
11
11
|
const gitVariableSyntax = RegExp(/^git:/g)
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Execute a shell command
|
|
15
|
+
* @param {string} cmd - Command to execute
|
|
16
|
+
* @param {import('child_process').ExecOptions} [options] - Exec options
|
|
17
|
+
* @returns {Promise<string>}
|
|
18
|
+
*/
|
|
13
19
|
async function _exec(cmd, options = { timeout: 1000 }) {
|
|
14
20
|
return new Promise((resolve, reject) => {
|
|
15
21
|
childProcess.exec(cmd, options, (err, stdout) => {
|
|
16
22
|
if (err) {
|
|
17
23
|
return reject(err)
|
|
18
24
|
}
|
|
19
|
-
return resolve(stdout.trim())
|
|
25
|
+
return resolve(String(stdout).trim())
|
|
20
26
|
})
|
|
21
27
|
})
|
|
22
28
|
}
|
|
@@ -213,8 +219,10 @@ const cache = new Map()
|
|
|
213
219
|
|
|
214
220
|
/**
|
|
215
221
|
* Gets the last Git commit timestamp for a file
|
|
216
|
-
* @param {string}
|
|
217
|
-
* @
|
|
222
|
+
* @param {string} _file - Path to the file to check
|
|
223
|
+
* @param {string} cwd - Working directory
|
|
224
|
+
* @param {boolean} [throwOnMissing] - Whether to throw on missing file
|
|
225
|
+
* @returns {Promise<string|undefined>} The commit timestamp ISO string or undefined if not in Git
|
|
218
226
|
*/
|
|
219
227
|
async function getGitTimestamp(_file, cwd, throwOnMissing = true) {
|
|
220
228
|
// Validate file path to prevent command injection
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
const PAREN_OPEN_PLACEHOLDER = '__PH_PAREN_OPEN__'
|
|
2
2
|
const OPEN_PAREN_PLACEHOLDER_PATTERN = /__PH_PAREN_OPEN__/g
|
|
3
3
|
|
|
4
|
+
const JSON_ENCODED_PREFIX = '__JSON_B64__'
|
|
5
|
+
const JSON_ENCODED_PATTERN = /__JSON_B64__([A-Za-z0-9+/=]+)__/g
|
|
6
|
+
|
|
4
7
|
function encodeJsSyntax(value = '') {
|
|
5
8
|
return value.replace(/\(/g, PAREN_OPEN_PLACEHOLDER)
|
|
6
9
|
}
|
|
@@ -14,9 +17,50 @@ function hasParenthesesPlaceholder(value = '') {
|
|
|
14
17
|
return OPEN_PAREN_PLACEHOLDER_PATTERN.test(value)
|
|
15
18
|
}
|
|
16
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Encode a JSON object to base64 for safe embedding in variable strings
|
|
22
|
+
* @param {object} obj - Object to encode
|
|
23
|
+
* @returns {string} Encoded string like __JSON_B64__eyJmb28iOiJiYXIifQ==__
|
|
24
|
+
*/
|
|
25
|
+
function encodeJsonForVariable(obj) {
|
|
26
|
+
const jsonStr = JSON.stringify(obj)
|
|
27
|
+
const b64 = Buffer.from(jsonStr).toString('base64')
|
|
28
|
+
return `${JSON_ENCODED_PREFIX}${b64}__`
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Decode base64-encoded JSON from variable strings
|
|
33
|
+
* @param {string} value - String potentially containing encoded JSON
|
|
34
|
+
* @returns {string} String with encoded JSON decoded back to JSON strings
|
|
35
|
+
*/
|
|
36
|
+
function decodeJsonInVariable(value) {
|
|
37
|
+
if (!value || typeof value !== 'string') return value
|
|
38
|
+
return value.replace(JSON_ENCODED_PATTERN, (match, b64) => {
|
|
39
|
+
try {
|
|
40
|
+
const jsonStr = Buffer.from(b64, 'base64').toString('utf8')
|
|
41
|
+
return jsonStr
|
|
42
|
+
} catch (e) {
|
|
43
|
+
return match
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Check if string contains encoded JSON
|
|
50
|
+
* @param {string} value - String to check
|
|
51
|
+
* @returns {boolean}
|
|
52
|
+
*/
|
|
53
|
+
function hasEncodedJson(value) {
|
|
54
|
+
if (!value || typeof value !== 'string') return false
|
|
55
|
+
return value.includes(JSON_ENCODED_PREFIX)
|
|
56
|
+
}
|
|
57
|
+
|
|
17
58
|
module.exports = {
|
|
18
59
|
OPEN_PAREN_PLACEHOLDER_PATTERN,
|
|
19
60
|
hasParenthesesPlaceholder,
|
|
20
61
|
encodeJsSyntax,
|
|
21
62
|
decodeJsSyntax,
|
|
63
|
+
encodeJsonForVariable,
|
|
64
|
+
decodeJsonInVariable,
|
|
65
|
+
hasEncodedJson,
|
|
22
66
|
}
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
*/
|
|
4
4
|
function mergeByKeys(data, path, keysToMerge) {
|
|
5
5
|
if (!data) return {}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
|
|
7
|
+
// Handle empty path - operate on root data
|
|
8
|
+
const items = path ? path.split('.').reduce((obj, key) => obj?.[key], data) : data
|
|
9
|
+
if (!Array.isArray(items)) return data
|
|
9
10
|
|
|
10
11
|
const result = {}
|
|
11
12
|
const mergeAll = !keysToMerge || !Array.isArray(keysToMerge) || keysToMerge.length === 0
|
|
@@ -31,12 +31,12 @@ function parseFileContents({ contents, filePath, varRegex, dynamicArgs }) {
|
|
|
31
31
|
|
|
32
32
|
if (fileType.match(/\.(yml|yaml)/i)) {
|
|
33
33
|
try {
|
|
34
|
-
const ymlText = YAML.preProcess(contents
|
|
34
|
+
const ymlText = YAML.preProcess(contents)
|
|
35
35
|
configObject = YAML.parse(ymlText)
|
|
36
36
|
} catch (err) {
|
|
37
37
|
// Attempt to fix cloudformation refs
|
|
38
38
|
if (err.message.match(/YAMLException/)) {
|
|
39
|
-
const ymlText = YAML.preProcess(contents
|
|
39
|
+
const ymlText = YAML.preProcess(contents)
|
|
40
40
|
const result = YAML.load(ymlText, {
|
|
41
41
|
filename: filePath,
|
|
42
42
|
schema: cloudFormationSchema.schema,
|
|
@@ -82,6 +82,8 @@ function parseFileContents({ contents, filePath, varRegex, dynamicArgs }) {
|
|
|
82
82
|
configObject = (typeof configObject.config === 'function') ? configObject.config(jsArgs) : configObject.config
|
|
83
83
|
} else if (configObject.default) {
|
|
84
84
|
configObject = (typeof configObject.default === 'function') ? configObject.default(jsArgs) : configObject.default
|
|
85
|
+
} else if (typeof configObject === 'function') {
|
|
86
|
+
configObject = configObject(jsArgs)
|
|
85
87
|
}
|
|
86
88
|
// console.log('parseFileContents configObject', configObject)
|
|
87
89
|
} catch (err) {
|
|
@@ -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
|
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"}
|