@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/dist/cli/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { program, CommanderError } from "commander";
3
3
  import { assertCommand } from "./commands/assert.js";
4
- import { generateCommand } from "./commands/generate.js";
5
- import { reverseEnvCommand } from "./commands/reverseEnv.js";
4
+ import { initCommand } from "./commands/init.js";
5
+ import { inferCommand } from "./commands/infer.js";
6
6
  import { explainCommand, printHuman } from "./commands/explain.js";
7
7
  import { exportCommand } from "./commands/export.js";
8
8
  import { toFile } from "./utils/toFile.js";
@@ -56,7 +56,7 @@ program
56
56
  dnl generate --schema my-dnl.ts --out .env
57
57
 
58
58
  # Create an env.dnl.ts schema from an existing .env
59
- dnl reverse-env --source .env
59
+ dnl infer --source .env
60
60
 
61
61
  # Display known variables and their description
62
62
  dnl explain
@@ -71,7 +71,10 @@ program
71
71
  .command("assert")
72
72
  .description("Verifies the runtime environment and exits the process if the schema is not satisfied.")
73
73
  .option("-s, --source <source>", "Variables source (default: process.env)")
74
- .action(assertCommand)
74
+ .action(async (opts) => {
75
+ const globalOpts = program.opts();
76
+ await assertCommand({ ...opts, schema: globalOpts.schema });
77
+ })
75
78
  .addHelpText("after", `\nExamples:
76
79
 
77
80
  # Validate environment variables from process.env
@@ -102,6 +105,7 @@ const exportHelp = {
102
105
  json: "Key/value JSON object",
103
106
  ts: "Typed TypeScript object",
104
107
  js: "JavaScript object",
108
+ types: "TypeScript declaration file (.d.ts) for your environment variables",
105
109
  };
106
110
  program
107
111
  .command("export")
@@ -117,7 +121,8 @@ program
117
121
  .option("--k8s-name <name>", "Name for the k8s resource. Default: env-secret for k8s-secret, env-config for k8s-configmap")
118
122
  .option("--github-org <org>", "GitHub organization name")
119
123
  .action(async (format, opts) => {
120
- const { content, warnings, out } = await exportCommand({ ...opts, format });
124
+ const globalOpts = program.opts();
125
+ const { content, warnings, out } = await exportCommand({ ...opts, format, schema: globalOpts.schema });
121
126
  if (out) {
122
127
  await toFile(content, out, opts.force ?? false);
123
128
  }
@@ -225,49 +230,84 @@ program
225
230
  # Export variables as a typed TypeScript object, or js
226
231
  dnl export ts --out env.generated.ts --serialize-typed
227
232
  dnl export js --out env.generated.js --serialize-typed
233
+ `)
234
+ .addHelpText("after", `\nSpecific case of export types:
235
+
236
+ This command generates a TypeScript declaration file (.d.ts) describing the static contract of your environment variables.
237
+
238
+ The generated types are intentionally conservative. Zod transforms are NOT reflected in the exported types.
239
+
240
+ If a variable uses a Zod transform:
241
+ * a CLI warning is emitted
242
+ * the generated type is annotated with @dnl-transform
243
+ * the runtime value returned by assert() may differ from the declared type
244
+
245
+ The --source option is NOT applicable to this format. Only the schema is used.
246
+
247
+ # Example:
248
+ dnl export types --out src/types/env.dnl.d.ts
228
249
  `);
229
250
  // #endregion export
230
- // #region generate
251
+ // #region init
231
252
  program
232
- .command("generate")
233
- .description("Generates a .env file from a DNL schema.\n" +
253
+ .command("init")
254
+ .description("Initialize an environment file from a DNL schema.\n" +
255
+ "This command does NOT read any existing environment variables.\n" +
234
256
  "Useful to bootstrap a project or facilitate onboarding of a new developer.\n" +
235
257
  "Only default values defined in the schema are written.")
236
258
  .option("-o, --out <file>", "Output file (default: .env)")
237
259
  .option("-f, --force", "Overwrite existing file")
238
260
  .action(async (opts) => {
239
- const { content, out } = await generateCommand(opts);
261
+ const globalOpts = program.opts();
262
+ const { content, out } = await initCommand({ ...opts, schema: globalOpts.schema });
240
263
  await toFile(content, out, opts.force ?? false);
241
264
  })
242
265
  .addHelpText("after", `\nExamples:
243
266
 
244
- # Generate a .env file from the default schema (env.dnl.ts)
245
- dnl generate
267
+ # Initialize a .env file from the default DNL schema (env.dnl.ts)
268
+ dnl init
246
269
 
247
- # Generate a .env file from a specified schema
248
- dnl generate --schema my-dnl.ts
270
+ # Initialize a .env file from a specified DNL schema
271
+ dnl init --schema my-dnl.ts
249
272
 
250
- # Generate a .env.local file from the schema
251
- dnl generate --out .env.local
273
+ # Initialize a .env.local file from the DNL schema
274
+ dnl init --out .env.local
252
275
 
253
- # Generate a .env file from a schema and overwrite the existing file
254
- dnl generate --out .env --force
276
+ # Initialize a .env file from a DNL schema and overwrite the existing file
277
+ dnl init --out .env --force
255
278
  `);
256
- // #endregion generate
257
- // #region reverse-env
279
+ // #endregion init
280
+ // #region infer
258
281
  program
259
- .command("reverse-env")
282
+ .command("infer")
260
283
  .description("Generates a dotenv-never-lies schema from a .env file.\n" +
261
284
  "Useful to migrate an existing project to dotenv-never-lies.\n" +
262
285
  "The generated schema is a starting point and must be refined manually.\n" +
263
- "Keys in the .env file that are not valid identifiers are escaped to JSON strings. (e.g. MY-KEY -> 'MY-KEY')")
286
+ "Keys in the .env file that are not valid identifiers are escaped to JSON strings. (e.g. MY-KEY -> 'MY-KEY')\n" +
287
+ "By default, the command will try to guess sensitive variables (e.g. SECRET, KEY, TOKEN, PASSWORD) as secrets.\n" +
288
+ "This detection is intentionally aggressive and may flag variables that are not secrets.\n" +
289
+ "This is a deliberate design choice to avoid missing sensitive values.\n" +
290
+ "Use the --dont-guess-secret option to disable this behavior.\n" +
291
+ "\n" +
292
+ "Documentation: https://github.com/rtaillandier/dotenv-never-lies/blob/main/docs/commands/infer.md")
264
293
  .option("-s, --source <source>", "Source .env file", ".env")
265
294
  .option("-o, --out <file>", "Output DNL file", "env.dnl.ts")
266
295
  .option("-f, --force", "Overwrite existing file")
267
- .option("--guess-secret", "Try to guess sensitive variables (heuristic)")
296
+ .option("--verbose", "Verbose mode")
297
+ .option("--dont-guess-secret", "Do not try to guess sensitive variables (heuristic)")
268
298
  .action(async (opts) => {
269
- const { content, out, warnings } = await reverseEnvCommand(opts);
270
- await toFile(content, out, opts.force ?? false);
299
+ const { content, out, warnings, verbose } = await inferCommand(opts);
300
+ if (opts.verbose) {
301
+ for (const v of verbose ?? []) {
302
+ console.log(v);
303
+ }
304
+ }
305
+ if (out) {
306
+ await toFile(content, out, opts.force ?? false);
307
+ }
308
+ else {
309
+ console.log(content);
310
+ }
271
311
  for (const warning of warnings) {
272
312
  console.error(`${warning}`);
273
313
  }
@@ -275,18 +315,21 @@ program
275
315
  .addHelpText("after", `\nExamples:
276
316
 
277
317
  # Generate an env.dnl.ts schema from a .env file, try to guess sensitive variables
278
- dnl reverse-env --guess-secret
318
+ dnl infer --guess-secret
279
319
 
280
320
  # Generate an env.dnl.ts schema from a .env.local file
281
- dnl reverse-env --source .env.local
321
+ dnl infer --source .env.local
282
322
 
283
323
  # Generate a my-dnl.ts schema from a .env file
284
- dnl reverse-env --out my-dnl.ts
324
+ dnl infer --out my-dnl.ts
285
325
 
286
326
  # Generate an env.dnl.ts schema from a .env file and overwrite the existing file
287
- dnl reverse-env --force
327
+ dnl infer --force
328
+
329
+ # Full documentation:
330
+ # https://github.com/romaintaillandier1978/dotenv-never-lies/blob/main/docs/commands/infer.md
288
331
  `);
289
- // #endregion reverse-env
332
+ // #endregion infer
290
333
  // #region explain
291
334
  program
292
335
  .command("explain")
@@ -294,7 +337,8 @@ program
294
337
  .argument("[keys...]", "Keys to explain (0..N). Without argument, all keys.")
295
338
  .option("-f, --format <format>", 'Output format ("human" | "json")', "human")
296
339
  .action(async (keys, opts) => {
297
- const { format, result } = await explainCommand({ keys: keys ?? [], schema: opts.schema, format: opts.format });
340
+ const globalOpts = program.opts();
341
+ const { format, result } = await explainCommand({ keys: keys ?? [], schema: globalOpts.schema, format: opts.format });
298
342
  if (format === "human") {
299
343
  printHuman(result);
300
344
  }
@@ -1,3 +1,3 @@
1
- export declare const inferSchema: (value: string | undefined) => "z.string().optional()" | "z.coerce.boolean()" | "z.coerce.number()" | "z.string().url()" | "z.string().email()" | "z.string()";
2
- export declare const guessSecret: (value: string) => boolean;
1
+ import { Import } from "../../infer/types.js";
2
+ export declare const infer: (name: string, rawValue: string, imports: Array<Import>, verbose: Array<string>, warnings: Array<string>) => string;
3
3
  //# sourceMappingURL=infer-schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"infer-schema.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/infer-schema.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,GAAG,SAAS,oIAuBpD,CAAC;AAIF,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,YAGxC,CAAC"}
1
+ {"version":3,"file":"infer-schema.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/infer-schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,eAAO,MAAM,KAAK,GAAI,MAAM,MAAM,EAAE,UAAU,MAAM,EAAE,SAAS,KAAK,CAAC,MAAM,CAAC,EAAE,SAAS,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,KAAK,CAAC,MAAM,CAAC,KAAG,MAsB/H,CAAC"}
@@ -1,25 +1,23 @@
1
- export const inferSchema = (value) => {
2
- if (value === undefined) {
3
- return "z.string().optional()";
4
- }
5
- if (/^(true|false)$/i.test(value)) {
6
- return "z.coerce.boolean()";
7
- }
8
- if (!isNaN(Number(value))) {
9
- return "z.coerce.number()";
10
- }
11
- try {
12
- new URL(value);
13
- return "z.string().url()";
14
- }
15
- catch { }
16
- if (/^[^@]+@[^@]+\.[^@]+$/.test(value)) {
17
- return "z.string().email()";
1
+ import { RULES } from "../../infer/index.js";
2
+ export const infer = (name, rawValue, imports, verbose, warnings) => {
3
+ for (const pass of RULES) {
4
+ const result = pass.tryInfer({ name, rawValue });
5
+ if (!result)
6
+ continue;
7
+ if (result.confidence >= pass.threshold) {
8
+ verbose.push(` Infer ${name} : `);
9
+ const importedNames = result.generated.imports.map((entry) => entry.name);
10
+ verbose.push(` [${importedNames.join(", ")}] confidence: ${result.confidence} / threshold: ${pass.threshold}`);
11
+ imports.push(...result.generated.imports);
12
+ if (result.reasons) {
13
+ verbose.push(...result.reasons.map((reason) => ` ${reason}`));
14
+ }
15
+ verbose.push(` -> selected schema: ${result.generated.code}`);
16
+ if (result.warnings) {
17
+ warnings.push(...result.warnings);
18
+ }
19
+ return result.generated.code;
20
+ }
18
21
  }
19
22
  return "z.string()";
20
23
  };
21
- const secretMarkers = ["SECRET", "KEY", "TOKEN", "PASSWORD", "PASS", "AUTH"];
22
- export const guessSecret = (value) => {
23
- const parts = value.toUpperCase().split(/[_\-]/);
24
- return secretMarkers.some((marker) => parts.includes(marker));
25
- };
@@ -11,6 +11,8 @@ export type Explanation = {
11
11
  };
12
12
  export declare const toExplanation: (key: string, value: EnvVarDefinition<any>) => Explanation;
13
13
  export declare function printZodType(def: z.core.$ZodTypeDef): string;
14
+ export declare function printZodTypeDts(def: z.core.$ZodTypeDef): string;
14
15
  export declare function getDefaultEnvValue(def: z.core.$ZodTypeDef): string | undefined;
15
16
  export declare function isRequired(def: z.core.$ZodTypeDef): boolean;
17
+ export declare function isTransform(def: z.core.$ZodTypeDef): boolean;
16
18
  //# sourceMappingURL=printer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"printer.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/printer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,MAAM,WAAW,GAAG;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AACF,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,EAAE,OAAO,gBAAgB,CAAC,GAAG,CAAC,KAAG,WAWzE,CAAC;AAEF,wBAAgB,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,MAAM,CAqE5D;AAuBD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,MAAM,GAAG,SAAS,CAwB9E;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,OAAO,CAyB3D"}
1
+ {"version":3,"file":"printer.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/printer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,MAAM,WAAW,GAAG;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AACF,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,EAAE,OAAO,gBAAgB,CAAC,GAAG,CAAC,KAAG,WAWzE,CAAC;AAEF,wBAAgB,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,MAAM,CAqE5D;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,MAAM,CA6E/D;AAuBD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,MAAM,GAAG,SAAS,CAwB9E;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,OAAO,CAyB3D;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,OAAO,CAkC5D"}
@@ -20,7 +20,7 @@ export function printZodType(def) {
20
20
  case "enum":
21
21
  if ("entries" in def) {
22
22
  return Object.keys(def.entries)
23
- .map((k) => k)
23
+ .map((k) => `"${k}"`)
24
24
  .join(" | ");
25
25
  }
26
26
  return "unknown";
@@ -74,6 +74,78 @@ export function printZodType(def) {
74
74
  return "unknown";
75
75
  }
76
76
  }
77
+ export function printZodTypeDts(def) {
78
+ switch (def.type) {
79
+ case "string":
80
+ case "number":
81
+ case "boolean":
82
+ case "transform":
83
+ return def.type;
84
+ case "enum":
85
+ if ("entries" in def) {
86
+ return Object.keys(def.entries)
87
+ .map((k) => `"${k}"`)
88
+ .join(" | ");
89
+ }
90
+ return "unknown";
91
+ case "literal":
92
+ if ("values" in def) {
93
+ return JSON.stringify(def.values[0]);
94
+ }
95
+ return "unknown";
96
+ case "array":
97
+ if ("element" in def) {
98
+ return printZodTypeDts(def.element) + "[]";
99
+ }
100
+ return "[]";
101
+ case "optional":
102
+ if ("innerType" in def) {
103
+ return printZodTypeDts(def.innerType) + " | undefined";
104
+ }
105
+ return "unknown | undefined";
106
+ case "nullable":
107
+ if ("innerType" in def) {
108
+ return printZodTypeDts(def.innerType) + " | null";
109
+ }
110
+ return "unknown | null";
111
+ case "default":
112
+ //TODO : ignore les valeurs par défaut falsy (0, false, "") dans printZodType, donc dnl explain omet des defaults valides.
113
+ if ("innerType" in def) {
114
+ const result = printZodTypeDts(def.innerType);
115
+ const defaultValue = typeof def.defaultValue === "function" ? def.defaultValue() : (def.defaultValue ?? undefined);
116
+ // const defaultValue = (def as any).defaultValue;
117
+ if (defaultValue !== undefined) {
118
+ return result;
119
+ }
120
+ return result;
121
+ }
122
+ return "unknown | null";
123
+ // z.union
124
+ case "union":
125
+ if ("options" in def) {
126
+ return def.options.map(printZodTypeDts).join(" | ");
127
+ }
128
+ return "unknown";
129
+ // z.transform
130
+ case "pipe": {
131
+ if ("in" in def) {
132
+ return printZodTypeDts(def.in);
133
+ }
134
+ return "string"; // fallback défensif
135
+ }
136
+ case "transform": {
137
+ if (def.schema?.def) {
138
+ return printZodTypeDts(def.schema.def);
139
+ }
140
+ if (def.in) {
141
+ return printZodTypeDts(def.in);
142
+ }
143
+ return "string";
144
+ }
145
+ default:
146
+ return "unknown";
147
+ }
148
+ }
77
149
  function stringifyEnvValue(value) {
78
150
  if (value === undefined || value === null) {
79
151
  return undefined;
@@ -136,3 +208,34 @@ export function isRequired(def) {
136
208
  return true;
137
209
  }
138
210
  }
211
+ export function isTransform(def) {
212
+ switch (def.type) {
213
+ // Direct transform wrappers: if we see them anywhere in the tree, it's a transform.
214
+ case "pipe":
215
+ case "transform":
216
+ return true;
217
+ // Transparent wrappers: keep walking.
218
+ case "optional":
219
+ case "nullable":
220
+ case "default":
221
+ if ("innerType" in def) {
222
+ return isTransform(def.innerType);
223
+ }
224
+ return false;
225
+ // Arrays: check element.
226
+ case "array":
227
+ if ("element" in def) {
228
+ return isTransform(def.element);
229
+ }
230
+ return false;
231
+ // Unions: any option being a transform means transform.
232
+ case "union":
233
+ if ("options" in def) {
234
+ return def.options.some((opt) => isTransform(opt));
235
+ }
236
+ return false;
237
+ // Other types: no transform.
238
+ default:
239
+ return false;
240
+ }
241
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO;IAC7D;;OAEG;IACH,MAAM,EAAE,CAAC,CAAC;IACV;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAID;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,aAAa,IAAI;KAClD,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;CAC1C,CAAC;AACF;;GAEG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,aAAa,IAAI;KAC3C,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;CACnD,CAAC;AAEF,KAAK,OAAO,GAAG,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;CAAE,KAAK,OAAO,CAAC;AACzE,KAAK,QAAQ,CAAC,CAAC,SAAS,aAAa,IAAI,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;CAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC;AAEvG;;;GAGG;AACH,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,aAAa,IAAI;IACvD;;OAEG;IACH,GAAG,EAAE,CAAC,CAAC;IACP;;OAEG;IACH,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;IAC7B;;OAEG;IACH,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C;;;;;;;;OAQG;IACH,KAAK,EAAE,OAAO,CAAC;IACf;;;;;;;;;OASG;IACH,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;CACvB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,MAAM,GAAI,CAAC,SAAS,aAAa,EAAE,KAAK,CAAC,KAAG,mBAAmB,CAAC,CAAC,CAuB7E,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,KAAG,SAa1C,CAAC"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO;IAE7D;;OAEG;IACH,MAAM,EAAE,CAAC,CAAC;IACV;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CAKvB;AAID;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,aAAa,IAAI;KAClD,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;CAC1C,CAAC;AACF;;GAEG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,aAAa,IAAI;KAC3C,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;CACnD,CAAC;AAEF,KAAK,OAAO,GAAG,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;CAAE,KAAK,OAAO,CAAC;AACzE,KAAK,QAAQ,CAAC,CAAC,SAAS,aAAa,IAAI,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;CAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC;AAEvG;;;GAGG;AACH,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,aAAa,IAAI;IACvD;;OAEG;IACH,GAAG,EAAE,CAAC,CAAC;IACP;;OAEG;IACH,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;IAC7B;;OAEG;IACH,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C;;;;;;;;OAQG;IACH,KAAK,EAAE,OAAO,CAAC;IACf;;;;;;;;;OASG;IACH,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;CACvB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,MAAM,GAAI,CAAC,SAAS,aAAa,EAAE,KAAK,CAAC,KAAG,mBAAmB,CAAC,CAAC,CAuB7E,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,KAAG,SAa1C,CAAC"}
package/dist/index.d.ts CHANGED
@@ -2,4 +2,5 @@ import * as dnl from "./core.js";
2
2
  export * from "./core.js";
3
3
  export { dnl };
4
4
  export default dnl;
5
+ export * from "./schemas/index.js";
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AASjC,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,CAAC;AACf,eAAe,GAAG,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AASjC,cAAc,WAAW,CAAC;AAE1B,OAAO,EAAE,GAAG,EAAE,CAAC;AACf,eAAe,GAAG,CAAC;AAEnB,cAAc,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -6,3 +6,4 @@ if (!("ZodFirstPartyTypeKind" in z)) {
6
6
  export * from "./core.js";
7
7
  export { dnl };
8
8
  export default dnl;
9
+ export * from "./schemas/index.js";
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=port-vs-version.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port-vs-version.test.d.ts","sourceRoot":"","sources":["../../../src/infer/__tests__/port-vs-version.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,32 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { portRule } from "../rules/port.js";
3
+ import { versionRule } from "../rules/version.js";
4
+ import { versionGenSchemaNoName } from "../generated/version.js";
5
+ describe("Inference rules – port vs version", () => {
6
+ it("portRule should NOT match API_VERSION=2.0", () => {
7
+ const result = portRule.tryInfer({
8
+ name: "API_VERSION",
9
+ rawValue: "2.0",
10
+ });
11
+ // rule does not apply → null
12
+ expect(result).toBeNull();
13
+ });
14
+ it("versionRule should not match API_VERSION=2.0", () => {
15
+ const result = versionRule.tryInfer({
16
+ name: "API_VERSION",
17
+ rawValue: "2.0",
18
+ });
19
+ // rule does not recognizes a version pattern
20
+ expect(result).toBeNull();
21
+ });
22
+ it("versionRule should not match API_VERSION=2.0.0", () => {
23
+ const result = versionRule.tryInfer({
24
+ name: "API_VERSION",
25
+ rawValue: "2.0.0",
26
+ });
27
+ // rule recognizes a version pattern
28
+ expect(result).not.toBeNull();
29
+ expect(result?.generated.code).toContain(versionGenSchemaNoName.imports[0].name);
30
+ expect(result.confidence).toBeGreaterThanOrEqual(versionRule.threshold);
31
+ });
32
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=basic.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"basic.test.d.ts","sourceRoot":"","sources":["../../../../src/infer/__tests__/rules/basic.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,85 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { numberRule, emailRule, stringRule } from "../../rules/basic.js";
3
+ import { zEmailGenSchema, zNumberGenSchema, zStringGenSchema } from "../../generated/basic.js";
4
+ describe("Inference rules – basic", () => {
5
+ it("numberRule should match a valid number", () => {
6
+ const input = {
7
+ name: "NUMBER",
8
+ rawValue: "123",
9
+ };
10
+ const result = numberRule.tryInfer(input);
11
+ expect(result).not.toBeNull();
12
+ expect(result?.generated.code).toBe(zNumberGenSchema.code);
13
+ expect(result.confidence).toBeGreaterThanOrEqual(numberRule.threshold);
14
+ });
15
+ it("numberRule should match a valid number wrapped in quotes", () => {
16
+ const input = {
17
+ name: "NUMBER",
18
+ rawValue: '"123"',
19
+ };
20
+ const result = numberRule.tryInfer(input);
21
+ expect(result).not.toBeNull();
22
+ expect(result?.generated.code).toBe(zNumberGenSchema.code);
23
+ expect(result.confidence).toBeGreaterThanOrEqual(numberRule.threshold);
24
+ });
25
+ it("numberRule should match float values", () => {
26
+ const input = {
27
+ name: "RATE",
28
+ rawValue: "-12.5",
29
+ };
30
+ const result = numberRule.tryInfer(input);
31
+ expect(result).not.toBeNull();
32
+ expect(result?.generated.code).toBe(zNumberGenSchema.code);
33
+ expect(result.confidence).toBeGreaterThanOrEqual(numberRule.threshold);
34
+ });
35
+ it("numberRule should match integers outside port range", () => {
36
+ const input = {
37
+ name: "BIG_NUMBER",
38
+ rawValue: "+7e6",
39
+ };
40
+ const result = numberRule.tryInfer(input);
41
+ expect(result).not.toBeNull();
42
+ expect(result?.generated.code).toBe(zNumberGenSchema.code);
43
+ expect(result.confidence).toBeGreaterThanOrEqual(numberRule.threshold);
44
+ });
45
+ });
46
+ describe("Inference rules – email", () => {
47
+ it("emailRule should match a valid email-like value", () => {
48
+ const input = {
49
+ name: "CONTACT_EMAIL",
50
+ rawValue: "dev@example.com",
51
+ };
52
+ const result = emailRule.tryInfer(input);
53
+ expect(result).not.toBeNull();
54
+ expect(result?.generated.code).toBe(zEmailGenSchema.code);
55
+ expect(result.confidence).toBeGreaterThanOrEqual(emailRule.threshold);
56
+ });
57
+ it("emailRule should ignore non-email values", () => {
58
+ const input = {
59
+ name: "NOT_EMAIL",
60
+ rawValue: "dev@example",
61
+ };
62
+ const result = emailRule.tryInfer(input);
63
+ expect(result).toBeNull();
64
+ });
65
+ it("emailRule should ignore non-email values (database URL)", () => {
66
+ const input = {
67
+ name: "DATABASE_URL",
68
+ rawValue: "postgres://user:pass@localhost:5432/app",
69
+ };
70
+ const result = emailRule.tryInfer(input);
71
+ expect(result).toBeNull();
72
+ });
73
+ });
74
+ describe("Inference rules – string", () => {
75
+ it("stringRule should always fallback to string", () => {
76
+ const input = {
77
+ name: "ANY_VALUE",
78
+ rawValue: "whatever",
79
+ };
80
+ const result = stringRule.tryInfer(input);
81
+ expect(result).not.toBeNull();
82
+ expect(result?.generated.code).toBe(zStringGenSchema.code);
83
+ expect(result.confidence).toBeGreaterThanOrEqual(stringRule.threshold);
84
+ });
85
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=boolean.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boolean.test.d.ts","sourceRoot":"","sources":["../../../../src/infer/__tests__/rules/boolean.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,34 @@
1
+ import { booleanRule } from "../../rules/boolean.js";
2
+ import { describe, it, expect } from "vitest";
3
+ describe("Inference rules – boolean", () => {
4
+ it("booleanRule should match strict boolean values", () => {
5
+ const trueFalseValues = ["true", "false"];
6
+ for (const rawValue of trueFalseValues) {
7
+ const result = booleanRule.tryInfer({
8
+ name: "IS_ENABLED",
9
+ rawValue,
10
+ });
11
+ expect(result).not.toBeNull();
12
+ }
13
+ });
14
+ it("booleanRule should match 0 or 1 values", () => {
15
+ const zeroOneValues = ["0", "1"];
16
+ for (const rawValue of zeroOneValues) {
17
+ const result = booleanRule.tryInfer({
18
+ name: "IS_ENABLED",
19
+ rawValue,
20
+ });
21
+ expect(result).not.toBeNull();
22
+ }
23
+ });
24
+ it("booleanRule should match yes,no,y,n values", () => {
25
+ const yesNoValues = ["yes", "no", "y", "n"];
26
+ for (const rawValue of yesNoValues) {
27
+ const result = booleanRule.tryInfer({
28
+ name: "IS_ENABLED",
29
+ rawValue,
30
+ });
31
+ expect(result).not.toBeNull();
32
+ }
33
+ });
34
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=duration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duration.test.d.ts","sourceRoot":"","sources":["../../../../src/infer/__tests__/rules/duration.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { durationRule } from "../../rules/duration.js";
3
+ describe("Inference rules – duration", () => {
4
+ it("durationRule should match a valid duration", () => {
5
+ const validDurations = ["5s", "10m", "2h", "3d", "4w", "5M", "6y"];
6
+ for (const rawValue of validDurations) {
7
+ const result = durationRule.tryInfer({
8
+ name: "REQUEST_TIMEOUT",
9
+ rawValue,
10
+ });
11
+ expect(result).not.toBeNull();
12
+ }
13
+ });
14
+ it("durationRule should ignore invalid durations", () => {
15
+ const invalidDurations = ["5", "-55.5h"];
16
+ for (const rawValue of invalidDurations) {
17
+ const result = durationRule.tryInfer({
18
+ name: "REQUEST_TIMEOUT",
19
+ rawValue,
20
+ });
21
+ expect(result).toBeNull();
22
+ }
23
+ });
24
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ip.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ip.test.d.ts","sourceRoot":"","sources":["../../../../src/infer/__tests__/rules/ip.test.ts"],"names":[],"mappings":""}