zenvx 0.2.1 → 1.0.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.
- package/README.md +11 -120
- package/dist/{chunk-3HCQKBTL.js → chunk-AUT6ZOMV.js} +6 -5
- package/dist/{chunk-R2XSSP2M.js → chunk-BPXBRFJ2.js} +9 -8
- package/dist/{chunk-ELPQSMQJ.js → chunk-LL4MFOXJ.js} +6 -5
- package/dist/core/define-env.cjs +38 -36
- package/dist/core/define-env.d.cts +2 -2
- package/dist/core/define-env.d.ts +2 -2
- package/dist/core/define-env.js +2 -2
- package/dist/core/parser.cjs +6 -5
- package/dist/core/parser.d.cts +5 -2
- package/dist/core/parser.d.ts +5 -2
- package/dist/core/parser.js +1 -1
- package/dist/core/types.d.cts +1 -1
- package/dist/core/types.d.ts +1 -1
- package/dist/index.cjs +40 -106
- package/dist/index.d.cts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +3 -7
- package/package.json +2 -23
- package/dist/adapters/next.cjs +0 -151
- package/dist/adapters/next.d.cts +0 -6
- package/dist/adapters/next.d.ts +0 -6
- package/dist/adapters/next.js +0 -32
- package/dist/adapters/node.cjs +0 -135
- package/dist/adapters/node.d.cts +0 -5
- package/dist/adapters/node.d.ts +0 -5
- package/dist/adapters/node.js +0 -17
- package/dist/adapters/vite.cjs +0 -135
- package/dist/adapters/vite.d.cts +0 -5
- package/dist/adapters/vite.d.ts +0 -5
- package/dist/adapters/vite.js +0 -16
- package/dist/chunk-E7OYVDFC.js +0 -67
- package/dist/core/tx.cjs +0 -91
- package/dist/core/tx.d.cts +0 -42
- package/dist/core/tx.d.ts +0 -42
- package/dist/core/tx.js +0 -6
package/README.md
CHANGED
|
@@ -35,7 +35,6 @@ Standard Zod is great, but environment variables are always strings. This leads
|
|
|
35
35
|
- ✅ Seamless TypeScript integration
|
|
36
36
|
- ✅ `.env.example` auto-generation
|
|
37
37
|
- ✅ Runtime **and** build-time validation modes
|
|
38
|
-
- ✅ Framework adapters: Node.js, Next.js (server + client), Vite
|
|
39
38
|
|
|
40
39
|
## Installation
|
|
41
40
|
|
|
@@ -54,20 +53,17 @@ yarn add zenvx zod
|
|
|
54
53
|
Create a file (e.g., src/env.ts) and export your configuration:
|
|
55
54
|
|
|
56
55
|
```ts
|
|
57
|
-
import { defineEnv
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
PORT:
|
|
62
|
-
DEBUG:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
DATABASE_URL: tx.url(), // Must be a valid URL
|
|
66
|
-
API_KEY: tx.string(), // "12345" will FAIL (Must be text)
|
|
67
|
-
|
|
68
|
-
// 3. Native Zod Support (optional)
|
|
69
|
-
NODE_ENV: tx.enum(["development", "production"]),
|
|
56
|
+
import { defineEnv } from "zenvx";
|
|
57
|
+
import z from "zod";
|
|
58
|
+
|
|
59
|
+
const schema = z.object({
|
|
60
|
+
PORT: z.coerce.number().int().min(1).max(65535),
|
|
61
|
+
DEBUG: z.preprocess((v) => v === "true" || v === "1", z.boolean()),
|
|
62
|
+
DATABASE_URL: z.string().url(),
|
|
63
|
+
CLOUDINARY_API_KEY: z.string(),
|
|
70
64
|
});
|
|
65
|
+
|
|
66
|
+
export const env = defineEnv(schema);
|
|
71
67
|
```
|
|
72
68
|
|
|
73
69
|
Now use it anywhere in your app:
|
|
@@ -79,75 +75,12 @@ console.log(`Server running on port ${env.PORT}`);
|
|
|
79
75
|
// TypeScript knows env.PORT is a number!
|
|
80
76
|
```
|
|
81
77
|
|
|
82
|
-
## Framework Adapters
|
|
83
|
-
|
|
84
|
-
zenvx supports different frameworks with adapters for proper environment handling.
|
|
85
|
-
|
|
86
|
-
### Node.js
|
|
87
|
-
|
|
88
|
-
```ts
|
|
89
|
-
import { loadNodeEnv } from "zenvx/node";
|
|
90
|
-
|
|
91
|
-
const env = loadNodeEnv({
|
|
92
|
-
PORT: tx.port(),
|
|
93
|
-
DEBUG: tx.bool(),
|
|
94
|
-
});
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
> Note: In Node.js, you must install dotenv separately and load it (e.g., via import "dotenv/config" or dotenv.config()) before calling loadNodeEnv().
|
|
98
|
-
|
|
99
|
-
### Next.js
|
|
100
|
-
|
|
101
|
-
Server-side
|
|
102
|
-
|
|
103
|
-
```ts
|
|
104
|
-
import { loadServerEnv } from "zenvx/next";
|
|
105
|
-
|
|
106
|
-
const env = loadServerEnv({
|
|
107
|
-
PORT: tx.port(),
|
|
108
|
-
SECRET_KEY: tx.string(),
|
|
109
|
-
});
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Client-side (only NEXT*PUBLIC*\* allowed):
|
|
113
|
-
|
|
114
|
-
```ts
|
|
115
|
-
import { loadClientEnv } from "zenvx/next";
|
|
116
|
-
|
|
117
|
-
const env = loadClientEnv({
|
|
118
|
-
NEXT_PUBLIC_API_URL: tx.string(),
|
|
119
|
-
NEXT_PUBLIC_DEBUG: tx.bool(),
|
|
120
|
-
});
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
> Attempting to access a key without NEXT*PUBLIC* in client env throws an error.
|
|
124
|
-
|
|
125
|
-
### Vite
|
|
126
|
-
|
|
127
|
-
```ts
|
|
128
|
-
import { loadViteEnv } from "zenvx/vite";
|
|
129
|
-
|
|
130
|
-
const env = loadViteEnv({
|
|
131
|
-
VITE_API_URL: tx.string(),
|
|
132
|
-
VITE_DEBUG: tx.bool(),
|
|
133
|
-
});
|
|
134
|
-
```
|
|
135
|
-
|
|
136
78
|
## .env.example Auto-Generation
|
|
137
79
|
|
|
138
80
|
zenvx can automatically generate a .env.example file from your schema — keeping your documentation always in sync.
|
|
139
81
|
|
|
140
82
|
```ts
|
|
141
|
-
defineEnv(
|
|
142
|
-
{
|
|
143
|
-
DATABASE_URL: tx.url(),
|
|
144
|
-
PORT: tx.port().default(3000),
|
|
145
|
-
DEBUG: tx.bool(),
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
generateExample: true,
|
|
149
|
-
},
|
|
150
|
-
);
|
|
83
|
+
defineEnv(schema, { generateExample: true });
|
|
151
84
|
```
|
|
152
85
|
|
|
153
86
|
This produces:
|
|
@@ -216,45 +149,3 @@ PORT: Must be a valid port (1-65535)
|
|
|
216
149
|
API_KEY: Value should be text, but looks like a number.
|
|
217
150
|
DATABASE_URL: Must be a valid URL
|
|
218
151
|
```
|
|
219
|
-
|
|
220
|
-
# The `tx` Validator Helper
|
|
221
|
-
|
|
222
|
-
`zenvx` provides a `tx` object with pre-configured Zod schemas optimized for `.env` files.
|
|
223
|
-
|
|
224
|
-
| Validator | Description | Example Input (.env) | Result (JS) |
|
|
225
|
-
| ---------------- | ------------------------------------------------------------------ | -------------------- | --------------- |
|
|
226
|
-
| `tx.string()` | Strict string. Rejects purely numeric values (prevents lazy keys). | `abc_key` | `"abc_key"` |
|
|
227
|
-
| `tx.number()` | Coerces string to number. | `"50"` | `50` |
|
|
228
|
-
| `tx.bool()` | Smart boolean. Accepts true, false, 1, 0. | `"true"`, `"1"` | `true` |
|
|
229
|
-
| `tx.port()` | Validates port range (1-65535). | `"3000"` | `3000` |
|
|
230
|
-
| `tx.url()` | Strict URL validation. | `"https://site.com"` | `"https://..."` |
|
|
231
|
-
| `tx.email()` | Valid email address. | `"admin@app.com"` | `"admin@..."` |
|
|
232
|
-
| `tx.json()` | Parses a JSON string into an Object. | `{"foo":"bar"}` | `{foo: "bar"}` |
|
|
233
|
-
| `tx.enum([...])` | Strict allow-list. | `"PROD"` | `"PROD"` |
|
|
234
|
-
|
|
235
|
-
## Customizing Error Messages
|
|
236
|
-
|
|
237
|
-
Every tx validator accepts an optional custom error message.
|
|
238
|
-
|
|
239
|
-
```ts
|
|
240
|
-
export const env = defineEnv({
|
|
241
|
-
API_KEY: tx.string("Please provide a REAL API Key, not just numbers!"),
|
|
242
|
-
PORT: tx.port("Port is invalid or out of range"),
|
|
243
|
-
});
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
## Mixing with Standard Zod
|
|
247
|
-
|
|
248
|
-
You can mix tx helpers with standard Zod schemas if you need specific logic.
|
|
249
|
-
|
|
250
|
-
```ts
|
|
251
|
-
import { defineEnv, tx } from "zenvx";
|
|
252
|
-
import { z } from "zod";
|
|
253
|
-
|
|
254
|
-
export const env = defineEnv({
|
|
255
|
-
PORT: tx.port(),
|
|
256
|
-
|
|
257
|
-
// Standard Zod Schema
|
|
258
|
-
APP_NAME: z.string().min(5).default("My Super App"),
|
|
259
|
-
});
|
|
260
|
-
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/core/parser.ts
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
function parseEnv(schema, source, options) {
|
|
3
|
+
const mode = options?.mode ?? "runtime";
|
|
4
4
|
const result = schema.safeParse(source);
|
|
5
5
|
if (!result.success) {
|
|
6
6
|
const issues = result.error.issues.map((i) => `\u274C ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
@@ -16,12 +16,13 @@ function parseEnv(schema, source, mode = "runtime") {
|
|
|
16
16
|
const box = ["", ...header, issues, ""].join("\n");
|
|
17
17
|
if (mode === "build") {
|
|
18
18
|
throw new Error(box);
|
|
19
|
-
}
|
|
20
|
-
|
|
19
|
+
}
|
|
20
|
+
console.warn(box);
|
|
21
|
+
if (options?.exitOnFail ?? true) {
|
|
21
22
|
process.exit(1);
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
|
-
return result.
|
|
25
|
+
return result.data;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
export {
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createTypedProxy
|
|
3
|
-
} from "./chunk-DX3SLVGQ.js";
|
|
4
1
|
import {
|
|
5
2
|
generateExample
|
|
6
3
|
} from "./chunk-KGVPNFG3.js";
|
|
7
4
|
import {
|
|
8
5
|
parseEnv
|
|
9
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-AUT6ZOMV.js";
|
|
7
|
+
import {
|
|
8
|
+
createTypedProxy
|
|
9
|
+
} from "./chunk-DX3SLVGQ.js";
|
|
10
10
|
|
|
11
11
|
// src/core/define-env.ts
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
function defineEnv(schema, source, options) {
|
|
13
|
+
const parsed = parseEnv(schema, source, {
|
|
14
|
+
exitOnFail: options?.exitOnFail ?? false,
|
|
15
|
+
mode: options?.mode ?? "runtime"
|
|
16
|
+
});
|
|
16
17
|
if (options?.generateExample) {
|
|
17
18
|
generateExample(schema);
|
|
18
19
|
}
|
|
@@ -3,16 +3,17 @@ import {
|
|
|
3
3
|
} from "./chunk-KGVPNFG3.js";
|
|
4
4
|
import {
|
|
5
5
|
parseEnv
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-AUT6ZOMV.js";
|
|
7
7
|
import {
|
|
8
8
|
createTypedProxy
|
|
9
9
|
} from "./chunk-DX3SLVGQ.js";
|
|
10
10
|
|
|
11
11
|
// src/core/define-env.ts
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
function defineEnv(schema, options) {
|
|
13
|
+
const parsed = parseEnv(schema, process.env, {
|
|
14
|
+
exitOnFail: options?.exitOnFail ?? false,
|
|
15
|
+
mode: options?.mode ?? "runtime"
|
|
16
|
+
});
|
|
16
17
|
if (options?.generateExample) {
|
|
17
18
|
generateExample(schema);
|
|
18
19
|
}
|
package/dist/core/define-env.cjs
CHANGED
|
@@ -33,33 +33,6 @@ __export(define_env_exports, {
|
|
|
33
33
|
defineEnv: () => defineEnv
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(define_env_exports);
|
|
36
|
-
var import_zod3 = require("zod");
|
|
37
|
-
|
|
38
|
-
// src/core/parser.ts
|
|
39
|
-
var import_zod = require("zod");
|
|
40
|
-
function parseEnv(schema, source, mode = "runtime") {
|
|
41
|
-
const result = schema.safeParse(source);
|
|
42
|
-
if (!result.success) {
|
|
43
|
-
const issues = result.error.issues.map((i) => `\u274C ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
44
|
-
const header = mode === "build" ? [
|
|
45
|
-
"\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
|
|
46
|
-
"\u2502 \u274C INVALID ENVIRONMENT VARIABLES DETECTED \u2502",
|
|
47
|
-
"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"
|
|
48
|
-
] : [
|
|
49
|
-
"\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
|
|
50
|
-
"\u2502 \u26A0 WARNING INVALID ENVIRONMENT VARIABLES \u26A0 \u2502",
|
|
51
|
-
"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"
|
|
52
|
-
];
|
|
53
|
-
const box = ["", ...header, issues, ""].join("\n");
|
|
54
|
-
if (mode === "build") {
|
|
55
|
-
throw new Error(box);
|
|
56
|
-
} else {
|
|
57
|
-
console.warn(box);
|
|
58
|
-
process.exit(1);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return result.success ? result.data : {};
|
|
62
|
-
}
|
|
63
36
|
|
|
64
37
|
// src/core/proxy.ts
|
|
65
38
|
function createTypedProxy(obj) {
|
|
@@ -77,13 +50,13 @@ function createTypedProxy(obj) {
|
|
|
77
50
|
}
|
|
78
51
|
|
|
79
52
|
// src/core/generate-example.ts
|
|
80
|
-
var
|
|
53
|
+
var import_zod = require("zod");
|
|
81
54
|
var import_fs = __toESM(require("fs"), 1);
|
|
82
55
|
function getZodTypeName(schema) {
|
|
83
56
|
let type = "unknown";
|
|
84
|
-
if (schema instanceof
|
|
85
|
-
else if (schema instanceof
|
|
86
|
-
else if (schema instanceof
|
|
57
|
+
if (schema instanceof import_zod.ZodString) type = "string";
|
|
58
|
+
else if (schema instanceof import_zod.ZodNumber) type = "number";
|
|
59
|
+
else if (schema instanceof import_zod.ZodBoolean) type = "boolean";
|
|
87
60
|
return type;
|
|
88
61
|
}
|
|
89
62
|
function generateExample(schema, path = ".env.example") {
|
|
@@ -96,8 +69,8 @@ function generateExample(schema, path = ".env.example") {
|
|
|
96
69
|
let placeholder = "";
|
|
97
70
|
let othertype = null;
|
|
98
71
|
let actualSchema = zodSchema;
|
|
99
|
-
if (zodSchema instanceof
|
|
100
|
-
if (zodSchema instanceof
|
|
72
|
+
if (zodSchema instanceof import_zod.ZodOptional) actualSchema = zodSchema.unwrap();
|
|
73
|
+
if (zodSchema instanceof import_zod.ZodDefault) {
|
|
101
74
|
actualSchema = zodSchema.def.innerType;
|
|
102
75
|
placeholder = zodSchema.def.defaultValue ?? "";
|
|
103
76
|
othertype = typeof zodSchema.def.defaultValue;
|
|
@@ -110,10 +83,39 @@ function generateExample(schema, path = ".env.example") {
|
|
|
110
83
|
console.log(`\u2705 .env.example generated at ${path}`);
|
|
111
84
|
}
|
|
112
85
|
|
|
86
|
+
// src/core/parser.ts
|
|
87
|
+
function parseEnv(schema, source, options) {
|
|
88
|
+
const mode = options?.mode ?? "runtime";
|
|
89
|
+
const result = schema.safeParse(source);
|
|
90
|
+
if (!result.success) {
|
|
91
|
+
const issues = result.error.issues.map((i) => `\u274C ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
92
|
+
const header = mode === "build" ? [
|
|
93
|
+
"\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
|
|
94
|
+
"\u2502 \u274C INVALID ENVIRONMENT VARIABLES DETECTED \u2502",
|
|
95
|
+
"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"
|
|
96
|
+
] : [
|
|
97
|
+
"\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
|
|
98
|
+
"\u2502 \u26A0 WARNING INVALID ENVIRONMENT VARIABLES \u26A0 \u2502",
|
|
99
|
+
"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"
|
|
100
|
+
];
|
|
101
|
+
const box = ["", ...header, issues, ""].join("\n");
|
|
102
|
+
if (mode === "build") {
|
|
103
|
+
throw new Error(box);
|
|
104
|
+
}
|
|
105
|
+
console.warn(box);
|
|
106
|
+
if (options?.exitOnFail ?? true) {
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return result.data;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
113
|
// src/core/define-env.ts
|
|
114
|
-
function defineEnv(
|
|
115
|
-
const
|
|
116
|
-
|
|
114
|
+
function defineEnv(schema, options) {
|
|
115
|
+
const parsed = parseEnv(schema, process.env, {
|
|
116
|
+
exitOnFail: options?.exitOnFail ?? false,
|
|
117
|
+
mode: options?.mode ?? "runtime"
|
|
118
|
+
});
|
|
117
119
|
if (options?.generateExample) {
|
|
118
120
|
generateExample(schema);
|
|
119
121
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as z from 'zod';
|
|
2
2
|
import { DefineEnvOptions } from './types.cjs';
|
|
3
3
|
|
|
4
|
-
declare function defineEnv<
|
|
4
|
+
declare function defineEnv<TSchema extends z.ZodObject<z.ZodRawShape>>(schema: TSchema, options?: DefineEnvOptions): z.infer<TSchema>;
|
|
5
5
|
|
|
6
6
|
export { defineEnv };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as z from 'zod';
|
|
2
2
|
import { DefineEnvOptions } from './types.js';
|
|
3
3
|
|
|
4
|
-
declare function defineEnv<
|
|
4
|
+
declare function defineEnv<TSchema extends z.ZodObject<z.ZodRawShape>>(schema: TSchema, options?: DefineEnvOptions): z.infer<TSchema>;
|
|
5
5
|
|
|
6
6
|
export { defineEnv };
|
package/dist/core/define-env.js
CHANGED
package/dist/core/parser.cjs
CHANGED
|
@@ -23,8 +23,8 @@ __export(parser_exports, {
|
|
|
23
23
|
parseEnv: () => parseEnv
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(parser_exports);
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
function parseEnv(schema, source, options) {
|
|
27
|
+
const mode = options?.mode ?? "runtime";
|
|
28
28
|
const result = schema.safeParse(source);
|
|
29
29
|
if (!result.success) {
|
|
30
30
|
const issues = result.error.issues.map((i) => `\u274C ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
@@ -40,12 +40,13 @@ function parseEnv(schema, source, mode = "runtime") {
|
|
|
40
40
|
const box = ["", ...header, issues, ""].join("\n");
|
|
41
41
|
if (mode === "build") {
|
|
42
42
|
throw new Error(box);
|
|
43
|
-
}
|
|
44
|
-
|
|
43
|
+
}
|
|
44
|
+
console.warn(box);
|
|
45
|
+
if (options?.exitOnFail ?? true) {
|
|
45
46
|
process.exit(1);
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
|
-
return result.
|
|
49
|
+
return result.data;
|
|
49
50
|
}
|
|
50
51
|
// Annotate the CommonJS export names for ESM import in node:
|
|
51
52
|
0 && (module.exports = {
|
package/dist/core/parser.d.cts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as z from 'zod';
|
|
2
2
|
import { ValidationMode } from './types.cjs';
|
|
3
3
|
|
|
4
|
-
declare function parseEnv<
|
|
4
|
+
declare function parseEnv<TSchema extends z.ZodObject<z.ZodRawShape>>(schema: TSchema, source: Record<string, unknown>, options?: {
|
|
5
|
+
exitOnFail?: boolean;
|
|
6
|
+
mode?: ValidationMode;
|
|
7
|
+
}): z.infer<TSchema>;
|
|
5
8
|
|
|
6
9
|
export { parseEnv };
|
package/dist/core/parser.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as z from 'zod';
|
|
2
2
|
import { ValidationMode } from './types.js';
|
|
3
3
|
|
|
4
|
-
declare function parseEnv<
|
|
4
|
+
declare function parseEnv<TSchema extends z.ZodObject<z.ZodRawShape>>(schema: TSchema, source: Record<string, unknown>, options?: {
|
|
5
|
+
exitOnFail?: boolean;
|
|
6
|
+
mode?: ValidationMode;
|
|
7
|
+
}): z.infer<TSchema>;
|
|
5
8
|
|
|
6
9
|
export { parseEnv };
|
package/dist/core/parser.js
CHANGED
package/dist/core/types.d.cts
CHANGED
package/dist/core/types.d.ts
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -30,104 +30,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
-
defineEnv: () => defineEnv
|
|
34
|
-
tx: () => tx
|
|
33
|
+
defineEnv: () => defineEnv
|
|
35
34
|
});
|
|
36
35
|
module.exports = __toCommonJS(index_exports);
|
|
37
36
|
|
|
38
|
-
// src/core/tx.ts
|
|
39
|
-
var import_zod = require("zod");
|
|
40
|
-
var SEMVER_REGEX = /^\d+\.\d+\.\d+(-[0-9A-Za-z-.]+)?$/;
|
|
41
|
-
var tx = {
|
|
42
|
-
/**
|
|
43
|
-
* STRICT STRING:
|
|
44
|
-
* Rejects purely numeric strings (e.g. "12345").
|
|
45
|
-
* Good for API Keys.
|
|
46
|
-
*/
|
|
47
|
-
string: (message = "Value should be text, but looks like a number.") => import_zod.z.string().trim().regex(/^(?!\d+$).+$/, { error: message }).describe("Non-numeric string"),
|
|
48
|
-
/**
|
|
49
|
-
* SMART NUMBER:
|
|
50
|
-
* Automatically converts "3000" -> 3000.
|
|
51
|
-
* Fails if the value is not a valid number (e.g. "abc").
|
|
52
|
-
*/
|
|
53
|
-
number: (message = "Must be a number") => import_zod.z.coerce.number({ error: message }).finite().describe("Numeric value"),
|
|
54
|
-
/**
|
|
55
|
-
* PORT VALIDATOR:
|
|
56
|
-
* Coerces to number and ensures it is between 1 and 65535.
|
|
57
|
-
*/
|
|
58
|
-
port: (message = "Must be a valid port (1\u201365535)") => import_zod.z.coerce.number({ error: message }).int().min(1).max(65535).describe("TCP/UDP port number (1\u201365535)"),
|
|
59
|
-
/**
|
|
60
|
-
* SMART BOOLEAN:
|
|
61
|
-
* Handles "true", "TRUE", "1" -> true
|
|
62
|
-
* Handles "false", "FALSE", "0" -> false
|
|
63
|
-
* Throws error on anything else.
|
|
64
|
-
*/
|
|
65
|
-
bool: (message) => {
|
|
66
|
-
return import_zod.z.union([import_zod.z.string(), import_zod.z.boolean()]).transform((val, ctx) => {
|
|
67
|
-
if (typeof val === "boolean") return val;
|
|
68
|
-
const v = val.toLowerCase();
|
|
69
|
-
if (v === "true" || v === "1") return true;
|
|
70
|
-
if (v === "false" || v === "0") return false;
|
|
71
|
-
ctx.addIssue({
|
|
72
|
-
code: import_zod.z.ZodIssueCode.custom,
|
|
73
|
-
message: message || 'Must be a boolean ("true"/"false"/"1"/"0")'
|
|
74
|
-
});
|
|
75
|
-
return import_zod.z.NEVER;
|
|
76
|
-
});
|
|
77
|
-
},
|
|
78
|
-
/**
|
|
79
|
-
* URL:
|
|
80
|
-
* Strict URL checking.
|
|
81
|
-
*/
|
|
82
|
-
url: (message = "Must be a valid URL (e.g. https://...)") => import_zod.z.url({ error: message }).describe("A valid URL including protocol"),
|
|
83
|
-
email: (message = "Must be a valid email address") => import_zod.z.email({ error: message }).describe("A valid email address"),
|
|
84
|
-
positiveNumber: (message = "Must be > 0") => import_zod.z.coerce.number().gt(0, { error: message }).describe("A positive number"),
|
|
85
|
-
nonEmptyString: (message = "Cannot be empty") => import_zod.z.string().trim().min(1, { error: message }).describe("A non-empty string"),
|
|
86
|
-
semver: (message = "Must be valid semver") => import_zod.z.string().regex(SEMVER_REGEX, { error: message }).describe("Semantic version (x.y.z)"),
|
|
87
|
-
path: (message = "Must be a valid path") => import_zod.z.string().trim().min(1, { error: message }).describe("Filesystem path"),
|
|
88
|
-
enum: (values, message = `Must be one of: ${values.join(", ")}`) => import_zod.z.enum(values, { error: message }).describe(`One of: ${values.join(", ")}`),
|
|
89
|
-
json: (message = "Must be valid JSON") => import_zod.z.string().transform((val, ctx) => {
|
|
90
|
-
try {
|
|
91
|
-
return JSON.parse(val);
|
|
92
|
-
} catch {
|
|
93
|
-
ctx.addIssue({
|
|
94
|
-
code: "custom",
|
|
95
|
-
error: message
|
|
96
|
-
});
|
|
97
|
-
return import_zod.z.NEVER;
|
|
98
|
-
}
|
|
99
|
-
}).describe("JSON-encoded value")
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
// src/core/define-env.ts
|
|
103
|
-
var import_zod4 = require("zod");
|
|
104
|
-
|
|
105
|
-
// src/core/parser.ts
|
|
106
|
-
var import_zod2 = require("zod");
|
|
107
|
-
function parseEnv(schema, source, mode = "runtime") {
|
|
108
|
-
const result = schema.safeParse(source);
|
|
109
|
-
if (!result.success) {
|
|
110
|
-
const issues = result.error.issues.map((i) => `\u274C ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
111
|
-
const header = mode === "build" ? [
|
|
112
|
-
"\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
|
|
113
|
-
"\u2502 \u274C INVALID ENVIRONMENT VARIABLES DETECTED \u2502",
|
|
114
|
-
"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"
|
|
115
|
-
] : [
|
|
116
|
-
"\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
|
|
117
|
-
"\u2502 \u26A0 WARNING INVALID ENVIRONMENT VARIABLES \u26A0 \u2502",
|
|
118
|
-
"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"
|
|
119
|
-
];
|
|
120
|
-
const box = ["", ...header, issues, ""].join("\n");
|
|
121
|
-
if (mode === "build") {
|
|
122
|
-
throw new Error(box);
|
|
123
|
-
} else {
|
|
124
|
-
console.warn(box);
|
|
125
|
-
process.exit(1);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return result.success ? result.data : {};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
37
|
// src/core/proxy.ts
|
|
132
38
|
function createTypedProxy(obj) {
|
|
133
39
|
return new Proxy(obj, {
|
|
@@ -144,13 +50,13 @@ function createTypedProxy(obj) {
|
|
|
144
50
|
}
|
|
145
51
|
|
|
146
52
|
// src/core/generate-example.ts
|
|
147
|
-
var
|
|
53
|
+
var import_zod = require("zod");
|
|
148
54
|
var import_fs = __toESM(require("fs"), 1);
|
|
149
55
|
function getZodTypeName(schema) {
|
|
150
56
|
let type = "unknown";
|
|
151
|
-
if (schema instanceof
|
|
152
|
-
else if (schema instanceof
|
|
153
|
-
else if (schema instanceof
|
|
57
|
+
if (schema instanceof import_zod.ZodString) type = "string";
|
|
58
|
+
else if (schema instanceof import_zod.ZodNumber) type = "number";
|
|
59
|
+
else if (schema instanceof import_zod.ZodBoolean) type = "boolean";
|
|
154
60
|
return type;
|
|
155
61
|
}
|
|
156
62
|
function generateExample(schema, path = ".env.example") {
|
|
@@ -163,8 +69,8 @@ function generateExample(schema, path = ".env.example") {
|
|
|
163
69
|
let placeholder = "";
|
|
164
70
|
let othertype = null;
|
|
165
71
|
let actualSchema = zodSchema;
|
|
166
|
-
if (zodSchema instanceof
|
|
167
|
-
if (zodSchema instanceof
|
|
72
|
+
if (zodSchema instanceof import_zod.ZodOptional) actualSchema = zodSchema.unwrap();
|
|
73
|
+
if (zodSchema instanceof import_zod.ZodDefault) {
|
|
168
74
|
actualSchema = zodSchema.def.innerType;
|
|
169
75
|
placeholder = zodSchema.def.defaultValue ?? "";
|
|
170
76
|
othertype = typeof zodSchema.def.defaultValue;
|
|
@@ -177,10 +83,39 @@ function generateExample(schema, path = ".env.example") {
|
|
|
177
83
|
console.log(`\u2705 .env.example generated at ${path}`);
|
|
178
84
|
}
|
|
179
85
|
|
|
86
|
+
// src/core/parser.ts
|
|
87
|
+
function parseEnv(schema, source, options) {
|
|
88
|
+
const mode = options?.mode ?? "runtime";
|
|
89
|
+
const result = schema.safeParse(source);
|
|
90
|
+
if (!result.success) {
|
|
91
|
+
const issues = result.error.issues.map((i) => `\u274C ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
92
|
+
const header = mode === "build" ? [
|
|
93
|
+
"\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
|
|
94
|
+
"\u2502 \u274C INVALID ENVIRONMENT VARIABLES DETECTED \u2502",
|
|
95
|
+
"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"
|
|
96
|
+
] : [
|
|
97
|
+
"\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
|
|
98
|
+
"\u2502 \u26A0 WARNING INVALID ENVIRONMENT VARIABLES \u26A0 \u2502",
|
|
99
|
+
"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"
|
|
100
|
+
];
|
|
101
|
+
const box = ["", ...header, issues, ""].join("\n");
|
|
102
|
+
if (mode === "build") {
|
|
103
|
+
throw new Error(box);
|
|
104
|
+
}
|
|
105
|
+
console.warn(box);
|
|
106
|
+
if (options?.exitOnFail ?? true) {
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return result.data;
|
|
111
|
+
}
|
|
112
|
+
|
|
180
113
|
// src/core/define-env.ts
|
|
181
|
-
function defineEnv(
|
|
182
|
-
const
|
|
183
|
-
|
|
114
|
+
function defineEnv(schema, options) {
|
|
115
|
+
const parsed = parseEnv(schema, process.env, {
|
|
116
|
+
exitOnFail: options?.exitOnFail ?? false,
|
|
117
|
+
mode: options?.mode ?? "runtime"
|
|
118
|
+
});
|
|
184
119
|
if (options?.generateExample) {
|
|
185
120
|
generateExample(schema);
|
|
186
121
|
}
|
|
@@ -188,6 +123,5 @@ function defineEnv(shape, source, options) {
|
|
|
188
123
|
}
|
|
189
124
|
// Annotate the CommonJS export names for ESM import in node:
|
|
190
125
|
0 && (module.exports = {
|
|
191
|
-
defineEnv
|
|
192
|
-
tx
|
|
126
|
+
defineEnv
|
|
193
127
|
});
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED