configorama 0.5.2 → 0.5.3

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.
@@ -1,3 +1,4 @@
1
+ const { findNestedVariables } = require('./find-nested-variables')
1
2
  /**
2
3
  * Convert variable into string
3
4
  * ${opt:foo} => 'opt:foo'
@@ -7,10 +8,37 @@
7
8
 
8
9
  const fileRefSyntax = RegExp(/^file\((~?[a-zA-Z0-9._\-\/,'" ]+?)\)/g)
9
10
  const funcRegex = /(\w+)\s*\(((?:[^()]+)*)?\s*\)\s*/
10
- module.exports = function cleanVariable(match, variableSyntax, simple) {
11
- const clean = match.replace(variableSyntax, (context, contents) => {
11
+ module.exports = function cleanVariable(match, variableSyntax, simple, caller) {
12
+ //console.log(`Clean input [${caller}]`, match)
13
+
14
+ let varToClean = match
15
+
16
+ /*
17
+ const nestedVar = findNestedVariables(match, variableSyntax)
18
+ console.log('nestedVarssss', nestedVar)
19
+ if (nestedVar.length > 1) {
20
+ const lastMatch = nestedVar[nestedVar.length - 1]
21
+ console.log(`Clean output nested [${caller}]`, lastMatch.variable)
22
+ return lastMatch.variable
23
+ console.log('lastMatch', lastMatch)
24
+ const matchIndex = lastMatch.varString.match(/__VAR_(\d+)__/)
25
+ console.log('matchIndex', matchIndex)
26
+ if (matchIndex) {
27
+ const index = parseInt(matchIndex[1])
28
+ console.log('index', index)
29
+ console.log('nestedVar', nestedVar)
30
+ console.log('nestedVar[index]', nestedVar[index])
31
+ varToClean = lastMatch.varString.replace(/__VAR_(\d+)__/g, nestedVar[index].fullMatch)
32
+ return varToClean
33
+ }
34
+ }
35
+ // process.exit(1)
36
+ /** */
37
+
38
+ const clean = varToClean.replace(variableSyntax, (context, contents) => {
12
39
  return contents.trim()
13
40
  })
41
+ //console.log(`Clean output [${caller}]`, clean)
14
42
  return clean
15
43
 
16
44
  // Support for simple variable cleaning with no space tweaks
@@ -0,0 +1,98 @@
1
+ const { test } = require('uvu')
2
+ const assert = require('uvu/assert')
3
+ const cleanVariable = require('./cleanVariable')
4
+
5
+ test('cleanVariable - simple variable syntax without nesting', () => {
6
+ // Setup
7
+ const variableSyntax = /\${([^{}]+?)}/g
8
+ const match = '${opt:foo}'
9
+
10
+ // Execute
11
+ const result = cleanVariable(match, variableSyntax, false, 'test')
12
+
13
+ // Verify
14
+ assert.is(result, 'opt:foo')
15
+ })
16
+
17
+ test.skip('cleanVariable - with nested variables', () => {
18
+ // Setup
19
+ const variableSyntax = /\${([^{}]+?)}/g
20
+ const match = '${var:${opt:stage}}'
21
+ const nestedVars = [
22
+ { varString: 'var:__VAR_1__', fullMatch: '${opt:stage}' },
23
+ { varString: 'opt:stage', fullMatch: '${opt:stage}' }
24
+ ]
25
+
26
+ // Execute
27
+ const result = cleanVariable(match, variableSyntax, false, 'test')
28
+
29
+ // Verify
30
+ assert.is(result, 'var:${opt:stage}')
31
+ })
32
+
33
+ test('cleanVariable - file reference with commas', () => {
34
+ // Setup
35
+ const variableSyntax = /\${([^{}]+?)}/g
36
+ const match = '${file(path/to/file.yml, key1, key2)}'
37
+
38
+ // Execute
39
+ const result = cleanVariable(match, variableSyntax, false, 'test')
40
+
41
+ // Verify
42
+ assert.is(result, 'file(path/to/file.yml, key1, key2)')
43
+ })
44
+
45
+ test('cleanVariable - function format', () => {
46
+ // Setup
47
+ const variableSyntax = /\${([^{}]+?)}/g
48
+ const match = '${someFunc(param1, param2)}'
49
+
50
+ // Execute
51
+ const result = cleanVariable(match, variableSyntax, false, 'test')
52
+
53
+ // Verify
54
+ assert.is(result, 'someFunc(param1, param2)')
55
+ })
56
+
57
+ test('cleanVariable - simple mode', () => {
58
+ // Setup
59
+ const variableSyntax = /\${([^{}]+?)}/g
60
+ const match = '${opt:foo with spaces}'
61
+
62
+ // Execute
63
+ const result = cleanVariable(match, variableSyntax, true, 'test')
64
+
65
+ // Verify
66
+ assert.is(result, 'opt:foo with spaces', 'Should preserve spaces in simple mode')
67
+ })
68
+
69
+ test('cleanVariable - whitespace handling outside quotes', () => {
70
+ // Setup
71
+ const variableSyntax = /\${([^{}]+?)}/g
72
+ const match = '${empty, "fallback value with space"}'
73
+
74
+ // Execute
75
+ const result = cleanVariable(match, variableSyntax, false, 'test')
76
+
77
+ // Verify
78
+ assert.is(result, 'empty, "fallback value with space"')
79
+ })
80
+
81
+ test.skip('cleanVariable - complex nested variables', () => {
82
+ // Setup
83
+ const variableSyntax = /\${([^{}]+?)}/g
84
+ const match = '${var:${opt:${stage}}}'
85
+ const nestedVars = [
86
+ { varString: 'var:__VAR_1__', fullMatch: '${opt:${stage}}' },
87
+ { varString: 'opt:__VAR_2__', fullMatch: '${stage}' },
88
+ { varString: 'stage', fullMatch: '${stage}' }
89
+ ]
90
+
91
+ // Execute
92
+ const result = cleanVariable(match, variableSyntax, false, 'test')
93
+
94
+ // Verify
95
+ assert.is(result, 'var:${opt:${stage}}')
96
+ })
97
+
98
+ test.run()
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Processes nested variable interpolations in a string and collects all matches
3
+ * @param {string} input - The input string containing variable interpolations
4
+ * @param {boolean} debug - Whether to print debug information
5
+ * @returns {Array} Array of match objects containing full match and captured group
6
+ */
7
+ function findNestedVariablesx(input, regex, debug = false) {
8
+ let str = input
9
+ let matches = []
10
+ let match
11
+ let iteration = 0
12
+
13
+ console.log('input', input)
14
+
15
+ if (debug) console.log(`Initial string: ${str}`)
16
+
17
+ // Process string until no more matches are found
18
+ while (true) {
19
+ iteration++
20
+ if (debug) console.log(`\nIteration ${iteration}:`)
21
+
22
+ // Reset regex index
23
+ regex.lastIndex = 0
24
+
25
+ // Find the next match
26
+ match = regex.exec(str)
27
+ if (!match) break
28
+
29
+ // Log match details if in debug mode
30
+ if (debug) {
31
+ console.log(`Match: ${match[0]}`)
32
+ console.log(`Captured group: ${match[1]}`)
33
+ }
34
+
35
+ // Store the match
36
+ matches.push({
37
+ fullMatch: match[0],
38
+ variable: match[1],
39
+ order: iteration
40
+ })
41
+
42
+ // Replace the match with placeholder
43
+ str = str.replace(regex, `__REPLACED_${iteration - 1}__`)
44
+ if (debug) console.log(`After replacement: ${str}`)
45
+ }
46
+
47
+ // Replace the `__REPLACED_${iteration - 1}__` with the original match
48
+ matches = matches.map((match, index) => {
49
+ const indexOfReplaced = match.fullMatch.match(/__REPLACED_(\d+)__/)
50
+ if (indexOfReplaced) {
51
+ const replacedIndex = parseInt(indexOfReplaced[1])
52
+ match.fullMatch = match.fullMatch.replace(`__REPLACED_${replacedIndex}__`, matches[replacedIndex].variable)
53
+ match.variable = match.variable.replace(`__REPLACED_${replacedIndex}__`, matches[replacedIndex].variable)
54
+ }
55
+ return match
56
+ })
57
+
58
+ if (debug) console.log(`\nTotal matches found: ${matches.length}`)
59
+ return matches
60
+ }
61
+
62
+ /**
63
+ * Finds all nested variable interpolations in a string while preserving original syntax
64
+ *
65
+ * This function handles complex nested variables like:
66
+ * ${file(./config.${opt:stage, ${defaultStage}}.json):CREDS}
67
+ *
68
+ * The returned matches will include:
69
+ * 1. innermost variables first (e.g., ${defaultStage})
70
+ * 2. middle variables next (e.g., ${opt:stage, ${defaultStage}})
71
+ * 3. outermost variables last (e.g., the entire expression)
72
+ *
73
+ * Each variable retains its original syntax even in nested form.
74
+ *
75
+ * @param {string} input - The input string containing variable interpolations
76
+ * @param {RegExp} regex - The regex pattern to match variables
77
+ * @param {boolean} debug - Whether to print debug information
78
+ * @returns {Array} Array of match objects with fullMatch, variable, varString and other properties
79
+ */
80
+ function findNestedVariables(input, regex, debug = false) {
81
+ // Create a copy of the input for replacement tracking
82
+ let workingString = input
83
+ // console.log('workingString', workingString)
84
+ // Store matches with their positions in the original string
85
+ let matches = []
86
+ // Track original positions and replacements
87
+ let replacements = []
88
+ let match
89
+ let iteration = 0
90
+
91
+ if (debug) console.log(`Initial string: ${input}`)
92
+
93
+ // First pass: Find all matches and create unique placeholders
94
+ while (true) {
95
+ iteration++
96
+ if (debug) console.log(`\nIteration ${iteration}:`)
97
+
98
+ // Reset regex index
99
+ regex.lastIndex = 0
100
+
101
+ // Find the next match in the working string
102
+ match = regex.exec(workingString)
103
+ if (!match) break
104
+
105
+ // Generate a unique placeholder
106
+ const placeholder = `__VAR_${iteration - 1}__`
107
+
108
+ // Store match details
109
+ const matchInfo = {
110
+ fullMatch: match[0],
111
+ variable: match[1],
112
+ order: iteration,
113
+ start: match.index,
114
+ end: match.index + match[0].length,
115
+ placeholder
116
+ }
117
+
118
+ if (debug) {
119
+ console.log(`Match: ${match[0]}`)
120
+ console.log(`Captured group: ${match[1]}`)
121
+ console.log(`Position: ${match.index}`)
122
+ }
123
+
124
+ matches.push(matchInfo)
125
+
126
+ // Store replacement info
127
+ replacements.push({
128
+ original: match[0],
129
+ placeholder,
130
+ start: match.index,
131
+ end: match.index + match[0].length
132
+ })
133
+
134
+ // Replace in working string (to find next match)
135
+ workingString = workingString.substring(0, match.index) +
136
+ placeholder +
137
+ workingString.substring(match.index + match[0].length)
138
+
139
+ if (debug) console.log(`After replacement: ${workingString}`)
140
+ }
141
+
142
+ if (debug) console.log(`\nTotal matches found: ${matches.length}`)
143
+
144
+ // We need to store varString - the variable string with placeholders
145
+ for (let i = 0; i < matches.length; i++) {
146
+ // First match, the variable is the same as varString
147
+ if (i === 0) {
148
+ matches[i].varString = matches[i].variable
149
+ } else {
150
+ // For other matches, we need to copy the original variable with placeholders
151
+ matches[i].varString = matches[i].variable
152
+ }
153
+ }
154
+
155
+ // Second pass: Reconstruct each variable with original nested syntax
156
+ // We need to do this recursively to ensure all placeholders are replaced properly
157
+ function replaceAllPlaceholders(text, matchesArray) {
158
+ let result = text
159
+ let needsAnotherPass = false
160
+
161
+ // Replace all placeholders with their original matches
162
+ for (let i = 0; i < matchesArray.length; i++) {
163
+ const m = matchesArray[i]
164
+ if (result.includes(m.placeholder)) {
165
+ result = result.replace(
166
+ new RegExp(m.placeholder, 'g'),
167
+ m.fullMatch
168
+ )
169
+ needsAnotherPass = true
170
+ }
171
+ }
172
+
173
+ // If we made replacements, we might need another pass to handle nested placeholders
174
+ if (needsAnotherPass) {
175
+ return replaceAllPlaceholders(result, matchesArray)
176
+ }
177
+
178
+ return result
179
+ }
180
+
181
+ // For each match, reconstruct the original nested syntax
182
+ for (let i = 0; i < matches.length; i++) {
183
+ const currentMatch = matches[i]
184
+
185
+ // Skip if this match doesn't contain any placeholders
186
+ if (!currentMatch.fullMatch.includes('__VAR_') && !currentMatch.variable.includes('__VAR_')) {
187
+ continue
188
+ }
189
+
190
+ // Reconstruct with all nested variables
191
+ currentMatch.fullMatch = replaceAllPlaceholders(currentMatch.fullMatch, matches)
192
+ currentMatch.variable = replaceAllPlaceholders(currentMatch.variable, matches)
193
+ }
194
+
195
+ if (debug) {
196
+ console.log("\nReconstructed matches:")
197
+ matches.forEach((m, i) => {
198
+ console.log(`Match #${i+1} (order ${m.order}):`)
199
+ console.log(`Full: ${m.fullMatch}`)
200
+ console.log(`Variable: ${m.variable}`)
201
+ console.log(`VarString: ${m.varString}`)
202
+ console.log(`Placeholder: ${m.placeholder}`)
203
+ })
204
+ }
205
+
206
+ return matches
207
+ }
208
+
209
+
210
+ // // Test with the example
211
+ // const regex = /\${((?!AWS|stageVariables)[ ~:a-zA-Z0-9=+!@#%*<>?._'",|\-\/\(\)\\]+?)}/g
212
+ // const input = '${file(./config.${opt:stage, ${defaultStage}}.json):CREDS}'
213
+
214
+ // // Run the function with debug output
215
+ // const result = findNestedVariables(input, regex, true)
216
+
217
+ // // Display final result
218
+ // console.log("\nFinal result:")
219
+ // console.log(JSON.stringify(result, null, 2))
220
+
221
+ // module.exports = {
222
+ // findNestedVariables
223
+ // }
224
+
225
+ module.exports = {
226
+ findNestedVariables
227
+ }
@@ -0,0 +1,99 @@
1
+ const { test } = require('uvu');
2
+ const assert = require('uvu/assert');
3
+ const { findNestedVariables } = require('./find-nested-variables');
4
+
5
+ // Define the regex pattern as used in the main function
6
+ const regex = /\${((?!AWS|stageVariables)[ ~:a-zA-Z0-9=+!@#%*<>?._'",|\-\/\(\)\\]+?)}/g;
7
+
8
+ test('findNestedVariables - simple variables', () => {
9
+ const input = '${simple}';
10
+ const result = findNestedVariables(input, regex);
11
+
12
+ assert.equal(result.length, 1);
13
+ assert.equal(result[0].fullMatch, '${simple}');
14
+ assert.equal(result[0].variable, 'simple');
15
+ assert.equal(result[0].order, 1);
16
+ });
17
+
18
+ test('findNestedVariables - complex variable with colon syntax', () => {
19
+ const input = '${opt:stage, dev}';
20
+ const result = findNestedVariables(input, regex);
21
+
22
+ assert.equal(result.length, 1);
23
+ assert.equal(result[0].fullMatch, '${opt:stage, dev}');
24
+ assert.equal(result[0].variable, 'opt:stage, dev');
25
+ });
26
+
27
+ test('findNestedVariables - one level nesting', () => {
28
+ const input = '${file(./config.${stage}.json)}';
29
+ const result = findNestedVariables(input, regex);
30
+
31
+ assert.equal(result.length, 2);
32
+ // The innermost variable should be found first
33
+ assert.equal(result[0].fullMatch, '${stage}');
34
+ assert.equal(result[0].variable, 'stage');
35
+ // Then the outer variable
36
+ assert.equal(result[1].fullMatch, '${file(./config.${stage}.json)}');
37
+ assert.equal(result[1].variable, 'file(./config.${stage}.json)');
38
+ });
39
+
40
+ test('findNestedVariables - two levels of nesting', () => {
41
+ const input = '${file(./config.${opt:stage, ${defaultStage}}.json):CREDS}';
42
+ const result = findNestedVariables(input, regex);
43
+
44
+ assert.equal(result.length, 3);
45
+ // Innermost first
46
+ assert.equal(result[0].fullMatch, '${defaultStage}');
47
+ assert.equal(result[0].variable, 'defaultStage');
48
+ // Middle next
49
+ assert.equal(result[1].fullMatch, '${opt:stage, ${defaultStage}}');
50
+ assert.equal(result[1].variable, 'opt:stage, ${defaultStage}');
51
+ // Outermost last
52
+ assert.equal(result[2].fullMatch, '${file(./config.${opt:stage, ${defaultStage}}.json):CREDS}');
53
+ assert.equal(result[2].variable, 'file(./config.${opt:stage, ${defaultStage}}.json):CREDS');
54
+ });
55
+
56
+ test('findNestedVariables - multiple separate variables', () => {
57
+ const input = 'Hello ${name}, welcome to ${service}!';
58
+ const result = findNestedVariables(input, regex);
59
+
60
+ assert.equal(result.length, 2);
61
+ assert.equal(result[0].fullMatch, '${name}');
62
+ assert.equal(result[1].fullMatch, '${service}');
63
+ });
64
+
65
+ test('findNestedVariables - complex mixed case', () => {
66
+ const input = '${db.${envOne}.host}:${db.${envTwo}.port} using ${credentials.${user.role}}';
67
+ const result = findNestedVariables(input, regex, true);
68
+ console.log('result', result)
69
+ assert.equal(result.length, 6);
70
+ // Check the correct nesting order
71
+ assert.equal(result[0].fullMatch, '${envOne}');
72
+ assert.equal(result[1].fullMatch, '${db.${envOne}.host}');
73
+ assert.equal(result[2].fullMatch, '${envTwo}');
74
+ assert.equal(result[3].fullMatch, '${db.${envTwo}.port}');
75
+ assert.equal(result[4].fullMatch, '${user.role}');
76
+ });
77
+
78
+ test('findNestedVariables - empty string', () => {
79
+ const input = '';
80
+ const result = findNestedVariables(input, regex);
81
+ assert.equal(result.length, 0);
82
+ });
83
+
84
+ test('findNestedVariables - string with no variables', () => {
85
+ const input = 'This is a string with no variables';
86
+ const result = findNestedVariables(input, regex);
87
+ assert.equal(result.length, 0);
88
+ });
89
+
90
+ test('findNestedVariables - varString property for nested variables', () => {
91
+ const input = '${file(./config.${opt:stage, ${defaultStage}}.json)}';
92
+ const result = findNestedVariables(input, regex);
93
+ console.log('result', result)
94
+ // Check varString property for the outermost variable
95
+ assert.equal(result[2].variable, 'file(./config.${opt:stage, ${defaultStage}}.json)');
96
+ });
97
+
98
+ // Run all tests
99
+ test.run();
@@ -1,6 +1,6 @@
1
- const { match } = require('../resolvers/valueFromString')
1
+ const stringResolver = require('../resolvers/valueFromString')
2
2
  const overwriteSyntax = RegExp(/\s*(?:,\s*)+/g) // /\s*(?:,\s*)+/g
3
- const stringRefSyntax = match
3
+ const stringRefSyntax = stringResolver.match
4
4
  /**
5
5
  * Split a given string by whitespace padded commas excluding those within single or double quoted
6
6
  * strings.
@@ -14,56 +14,68 @@ const stringRefSyntax = match
14
14
  // https://regex101.com/r/4uPmpt/1
15
15
  const commasOutsideOfParens = /(?!<(?:\(|\[)[^)\]]+),(?![^(\[]+(?:\)|\]))/
16
16
  // const commasOutOfParens = /(?!(?:\()[^)\]]+),(?![^(\[]+(?:\)))/g
17
- function splitByComma(string) {
18
- // If comma is not outside of parens, return early,
19
- // for file(file.js, param, paramTwo) & function support
20
- // TODO clean this up
21
- if (!string.match(commasOutsideOfParens)) {
22
- return [ string ]
17
+ function splitByComma(string, regexPattern) {
18
+ // Handle empty or undefined input
19
+ if (!string || string.trim() === "") {
20
+ return [""]
23
21
  }
24
- const input = string.trim()
25
- const stringMatches = []
26
- let match = stringRefSyntax.exec(input)
27
- while (match) {
28
- stringMatches.push({
29
- start: match.index,
30
- end: stringRefSyntax.lastIndex,
22
+
23
+ // Extract regex patterns to protect them
24
+ const placeholders = []
25
+ let protectedString = string
26
+ if (regexPattern) {
27
+ protectedString = string.replace(regexPattern, (match) => {
28
+ placeholders.push(match)
29
+ return `__PLACEHOLDER_${placeholders.length - 1}__`
31
30
  })
32
- match = stringRefSyntax.exec(input)
33
31
  }
34
- const commaReplacements = []
35
- const contained = (commaMatch) => { // curry the current commaMatch
36
- return (stringMatch) => { // check whether stringMatch containing the commaMatch
37
- return stringMatch.start < commaMatch.index && overwriteSyntax.lastIndex < stringMatch.end
32
+
33
+ const result = []
34
+ let current = ""
35
+ let inQuote = false
36
+ let quoteChar = ""
37
+ let bracketDepth = 0 // Includes both () and []
38
+
39
+ for (let i = 0; i < protectedString.length; i++) {
40
+ const char = protectedString[i]
41
+
42
+ // Handle quotes
43
+ if ((char === "'" || char === '"') && (i === 0 || protectedString[i-1] !== "\\")) {
44
+ if (!inQuote) {
45
+ inQuote = true
46
+ quoteChar = char
47
+ } else if (char === quoteChar) {
48
+ inQuote = false
49
+ }
38
50
  }
39
- }
40
- match = overwriteSyntax.exec(input)
41
- while (match) {
42
- const matchContained = contained(match)
43
- const containedBy = stringMatches.find(matchContained)
44
- if (!containedBy) { // if un-contained, this comma represents a splitting location
45
- commaReplacements.push({
46
- start: match.index,
47
- end: overwriteSyntax.lastIndex,
48
- })
51
+
52
+ // Handle parentheses and brackets
53
+ if ((char === "(" || char === "[") && !inQuote) bracketDepth++
54
+ if ((char === ")" || char === "]") && !inQuote) bracketDepth--
55
+
56
+ // Process comma
57
+ if (char === "," && !inQuote && bracketDepth === 0) {
58
+ result.push(current.trim())
59
+ current = ""
60
+ } else {
61
+ current += char
49
62
  }
50
- match = overwriteSyntax.exec(input)
51
63
  }
52
- let prior = 0
53
- const results = []
54
- commaReplacements.forEach((replacement) => {
55
- results.push(input.slice(prior, replacement.start))
56
- prior = replacement.end
64
+
65
+ if (current.trim() || result.length > 0) {
66
+ result.push(current.trim())
67
+ }
68
+
69
+ if (!regexPattern) {
70
+ return result
71
+ }
72
+
73
+ // Restore placeholders in the result
74
+ return result.map(item => {
75
+ return item.replace(/__PLACEHOLDER_(\d+)__/g, (match, index) => {
76
+ return placeholders[parseInt(index)]
77
+ })
57
78
  })
58
- // const what = input.slice(prior)
59
- // // TODO finish digit string matching
60
- // const matchDigitString = /^['|"]\d+['|"]$/g
61
- // if (what.match(matchDigitString)) {
62
- // console.log('Is digit string')
63
- // }
64
- // console.log('what', what)
65
- results.push(input.slice(prior))
66
- return results
67
79
  }
68
80
 
69
81
  module.exports = {
@@ -0,0 +1,84 @@
1
+ const { test } = require('uvu')
2
+ const assert = require('uvu/assert')
3
+ const { splitByComma } = require('./splitByComma')
4
+
5
+ const variableSyntax = /\${((?!AWS|stageVariables)[ ~:a-zA-Z0-9=+!@#%*<>?._'",|\-\/\(\)\\]+?)}/g
6
+
7
+ test('splitByComma - should return array with original string when no commas present', () => {
8
+ const result = splitByComma('singleString')
9
+ assert.equal(result, ['singleString'])
10
+ })
11
+
12
+ test('splitByComma - should split by comma and trim whitespace', () => {
13
+ const result = splitByComma('first, second, third')
14
+ assert.equal(result, ['first', 'second', 'third'])
15
+ })
16
+
17
+ test('splitByComma - should preserve quoted strings', () => {
18
+ const result = splitByComma("env:BAZ,'defaultEnvValue'")
19
+ assert.equal(result, ["env:BAZ", "'defaultEnvValue'"])
20
+ })
21
+
22
+ test('splitByComma - should not split commas inside parentheses', () => {
23
+ const result = splitByComma('file(file.js, param, paramTwo)')
24
+ assert.equal(result, ['file(file.js, param, paramTwo)'])
25
+ })
26
+
27
+ test('splitByComma - should not split commas inside square brackets', () => {
28
+ const result = splitByComma('array[item1, item2, item3]')
29
+ assert.equal(result, ['array[item1, item2, item3]'])
30
+ })
31
+
32
+ test('splitByComma - should handle multiple quoted strings', () => {
33
+ const result = splitByComma("'string one', 'string, with comma', \"double quoted\"")
34
+ assert.equal(result, ["'string one'", "'string, with comma'", "\"double quoted\""])
35
+ })
36
+
37
+ test('splitByComma - should handle empty input', () => {
38
+ const result = splitByComma('')
39
+ assert.equal(result, [''])
40
+ })
41
+
42
+ test('splitByComma - should handle input with extra whitespace', () => {
43
+ const result = splitByComma(' first , second , third ')
44
+ assert.equal(result, ['first', 'second', 'third'])
45
+ })
46
+
47
+ test('splitByComma - should handle mixed scenarios', () => {
48
+ const result = splitByComma("normal, 'quoted, string', function(param1, param2)")
49
+ console.log('result', result)
50
+ assert.equal(result, ["normal", "'quoted, string'", "function(param1, param2)"])
51
+ })
52
+
53
+ test('splitByComma - should handle nested parentheses', () => {
54
+ const result = splitByComma('outer(inner(a, b), c)')
55
+ assert.equal(result, ['outer(inner(a, b), c)'])
56
+ })
57
+
58
+ test('splitByComma - should handle nested square brackets', () => {
59
+ const result = splitByComma('matrix[[1, 2], [3, 4]]')
60
+ assert.equal(result, ['matrix[[1, 2], [3, 4]]'])
61
+ })
62
+
63
+ test('splitByComma - should handle combination of parentheses and brackets', () => {
64
+ const result = splitByComma('func(array[1, 2], obj.method(a, b))')
65
+ assert.equal(result, ['func(array[1, 2], obj.method(a, b))'])
66
+ })
67
+
68
+ test('splitByComma - should handle escaped quotes in strings', () => {
69
+ const result = splitByComma("normal, 'string with \\'escaped\\' quotes', \"double \\\"escaped\\\" quotes\"")
70
+ assert.equal(result, ["normal", "'string with \\'escaped\\' quotes'", "\"double \\\"escaped\\\" quotes\""])
71
+ })
72
+
73
+ test('splitByComma - should handle complex nested structures', () => {
74
+ const result = splitByComma('func(arg1, {key: [1, 2], other: "value, with comma"}, callback())')
75
+ assert.equal(result, ['func(arg1, {key: [1, 2], other: "value, with comma"}, callback())'])
76
+ })
77
+
78
+ test('splitByComma - should handle backtick quotes', () => {
79
+ const result = splitByComma("normal, `template ${with, commas} inside`", variableSyntax)
80
+ assert.equal(result, ["normal", "`template ${with, commas} inside`"])
81
+ })
82
+
83
+ // Run all tests
84
+ test.run()