@romaintaillandier1978/dotenv-never-lies 1.1.1 → 1.3.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.
Files changed (212) hide show
  1. package/README.md +103 -42
  2. package/dist/cli/commands/assert.d.ts +3 -4
  3. package/dist/cli/commands/assert.d.ts.map +1 -1
  4. package/dist/cli/commands/explain.d.ts +2 -3
  5. package/dist/cli/commands/explain.d.ts.map +1 -1
  6. package/dist/cli/commands/export.d.ts +4 -3
  7. package/dist/cli/commands/export.d.ts.map +1 -1
  8. package/dist/cli/commands/export.js +46 -0
  9. package/dist/cli/commands/generate.d.ts +2 -2
  10. package/dist/cli/commands/generate.d.ts.map +1 -1
  11. package/dist/cli/commands/infer.d.ts +15 -0
  12. package/dist/cli/commands/infer.d.ts.map +1 -0
  13. package/dist/cli/commands/infer.js +86 -0
  14. package/dist/cli/commands/init.d.ts +15 -0
  15. package/dist/cli/commands/init.d.ts.map +1 -0
  16. package/dist/cli/commands/init.js +30 -0
  17. package/dist/cli/commands/program.d.ts +4 -0
  18. package/dist/cli/commands/program.d.ts.map +1 -0
  19. package/dist/cli/commands/program.js +1 -0
  20. package/dist/cli/index.js +74 -30
  21. package/dist/cli/utils/infer-schema.d.ts +2 -2
  22. package/dist/cli/utils/infer-schema.d.ts.map +1 -1
  23. package/dist/cli/utils/infer-schema.js +20 -22
  24. package/dist/cli/utils/printer.d.ts +2 -0
  25. package/dist/cli/utils/printer.d.ts.map +1 -1
  26. package/dist/cli/utils/printer.js +104 -1
  27. package/dist/core.d.ts.map +1 -1
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +1 -0
  31. package/dist/infer/__tests__/port-vs-version.test.d.ts +2 -0
  32. package/dist/infer/__tests__/port-vs-version.test.d.ts.map +1 -0
  33. package/dist/infer/__tests__/port-vs-version.test.js +32 -0
  34. package/dist/infer/__tests__/rules/basic.test.d.ts +2 -0
  35. package/dist/infer/__tests__/rules/basic.test.d.ts.map +1 -0
  36. package/dist/infer/__tests__/rules/basic.test.js +85 -0
  37. package/dist/infer/__tests__/rules/boolean.test.d.ts +2 -0
  38. package/dist/infer/__tests__/rules/boolean.test.d.ts.map +1 -0
  39. package/dist/infer/__tests__/rules/boolean.test.js +34 -0
  40. package/dist/infer/__tests__/rules/duration.test.d.ts +2 -0
  41. package/dist/infer/__tests__/rules/duration.test.d.ts.map +1 -0
  42. package/dist/infer/__tests__/rules/duration.test.js +24 -0
  43. package/dist/infer/__tests__/rules/ip.test.d.ts +2 -0
  44. package/dist/infer/__tests__/rules/ip.test.d.ts.map +1 -0
  45. package/dist/infer/__tests__/rules/ip.test.js +24 -0
  46. package/dist/infer/__tests__/rules/json.test.d.ts +2 -0
  47. package/dist/infer/__tests__/rules/json.test.d.ts.map +1 -0
  48. package/dist/infer/__tests__/rules/json.test.js +38 -0
  49. package/dist/infer/__tests__/rules/list.test.d.ts +2 -0
  50. package/dist/infer/__tests__/rules/list.test.d.ts.map +1 -0
  51. package/dist/infer/__tests__/rules/list.test.js +130 -0
  52. package/dist/infer/__tests__/rules/port.test.d.ts +2 -0
  53. package/dist/infer/__tests__/rules/port.test.d.ts.map +1 -0
  54. package/dist/infer/__tests__/rules/port.test.js +24 -0
  55. package/dist/infer/__tests__/rules/url.test.d.ts +2 -0
  56. package/dist/infer/__tests__/rules/url.test.d.ts.map +1 -0
  57. package/dist/infer/__tests__/rules/url.test.js +39 -0
  58. package/dist/infer/__tests__/rules/version.test.d.ts +2 -0
  59. package/dist/infer/__tests__/rules/version.test.d.ts.map +1 -0
  60. package/dist/infer/__tests__/rules/version.test.js +37 -0
  61. package/dist/infer/generated/basic.d.ts +8 -0
  62. package/dist/infer/generated/basic.d.ts.map +1 -0
  63. package/dist/infer/generated/basic.js +24 -0
  64. package/dist/infer/generated/boolean.d.ts +3 -0
  65. package/dist/infer/generated/boolean.d.ts.map +1 -0
  66. package/dist/infer/generated/boolean.js +9 -0
  67. package/dist/infer/generated/duration.d.ts +3 -0
  68. package/dist/infer/generated/duration.d.ts.map +1 -0
  69. package/dist/infer/generated/duration.js +9 -0
  70. package/dist/infer/generated/ip.d.ts +3 -0
  71. package/dist/infer/generated/ip.d.ts.map +1 -0
  72. package/dist/infer/generated/ip.js +9 -0
  73. package/dist/infer/generated/json.d.ts +4 -0
  74. package/dist/infer/generated/json.d.ts.map +1 -0
  75. package/dist/infer/generated/json.js +10 -0
  76. package/dist/infer/generated/list.d.ts +8 -0
  77. package/dist/infer/generated/list.d.ts.map +1 -0
  78. package/dist/infer/generated/list.js +49 -0
  79. package/dist/infer/generated/port.d.ts +4 -0
  80. package/dist/infer/generated/port.d.ts.map +1 -0
  81. package/dist/infer/generated/port.js +10 -0
  82. package/dist/infer/generated/url.d.ts +14 -0
  83. package/dist/infer/generated/url.d.ts.map +1 -0
  84. package/dist/infer/generated/url.js +30 -0
  85. package/dist/infer/generated/version.d.ts +4 -0
  86. package/dist/infer/generated/version.d.ts.map +1 -0
  87. package/dist/infer/generated/version.js +10 -0
  88. package/dist/infer/helpers.d.ts +11 -0
  89. package/dist/infer/helpers.d.ts.map +1 -0
  90. package/dist/infer/helpers.js +41 -0
  91. package/dist/infer/index.d.ts +4 -0
  92. package/dist/infer/index.d.ts.map +1 -0
  93. package/dist/infer/index.js +35 -0
  94. package/dist/infer/rules/basic.d.ts +11 -0
  95. package/dist/infer/rules/basic.d.ts.map +1 -0
  96. package/dist/infer/rules/basic.js +90 -0
  97. package/dist/infer/rules/boolean.d.ts +3 -0
  98. package/dist/infer/rules/boolean.d.ts.map +1 -0
  99. package/dist/infer/rules/boolean.js +25 -0
  100. package/dist/infer/rules/duration.d.ts +3 -0
  101. package/dist/infer/rules/duration.d.ts.map +1 -0
  102. package/dist/infer/rules/duration.js +25 -0
  103. package/dist/infer/rules/ip.d.ts +3 -0
  104. package/dist/infer/rules/ip.d.ts.map +1 -0
  105. package/dist/infer/rules/ip.js +25 -0
  106. package/dist/infer/rules/json.d.ts +3 -0
  107. package/dist/infer/rules/json.d.ts.map +1 -0
  108. package/dist/infer/rules/json.js +59 -0
  109. package/dist/infer/rules/list.d.ts +12 -0
  110. package/dist/infer/rules/list.d.ts.map +1 -0
  111. package/dist/infer/rules/list.js +221 -0
  112. package/dist/infer/rules/port.d.ts +3 -0
  113. package/dist/infer/rules/port.d.ts.map +1 -0
  114. package/dist/infer/rules/port.js +30 -0
  115. package/dist/infer/rules/url.d.ts +4 -0
  116. package/dist/infer/rules/url.d.ts.map +1 -0
  117. package/dist/infer/rules/url.js +143 -0
  118. package/dist/infer/rules/version.d.ts +3 -0
  119. package/dist/infer/rules/version.d.ts.map +1 -0
  120. package/dist/infer/rules/version.js +26 -0
  121. package/dist/infer/types.d.ts +87 -0
  122. package/dist/infer/types.d.ts.map +1 -0
  123. package/dist/infer/types.js +1 -0
  124. package/dist/infer-rules/basic.d.ts +5 -0
  125. package/dist/infer-rules/basic.d.ts.map +1 -0
  126. package/dist/infer-rules/basic.js +48 -0
  127. package/dist/infer-rules/boolean.d.ts +3 -0
  128. package/dist/infer-rules/boolean.d.ts.map +1 -0
  129. package/dist/infer-rules/boolean.js +25 -0
  130. package/dist/infer-rules/dotted.d.ts +4 -0
  131. package/dist/infer-rules/dotted.d.ts.map +1 -0
  132. package/dist/infer-rules/dotted.js +48 -0
  133. package/dist/infer-rules/duration.d.ts +3 -0
  134. package/dist/infer-rules/duration.d.ts.map +1 -0
  135. package/dist/infer-rules/duration.js +25 -0
  136. package/dist/infer-rules/index.d.ts +50 -0
  137. package/dist/infer-rules/index.d.ts.map +1 -0
  138. package/dist/infer-rules/index.js +42 -0
  139. package/dist/infer-rules/json.d.ts +3 -0
  140. package/dist/infer-rules/json.d.ts.map +1 -0
  141. package/dist/infer-rules/json.js +50 -0
  142. package/dist/infer-rules/list.d.ts +5 -0
  143. package/dist/infer-rules/list.d.ts.map +1 -0
  144. package/dist/infer-rules/list.js +200 -0
  145. package/dist/infer-rules/path.d.ts +5 -0
  146. package/dist/infer-rules/path.d.ts.map +1 -0
  147. package/dist/infer-rules/path.js +78 -0
  148. package/dist/infer-rules/port.d.ts +3 -0
  149. package/dist/infer-rules/port.d.ts.map +1 -0
  150. package/dist/infer-rules/port.js +26 -0
  151. package/dist/infer-rules/simple.d.ts +3 -0
  152. package/dist/infer-rules/simple.d.ts.map +1 -0
  153. package/dist/infer-rules/simple.js +37 -0
  154. package/dist/infer-rules/url.d.ts +4 -0
  155. package/dist/infer-rules/url.d.ts.map +1 -0
  156. package/dist/infer-rules/url.js +149 -0
  157. package/dist/llm-kit/context.json.d.ts +2 -0
  158. package/dist/llm-kit/context.json.d.ts.map +1 -0
  159. package/dist/llm-kit/context.json.js +22 -0
  160. package/dist/sample/DNLTest.d.ts +2 -0
  161. package/dist/sample/DNLTest.d.ts.map +1 -0
  162. package/dist/sample/DNLTest.js +4 -0
  163. package/dist/sample/debug.d.ts +2 -0
  164. package/dist/sample/debug.d.ts.map +1 -0
  165. package/dist/sample/debug.js +5 -0
  166. package/dist/sample/env.dnl.d.ts +426 -0
  167. package/dist/sample/env.dnl.d.ts.map +1 -0
  168. package/dist/sample/env.dnl.js +429 -0
  169. package/dist/schemas/bool.d.ts +9 -0
  170. package/dist/schemas/bool.d.ts.map +1 -0
  171. package/dist/schemas/bool.js +22 -0
  172. package/dist/schemas/boolean.d.ts +9 -0
  173. package/dist/schemas/boolean.d.ts.map +1 -0
  174. package/dist/schemas/boolean.js +23 -0
  175. package/dist/schemas/dotted.d.ts +21 -0
  176. package/dist/schemas/dotted.d.ts.map +1 -0
  177. package/dist/schemas/dotted.js +45 -0
  178. package/dist/schemas/duration.d.ts +11 -0
  179. package/dist/schemas/duration.d.ts.map +1 -0
  180. package/dist/schemas/duration.js +44 -0
  181. package/dist/schemas/index.d.ts +9 -0
  182. package/dist/schemas/index.d.ts.map +1 -0
  183. package/dist/schemas/index.js +8 -0
  184. package/dist/schemas/ip-and-version.d.ts +12 -0
  185. package/dist/schemas/ip-and-version.d.ts.map +1 -0
  186. package/dist/schemas/ip-and-version.js +35 -0
  187. package/dist/schemas/ip.d.ts +11 -0
  188. package/dist/schemas/ip.d.ts.map +1 -0
  189. package/dist/schemas/ip.js +33 -0
  190. package/dist/schemas/json.d.ts +15 -0
  191. package/dist/schemas/json.d.ts.map +1 -0
  192. package/dist/schemas/json.js +34 -0
  193. package/dist/schemas/list.d.ts +89 -0
  194. package/dist/schemas/list.d.ts.map +1 -0
  195. package/dist/schemas/list.js +139 -0
  196. package/dist/schemas/path.d.ts +23 -0
  197. package/dist/schemas/path.d.ts.map +1 -0
  198. package/dist/schemas/path.js +33 -0
  199. package/dist/schemas/port.d.ts +8 -0
  200. package/dist/schemas/port.d.ts.map +1 -0
  201. package/dist/schemas/port.js +9 -0
  202. package/dist/schemas/urls.d.ts +15 -0
  203. package/dist/schemas/urls.d.ts.map +1 -0
  204. package/dist/schemas/urls.js +54 -0
  205. package/package.json +11 -6
  206. package/dist/DnlTest.d.ts +0 -2
  207. package/dist/DnlTest.d.ts.map +0 -1
  208. package/dist/DnlTest.js +0 -12
  209. package/dist/cli/utils/exitCodes.d.ts +0 -8
  210. package/dist/cli/utils/exitCodes.d.ts.map +0 -1
  211. package/dist/cli/utils/exitCodes.js +0 -8
  212. package/dist/romaintaillandier1978-dotenv-never-lies-0.3.0.tgz +0 -0
package/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # dotenv-never-lies
2
2
 
3
+ > [!CAUTION]
4
+ > Experimental — not yet ready to use.
5
+
3
6
  > Because environment variables lie all the time.
4
7
 
5
8
  **dotenv-never-lies** validates, types, and documents your environment variables from a TypeScript / Zod schema.
@@ -28,10 +31,11 @@ And because `.env` files are:
28
31
  ## What the library does
29
32
 
30
33
  - ✅ validates environment variables at startup
34
+ powered by zod, enables complex transformations (arrays, parsing, coercion…)
35
+ - ✅ provides infer .Env to get a first real life dnl schema
31
36
  - ✅ provides reliable TypeScript typings
32
37
  - ✅ documents each variable
33
- - ✅ exposes a CLI for CI and humans
34
- - ✅ enables complex transformations (arrays, parsing, coercion…)
38
+ - ✅ exposes a CLI for CI and humans (dnl export)
35
39
 
36
40
  ---
37
41
 
@@ -98,7 +102,7 @@ NODE_CORS_ORIGIN="${FRONT_A};${FRONT_B};${FRONT_C}"
98
102
 
99
103
  The DNL schema is your new source of truth.
100
104
 
101
- (`dnl reverse-env` will help you scaffold the first skeleton)
105
+ (`dnl infer` will help you scaffold the first skeleton)
102
106
 
103
107
  ### schema location
104
108
 
@@ -135,7 +139,7 @@ export default define({
135
139
 
136
140
  NODE_PORT: {
137
141
  description: "API port",
138
- schema: z.coerce.number().default(3000),
142
+ schema: portSchema("NODE_PORT").default(3000),
139
143
  },
140
144
 
141
145
  FRONT_URL: {
@@ -169,32 +173,8 @@ JWT_SECRET: {
169
173
  }
170
174
  ```
171
175
 
172
- ### Secrets and CLI commands
173
-
174
- assert: validates secrets like any other variable
175
-
176
- reverse-env: when generating the schema, with `--guess-secret` option, the command tries to automatically identify sensitive variables (e.g. SECRET, KEY, TOKEN, PASSWORD).
177
- **This detection is heuristic and must always be reviewed and corrected manually.**
178
-
179
- export: adapts behavior depending on the target format (env, docker, CI, Kubernetes…). See the table below for details by format.
180
-
181
- ### During export
182
-
183
- Variables marked `secret: true` in the schema are treated differently depending on the export format.
184
-
185
- | Format | Secrets included by default | Maskable (`--hide-secret`) | Excludable (`--exclude-secret`) | Notes |
186
- | ------------- | --------------------------- | -------------------------- | ------------------------------- | -------------------------- |
187
- | env | yes | yes | yes | classic .env |
188
- | docker-env | yes | yes | yes | For --env-file |
189
- | docker-args | yes | yes | yes | For docker run -e |
190
- | json | yes | yes | yes | Debug / tooling |
191
- | ts | yes | yes | yes | Typed export |
192
- | js | yes | yes | yes | Runtime export |
193
- | github-env | yes | yes | yes | visible in logs |
194
- | github-secret | secrets only | no | yes | Via gh secret set |
195
- | gitlab-env | yes | yes | yes | GitLab CI variables |
196
- | k8s-configmap | yes | yes | yes | warning if secret unmasked |
197
- | k8s-secret | secrets only | yes | yes | Kubernetes Secret |
176
+ More about secrets, and usage in cli commands :
177
+ → [Read secret documentation](docs/concepts/secrets.md)
198
178
 
199
179
  ## Variable lifecycle
200
180
 
@@ -302,12 +282,13 @@ This is the recommended mode when variables are injected by the runtime or CI.
302
282
  - a value is invalid
303
283
  - the schema is not respected
304
284
 
305
- ### generate: Generate a .env file from the schema
285
+ ### init: Generate a .env file from the schema
306
286
 
307
- Generates a documented `.env` from the schema.
287
+ Initialize a documented `.env` from the schema.
288
+ Do not read any environment variables
308
289
 
309
290
  ```bash
310
- dnl generate --schema env.dnl.ts --out .env
291
+ dnl init --schema env.dnl.ts --out .env
311
292
  ```
312
293
 
313
294
  Useful for:
@@ -316,18 +297,17 @@ Useful for:
316
297
  - sharing a template
317
298
  - avoiding obsolete `.env.example` files
318
299
 
319
- ### reverse-env: Generate a schema from an existing .env
300
+ ### infer: discover a .envfile, and generate a schema from an existing .env
320
301
 
321
- Creates an `env.dnl.ts` file from a `.env`.
302
+ Generate a DNL schema from an existing `.env` file.
322
303
 
323
304
  ```bash
324
- dnl reverse-env --source .env
305
+ dnl infer --source .env
325
306
  ```
326
307
 
327
- Useful for:
308
+ Useful for migrating an existing project
328
309
 
329
- - migrating an existing project
330
- - documenting a legacy configuration afterwards
310
+ [Read infer documentation](docs/commands/infer.md)
331
311
 
332
312
  ### explain: Display variables documentation
333
313
 
@@ -402,6 +382,24 @@ printf '%s\n' "NODE_PORT=3000" >> $GITHUB_ENV
402
382
 
403
383
  There are a few more formats and options (see CLI docs `dnl export --help`).
404
384
 
385
+ ## export types : Exporting TypeScript types
386
+
387
+ `dnl export types` generates a `.d.ts` file describing the **static contract** of your environment variables.
388
+
389
+ This file is intentionally **conservative**.
390
+
391
+ ### Transformed variables
392
+
393
+ If a variable uses a Zod `transform`, the exported type always reflects the **input type**, not the runtime output.
394
+
395
+ In that case:
396
+
397
+ - a warning is emitted in the CLI
398
+ - the generated type is annotated with `@dnl-transform`
399
+ - the runtime value returned by `assert()` may differ
400
+
401
+ This is a deliberate design choice to avoid lying to TypeScript.
402
+
405
403
  ## Real-life usage
406
404
 
407
405
  ### GitIgnore
@@ -484,7 +482,7 @@ jobs:
484
482
  - run: corepack enable
485
483
  - run: yarn install --frozen-lockfile
486
484
 
487
- # Example with a .env file provided by a secret
485
+ # Example with a .env file
488
486
  - run: yarn dnl assert --source .env
489
487
  ```
490
488
 
@@ -500,8 +498,8 @@ The `.env` file can be generated from a GitHub secret or mounted dynamically.
500
498
 
501
499
  | Situation | Command to use |
502
500
  | --------------------------------------: | ------------------------------ |
503
- | New project | generate |
504
- | Existing project with a .env | reverse-env |
501
+ | New project | init |
502
+ | Existing project with a .env | infer |
505
503
  | Validate configuration in CI | assert |
506
504
  | Validate config injected by the runtime | assert |
507
505
  | Document variables | explain |
@@ -515,6 +513,69 @@ Simple rule:
515
513
  > The schema is always the source of truth.
516
514
  > Commands only validate, document, or transform.
517
515
 
516
+ ### Tips
517
+
518
+ **Alternative: minimal-intrusion integration**
519
+
520
+ For a minimally invasive integration, you can add an optional Yarn script
521
+ to validate your `.env` file before starting the application:
522
+
523
+ ```json
524
+ {
525
+ "scripts": {
526
+ "env:check": "dnl assert --source .env",
527
+ "start:withdnl": "yarn env:check && yarn start"
528
+ }
529
+ }
530
+ ```
531
+
532
+ This validates the environment before startup, without changing runtime behavior or application code.
533
+
534
+ > This is optional. It does not replace runtime validation.
535
+
536
+ **Intellisens and JSdoc for env vars**
537
+
538
+ After using `dnl export types` and importing the generated file, you get strong typing, auto-completion, IntelliSense and JSDoc for each environment variable.
539
+
540
+ ![IntelliSense and JSDoc for environment variables](docs/images/env-intellisense.png)
541
+
542
+ > IntelliSense and JSDoc generated from the DNL schema after `dnl export types`.
543
+
544
+ ## Common issues / Troubleshooting
545
+
546
+ ### TypeScript projects with `rootDir: "src"`
547
+
548
+ If your project uses a strict TypeScript setup with `rootDir: "src"`,
549
+ and your `env.dnl.ts` file is located at the project root,
550
+ TypeScript may report an error like:
551
+
552
+ > File 'env.dnl.ts' is not under 'rootDir' (TS6059)
553
+
554
+ **Option A** (preferred) :
555
+
556
+ Keeps the schema outside application code, allowing reuse by the CLI, CI, and tooling.
557
+
558
+ To fix this, include `env.dnl.ts` explicitly in your `tsconfig.json` and widen `rootDir`:
559
+
560
+ ```json
561
+ {
562
+ "compilerOptions": {
563
+ "rootDir": "."
564
+ },
565
+ "include": ["src/**/*.ts", "env.dnl.ts"]
566
+ }
567
+ ```
568
+
569
+ This ensures `env.dnl.ts` is included in the TypeScript compilation graph.
570
+
571
+ **Option B** :
572
+
573
+ Move the schema into `./src` (for example `./src/env/env.dnl.ts`).
574
+
575
+ This avoids TypeScript configuration changes, but makes the schema part of the application codebase
576
+
577
+ You will need to specify schema location, see related section
578
+
518
579
  ## FAQ / Design choices
519
580
 
520
581
  ### Why so strict?
@@ -1,7 +1,6 @@
1
- type AssertCliOptions = {
2
- schema: string;
3
- source: string;
1
+ import { ProgramCliOptions } from "./program.js";
2
+ export type AssertCliOptions = ProgramCliOptions & {
3
+ source?: string;
4
4
  };
5
5
  export declare const assertCommand: (opts?: AssertCliOptions | undefined) => Promise<void>;
6
- export {};
7
6
  //# sourceMappingURL=assert.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"assert.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/assert.ts"],"names":[],"mappings":"AAOA,KAAK,gBAAgB,GAAG;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAU,OAAO,gBAAgB,GAAG,SAAS,KAAG,OAAO,CAAC,IAAI,CAsBrF,CAAC"}
1
+ {"version":3,"file":"assert.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/assert.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,GAAG;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAU,OAAO,gBAAgB,GAAG,SAAS,KAAG,OAAO,CAAC,IAAI,CAsBrF,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { Explanation } from "../utils/printer.js";
2
- type ExplainCliOptions = {
3
- schema?: string | undefined;
2
+ import { ProgramCliOptions } from "./program.js";
3
+ export type ExplainCliOptions = ProgramCliOptions & {
4
4
  keys?: string[] | undefined;
5
5
  format?: "human" | "json" | undefined;
6
6
  };
@@ -9,5 +9,4 @@ export declare const explainCommand: (options?: ExplainCliOptions) => Promise<{
9
9
  result: Explanation[];
10
10
  }>;
11
11
  export declare const printHuman: (result: Explanation[]) => void;
12
- export {};
13
12
  //# sourceMappingURL=explain.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"explain.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/explain.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAiB,MAAM,qBAAqB,CAAC;AAGjE,KAAK,iBAAiB,GAAG;IACrB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;CACzC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAU,UAAU,iBAAiB,KAAG,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,EAAE,CAAA;CAAE,CA2B7H,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,QAAQ,WAAW,EAAE,SAqB/C,CAAC"}
1
+ {"version":3,"file":"explain.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/explain.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAiB,MAAM,qBAAqB,CAAC;AAEjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,GAAG;IAChD,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;CACzC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAU,UAAU,iBAAiB,KAAG,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,EAAE,CAAA;CAAE,CA2B7H,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,QAAQ,WAAW,EAAE,SAqB/C,CAAC"}
@@ -1,14 +1,14 @@
1
1
  import dnl from "../../index.js";
2
- export declare const exportFormatsNames: readonly ["docker-env", "docker-args", "env", "k8s-configmap", "k8s-secret", "github-env", "github-secret", "gitlab-env", "json", "ts", "js"];
2
+ import { ProgramCliOptions } from "./program.js";
3
+ export declare const exportFormatsNames: readonly ["docker-env", "docker-args", "env", "k8s-configmap", "k8s-secret", "github-env", "github-secret", "gitlab-env", "json", "ts", "js", "types"];
3
4
  export type ExportFormat = (typeof exportFormatsNames)[number];
4
5
  export type ExportResult = {
5
6
  content: string;
6
7
  warnings: string[];
7
8
  out?: string;
8
9
  };
9
- export type ExportCliOptions = {
10
+ export type ExportCliOptions = ProgramCliOptions & {
10
11
  format: ExportFormat;
11
- schema?: string | undefined;
12
12
  source?: string | undefined;
13
13
  hideSecret?: boolean;
14
14
  excludeSecret?: boolean;
@@ -32,4 +32,5 @@ export declare const exportGitlabEnv: (envDef: dnl.EnvDefinitionHelper<any>, opt
32
32
  export declare const exportJson: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
33
33
  export declare const exportTs: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
34
34
  export declare const exportJs: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
35
+ export declare const exportDts: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
35
36
  //# sourceMappingURL=export.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/export.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/export.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@ import { loadDef } from "../utils/load-schema.js";
3
3
  import { resolveSchemaPath } from "../utils/resolve-schema.js";
4
4
  import path from "path";
5
5
  import { UsageError } from "../../errors.js";
6
+ import { isRequired, isTransform, printZodTypeDts } from "../utils/printer.js";
6
7
  export const exportFormatsNames = [
7
8
  "docker-env",
8
9
  "docker-args",
@@ -15,6 +16,7 @@ export const exportFormatsNames = [
15
16
  "json",
16
17
  "ts",
17
18
  "js",
19
+ "types",
18
20
  ];
19
21
  const shellEscape = (value) => {
20
22
  if (value.length === 0) {
@@ -32,6 +34,9 @@ export const exportCommand = async (options) => {
32
34
  if (options.serializeTyped && !["js", "ts", "json"].includes(options.format)) {
33
35
  throw new UsageError("--serialize-typed is only valid for js, ts and json exports");
34
36
  }
37
+ if (options.format === "types" && options.source) {
38
+ throw new UsageError("--source is not applicable to the 'types' export format");
39
+ }
35
40
  const schemaPath = resolveSchemaPath(options?.schema);
36
41
  const envDef = (await loadDef(schemaPath));
37
42
  const warnings = [];
@@ -66,6 +71,8 @@ export const contentByFormat = (format, envDef, options, warnings) => {
66
71
  return exportDockerArgs(envDef, options, warnings);
67
72
  case "docker-env":
68
73
  return exportDockerEnv(envDef, options, warnings);
74
+ case "types":
75
+ return exportDts(envDef, options, warnings);
69
76
  default:
70
77
  throw new UsageError(`Unsupported format: ${format}`);
71
78
  }
@@ -265,4 +272,43 @@ export const exportJs = (envDef, options, warnings) => {
265
272
  }
266
273
  return `export const env = {\n${middle.join("\n")}\n};`;
267
274
  };
275
+ export const exportDts = (envDef, options, warnings) => {
276
+ const middle = [];
277
+ let transformedCount = 0;
278
+ for (const key of Object.keys(envDef.def)) {
279
+ const type = printZodTypeDts(envDef.def[key].schema.def);
280
+ const optional = isRequired(envDef.def[key].schema.def) ? "" : "?";
281
+ const transform = isTransform(envDef.def[key].schema.def);
282
+ const secret = envDef.def[key].secret;
283
+ const required = isRequired(envDef.def[key].schema.def);
284
+ const description = envDef.def[key].description;
285
+ let comment = ` /**\n * @env ${key}\n`;
286
+ if (secret)
287
+ comment += ` * @secret\n`;
288
+ if (required)
289
+ comment += ` * @required\n`;
290
+ if (description)
291
+ comment += ` * ${description}\n`;
292
+ if (transform) {
293
+ comment += ` *
294
+ * ⚠️ TRANSFORMED ENV VARIABLE
295
+ *
296
+ * Runtime type differs from declared type.
297
+ * Do NOT trust this type without checking the schema.
298
+ *
299
+ * @dnl-transform\n`;
300
+ }
301
+ comment += ` */`;
302
+ middle.push(comment);
303
+ middle.push(` ${key}${optional}: ${type};`);
304
+ if (transform) {
305
+ transformedCount++;
306
+ warnings.push(` - ${key} (@dnl-transform): runtime type differs from exported type.`);
307
+ }
308
+ }
309
+ if (transformedCount > 0) {
310
+ warnings.push(`⚠️ ${transformedCount} transformed variable detected. See @dnl-transform annotations.`);
311
+ }
312
+ return `export interface Env {\n${middle.join("\n")}\n}`;
313
+ };
268
314
  // #endregion serialisation json/ts/js
@@ -1,5 +1,5 @@
1
- export type GenerateCliOptions = {
2
- schema?: string;
1
+ import { ProgramCliOptions } from "./program.js";
2
+ export type GenerateCliOptions = ProgramCliOptions & {
3
3
  out?: string;
4
4
  includeSecret?: boolean;
5
5
  force?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,kBAAkB,GAAG;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AACF,MAAM,MAAM,cAAc,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,eAAe,GAAU,OAAO,kBAAkB,GAAG,SAAS,KAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CA6BrH,CAAC"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,GAAG;IACjD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AACF,MAAM,MAAM,cAAc,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,eAAe,GAAU,OAAO,kBAAkB,GAAG,SAAS,KAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CA6BrH,CAAC"}
@@ -0,0 +1,15 @@
1
+ export type InferCliOptions = {
2
+ source?: string;
3
+ out?: string;
4
+ force?: boolean;
5
+ dontGuessSecret?: boolean;
6
+ verbose?: boolean;
7
+ };
8
+ export type InferResult = {
9
+ content: string;
10
+ out: string;
11
+ warnings: string[];
12
+ verbose?: Array<string>;
13
+ };
14
+ export declare const inferCommand: (opts?: InferCliOptions | undefined) => Promise<InferResult>;
15
+ //# sourceMappingURL=infer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"infer.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/infer.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,eAAe,GAAG;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CAC3B,CAAC;AAEF,eAAO,MAAM,YAAY,GAAU,OAAO,eAAe,GAAG,SAAS,KAAG,OAAO,CAAC,WAAW,CA+D1F,CAAC"}
@@ -0,0 +1,86 @@
1
+ import path from "node:path";
2
+ import dnl from "../../index.js";
3
+ import { guessSecret } from "../../infer/helpers.js";
4
+ import { infer } from "../utils/infer-schema.js";
5
+ import fs from "node:fs";
6
+ import { ExportError } from "../../errors.js";
7
+ export const inferCommand = async (opts) => {
8
+ const source = path.resolve(process.cwd(), opts?.source ?? ".env");
9
+ if (!fs.existsSync(source)) {
10
+ throw new ExportError(`Source env file not found: ${source}`);
11
+ }
12
+ const out = opts?.out ?? "env.dnl.ts";
13
+ const target = path.resolve(process.cwd(), out);
14
+ if (fs.existsSync(target) && !opts?.force) {
15
+ throw new ExportError(`${out} already exists. Use --force to overwrite.`);
16
+ }
17
+ const env = dnl.readEnvFile(source);
18
+ const lines = [];
19
+ const warnings = [];
20
+ const importedSchemas = [];
21
+ const verbose = [];
22
+ lines.push(`// ⚠️ This file was generated by dotenv-never-lies`);
23
+ lines.push(`// Review and adjust schemas, descriptions and secrets before using`);
24
+ lines.push("");
25
+ lines.push(`import { z } from "zod";`);
26
+ lines.push(`import { define } from "@romaintaillandier1978/dotenv-never-lies";`);
27
+ lines.push("");
28
+ lines.push(`export default define({`);
29
+ for (const [key, value] of Object.entries(env)) {
30
+ const isValidIdentifier = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key);
31
+ const safeKey = isValidIdentifier ? key : JSON.stringify(key);
32
+ if (!isValidIdentifier) {
33
+ warnings.push(`Key ${key} is not a valid identifier. It has been escaped to ${safeKey}.`);
34
+ }
35
+ lines.push(` ${safeKey}: {`);
36
+ lines.push(` description: "TODO",`);
37
+ if (value === undefined) {
38
+ lines.push(` schema: z.string().optional(),`);
39
+ }
40
+ else {
41
+ const localWarnings = [];
42
+ const schema = infer(key, value, importedSchemas, verbose, localWarnings);
43
+ for (const warning of localWarnings) {
44
+ lines.push(" // " + warning);
45
+ }
46
+ lines.push(` schema: ${schema},`);
47
+ }
48
+ if (!opts?.dontGuessSecret && guessSecret(key)) {
49
+ lines.push(` secret: true, // ⚠️ inferred as secret`);
50
+ verbose.push(` -> inferred as secret`);
51
+ warnings.push(`${key} inferred as secret`);
52
+ }
53
+ lines.push(` },`);
54
+ }
55
+ lines.push(`});`);
56
+ // insert the imported schemas at the top of the file
57
+ insertImports(lines, importedSchemas);
58
+ return {
59
+ content: lines.join("\n"),
60
+ out: target,
61
+ warnings: [...warnings, "Generated schema is a prototype. Review schemas, descriptions and secrets before using."],
62
+ verbose,
63
+ };
64
+ };
65
+ const insertImports = (lines, imports) => {
66
+ if (!imports || imports.length === 0)
67
+ return;
68
+ const byFrom = new Map();
69
+ for (const imp of imports) {
70
+ const current = byFrom.get(imp.from) ?? new Set();
71
+ current.add(imp.name);
72
+ byFrom.set(imp.from, current);
73
+ }
74
+ const importLines = [];
75
+ // tri par 'from' pour stabilité
76
+ const froms = Array.from(byFrom.keys()).sort();
77
+ for (const from of froms) {
78
+ const names = Array.from(byFrom.get(from) ?? new Set()).sort();
79
+ if (names.length === 0)
80
+ continue;
81
+ importLines.push(`import { ${names.join(", ")} } from ${JSON.stringify(from)};`);
82
+ }
83
+ if (importLines.length === 0)
84
+ return;
85
+ lines.splice(5, 0, ...importLines);
86
+ };
@@ -0,0 +1,15 @@
1
+ import { ProgramCliOptions } from "./program.js";
2
+ export type initCliOptions = ProgramCliOptions & {
3
+ out?: string;
4
+ includeSecret?: boolean;
5
+ force?: boolean;
6
+ };
7
+ export type InitResult = {
8
+ content: string;
9
+ out: string;
10
+ };
11
+ export declare const initCommand: (opts?: initCliOptions | undefined) => Promise<{
12
+ content: string;
13
+ out: string;
14
+ }>;
15
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAAG;IAC7C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AACF,MAAM,MAAM,UAAU,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,WAAW,GAAU,OAAO,cAAc,GAAG,SAAS,KAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CA6B7G,CAAC"}
@@ -0,0 +1,30 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { loadDef } from "../utils/load-schema.js";
4
+ import { resolveSchemaPath } from "../utils/resolve-schema.js";
5
+ import { getDefaultEnvValue } from "../utils/printer.js";
6
+ import { ExportError } from "../../errors.js";
7
+ export const initCommand = async (opts) => {
8
+ const outFile = opts?.out ?? ".env";
9
+ const target = path.resolve(process.cwd(), outFile);
10
+ if (fs.existsSync(target) && !opts?.force) {
11
+ throw new ExportError(`${outFile} already exists. Use --force to overwrite.`);
12
+ }
13
+ const schemaPath = resolveSchemaPath(opts?.schema);
14
+ const envDef = (await loadDef(schemaPath));
15
+ const lines = [];
16
+ for (const [key, def] of Object.entries(envDef.def)) {
17
+ const typedDef = def;
18
+ if (typedDef.description) {
19
+ lines.push(`# ${typedDef.description}`);
20
+ }
21
+ const defaultValue = getDefaultEnvValue(typedDef.schema.def);
22
+ lines.push(`${key}=${defaultValue ?? ""}`);
23
+ lines.push(""); // blank line
24
+ }
25
+ const output = lines.join("\n");
26
+ return {
27
+ content: output,
28
+ out: target,
29
+ };
30
+ };
@@ -0,0 +1,4 @@
1
+ export type ProgramCliOptions = {
2
+ schema?: string;
3
+ };
4
+ //# sourceMappingURL=program.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/program.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC"}
@@ -0,0 +1 @@
1
+ export {};