zod-envkit 1.2.1 → 1.2.3
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 +15 -0
- package/dist/cli/index.cjs +61 -23
- package/dist/cli/index.js +61 -23
- package/dist/index.cjs +8 -1
- package/dist/index.d.cts +2 -4
- package/dist/index.d.ts +2 -4
- package/dist/index.js +8 -1
- package/package.json +2 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
## [1.2.3](https://github.com/nxtxe/zod-envkit/compare/v1.2.2...v1.2.3) (2026-02-19)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* reliability polish (meta fallback, strict isolation, deterministic errors) ([a439230](https://github.com/nxtxe/zod-envkit/commit/a439230ccd06f7c7dbd70963cdfe33ed9fae9c57))
|
|
7
|
+
|
|
8
|
+
## [1.2.2](https://github.com/nxtxe/zod-envkit/compare/v1.2.1...v1.2.2) (2026-02-16)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* regenerate lockfile (remove stale link: specifier) ([19d243b](https://github.com/nxtxe/zod-envkit/commit/19d243b411f03c2044fae7f59e0c66676d1d1e90))
|
|
14
|
+
* remove self link dependency from optionalDependencies ([3fd0568](https://github.com/nxtxe/zod-envkit/commit/3fd0568f327d112f496e357962810efdb06deaee))
|
|
15
|
+
|
|
1
16
|
## [1.2.1](https://github.com/nxtxe/zod-envkit/compare/v1.2.0...v1.2.1) (2026-02-16)
|
|
2
17
|
|
|
3
18
|
|
package/dist/cli/index.cjs
CHANGED
|
@@ -33,6 +33,8 @@ var messages = {
|
|
|
33
33
|
META_TRIED: "Tried:",
|
|
34
34
|
META_TIP: "Tip:",
|
|
35
35
|
META_PARSE_FAILED: "Failed to read/parse env meta file:",
|
|
36
|
+
META_FALLBACK_EXAMPLE: "env.meta.json not found, falling back to .env.example (minimal meta).",
|
|
37
|
+
META_FALLBACK_TIP: "Tip: create env.meta.json for richer docs, grouping, and stable CLI behavior.",
|
|
36
38
|
GENERATED: "Generated: {example}, {docs}",
|
|
37
39
|
ENV_OK: "Environment looks good.",
|
|
38
40
|
MISSING_ENV: "Missing required environment variables:",
|
|
@@ -47,6 +49,8 @@ var messages = {
|
|
|
47
49
|
META_TRIED: "\u041F\u0440\u043E\u0431\u043E\u0432\u0430\u043B\u0438:",
|
|
48
50
|
META_TIP: "\u041F\u043E\u0434\u0441\u043A\u0430\u0437\u043A\u0430:",
|
|
49
51
|
META_PARSE_FAILED: "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C \u0438\u043B\u0438 \u0440\u0430\u0441\u043F\u0430\u0440\u0441\u0438\u0442\u044C env meta \u0444\u0430\u0439\u043B:",
|
|
52
|
+
META_FALLBACK_EXAMPLE: "env.meta.json \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D, \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u043C .env.example \u043A\u0430\u043A \u043C\u0438\u043D\u0438\u043C\u0430\u043B\u044C\u043D\u0443\u044E \u043C\u0435\u0442\u0443.",
|
|
53
|
+
META_FALLBACK_TIP: "\u041F\u043E\u0434\u0441\u043A\u0430\u0437\u043A\u0430: \u043B\u0443\u0447\u0448\u0435 \u0441\u043E\u0437\u0434\u0430\u0442\u044C env.meta.json \u2014 \u0431\u0443\u0434\u0435\u0442 \u0431\u043E\u0433\u0430\u0447\u0435 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u044F \u0438 \u0441\u0442\u0430\u0431\u0438\u043B\u044C\u043D\u0435\u0435 CLI-\u043A\u043E\u043D\u0442\u0440\u0430\u043A\u0442.",
|
|
50
54
|
GENERATED: "\u0421\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u043E\u0432\u0430\u043D\u043E: {example}, {docs}",
|
|
51
55
|
ENV_OK: "\u041F\u0435\u0440\u0435\u043C\u0435\u043D\u043D\u044B\u0435 \u043E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u044F \u0432 \u043F\u043E\u0440\u044F\u0434\u043A\u0435.",
|
|
52
56
|
MISSING_ENV: "\u041E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044E\u0442 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u043F\u0435\u0440\u0435\u043C\u0435\u043D\u043D\u044B\u0435 \u043E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u044F:",
|
|
@@ -59,6 +63,9 @@ var messages = {
|
|
|
59
63
|
};
|
|
60
64
|
|
|
61
65
|
// src/i18n.ts
|
|
66
|
+
function escapeRegExp(source) {
|
|
67
|
+
return source.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
68
|
+
}
|
|
62
69
|
function resolveLang(cliLang) {
|
|
63
70
|
if (cliLang === "ru" || cliLang === "en") return cliLang;
|
|
64
71
|
const envLang = process.env.LANG?.toLowerCase();
|
|
@@ -69,7 +76,8 @@ function t(lang, key, vars) {
|
|
|
69
76
|
let text = messages[lang][key] ?? messages.en[key];
|
|
70
77
|
if (vars) {
|
|
71
78
|
for (const [k, v] of Object.entries(vars)) {
|
|
72
|
-
|
|
79
|
+
const pattern = new RegExp(`\\{${escapeRegExp(k)}\\}`, "g");
|
|
80
|
+
text = text.replace(pattern, v);
|
|
73
81
|
}
|
|
74
82
|
}
|
|
75
83
|
return text;
|
|
@@ -95,6 +103,7 @@ var import_node_fs2 = __toESM(require("fs"), 1);
|
|
|
95
103
|
// src/cli/lib/meta.ts
|
|
96
104
|
var import_node_fs = __toESM(require("fs"), 1);
|
|
97
105
|
var import_node_path = __toESM(require("path"), 1);
|
|
106
|
+
var import_dotenv = __toESM(require("dotenv"), 1);
|
|
98
107
|
|
|
99
108
|
// src/cli/lib/fail.ts
|
|
100
109
|
function fail(lang, key, details) {
|
|
@@ -118,24 +127,44 @@ function resolveMetaPath(configFile) {
|
|
|
118
127
|
const found = candidates.find((p) => import_node_fs.default.existsSync(p));
|
|
119
128
|
return { candidates, found };
|
|
120
129
|
}
|
|
130
|
+
function buildMetaFromEnvExample(examplePath) {
|
|
131
|
+
const raw = import_node_fs.default.readFileSync(examplePath, "utf8");
|
|
132
|
+
const parsed = import_dotenv.default.parse(raw);
|
|
133
|
+
const meta = {};
|
|
134
|
+
const keys = Object.keys(parsed).sort((a, b) => a.localeCompare(b));
|
|
135
|
+
for (const key of keys) {
|
|
136
|
+
meta[key] = {
|
|
137
|
+
example: parsed[key] ?? "",
|
|
138
|
+
required: true,
|
|
139
|
+
description: ""
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return meta;
|
|
143
|
+
}
|
|
121
144
|
function loadMeta(lang, configFile) {
|
|
122
145
|
const { candidates, found } = resolveMetaPath(configFile);
|
|
123
|
-
if (
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
]);
|
|
146
|
+
if (found) {
|
|
147
|
+
try {
|
|
148
|
+
const raw = import_node_fs.default.readFileSync(found, "utf8");
|
|
149
|
+
return { meta: JSON.parse(raw), configPath: found };
|
|
150
|
+
} catch {
|
|
151
|
+
fail(lang, "META_PARSE_FAILED", [`- ${found}`]);
|
|
152
|
+
}
|
|
131
153
|
}
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
154
|
+
const examplePath = import_node_path.default.resolve(process.cwd(), ".env.example");
|
|
155
|
+
if (import_node_fs.default.existsSync(examplePath)) {
|
|
156
|
+
console.warn(`\u26A0\uFE0F ${t(lang, "META_FALLBACK_EXAMPLE")}`);
|
|
157
|
+
console.warn(` ${t(lang, "META_FALLBACK_TIP")}`);
|
|
158
|
+
console.warn("");
|
|
159
|
+
return { meta: buildMetaFromEnvExample(examplePath), configPath: examplePath };
|
|
138
160
|
}
|
|
161
|
+
fail(lang, "META_NOT_FOUND", [
|
|
162
|
+
t(lang, "META_TRIED"),
|
|
163
|
+
...candidates.map((p) => `- ${p}`),
|
|
164
|
+
"",
|
|
165
|
+
t(lang, "META_TIP"),
|
|
166
|
+
" npx zod-envkit show -c examples/env.meta.json"
|
|
167
|
+
]);
|
|
139
168
|
}
|
|
140
169
|
|
|
141
170
|
// src/generate.ts
|
|
@@ -345,12 +374,15 @@ function registerGenerate(program2, getLang2) {
|
|
|
345
374
|
// src/cli/lib/dotenv.ts
|
|
346
375
|
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
347
376
|
var import_node_path2 = __toESM(require("path"), 1);
|
|
348
|
-
var
|
|
377
|
+
var import_dotenv2 = __toESM(require("dotenv"), 1);
|
|
349
378
|
function resolvePath(p) {
|
|
350
379
|
return import_node_path2.default.resolve(process.cwd(), p);
|
|
351
380
|
}
|
|
352
381
|
function loadDotEnv(files) {
|
|
353
|
-
|
|
382
|
+
let list = files?.split(",").map((s) => s.trim()).filter(Boolean) ?? [".env"];
|
|
383
|
+
if (list.length === 0) {
|
|
384
|
+
list = [".env"];
|
|
385
|
+
}
|
|
354
386
|
const loaded = [];
|
|
355
387
|
const skipped = [];
|
|
356
388
|
const merged = {};
|
|
@@ -361,7 +393,7 @@ function loadDotEnv(files) {
|
|
|
361
393
|
continue;
|
|
362
394
|
}
|
|
363
395
|
const raw = import_node_fs3.default.readFileSync(abs, "utf8");
|
|
364
|
-
const parsed =
|
|
396
|
+
const parsed = import_dotenv2.default.parse(raw);
|
|
365
397
|
for (const [k, v] of Object.entries(parsed)) merged[k] = v;
|
|
366
398
|
for (const [k, v] of Object.entries(parsed)) process.env[k] = v;
|
|
367
399
|
loaded.push(f);
|
|
@@ -479,12 +511,18 @@ function isSortMode2(v) {
|
|
|
479
511
|
return v === "alpha" || v === "required-first" || v === "none";
|
|
480
512
|
}
|
|
481
513
|
function registerShow(program2, getLang2) {
|
|
482
|
-
program2.command("show").description("Show current env status (loads dotenv, masks secrets)").option("-c, --config <file>", "Path to env meta json", "env.meta.json").option("--dotenv <list>", "Comma-separated dotenv files (default: .env)", ".env").option("--mask-mode <mode>", "Mask mode (partial | full | none)"
|
|
514
|
+
program2.command("show").description("Show current env status (loads dotenv, masks secrets)").option("-c, --config <file>", "Path to env meta json", "env.meta.json").option("--dotenv <list>", "Comma-separated dotenv files (default: .env)", ".env").option("--mask-mode <mode>", "Mask mode (partial | full | none)").option("--no-mask", "Alias for --mask-mode none").option("--sort <mode>", "Sort mode (alpha | required-first | none)", "none").action((opts) => {
|
|
483
515
|
const lang = getLang2();
|
|
484
516
|
loadDotEnv(String(opts.dotenv ?? ".env"));
|
|
485
517
|
const { meta } = loadMeta(lang, String(opts.config ?? "env.meta.json"));
|
|
486
|
-
|
|
487
|
-
|
|
518
|
+
let modeRaw;
|
|
519
|
+
if (opts.mask === false) {
|
|
520
|
+
modeRaw = "none";
|
|
521
|
+
} else if (opts.maskMode) {
|
|
522
|
+
modeRaw = String(opts.maskMode);
|
|
523
|
+
} else {
|
|
524
|
+
modeRaw = "partial";
|
|
525
|
+
}
|
|
488
526
|
if (!isMaskMode(modeRaw)) {
|
|
489
527
|
console.error(`\u274C ${t(lang, "INVALID_MASK_MODE")}: ${modeRaw}`);
|
|
490
528
|
console.error(`- partial | full | none`);
|
|
@@ -540,12 +578,12 @@ function registerCheck(program2, getLang2) {
|
|
|
540
578
|
// src/cli/commands/init.ts
|
|
541
579
|
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
542
580
|
var import_node_path3 = __toESM(require("path"), 1);
|
|
543
|
-
var
|
|
581
|
+
var import_dotenv5 = __toESM(require("dotenv"), 1);
|
|
544
582
|
function readEnvFile(file) {
|
|
545
583
|
const abs = import_node_path3.default.resolve(process.cwd(), file);
|
|
546
584
|
if (!import_node_fs4.default.existsSync(abs)) return {};
|
|
547
585
|
const raw = import_node_fs4.default.readFileSync(abs, "utf8");
|
|
548
|
-
return
|
|
586
|
+
return import_dotenv5.default.parse(raw);
|
|
549
587
|
}
|
|
550
588
|
function metaFromEnv(env, defaultGroup) {
|
|
551
589
|
const meta = {};
|
package/dist/cli/index.js
CHANGED
|
@@ -17,6 +17,8 @@ var messages = {
|
|
|
17
17
|
META_TRIED: "Tried:",
|
|
18
18
|
META_TIP: "Tip:",
|
|
19
19
|
META_PARSE_FAILED: "Failed to read/parse env meta file:",
|
|
20
|
+
META_FALLBACK_EXAMPLE: "env.meta.json not found, falling back to .env.example (minimal meta).",
|
|
21
|
+
META_FALLBACK_TIP: "Tip: create env.meta.json for richer docs, grouping, and stable CLI behavior.",
|
|
20
22
|
GENERATED: "Generated: {example}, {docs}",
|
|
21
23
|
ENV_OK: "Environment looks good.",
|
|
22
24
|
MISSING_ENV: "Missing required environment variables:",
|
|
@@ -31,6 +33,8 @@ var messages = {
|
|
|
31
33
|
META_TRIED: "\u041F\u0440\u043E\u0431\u043E\u0432\u0430\u043B\u0438:",
|
|
32
34
|
META_TIP: "\u041F\u043E\u0434\u0441\u043A\u0430\u0437\u043A\u0430:",
|
|
33
35
|
META_PARSE_FAILED: "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C \u0438\u043B\u0438 \u0440\u0430\u0441\u043F\u0430\u0440\u0441\u0438\u0442\u044C env meta \u0444\u0430\u0439\u043B:",
|
|
36
|
+
META_FALLBACK_EXAMPLE: "env.meta.json \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D, \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u043C .env.example \u043A\u0430\u043A \u043C\u0438\u043D\u0438\u043C\u0430\u043B\u044C\u043D\u0443\u044E \u043C\u0435\u0442\u0443.",
|
|
37
|
+
META_FALLBACK_TIP: "\u041F\u043E\u0434\u0441\u043A\u0430\u0437\u043A\u0430: \u043B\u0443\u0447\u0448\u0435 \u0441\u043E\u0437\u0434\u0430\u0442\u044C env.meta.json \u2014 \u0431\u0443\u0434\u0435\u0442 \u0431\u043E\u0433\u0430\u0447\u0435 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u044F \u0438 \u0441\u0442\u0430\u0431\u0438\u043B\u044C\u043D\u0435\u0435 CLI-\u043A\u043E\u043D\u0442\u0440\u0430\u043A\u0442.",
|
|
34
38
|
GENERATED: "\u0421\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u043E\u0432\u0430\u043D\u043E: {example}, {docs}",
|
|
35
39
|
ENV_OK: "\u041F\u0435\u0440\u0435\u043C\u0435\u043D\u043D\u044B\u0435 \u043E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u044F \u0432 \u043F\u043E\u0440\u044F\u0434\u043A\u0435.",
|
|
36
40
|
MISSING_ENV: "\u041E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044E\u0442 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u043F\u0435\u0440\u0435\u043C\u0435\u043D\u043D\u044B\u0435 \u043E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u044F:",
|
|
@@ -43,6 +47,9 @@ var messages = {
|
|
|
43
47
|
};
|
|
44
48
|
|
|
45
49
|
// src/i18n.ts
|
|
50
|
+
function escapeRegExp(source) {
|
|
51
|
+
return source.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
52
|
+
}
|
|
46
53
|
function resolveLang(cliLang) {
|
|
47
54
|
if (cliLang === "ru" || cliLang === "en") return cliLang;
|
|
48
55
|
const envLang = process.env.LANG?.toLowerCase();
|
|
@@ -53,7 +60,8 @@ function t(lang, key, vars) {
|
|
|
53
60
|
let text = messages[lang][key] ?? messages.en[key];
|
|
54
61
|
if (vars) {
|
|
55
62
|
for (const [k, v] of Object.entries(vars)) {
|
|
56
|
-
|
|
63
|
+
const pattern = new RegExp(`\\{${escapeRegExp(k)}\\}`, "g");
|
|
64
|
+
text = text.replace(pattern, v);
|
|
57
65
|
}
|
|
58
66
|
}
|
|
59
67
|
return text;
|
|
@@ -79,6 +87,7 @@ import fs2 from "fs";
|
|
|
79
87
|
// src/cli/lib/meta.ts
|
|
80
88
|
import fs from "fs";
|
|
81
89
|
import path from "path";
|
|
90
|
+
import dotenv from "dotenv";
|
|
82
91
|
|
|
83
92
|
// src/cli/lib/fail.ts
|
|
84
93
|
function fail(lang, key, details) {
|
|
@@ -102,24 +111,44 @@ function resolveMetaPath(configFile) {
|
|
|
102
111
|
const found = candidates.find((p) => fs.existsSync(p));
|
|
103
112
|
return { candidates, found };
|
|
104
113
|
}
|
|
114
|
+
function buildMetaFromEnvExample(examplePath) {
|
|
115
|
+
const raw = fs.readFileSync(examplePath, "utf8");
|
|
116
|
+
const parsed = dotenv.parse(raw);
|
|
117
|
+
const meta = {};
|
|
118
|
+
const keys = Object.keys(parsed).sort((a, b) => a.localeCompare(b));
|
|
119
|
+
for (const key of keys) {
|
|
120
|
+
meta[key] = {
|
|
121
|
+
example: parsed[key] ?? "",
|
|
122
|
+
required: true,
|
|
123
|
+
description: ""
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
return meta;
|
|
127
|
+
}
|
|
105
128
|
function loadMeta(lang, configFile) {
|
|
106
129
|
const { candidates, found } = resolveMetaPath(configFile);
|
|
107
|
-
if (
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
]);
|
|
130
|
+
if (found) {
|
|
131
|
+
try {
|
|
132
|
+
const raw = fs.readFileSync(found, "utf8");
|
|
133
|
+
return { meta: JSON.parse(raw), configPath: found };
|
|
134
|
+
} catch {
|
|
135
|
+
fail(lang, "META_PARSE_FAILED", [`- ${found}`]);
|
|
136
|
+
}
|
|
115
137
|
}
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
138
|
+
const examplePath = path.resolve(process.cwd(), ".env.example");
|
|
139
|
+
if (fs.existsSync(examplePath)) {
|
|
140
|
+
console.warn(`\u26A0\uFE0F ${t(lang, "META_FALLBACK_EXAMPLE")}`);
|
|
141
|
+
console.warn(` ${t(lang, "META_FALLBACK_TIP")}`);
|
|
142
|
+
console.warn("");
|
|
143
|
+
return { meta: buildMetaFromEnvExample(examplePath), configPath: examplePath };
|
|
122
144
|
}
|
|
145
|
+
fail(lang, "META_NOT_FOUND", [
|
|
146
|
+
t(lang, "META_TRIED"),
|
|
147
|
+
...candidates.map((p) => `- ${p}`),
|
|
148
|
+
"",
|
|
149
|
+
t(lang, "META_TIP"),
|
|
150
|
+
" npx zod-envkit show -c examples/env.meta.json"
|
|
151
|
+
]);
|
|
123
152
|
}
|
|
124
153
|
|
|
125
154
|
// src/cli/commands/generate.ts
|
|
@@ -166,12 +195,15 @@ function registerGenerate(program2, getLang2) {
|
|
|
166
195
|
// src/cli/lib/dotenv.ts
|
|
167
196
|
import fs3 from "fs";
|
|
168
197
|
import path2 from "path";
|
|
169
|
-
import
|
|
198
|
+
import dotenv2 from "dotenv";
|
|
170
199
|
function resolvePath(p) {
|
|
171
200
|
return path2.resolve(process.cwd(), p);
|
|
172
201
|
}
|
|
173
202
|
function loadDotEnv(files) {
|
|
174
|
-
|
|
203
|
+
let list = files?.split(",").map((s) => s.trim()).filter(Boolean) ?? [".env"];
|
|
204
|
+
if (list.length === 0) {
|
|
205
|
+
list = [".env"];
|
|
206
|
+
}
|
|
175
207
|
const loaded = [];
|
|
176
208
|
const skipped = [];
|
|
177
209
|
const merged = {};
|
|
@@ -182,7 +214,7 @@ function loadDotEnv(files) {
|
|
|
182
214
|
continue;
|
|
183
215
|
}
|
|
184
216
|
const raw = fs3.readFileSync(abs, "utf8");
|
|
185
|
-
const parsed =
|
|
217
|
+
const parsed = dotenv2.parse(raw);
|
|
186
218
|
for (const [k, v] of Object.entries(parsed)) merged[k] = v;
|
|
187
219
|
for (const [k, v] of Object.entries(parsed)) process.env[k] = v;
|
|
188
220
|
loaded.push(f);
|
|
@@ -267,12 +299,18 @@ function isSortMode2(v) {
|
|
|
267
299
|
return v === "alpha" || v === "required-first" || v === "none";
|
|
268
300
|
}
|
|
269
301
|
function registerShow(program2, getLang2) {
|
|
270
|
-
program2.command("show").description("Show current env status (loads dotenv, masks secrets)").option("-c, --config <file>", "Path to env meta json", "env.meta.json").option("--dotenv <list>", "Comma-separated dotenv files (default: .env)", ".env").option("--mask-mode <mode>", "Mask mode (partial | full | none)"
|
|
302
|
+
program2.command("show").description("Show current env status (loads dotenv, masks secrets)").option("-c, --config <file>", "Path to env meta json", "env.meta.json").option("--dotenv <list>", "Comma-separated dotenv files (default: .env)", ".env").option("--mask-mode <mode>", "Mask mode (partial | full | none)").option("--no-mask", "Alias for --mask-mode none").option("--sort <mode>", "Sort mode (alpha | required-first | none)", "none").action((opts) => {
|
|
271
303
|
const lang = getLang2();
|
|
272
304
|
loadDotEnv(String(opts.dotenv ?? ".env"));
|
|
273
305
|
const { meta } = loadMeta(lang, String(opts.config ?? "env.meta.json"));
|
|
274
|
-
|
|
275
|
-
|
|
306
|
+
let modeRaw;
|
|
307
|
+
if (opts.mask === false) {
|
|
308
|
+
modeRaw = "none";
|
|
309
|
+
} else if (opts.maskMode) {
|
|
310
|
+
modeRaw = String(opts.maskMode);
|
|
311
|
+
} else {
|
|
312
|
+
modeRaw = "partial";
|
|
313
|
+
}
|
|
276
314
|
if (!isMaskMode(modeRaw)) {
|
|
277
315
|
console.error(`\u274C ${t(lang, "INVALID_MASK_MODE")}: ${modeRaw}`);
|
|
278
316
|
console.error(`- partial | full | none`);
|
|
@@ -328,12 +366,12 @@ function registerCheck(program2, getLang2) {
|
|
|
328
366
|
// src/cli/commands/init.ts
|
|
329
367
|
import fs4 from "fs";
|
|
330
368
|
import path3 from "path";
|
|
331
|
-
import
|
|
369
|
+
import dotenv3 from "dotenv";
|
|
332
370
|
function readEnvFile(file) {
|
|
333
371
|
const abs = path3.resolve(process.cwd(), file);
|
|
334
372
|
if (!fs4.existsSync(abs)) return {};
|
|
335
373
|
const raw = fs4.readFileSync(abs, "utf8");
|
|
336
|
-
return
|
|
374
|
+
return dotenv3.parse(raw);
|
|
337
375
|
}
|
|
338
376
|
function metaFromEnv(env, defaultGroup) {
|
|
339
377
|
const meta = {};
|
package/dist/index.cjs
CHANGED
|
@@ -247,7 +247,14 @@ function mustLoadEnv(schema) {
|
|
|
247
247
|
throw res.error;
|
|
248
248
|
}
|
|
249
249
|
function formatZodError(err) {
|
|
250
|
-
return err.issues.
|
|
250
|
+
return err.issues.slice().sort((a, b) => {
|
|
251
|
+
const pa = a.path.length ? a.path.join(".") : "";
|
|
252
|
+
const pb = b.path.length ? b.path.join(".") : "";
|
|
253
|
+
return pa.localeCompare(pb);
|
|
254
|
+
}).map((issue) => {
|
|
255
|
+
const path = issue.path.length ? issue.path.join(".") : "(root)";
|
|
256
|
+
return `- ${path}: ${issue.message.trim()}`;
|
|
257
|
+
}).join("\n");
|
|
251
258
|
}
|
|
252
259
|
// Annotate the CommonJS export names for ESM import in node:
|
|
253
260
|
0 && (module.exports = {
|
package/dist/index.d.cts
CHANGED
|
@@ -274,10 +274,8 @@ declare function mustLoadEnv<T extends z.ZodTypeAny>(schema: T): z.infer<T>;
|
|
|
274
274
|
/**
|
|
275
275
|
* Format `ZodError` into a human-friendly multi-line message (one issue per line).
|
|
276
276
|
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
* console.error("Invalid environment:\n" + formatZodError(err));
|
|
280
|
-
* ```
|
|
277
|
+
* Output format (stable in 1.x):
|
|
278
|
+
* - path: message
|
|
281
279
|
*
|
|
282
280
|
* @public
|
|
283
281
|
* @since 1.0.0
|
package/dist/index.d.ts
CHANGED
|
@@ -274,10 +274,8 @@ declare function mustLoadEnv<T extends z.ZodTypeAny>(schema: T): z.infer<T>;
|
|
|
274
274
|
/**
|
|
275
275
|
* Format `ZodError` into a human-friendly multi-line message (one issue per line).
|
|
276
276
|
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
* console.error("Invalid environment:\n" + formatZodError(err));
|
|
280
|
-
* ```
|
|
277
|
+
* Output format (stable in 1.x):
|
|
278
|
+
* - path: message
|
|
281
279
|
*
|
|
282
280
|
* @public
|
|
283
281
|
* @since 1.0.0
|
package/dist/index.js
CHANGED
|
@@ -21,7 +21,14 @@ function mustLoadEnv(schema) {
|
|
|
21
21
|
throw res.error;
|
|
22
22
|
}
|
|
23
23
|
function formatZodError(err) {
|
|
24
|
-
return err.issues.
|
|
24
|
+
return err.issues.slice().sort((a, b) => {
|
|
25
|
+
const pa = a.path.length ? a.path.join(".") : "";
|
|
26
|
+
const pb = b.path.length ? b.path.join(".") : "";
|
|
27
|
+
return pa.localeCompare(pb);
|
|
28
|
+
}).map((issue) => {
|
|
29
|
+
const path = issue.path.length ? issue.path.join(".") : "(root)";
|
|
30
|
+
return `- ${path}: ${issue.message.trim()}`;
|
|
31
|
+
}).join("\n");
|
|
25
32
|
}
|
|
26
33
|
export {
|
|
27
34
|
checkEnv,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zod-envkit",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "Validate environment variables with Zod and generate .env.example",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "",
|
|
@@ -60,8 +60,7 @@
|
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"commander": "^13.1.0",
|
|
62
62
|
"dotenv": "^17.2.3",
|
|
63
|
-
"zod": "^4.3.6"
|
|
64
|
-
"zod-envkit": "link:"
|
|
63
|
+
"zod": "^4.3.6"
|
|
65
64
|
},
|
|
66
65
|
"devDependencies": {
|
|
67
66
|
"@semantic-release/changelog": "^6.0.3",
|