configorama 0.7.1 → 0.7.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "configorama",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "description": "Variable support for configuration files",
5
5
  "main": "src/index.js",
6
6
  "types": "index.d.ts",
@@ -34,20 +34,44 @@ function normalizePath(filePath) {
34
34
  }
35
35
 
36
36
  /**
37
- * Extract file path from a file() or text() variable string
37
+ * Extract file path from a file() or text() variable string using balanced paren matching
38
38
  * @param {string} variableString - The variable string (with or without ${} wrapper)
39
39
  * @returns {object|null} Object with filePath, or null if no match
40
40
  */
41
41
  function extractFilePath(variableString) {
42
- // Match both ${file(...)} and file(...) formats
43
- const fileMatch = variableString.match(/^(?:\$\{)?(?:file|text)\((.*?)\)/)
44
- if (!fileMatch || !fileMatch[1]) {
42
+ // Match the file( or text( prefix
43
+ const prefixMatch = variableString.match(/^(?:\$\{)?(file|text)\(/)
44
+ if (!prefixMatch) {
45
+ return null
46
+ }
47
+
48
+ // Find matching closing paren using depth tracking
49
+ const startIndex = prefixMatch[0].length - 1 // Position of opening (
50
+ let depth = 1
51
+ let i = startIndex + 1
52
+
53
+ while (i < variableString.length && depth > 0) {
54
+ if (variableString[i] === '(') {
55
+ depth++
56
+ } else if (variableString[i] === ')') {
57
+ depth--
58
+ }
59
+ i++
60
+ }
61
+
62
+ if (depth !== 0) {
63
+ return null
64
+ }
65
+
66
+ // Extract content between balanced parens
67
+ const fileContent = variableString.substring(startIndex + 1, i - 1).trim()
68
+ if (!fileContent) {
45
69
  return null
46
70
  }
47
71
 
48
72
  const { trimSurroundingQuotes } = require('../strings/quoteUtils')
49
- const fileContent = fileMatch[1].trim()
50
- const parts = splitCsv(fileContent)
73
+ // Protect ${} variables from being split (e.g., file paths with default values)
74
+ const parts = splitCsv(fileContent, undefined, { protectVariables: true })
51
75
  let filePath = parts[0].trim()
52
76
 
53
77
  // Remove quotes if present
@@ -103,6 +103,22 @@ test('extractFilePath - handles bare filename', () => {
103
103
  assert.is(result.filePath, 'config.json')
104
104
  })
105
105
 
106
+ test('extractFilePath - handles nested variable with default value in path', () => {
107
+ // This is the bug case: ${self:provider.stage, 'dev'} has a comma inside
108
+ const result = extractFilePath("file(./env.${self:provider.stage, 'dev'}.yml):FOO")
109
+ assert.is(result.filePath, "./env.${self:provider.stage, 'dev'}.yml")
110
+ })
111
+
112
+ test('extractFilePath - handles nested variable without default in path', () => {
113
+ const result = extractFilePath("file(./env.${self:provider.stage}.yml):FOO")
114
+ assert.is(result.filePath, "./env.${self:provider.stage}.yml")
115
+ })
116
+
117
+ test('extractFilePath - handles multiple nested variables in path', () => {
118
+ const result = extractFilePath("file(./config-${self:stage, 'dev'}-${self:region}.yml)")
119
+ assert.is(result.filePath, "./config-${self:stage, 'dev'}-${self:region}.yml")
120
+ })
121
+
106
122
  // normalizeFileVariable tests
107
123
 
108
124
  test('normalizeFileVariable - returns non-file strings unchanged', () => {
@@ -1,14 +1,19 @@
1
1
  const { splitByComma } = require('./splitByComma')
2
2
 
3
+ // Regex to match ${...} variables (used for protection during file path splitting)
4
+ const VARIABLE_SYNTAX = /\${[^}]+}/g
5
+
3
6
  /**
4
7
  * Split a string by comma while preserving quoted content
5
8
  * NOTE: This is a simpler version that delegates to splitByComma for consistency.
6
9
  * For advanced use cases with bracket depth tracking and regex protection, use splitByComma directly.
7
10
  * @param {string} str - String to split
8
11
  * @param {string} [splitter] - Optional custom splitter (defaults to ',')
12
+ * @param {object} [options] - Options object
13
+ * @param {boolean} [options.protectVariables] - If true, protect ${} variables from splitting
9
14
  * @returns {string[]} Array of split strings
10
15
  */
11
- function splitCsv(str, splitter) {
16
+ function splitCsv(str, splitter, options = {}) {
12
17
  // If custom splitter is provided, fall back to original simple implementation
13
18
  if (splitter && splitter !== ',') {
14
19
  const splitSyntax = splitter
@@ -32,6 +37,10 @@ function splitCsv(str, splitter) {
32
37
  }
33
38
 
34
39
  // For standard comma splitting, use the more robust splitByComma
40
+ // Pass VARIABLE_SYNTAX if protectVariables is true to protect ${} from splitting
41
+ if (options.protectVariables) {
42
+ return splitByComma(str, VARIABLE_SYNTAX)
43
+ }
35
44
  return splitByComma(str)
36
45
  }
37
46
 
@@ -5,7 +5,7 @@
5
5
  */
6
6
  export function normalizePath(filePath: string): string | null;
7
7
  /**
8
- * Extract file path from a file() or text() variable string
8
+ * Extract file path from a file() or text() variable string using balanced paren matching
9
9
  * @param {string} variableString - The variable string (with or without ${} wrapper)
10
10
  * @returns {object|null} Object with filePath, or null if no match
11
11
  */
@@ -1 +1 @@
1
- {"version":3,"file":"filePathUtils.d.ts","sourceRoot":"","sources":["../../../../src/utils/paths/filePathUtils.js"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wCAHW,MAAM,GACJ,MAAM,GAAC,IAAI,CA0BvB;AAED;;;;GAIG;AACH,gDAHW,MAAM,GACJ,MAAM,GAAC,IAAI,CAkBvB;AAED;;;;;GAKG;AACH,sDAHW,MAAM,GACJ,MAAM,CAkBlB;AAED;;;;;;;GAOG;AACH,2CANW,MAAM,kBACN,MAAM,UACN,MAAM,sBAEJ;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAC,CAwCnD"}
1
+ {"version":3,"file":"filePathUtils.d.ts","sourceRoot":"","sources":["../../../../src/utils/paths/filePathUtils.js"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wCAHW,MAAM,GACJ,MAAM,GAAC,IAAI,CA0BvB;AAED;;;;GAIG;AACH,gDAHW,MAAM,GACJ,MAAM,GAAC,IAAI,CA0CvB;AAED;;;;;GAKG;AACH,sDAHW,MAAM,GACJ,MAAM,CAkBlB;AAED;;;;;;;GAOG;AACH,2CANW,MAAM,kBACN,MAAM,UACN,MAAM,sBAEJ;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAC,CAwCnD"}
@@ -4,7 +4,11 @@
4
4
  * For advanced use cases with bracket depth tracking and regex protection, use splitByComma directly.
5
5
  * @param {string} str - String to split
6
6
  * @param {string} [splitter] - Optional custom splitter (defaults to ',')
7
+ * @param {object} [options] - Options object
8
+ * @param {boolean} [options.protectVariables] - If true, protect ${} variables from splitting
7
9
  * @returns {string[]} Array of split strings
8
10
  */
9
- export function splitCsv(str: string, splitter?: string): string[];
11
+ export function splitCsv(str: string, splitter?: string, options?: {
12
+ protectVariables?: boolean;
13
+ }): string[];
10
14
  //# sourceMappingURL=splitCsv.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"splitCsv.d.ts","sourceRoot":"","sources":["../../../../src/utils/strings/splitCsv.js"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,8BAJW,MAAM,aACN,MAAM,GACJ,MAAM,EAAE,CA2BpB"}
1
+ {"version":3,"file":"splitCsv.d.ts","sourceRoot":"","sources":["../../../../src/utils/strings/splitCsv.js"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AACH,8BANW,MAAM,aACN,MAAM,YAEd;IAA0B,gBAAgB,GAAlC,OAAO;CACf,GAAU,MAAM,EAAE,CA+BpB"}