configorama 0.4.6 → 0.4.8

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/lib/main.js CHANGED
@@ -77,6 +77,18 @@ class Configorama {
77
77
  allowUndefinedValues: false,
78
78
  }, options)
79
79
 
80
+
81
+ const defaultSyntax = '\\${((?!AWS)[ ~:a-zA-Z0-9=+!@#%*<>?._\'",|\\-\\/\\(\\)\\\\]+?)}'
82
+ const variableSyntax = options.syntax || defaultSyntax
83
+ let varRegex
84
+ if (typeof variableSyntax === 'string') {
85
+ varRegex = RegExp(variableSyntax, 'g')
86
+ // this.variableSyntax = /\${((?!AWS)([ ~:a-zA-Z0-9=+!@#%*<>?._'",|\-\/\(\)\\]+?|(\w+)\s*\(((?:[^()]+)*)?\s*\)\s*))}/
87
+ } else if (variableSyntax instanceof RegExp) {
88
+ varRegex = variableSyntax
89
+ }
90
+ this.variableSyntax = varRegex
91
+
80
92
  // Set initial config object to populate
81
93
  if (typeof fileOrObject === 'object') {
82
94
  // set config objects
@@ -94,11 +106,14 @@ class Configorama {
94
106
  let configObject
95
107
  if (fileType.match(/\.(yml|yaml)/)) {
96
108
  try {
97
- configObject = YAML.parse(fileContents)
109
+ const ymlText = YAML.preProcess(fileContents, varRegex)
110
+ // console.log('ymlText', ymlText)
111
+ configObject = YAML.parse(ymlText)
98
112
  } catch (err) {
99
113
  // Attempt to fix cloudformation refs
100
114
  if (err.message.match(/YAMLException/)) {
101
- const result = YAML.load(fileContents, {
115
+ const ymlText = YAML.preProcess(fileContents, varRegex)
116
+ const result = YAML.load(ymlText, {
102
117
  filename: fileOrObject,
103
118
  schema: cloudFormationSchema.schema
104
119
  })
@@ -140,16 +155,6 @@ class Configorama {
140
155
  // Track promise resolution
141
156
  this.tracker = new PromiseTracker()
142
157
 
143
- const defaultSyntax = '\\${((?!AWS)[ ~:a-zA-Z0-9=+!@#%*<>?._\'",|\\-\\/\\(\\)\\\\]+?)}'
144
- const variableSyntax = options.syntax || defaultSyntax
145
-
146
- if (typeof variableSyntax === 'string') {
147
- this.variableSyntax = RegExp(variableSyntax, 'g')
148
- // this.variableSyntax = /\${((?!AWS)([ ~:a-zA-Z0-9=+!@#%*<>?._'",|\-\/\(\)\\]+?|(\w+)\s*\(((?:[^()]+)*)?\s*\)\s*))}/
149
- } else if (variableSyntax instanceof RegExp) {
150
- this.variableSyntax = variableSyntax
151
- }
152
-
153
158
  // Variable Sources
154
159
  this.variableTypes = [
155
160
  /**
@@ -1671,7 +1676,7 @@ Please use ":" to reference sub properties`
1671
1676
 
1672
1677
  function findNestedVariable(split, originalSource) {
1673
1678
  return split.find((thing) => {
1674
- if (originalSource) {
1679
+ if (originalSource && typeof originalSource === 'string') {
1675
1680
  return originalSource.indexOf(`\${${thing}}`) > -1
1676
1681
  }
1677
1682
  return false
@@ -57,7 +57,128 @@ function toJson(ymlContents) {
57
57
  return json
58
58
  }
59
59
 
60
+ // TODO only works for default var syntax ${}. Maybe fix?
61
+ function findOutermostVariables(text) {
62
+ let matches = [];
63
+ let depth = 0;
64
+ let startIndex = -1;
65
+
66
+ for (let i = 0; i < text.length; i++) {
67
+ if (text[i] === '$' && text[i + 1] === '{') {
68
+ if (depth === 0) {
69
+ startIndex = i;
70
+ }
71
+ depth++;
72
+ i++; // Skip '{'
73
+ } else if (text[i] === '}') {
74
+ depth--;
75
+ if (depth === 0 && startIndex !== -1) {
76
+ matches.push(text.substring(startIndex, i + 1));
77
+ startIndex = -1;
78
+ }
79
+ }
80
+ }
81
+ return matches;
82
+ }
83
+
84
+
85
+ function matchOutermostBraces(text) {
86
+ let depth = 0;
87
+ let startIndex = -1;
88
+ let results = [];
89
+
90
+ for (let i = 0; i < text.length; i++) {
91
+ if (text[i] === '{') {
92
+ if (depth === 0) {
93
+ startIndex = i;
94
+ }
95
+ depth++;
96
+ } else if (text[i] === '}') {
97
+ depth--;
98
+ if (depth === 0 && startIndex !== -1) {
99
+ results.push(text.substring(startIndex, i + 1));
100
+ startIndex = -1;
101
+ }
102
+ }
103
+ }
104
+
105
+ return results;
106
+ }
107
+
108
+ function preProcess(ymlStr = '') {
109
+ /*
110
+ return ymlStr
111
+ /** */
112
+
113
+ // Fix nested variables in array brackets
114
+ // in -> y: !Not [!Equals [!Join ['', ${param:xyz}]]]
115
+ // out -> y: !Not [!Equals [!Join ['', "${param:xyz}"]]]
116
+ const arrayBracketMatches = ymlStr && ymlStr.match(
117
+ // /\[(?:[^\[\]]+|)*\]/gm
118
+ /\[(?:[^\[\]])*\]/g
119
+ )
120
+ if (arrayBracketMatches) {
121
+ // console.log('arrayBracketMatches', arrayBracketMatches)
122
+ arrayBracketMatches.forEach((txt) => {
123
+ // console.log('txt', txt)
124
+ const hasNestedVars = txt && findOutermostVariables(txt)
125
+ /*
126
+ console.log(varRegex)
127
+ console.log('findOutermostVariables(txt)', findOutermostVariables(txt))
128
+ console.log('hasNested', hasNested)
129
+ /** */
130
+ if (hasNestedVars && hasNestedVars.length) {
131
+ let fixedText = txt
132
+ hasNestedVars.forEach((nested) => {
133
+ // console.log('nested', nested)
134
+ if (txt.indexOf(`"${nested}"`) > -1) {
135
+ return
136
+ }
137
+ if (txt.indexOf(`'${nested}'`) > -1) {
138
+ return
139
+ }
140
+ /* Replace variable wrapped in quotes */
141
+ fixedText = fixedText.replace(nested, `"${nested}"`)
142
+ })
143
+ ymlStr = ymlStr.replace(txt, fixedText)
144
+ }
145
+ })
146
+ }
147
+
148
+ /* If have yaml object and vars not wrapped in quotes, wrap them */
149
+ if (ymlStr.match(/^[ \t]*[^:\n]*:\s*\{/gm)) {
150
+ const hasObjects = matchOutermostBraces(ymlStr)
151
+ // console.log('hasObjects', hasObjects)
152
+ if (hasObjects && hasObjects.length) {
153
+ hasObjects.forEach((txt) => {
154
+ // console.log('obj text', txt)
155
+ const hasNestedVars = txt && findOutermostVariables(txt)
156
+ if (hasNestedVars && hasNestedVars.length) {
157
+ let fixedText = txt
158
+ hasNestedVars.forEach((nested) => {
159
+ // console.log('nested', nested)
160
+ if (txt.indexOf(`"${nested}"`) > -1) {
161
+ return
162
+ }
163
+ if (txt.indexOf(`'${nested}'`) > -1) {
164
+ return
165
+ }
166
+ /* Replace variable wrapped in quotes */
167
+ fixedText = fixedText.replace(nested, `"${nested}"`)
168
+ })
169
+ ymlStr = ymlStr.replace(txt, fixedText)
170
+ }
171
+ })
172
+ }
173
+ }
174
+
175
+ // console.log('ymlStr', ymlStr)
176
+
177
+ return ymlStr
178
+ }
179
+
60
180
  module.exports = {
181
+ preProcess: preProcess,
61
182
  parse: parse,
62
183
  load: load,
63
184
  dump: dump,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "configorama",
3
- "version": "0.4.6",
3
+ "version": "0.4.8",
4
4
  "description": "Variable support for configuration files",
5
5
  "main": "lib/index.js",
6
6
  "files": [
@@ -31,18 +31,18 @@
31
31
  "dot-prop": "^5.3.0",
32
32
  "find-up": "^3.0.0",
33
33
  "git-url-parse": "^14.0.0",
34
- "js-yaml": "^3.14.0",
35
- "json5": "^2.1.3",
36
- "lodash": "^4.17.20",
37
- "promise.prototype.finally": "^3.1.2",
34
+ "js-yaml": "^3.14.1",
35
+ "json5": "^2.2.3",
36
+ "lodash": "^4.17.21",
37
+ "promise.prototype.finally": "^3.1.8",
38
38
  "replaceall": "^0.1.6",
39
39
  "sync-rpc": "^1.3.6",
40
- "traverse": "^0.6.6"
40
+ "traverse": "^0.6.8"
41
41
  },
42
42
  "devDependencies": {
43
- "ava": "^2.3.0",
44
- "markdown-magic": "^1.0.0",
45
- "minimist": "^1.2.5"
43
+ "ava": "^2.4.0",
44
+ "markdown-magic": "^2.6.1",
45
+ "minimist": "^1.2.8"
46
46
  },
47
47
  "ava": {
48
48
  "files": [