configorama 0.7.2 → 0.9.0
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/README.md +193 -13
- package/cli.js +3 -1
- package/index.d.ts +36 -3
- package/package.json +1 -1
- package/src/index.js +15 -2
- package/src/main.js +129 -47
- package/src/resolvers/valueFromFile.js +7 -1
- package/src/resolvers/valueFromParam.js +91 -0
- package/src/resolvers/valueFromParam.test.js +207 -0
- package/src/utils/PromiseTracker.js +54 -0
- package/src/utils/variables/variableUtils.js +54 -1
- package/src/utils/variables/variableUtils.test.js +44 -0
- package/types/src/index.d.ts +4 -2
- package/types/src/index.d.ts.map +1 -1
- package/types/src/main.d.ts +18 -0
- package/types/src/main.d.ts.map +1 -1
- package/types/src/resolvers/valueFromFile.d.ts.map +1 -1
- package/types/src/resolvers/valueFromParam.d.ts +19 -0
- package/types/src/resolvers/valueFromParam.d.ts.map +1 -0
- package/types/src/utils/PromiseTracker.d.ts +4 -0
- package/types/src/utils/PromiseTracker.d.ts.map +1 -1
- package/types/src/utils/variables/variableUtils.d.ts +9 -0
- package/types/src/utils/variables/variableUtils.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -29,14 +29,18 @@ See [tests](https://github.com/DavidWells/configorama/tree/master/tests) for mor
|
|
|
29
29
|
<summary>Click to expand</summary>
|
|
30
30
|
|
|
31
31
|
- [About](#about)
|
|
32
|
-
- [How it works](#how-it-works)
|
|
33
32
|
- [Usage](#usage)
|
|
33
|
+
- [How it works](#how-it-works)
|
|
34
34
|
- [Variable Sources](#variable-sources)
|
|
35
35
|
- [Environment variables](#environment-variables)
|
|
36
36
|
- [CLI option flags](#cli-option-flags)
|
|
37
|
+
- [Parameter values](#parameter-values)
|
|
37
38
|
- [Self references](#self-references)
|
|
38
39
|
- [File references](#file-references)
|
|
39
40
|
- [Sync/Async file references](#syncasync-file-references)
|
|
41
|
+
- [Passing arguments to functions](#passing-arguments-to-functions)
|
|
42
|
+
- [ConfigContext](#configcontext)
|
|
43
|
+
- [Functions without arguments](#functions-without-arguments)
|
|
40
44
|
- [TypeScript file references](#typescript-file-references)
|
|
41
45
|
- [Git references](#git-references)
|
|
42
46
|
- [Cron Values](#cron-values)
|
|
@@ -45,7 +49,11 @@ See [tests](https://github.com/DavidWells/configorama/tree/master/tests) for mor
|
|
|
45
49
|
- [Functions (experimental)](#functions-experimental)
|
|
46
50
|
- [More Examples](#more-examples)
|
|
47
51
|
- [Custom Variable Sources](#custom-variable-sources)
|
|
52
|
+
- [Variable Source Types](#variable-source-types)
|
|
48
53
|
- [Options](#options)
|
|
54
|
+
- [Custom Variable Syntax](#custom-variable-syntax)
|
|
55
|
+
- [allowUnknownVariableTypes](#allowunknownvariabletypes)
|
|
56
|
+
- [allowUnresolvedVariables](#allowunresolvedvariables)
|
|
49
57
|
- [FAQ](#faq)
|
|
50
58
|
- [Whats new](#whats-new)
|
|
51
59
|
- [Alt libs](#alt-libs)
|
|
@@ -136,6 +144,7 @@ console.log(result.resolutionHistory) // Step-by-step resolution for each path
|
|
|
136
144
|
|----------|-----------------------|------------------------|
|
|
137
145
|
| env | ${env:VAR} | Environment variables |
|
|
138
146
|
| opt | ${opt:flag} | CLI option flags |
|
|
147
|
+
| param | ${param:key} | Parameter values |
|
|
139
148
|
| self | ${key} or ${self:key} | Self references |
|
|
140
149
|
| file | ${file(path)} | File references |
|
|
141
150
|
| git | ${git:value} | Git data |
|
|
@@ -168,6 +177,58 @@ foo: ${opt:stage}-hello
|
|
|
168
177
|
foo: ${opt:stage, 'dev'}
|
|
169
178
|
```
|
|
170
179
|
|
|
180
|
+
### Parameter values
|
|
181
|
+
|
|
182
|
+
Access parameter values via `${param:key}`. Parameters follow a resolution hierarchy:
|
|
183
|
+
|
|
184
|
+
1. **CLI params** (`--param="key=value"`) - highest priority
|
|
185
|
+
2. **Stage-specific params** (`stages.<stage>.params`)
|
|
186
|
+
3. **Default params** (`stages.default.params`)
|
|
187
|
+
|
|
188
|
+
```yml
|
|
189
|
+
# Direct parameter reference
|
|
190
|
+
appDomain: ${param:domain}
|
|
191
|
+
|
|
192
|
+
# Parameter with fallback
|
|
193
|
+
apiKey: ${param:apiKey, 'default-api-key'}
|
|
194
|
+
|
|
195
|
+
# Stage-specific parameters defined in config
|
|
196
|
+
stages:
|
|
197
|
+
dev:
|
|
198
|
+
params:
|
|
199
|
+
domain: dev.myapp.com
|
|
200
|
+
dbHost: localhost
|
|
201
|
+
prod:
|
|
202
|
+
params:
|
|
203
|
+
domain: myapp.com
|
|
204
|
+
dbHost: prod-db.myapp.com
|
|
205
|
+
default:
|
|
206
|
+
params:
|
|
207
|
+
domain: default.myapp.com
|
|
208
|
+
dbPort: 3306
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**CLI Usage:**
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
# Single param
|
|
215
|
+
node app.js --param="domain=example.com"
|
|
216
|
+
|
|
217
|
+
# Multiple params
|
|
218
|
+
node app.js --param="domain=example.com" --param="apiKey=secret123"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Code Usage:**
|
|
222
|
+
|
|
223
|
+
```js
|
|
224
|
+
const config = await configorama('config.yml', {
|
|
225
|
+
options: {
|
|
226
|
+
stage: 'prod',
|
|
227
|
+
param: ['domain=cli-override.com', 'apiKey=secret']
|
|
228
|
+
}
|
|
229
|
+
})
|
|
230
|
+
```
|
|
231
|
+
|
|
171
232
|
### Self references
|
|
172
233
|
|
|
173
234
|
Reference values from other key paths in the same configuration file.
|
|
@@ -682,6 +743,7 @@ The `source` property defines how the config wizard handles each variable type:
|
|
|
682
743
|
|----------|-------------|-------------|
|
|
683
744
|
| `${env:VAR}` | `user` | Environment variables |
|
|
684
745
|
| `${opt:flag}` | `user` | CLI option flags |
|
|
746
|
+
| `${param:key}` | `user` | Parameter values |
|
|
685
747
|
| `${self:key}` | `config` | Self references |
|
|
686
748
|
| `${file(path)}` | `config` | File references |
|
|
687
749
|
| `${text(path)}` | `config` | Raw text file references |
|
|
@@ -694,45 +756,163 @@ The `source` property defines how the config wizard handles each variable type:
|
|
|
694
756
|
| Option | Type | Default | Description |
|
|
695
757
|
|--------|------|---------|-------------|
|
|
696
758
|
| `options` | object | `{}` | CLI options/flags to populate `${opt:xyz}` variables |
|
|
697
|
-
| `
|
|
698
|
-
| `
|
|
759
|
+
| `syntax` | string/RegExp | `${...}` | Custom variable syntax regex pattern |
|
|
760
|
+
| `allowUnknownVariableTypes` | boolean \| string[] | `false` | Allow unknown variable types to pass through (e.g., `${ssm:path}`) |
|
|
761
|
+
| `allowUnresolvedVariables` | boolean \| string[] | `false` | Allow known variable types that can't be resolved to pass through |
|
|
699
762
|
| `allowUndefinedValues` | boolean | `false` | Allow undefined to be an end result |
|
|
700
763
|
| `variableSources` | array | `[]` | Custom variable sources (see above) |
|
|
701
764
|
|
|
702
|
-
> **Note:** `allowUnknownVars`
|
|
765
|
+
> **Note:** Legacy options `allowUnknownVars`, `allowUnknownVariables`, `allowUnknownParams`, and `allowUnknownFileRefs` are deprecated. Use `allowUnknownVariableTypes` and `allowUnresolvedVariables` instead.
|
|
703
766
|
|
|
704
|
-
|
|
767
|
+
<details>
|
|
768
|
+
<summary><strong>Migration Guide</strong></summary>
|
|
705
769
|
|
|
706
|
-
|
|
770
|
+
**From legacy options to new API:**
|
|
707
771
|
|
|
708
772
|
```js
|
|
773
|
+
// OLD → NEW
|
|
774
|
+
|
|
775
|
+
// Unknown variable types (unregistered resolvers)
|
|
776
|
+
{ allowUnknownVars: true } → { allowUnknownVariableTypes: true }
|
|
777
|
+
{ allowUnknownVariables: true } → { allowUnknownVariableTypes: true }
|
|
778
|
+
|
|
779
|
+
// Unresolved params
|
|
780
|
+
{ allowUnknownParams: true } → { allowUnresolvedVariables: ['param'] }
|
|
781
|
+
|
|
782
|
+
// Unresolved file refs
|
|
783
|
+
{ allowUnknownFileRefs: true } → { allowUnresolvedVariables: ['file'] }
|
|
784
|
+
|
|
785
|
+
// Both params and files
|
|
786
|
+
{ allowUnknownParams: true, allowUnknownFileRefs: true }
|
|
787
|
+
→ { allowUnresolvedVariables: ['param', 'file'] }
|
|
788
|
+
|
|
789
|
+
// All unresolved (env, opt, file, param, etc.)
|
|
790
|
+
{ allowUnresolvedVariables: true } // unchanged, now also accepts arrays
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
**New array syntax allows granular control:**
|
|
794
|
+
|
|
795
|
+
```js
|
|
796
|
+
// Only allow specific unknown types
|
|
797
|
+
{ allowUnknownVariableTypes: ['ssm', 'cf', 's3'] }
|
|
798
|
+
|
|
799
|
+
// Only allow specific resolver types to fail gracefully
|
|
800
|
+
{ allowUnresolvedVariables: ['param'] } // only params, env/file/opt still throw
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
Legacy options still work but will be removed in a future major version.
|
|
804
|
+
|
|
805
|
+
</details>
|
|
806
|
+
|
|
807
|
+
### Custom Variable Syntax
|
|
808
|
+
|
|
809
|
+
Use the `syntax` option to change the variable delimiters. You can provide a regex string directly or use `buildVariableSyntax()` to generate one with proper character escaping:
|
|
810
|
+
|
|
811
|
+
```js
|
|
812
|
+
const configorama = require('configorama')
|
|
813
|
+
const { buildVariableSyntax } = require('configorama')
|
|
814
|
+
|
|
815
|
+
// Using buildVariableSyntax helper (recommended)
|
|
709
816
|
const config = await configorama(configFile, {
|
|
710
|
-
|
|
817
|
+
syntax: buildVariableSyntax('{{', '}}'), // Mustache-style: {{env:FOO}}
|
|
711
818
|
options: { stage: 'dev' }
|
|
712
819
|
})
|
|
713
820
|
|
|
714
|
-
//
|
|
715
|
-
|
|
821
|
+
// Other examples:
|
|
822
|
+
buildVariableSyntax('${{', '}}') // ${{env:FOO}}
|
|
823
|
+
buildVariableSyntax('#{', '}') // #{env:FOO}
|
|
824
|
+
buildVariableSyntax('[[', ']]') // [[env:FOO]]
|
|
825
|
+
buildVariableSyntax('<', '>') // <env:FOO>
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
The `buildVariableSyntax(prefix, suffix, excludePatterns)` function:
|
|
829
|
+
- Automatically excludes suffix characters from the allowed character class (prevents parsing issues)
|
|
830
|
+
- Supports nested variables by excluding `$` and `{` from values
|
|
831
|
+
- Third parameter `excludePatterns` is an array of strings to exclude via negative lookahead (default: `['AWS', 'stageVariables']`)
|
|
832
|
+
|
|
833
|
+
### allowUnknownVariableTypes
|
|
834
|
+
|
|
835
|
+
Controls what happens when encountering unregistered variable types (e.g., `${ssm:path}` when `ssm` isn't a registered resolver).
|
|
836
|
+
|
|
837
|
+
```js
|
|
838
|
+
// Allow ALL unknown types to pass through
|
|
839
|
+
const config = await configorama(configFile, {
|
|
840
|
+
allowUnknownVariableTypes: true,
|
|
841
|
+
options: { stage: 'dev' }
|
|
842
|
+
})
|
|
843
|
+
// Input: { key: '${ssm:/path/to/secret}' }
|
|
844
|
+
// Output: { key: '${ssm:/path/to/secret}' }
|
|
845
|
+
|
|
846
|
+
// Allow only SPECIFIC unknown types
|
|
847
|
+
const config = await configorama(configFile, {
|
|
848
|
+
allowUnknownVariableTypes: ['ssm', 'cf'], // only these pass through
|
|
849
|
+
options: { stage: 'dev' }
|
|
850
|
+
})
|
|
851
|
+
// ${ssm:path} and ${cf:stack.output} pass through
|
|
852
|
+
// ${custom:thing} throws an error
|
|
716
853
|
```
|
|
717
854
|
|
|
718
855
|
### allowUnresolvedVariables
|
|
719
856
|
|
|
720
|
-
|
|
857
|
+
Controls what happens when a known resolver can't find a value (missing env vars, missing files, etc.).
|
|
721
858
|
|
|
722
859
|
```js
|
|
860
|
+
// Allow ALL unresolved variables to pass through
|
|
723
861
|
const config = await configorama(configFile, {
|
|
724
862
|
allowUnresolvedVariables: true,
|
|
725
863
|
options: { stage: 'dev' }
|
|
726
864
|
})
|
|
727
|
-
|
|
728
865
|
// Input: { key: '${env:MISSING_VAR}' }
|
|
729
|
-
// Output: { key: '${env:MISSING_VAR}' }
|
|
866
|
+
// Output: { key: '${env:MISSING_VAR}' }
|
|
867
|
+
|
|
868
|
+
// Allow only SPECIFIC types to be unresolved
|
|
869
|
+
const config = await configorama(configFile, {
|
|
870
|
+
allowUnresolvedVariables: ['param', 'file'], // only these pass through
|
|
871
|
+
options: { stage: 'prod' }
|
|
872
|
+
})
|
|
873
|
+
// Input: { paramKey: '${param:x}', fileKey: '${file(missing.yml)}' }
|
|
874
|
+
// Output: { paramKey: '${param:x}', fileKey: '${file(missing.yml)}' }
|
|
875
|
+
|
|
876
|
+
// Allow only SPECIFIC types to be unresolved
|
|
877
|
+
const config = await configorama(configFile, {
|
|
878
|
+
allowUnresolvedVariables: ['param', 'file'], // only these pass through
|
|
879
|
+
options: { stage: 'prod' }
|
|
880
|
+
})
|
|
881
|
+
// Input: { key: '${env:MISSING_VAR}', paramKey: '${param:x}', fileKey: '${file(missing.yml)}' }
|
|
882
|
+
// Unresolved ${param:x} and ${file(missing.yml)} pass through but
|
|
883
|
+
// Output error thrown because ${env:MISSING_VAR} throws an error
|
|
730
884
|
```
|
|
731
885
|
|
|
732
|
-
This is useful for multi-stage resolution
|
|
886
|
+
This is useful for multi-stage resolution (e.g., Downstream Serverless Dashboard resolves params after local resolution).
|
|
887
|
+
|
|
888
|
+
> **Note:** This option does NOT apply to `self:` or dotProp variables (e.g., `${foo.bar.baz}`). These are local references that configorama fully owns—if they can't be resolved, it's a config error, not something to defer to another system.
|
|
733
889
|
|
|
734
890
|
## FAQ
|
|
735
891
|
|
|
892
|
+
**Q: What happens with circular variable dependencies?**
|
|
893
|
+
|
|
894
|
+
Configorama detects circular dependencies and throws a helpful error instead of hanging forever.
|
|
895
|
+
|
|
896
|
+
```yml
|
|
897
|
+
# Direct cycle - throws error
|
|
898
|
+
a: ${self:b}
|
|
899
|
+
b: ${self:a}
|
|
900
|
+
# Error: Circular variable dependency detected: b → a → b
|
|
901
|
+
|
|
902
|
+
# Indirect cycle - also detected
|
|
903
|
+
a: ${self:b}
|
|
904
|
+
b: ${self:c}
|
|
905
|
+
c: ${self:a}
|
|
906
|
+
# Error: Circular variable dependency detected: c → a → b → c
|
|
907
|
+
|
|
908
|
+
# Works with shorthand syntax too
|
|
909
|
+
foo:
|
|
910
|
+
bar: ${baz.qux}
|
|
911
|
+
baz:
|
|
912
|
+
qux: ${foo.bar}
|
|
913
|
+
# Error: Circular variable dependency detected: baz.qux → foo.bar → baz.qux
|
|
914
|
+
```
|
|
915
|
+
|
|
736
916
|
**Q: Why should I use this?**
|
|
737
917
|
|
|
738
918
|
Never rendering a stale configuration file again!
|
package/cli.js
CHANGED
|
@@ -10,7 +10,7 @@ const { makeBox } = require('@davidwells/box-logger')
|
|
|
10
10
|
|
|
11
11
|
// Parse command line arguments
|
|
12
12
|
const argv = minimist(process.argv.slice(2), {
|
|
13
|
-
string: ['output', 'o', 'format', 'f'],
|
|
13
|
+
string: ['output', 'o', 'format', 'f', 'param'],
|
|
14
14
|
boolean: ['help', 'h', 'version', 'v', 'debug', 'allow-unknown', 'allow-undefined', 'list', 'info', 'verify'],
|
|
15
15
|
alias: {
|
|
16
16
|
h: 'help',
|
|
@@ -41,6 +41,7 @@ Options:
|
|
|
41
41
|
-d, --debug Enable debug mode
|
|
42
42
|
-i, --info Show info about the config
|
|
43
43
|
-v, --verify Verify the config
|
|
44
|
+
--param <key=value> Pass parameter values (can be used multiple times)
|
|
44
45
|
--allow-unknown Allow unknown variables to pass through
|
|
45
46
|
--allow-undefined Allow undefined values in the final output
|
|
46
47
|
|
|
@@ -49,6 +50,7 @@ Examples:
|
|
|
49
50
|
configorama --info config.yml
|
|
50
51
|
configorama --format yaml config.json
|
|
51
52
|
configorama --output resolved.json config.yml
|
|
53
|
+
configorama --param="domain=myapp.com" --param="key=value" config.yml
|
|
52
54
|
configorama --allow-unknown config.toml
|
|
53
55
|
`)
|
|
54
56
|
process.exit(0)
|
package/index.d.ts
CHANGED
|
@@ -17,10 +17,43 @@ export interface ConfigoramaSettings {
|
|
|
17
17
|
filters?: Record<string, Function>
|
|
18
18
|
/** Object of custom functions */
|
|
19
19
|
functions?: Record<string, Function>
|
|
20
|
-
/**
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
/** Parameters to populate for ${param:xyz} */
|
|
21
|
+
params?: Record<string, any>
|
|
22
|
+
|
|
23
|
+
// === Variable Resolution Options ===
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Allow unknown variable types (unregistered resolvers) to pass through.
|
|
27
|
+
* - `true`: All unknown types pass through (e.g., ${ssm:path}, ${cf:stack})
|
|
28
|
+
* - `false`: Throws on unknown types
|
|
29
|
+
* - `string[]`: Only specified types pass through (e.g., ['ssm', 'cf'])
|
|
30
|
+
*/
|
|
31
|
+
allowUnknownVariableTypes?: boolean | string[]
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Allow known variable types that can't resolve to pass through.
|
|
35
|
+
* - `true`: All unresolved variables pass through
|
|
36
|
+
* - `false`: Throws when resolution fails
|
|
37
|
+
* - `string[]`: Only specified types pass through (e.g., ['param', 'file'])
|
|
38
|
+
*/
|
|
39
|
+
allowUnresolvedVariables?: boolean | string[]
|
|
40
|
+
|
|
41
|
+
/** Allow undefined values as final results */
|
|
23
42
|
allowUndefinedValues?: boolean
|
|
43
|
+
|
|
44
|
+
// === Legacy Options (deprecated, use above instead) ===
|
|
45
|
+
|
|
46
|
+
/** @deprecated Use allowUnknownVariableTypes instead */
|
|
47
|
+
allowUnknownVars?: boolean
|
|
48
|
+
/** @deprecated Use allowUnknownVariableTypes instead */
|
|
49
|
+
allowUnknownVariables?: boolean
|
|
50
|
+
/** @deprecated Use allowUnresolvedVariables: ['param'] instead */
|
|
51
|
+
allowUnknownParams?: boolean
|
|
52
|
+
/** @deprecated Use allowUnresolvedVariables: ['file'] instead */
|
|
53
|
+
allowUnknownFileRefs?: boolean
|
|
54
|
+
|
|
55
|
+
// === Other Options ===
|
|
56
|
+
|
|
24
57
|
/** Values passed into .js config files if user using javascript config */
|
|
25
58
|
dynamicArgs?: object | Function
|
|
26
59
|
/** Return both config and metadata about variables found */
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
const Configorama = require('./main')
|
|
2
2
|
const parsers = require('./parsers')
|
|
3
3
|
const enrichMetadata = require('./utils/parsing/enrichMetadata')
|
|
4
|
-
|
|
5
|
-
module.exports.Configorama = Configorama
|
|
4
|
+
const { buildVariableSyntax } = require('./utils/variables/variableUtils')
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* @typedef {Object} ConfigoramaSettings
|
|
@@ -130,3 +129,17 @@ module.exports.analyze = async (configPathOrObject, settings = {}) => {
|
|
|
130
129
|
* @type {Object}
|
|
131
130
|
*/
|
|
132
131
|
module.exports.format = parsers
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Configorama class for advanced usage
|
|
135
|
+
*/
|
|
136
|
+
module.exports.Configorama = Configorama
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Build variable syntax regex with proper character escaping
|
|
140
|
+
* @param {string} [prefix='${'] - Variable prefix (e.g., '${', '{{', '[[')
|
|
141
|
+
* @param {string} [suffix='}'] - Variable suffix (e.g., '}', '}}', ']]')
|
|
142
|
+
* @param {string[]} [excludePatterns] - Patterns to exclude via negative lookahead
|
|
143
|
+
* @returns {string} Regex source string for use with syntax option
|
|
144
|
+
*/
|
|
145
|
+
module.exports.buildVariableSyntax = buildVariableSyntax
|