configorama 0.9.14 → 0.9.16

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/index.d.ts CHANGED
@@ -55,6 +55,10 @@ interface ConfigoramaSettings {
55
55
  dynamicArgs?: object | Function
56
56
  /** Return both config and metadata about variables found */
57
57
  returnMetadata?: boolean
58
+ /** Suppress env-stage-loader logs when useDotenv/useDotEnv is enabled. Defaults to true for API calls. */
59
+ dotEnvSilent?: boolean
60
+ /** Enable env-stage-loader debug logs when useDotenv/useDotEnv is enabled */
61
+ dotEnvDebug?: boolean
58
62
  /** Keys to merge in arrays of objects */
59
63
  mergeKeys?: string[]
60
64
  /** Map of file paths to override */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "configorama",
3
- "version": "0.9.14",
3
+ "version": "0.9.16",
4
4
  "description": "Variable support for configuration files",
5
5
  "main": "src/index.js",
6
6
  "types": "index.d.ts",
package/src/display.js ADDED
@@ -0,0 +1,485 @@
1
+ // CLI display formatting for variable info, verify, and discovery output
2
+ // Pure functions that write directly to stdout
3
+
4
+ const chalk = require('./utils/ui/chalk')
5
+ const { logHeader } = require('./utils/ui/logs')
6
+ const { makeStackedBoxes } = require('@davidwells/box-logger')
7
+ const { findLineForKey } = require('./utils/paths/findLineForKey')
8
+ const { createEditorLink } = require('./utils/ui/createEditorLink')
9
+ const { isSensitiveVariable } = require('./utils/ui/configWizard')
10
+
11
+ const SPACING = ' '
12
+ const TITLE_TEXT = `Variable:${SPACING}`
13
+ const VALUE_HEX = '#899499'
14
+
15
+ /**
16
+ * Display "No Variables Found" message
17
+ * @param {string} configFilePath
18
+ * @param {RegExp} variableSyntax
19
+ * @param {Object} variableTypes
20
+ */
21
+ function displayNoVariablesFound(configFilePath, variableSyntax, variableTypes) {
22
+ logHeader('No Variables Found in Config')
23
+ if (configFilePath) {
24
+ console.log(`File: ${configFilePath}`)
25
+ }
26
+
27
+ console.log(`\nVariable syntax: `, variableSyntax)
28
+
29
+ const varTypes = Object.keys(variableTypes)
30
+ if (varTypes.length) {
31
+ const exclude = ['dot.prop', 'deep']
32
+ console.log('\nAllowed variable types:')
33
+ varTypes.forEach((v) => {
34
+ const vData = variableTypes[v]
35
+ if (exclude.includes(vData.type)) {
36
+ return
37
+ }
38
+ console.log(` - ${vData.type}: `, vData.match)
39
+ })
40
+ }
41
+ console.log()
42
+ }
43
+
44
+ /**
45
+ * Display variable details in stacked box format
46
+ * @param {Object} params
47
+ * @param {string[]} params.varKeys
48
+ * @param {Object} params.variableData
49
+ * @param {Object} params.uniqueVariables
50
+ * @param {RegExp} params.varPrefixPattern
51
+ * @param {RegExp} params.varSuffixPattern
52
+ * @param {string[]} params.lines
53
+ * @param {string} params.fileType
54
+ * @param {string} params.configFilePath
55
+ */
56
+ function displayVariableDetails({ varKeys, variableData, uniqueVariables, varPrefixPattern, varSuffixPattern, lines, fileType, configFilePath }) {
57
+ if (!varKeys.length) return
58
+
59
+ const getBaseVarName = (key) => key.replace(varPrefixPattern, '').replace(varSuffixPattern, '').split(',')[0].trim()
60
+
61
+ const fileName = configFilePath ? ` in ${configFilePath}` : ''
62
+
63
+ logHeader(`Found ${varKeys.length} Variables${fileName}`)
64
+
65
+ // deepLog('variableData', variableData)
66
+
67
+ if (varKeys.length) {
68
+ console.log()
69
+ const longestKey = varKeys.reduce((acc, k) => {
70
+ return Math.max(acc, k.length)
71
+ }, 0)
72
+
73
+ // Use uniqueVariables for simpler reference counting
74
+ const referenceData = varKeys.map((k) => {
75
+ const varName = getBaseVarName(k)
76
+ const uniqueVar = uniqueVariables[varName]
77
+ const refCount = uniqueVar ? uniqueVar.occurrences.length : variableData[k].length
78
+ const placesWord = refCount > 1 ? 'places' : 'place'
79
+ return `- ${k.padEnd(longestKey).padEnd(longestKey + 10)} referenced ${refCount} ${placesWord}`
80
+ }).join('\n')
81
+
82
+ console.log(`${referenceData}\n`)
83
+ }
84
+
85
+ logHeader('Variable Details')
86
+
87
+ const keyChalk = chalk.whiteBright
88
+ const valueChalk = chalk.hex(VALUE_HEX)
89
+
90
+ const indent = ''
91
+ const boxes = varKeys.map((key, i) => {
92
+ const variableInstances = variableData[key]
93
+ // console.log('variableInstances', variableInstances)
94
+ const firstInstance = variableInstances[0]
95
+
96
+ // Get uniqueVariable data for description and other metadata
97
+ const varName = getBaseVarName(key)
98
+ const uniqueVar = uniqueVariables[varName]
99
+
100
+ // Build display message from enriched metadata
101
+ let varMsg = ''
102
+ let requiredMessage = ''
103
+
104
+ // Show required status from metadata
105
+ if (firstInstance.isRequired) {
106
+ requiredMessage = `${chalk.red.bold('[Required]')}`
107
+ }
108
+
109
+ // Show type filter if present (Boolean, String, Number, etc.)
110
+ if (uniqueVar && uniqueVar.types && uniqueVar.types.length > 0) {
111
+ const typeLabel = `${indent}${keyChalk('Type:'.padEnd(TITLE_TEXT.length, ' '))}`
112
+ varMsg += `${typeLabel} ${valueChalk(uniqueVar.types.join(', '))}\n`
113
+ }
114
+
115
+ // Show description from uniqueVariables if available
116
+ if (uniqueVar && uniqueVar.descriptions && uniqueVar.descriptions.length > 0) {
117
+ const descText = `${indent}${keyChalk('Description:'.padEnd(TITLE_TEXT.length, ' '))}`
118
+ const combinedDesc = uniqueVar.descriptions.join('. ')
119
+ varMsg += `${descText} ${valueChalk(combinedDesc)}\n`
120
+ }
121
+
122
+ // Show resolve order from metadata
123
+ if (firstInstance.resolveOrder.length > 1) {
124
+ varMsg += `${indent}${keyChalk('Resolve Order:'.padEnd(TITLE_TEXT.length, ' '))}`
125
+ const resolveOrder = firstInstance.resolveOrder.join(', ')
126
+ varMsg += ` ${valueChalk(resolveOrder)}\n`
127
+ }
128
+
129
+ // Show default value from metadata
130
+ if (typeof firstInstance.defaultValue !== 'undefined') {
131
+ const defaultValueRender = firstInstance.defaultValue === '' ? '""' : firstInstance.defaultValue
132
+ const defaultValueText = `${indent}${keyChalk('Default value:'.padEnd(TITLE_TEXT.length, ' '))}`
133
+ varMsg += `${defaultValueText} ${valueChalk(defaultValueRender)}\n`
134
+ }
135
+
136
+ // Show default value source path from metadata
137
+ if (firstInstance.defaultValueSrc) {
138
+ varMsg += `${indent}${keyChalk('Default path:'.padEnd(TITLE_TEXT.length, ' '))} `
139
+ const defaultPathLine = findLineForKey(firstInstance.defaultValueSrc, lines, fileType)
140
+ if (defaultPathLine) {
141
+ varMsg += `${createEditorLink(configFilePath, defaultPathLine, 1, firstInstance.defaultValueSrc, 'gray')}\n`
142
+ } else {
143
+ varMsg += `${valueChalk(firstInstance.defaultValueSrc)}\n`
144
+ }
145
+ }
146
+
147
+ // Show path(s) from metadata
148
+ const configPathLine = findLineForKey(variableInstances[0].path, lines, fileType)
149
+ let locationRender = configPathLine
150
+ ? createEditorLink(configFilePath, configPathLine, 1, variableInstances[0].path, 'gray')
151
+ : valueChalk(variableInstances[0].path)
152
+ let locationLabel = `${indent}${keyChalk('Config Path:'.padEnd(TITLE_TEXT.length, ' '))}`
153
+ let typeText = ''
154
+ if (variableInstances.length > 1) {
155
+ const pathIndent = ' '.repeat(TITLE_TEXT.length + 1)
156
+ const pathItems = variableInstances.map((v, idx) => {
157
+ const pathLine = findLineForKey(v.path, lines, fileType)
158
+ const pathLink = pathLine
159
+ ? createEditorLink(configFilePath, pathLine, 1, `- ${v.path}`, 'gray')
160
+ : valueChalk(`- ${v.path}`)
161
+ // Show type filter per path if different
162
+ if (uniqueVar && uniqueVar.occurrences.length > 1) {
163
+ const occurrence = uniqueVar.occurrences.find(occ => occ.path === v.path)
164
+ const pathType = occurrence && occurrence.type
165
+ typeText = pathType ? ` ${chalk.dim(`Type: ${pathType}`)}` : ''
166
+ const prefix = idx === 0 ? '' : `${indent}${pathIndent}`
167
+ return `${prefix}${pathLink}${typeText}`
168
+ }
169
+ const prefix = idx === 0 ? '' : `${indent}${pathIndent}`
170
+ return `${prefix}${pathLink}${typeText}`
171
+ })
172
+ locationRender = pathItems.join('\n')
173
+ locationLabel = `${indent}${keyChalk('Config Paths:'.padEnd(TITLE_TEXT.length, ' '))}`
174
+ } else {
175
+ const pathType = firstInstance.type
176
+ typeText = pathType ? ` ${chalk.dim(`Type: ${pathType}`)}` : ''
177
+ }
178
+ varMsg += `${locationLabel} ${locationRender}`
179
+
180
+ const lineNumber = findLineForKey(firstInstance.key, lines, fileType)
181
+
182
+ return {
183
+ content: {
184
+ left: varMsg,
185
+ backgroundColor: 'red',
186
+ width: '100%',
187
+ },
188
+ title: {
189
+ left: `▷ ${lineNumber ? createEditorLink(configFilePath, lineNumber, 1, key) : key}`,
190
+ right: lineNumber ? createEditorLink(configFilePath, lineNumber, 1, `${requiredMessage} ${lineNumber ? `Line: ${lineNumber.toString().padEnd(2, ' ')}` : ''}`, 'gray') : '',
191
+ center: typeText,
192
+ paddingBottom: 1,
193
+ paddingTop: (i === 0) ? 1 : 0,
194
+ truncate: true,
195
+ },
196
+ width: '100%',
197
+ }
198
+ })
199
+
200
+ console.log(makeStackedBoxes(boxes, {
201
+ borderText: 'Variable Details. Click on titles to open in editor.',
202
+ borderColor: 'gray',
203
+ minWidth: '96%',
204
+ borderStyle: 'bold',
205
+ disableTitleSeparator: true,
206
+ }))
207
+ // process.exit(1)
208
+ }
209
+
210
+ /**
211
+ * Display unique variables in stacked box format
212
+ * @param {Object} params
213
+ * @param {string[]} params.uniqueVarKeys
214
+ * @param {Object} params.uniqueVariables
215
+ * @param {string[]} params.lines
216
+ * @param {string} params.fileType
217
+ * @param {string} params.configFilePath
218
+ */
219
+ function displayUniqueVariables({ uniqueVarKeys, uniqueVariables, lines, fileType, configFilePath }) {
220
+ const keyChalk = chalk.whiteBright
221
+ const valueChalk = chalk.hex(VALUE_HEX)
222
+
223
+ // New unique variable makeStackedBoxes display
224
+ const uniqueBoxes = uniqueVarKeys.map((varName, i) => {
225
+ const uniqueVar = uniqueVariables[varName]
226
+ const occurrences = uniqueVar.occurrences || []
227
+ const firstOcc = occurrences[0] || {}
228
+
229
+ let varMsg = ''
230
+ let requiredMessage = ''
231
+
232
+ // Show required status from computed isRequired (accounts for resolved self-refs)
233
+ const isRequired = occurrences.some(occ => occ.isRequired)
234
+ if (isRequired) {
235
+ requiredMessage = `${chalk.red.bold('[Required]')}`
236
+ }
237
+
238
+ // Show type filter if present
239
+ if (uniqueVar.types && uniqueVar.types.length > 0) {
240
+ const typeLabel = `${keyChalk('Type:'.padEnd(TITLE_TEXT.length, ' '))}`
241
+ varMsg += `${typeLabel} ${valueChalk(uniqueVar.types.join(', '))}\n`
242
+ }
243
+
244
+ // Show description
245
+ if (uniqueVar.descriptions && uniqueVar.descriptions.length > 0) {
246
+ const descText = `${keyChalk('Description:'.padEnd(TITLE_TEXT.length, ' '))}`
247
+ const combinedDesc = uniqueVar.descriptions.join('. ')
248
+ varMsg += `${descText} ${valueChalk(combinedDesc)}\n`
249
+ }
250
+
251
+ // Show default value only if it's a true fallback, not a pre-resolved value
252
+ // Redact sensitive values like API keys, secrets, tokens
253
+ const isSensitive = isSensitiveVariable(varName)
254
+ const hasActualDefault = firstOcc.hasFallback && typeof firstOcc.defaultValue !== 'undefined'
255
+ if (hasActualDefault) {
256
+ const defaultValueRender = isSensitive ? '********' : (firstOcc.defaultValue === '' ? '""' : firstOcc.defaultValue)
257
+ const defaultValueText = `${keyChalk('Default value:'.padEnd(TITLE_TEXT.length, ' '))}`
258
+ varMsg += `${defaultValueText} ${valueChalk(defaultValueRender)}\n`
259
+ } else if (uniqueVar.resolvedValue !== undefined) {
260
+ // Show pre-resolved current value (e.g., from env, git)
261
+ const resolvedRender = isSensitive ? '********' : (uniqueVar.resolvedValue === '' ? '""' : uniqueVar.resolvedValue)
262
+ const resolvedText = `${keyChalk('Current value:'.padEnd(TITLE_TEXT.length, ' '))}`
263
+ const envIndicator = uniqueVar.variableType === 'env' ? ` ${chalk.red('(currently set env var)')}` : ''
264
+ varMsg += `${resolvedText} ${valueChalk(resolvedRender)}${envIndicator}\n`
265
+ }
266
+
267
+ // Show default value source path
268
+ if (firstOcc.defaultValueSrc) {
269
+ varMsg += `${keyChalk('Default path:'.padEnd(TITLE_TEXT.length, ' '))} `
270
+ const defaultPathLine = findLineForKey(firstOcc.defaultValueSrc, lines, fileType)
271
+ if (defaultPathLine) {
272
+ varMsg += `${createEditorLink(configFilePath, defaultPathLine, 1, firstOcc.defaultValueSrc, 'gray')}\n`
273
+ } else {
274
+ varMsg += `${valueChalk(firstOcc.defaultValueSrc)}\n`
275
+ }
276
+ }
277
+
278
+ // Show config path(s) from occurrences
279
+ let locationRender
280
+ let locationLabel
281
+ if (occurrences.length > 1) {
282
+ const pathIndent = ' '.repeat(TITLE_TEXT.length + 1)
283
+ const pathItems = occurrences.map((occ, idx) => {
284
+ const pathLine = findLineForKey(occ.path, lines, fileType)
285
+ const pathLink = pathLine
286
+ ? createEditorLink(configFilePath, pathLine, 1, `- ${occ.path}`, 'gray')
287
+ : valueChalk(`- ${occ.path}`)
288
+ const typeText = occ.type ? ` ${chalk.dim(`Type: ${occ.type}`)}` : ''
289
+ const prefix = idx === 0 ? '' : `${pathIndent}`
290
+ return `${prefix}${pathLink}${typeText}`
291
+ })
292
+ locationRender = pathItems.join('\n')
293
+ locationLabel = `${keyChalk('Config Paths:'.padEnd(TITLE_TEXT.length, ' '))}`
294
+ } else {
295
+ const pathLine = findLineForKey(firstOcc.path, lines, fileType)
296
+ locationRender = pathLine
297
+ ? createEditorLink(configFilePath, pathLine, 1, firstOcc.path, 'gray')
298
+ : valueChalk(firstOcc.path)
299
+ locationLabel = `${keyChalk('Config Path:'.padEnd(TITLE_TEXT.length, ' '))}`
300
+ }
301
+ varMsg += `${locationLabel} ${locationRender}`
302
+
303
+ // Find first line number for title
304
+ const lineNumber = findLineForKey(firstOcc.path, lines, fileType)
305
+
306
+ return {
307
+ content: {
308
+ left: varMsg,
309
+ backgroundColor: 'red',
310
+ width: '100%',
311
+ },
312
+ title: {
313
+ left: `▷ ${firstOcc.varMatch}`,
314
+ right: `${requiredMessage} ${lineNumber ? `Line: ${lineNumber.toString().padEnd(2, ' ')}` : ''}`,
315
+ paddingBottom: 1,
316
+ paddingTop: (i === 0) ? 1 : 0,
317
+ truncate: true,
318
+ },
319
+ width: '100%',
320
+ }
321
+ })
322
+
323
+ console.log(makeStackedBoxes(uniqueBoxes, {
324
+ borderText: 'Unique Variables',
325
+ borderColor: 'gray',
326
+ minWidth: '96%',
327
+ borderStyle: 'bold',
328
+ disableTitleSeparator: true,
329
+ }))
330
+ console.log()
331
+ }
332
+
333
+ /**
334
+ * Display configurable variables grouped by source type
335
+ * @param {Object} params
336
+ * @param {string[]} params.uniqueVarKeys
337
+ * @param {Object} params.uniqueVariables
338
+ * @param {string[]} params.lines
339
+ * @param {string} params.fileType
340
+ * @param {string} params.configFilePath
341
+ */
342
+ function displayConfigurableVariables({ uniqueVarKeys, uniqueVariables, lines, fileType, configFilePath }) {
343
+ // Unique variables that require setup (excludes readonly source types)
344
+ const CONFIGURABLE_SOURCES = ['user', 'config', 'remote']
345
+ const configurableVarKeys = []
346
+
347
+ for (const varName of uniqueVarKeys) {
348
+ const uniqueVar = uniqueVariables[varName]
349
+ // Include if source type is user, config, or remote (not readonly)
350
+ if (CONFIGURABLE_SOURCES.includes(uniqueVar.variableSourceType)) {
351
+ configurableVarKeys.push(varName)
352
+ }
353
+ }
354
+
355
+ if (!configurableVarKeys.length) return
356
+
357
+ const keyChalk = chalk.whiteBright
358
+ const valueChalk = chalk.hex(VALUE_HEX)
359
+
360
+ // Group by source type
361
+ const bySource = {
362
+ user: [],
363
+ config: [],
364
+ remote: [],
365
+ }
366
+
367
+ for (const varName of configurableVarKeys) {
368
+ const v = uniqueVariables[varName]
369
+ const sourceType = v.variableSourceType || 'user'
370
+ if (bySource[sourceType]) {
371
+ bySource[sourceType].push({ varName, ...v })
372
+ }
373
+ }
374
+
375
+ const configurableBoxes = []
376
+
377
+ for (const [sourceType, vars] of Object.entries(bySource)) {
378
+ if (vars.length === 0) continue
379
+
380
+ for (let i = 0; i < vars.length; i++) {
381
+ const v = vars[i]
382
+ const occurrences = v.occurrences || []
383
+ const firstOcc = occurrences[0] || {}
384
+
385
+ let varMsg = ''
386
+ let requiredMessage = ''
387
+
388
+ // Show required status from computed isRequired (accounts for resolved self-refs)
389
+ const isRequired = occurrences.some(occ => occ.isRequired)
390
+ if (isRequired) {
391
+ requiredMessage = `${chalk.red.bold('[Required]')}`
392
+ }
393
+
394
+ // Show description if present (directly under title, not as key/value)
395
+ if (v.descriptions && v.descriptions.length > 0) {
396
+ varMsg += `${chalk.dim(v.descriptions.join('. '))}\n\n`
397
+ }
398
+
399
+ // Show type filter if defined (String, Number, etc.)
400
+ const varType = (v.types && v.types[0]) || firstOcc.type
401
+ if (varType) {
402
+ varMsg += `${keyChalk('Type:'.padEnd(TITLE_TEXT.length, ' '))} ${valueChalk(varType)}\n`
403
+ }
404
+
405
+ // Show current/default value (redact sensitive values)
406
+ const isSensitive = isSensitiveVariable(v.varName)
407
+ if (v.resolvedValue !== undefined) {
408
+ const resolvedRender = isSensitive ? '********' : (v.resolvedValue === '' ? '""' : v.resolvedValue)
409
+ varMsg += `${keyChalk('Current value:'.padEnd(TITLE_TEXT.length, ' '))} ${valueChalk(resolvedRender)}\n`
410
+ } else if (firstOcc.hasFallback && firstOcc.defaultValue !== undefined) {
411
+ const defaultRender = isSensitive ? '********' : (firstOcc.defaultValue === '' ? '""' : firstOcc.defaultValue)
412
+ varMsg += `${keyChalk('Default value:'.padEnd(TITLE_TEXT.length, ' '))} ${valueChalk(defaultRender)}\n`
413
+ }
414
+
415
+ // Show config path(s)
416
+ let locationRender
417
+ let locationLabel
418
+ if (occurrences.length > 1) {
419
+ const pathIndent = ' '.repeat(TITLE_TEXT.length + 1)
420
+ const pathItems = occurrences.map((occ, idx) => {
421
+ const pathLine = findLineForKey(occ.path, lines, fileType)
422
+ const pathLink = pathLine
423
+ ? createEditorLink(configFilePath, pathLine, 1, `- ${occ.path}`, VALUE_HEX)
424
+ : valueChalk(`- ${occ.path}`)
425
+ const prefix = idx === 0 ? '' : `${pathIndent}`
426
+ return `${prefix}${pathLink}`
427
+ })
428
+ locationRender = pathItems.join('\n')
429
+ locationLabel = 'Config Paths:'
430
+ } else {
431
+ const pathLine = findLineForKey(firstOcc.path, lines, fileType)
432
+ locationRender = pathLine
433
+ ? createEditorLink(configFilePath, pathLine, 1, firstOcc.path, VALUE_HEX)
434
+ : valueChalk(firstOcc.path)
435
+ locationLabel = 'Config Path:'
436
+ }
437
+ varMsg += `${keyChalk(locationLabel.padEnd(TITLE_TEXT.length, ' '))} ${locationRender}`
438
+
439
+ // Get type for center heading (reuse varType from above)
440
+ const typeText = varType ? chalk.dim(`Type: ${varType}`) : ''
441
+
442
+ // Get line number for first occurrence
443
+ const firstOccLine = findLineForKey(firstOcc.path, lines, fileType)
444
+ const varTitle = firstOcc.varMatch || v.varName
445
+ const requiredSuffix = requiredMessage ? ` - ${requiredMessage}` : ''
446
+ const titleLink = firstOccLine
447
+ ? createEditorLink(configFilePath, firstOccLine, 1, `▷ ${varTitle}`) + requiredSuffix
448
+ : `▷ ${varTitle}${requiredSuffix}`
449
+
450
+ configurableBoxes.push({
451
+ content: {
452
+ left: varMsg,
453
+ width: '100%',
454
+ },
455
+ title: {
456
+ left: titleLink,
457
+ // center: typeText,
458
+ right: chalk.dim(`${v.variableType}`),
459
+ paddingBottom: 1,
460
+ paddingTop: (configurableBoxes.length === 0) ? 1 : 0,
461
+ truncate: true,
462
+ },
463
+ width: '100%',
464
+ })
465
+ }
466
+ }
467
+
468
+ if (configurableBoxes.length > 0) {
469
+ console.log(makeStackedBoxes(configurableBoxes, {
470
+ borderText: `Configurable Variables (${configurableVarKeys.length})`,
471
+ borderColor: 'yellow',
472
+ minWidth: '96%',
473
+ borderStyle: 'bold',
474
+ disableTitleSeparator: true,
475
+ }))
476
+ console.log()
477
+ }
478
+ }
479
+
480
+ module.exports = {
481
+ displayNoVariablesFound,
482
+ displayVariableDetails,
483
+ displayUniqueVariables,
484
+ displayConfigurableVariables,
485
+ }
package/src/index.js CHANGED
@@ -15,6 +15,8 @@ const { buildVariableSyntax } = require('./utils/variables/variableUtils')
15
15
  * @property {boolean} [allowUndefinedValues] - allow undefined values to pass through without throwing errors
16
16
  * @property {Object|Function} [dynamicArgs] - values passed into .js config files if user using javascript config
17
17
  * @property {boolean} [returnMetadata] - return both config and metadata about variables found
18
+ * @property {boolean} [dotEnvSilent] - suppress env-stage-loader logs when useDotenv/useDotEnv is enabled
19
+ * @property {boolean} [dotEnvDebug] - enable env-stage-loader debug logs when useDotenv/useDotEnv is enabled
18
20
  * @property {string[]} [mergeKeys] - keys to merge in arrays of objects
19
21
  * @property {Object.<string, string>} [filePathOverrides] - map of file paths to override
20
22
  */