configorama 0.6.4 → 0.6.5

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.
@@ -0,0 +1,132 @@
1
+ const { test } = require('uvu')
2
+ const assert = require('uvu/assert')
3
+ const { _parseCronExpression } = require('./valueFromCron')
4
+
5
+ test('parseCronExpression: basic patterns', () => {
6
+ assert.equal(_parseCronExpression('every minute'), '* * * * *')
7
+ assert.equal(_parseCronExpression('every hour'), '0 * * * *')
8
+ assert.equal(_parseCronExpression('every day'), '0 0 * * *')
9
+ assert.equal(_parseCronExpression('daily'), '0 0 * * *')
10
+ assert.equal(_parseCronExpression('hourly'), '0 * * * *')
11
+ assert.equal(_parseCronExpression('yearly'), '0 0 1 1 *')
12
+ })
13
+
14
+ test('parseCronExpression: business patterns', () => {
15
+ assert.equal(_parseCronExpression('weekdays'), '0 0 * * 1-5')
16
+ assert.equal(_parseCronExpression('weekends'), '0 0 * * 0,6')
17
+ assert.equal(_parseCronExpression('business hours'), '0 9-17 * * 1-5')
18
+ })
19
+
20
+ test('parseCronExpression: interval patterns', () => {
21
+ assert.equal(_parseCronExpression('every 5 minutes'), '*/5 * * * *')
22
+ assert.equal(_parseCronExpression('every 15 minutes'), '*/15 * * * *')
23
+ assert.equal(_parseCronExpression('every 2 hours'), '0 */2 * * *')
24
+ assert.equal(_parseCronExpression('every 3 days'), '0 0 */3 * *')
25
+ assert.equal(_parseCronExpression('every 2 weeks'), '0 0 * * 0/2')
26
+ assert.equal(_parseCronExpression('every 6 months'), '0 0 1 */6 *')
27
+
28
+ // Test singular/plural forms
29
+ assert.equal(_parseCronExpression('every 1 minute'), '*/1 * * * *')
30
+ assert.equal(_parseCronExpression('every 1 hour'), '0 */1 * * *')
31
+ assert.equal(_parseCronExpression('every 1 day'), '0 0 */1 * *')
32
+ assert.equal(_parseCronExpression('every 1 week'), '0 0 * * 0/1')
33
+ assert.equal(_parseCronExpression('every 1 month'), '0 0 1 */1 *')
34
+
35
+ // Test plural forms
36
+ assert.equal(_parseCronExpression('every 5 minutes'), '*/5 * * * *')
37
+ assert.equal(_parseCronExpression('every 2 hours'), '0 */2 * * *')
38
+ assert.equal(_parseCronExpression('every 3 days'), '0 0 */3 * *')
39
+ assert.equal(_parseCronExpression('every 2 weeks'), '0 0 * * 0/2')
40
+ assert.equal(_parseCronExpression('every 6 months'), '0 0 1 */6 *')
41
+ })
42
+
43
+ test('parseCronExpression: simple interval patterns', () => {
44
+ // Test singular forms
45
+ assert.equal(_parseCronExpression('1 minute'), '*/1 * * * *')
46
+ assert.equal(_parseCronExpression('1 hour'), '0 */1 * * *')
47
+ assert.equal(_parseCronExpression('1 day'), '0 0 */1 * *')
48
+ assert.equal(_parseCronExpression('1 week'), '0 0 * * 0/1')
49
+ assert.equal(_parseCronExpression('1 month'), '0 0 1 */1 *')
50
+
51
+ // Test plural forms
52
+ assert.equal(_parseCronExpression('5 minutes'), '*/5 * * * *')
53
+ assert.equal(_parseCronExpression('2 hours'), '0 */2 * * *')
54
+ assert.equal(_parseCronExpression('3 days'), '0 0 */3 * *')
55
+ assert.equal(_parseCronExpression('2 weeks'), '0 0 * * 0/2')
56
+ assert.equal(_parseCronExpression('6 months'), '0 0 1 */6 *')
57
+ })
58
+
59
+ test('parseCronExpression: specific times', () => {
60
+ assert.equal(_parseCronExpression('at 9:30'), '30 9 * * *')
61
+ assert.equal(_parseCronExpression('at 14:15'), '15 14 * * *')
62
+ assert.equal(_parseCronExpression('at 9:30 am'), '30 9 * * *')
63
+ assert.equal(_parseCronExpression('at 9:30 pm'), '30 21 * * *')
64
+ assert.equal(_parseCronExpression('at 12:30 am'), '30 0 * * *')
65
+ assert.equal(_parseCronExpression('at 12:30 pm'), '30 12 * * *')
66
+ })
67
+
68
+ test('parseCronExpression: weekday + time patterns', () => {
69
+ assert.equal(_parseCronExpression('on monday at 9:00'), '0 9 * * 1', 'monday')
70
+ assert.equal(_parseCronExpression('on friday at 17:30'), '30 17 * * 5', 'friday')
71
+ assert.equal(_parseCronExpression('on sunday at 12:00'), '0 12 * * 0', 'sunday')
72
+ assert.equal(_parseCronExpression('on wednesday at 9:30 pm'), '30 21 * * 3', 'wednesday')
73
+ assert.equal(_parseCronExpression('on saturday,sunday at 12:00'), '0 12 * * 6,0', 'saturday,sunday')
74
+ const mwf = _parseCronExpression('on monday,wednesday,friday at 9:00')
75
+ console.log('mwf', mwf)
76
+ assert.equal(mwf, '0 9 * * 1,3,5', 'monday,wednesday,friday')
77
+ const tth = _parseCronExpression('on tuesday,thursday at 2:30 pm')
78
+ assert.equal(tth, '30 14 * * 2,4', 'tuesday,thursday')
79
+ const sst = _parseCronExpression('on saturday,sunday at 12:00')
80
+ assert.equal(sst, '0 12 * * 6,0', 'saturday,sunday')
81
+ })
82
+
83
+ test('parseCronExpression: ordinal dates of month', () => {
84
+ assert.equal(_parseCronExpression('on 1st of month at 00:00'), '0 0 1 * *')
85
+ assert.equal(_parseCronExpression('on 15th of month at 9:30 am'), '30 9 15 * *')
86
+ assert.equal(_parseCronExpression('on 31st of month at 2:00 pm'), '0 14 31 * *')
87
+ assert.equal(_parseCronExpression('on 2nd of month at 12:00'), '0 12 2 * *')
88
+ assert.equal(_parseCronExpression('on 3rd of month at 15:30'), '30 15 3 * *')
89
+ assert.equal(_parseCronExpression('on 4th of month at 12:00 am'), '0 0 4 * *')
90
+ })
91
+
92
+ test('parseCronExpression: case insensitive', () => {
93
+ assert.equal(_parseCronExpression('EVERY MINUTE'), '* * * * *')
94
+ assert.equal(_parseCronExpression('Weekdays'), '0 0 * * 1-5')
95
+ assert.equal(_parseCronExpression('At 9:30 PM'), '30 21 * * *')
96
+ assert.equal(_parseCronExpression('ON MONDAY AT 9:00'), '0 9 * * 1')
97
+ })
98
+
99
+ test('parseCronExpression: existing cron expressions pass through', () => {
100
+ assert.equal(_parseCronExpression('0 12 * * *'), '0 12 * * *')
101
+ assert.equal(_parseCronExpression('*/5 * * * *'), '*/5 * * * *')
102
+ //assert.equal(_parseCronExpression('@reboot'), '@reboot')
103
+ assert.equal(_parseCronExpression('15 2,14 * * *'), '15 2,14 * * *')
104
+ })
105
+
106
+ test('parseCronExpression: days of week', () => {
107
+ assert.equal(_parseCronExpression('monday'), '0 0 * * 1')
108
+ assert.equal(_parseCronExpression('tuesday'), '0 0 * * 2')
109
+ assert.equal(_parseCronExpression('wednesday'), '0 0 * * 3')
110
+ assert.equal(_parseCronExpression('thursday'), '0 0 * * 4')
111
+ assert.equal(_parseCronExpression('friday'), '0 0 * * 5')
112
+ assert.equal(_parseCronExpression('saturday'), '0 0 * * 6')
113
+ assert.equal(_parseCronExpression('sunday'), '0 0 * * 0')
114
+ })
115
+
116
+ test('parseCronExpression: special patterns', () => {
117
+ assert.equal(_parseCronExpression('first day of month'), '0 0 1 * *')
118
+ assert.equal(_parseCronExpression('middle of month'), '0 0 15 * *')
119
+ assert.equal(_parseCronExpression('never'), '0 0 30 2 *')
120
+ assert.equal(_parseCronExpression('reboot'), '@reboot')
121
+ assert.equal(_parseCronExpression('startup'), '@reboot')
122
+ })
123
+
124
+ test('parseCronExpression: error handling', () => {
125
+ assert.throws(() => _parseCronExpression(''), /must be a non-empty string/)
126
+ assert.throws(() => _parseCronExpression(null), /must be a non-empty string/)
127
+ assert.throws(() => _parseCronExpression(123), /must be a non-empty string/)
128
+ assert.throws(() => _parseCronExpression('invalid pattern'), /Unrecognized cron pattern/)
129
+ assert.throws(() => _parseCronExpression('every xyz'), /Unrecognized cron pattern/)
130
+ })
131
+
132
+ test.run()
@@ -0,0 +1,37 @@
1
+ // const evalRefSyntax = RegExp(/^eval\((~?[\{\}\:\${}a-zA=>+!-Z0-9._\-\/,'"\*\` ]+?)?\)/g)
2
+ const evalRefSyntax = RegExp(/^eval\((.*)?\)/g)
3
+
4
+ async function getValueFromEval(variableString) {
5
+ // console.log('getValueFromEval variableString', variableString)
6
+ // console.log('getValueFromEval variableString', variableString)
7
+ // Extract the expression inside eval()
8
+ const match = variableString.match(/^eval\((.+)\)$/)
9
+ // console.log('match', match)
10
+ if (!match) {
11
+ throw new Error(`Invalid eval syntax: ${variableString}. Expected format: eval(expression)`)
12
+ }
13
+
14
+ const expression = match[1].trim()
15
+ // console.log('expression', expression)
16
+
17
+ // Use "justin" variant to support strict comparison (===, !==) and other JS-like operators
18
+ try {
19
+ const { default: subscript } = await import('subscript/justin')
20
+
21
+ // Handle string comparisons by ensuring both sides are quoted
22
+ const processedExpression = expression.replace(/([a-zA-Z0-9_]+)\s*([=!<>]=?)\s*['"]([^'"]+)['"]/g, '"$1"$2"$3"')
23
+
24
+ // console.log('processedExpression', processedExpression)
25
+ const fn = subscript(processedExpression)
26
+ const result = fn()
27
+ return result
28
+ } catch (error) {
29
+ throw new Error(`Error evaluating expression "${expression}": ${error.message}`)
30
+ }
31
+ }
32
+
33
+ module.exports = {
34
+ type: 'eval',
35
+ match: evalRefSyntax,
36
+ resolver: getValueFromEval
37
+ }
@@ -0,0 +1,44 @@
1
+ const { test } = require('uvu')
2
+ const assert = require('uvu/assert')
3
+ const { resolver } = require('./valueFromEval')
4
+
5
+ test('Basic boolean evaluation - true', async () => {
6
+ const result = await resolver('eval(200 > 100)')
7
+ assert.is(result, true)
8
+ })
9
+
10
+ test('Basic boolean evaluation - false', async () => {
11
+ const result = await resolver('eval(100 > 200)')
12
+ assert.is(result, false)
13
+ })
14
+
15
+ test('Numeric evaluation', async () => {
16
+ const result = await resolver('eval(10 + 5)')
17
+ assert.is(result, 15)
18
+ })
19
+
20
+ test('String comparison', async () => {
21
+ const result = await resolver('eval("hello" == "hello")')
22
+ assert.is(result, true)
23
+ })
24
+
25
+ test('String comparison - strict', async () => {
26
+ const result = await resolver('eval("hello" === "hello")')
27
+ assert.is(result, true)
28
+ })
29
+
30
+ test('Complex boolean expression', async () => {
31
+ const result = await resolver('eval(100 > 50)')
32
+ assert.is(result, true)
33
+ })
34
+
35
+ test('Invalid syntax throws error', async () => {
36
+ try {
37
+ await resolver('eval(')
38
+ assert.unreachable('Should have thrown an error')
39
+ } catch (error) {
40
+ assert.ok(error.message.includes('Invalid eval syntax'))
41
+ }
42
+ })
43
+
44
+ test.run()
@@ -227,8 +227,9 @@ async function getGitTimestamp(_file, cwd, throwOnMissing = true) {
227
227
  // console.log('cwd', cwd)
228
228
  const output = await _exec(cmd, { cwd })
229
229
  const date = new Date(output)
230
- cache.set(file, date)
231
- return date.toISOString()
230
+ const dateString = date.toISOString()
231
+ cache.set(file, dateString)
232
+ return dateString
232
233
  } catch (err) {
233
234
  const projectRoot = findProjectRoot(cwd)
234
235
  if (!projectRoot) {
@@ -242,8 +243,9 @@ async function getGitTimestamp(_file, cwd, throwOnMissing = true) {
242
243
  const backupFile = path.join(projectRoot, _file)
243
244
  const output = await _exec(`git log -1 --pretty="%ai" ${backupFile}`, { cwd: projectRoot })
244
245
  const date = new Date(output)
245
- cache.set(file, date)
246
- return date.toISOString()
246
+ const dateString = date.toISOString()
247
+ cache.set(file, dateString)
248
+ return dateString
247
249
  } catch (err) {
248
250
  if (throwOnMissing) {
249
251
  throw new Error(`File ${file} does not exist in Git`)
package/src/types.d.ts ADDED
@@ -0,0 +1,112 @@
1
+ // Type definitions for configorama variable validation
2
+ // This file provides TypeScript support for validating configuration variables
3
+
4
+ // Valid variable prefixes supported by configorama
5
+ export type KnownVariablePrefix = 'env:' | 'opt:' | 'self:' | 'file:' | 'git:' | 'cron:'
6
+
7
+ // Quoted string literal type for fallback values
8
+ type QuotedString = `"${string}"` | `'${string}'`
9
+
10
+ // Helper to detect unknown variable prefixes (for validation)
11
+ type UnknownVariablePrefix<S extends string> = S extends `\${${string}:${string}}`
12
+ ? S extends `\${${KnownVariablePrefix}${string}}`
13
+ ? never
14
+ : S
15
+ : never
16
+
17
+ // Helper to exclude spaces or commas in the key section
18
+ type NoCommaOrSpace<S extends string> = S extends `${string} ${string}`
19
+ ? never
20
+ : S extends `${string},${string}`
21
+ ? never
22
+ : S
23
+
24
+ // Main prefix token that must not include spaces or commas
25
+ type PrefixedKey = NoCommaOrSpace<string>
26
+
27
+ // Helper for recursively building dot-prop paths from an object
28
+ export type ObjectPaths<T> = T extends object
29
+ ? {
30
+ [K in keyof T & string]: T[K] extends object ? `${K}` | `${K}.${ObjectPaths<T[K]>}` : `${K}`
31
+ }[keyof T & string]
32
+ : never
33
+
34
+ // Variables with fallback values (fully validated)
35
+ type PrefixedVariableWithFallbackNumber = `\${${KnownVariablePrefix}${PrefixedKey}, ${number}}`
36
+ type PrefixedVariableWithFallbackString = `\${${KnownVariablePrefix}${PrefixedKey}, ${QuotedString}}`
37
+ type PrefixedVariableWithFallbackBoolean = `\${${KnownVariablePrefix}${PrefixedKey}, ${boolean}}`
38
+
39
+ // Variables without fallback values (prefix-only)
40
+ type PrefixedVariableNoFallback = `\${${KnownVariablePrefix}${PrefixedKey}}`
41
+
42
+ // Self-reference (dot-prop) variables
43
+ type SelfReferenceVariable<Root> = `\${${ObjectPaths<Root>}}`
44
+
45
+ // Generic dot-prop variables (non-typed)
46
+ type GenericDotPropVariable = `\${${string}.${string}}`
47
+
48
+ // Union of all variable styles supported – narrowed by the primitive type T
49
+ export type VariableToken<T, Root> = T extends string
50
+ ? PrefixedVariableWithFallbackString | PrefixedVariableNoFallback | SelfReferenceVariable<Root> | GenericDotPropVariable
51
+ : T extends number
52
+ ? PrefixedVariableWithFallbackNumber | PrefixedVariableNoFallback | SelfReferenceVariable<Root> | GenericDotPropVariable
53
+ : T extends boolean
54
+ ? PrefixedVariableWithFallbackBoolean | PrefixedVariableNoFallback | SelfReferenceVariable<Root> | GenericDotPropVariable
55
+ : never
56
+
57
+ // Resolution rule for primitive types
58
+ export type ResolvedPrimitive<T, Root> = T extends string
59
+ ? T | VariableToken<T, Root>
60
+ : T | VariableToken<T, Root>
61
+
62
+ // Recursively resolve all values in an object tree
63
+ export type DeepResolved<T, Root = T> = T extends object
64
+ ? { [K in keyof T]: DeepResolved<T[K], Root> }
65
+ : ResolvedPrimitive<T, Root>
66
+
67
+ // Generic configuration resolver function type
68
+ export type ConfigResolver<T> = (config: DeepResolved<T>) => DeepResolved<T>
69
+
70
+ // Example usage with a custom config interface:
71
+ /*
72
+ interface MyConfig {
73
+ database: {
74
+ host: string
75
+ port: number
76
+ ssl: boolean
77
+ }
78
+ api: {
79
+ baseUrl: string
80
+ timeout: number
81
+ }
82
+ }
83
+
84
+ // This type allows variables in your config while maintaining type safety
85
+ type ResolvedMyConfig = DeepResolved<MyConfig>
86
+
87
+ // Usage example:
88
+ const config: ResolvedMyConfig = {
89
+ database: {
90
+ host: '${env:DB_HOST, "localhost"}', // ✅ String with quoted fallback
91
+ port: '${env:DB_PORT, 5432}', // ✅ Number with unquoted fallback
92
+ ssl: '${env:SSL_ENABLED, false}' // ✅ Boolean with unquoted fallback
93
+ },
94
+ api: {
95
+ baseUrl: '${env:API_URL}', // ✅ Variable without fallback
96
+ timeout: '${api.defaultTimeout}' // ✅ Dot-prop reference
97
+ }
98
+ }
99
+
100
+ // These would cause TypeScript errors:
101
+ const badConfig: ResolvedMyConfig = {
102
+ database: {
103
+ host: '${env:DB_HOST, localhost}', // ❌ Unquoted string fallback
104
+ port: '${env:DB_PORT, "5432"}', // ❌ Quoted number fallback
105
+ ssl: '${env:SSL_ENABLED, "false"}' // ❌ Quoted boolean fallback
106
+ },
107
+ api: {
108
+ baseUrl: '${unknownPrefix:API_URL}', // ❌ Unknown variable prefix
109
+ timeout: 5000
110
+ }
111
+ }
112
+ */
@@ -1,4 +1,6 @@
1
1
  const { findNestedVariables } = require('./find-nested-variables')
2
+
3
+ const DEBUG = false
2
4
  /**
3
5
  * Convert variable into string
4
6
  * ${opt:foo} => 'opt:foo'
@@ -8,8 +10,20 @@ const { findNestedVariables } = require('./find-nested-variables')
8
10
 
9
11
  const fileRefSyntax = RegExp(/^file\((~?[a-zA-Z0-9._\-\/,'" ]+?)\)/g)
10
12
  const funcRegex = /(\w+)\s*\(((?:[^()]+)*)?\s*\)\s*/
11
- module.exports = function cleanVariable(match, variableSyntax, simple, caller) {
12
- //console.log(`Clean input [${caller}]`, match)
13
+ module.exports = function cleanVariable(
14
+ match,
15
+ variableSyntax,
16
+ simple,
17
+ caller,
18
+ recursive = false,
19
+ ) {
20
+ if (DEBUG) {
21
+ console.log(`Clean input [${caller}]`, match)
22
+ }
23
+
24
+ // const outermostMatch = removeOuterMostBraces(match)
25
+ // console.log('outermostMatch', outermostMatch)
26
+ // return outermostMatch
13
27
 
14
28
  let varToClean = match
15
29
 
@@ -38,7 +52,13 @@ module.exports = function cleanVariable(match, variableSyntax, simple, caller) {
38
52
  const clean = varToClean.replace(variableSyntax, (context, contents) => {
39
53
  return contents.trim()
40
54
  })
41
- //console.log(`Clean output [${caller}]`, clean)
55
+
56
+ // if (recursive && clean.match(variableSyntax)) {
57
+ // return cleanVariable(clean, variableSyntax, simple, caller, true)
58
+ // }
59
+ if (DEBUG) {
60
+ console.log(`Clean output [${caller}]`, clean)
61
+ }
42
62
  return clean
43
63
 
44
64
  // Support for simple variable cleaning with no space tweaks
@@ -62,3 +82,47 @@ module.exports = function cleanVariable(match, variableSyntax, simple, caller) {
62
82
  // ^ trim White Space OutSide Quotes https://regex101.com/r/BuBNPN/1
63
83
  // Needed for fallback values with spaces. ${empty, 'fallback value with space'}
64
84
  }
85
+
86
+
87
+ function findOutermostBraces(str) {
88
+ const matches = []
89
+ let i = 0
90
+
91
+ while (i < str.length) {
92
+ if (str.substring(i, i + 2) === '${') {
93
+ let braceCount = 1
94
+ let start = i
95
+ i += 2
96
+
97
+ while (i < str.length && braceCount > 0) {
98
+ if (str[i] === '{') braceCount++
99
+ else if (str[i] === '}') braceCount--
100
+ i++
101
+ }
102
+
103
+ if (braceCount === 0) {
104
+ matches.push(str.substring(start, i))
105
+ }
106
+ } else {
107
+ i++
108
+ }
109
+ }
110
+
111
+ return matches
112
+ }
113
+
114
+ /**
115
+ * Removes the outermost ${} from a string
116
+ * @param {string} str - The input string containing ${} syntax
117
+ * @returns {string} The string with outermost ${} removed
118
+ * @example
119
+ * removeOuterMostBraces('${eval(${self:three} > ${self:four})}')
120
+ * // returns 'eval(${self:three} > ${self:four})'
121
+ */
122
+ function removeOuterMostBraces(str) {
123
+ const matches = findOutermostBraces(str)
124
+ if (matches.length === 0) return str
125
+
126
+ const outermostMatch = matches[0]
127
+ return outermostMatch.slice(2, -1)
128
+ }
@@ -0,0 +1,23 @@
1
+ const path = require('path')
2
+ const chalk = require('./chalk')
3
+
4
+ /**
5
+ * Creates a hyperlink for the default editor (Cursor/VS Code)
6
+ * @param {string} filePath - The file path to link to
7
+ * @param {number} line - Line number (default: 1)
8
+ * @param {number} column - Column number (default: 1)
9
+ * @param {string} customDisplay - Custom display text (default: filename:line)
10
+ * @param {string} color - Chalk color for the link (default: 'cyanBright')
11
+ * @returns {string} The hyperlink string
12
+ */
13
+ function createEditorLink(filePath, line = 1, column = 1, customDisplay = null, color = 'cyanBright') {
14
+ const absolutePath = path.resolve(filePath)
15
+ const url = `cursor://file${absolutePath}:${line}:${column}`
16
+ const display = customDisplay ? customDisplay: `${path.basename(filePath)}:${line}`
17
+
18
+ return `\x1b]8;;${url}\x1b\\${chalk[color](display)}\x1b]8;;\x1b\\`
19
+ }
20
+
21
+ module.exports = {
22
+ createEditorLink
23
+ }
@@ -193,7 +193,16 @@ function findNestedVariables(input, regex, variablesKnownTypes, location, debug
193
193
  fallbackData.stringValue = trimQuotes(item)
194
194
  fallbackData.isResolvedFallback = true
195
195
  }
196
-
196
+
197
+ if (isVariable) {
198
+ const varType = item.match(variablesKnownTypes)[1]
199
+ fallbackData.varType = varType
200
+ // if (varType === 'self:') {
201
+ // fallbackData.fullMatch = item.replace('self:', '')
202
+ // fallbackData.variable = item.replace('self:', '')
203
+ // fallbackData.varType = 'dot.prop'
204
+ // }
205
+ }
197
206
  return fallbackData
198
207
  })
199
208
  }
package/src/utils/logs.js CHANGED
@@ -5,7 +5,8 @@ function logHeader(message) {
5
5
  text: message,
6
6
  rightBorder: true,
7
7
  minWidth: 80,
8
- textStyle: 'normal',
8
+ textStyle: 'bold',
9
+ borderStyle: 'bold',
9
10
  borderColor: 'cyanBright',
10
11
  }))
11
12
  }
@@ -1,5 +1,8 @@
1
1
  const YAML = require('../parsers/yaml')
2
2
  const TOML = require('../parsers/toml')
3
+ const INI = require('../parsers/ini')
4
+ const { executeTypeScriptFileSync } = require('../parsers/typescript')
5
+ const { executeESMFileSync } = require('../parsers/esm')
3
6
  const cloudFormationSchema = require('./cloudformationSchema')
4
7
 
5
8
  /**
@@ -34,6 +37,8 @@ function parseFileContents(fileContents, fileType, filePath, varRegex, opts = {}
34
37
  }
35
38
  } else if (fileType.match(/\.(toml)/)) {
36
39
  configObject = TOML.parse(fileContents)
40
+ } else if (fileType.match(/\.(ini)/)) {
41
+ configObject = INI.parse(fileContents)
37
42
  } else if (fileType.match(/\.(json)/)) {
38
43
  configObject = JSON.parse(fileContents)
39
44
  } else if (fileType.match(/\.(js)/)) {
@@ -47,11 +52,46 @@ function parseFileContents(fileContents, fileType, filePath, varRegex, opts = {}
47
52
  if (jsArgs && typeof jsArgs === 'function') {
48
53
  jsArgs = jsArgs()
49
54
  }
55
+ // console.log('jsArgs', jsArgs)
50
56
  configObject = jsFile(jsArgs)
51
57
  }
52
58
  } catch (err) {
53
59
  throw new Error(err)
54
60
  }
61
+ } else if (fileType.match(/\.(ts|tsx)/)) {
62
+ try {
63
+ let jsArgs = opts.dynamicArgs || {}
64
+ if (jsArgs && typeof jsArgs === 'function') {
65
+ jsArgs = jsArgs()
66
+ }
67
+ configObject = executeTypeScriptFileSync(filePath, opts)
68
+ if (configObject.config) {
69
+ configObject = (typeof configObject.config === 'function') ? configObject.config(jsArgs) : configObject.config
70
+ } else if (configObject.default) {
71
+ configObject = (typeof configObject.default === 'function') ? configObject.default(jsArgs) : configObject.default
72
+ }
73
+ // console.log('parseFileContents configObject', configObject, opts)
74
+ } catch (err) {
75
+ throw new Error(`Failed to execute TypeScript file ${filePath}: ${err.message}`)
76
+ }
77
+ } else if (fileType.match(/\.(mjs|esm)/)) {
78
+ try {
79
+ let jsArgs = opts.dynamicArgs || {}
80
+ if (jsArgs && typeof jsArgs === 'function') {
81
+ jsArgs = jsArgs()
82
+ }
83
+ configObject = executeESMFileSync(filePath, opts)
84
+ if (configObject.config) {
85
+ configObject = (typeof configObject.config === 'function') ? configObject.config(jsArgs) : configObject.config
86
+ } else if (configObject.default) {
87
+ configObject = (typeof configObject.default === 'function') ? configObject.default(jsArgs) : configObject.default
88
+ } else if (typeof configObject === 'function') {
89
+ configObject = configObject(jsArgs)
90
+ }
91
+ // console.log('parseFileContents ESM configObject', configObject, opts)
92
+ } catch (err) {
93
+ throw new Error(`Failed to execute ESM file ${filePath}: ${err.message}`)
94
+ }
55
95
  }
56
96
 
57
97
  return configObject