configorama 0.6.14 → 0.6.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/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "configorama",
3
- "version": "0.6.14",
3
+ "version": "0.6.16",
4
4
  "description": "Variable support for configuration files",
5
5
  "main": "src/index.js",
6
6
  "types": "index.d.ts",
7
+ "exports": {
8
+ ".": "./src/index.js",
9
+ "./parse-file": "./src/utils/parsing/parse.js"
10
+ },
7
11
  "files": [
8
12
  "cli.js",
9
13
  "src",
package/src/main.js CHANGED
@@ -549,13 +549,12 @@ class Configorama {
549
549
 
550
550
  // If we have a file path but no config yet, parse it now
551
551
  if (this.configFilePath && !this.config) {
552
- let configObject = await parseFileContents(
553
- this.originalString,
554
- this.configFileType,
555
- this.configFilePath,
556
- this.variableSyntax,
557
- this.opts
558
- )
552
+ let configObject = await parseFileContents({
553
+ contents: this.originalString,
554
+ filePath: this.configFilePath,
555
+ varRegex: this.variableSyntax,
556
+ dynamicArgs: this.opts.dynamicArgs
557
+ })
559
558
  this.configFileContents = ''
560
559
  if (VERBOSE || showFoundVariables || this.opts.returnPreResolvedVariableDetails || SETUP_MODE) {
561
560
  this.configFileContents = fs.readFileSync(this.configFilePath, 'utf8')
@@ -1,3 +1,6 @@
1
+ // Parses config file contents based on file extension
2
+ const fs = require('fs')
3
+ const path = require('path')
1
4
  const YAML = require('../../parsers/yaml')
2
5
  const TOML = require('../../parsers/toml')
3
6
  const INI = require('../../parsers/ini')
@@ -6,26 +9,34 @@ const { executeTypeScriptFileSync } = require('../../parsers/typescript')
6
9
  const { executeESMFileSync } = require('../../parsers/esm')
7
10
  const cloudFormationSchema = require('./cloudformationSchema')
8
11
 
12
+ const DEFAULT_VAR_SYNTAX = '\\${((?!AWS|stageVariables)[ ~:a-zA-Z0-9=+!@#%*<>?._\'",|\\-\\/\\(\\)\\\\]+?)}'
13
+
14
+ /**
15
+ * @typedef {Object} ParseOptions
16
+ * @property {string} contents - Raw file contents to parse
17
+ * @property {string} filePath - Full file path (used for extension detection and error messages)
18
+ * @property {RegExp} [varRegex] - Variable syntax regex (defaults to configorama syntax)
19
+ * @property {Object|Function} [dynamicArgs] - Arguments passed to JS/TS function exports
20
+ */
21
+
9
22
  /**
10
23
  * Parse file contents based on file extension
11
- * @param {string} fileContents - Raw file contents to parse
12
- * @param {string} fileType - File extension (.yml, .yaml, .json, etc)
13
- * @param {string} filePath - Full file path (used for error messages)
14
- * @param {RegExp} varRegex - Variable syntax regex
15
- * @param {Object} opts - Additional options
24
+ * @param {ParseOptions} options
16
25
  * @returns {Object} Parsed configuration object
17
26
  */
18
- function parseFileContents(fileContents, fileType, filePath, varRegex, opts = {}) {
27
+ function parseFileContents({ contents, filePath, varRegex, dynamicArgs }) {
28
+ const fileType = path.extname(filePath)
29
+ const regex = varRegex || new RegExp(DEFAULT_VAR_SYNTAX, 'g')
19
30
  let configObject
20
31
 
21
32
  if (fileType.match(/\.(yml|yaml)/i)) {
22
33
  try {
23
- const ymlText = YAML.preProcess(fileContents, varRegex)
34
+ const ymlText = YAML.preProcess(contents, regex)
24
35
  configObject = YAML.parse(ymlText)
25
36
  } catch (err) {
26
37
  // Attempt to fix cloudformation refs
27
38
  if (err.message.match(/YAMLException/)) {
28
- const ymlText = YAML.preProcess(fileContents, varRegex)
39
+ const ymlText = YAML.preProcess(contents, regex)
29
40
  const result = YAML.load(ymlText, {
30
41
  filename: filePath,
31
42
  schema: cloudFormationSchema.schema,
@@ -37,11 +48,11 @@ function parseFileContents(fileContents, fileType, filePath, varRegex, opts = {}
37
48
  }
38
49
  }
39
50
  } else if (fileType.match(/\.(toml|tml)/i)) {
40
- configObject = TOML.parse(fileContents)
51
+ configObject = TOML.parse(contents)
41
52
  } else if (fileType.match(/\.(ini)/i)) {
42
- configObject = INI.parse(fileContents)
53
+ configObject = INI.parse(contents)
43
54
  } else if (fileType.match(/\.(json|json5)/i)) {
44
- configObject = JSON5.parse(fileContents)
55
+ configObject = JSON5.parse(contents)
45
56
  // TODO detect js syntax and use appropriate parser
46
57
  } else if (fileType.match(/\.(js|cjs)/i)) {
47
58
  let jsFile
@@ -50,7 +61,7 @@ function parseFileContents(fileContents, fileType, filePath, varRegex, opts = {}
50
61
  if (typeof jsFile !== 'function') {
51
62
  configObject = jsFile
52
63
  } else {
53
- let jsArgs = opts.dynamicArgs || {}
64
+ let jsArgs = dynamicArgs || {}
54
65
  if (jsArgs && typeof jsArgs === 'function') {
55
66
  jsArgs = jsArgs()
56
67
  }
@@ -62,27 +73,27 @@ function parseFileContents(fileContents, fileType, filePath, varRegex, opts = {}
62
73
  }
63
74
  } else if (fileType.match(/\.(ts|tsx|mts|cts)/i)) {
64
75
  try {
65
- let jsArgs = opts.dynamicArgs || {}
76
+ let jsArgs = dynamicArgs || {}
66
77
  if (jsArgs && typeof jsArgs === 'function') {
67
78
  jsArgs = jsArgs()
68
79
  }
69
- configObject = executeTypeScriptFileSync(filePath, opts)
80
+ configObject = executeTypeScriptFileSync(filePath, { dynamicArgs })
70
81
  if (configObject.config) {
71
82
  configObject = (typeof configObject.config === 'function') ? configObject.config(jsArgs) : configObject.config
72
83
  } else if (configObject.default) {
73
84
  configObject = (typeof configObject.default === 'function') ? configObject.default(jsArgs) : configObject.default
74
85
  }
75
- // console.log('parseFileContents configObject', configObject, opts)
86
+ // console.log('parseFileContents configObject', configObject)
76
87
  } catch (err) {
77
88
  throw new Error(`Failed to execute TypeScript file ${filePath}: ${err.message}`)
78
89
  }
79
90
  } else if (fileType.match(/\.(mjs|esm)/i)) {
80
91
  try {
81
- let jsArgs = opts.dynamicArgs || {}
92
+ let jsArgs = dynamicArgs || {}
82
93
  if (jsArgs && typeof jsArgs === 'function') {
83
94
  jsArgs = jsArgs()
84
95
  }
85
- configObject = executeESMFileSync(filePath, opts)
96
+ configObject = executeESMFileSync(filePath, { dynamicArgs })
86
97
  if (configObject.config) {
87
98
  configObject = (typeof configObject.config === 'function') ? configObject.config(jsArgs) : configObject.config
88
99
  } else if (configObject.default) {
@@ -90,7 +101,7 @@ function parseFileContents(fileContents, fileType, filePath, varRegex, opts = {}
90
101
  } else if (typeof configObject === 'function') {
91
102
  configObject = configObject(jsArgs)
92
103
  }
93
- // console.log('parseFileContents ESM configObject', configObject, opts)
104
+ // console.log('parseFileContents ESM configObject', configObject)
94
105
  } catch (err) {
95
106
  throw new Error(`Failed to execute ESM file ${filePath}: ${err.message}`)
96
107
  }
@@ -99,6 +110,29 @@ function parseFileContents(fileContents, fileType, filePath, varRegex, opts = {}
99
110
  return configObject
100
111
  }
101
112
 
113
+ /**
114
+ * @typedef {Object} ParseFileOptions
115
+ * @property {RegExp} [varRegex] - Variable syntax regex (defaults to configorama syntax)
116
+ * @property {Object|Function} [dynamicArgs] - Arguments passed to JS/TS function exports
117
+ */
118
+
119
+ /**
120
+ * Read and parse a config file
121
+ * @param {string} filePath - Path to the config file
122
+ * @param {ParseFileOptions} [opts]
123
+ * @returns {Object} Parsed configuration object
124
+ */
125
+ function parseFile(filePath, opts = {}) {
126
+ const contents = fs.readFileSync(filePath, 'utf8')
127
+ return parseFileContents({
128
+ contents,
129
+ filePath,
130
+ varRegex: opts.varRegex,
131
+ dynamicArgs: opts.dynamicArgs
132
+ })
133
+ }
134
+
102
135
  module.exports = {
103
- parseFileContents
104
- }
136
+ parseFileContents,
137
+ parseFile
138
+ }