@xlameiro/env-typegen 0.1.1 → 0.1.2
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/CHANGELOG.md +40 -2
- package/README.md +37 -20
- package/dist/cli.js +123 -44
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +63 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -6
- package/dist/index.d.ts +24 -6
- package/dist/index.js +63 -33
- package/dist/index.js.map +1 -1
- package/package.json +19 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Refresh the published npm package metadata and README to match the current repository documentation.
|
|
8
|
+
|
|
3
9
|
All notable changes to this project will be documented in this file.
|
|
4
10
|
|
|
5
11
|
This project adheres to [Semantic Versioning](https://semver.org/) and uses
|
|
@@ -7,7 +13,39 @@ This project adheres to [Semantic Versioning](https://semver.org/) and uses
|
|
|
7
13
|
|
|
8
14
|
<!-- Releases are added automatically by `changeset version` -->
|
|
9
15
|
|
|
10
|
-
## [0.1.
|
|
16
|
+
## [0.1.1] — 2026-03-17
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **A1** — VERSION was hardcoded as `"0.1.0"` in `cli.ts`; now read dynamically from `package.json` via `createRequire` so it stays in sync without manual edits.
|
|
21
|
+
- **A2** — Double-quotes in `@description` annotations were not escaped in the t3-generator output, corrupting the generated `createEnv(...)` call. Fixed with `.replace(/"/g, '\\"')`.
|
|
22
|
+
- **A3** — Prettier parse errors in `formatOutput` were silently swallowed; a `console.warn` is now emitted before the raw-content fallback.
|
|
23
|
+
- **A4** — Watch mode only listened for `"change"` events; it now also handles `"add"` and `"unlink"` so editor save-with-delete patterns are covered.
|
|
24
|
+
- **A5** — Config file changes during `--watch` were silently ignored; a second chokidar watcher now monitors the config file and reloads it on change.
|
|
25
|
+
- **C1** — `formatOutput` (Prettier) was called unnecessarily in dry-run mode; formatting now runs only when actually writing to disk.
|
|
26
|
+
- **C3** — Removed duplicate alias exports (`generateTypeScript`, `generateZod`); the canonical names `generateTypeScriptTypes` and `generateZodSchema` are the only public exports.
|
|
27
|
+
- **E1–E3** — README badge URLs had `YOUR_USERNAME` placeholders; replaced with the real GitHub/npm identifiers. Package name aligned to `@xlameiro/env-typegen` throughout all docs.
|
|
28
|
+
- **E4** — README `--format` example was misleading; corrected to use `--generator`/`-f` for generator selection and document `--no-format` for disabling Prettier.
|
|
29
|
+
- **E5** — `parseEnvFile` was documented as `async`/awaitable but is synchronous; removed erroneous `await` from all examples.
|
|
30
|
+
- **DRY** — `CONFIG_FILE_NAMES` was duplicated between `config.ts` and `watch.ts`; exported from `config.ts` and imported in `watch.ts`.
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- **B1** — `EnvTypegenConfig.input` now accepts `string | string[]`; CLI `--input`/`-i` can be repeated to process multiple `.env` files in one run.
|
|
35
|
+
- **B2** — `inferenceRules?: InferenceRule[]` added to `EnvTypegenConfig` and `RunGenerateOptions`; custom rules are prepended before the built-in ruleset.
|
|
36
|
+
- **B3** — Default generators changed from `["typescript"]` to all four: `["typescript", "zod", "t3", "declaration"]`, matching the spec.
|
|
37
|
+
- **B4** — Dry-run mode now prints each generated output block to stdout so users can preview content without touching the filesystem.
|
|
38
|
+
- **B5** — Watch mode debounces rapid file-change events (200 ms) to prevent multiple simultaneous pipeline runs on editor autosave.
|
|
39
|
+
|
|
40
|
+
### Tests
|
|
41
|
+
|
|
42
|
+
- Regression test for double-quotes in t3-generator descriptions (A2).
|
|
43
|
+
- CLI version tests read expected version from `package.json` (A1).
|
|
44
|
+
- Four `loadConfig()` unit tests with temp-dir fixtures (no stale state).
|
|
45
|
+
- Dry-run stdout spy test verifying preview content appears (B4).
|
|
46
|
+
- Integration tests expanded to five end-to-end scenarios via `execSync` against the built `dist/cli.js`.
|
|
47
|
+
|
|
48
|
+
[0.1.1]: https://github.com/xlameiro/env-typegen/compare/packages/env-typegen@0.1.0...packages/env-typegen@0.1.1
|
|
11
49
|
|
|
12
50
|
### Added
|
|
13
51
|
|
|
@@ -54,4 +92,4 @@ This project adheres to [Semantic Versioning](https://semver.org/) and uses
|
|
|
54
92
|
- Full TSDoc on every public export in `src/index.ts`
|
|
55
93
|
- README with Quick Start (CLI examples), Programmatic API, and Configuration sections
|
|
56
94
|
|
|
57
|
-
[0.1.0]: https://github.com/
|
|
95
|
+
[0.1.0]: https://github.com/xlameiro/env-typegen/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> From `.env.example` to TypeScript in one command.
|
|
4
4
|
|
|
5
|
-
[](https://npmjs.com/package/@xlameiro/env-typegen)
|
|
6
|
+
[](https://github.com/xlameiro/env-typegen/actions/workflows/ci.yml)
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://www.typescriptlang.org/)
|
|
9
9
|
|
|
@@ -11,31 +11,53 @@
|
|
|
11
11
|
|
|
12
12
|
`env-typegen` reads `.env.example` files and automatically generates:
|
|
13
13
|
|
|
14
|
-
- TypeScript types (`type
|
|
14
|
+
- TypeScript types (`type EnvVars = { PORT: number; DATABASE_URL: string }`)
|
|
15
15
|
- Zod v4 schemas (`z.object({ PORT: z.coerce.number() })`)
|
|
16
16
|
- `@t3-oss/env-nextjs` `createEnv` configuration
|
|
17
17
|
- `.d.ts` declaration files that augment `NodeJS.ProcessEnv`
|
|
18
18
|
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm add -D @xlameiro/env-typegen
|
|
23
|
+
# or
|
|
24
|
+
npm install --save-dev @xlameiro/env-typegen
|
|
25
|
+
```
|
|
26
|
+
|
|
19
27
|
## Quick Start
|
|
20
28
|
|
|
21
29
|
```bash
|
|
22
|
-
# Generate
|
|
30
|
+
# Generate all outputs (default: typescript + zod + t3 + declaration)
|
|
23
31
|
npx env-typegen --input .env.example --output src/env.generated.ts
|
|
24
32
|
|
|
25
|
-
# Generate a Zod schema
|
|
33
|
+
# Generate only a Zod schema
|
|
26
34
|
npx env-typegen -i .env.example -o src/env.schema.ts -g zod
|
|
27
35
|
|
|
28
|
-
# Generate multiple outputs
|
|
29
|
-
npx env-typegen -i .env.example -o src/env.ts -
|
|
36
|
+
# Generate multiple outputs explicitly
|
|
37
|
+
npx env-typegen -i .env.example -o src/env.ts -f typescript -f zod
|
|
38
|
+
|
|
39
|
+
# Generate without running Prettier
|
|
40
|
+
npx env-typegen -i .env.example -o src/env.ts --no-format
|
|
30
41
|
|
|
31
42
|
# Watch mode — regenerate on every change
|
|
32
43
|
npx env-typegen -i .env.example -o src/env.ts --watch
|
|
33
44
|
```
|
|
34
45
|
|
|
46
|
+
## Generator formats
|
|
47
|
+
|
|
48
|
+
Use `-f` / `--format` (or `-g` / `--generator` alias):
|
|
49
|
+
|
|
50
|
+
| Value | Meaning |
|
|
51
|
+
| -------------------- | ------------------------------------ |
|
|
52
|
+
| `ts` or `typescript` | Generate TypeScript types |
|
|
53
|
+
| `zod` | Generate Zod schema |
|
|
54
|
+
| `t3` | Generate `@t3-oss/env-nextjs` config |
|
|
55
|
+
| `declaration` | Generate `.d.ts` declaration |
|
|
56
|
+
|
|
35
57
|
## Programmatic API
|
|
36
58
|
|
|
37
59
|
```ts
|
|
38
|
-
import { runGenerate, parseEnvFile, generateTypeScriptTypes } from "env-typegen";
|
|
60
|
+
import { runGenerate, parseEnvFile, generateTypeScriptTypes } from "@xlameiro/env-typegen";
|
|
39
61
|
|
|
40
62
|
// High-level: full pipeline
|
|
41
63
|
await runGenerate({
|
|
@@ -46,7 +68,7 @@ await runGenerate({
|
|
|
46
68
|
});
|
|
47
69
|
|
|
48
70
|
// Low-level: parse then generate individually
|
|
49
|
-
const parsed =
|
|
71
|
+
const parsed = parseEnvFile(".env.example");
|
|
50
72
|
const ts = generateTypeScriptTypes(parsed);
|
|
51
73
|
```
|
|
52
74
|
|
|
@@ -55,7 +77,7 @@ const ts = generateTypeScriptTypes(parsed);
|
|
|
55
77
|
Create `env-typegen.config.ts` at your project root:
|
|
56
78
|
|
|
57
79
|
```ts
|
|
58
|
-
import { defineConfig } from "env-typegen";
|
|
80
|
+
import { defineConfig } from "@xlameiro/env-typegen";
|
|
59
81
|
|
|
60
82
|
export default defineConfig({
|
|
61
83
|
input: ".env.example",
|
|
@@ -67,16 +89,11 @@ export default defineConfig({
|
|
|
67
89
|
|
|
68
90
|
## Status
|
|
69
91
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
| 4 | Generators | ✅ |
|
|
76
|
-
| 5 | Config & Utils | ✅ |
|
|
77
|
-
| 6 | CLI | ✅ |
|
|
78
|
-
| 7 | Quality & Docs | ✅ |
|
|
79
|
-
| 8 | Publishing | 🔜 |
|
|
92
|
+
`env-typegen` is actively maintained and published on npm.
|
|
93
|
+
|
|
94
|
+
## Changelog
|
|
95
|
+
|
|
96
|
+
See [`CHANGELOG.md`](./CHANGELOG.md) for release notes.
|
|
80
97
|
|
|
81
98
|
## License
|
|
82
99
|
|
package/dist/cli.js
CHANGED
|
@@ -99,8 +99,9 @@ var require_picocolors = __commonJS({
|
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
// src/cli.ts
|
|
102
|
+
import { createRequire } from "module";
|
|
102
103
|
import { realpathSync } from "fs";
|
|
103
|
-
import
|
|
104
|
+
import path7 from "path";
|
|
104
105
|
import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "url";
|
|
105
106
|
import { inspect, parseArgs } from "util";
|
|
106
107
|
|
|
@@ -180,7 +181,7 @@ function generateT3Env(parsed) {
|
|
|
180
181
|
const effectiveType = variable.annotatedType ?? variable.inferredType;
|
|
181
182
|
let zodExpr = toT3ZodType(effectiveType);
|
|
182
183
|
if (variable.description !== void 0) {
|
|
183
|
-
zodExpr += `.describe("${variable.description}")`;
|
|
184
|
+
zodExpr += `.describe("${variable.description.replace(/"/g, '\\"')}")`;
|
|
184
185
|
}
|
|
185
186
|
if (variable.isOptional) {
|
|
186
187
|
zodExpr += ".optional()";
|
|
@@ -195,7 +196,7 @@ function generateT3Env(parsed) {
|
|
|
195
196
|
const effectiveType = variable.annotatedType ?? variable.inferredType;
|
|
196
197
|
let zodExpr = toT3ZodType(effectiveType);
|
|
197
198
|
if (variable.description !== void 0) {
|
|
198
|
-
zodExpr += `.describe("${variable.description}")`;
|
|
199
|
+
zodExpr += `.describe("${variable.description.replace(/"/g, '\\"')}")`;
|
|
199
200
|
}
|
|
200
201
|
if (variable.isOptional) {
|
|
201
202
|
zodExpr += ".optional()";
|
|
@@ -397,7 +398,9 @@ var inferenceRules = [
|
|
|
397
398
|
// src/inferrer/type-inferrer.ts
|
|
398
399
|
var sortedRules = [...inferenceRules].sort((left, right) => left.priority - right.priority);
|
|
399
400
|
function inferType(key, value, options) {
|
|
400
|
-
|
|
401
|
+
const extra = options?.extraRules;
|
|
402
|
+
const rules = extra && extra.length > 0 ? [...extra].sort((a, b) => a.priority - b.priority).concat(sortedRules) : sortedRules;
|
|
403
|
+
for (const rule of rules) {
|
|
401
404
|
if (rule.match(key, value)) {
|
|
402
405
|
return rule.type;
|
|
403
406
|
}
|
|
@@ -448,7 +451,7 @@ function parseCommentBlock(lines) {
|
|
|
448
451
|
// src/parser/env-parser.ts
|
|
449
452
|
var ENV_VAR_RE = /^([A-Z_][A-Z0-9_]*)=(.*)$/;
|
|
450
453
|
var SECTION_HEADER_RE = /^#\s+[-=]{3,}\s+(.+?)\s+[-=]{3,}\s*$/;
|
|
451
|
-
function parseEnvFileContent(content, filePath) {
|
|
454
|
+
function parseEnvFileContent(content, filePath, options) {
|
|
452
455
|
const lines = content.split("\n");
|
|
453
456
|
const vars = [];
|
|
454
457
|
const groups = [];
|
|
@@ -481,7 +484,11 @@ function parseEnvFileContent(content, filePath) {
|
|
|
481
484
|
const key = envMatch[1] ?? "";
|
|
482
485
|
const rawValue = envMatch[2] ?? "";
|
|
483
486
|
const annotations = parseCommentBlock(commentBlock);
|
|
484
|
-
const inferredType = inferType(
|
|
487
|
+
const inferredType = inferType(
|
|
488
|
+
key,
|
|
489
|
+
rawValue,
|
|
490
|
+
...options?.inferenceRules !== void 0 ? [{ extraRules: options.inferenceRules }] : []
|
|
491
|
+
);
|
|
485
492
|
const isRequired = rawValue.length > 0 || annotations.isRequired;
|
|
486
493
|
const isOptional = rawValue.length === 0 && !annotations.isRequired;
|
|
487
494
|
const isClientSide = key.startsWith("NEXT_PUBLIC_");
|
|
@@ -529,7 +536,11 @@ import { format } from "prettier";
|
|
|
529
536
|
async function formatOutput(content, parser = "typescript") {
|
|
530
537
|
try {
|
|
531
538
|
return await format(content, { parser });
|
|
532
|
-
} catch {
|
|
539
|
+
} catch (err) {
|
|
540
|
+
console.warn(
|
|
541
|
+
"env-typegen: Prettier formatting failed, writing unformatted output.",
|
|
542
|
+
err instanceof Error ? err.message : String(err)
|
|
543
|
+
);
|
|
533
544
|
return content;
|
|
534
545
|
}
|
|
535
546
|
}
|
|
@@ -555,6 +566,12 @@ function deriveOutputPath(base, generator, isSingle) {
|
|
|
555
566
|
const outExt = generator === "declaration" ? ".d.ts" : baseExt;
|
|
556
567
|
return `${noExt}.${generator}${outExt}`;
|
|
557
568
|
}
|
|
569
|
+
function deriveOutputBaseForInput(output, inputPath) {
|
|
570
|
+
const dir = path5.dirname(output);
|
|
571
|
+
const ext = path5.extname(output);
|
|
572
|
+
const stem = path5.basename(inputPath, path5.extname(inputPath));
|
|
573
|
+
return path5.join(dir, `${stem}${ext}`);
|
|
574
|
+
}
|
|
558
575
|
function buildOutput(generator, parsed) {
|
|
559
576
|
switch (generator) {
|
|
560
577
|
case "typescript":
|
|
@@ -580,7 +597,11 @@ async function persistOutput(params) {
|
|
|
580
597
|
}
|
|
581
598
|
if (dryRun) {
|
|
582
599
|
if (!silent) {
|
|
583
|
-
|
|
600
|
+
if (!isSingle) {
|
|
601
|
+
console.log(`// --- ${generator}: ${outputPath} ---`);
|
|
602
|
+
}
|
|
603
|
+
console.log(generated);
|
|
604
|
+
success(`Dry run: would write ${outputPath}`);
|
|
584
605
|
}
|
|
585
606
|
return;
|
|
586
607
|
}
|
|
@@ -597,47 +618,97 @@ async function runGenerate(options) {
|
|
|
597
618
|
format: shouldFormat,
|
|
598
619
|
stdout = false,
|
|
599
620
|
dryRun = false,
|
|
600
|
-
silent = false
|
|
621
|
+
silent = false,
|
|
622
|
+
inferenceRules: inferenceRules2
|
|
601
623
|
} = options;
|
|
624
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
625
|
+
const hasMultipleInputs = inputs.length > 1;
|
|
602
626
|
const isSingle = generators.length === 1;
|
|
603
|
-
const
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
627
|
+
for (const inputPath of inputs) {
|
|
628
|
+
const outputBase = hasMultipleInputs ? deriveOutputBaseForInput(output, inputPath) : output;
|
|
629
|
+
const content = await readEnvFile(inputPath);
|
|
630
|
+
const parsed = parseEnvFileContent(
|
|
631
|
+
content,
|
|
632
|
+
inputPath,
|
|
633
|
+
inferenceRules2 !== void 0 ? { inferenceRules: inferenceRules2 } : void 0
|
|
634
|
+
);
|
|
635
|
+
for (const generator of generators) {
|
|
636
|
+
let generated = buildOutput(generator, parsed);
|
|
637
|
+
if (shouldFormat && !dryRun) {
|
|
638
|
+
generated = await formatOutput(generated);
|
|
639
|
+
}
|
|
640
|
+
const outputPath = deriveOutputPath(outputBase, generator, isSingle);
|
|
641
|
+
await persistOutput({
|
|
642
|
+
generated,
|
|
643
|
+
generator,
|
|
644
|
+
outputPath,
|
|
645
|
+
isSingle,
|
|
646
|
+
stdout,
|
|
647
|
+
dryRun,
|
|
648
|
+
silent
|
|
649
|
+
});
|
|
609
650
|
}
|
|
610
|
-
const outputPath = deriveOutputPath(output, generator, isSingle);
|
|
611
|
-
await persistOutput({
|
|
612
|
-
generated,
|
|
613
|
-
generator,
|
|
614
|
-
outputPath,
|
|
615
|
-
isSingle,
|
|
616
|
-
stdout,
|
|
617
|
-
dryRun,
|
|
618
|
-
silent
|
|
619
|
-
});
|
|
620
651
|
}
|
|
621
652
|
}
|
|
622
653
|
|
|
623
654
|
// src/watch.ts
|
|
655
|
+
import path6 from "path";
|
|
624
656
|
import { watch } from "chokidar";
|
|
625
|
-
function
|
|
626
|
-
|
|
657
|
+
function debounce(fn, delay) {
|
|
658
|
+
let timer;
|
|
659
|
+
return (...args) => {
|
|
660
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
661
|
+
timer = setTimeout(() => {
|
|
662
|
+
timer = void 0;
|
|
663
|
+
fn(...args);
|
|
664
|
+
}, delay);
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
function startWatch({ inputPath, runOptions, cwd = process.cwd() }) {
|
|
668
|
+
const inputLabel = Array.isArray(inputPath) ? inputPath.join(", ") : inputPath;
|
|
669
|
+
log(`Watching ${inputLabel} for changes...`);
|
|
627
670
|
void runGenerate(runOptions).catch((err) => {
|
|
628
671
|
const message = err instanceof Error ? err.message : JSON.stringify(err);
|
|
629
672
|
error(message);
|
|
630
673
|
});
|
|
631
|
-
const
|
|
632
|
-
|
|
633
|
-
log(`${inputPath} changed, regenerating...`);
|
|
674
|
+
const handleChange = debounce((eventPath) => {
|
|
675
|
+
log(`${eventPath} changed, regenerating...`);
|
|
634
676
|
void runGenerate(runOptions).catch((err) => {
|
|
635
677
|
const message = err instanceof Error ? err.message : JSON.stringify(err);
|
|
636
678
|
error(message);
|
|
637
679
|
});
|
|
638
|
-
});
|
|
680
|
+
}, 200);
|
|
681
|
+
const handleConfigChange = debounce(async (eventPath) => {
|
|
682
|
+
log(`Config file ${eventPath} changed, reloading...`);
|
|
683
|
+
try {
|
|
684
|
+
const reloaded = await loadConfig(cwd);
|
|
685
|
+
if (reloaded) {
|
|
686
|
+
runOptions.generators = reloaded.generators ?? runOptions.generators;
|
|
687
|
+
runOptions.format = reloaded.format ?? runOptions.format;
|
|
688
|
+
if (reloaded.inferenceRules !== void 0) {
|
|
689
|
+
runOptions.inferenceRules = reloaded.inferenceRules;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
void runGenerate(runOptions).catch((err) => {
|
|
693
|
+
const message = err instanceof Error ? err.message : JSON.stringify(err);
|
|
694
|
+
error(message);
|
|
695
|
+
});
|
|
696
|
+
} catch (err) {
|
|
697
|
+
const message = err instanceof Error ? err.message : JSON.stringify(err);
|
|
698
|
+
error(`Failed to reload config: ${message}`);
|
|
699
|
+
}
|
|
700
|
+
}, 200);
|
|
701
|
+
const inputWatcher = watch(inputPath, { persistent: true });
|
|
702
|
+
for (const event of ["add", "change", "unlink"]) {
|
|
703
|
+
inputWatcher.on(event, handleChange);
|
|
704
|
+
}
|
|
705
|
+
const configPaths = CONFIG_FILE_NAMES.map((name) => path6.resolve(cwd, name));
|
|
706
|
+
const configWatcher = watch(configPaths, { persistent: true, ignoreInitial: true });
|
|
707
|
+
for (const event of ["add", "change"]) {
|
|
708
|
+
configWatcher.on(event, (eventPath) => void handleConfigChange(eventPath));
|
|
709
|
+
}
|
|
639
710
|
process.on("SIGINT", () => {
|
|
640
|
-
void
|
|
711
|
+
void Promise.all([inputWatcher.close(), configWatcher.close()]).then(() => {
|
|
641
712
|
log("Watcher stopped.");
|
|
642
713
|
process.exit(0);
|
|
643
714
|
});
|
|
@@ -645,7 +716,8 @@ function startWatch({ inputPath, runOptions }) {
|
|
|
645
716
|
}
|
|
646
717
|
|
|
647
718
|
// src/cli.ts
|
|
648
|
-
var
|
|
719
|
+
var _require = createRequire(import.meta.url);
|
|
720
|
+
var VERSION = _require("../package.json").version;
|
|
649
721
|
var HELP_TEXT = [
|
|
650
722
|
"env-typegen \u2014 Generate TypeScript types from .env.example",
|
|
651
723
|
"",
|
|
@@ -653,7 +725,7 @@ var HELP_TEXT = [
|
|
|
653
725
|
" env-typegen -i <path> [options]",
|
|
654
726
|
"",
|
|
655
727
|
"Options:",
|
|
656
|
-
" -i, --input <path> Path to .env.example file",
|
|
728
|
+
" -i, --input <path> Path to .env.example file(s). May be specified multiple times.",
|
|
657
729
|
" -o, --output <path> Output file path (default: env.generated.ts)",
|
|
658
730
|
" -f, --format <name> Generator format: ts|zod|t3|declaration",
|
|
659
731
|
" May be specified multiple times.",
|
|
@@ -684,11 +756,16 @@ function getErrorMessage(errorValue) {
|
|
|
684
756
|
return inspect(errorValue, { depth: 2 });
|
|
685
757
|
}
|
|
686
758
|
function resolveConfigRelative(value, configDir) {
|
|
687
|
-
if (value === void 0 ||
|
|
688
|
-
return
|
|
759
|
+
if (value === void 0 || path7.isAbsolute(value)) return value;
|
|
760
|
+
return path7.resolve(configDir, value);
|
|
689
761
|
}
|
|
690
762
|
function applyConfigPaths(config, configDir) {
|
|
691
|
-
|
|
763
|
+
let input;
|
|
764
|
+
if (Array.isArray(config.input)) {
|
|
765
|
+
input = config.input.map((v) => resolveConfigRelative(v, configDir) ?? v);
|
|
766
|
+
} else {
|
|
767
|
+
input = resolveConfigRelative(config.input, configDir);
|
|
768
|
+
}
|
|
692
769
|
const output = resolveConfigRelative(config.output, configDir);
|
|
693
770
|
return {
|
|
694
771
|
...config,
|
|
@@ -700,7 +777,7 @@ async function runCli(argv = process.argv.slice(2)) {
|
|
|
700
777
|
const { values } = parseArgs({
|
|
701
778
|
args: argv,
|
|
702
779
|
options: {
|
|
703
|
-
input: { type: "string", short: "i" },
|
|
780
|
+
input: { type: "string", short: "i", multiple: true },
|
|
704
781
|
output: { type: "string", short: "o" },
|
|
705
782
|
generator: { type: "string", short: "g", multiple: true },
|
|
706
783
|
format: { type: "string", short: "f", multiple: true },
|
|
@@ -726,15 +803,16 @@ async function runCli(argv = process.argv.slice(2)) {
|
|
|
726
803
|
if (values.config === void 0) {
|
|
727
804
|
fileConfig = await loadConfig(process.cwd());
|
|
728
805
|
} else {
|
|
729
|
-
const configPath =
|
|
730
|
-
const configDir =
|
|
806
|
+
const configPath = path7.resolve(values.config);
|
|
807
|
+
const configDir = path7.dirname(configPath);
|
|
731
808
|
const mod = await import(pathToFileURL2(configPath).href);
|
|
732
809
|
const rawConfig = mod.default;
|
|
733
810
|
if (rawConfig) {
|
|
734
811
|
fileConfig = applyConfigPaths(rawConfig, configDir);
|
|
735
812
|
}
|
|
736
813
|
}
|
|
737
|
-
const
|
|
814
|
+
const cliInput = values.input?.length ? values.input : void 0;
|
|
815
|
+
const input = cliInput ?? fileConfig?.input;
|
|
738
816
|
if (input === void 0) {
|
|
739
817
|
error("No input file specified. Use -i <path> or set input in env-typegen.config.ts");
|
|
740
818
|
process.exit(1);
|
|
@@ -753,7 +831,7 @@ async function runCli(argv = process.argv.slice(2)) {
|
|
|
753
831
|
}
|
|
754
832
|
generators = [...new Set(normalizedGenerators)];
|
|
755
833
|
} else {
|
|
756
|
-
generators = fileConfig?.generators ?? ["typescript"];
|
|
834
|
+
generators = fileConfig?.generators ?? ["typescript", "zod", "t3", "declaration"];
|
|
757
835
|
}
|
|
758
836
|
const shouldFormat = values["no-format"] === true ? false : fileConfig?.format ?? true;
|
|
759
837
|
const useStdout = values.stdout ?? false;
|
|
@@ -767,7 +845,8 @@ async function runCli(argv = process.argv.slice(2)) {
|
|
|
767
845
|
format: shouldFormat,
|
|
768
846
|
stdout: useStdout,
|
|
769
847
|
dryRun: isDryRun,
|
|
770
|
-
silent: isSilent
|
|
848
|
+
silent: isSilent,
|
|
849
|
+
...fileConfig?.inferenceRules !== void 0 && { inferenceRules: fileConfig.inferenceRules }
|
|
771
850
|
};
|
|
772
851
|
if (shouldWatch) {
|
|
773
852
|
startWatch({ inputPath: input, runOptions: options });
|
|
@@ -777,7 +856,7 @@ async function runCli(argv = process.argv.slice(2)) {
|
|
|
777
856
|
}
|
|
778
857
|
if (process.argv[1] !== void 0 && (() => {
|
|
779
858
|
try {
|
|
780
|
-
return realpathSync(
|
|
859
|
+
return realpathSync(path7.resolve(process.argv[1])) === realpathSync(fileURLToPath(import.meta.url));
|
|
781
860
|
} catch {
|
|
782
861
|
return false;
|
|
783
862
|
}
|