@arthur-lobo/zod-env 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 +121 -0
- package/dist/index.cjs +59 -0
- package/dist/index.d.cts +30 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +33 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Zod Env
|
|
2
|
+
|
|
3
|
+
A TypeScript library for loading and validating environment variables using [Zod](https://zod.dev/), providing strong and safe type validation for environment configurations.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @arthur-lobo/zod-env
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Description
|
|
12
|
+
|
|
13
|
+
`ZodEnv` allows you to define Zod schemas to validate environment variables, ensuring their values are in the correct format and providing default values when necessary. It supports both synchronous and asynchronous operations, and allow you to define how `.env` must be loaded.
|
|
14
|
+
|
|
15
|
+
## Basic Usage
|
|
16
|
+
|
|
17
|
+
### Synchronous Class: `ZodEnv`
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { z } from 'zod';
|
|
21
|
+
import { ZodEnv } from '@arthur-lobo/zod-env';
|
|
22
|
+
|
|
23
|
+
const schema = z.object({
|
|
24
|
+
PORT: z.coerce.number().default(3000),
|
|
25
|
+
DATABASE_URL: z.string(),
|
|
26
|
+
DEBUG: z.coerce.boolean().default(false),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const env = new ZodEnv({
|
|
30
|
+
schema,
|
|
31
|
+
getEnv: () => process.env, // or any function that returns an object with the variables like `import.meta.env` when using vite to build your frontend
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Access validated values
|
|
35
|
+
console.log(env.get('PORT')); // 3000 (or the value of process.env.PORT if defined)
|
|
36
|
+
console.log(env.get('DATABASE_URL')); // validated string
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Asynchronous Class: `AsyncZodEnv`
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { z } from 'zod';
|
|
43
|
+
import { AsyncZodEnv } from '@arthur-lobo/zod-env';
|
|
44
|
+
|
|
45
|
+
const schema = z.object({
|
|
46
|
+
API_KEY: z.string(),
|
|
47
|
+
TIMEOUT: z.coerce.number().default(5000),
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const env = new AsyncZodEnv({
|
|
51
|
+
schema,
|
|
52
|
+
getEnv: async () => {
|
|
53
|
+
await someAsyncOperation();
|
|
54
|
+
return process.env;
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Access validated values asynchronously
|
|
59
|
+
const apiKey = await env.get('API_KEY');
|
|
60
|
+
const timeout = await env.get('TIMEOUT');
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Loading .env File
|
|
64
|
+
|
|
65
|
+
You can automatically load a `.env` file using Node.js's `loadEnv` function:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { loadEnvFile } from 'node:process';
|
|
69
|
+
|
|
70
|
+
const env = new ZodEnv({
|
|
71
|
+
schema: z.object({
|
|
72
|
+
SECRET_KEY: z.string(),
|
|
73
|
+
}),
|
|
74
|
+
loadEnv: loadEnvFile, // Loads the .env file
|
|
75
|
+
getEnv: () => process.env,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
console.log(env.get('SECRET_KEY')); // Validated value from .env
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
For asynchronous operations:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
const env = new AsyncZodEnv({
|
|
85
|
+
schema: z.object({
|
|
86
|
+
SECRET_KEY: z.string(),
|
|
87
|
+
}),
|
|
88
|
+
loadEnv: async () => loadEnvFile(), // Loads .env asynchronously
|
|
89
|
+
getEnv: async () => process.env,
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Schema Examples
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { z } from 'zod';
|
|
97
|
+
|
|
98
|
+
// Basic schema with default values
|
|
99
|
+
const basicSchema = z.object({
|
|
100
|
+
PORT: z.coerce.number().default(3000),
|
|
101
|
+
HOST: z.string().default('localhost'),
|
|
102
|
+
DEBUG: z.coerce.boolean().default(false),
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Schema with custom validations
|
|
106
|
+
const advancedSchema = z.object({
|
|
107
|
+
DATABASE_URL: z.string().url(),
|
|
108
|
+
JWT_SECRET: z.string().min(32, 'JWT secret must be at least 32 characters'),
|
|
109
|
+
MAX_CONNECTIONS: z.coerce.number().min(1).max(100),
|
|
110
|
+
ALLOWED_ORIGINS: z.string().transform(str => str.split(',')).pipe(z.array(z.string().url())),
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Benefits
|
|
115
|
+
|
|
116
|
+
- **Strong Type Validation**: Uses Zod to ensure environment variables are in the correct format.
|
|
117
|
+
- **Default Values**: Native support for default values in the Zod schema.
|
|
118
|
+
- **Flexibility**: Works with any source of environment variables (process.env, import.meta.env, custom files, etc.).
|
|
119
|
+
- **.env Support**: Easy integration with `.env` files via Node.js's `loadEnvFile`.
|
|
120
|
+
- **Async/Sync**: Choose between synchronous or asynchronous operations as needed.
|
|
121
|
+
- **TypeScript**: Fully typed, providing autocomplete and type checking.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AsyncZodEnv: () => AsyncZodEnv,
|
|
24
|
+
ZodEnv: () => ZodEnv
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
var import_zod = require("zod");
|
|
28
|
+
var ZodEnv = class {
|
|
29
|
+
schema;
|
|
30
|
+
env;
|
|
31
|
+
constructor({ schema, loadEnv, getEnv }) {
|
|
32
|
+
this.schema = schema;
|
|
33
|
+
loadEnv?.();
|
|
34
|
+
this.env = schema.parse(getEnv());
|
|
35
|
+
}
|
|
36
|
+
get(key) {
|
|
37
|
+
return this.env[key];
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var AsyncZodEnv = class {
|
|
41
|
+
schema;
|
|
42
|
+
env;
|
|
43
|
+
constructor({ schema, loadEnv, getEnv }) {
|
|
44
|
+
this.schema = schema;
|
|
45
|
+
if (typeof loadEnv === "function") {
|
|
46
|
+
this.env = loadEnv().then(getEnv).then((result) => schema.parse(result));
|
|
47
|
+
} else {
|
|
48
|
+
this.env = getEnv().then((result) => schema.parse(result));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async get(key) {
|
|
52
|
+
return (await this.env)[key];
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
56
|
+
0 && (module.exports = {
|
|
57
|
+
AsyncZodEnv,
|
|
58
|
+
ZodEnv
|
|
59
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ZodObject, z } from 'zod';
|
|
2
|
+
|
|
3
|
+
interface ZodEnvConstructor {
|
|
4
|
+
schema: ZodObject;
|
|
5
|
+
loadEnv?: () => void;
|
|
6
|
+
getEnv: () => Record<string, any>;
|
|
7
|
+
}
|
|
8
|
+
declare class ZodEnv<S extends ZodObject> {
|
|
9
|
+
schema: S;
|
|
10
|
+
env: z.infer<S>;
|
|
11
|
+
constructor({ schema, loadEnv, getEnv }: ZodEnvConstructor & {
|
|
12
|
+
schema: S;
|
|
13
|
+
});
|
|
14
|
+
get<K extends keyof S["shape"]>(key: K): z.core.output<S>[K];
|
|
15
|
+
}
|
|
16
|
+
interface AsyncZodEnvConstructor {
|
|
17
|
+
schema: ZodObject;
|
|
18
|
+
loadEnv?: () => Promise<void>;
|
|
19
|
+
getEnv: () => Promise<Record<string, any>>;
|
|
20
|
+
}
|
|
21
|
+
declare class AsyncZodEnv<S extends ZodObject> {
|
|
22
|
+
schema: S;
|
|
23
|
+
env: Promise<z.infer<S>>;
|
|
24
|
+
constructor({ schema, loadEnv, getEnv }: AsyncZodEnvConstructor & {
|
|
25
|
+
schema: S;
|
|
26
|
+
});
|
|
27
|
+
get<K extends keyof S["shape"]>(key: K): Promise<z.core.output<S>[K]>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { AsyncZodEnv, ZodEnv };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ZodObject, z } from 'zod';
|
|
2
|
+
|
|
3
|
+
interface ZodEnvConstructor {
|
|
4
|
+
schema: ZodObject;
|
|
5
|
+
loadEnv?: () => void;
|
|
6
|
+
getEnv: () => Record<string, any>;
|
|
7
|
+
}
|
|
8
|
+
declare class ZodEnv<S extends ZodObject> {
|
|
9
|
+
schema: S;
|
|
10
|
+
env: z.infer<S>;
|
|
11
|
+
constructor({ schema, loadEnv, getEnv }: ZodEnvConstructor & {
|
|
12
|
+
schema: S;
|
|
13
|
+
});
|
|
14
|
+
get<K extends keyof S["shape"]>(key: K): z.core.output<S>[K];
|
|
15
|
+
}
|
|
16
|
+
interface AsyncZodEnvConstructor {
|
|
17
|
+
schema: ZodObject;
|
|
18
|
+
loadEnv?: () => Promise<void>;
|
|
19
|
+
getEnv: () => Promise<Record<string, any>>;
|
|
20
|
+
}
|
|
21
|
+
declare class AsyncZodEnv<S extends ZodObject> {
|
|
22
|
+
schema: S;
|
|
23
|
+
env: Promise<z.infer<S>>;
|
|
24
|
+
constructor({ schema, loadEnv, getEnv }: AsyncZodEnvConstructor & {
|
|
25
|
+
schema: S;
|
|
26
|
+
});
|
|
27
|
+
get<K extends keyof S["shape"]>(key: K): Promise<z.core.output<S>[K]>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { AsyncZodEnv, ZodEnv };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import "zod";
|
|
3
|
+
var ZodEnv = class {
|
|
4
|
+
schema;
|
|
5
|
+
env;
|
|
6
|
+
constructor({ schema, loadEnv, getEnv }) {
|
|
7
|
+
this.schema = schema;
|
|
8
|
+
loadEnv?.();
|
|
9
|
+
this.env = schema.parse(getEnv());
|
|
10
|
+
}
|
|
11
|
+
get(key) {
|
|
12
|
+
return this.env[key];
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
var AsyncZodEnv = class {
|
|
16
|
+
schema;
|
|
17
|
+
env;
|
|
18
|
+
constructor({ schema, loadEnv, getEnv }) {
|
|
19
|
+
this.schema = schema;
|
|
20
|
+
if (typeof loadEnv === "function") {
|
|
21
|
+
this.env = loadEnv().then(getEnv).then((result) => schema.parse(result));
|
|
22
|
+
} else {
|
|
23
|
+
this.env = getEnv().then((result) => schema.parse(result));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async get(key) {
|
|
27
|
+
return (await this.env)[key];
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
export {
|
|
31
|
+
AsyncZodEnv,
|
|
32
|
+
ZodEnv
|
|
33
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arthur-lobo/zod-env",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "load and validate your env with zod.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"zod",
|
|
7
|
+
"env",
|
|
8
|
+
"dotenv",
|
|
9
|
+
"validation"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"author": "Arthur Lobo",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"require": "./dist/index.cjs",
|
|
21
|
+
"import": "./dist/index.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"test": "vitest --run",
|
|
26
|
+
"build": "tsup",
|
|
27
|
+
"prepack": "npm run build"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist"
|
|
31
|
+
],
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"zod": "^4.3.6"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^25.5.0",
|
|
37
|
+
"tsup": "^8.5.1",
|
|
38
|
+
"typescript": "^5.9.3",
|
|
39
|
+
"vitest": "^4.1.0"
|
|
40
|
+
}
|
|
41
|
+
}
|