configorama 0.9.5 → 0.9.11

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.
Files changed (65) hide show
  1. package/README.md +156 -5
  2. package/package.json +20 -2
  3. package/src/main.js +268 -105
  4. package/src/parsers/esm.js +0 -14
  5. package/src/parsers/hcl-parse-script.js +40 -0
  6. package/src/parsers/hcl.js +131 -3
  7. package/src/parsers/hcl.slow-test.js +141 -0
  8. package/src/parsers/index.js +3 -1
  9. package/src/parsers/typescript.js +0 -10
  10. package/src/resolvers/valueFromEval.js +69 -11
  11. package/src/resolvers/valueFromFile.js +54 -1
  12. package/src/resolvers/valueFromIf.js +75 -0
  13. package/src/resolvers/valueFromIf.test.js +66 -0
  14. package/src/resolvers/valueFromNumber.js +3 -0
  15. package/src/utils/handleSignalEvents.js +3 -4
  16. package/src/utils/lodash.js +18 -7
  17. package/src/utils/parsing/cloudformationSchema.js +1 -2
  18. package/src/utils/parsing/cloudformationSchema.test.js +14 -0
  19. package/src/utils/parsing/parse.js +11 -1
  20. package/src/utils/parsing/preProcess.js +220 -5
  21. package/src/utils/paths/getFullFilePath.js +6 -2
  22. package/src/utils/paths/getFullFilePath.test.js +18 -0
  23. package/src/utils/regex/index.js +18 -3
  24. package/src/utils/regex/index.test.js +24 -0
  25. package/src/utils/strings/quoteAware.js +141 -0
  26. package/src/utils/strings/replaceAll.js +13 -1
  27. package/src/utils/strings/splitByComma.js +25 -15
  28. package/src/utils/strings/splitByComma.test.js +19 -0
  29. package/src/utils/strings/splitOnPipe.js +30 -0
  30. package/src/utils/strings/splitOnPipe.test.js +68 -0
  31. package/src/utils/validation/isValidValue.test.js +1 -1
  32. package/src/utils/validation/warnIfNotFound.js +1 -1
  33. package/src/utils/variables/findNestedVariables.js +8 -2
  34. package/types/src/main.d.ts +3 -1
  35. package/types/src/main.d.ts.map +1 -1
  36. package/types/src/parsers/esm.d.ts.map +1 -1
  37. package/types/src/parsers/hcl-parse-script.d.ts +3 -0
  38. package/types/src/parsers/hcl-parse-script.d.ts.map +1 -0
  39. package/types/src/parsers/hcl.d.ts +43 -0
  40. package/types/src/parsers/hcl.d.ts.map +1 -1
  41. package/types/src/parsers/hcl.slow-test.d.ts +2 -0
  42. package/types/src/parsers/hcl.slow-test.d.ts.map +1 -0
  43. package/types/src/parsers/typescript.d.ts.map +1 -1
  44. package/types/src/resolvers/valueFromEval.d.ts +1 -0
  45. package/types/src/resolvers/valueFromEval.d.ts.map +1 -1
  46. package/types/src/resolvers/valueFromFile.d.ts +4 -0
  47. package/types/src/resolvers/valueFromFile.d.ts.map +1 -1
  48. package/types/src/resolvers/valueFromIf.d.ts +7 -0
  49. package/types/src/resolvers/valueFromIf.d.ts.map +1 -0
  50. package/types/src/resolvers/valueFromNumber.d.ts.map +1 -1
  51. package/types/src/utils/handleSignalEvents.d.ts.map +1 -1
  52. package/types/src/utils/lodash.d.ts.map +1 -1
  53. package/types/src/utils/parsing/parse.d.ts.map +1 -1
  54. package/types/src/utils/parsing/preProcess.d.ts +5 -1
  55. package/types/src/utils/parsing/preProcess.d.ts.map +1 -1
  56. package/types/src/utils/paths/getFullFilePath.d.ts.map +1 -1
  57. package/types/src/utils/regex/index.d.ts.map +1 -1
  58. package/types/src/utils/strings/quoteAware.d.ts +30 -0
  59. package/types/src/utils/strings/quoteAware.d.ts.map +1 -0
  60. package/types/src/utils/strings/replaceAll.d.ts.map +1 -1
  61. package/types/src/utils/strings/splitByComma.d.ts +1 -1
  62. package/types/src/utils/strings/splitByComma.d.ts.map +1 -1
  63. package/types/src/utils/strings/splitOnPipe.d.ts +8 -0
  64. package/types/src/utils/strings/splitOnPipe.d.ts.map +1 -0
  65. package/types/src/utils/variables/findNestedVariables.d.ts.map +1 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Dynamic configuration values with variable support.
4
4
 
5
- Works with `yml`, `json`, `toml` config formats and anything that parsed down to a plain ol' javascript object
5
+ Works with `yml`, `json`, `toml`, `hcl` (Terraform), and other config formats. Supports any format that can be parsed to a plain JavaScript object
6
6
 
7
7
  ## About
8
8
 
@@ -16,6 +16,7 @@ Configorama extends your configuration with a powerful variable system. It resol
16
16
  - Git references
17
17
  - Cron values
18
18
  - Eval expressions
19
+ - If/conditional expressions
19
20
  - Async/sync JS functions
20
21
  - Filters (experimental)
21
22
  - Functions (experimental)
@@ -45,6 +46,7 @@ See [tests](https://github.com/DavidWells/configorama/tree/master/tests) for mor
45
46
  - [Git references](#git-references)
46
47
  - [Cron Values](#cron-values)
47
48
  - [Eval expressions](#eval-expressions)
49
+ - [If expressions](#if-expressions)
48
50
  - [Filters (experimental)](#filters-experimental)
49
51
  - [Functions (experimental)](#functions-experimental)
50
52
  - [More Examples](#more-examples)
@@ -98,7 +100,7 @@ Configorama creates a graph of your config file and all its dependencies, then i
98
100
 
99
101
  ```mermaid
100
102
  flowchart TD
101
- A[Load config file] --> B[Parse yml/json/toml to object]
103
+ A[Load config file] --> B[Parse yml/json/toml/hcl to object]
102
104
  B --> C[Preprocess: raw config file]
103
105
  C --> D{Return metadata only?}
104
106
  D -->|Yes| E[Collect variable metadata]
@@ -150,6 +152,7 @@ console.log(result.resolutionHistory) // Step-by-step resolution for each path
150
152
  | git | ${git:value} | Git data |
151
153
  | cron | ${cron(expr)} | Cron expressions |
152
154
  | eval | ${eval(expr)} | Math/logic expressions |
155
+ | if | ${if(expr)} | Conditional expressions |
153
156
 
154
157
  ### Environment variables
155
158
 
@@ -253,10 +256,10 @@ three: ${zaz.wow.cool} # Resolves to `2`
253
256
 
254
257
  ### File references
255
258
 
256
- Import values from external yml, json, or toml files by relative path.
259
+ Import values from external yml, json, toml, or hcl files by relative path.
257
260
 
258
261
  ```yml
259
- # Import full yml/json/toml file via relative path
262
+ # Import full yml/json/toml/hcl file via relative path
260
263
  fileRef: ${file(./subFile.yml)}
261
264
 
262
265
  # Import sub values from files. This imports other-config.yml `topLevel:` value
@@ -279,7 +282,7 @@ Supported file types (extensions are case-insensitive):
279
282
  | YAML | `.yml`, `.yaml` |
280
283
  | TOML | `.toml`, `.tml` |
281
284
  | INI | `.ini` |
282
- | JSON | `.json`, `.json5` |
285
+ | JSON | `.json`, `.json5`, `.jsonc` |
283
286
 
284
287
  ### Sync/Async file references
285
288
 
@@ -533,6 +536,74 @@ npm install ts-node typescript --save-dev
533
536
  - Full TypeScript interface support
534
537
  - Comprehensive error handling with helpful dependency messages
535
538
 
539
+ ### Terraform HCL support
540
+
541
+ Configorama supports Terraform HCL (HashiCorp Configuration Language) files, allowing you to parse `.tf`, `.tf.json`, and `.hcl` files.
542
+
543
+ **Installation:**
544
+
545
+ HCL parsing requires the optional `@cdktf/hcl2json` package:
546
+
547
+ ```bash
548
+ npm install @cdktf/hcl2json
549
+ ```
550
+
551
+ **Supported file types:**
552
+ - `.tf` - Terraform configuration files
553
+ - `.hcl` - Generic HCL files
554
+ - `.tf.json` - Terraform JSON configuration files
555
+
556
+ **Example:**
557
+
558
+ ```js
559
+ const configorama = require('configorama')
560
+
561
+ // Parse a Terraform configuration file
562
+ const terraformConfig = await configorama('./main.tf')
563
+
564
+ // Access Terraform variables, resources, locals, etc.
565
+ console.log(terraformConfig.variable) // Variables defined in the file
566
+ console.log(terraformConfig.resource) // Resources
567
+ console.log(terraformConfig.locals) // Local values
568
+ console.log(terraformConfig.output) // Outputs
569
+ ```
570
+
571
+ **Importing Terraform files:**
572
+
573
+ ```yml
574
+ # Import Terraform variables from a .tf file
575
+ terraformVars: ${file(./terraform/variables.tf)}
576
+
577
+ # Import specific variable from Terraform file
578
+ region: ${file(./terraform/variables.tf):variable.region[0].default}
579
+ ```
580
+
581
+ **Variable syntax:**
582
+ When loading `.tf` or `.hcl` files directly, configorama automatically uses `$[...]` syntax instead of `${...}` to avoid conflicts with Terraform's native `${var.name}` interpolation. Terraform expressions like `${var.environment}` and `${map(string)}` are preserved as-is.
583
+
584
+ ```js
585
+ // Loading .tf directly - uses $[...] syntax automatically
586
+ const config = await configorama('./main.tf')
587
+ // config.locals[0].app_name = "myapp-${var.environment}" (preserved)
588
+
589
+ // Use $[...] for configorama variables in .tf files
590
+ // myvar: $[env:MY_VAR]
591
+ // myref: $[file(./other.yml)] # referenced files also use $[...]
592
+ ```
593
+
594
+ When importing `.tf` files from other config formats (yml, json, etc.) via `${file()}`, the parent file's syntax applies. Use `allowUnknownVariableTypes: true` if the imported `.tf` contains Terraform interpolations:
595
+
596
+ ```js
597
+ const config = await configorama('./config.yml', {
598
+ allowUnknownVariableTypes: true
599
+ })
600
+ ```
601
+
602
+ **Read-only support:**
603
+ Currently, HCL files can be read and parsed, but writing/generating HCL files is not supported.
604
+
605
+ See [tests/hclTests](./tests/hclTests) for example Terraform files.
606
+
536
607
  ### Git references
537
608
 
538
609
  Access repository information from the current working directory's git data.
@@ -647,6 +718,85 @@ strictEqual: ${eval("foo" === "foo")} # true
647
718
  complex: ${eval((10 + 5) * 2)} # 30
648
719
  ```
649
720
 
721
+ ### If expressions
722
+
723
+ Conditional expressions using ternary syntax. This is an alias for `eval` with a more intuitive name for conditionals.
724
+
725
+ ```yml
726
+ # Basic ternary (condition ? "yes" : "no")
727
+ status: ${if((5 > 3) ? "yes" : "no")} # "yes"
728
+
729
+ # With variables
730
+ threshold: 50
731
+ value: 75
732
+ result: ${if((${self:value} > ${self:threshold}) ? "above" : "below")} # "above"
733
+
734
+ # Nested ternary (if/else if/else)
735
+ score: 85
736
+ grade: ${if((${self:score} >= 90) ? "A" : (${self:score} >= 80) ? "B" : "C")} # "B"
737
+
738
+ # Boolean result (no ternary needed)
739
+ isValid: ${if(${self:value} > 0)} # true
740
+
741
+ # Logical operators
742
+ enabled: true
743
+ count: 5
744
+ canProceed: ${if(${self:enabled} && ${self:count} > 0)} # true
745
+ ```
746
+
747
+ **Supported operators:**
748
+
749
+ | Category | Operators |
750
+ |----------|-----------|
751
+ | Comparison | `==` `!=` `===` `!==` `>` `<` `>=` `<=` |
752
+ | Logical | `&&` `\|\|` `!` |
753
+ | Nullish | `??` |
754
+ | Ternary | `condition ? "yes" : "no"` |
755
+
756
+ **Serverless deployment examples:**
757
+
758
+ ```yml
759
+ service: my-service
760
+
761
+ provider:
762
+ name: aws
763
+ stage: ${opt:stage, 'dev'}
764
+ region: ${opt:region, 'us-east-1'}
765
+
766
+ custom:
767
+ # Different memory by stage
768
+ memorySize: '${ if( ${provider.stage} === "prod" ) ? 1024 : 512 }'
769
+
770
+ # Different log retention by stage
771
+ logRetention: ${if(("${provider.stage}" === "prod") ? 30 : 7)}
772
+
773
+ # Enable features per environment
774
+ enableDebugEndpoints: ${if("${provider.stage}" !== "prod")}
775
+ enableMetrics: ${if("${provider.stage}" === "prod")}
776
+
777
+ # Regional settings
778
+ replicaCount: ${if(("${provider.region}" === "us-east-1") ? 3 : 1)}
779
+
780
+ # Conditional IAM role (use predefined role in prod, inline in dev)
781
+ useExternalRole: ${if("${provider.stage}" === "prod")}
782
+ role: ${if((${custom.useExternalRole}) ? "arn:aws:iam::123:role/prod-role" : null)}
783
+
784
+ functions:
785
+ api:
786
+ handler: handler.api
787
+ memorySize: ${custom.memorySize}
788
+
789
+ # Debug function - only deployed in non-prod
790
+ debug:
791
+ handler: handler.debug
792
+ enabled: ${custom.enableDebugEndpoints}
793
+
794
+ # Metrics processor - only in prod
795
+ metricsProcessor:
796
+ handler: handler.metrics
797
+ enabled: ${custom.enableMetrics}
798
+ ```
799
+
650
800
  ### Filters (experimental)
651
801
 
652
802
  Pipe resolved values through transformation functions like case conversion.
@@ -750,6 +900,7 @@ The `source` property defines how the config wizard handles each variable type:
750
900
  | `${git:branch}` | `readonly` | Git repository data |
751
901
  | `${cron(expr)}` | `readonly` | Cron expression conversion |
752
902
  | `${eval(expr)}` | `readonly` | Math/logic evaluation |
903
+ | `${if(expr)}` | `readonly` | Conditional expressions |
753
904
 
754
905
  ## Options
755
906
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "configorama",
3
- "version": "0.9.5",
3
+ "version": "0.9.11",
4
4
  "description": "Variable support for configuration files",
5
5
  "main": "src/index.js",
6
6
  "types": "index.d.ts",
@@ -25,10 +25,11 @@
25
25
  "info": "repomix --include \"cli.js,src/**/*.js\" --ignore \"**/*.test.js\" --copy",
26
26
  "docs": "node ./scripts/docs.js",
27
27
  "t": "./scripts/run-tests.sh",
28
- "test": "npm run test:lib && uvu tests \".*\\.test.js$\" ",
28
+ "test": "npm run test:slow && npm run test:lib && uvu tests \".*\\.test.js$\"",
29
29
  "test:tests": "uvu tests \".*\\.test.js$\" ",
30
30
  "test:api": "uvu tests/api api.test.js",
31
31
  "test:lib": "uvu src \".*\\.test.js$\"",
32
+ "test:slow": "uvu src \".*\\.slow-test.js$\" && uvu tests \".*\\.slow-test.js$\"",
32
33
  "watch": "watchlist tests -- npm test",
33
34
  "typecheck": "tsc --noEmit",
34
35
  "types": "tsc",
@@ -84,11 +85,28 @@
84
85
  "traverse": "^0.6.8"
85
86
  },
86
87
  "devDependencies": {
88
+ "@cdktf/hcl2json": "^0.21.0",
87
89
  "@types/node": "^24.10.1",
88
90
  "markdown-magic": "^3.4.0",
89
91
  "tsx": "^4.7.0",
90
92
  "typescript": "^5.8.3",
91
93
  "uvu": "^0.5.6",
92
94
  "watchlist": "^0.3.1"
95
+ },
96
+ "peerDependencies": {
97
+ "@cdktf/hcl2json": ">=0.20.0",
98
+ "tsx": ">=4.0.0",
99
+ "ts-node": ">=10.0.0"
100
+ },
101
+ "peerDependenciesMeta": {
102
+ "@cdktf/hcl2json": {
103
+ "optional": true
104
+ },
105
+ "tsx": {
106
+ "optional": true
107
+ },
108
+ "ts-node": {
109
+ "optional": true
110
+ }
93
111
  }
94
112
  }