zod-conf 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/LICENSE +21 -0
- package/README.md +217 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +372 -0
- package/dist/values/define.d.ts +78 -0
- package/dist/values/define.d.ts.map +1 -0
- package/dist/values/define.js +156 -0
- package/dist/values/define.js.map +1 -0
- package/dist/values/env-metadata.d.ts +6 -0
- package/dist/values/env-metadata.d.ts.map +1 -0
- package/dist/values/env-metadata.js +3 -0
- package/dist/values/env-metadata.js.map +1 -0
- package/dist/values/env.d.ts +41 -0
- package/dist/values/env.d.ts.map +1 -0
- package/dist/values/env.js +71 -0
- package/dist/values/env.js.map +1 -0
- package/dist/values/object.d.ts +34 -0
- package/dist/values/object.d.ts.map +1 -0
- package/dist/values/object.js +34 -0
- package/dist/values/object.js.map +1 -0
- package/package.json +80 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Simon Bobrov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# zod-conf
|
|
2
|
+
|
|
3
|
+
Type-safe configuration management with Zod schemas and environment variables.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Type-safe** - Full TypeScript support with Zod schema validation
|
|
8
|
+
- **Env-first** - Bind schema fields directly to environment variables
|
|
9
|
+
- **Simple API** - Intuitive, Zod-native API that feels familiar
|
|
10
|
+
- **Zero compromise** - All Zod features work - transformations, refinements, and more
|
|
11
|
+
- **Lightweight** - Only Zod as peer dependency, no extra bloat
|
|
12
|
+
- **Universal** - Works with process.env, dotenv, or any environment loader
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install zod-conf zod
|
|
18
|
+
# or
|
|
19
|
+
yarn add zod-conf zod
|
|
20
|
+
# or
|
|
21
|
+
pnpm add zod-conf zod
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import zc from 'zod-conf';
|
|
28
|
+
|
|
29
|
+
// define your configuration schema
|
|
30
|
+
const schema = zc.define({
|
|
31
|
+
port: zc.env('PORT').number().default(3000),
|
|
32
|
+
host: zc.env('HOST').string().default('localhost'),
|
|
33
|
+
debug: zc.env('DEBUG').boolean().default(false),
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// load configuration from environment
|
|
37
|
+
const config = schema.load({
|
|
38
|
+
env: process.env,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
console.log(config);
|
|
42
|
+
// { port: 3000, host: 'localhost', debug: false }
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Usage
|
|
46
|
+
|
|
47
|
+
### Basic Types
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
const schema = zc.define({
|
|
51
|
+
// string
|
|
52
|
+
apiUrl: zc.env('API_URL').string(),
|
|
53
|
+
|
|
54
|
+
// number
|
|
55
|
+
port: zc.env('PORT').number(),
|
|
56
|
+
|
|
57
|
+
// boolean
|
|
58
|
+
isProduction: zc.env('NODE_ENV').boolean(),
|
|
59
|
+
|
|
60
|
+
// enum
|
|
61
|
+
logLevel: zc.env('LOG_LEVEL').enum(['debug', 'info', 'warn', 'error']),
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Defaults and Optional Values
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
const schema = zc.define({
|
|
69
|
+
// with default value
|
|
70
|
+
port: zc.env('PORT').number().default(3000),
|
|
71
|
+
|
|
72
|
+
// optional field
|
|
73
|
+
apiKey: zc.env('API_KEY').string().optional(),
|
|
74
|
+
|
|
75
|
+
// nullable field
|
|
76
|
+
proxyUrl: zc.env('PROXY_URL').string().nullable(),
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Nested Objects
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
const schema = zc.define({
|
|
84
|
+
server: zc.object({
|
|
85
|
+
host: zc.env('SERVER_HOST').string().default('localhost'),
|
|
86
|
+
port: zc.env('SERVER_PORT').number().default(3000),
|
|
87
|
+
}),
|
|
88
|
+
database: zc.object({
|
|
89
|
+
url: zc.env('DATABASE_URL').string(),
|
|
90
|
+
pool: zc.object({
|
|
91
|
+
min: zc.env('DB_POOL_MIN').number().default(1),
|
|
92
|
+
max: zc.env('DB_POOL_MAX').number().default(10),
|
|
93
|
+
}),
|
|
94
|
+
}),
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### TypeScript Enums
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
enum LogLevel {
|
|
102
|
+
DEBUG = 'debug',
|
|
103
|
+
INFO = 'info',
|
|
104
|
+
WARN = 'warn',
|
|
105
|
+
ERROR = 'error',
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const schema = zc.define({
|
|
109
|
+
logLevel: zc.env('LOG_LEVEL').enum(LogLevel).default(LogLevel.INFO),
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Loading Configuration
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// from process.env
|
|
117
|
+
const config = schema.load({ env: process.env });
|
|
118
|
+
|
|
119
|
+
// from .env file (using dotenv)
|
|
120
|
+
import { config as dotenvConfig } from 'dotenv';
|
|
121
|
+
|
|
122
|
+
const env = dotenvConfig();
|
|
123
|
+
const config = schema.load({ env: env.parsed });
|
|
124
|
+
|
|
125
|
+
// from custom source
|
|
126
|
+
const config = schema.load({
|
|
127
|
+
env: {
|
|
128
|
+
PORT: '8080',
|
|
129
|
+
HOST: '0.0.0.0',
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Error Handling
|
|
135
|
+
|
|
136
|
+
The error-handling is similar to Zod's standard behavior:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
// throws on validation error
|
|
140
|
+
try {
|
|
141
|
+
const config = schema.load({ env: process.env });
|
|
142
|
+
} catch (error) {
|
|
143
|
+
console.error('Configuration validation failed:', error);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// safe parsing without throwing
|
|
147
|
+
const result = schema.safeLoad({ env: process.env });
|
|
148
|
+
if (result.success) {
|
|
149
|
+
console.log('Config:', result.data);
|
|
150
|
+
} else {
|
|
151
|
+
console.error('Validation errors:', result.error);
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Advanced: Transformations
|
|
156
|
+
|
|
157
|
+
All Zod transformations work seamlessly:
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
const schema = zc.define({
|
|
161
|
+
port: zc.env('PORT')
|
|
162
|
+
.number()
|
|
163
|
+
.default(3000)
|
|
164
|
+
.transform(p => Math.max(1024, p)), // Ensure port is at least 1024
|
|
165
|
+
|
|
166
|
+
apiUrl: zc.env('API_URL')
|
|
167
|
+
.string()
|
|
168
|
+
.transform(url => url.replace(/\/$/, '')), // Remove trailing slash
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## API Reference
|
|
173
|
+
|
|
174
|
+
### `zc.define(shape)`
|
|
175
|
+
|
|
176
|
+
Creates a configuration schema with environment variable bindings.
|
|
177
|
+
|
|
178
|
+
- **shape**: An object where each value is created using `zc.env()` or `zc.object()`
|
|
179
|
+
- **returns**: A `ZodConfSchema` instance with `load()` and `safeLoad()` methods
|
|
180
|
+
|
|
181
|
+
### `zc.env(key)`
|
|
182
|
+
|
|
183
|
+
Binds a schema field to an environment variable.
|
|
184
|
+
|
|
185
|
+
- **key**: The environment variable name
|
|
186
|
+
- **returns**: An object with methods for different types:
|
|
187
|
+
- `.string()` - String value
|
|
188
|
+
- `.number()` - Numeric value (auto-converted)
|
|
189
|
+
- `.boolean()` - Boolean value (accepts 'true'/'false')
|
|
190
|
+
- `.enum(values)` - Enum value (string array or TypeScript enum)
|
|
191
|
+
|
|
192
|
+
### `zc.object(shape)`
|
|
193
|
+
|
|
194
|
+
Creates a nested object schema.
|
|
195
|
+
|
|
196
|
+
- **shape**: An object where values are `zc.env()` or nested `zc.object()` calls
|
|
197
|
+
- **returns**: A Zod object schema
|
|
198
|
+
|
|
199
|
+
### `schema.load(params)`
|
|
200
|
+
|
|
201
|
+
Loads and validates configuration.
|
|
202
|
+
|
|
203
|
+
- **params.env**: Environment variables object
|
|
204
|
+
- **returns**: Validated configuration object
|
|
205
|
+
- **throws**: ZodError if validation fails
|
|
206
|
+
|
|
207
|
+
### `schema.safeLoad(params)`
|
|
208
|
+
|
|
209
|
+
Safely loads configuration without throwing.
|
|
210
|
+
|
|
211
|
+
- **params.env**: Environment variables object
|
|
212
|
+
- **returns**: `{ success: true, data: T }` or `{ success: false, error: ZodError }`
|
|
213
|
+
|
|
214
|
+
## License
|
|
215
|
+
|
|
216
|
+
MIT
|
|
217
|
+
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { boolean, number, string, enum as zenum } from 'zod';
|
|
2
|
+
export declare const zc: {
|
|
3
|
+
define: <T extends import("zod").ZodRawShape>(shape: T) => import("./values/define.js").ZodConfSchema<T>;
|
|
4
|
+
env: (key: string) => {
|
|
5
|
+
string: () => import("zod").ZodString;
|
|
6
|
+
number: () => import("zod").ZodCoercedNumber<unknown>;
|
|
7
|
+
boolean: () => import("zod").ZodCoercedBoolean<unknown>;
|
|
8
|
+
enum: {
|
|
9
|
+
<const T extends readonly string[]>(values: T): import("zod").ZodEnum<{ [k_1 in T[number]]: k_1; } extends infer T_1 ? { [k in keyof T_1]: T_1[k]; } : never>;
|
|
10
|
+
<const T extends Readonly<Record<string, string | number>>>(entries: T): import("zod").ZodEnum<T>;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
object: <T extends import("zod").ZodRawShape>(shape: T) => import("zod").ZodObject<T>;
|
|
14
|
+
string: typeof string;
|
|
15
|
+
boolean: typeof boolean;
|
|
16
|
+
number: typeof number;
|
|
17
|
+
enum: typeof zenum;
|
|
18
|
+
};
|
|
19
|
+
export default zc;
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,IAAI,KAAK,EAAE,MAAM,KAAK,CAAC;AAK7D,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;CAWd,CAAC;AAEF,eAAe,EAAE,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { boolean, number, string, enum as zenum } from 'zod';
|
|
2
|
+
import { define } from './values/define.js';
|
|
3
|
+
import { env } from './values/env.js';
|
|
4
|
+
import { object } from './values/object.js';
|
|
5
|
+
export const zc = {
|
|
6
|
+
// core values
|
|
7
|
+
define,
|
|
8
|
+
env,
|
|
9
|
+
object,
|
|
10
|
+
// re-export common zod values for convenience
|
|
11
|
+
string,
|
|
12
|
+
boolean,
|
|
13
|
+
number,
|
|
14
|
+
enum: zenum,
|
|
15
|
+
};
|
|
16
|
+
export default zc;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,IAAI,KAAK,EAAE,MAAM,KAAK,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,CAAC,MAAM,EAAE,GAAG;IAEhB,MAAM;IACN,GAAG;IACH,MAAM;IAGN,MAAM;IACN,OAAO;IACP,MAAM;IACN,IAAI,EAAE,KAAK;CACZ,CAAC;AAEF,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import { strictEqual, deepStrictEqual } from 'node:assert';
|
|
2
|
+
import { test } from 'node:test';
|
|
3
|
+
import zc from './index.js';
|
|
4
|
+
test('zod-conf configuration parsing', async (t) => {
|
|
5
|
+
await t.test('parses string environment variables', () => {
|
|
6
|
+
const schema = zc.define({
|
|
7
|
+
apiUrl: zc.env('API_URL').string(),
|
|
8
|
+
});
|
|
9
|
+
const config = schema.load({
|
|
10
|
+
env: { API_URL: 'https://api.example.com' },
|
|
11
|
+
});
|
|
12
|
+
strictEqual(config.apiUrl, 'https://api.example.com');
|
|
13
|
+
});
|
|
14
|
+
await t.test('parses number environment variables', () => {
|
|
15
|
+
const schema = zc.define({
|
|
16
|
+
port: zc.env('PORT').number(),
|
|
17
|
+
});
|
|
18
|
+
const config = schema.load({
|
|
19
|
+
env: { PORT: '3000' },
|
|
20
|
+
});
|
|
21
|
+
strictEqual(config.port, 3000);
|
|
22
|
+
});
|
|
23
|
+
await t.test('parses boolean environment variables', () => {
|
|
24
|
+
const schema = zc.define({
|
|
25
|
+
debug: zc.env('DEBUG').boolean(),
|
|
26
|
+
verbose: zc.env('VERBOSE').boolean(),
|
|
27
|
+
});
|
|
28
|
+
const config = schema.load({
|
|
29
|
+
env: { DEBUG: 'true', VERBOSE: 'false' },
|
|
30
|
+
});
|
|
31
|
+
strictEqual(config.debug, true);
|
|
32
|
+
strictEqual(config.verbose, false);
|
|
33
|
+
});
|
|
34
|
+
await t.test('parses enum environment variables with string array', () => {
|
|
35
|
+
const schema = zc.define({
|
|
36
|
+
logLevel: zc.env('LOG_LEVEL').enum(['info', 'debug', 'error']),
|
|
37
|
+
});
|
|
38
|
+
const config = schema.load({
|
|
39
|
+
env: { LOG_LEVEL: 'debug' },
|
|
40
|
+
});
|
|
41
|
+
strictEqual(config.logLevel, 'debug');
|
|
42
|
+
});
|
|
43
|
+
await t.test('parses enum environment variables with string enum', () => {
|
|
44
|
+
let LogLevel;
|
|
45
|
+
(function (LogLevel) {
|
|
46
|
+
LogLevel["INFO"] = "info";
|
|
47
|
+
LogLevel["DEBUG"] = "debug";
|
|
48
|
+
LogLevel["ERROR"] = "error";
|
|
49
|
+
})(LogLevel || (LogLevel = {}));
|
|
50
|
+
const schema = zc.define({
|
|
51
|
+
logLevel: zc.env('LOG_LEVEL').enum(LogLevel),
|
|
52
|
+
});
|
|
53
|
+
const config = schema.load({
|
|
54
|
+
env: { LOG_LEVEL: 'info' },
|
|
55
|
+
});
|
|
56
|
+
strictEqual(config.logLevel, 'info');
|
|
57
|
+
});
|
|
58
|
+
await t.test('parses enum environment variables with numeric enum', () => {
|
|
59
|
+
let Priority;
|
|
60
|
+
(function (Priority) {
|
|
61
|
+
Priority[Priority["LOW"] = 1] = "LOW";
|
|
62
|
+
Priority[Priority["MEDIUM"] = 2] = "MEDIUM";
|
|
63
|
+
Priority[Priority["HIGH"] = 3] = "HIGH";
|
|
64
|
+
Priority[Priority["URGENT"] = 4] = "URGENT";
|
|
65
|
+
})(Priority || (Priority = {}));
|
|
66
|
+
const schema = zc.define({
|
|
67
|
+
priority: zc.env('PRIORITY').enum(Priority),
|
|
68
|
+
});
|
|
69
|
+
const config = schema.load({
|
|
70
|
+
env: { PRIORITY: '3' },
|
|
71
|
+
});
|
|
72
|
+
strictEqual(config.priority, 3);
|
|
73
|
+
});
|
|
74
|
+
await t.test('parses enum environment variables with mixed enum', () => {
|
|
75
|
+
let Status;
|
|
76
|
+
(function (Status) {
|
|
77
|
+
Status[Status["INACTIVE"] = 0] = "INACTIVE";
|
|
78
|
+
Status[Status["ACTIVE"] = 1] = "ACTIVE";
|
|
79
|
+
Status["PENDING"] = "pending";
|
|
80
|
+
Status["ARCHIVED"] = "archived";
|
|
81
|
+
})(Status || (Status = {}));
|
|
82
|
+
const schema = zc.define({
|
|
83
|
+
statusNum: zc.env('STATUS_NUM').enum(Status),
|
|
84
|
+
statusStr: zc.env('STATUS_STR').enum(Status),
|
|
85
|
+
});
|
|
86
|
+
const config = schema.load({
|
|
87
|
+
env: {
|
|
88
|
+
STATUS_NUM: '1',
|
|
89
|
+
STATUS_STR: 'pending',
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
strictEqual(config.statusNum, 1);
|
|
93
|
+
strictEqual(config.statusStr, 'pending');
|
|
94
|
+
});
|
|
95
|
+
await t.test('handles default values', () => {
|
|
96
|
+
const schema = zc.define({
|
|
97
|
+
host: zc.env('HOST').string().default('localhost'),
|
|
98
|
+
port: zc.env('PORT').number().default(8080),
|
|
99
|
+
secure: zc.env('SECURE').boolean().default(false),
|
|
100
|
+
});
|
|
101
|
+
const config = schema.load({
|
|
102
|
+
env: {},
|
|
103
|
+
});
|
|
104
|
+
strictEqual(config.host, 'localhost');
|
|
105
|
+
strictEqual(config.port, 8080);
|
|
106
|
+
strictEqual(config.secure, false);
|
|
107
|
+
});
|
|
108
|
+
await t.test('handles optional values', () => {
|
|
109
|
+
const schema = zc.define({
|
|
110
|
+
optionalKey: zc.env('OPTIONAL_KEY').string().optional(),
|
|
111
|
+
});
|
|
112
|
+
const config = schema.load({
|
|
113
|
+
env: {},
|
|
114
|
+
});
|
|
115
|
+
strictEqual(config.optionalKey, undefined);
|
|
116
|
+
});
|
|
117
|
+
await t.test('handles nested objects', () => {
|
|
118
|
+
const schema = zc.define({
|
|
119
|
+
server: zc.object({
|
|
120
|
+
host: zc.env('SERVER_HOST').string().default('localhost'),
|
|
121
|
+
port: zc.env('SERVER_PORT').number().default(3000),
|
|
122
|
+
}),
|
|
123
|
+
database: zc.object({
|
|
124
|
+
url: zc.env('DB_URL').string(),
|
|
125
|
+
pool: zc.object({
|
|
126
|
+
min: zc.env('DB_POOL_MIN').number().default(1),
|
|
127
|
+
max: zc.env('DB_POOL_MAX').number().default(10),
|
|
128
|
+
}),
|
|
129
|
+
}),
|
|
130
|
+
});
|
|
131
|
+
const config = schema.load({
|
|
132
|
+
env: {
|
|
133
|
+
SERVER_HOST: '0.0.0.0',
|
|
134
|
+
SERVER_PORT: '4000',
|
|
135
|
+
DB_URL: 'postgres://localhost/mydb',
|
|
136
|
+
DB_POOL_MAX: '20',
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
deepStrictEqual(config, {
|
|
140
|
+
server: {
|
|
141
|
+
host: '0.0.0.0',
|
|
142
|
+
port: 4000,
|
|
143
|
+
},
|
|
144
|
+
database: {
|
|
145
|
+
url: 'postgres://localhost/mydb',
|
|
146
|
+
pool: {
|
|
147
|
+
min: 1,
|
|
148
|
+
max: 20,
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
await t.test('handles complex configuration', () => {
|
|
154
|
+
const schema = zc.define({
|
|
155
|
+
app: zc.object({
|
|
156
|
+
name: zc.env('APP_NAME').string().default('MyApp'),
|
|
157
|
+
version: zc.env('APP_VERSION').string().default('1.0.0'),
|
|
158
|
+
debug: zc.env('DEBUG').boolean().default(false),
|
|
159
|
+
}),
|
|
160
|
+
server: zc.object({
|
|
161
|
+
host: zc.env('HOST').string().default('localhost'),
|
|
162
|
+
port: zc.env('PORT').number().default(3000),
|
|
163
|
+
ssl: zc.object({
|
|
164
|
+
enabled: zc.env('SSL_ENABLED').boolean().default(false),
|
|
165
|
+
cert: zc.env('SSL_CERT').string().optional(),
|
|
166
|
+
key: zc.env('SSL_KEY').string().optional(),
|
|
167
|
+
}),
|
|
168
|
+
}),
|
|
169
|
+
features: zc.object({
|
|
170
|
+
auth: zc.env('FEATURE_AUTH').boolean().default(true),
|
|
171
|
+
analytics: zc.env('FEATURE_ANALYTICS').boolean().default(false),
|
|
172
|
+
}),
|
|
173
|
+
});
|
|
174
|
+
const config = schema.load({
|
|
175
|
+
env: {
|
|
176
|
+
APP_NAME: 'TestApp',
|
|
177
|
+
DEBUG: 'true',
|
|
178
|
+
PORT: '5000',
|
|
179
|
+
SSL_ENABLED: 'true',
|
|
180
|
+
SSL_CERT: '/path/to/cert.pem',
|
|
181
|
+
SSL_KEY: '/path/to/key.pem',
|
|
182
|
+
FEATURE_ANALYTICS: 'true',
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
deepStrictEqual(config, {
|
|
186
|
+
app: {
|
|
187
|
+
name: 'TestApp',
|
|
188
|
+
version: '1.0.0',
|
|
189
|
+
debug: true,
|
|
190
|
+
},
|
|
191
|
+
server: {
|
|
192
|
+
host: 'localhost',
|
|
193
|
+
port: 5000,
|
|
194
|
+
ssl: {
|
|
195
|
+
enabled: true,
|
|
196
|
+
cert: '/path/to/cert.pem',
|
|
197
|
+
key: '/path/to/key.pem',
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
features: {
|
|
201
|
+
auth: true,
|
|
202
|
+
analytics: true,
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
await t.test('safeLoad returns success for valid config', () => {
|
|
207
|
+
const schema = zc.define({
|
|
208
|
+
apiKey: zc.env('API_KEY').string(),
|
|
209
|
+
});
|
|
210
|
+
const result = schema.safeLoad({
|
|
211
|
+
env: { API_KEY: 'secret-key' },
|
|
212
|
+
});
|
|
213
|
+
strictEqual(result.success, true);
|
|
214
|
+
if (result.success) {
|
|
215
|
+
strictEqual(result.data.apiKey, 'secret-key');
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
await t.test('safeLoad returns error for invalid config', () => {
|
|
219
|
+
const schema = zc.define({
|
|
220
|
+
port: zc.env('PORT').number(),
|
|
221
|
+
});
|
|
222
|
+
const result = schema.safeLoad({
|
|
223
|
+
env: { PORT: 'not-a-number' },
|
|
224
|
+
});
|
|
225
|
+
strictEqual(result.success, false);
|
|
226
|
+
if (!result.success) {
|
|
227
|
+
strictEqual(result.error.issues.length > 0, true);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
await t.test('handles fields without env metadata', () => {
|
|
231
|
+
const schema = zc.define({
|
|
232
|
+
// this field has no env binding, just a plain zod schema
|
|
233
|
+
plainField: zc.object({
|
|
234
|
+
nestedPlain: zc.env('SHOULD_WORK').string().default('default'),
|
|
235
|
+
}),
|
|
236
|
+
});
|
|
237
|
+
const config = schema.load({
|
|
238
|
+
env: {},
|
|
239
|
+
});
|
|
240
|
+
deepStrictEqual(config, {
|
|
241
|
+
plainField: {
|
|
242
|
+
nestedPlain: 'default',
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
await t.test('load throws error for invalid config', () => {
|
|
247
|
+
const schema = zc.define({
|
|
248
|
+
requiredField: zc.env('REQUIRED').string(),
|
|
249
|
+
});
|
|
250
|
+
let error;
|
|
251
|
+
try {
|
|
252
|
+
schema.load({
|
|
253
|
+
env: {},
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
catch (e) {
|
|
257
|
+
error = e;
|
|
258
|
+
}
|
|
259
|
+
strictEqual(error !== undefined, true);
|
|
260
|
+
strictEqual(error.issues !== undefined, true);
|
|
261
|
+
});
|
|
262
|
+
await t.test('handles enum with non-integer number strings', () => {
|
|
263
|
+
const schema = zc.define({
|
|
264
|
+
value: zc.env('VALUE').enum(['a', 'b', 'c']),
|
|
265
|
+
});
|
|
266
|
+
const config = schema.load({
|
|
267
|
+
env: { VALUE: 'a' },
|
|
268
|
+
});
|
|
269
|
+
strictEqual(config.value, 'a');
|
|
270
|
+
});
|
|
271
|
+
await t.test('handles enum with decimal number string', () => {
|
|
272
|
+
const schema = zc.define({
|
|
273
|
+
value: zc.env('DECIMAL_VALUE').enum(['3.14', 'pi', 'e']),
|
|
274
|
+
});
|
|
275
|
+
// this should pass the string through since "3.14" is not an integer
|
|
276
|
+
const config = schema.load({
|
|
277
|
+
env: { DECIMAL_VALUE: '3.14' },
|
|
278
|
+
});
|
|
279
|
+
strictEqual(config.value, '3.14');
|
|
280
|
+
});
|
|
281
|
+
await t.test('handles undefined env values for enum', () => {
|
|
282
|
+
const schema = zc.define({
|
|
283
|
+
optionalEnum: zc.env('OPT_ENUM').enum(['a', 'b']).optional(),
|
|
284
|
+
});
|
|
285
|
+
const config = schema.load({
|
|
286
|
+
env: {},
|
|
287
|
+
});
|
|
288
|
+
strictEqual(config.optionalEnum, undefined);
|
|
289
|
+
});
|
|
290
|
+
await t.test('handles schema without innerType or schema properties', () => {
|
|
291
|
+
// this tests the branch where we break out of the while loop
|
|
292
|
+
const schema = zc.define({
|
|
293
|
+
value: zc.env('VALUE').string(),
|
|
294
|
+
});
|
|
295
|
+
const config = schema.load({
|
|
296
|
+
env: { VALUE: 'test' },
|
|
297
|
+
});
|
|
298
|
+
strictEqual(config.value, 'test');
|
|
299
|
+
});
|
|
300
|
+
await t.test('handles deeply wrapped schemas with transformations', () => {
|
|
301
|
+
const schema = zc.define({
|
|
302
|
+
transformed: zc
|
|
303
|
+
.env('TRANSFORMED')
|
|
304
|
+
.string()
|
|
305
|
+
.optional()
|
|
306
|
+
.default('default')
|
|
307
|
+
.transform((v) => v.toUpperCase()),
|
|
308
|
+
});
|
|
309
|
+
const config = schema.load({
|
|
310
|
+
env: {},
|
|
311
|
+
});
|
|
312
|
+
strictEqual(config.transformed, 'DEFAULT');
|
|
313
|
+
});
|
|
314
|
+
await t.test('handles schema with no env metadata at all', async () => {
|
|
315
|
+
// create a plain zod schema without env bindings
|
|
316
|
+
const z = await import('zod');
|
|
317
|
+
const plainSchema = z.object({
|
|
318
|
+
plainField: z.string().default('plain'),
|
|
319
|
+
});
|
|
320
|
+
// mix it with env-bound fields
|
|
321
|
+
const schema = zc.define({
|
|
322
|
+
envField: zc.env('ENV_FIELD').string().default('env'),
|
|
323
|
+
plainNested: plainSchema.shape.plainField,
|
|
324
|
+
});
|
|
325
|
+
const config = schema.load({
|
|
326
|
+
env: {},
|
|
327
|
+
});
|
|
328
|
+
strictEqual(config.envField, 'env');
|
|
329
|
+
// plain fields without env binding will still use their Zod defaults
|
|
330
|
+
strictEqual(config.plainNested, 'plain');
|
|
331
|
+
});
|
|
332
|
+
await t.test('env proxy preserves non-schema properties and methods', async () => {
|
|
333
|
+
const envSchema = zc.env('TEST').string();
|
|
334
|
+
// test that metadata is stored in WeakMap (we can't directly access it from here)
|
|
335
|
+
// but we can verify the schema works correctly
|
|
336
|
+
const schema = zc.define({
|
|
337
|
+
test: envSchema,
|
|
338
|
+
});
|
|
339
|
+
const config = schema.load({ env: { TEST: 'value' } });
|
|
340
|
+
strictEqual(config.test, 'value');
|
|
341
|
+
// call methods that don't return schemas
|
|
342
|
+
const parsed = envSchema.parse('test');
|
|
343
|
+
strictEqual(parsed, 'test');
|
|
344
|
+
// access description property
|
|
345
|
+
const withDesc = zc.env('DESC').string().describe('A test field');
|
|
346
|
+
strictEqual(withDesc.description, 'A test field');
|
|
347
|
+
// test safeParse which returns a result object, not a schema
|
|
348
|
+
const result = zc.env('SAFE').number().safeParse('123');
|
|
349
|
+
strictEqual(result.success, true);
|
|
350
|
+
if (result.success) {
|
|
351
|
+
strictEqual(result.data, 123);
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
await t.test('env proxy handles methods returning non-objects', () => {
|
|
355
|
+
const schema = zc.env('TEST').string();
|
|
356
|
+
// test parse method returns the parsed value (not a schema)
|
|
357
|
+
const parsed = schema.parse('test');
|
|
358
|
+
strictEqual(parsed, 'test');
|
|
359
|
+
// test safeParse returns a result object (not a schema)
|
|
360
|
+
const result = schema.safeParse('value');
|
|
361
|
+
strictEqual(result.success, true);
|
|
362
|
+
if (result.success) {
|
|
363
|
+
strictEqual(result.data, 'value');
|
|
364
|
+
}
|
|
365
|
+
// test that optional() and nullable() still work (these are NOT deprecated)
|
|
366
|
+
const optionalSchema = schema.optional();
|
|
367
|
+
const nullableSchema = schema.nullable();
|
|
368
|
+
// verify they can parse undefined/null respectively
|
|
369
|
+
strictEqual(optionalSchema.parse(undefined), undefined);
|
|
370
|
+
strictEqual(nullableSchema.parse(null), null);
|
|
371
|
+
});
|
|
372
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { ZodObject, type ZodRawShape, type infer as ZodInfer } from 'zod';
|
|
2
|
+
type Env = Record<string, string | undefined>;
|
|
3
|
+
export type LoadParams = {
|
|
4
|
+
env: Env;
|
|
5
|
+
};
|
|
6
|
+
export declare class ZodConfSchema<T extends ZodRawShape> {
|
|
7
|
+
private shape;
|
|
8
|
+
private schema;
|
|
9
|
+
constructor(shape: T, schema: ZodObject<T>);
|
|
10
|
+
private loadValue;
|
|
11
|
+
/**
|
|
12
|
+
* Loads and validates configuration from environment variables.
|
|
13
|
+
* Throws a ZodError if validation fails.
|
|
14
|
+
*
|
|
15
|
+
* @param input - Object containing environment variables
|
|
16
|
+
* @param input.env - Environment variables as key-value pairs
|
|
17
|
+
* @returns Validated configuration object
|
|
18
|
+
* @throws {ZodError} If validation fails
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const config = schema.load({ env: process.env });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
load(input: LoadParams): ZodInfer<ZodObject<T>>;
|
|
26
|
+
/**
|
|
27
|
+
* Safely loads and validates configuration without throwing.
|
|
28
|
+
* Returns a result object with either success or error.
|
|
29
|
+
*
|
|
30
|
+
* @param input - Object containing environment variables
|
|
31
|
+
* @param input.env - Environment variables as key-value pairs
|
|
32
|
+
* @returns SafeParseReturnType with either { success: true, data } or { success: false, error }
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const result = schema.safeLoad({ env: process.env });
|
|
37
|
+
*
|
|
38
|
+
* if (result.success) {
|
|
39
|
+
* console.log('Config:', result.data);
|
|
40
|
+
* } else {
|
|
41
|
+
* console.error('Errors:', result.error.issues);
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
safeLoad(input: LoadParams): import("zod").ZodSafeParseResult<import("zod/v4/core").$InferObjectOutput<T, {}>>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Creates a configuration schema with environment variable bindings.
|
|
49
|
+
*
|
|
50
|
+
* @param shape - An object defining the configuration structure where each field
|
|
51
|
+
* uses `env()` to bind to environment variables or `object()` for nesting
|
|
52
|
+
* @returns A ZodConfSchema instance with `load()` and `safeLoad()` methods
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* // define a configuration schema
|
|
57
|
+
* const schema = define({
|
|
58
|
+
* port: env('PORT').number().default(3000),
|
|
59
|
+
* host: env('HOST').string().default('localhost'),
|
|
60
|
+
* database: object({
|
|
61
|
+
* url: env('DATABASE_URL').string(),
|
|
62
|
+
* poolSize: env('DB_POOL_SIZE').number().default(10),
|
|
63
|
+
* }),
|
|
64
|
+
* });
|
|
65
|
+
*
|
|
66
|
+
* // load configuration from environment
|
|
67
|
+
* const config = schema.load({ env: process.env });
|
|
68
|
+
*
|
|
69
|
+
* // safe load without throwing
|
|
70
|
+
* const result = schema.safeLoad({ env: process.env });
|
|
71
|
+
* if (result.success) {
|
|
72
|
+
* console.log(result.data);
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare const define: <T extends ZodRawShape>(shape: T) => ZodConfSchema<T>;
|
|
77
|
+
export {};
|
|
78
|
+
//# sourceMappingURL=define.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/values/define.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAU,KAAK,WAAW,EAAgB,KAAK,KAAK,IAAI,QAAQ,EAAE,MAAM,KAAK,CAAC;AAGhG,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAE9C,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,GAAG,CAAC;CACV,CAAC;AAEF,qBAAa,aAAa,CAAC,CAAC,SAAS,WAAW;IAE5C,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,MAAM;gBADN,KAAK,EAAE,CAAC,EACR,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAG9B,OAAO,CAAC,SAAS;IA6EjB;;;;;;;;;;;;;OAaG;IACH,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAU/C;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,KAAK,EAAE,UAAU;CAK3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,MAAM,GAAI,CAAC,SAAS,WAAW,EAAE,OAAO,CAAC,KAAG,aAAa,CAAC,CAAC,CAEvE,CAAC"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { ZodObject, object } from 'zod';
|
|
2
|
+
import { _envMetadata } from './env-metadata.js';
|
|
3
|
+
export class ZodConfSchema {
|
|
4
|
+
shape;
|
|
5
|
+
schema;
|
|
6
|
+
constructor(shape, schema) {
|
|
7
|
+
this.shape = shape;
|
|
8
|
+
this.schema = schema;
|
|
9
|
+
}
|
|
10
|
+
loadValue(shape, env) {
|
|
11
|
+
const input = {};
|
|
12
|
+
for (const key in shape) {
|
|
13
|
+
const schema = shape[key];
|
|
14
|
+
if (schema instanceof ZodObject) {
|
|
15
|
+
// for nested objects, recurse
|
|
16
|
+
input[key] = this.loadValue(schema.shape, env);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
let currentSchema = schema;
|
|
20
|
+
let envKey;
|
|
21
|
+
let envType;
|
|
22
|
+
// traverse wrapped schemas to find metadata
|
|
23
|
+
while (currentSchema && !envKey) {
|
|
24
|
+
const metadata = _envMetadata.get(currentSchema);
|
|
25
|
+
if (metadata) {
|
|
26
|
+
// found metadata -> use it
|
|
27
|
+
envKey = metadata.key;
|
|
28
|
+
envType = metadata.type;
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
// check if this is a wrapped schema (default, optional, etc.)
|
|
32
|
+
const def = currentSchema._def;
|
|
33
|
+
if (def?.innerType) {
|
|
34
|
+
// zod wrappers like optional, default, nullable, etc.
|
|
35
|
+
currentSchema = def.innerType;
|
|
36
|
+
}
|
|
37
|
+
else if (def?.schema) {
|
|
38
|
+
// zod effects
|
|
39
|
+
currentSchema = def.schema;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
// end of the chain, no metadata found
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (envKey) {
|
|
47
|
+
const value = env[envKey];
|
|
48
|
+
switch (envType) {
|
|
49
|
+
case 'string':
|
|
50
|
+
input[key] = value;
|
|
51
|
+
break;
|
|
52
|
+
case 'number':
|
|
53
|
+
input[key] = value ? Number(value) : undefined;
|
|
54
|
+
break;
|
|
55
|
+
case 'boolean':
|
|
56
|
+
input[key] = value === 'true' ? true : value === 'false' ? false : undefined;
|
|
57
|
+
break;
|
|
58
|
+
case 'enum': {
|
|
59
|
+
const numValue = Number(value);
|
|
60
|
+
// guess if enum is number-based
|
|
61
|
+
if (value && !isNaN(numValue) && Number.isInteger(numValue)) {
|
|
62
|
+
input[key] = numValue;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
input[key] = value;
|
|
66
|
+
}
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
default:
|
|
70
|
+
input[key] = undefined;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
input[key] = undefined;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return input;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Loads and validates configuration from environment variables.
|
|
82
|
+
* Throws a ZodError if validation fails.
|
|
83
|
+
*
|
|
84
|
+
* @param input - Object containing environment variables
|
|
85
|
+
* @param input.env - Environment variables as key-value pairs
|
|
86
|
+
* @returns Validated configuration object
|
|
87
|
+
* @throws {ZodError} If validation fails
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* const config = schema.load({ env: process.env });
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
load(input) {
|
|
95
|
+
const result = this.safeLoad(input);
|
|
96
|
+
if (!result.success) {
|
|
97
|
+
throw result.error;
|
|
98
|
+
}
|
|
99
|
+
return result.data;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Safely loads and validates configuration without throwing.
|
|
103
|
+
* Returns a result object with either success or error.
|
|
104
|
+
*
|
|
105
|
+
* @param input - Object containing environment variables
|
|
106
|
+
* @param input.env - Environment variables as key-value pairs
|
|
107
|
+
* @returns SafeParseReturnType with either { success: true, data } or { success: false, error }
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```typescript
|
|
111
|
+
* const result = schema.safeLoad({ env: process.env });
|
|
112
|
+
*
|
|
113
|
+
* if (result.success) {
|
|
114
|
+
* console.log('Config:', result.data);
|
|
115
|
+
* } else {
|
|
116
|
+
* console.error('Errors:', result.error.issues);
|
|
117
|
+
* }
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
safeLoad(input) {
|
|
121
|
+
const value = this.loadValue(this.shape, input.env);
|
|
122
|
+
return this.schema.safeParse(value);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Creates a configuration schema with environment variable bindings.
|
|
127
|
+
*
|
|
128
|
+
* @param shape - An object defining the configuration structure where each field
|
|
129
|
+
* uses `env()` to bind to environment variables or `object()` for nesting
|
|
130
|
+
* @returns A ZodConfSchema instance with `load()` and `safeLoad()` methods
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* // define a configuration schema
|
|
135
|
+
* const schema = define({
|
|
136
|
+
* port: env('PORT').number().default(3000),
|
|
137
|
+
* host: env('HOST').string().default('localhost'),
|
|
138
|
+
* database: object({
|
|
139
|
+
* url: env('DATABASE_URL').string(),
|
|
140
|
+
* poolSize: env('DB_POOL_SIZE').number().default(10),
|
|
141
|
+
* }),
|
|
142
|
+
* });
|
|
143
|
+
*
|
|
144
|
+
* // load configuration from environment
|
|
145
|
+
* const config = schema.load({ env: process.env });
|
|
146
|
+
*
|
|
147
|
+
* // safe load without throwing
|
|
148
|
+
* const result = schema.safeLoad({ env: process.env });
|
|
149
|
+
* if (result.success) {
|
|
150
|
+
* console.log(result.data);
|
|
151
|
+
* }
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export const define = (shape) => {
|
|
155
|
+
return new ZodConfSchema(shape, object(shape));
|
|
156
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/values/define.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAA0D,MAAM,KAAK,CAAC;AAChG,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAQjD,MAAM,OAAO,aAAa;IAEd;IACA;IAFV,YACU,KAAQ,EACR,MAAoB;QADpB,UAAK,GAAL,KAAK,CAAG;QACR,WAAM,GAAN,MAAM,CAAc;IAC3B,CAAC;IAEI,SAAS,CAAC,KAAkB,EAAE,GAAQ;QAC5C,MAAM,KAAK,GAAQ,EAAE,CAAC;QAEtB,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;YAE1B,IAAI,MAAM,YAAY,SAAS,EAAE,CAAC;gBAEhC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACjD,CAAC;iBAAM,CAAC;gBACN,IAAI,aAAa,GAAG,MAAiB,CAAC;gBACtC,IAAI,MAA0B,CAAC;gBAC/B,IAAI,OAA2B,CAAC;gBAGhC,OAAO,aAAa,IAAI,CAAC,MAAM,EAAE,CAAC;oBAChC,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;oBAEjD,IAAI,QAAQ,EAAE,CAAC;wBAEb,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC;wBACtB,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC;wBACxB,MAAM;oBACR,CAAC;oBAGD,MAAM,GAAG,GAAI,aAAqB,CAAC,IAAI,CAAC;oBAExC,IAAI,GAAG,EAAE,SAAS,EAAE,CAAC;wBAEnB,aAAa,GAAG,GAAG,CAAC,SAAS,CAAC;oBAChC,CAAC;yBAAM,IAAI,GAAG,EAAE,MAAM,EAAE,CAAC;wBAEvB,aAAa,GAAG,GAAG,CAAC,MAAM,CAAC;oBAC7B,CAAC;yBAAM,CAAC;wBAEN,MAAM;oBACR,CAAC;gBACH,CAAC;gBAED,IAAI,MAAM,EAAE,CAAC;oBACX,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;oBAE1B,QAAQ,OAAO,EAAE,CAAC;wBAChB,KAAK,QAAQ;4BACX,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;4BACnB,MAAM;wBACR,KAAK,QAAQ;4BACX,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;4BAC/C,MAAM;wBACR,KAAK,SAAS;4BACZ,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;4BAC7E,MAAM;wBACR,KAAK,MAAM,CAAC,CAAC,CAAC;4BACZ,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;4BAG/B,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;gCAC5D,KAAK,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;4BACxB,CAAC;iCAAM,CAAC;gCACN,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;4BACrB,CAAC;4BAED,MAAM;wBACR,CAAC;wBACD;4BACE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;oBAC3B,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;gBACzB,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAgBD,IAAI,CAAC,KAAiB;QACpB,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAEpC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,MAAM,CAAC,KAAK,CAAC;QACrB,CAAC;QAED,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAqBD,QAAQ,CAAC,KAAiB;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAEpD,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;CACF;AA+BD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAwB,KAAQ,EAAoB,EAAE;IAC1E,OAAO,IAAI,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-metadata.d.ts","sourceRoot":"","sources":["../../src/values/env-metadata.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AAGnC,eAAO,MAAM,YAAY;SAA+B,MAAM;UAAQ,MAAM;EAAK,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-metadata.js","sourceRoot":"","sources":["../../src/values/env-metadata.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,EAA0C,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type util, type ZodEnum } from 'zod';
|
|
2
|
+
import { coerce } from 'zod';
|
|
3
|
+
/**
|
|
4
|
+
* Binds a Zod schema to an environment variable.
|
|
5
|
+
*
|
|
6
|
+
* @param key - The name of the environment variable to bind to
|
|
7
|
+
* @returns An object with methods to create different types of schemas:
|
|
8
|
+
* - `string()` - Creates a string schema
|
|
9
|
+
* - `number()` - Creates a number schema (auto-coerced from string)
|
|
10
|
+
* - `boolean()` - Creates a boolean schema (accepts 'true'/'false')
|
|
11
|
+
* - `enum(values)` - Creates an enum schema (string array or TypeScript enum)
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // string environment variable
|
|
16
|
+
* const apiUrl = env('API_URL').string();
|
|
17
|
+
*
|
|
18
|
+
* // number with default
|
|
19
|
+
* const port = env('PORT').number().default(3000);
|
|
20
|
+
*
|
|
21
|
+
* // boolean
|
|
22
|
+
* const debug = env('DEBUG').boolean().default(false);
|
|
23
|
+
*
|
|
24
|
+
* // enum with string array
|
|
25
|
+
* const logLevel = env('LOG_LEVEL').enum(['info', 'debug', 'error']);
|
|
26
|
+
*
|
|
27
|
+
* // enum with TypeScript enum
|
|
28
|
+
* enum Level { INFO = 'info', DEBUG = 'debug' }
|
|
29
|
+
* const level = env('LOG_LEVEL').enum(Level);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare const env: (key: string) => {
|
|
33
|
+
string: () => import("zod").ZodString;
|
|
34
|
+
number: () => coerce.ZodCoercedNumber<unknown>;
|
|
35
|
+
boolean: () => coerce.ZodCoercedBoolean<unknown>;
|
|
36
|
+
enum: {
|
|
37
|
+
<const T extends readonly string[]>(values: T): ZodEnum<util.ToEnum<T[number]>>;
|
|
38
|
+
<const T extends Readonly<Record<string, string | number>>>(entries: T): ZodEnum<T>;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/values/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,OAAO,EAAgB,MAAM,KAAK,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAyB,MAAM,KAAK,CAAC;AAGpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,GAAG,GAAI,KAAK,MAAM;;;;;eA2CC,CAAC,SAAS,SAAS,MAAM,EAAE,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;eAExE,CAAC,6DAA4B,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;;CAS1E,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { coerce, string, enum as zenum } from 'zod';
|
|
2
|
+
import { _envMetadata } from './env-metadata.js';
|
|
3
|
+
/**
|
|
4
|
+
* Binds a Zod schema to an environment variable.
|
|
5
|
+
*
|
|
6
|
+
* @param key - The name of the environment variable to bind to
|
|
7
|
+
* @returns An object with methods to create different types of schemas:
|
|
8
|
+
* - `string()` - Creates a string schema
|
|
9
|
+
* - `number()` - Creates a number schema (auto-coerced from string)
|
|
10
|
+
* - `boolean()` - Creates a boolean schema (accepts 'true'/'false')
|
|
11
|
+
* - `enum(values)` - Creates an enum schema (string array or TypeScript enum)
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // string environment variable
|
|
16
|
+
* const apiUrl = env('API_URL').string();
|
|
17
|
+
*
|
|
18
|
+
* // number with default
|
|
19
|
+
* const port = env('PORT').number().default(3000);
|
|
20
|
+
*
|
|
21
|
+
* // boolean
|
|
22
|
+
* const debug = env('DEBUG').boolean().default(false);
|
|
23
|
+
*
|
|
24
|
+
* // enum with string array
|
|
25
|
+
* const logLevel = env('LOG_LEVEL').enum(['info', 'debug', 'error']);
|
|
26
|
+
*
|
|
27
|
+
* // enum with TypeScript enum
|
|
28
|
+
* enum Level { INFO = 'info', DEBUG = 'debug' }
|
|
29
|
+
* const level = env('LOG_LEVEL').enum(Level);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export const env = (key) => {
|
|
33
|
+
const wrap = (schema, envKey, envType) => {
|
|
34
|
+
// create a proxy to preserve metadata through method chaining
|
|
35
|
+
const proxied = new Proxy(schema, {
|
|
36
|
+
get(target, prop) {
|
|
37
|
+
const value = target[prop];
|
|
38
|
+
// if it's a method, wrap the result to preserve metadata
|
|
39
|
+
// e.g. .default(), .optional(), etc.
|
|
40
|
+
if (typeof value === 'function') {
|
|
41
|
+
return (...args) => {
|
|
42
|
+
// call original method
|
|
43
|
+
const result = value.apply(target, args);
|
|
44
|
+
if (result && typeof result === 'object' && result._def) {
|
|
45
|
+
// if result is a new chained Zod schema, wrap it in a new proxy
|
|
46
|
+
return wrap(result, envKey, envType);
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// regular property, just return it
|
|
52
|
+
return value;
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
// remember metadata for the proxied object
|
|
56
|
+
_envMetadata.set(proxied, { key: envKey, type: envType });
|
|
57
|
+
return proxied;
|
|
58
|
+
};
|
|
59
|
+
return {
|
|
60
|
+
string: () => wrap(string(), key, 'string'),
|
|
61
|
+
number: () => wrap(coerce.number(), key, 'number'),
|
|
62
|
+
boolean: () => wrap(coerce.boolean(), key, 'boolean'),
|
|
63
|
+
enum: (() => {
|
|
64
|
+
// implementation
|
|
65
|
+
function enumMethod(values) {
|
|
66
|
+
return wrap(zenum(values), key, 'enum');
|
|
67
|
+
}
|
|
68
|
+
return enumMethod;
|
|
69
|
+
})(),
|
|
70
|
+
};
|
|
71
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/values/env.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,IAAI,KAAK,EAAE,MAAM,KAAK,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AA+BjD,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE;IACjC,MAAM,IAAI,GAAG,CAAoB,MAAS,EAAE,MAAc,EAAE,OAAe,EAAK,EAAE;QAEhF,MAAM,OAAO,GAAG,IAAI,KAAK,CAAC,MAAM,EAAE;YAChC,GAAG,CAAC,MAAM,EAAE,IAAI;gBACd,MAAM,KAAK,GAAI,MAAc,CAAC,IAAI,CAAC,CAAC;gBAIpC,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;oBAChC,OAAO,CAAC,GAAG,IAAW,EAAE,EAAE;wBAExB,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;wBAEzC,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;4BAExD,OAAO,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;wBACvC,CAAC;wBAED,OAAO,MAAM,CAAC;oBAChB,CAAC,CAAC;gBACJ,CAAC;gBAGD,OAAO,KAAK,CAAC;YACf,CAAC;SACF,CAAM,CAAC;QAGR,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAE1D,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;IAEF,OAAO;QACL,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,QAAQ,CAAC;QAC3C,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,QAAQ,CAAC;QAClD,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC;QACrD,IAAI,EAAE,CAAC,GAAG,EAAE;YASV,SAAS,UAAU,CAAC,MAAW;gBAC7B,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;YAC1C,CAAC;YAED,OAAO,UAAU,CAAC;QACpB,CAAC,CAAC,EAAE;KACL,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type ZodObject } from 'zod';
|
|
2
|
+
import { type ZodRawShape } from 'zod';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a nested object schema for grouping related configuration.
|
|
5
|
+
* This is a convenience wrapper around Zod's object() for consistency.
|
|
6
|
+
*
|
|
7
|
+
* @param shape - An object where values are environment bindings or nested objects
|
|
8
|
+
* @returns A Zod object schema
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const schema = define({
|
|
13
|
+
* // group related configuration
|
|
14
|
+
* server: object({
|
|
15
|
+
* host: env('SERVER_HOST').string().default('localhost'),
|
|
16
|
+
* port: env('SERVER_PORT').number().default(3000),
|
|
17
|
+
* }),
|
|
18
|
+
*
|
|
19
|
+
* // nested objects
|
|
20
|
+
* database: object({
|
|
21
|
+
* connection: object({
|
|
22
|
+
* url: env('DATABASE_URL').string(),
|
|
23
|
+
* timeout: env('DB_TIMEOUT').number().default(5000),
|
|
24
|
+
* }),
|
|
25
|
+
* pool: object({
|
|
26
|
+
* min: env('DB_POOL_MIN').number().default(1),
|
|
27
|
+
* max: env('DB_POOL_MAX').number().default(10),
|
|
28
|
+
* }),
|
|
29
|
+
* }),
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare const object: <T extends ZodRawShape>(shape: T) => ZodObject<T>;
|
|
34
|
+
//# sourceMappingURL=object.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../../src/values/object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,KAAK,CAAC;AACrC,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,KAAK,CAAC;AAGvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,MAAM,GAAI,CAAC,SAAS,WAAW,EAAE,OAAO,CAAC,KAAG,SAAS,CAAC,CAAC,CAEnE,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { object as zobject } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a nested object schema for grouping related configuration.
|
|
4
|
+
* This is a convenience wrapper around Zod's object() for consistency.
|
|
5
|
+
*
|
|
6
|
+
* @param shape - An object where values are environment bindings or nested objects
|
|
7
|
+
* @returns A Zod object schema
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const schema = define({
|
|
12
|
+
* // group related configuration
|
|
13
|
+
* server: object({
|
|
14
|
+
* host: env('SERVER_HOST').string().default('localhost'),
|
|
15
|
+
* port: env('SERVER_PORT').number().default(3000),
|
|
16
|
+
* }),
|
|
17
|
+
*
|
|
18
|
+
* // nested objects
|
|
19
|
+
* database: object({
|
|
20
|
+
* connection: object({
|
|
21
|
+
* url: env('DATABASE_URL').string(),
|
|
22
|
+
* timeout: env('DB_TIMEOUT').number().default(5000),
|
|
23
|
+
* }),
|
|
24
|
+
* pool: object({
|
|
25
|
+
* min: env('DB_POOL_MIN').number().default(1),
|
|
26
|
+
* max: env('DB_POOL_MAX').number().default(10),
|
|
27
|
+
* }),
|
|
28
|
+
* }),
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export const object = (shape) => {
|
|
33
|
+
return zobject(shape);
|
|
34
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object.js","sourceRoot":"","sources":["../../src/values/object.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,KAAK,CAAC;AAgCxC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAwB,KAAQ,EAAgB,EAAE;IACtE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;AACxB,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zod-conf",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Type-safe configuration management with Zod schemas and environment variables",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "smnbbrv",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
"keywords": [
|
|
23
|
+
"zod",
|
|
24
|
+
"config",
|
|
25
|
+
"configuration",
|
|
26
|
+
"env",
|
|
27
|
+
"environment",
|
|
28
|
+
"schema",
|
|
29
|
+
"validation",
|
|
30
|
+
"typescript"
|
|
31
|
+
],
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/smnbbrv/zod-conf.git"
|
|
35
|
+
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/smnbbrv/zod-conf/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/smnbbrv/zod-conf#readme",
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc --project tsconfig.build.json",
|
|
42
|
+
"clean": "rm -rf dist",
|
|
43
|
+
"prebuild": "npm run clean",
|
|
44
|
+
"prepublishOnly": "npm run build && npm run test && npm run lint",
|
|
45
|
+
"lint": "run-s lint:*",
|
|
46
|
+
"lint:eslint": "eslint . --report-unused-disable-directives --max-warnings 0",
|
|
47
|
+
"lint:tsc": "tsc",
|
|
48
|
+
"test": "npx tsx --test --experimental-test-coverage src/index.test.ts",
|
|
49
|
+
"prepare": "husky",
|
|
50
|
+
"semantic-release": "semantic-release"
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public",
|
|
54
|
+
"provenance": true
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"zod": "^4.0.0"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@commitlint/cli": "^19.8.1",
|
|
61
|
+
"@commitlint/config-conventional": "^19.8.1",
|
|
62
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
63
|
+
"@semantic-release/git": "^10.0.1",
|
|
64
|
+
"@types/node": "^24.3.1",
|
|
65
|
+
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
|
66
|
+
"dotenv": "^17.2.2",
|
|
67
|
+
"eslint": "^9.32.0",
|
|
68
|
+
"eslint-config-prettier": "^10.1.8",
|
|
69
|
+
"eslint-import-resolver-typescript": "^4.4.4",
|
|
70
|
+
"eslint-plugin-import": "^2.32.0",
|
|
71
|
+
"eslint-plugin-prettier": "^5.5.3",
|
|
72
|
+
"husky": "^9.1.7",
|
|
73
|
+
"npm-run-all": "^4.1.5",
|
|
74
|
+
"semantic-release": "^24.2.7",
|
|
75
|
+
"tsx": "^4.20.5",
|
|
76
|
+
"typescript": "^5.9.2",
|
|
77
|
+
"typescript-eslint": "^8.38.0",
|
|
78
|
+
"zod": "^4.0.13"
|
|
79
|
+
}
|
|
80
|
+
}
|