use-zod-default 1.0.1
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 +126 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +234 -0
- package/package.json +29 -0
package/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# use-zod-default
|
|
2
|
+
|
|
3
|
+
Effortlessly create default instances from Zod schemas with intelligent type inference and flexible customization.
|
|
4
|
+
|
|
5
|
+
## 🚀 Features
|
|
6
|
+
|
|
7
|
+
- 📦 Create default instances from Zod schemas
|
|
8
|
+
- 🧠 Intelligent type inference
|
|
9
|
+
- 🛠 Support for nested objects, arrays, and complex types
|
|
10
|
+
- 🎛 Customizable with partial source objects
|
|
11
|
+
- 🔄 Handles discriminated unions and regular unions
|
|
12
|
+
- 🏷 Full TypeScript support
|
|
13
|
+
|
|
14
|
+
## 📦 Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install use-zod-default
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
or
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
yarn add use-zod-default
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 🛠 Usage
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { z } from 'zod';
|
|
30
|
+
import defaultInstance from 'use-zod-default';
|
|
31
|
+
|
|
32
|
+
// Define your Zod schema
|
|
33
|
+
const userSchema = z.object({
|
|
34
|
+
name: z.string(),
|
|
35
|
+
age: z.number(),
|
|
36
|
+
isActive: z.boolean(),
|
|
37
|
+
roles: z.array(z.string()),
|
|
38
|
+
settings: z.object({
|
|
39
|
+
theme: z.enum(['light', 'dark']),
|
|
40
|
+
notifications: z.boolean()
|
|
41
|
+
})
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Create a default instance
|
|
45
|
+
const defaultUser = defaultInstance(userSchema);
|
|
46
|
+
|
|
47
|
+
console.log(defaultUser);
|
|
48
|
+
// Output:
|
|
49
|
+
// {
|
|
50
|
+
// name: '',
|
|
51
|
+
// age: 0,
|
|
52
|
+
// isActive: false,
|
|
53
|
+
// roles: [],
|
|
54
|
+
// settings: {
|
|
55
|
+
// theme: 'light',
|
|
56
|
+
// notifications: false
|
|
57
|
+
// }
|
|
58
|
+
// }
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### With Partial Source
|
|
62
|
+
|
|
63
|
+
You can provide a partial source object to override default values:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
const partialUser = {
|
|
67
|
+
name: 'John Doe',
|
|
68
|
+
settings: {
|
|
69
|
+
theme: 'dark'
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const userWithCustomValues = defaultInstance(userSchema, partialUser);
|
|
74
|
+
|
|
75
|
+
console.log(userWithCustomValues);
|
|
76
|
+
// Output:
|
|
77
|
+
// {
|
|
78
|
+
// name: 'John Doe',
|
|
79
|
+
// age: 0,
|
|
80
|
+
// isActive: false,
|
|
81
|
+
// roles: [],
|
|
82
|
+
// settings: {
|
|
83
|
+
// theme: 'dark',
|
|
84
|
+
// notifications: false
|
|
85
|
+
// }
|
|
86
|
+
// }
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## 🧩 Advanced Usage
|
|
90
|
+
|
|
91
|
+
### Discriminated Unions
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const resultSchema = z.discriminatedUnion('status', [
|
|
95
|
+
z.object({ status: z.literal('success'), data: z.string() }),
|
|
96
|
+
z.object({ status: z.literal('error'), message: z.string() })
|
|
97
|
+
]);
|
|
98
|
+
|
|
99
|
+
const defaultResult = defaultInstance(resultSchema);
|
|
100
|
+
console.log(defaultResult); // { status: 'success', data: '' }
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Regular Unions
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
const dataSchema = z.union([
|
|
107
|
+
z.object({ type: z.literal('string'), value: z.string() }),
|
|
108
|
+
z.object({ type: z.literal('number'), value: z.number() }),
|
|
109
|
+
z.string()
|
|
110
|
+
]);
|
|
111
|
+
|
|
112
|
+
const defaultData = defaultInstance(dataSchema);
|
|
113
|
+
console.log(defaultData); // { type: 'string', value: '' }
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## 📝 License
|
|
117
|
+
|
|
118
|
+
MIT © [Felipe Rohde](mailto:feliperohdee@gmail.com)
|
|
119
|
+
|
|
120
|
+
## 👨💻 Author
|
|
121
|
+
|
|
122
|
+
**Felipe Rohde**
|
|
123
|
+
|
|
124
|
+
- Twitter: [@felipe_rohde](https://twitter.com/felipe_rohde)
|
|
125
|
+
- Github: [@feliperohdee](https://github.com/feliperohdee)
|
|
126
|
+
- Email: feliperohdee@gmail.com
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const defaultInstance = (schema, source = {}) => {
|
|
3
|
+
const getDefaultValue = (schema) => {
|
|
4
|
+
if (schema instanceof z.ZodDefault) {
|
|
5
|
+
return schema._def.defaultValue();
|
|
6
|
+
}
|
|
7
|
+
if (schema instanceof z.ZodAny) {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
if (schema instanceof z.ZodArray) {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
if (schema instanceof z.ZodBoolean) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
if (schema instanceof z.ZodDate) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
if (schema instanceof z.ZodDiscriminatedUnion) {
|
|
20
|
+
return defaultInstance(schema.options[0]);
|
|
21
|
+
}
|
|
22
|
+
if (schema instanceof z.ZodEffects) {
|
|
23
|
+
return getDefaultValue(schema.innerType());
|
|
24
|
+
}
|
|
25
|
+
if (schema instanceof z.ZodEnum) {
|
|
26
|
+
return schema.options[0];
|
|
27
|
+
}
|
|
28
|
+
if (schema instanceof z.ZodFunction) {
|
|
29
|
+
return () => null;
|
|
30
|
+
}
|
|
31
|
+
if (schema instanceof z.ZodIntersection) {
|
|
32
|
+
return defaultInstance(schema._def.left, source);
|
|
33
|
+
}
|
|
34
|
+
if (schema instanceof z.ZodLiteral) {
|
|
35
|
+
return schema.value;
|
|
36
|
+
}
|
|
37
|
+
if (schema instanceof z.ZodMap) {
|
|
38
|
+
return new Map();
|
|
39
|
+
}
|
|
40
|
+
if (schema instanceof z.ZodNativeEnum) {
|
|
41
|
+
const keys = Object.keys(schema._def.values);
|
|
42
|
+
return schema._def.values[keys[0]];
|
|
43
|
+
}
|
|
44
|
+
if (schema instanceof z.ZodNaN) {
|
|
45
|
+
return NaN;
|
|
46
|
+
}
|
|
47
|
+
if (schema instanceof z.ZodNever) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
if (schema instanceof z.ZodNull) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
if (schema instanceof z.ZodNullable) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
if (schema instanceof z.ZodNumber || schema instanceof z.ZodBigInt) {
|
|
57
|
+
return schema.minValue ?? 0;
|
|
58
|
+
}
|
|
59
|
+
if (schema instanceof z.ZodObject) {
|
|
60
|
+
return defaultInstance(schema, {});
|
|
61
|
+
}
|
|
62
|
+
if (schema instanceof z.ZodPipeline) {
|
|
63
|
+
if (!('out' in schema._def)) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
return getDefaultValue(schema._def.out);
|
|
67
|
+
}
|
|
68
|
+
if (schema instanceof z.ZodPromise) {
|
|
69
|
+
return Promise.resolve(getDefaultValue(schema.unwrap()));
|
|
70
|
+
}
|
|
71
|
+
if (schema instanceof z.ZodRecord) {
|
|
72
|
+
return {};
|
|
73
|
+
}
|
|
74
|
+
if (schema instanceof z.ZodSet) {
|
|
75
|
+
return new Set();
|
|
76
|
+
}
|
|
77
|
+
if (schema instanceof z.ZodString) {
|
|
78
|
+
return '';
|
|
79
|
+
}
|
|
80
|
+
if (schema instanceof z.ZodSymbol) {
|
|
81
|
+
return '';
|
|
82
|
+
}
|
|
83
|
+
if (schema instanceof z.ZodTuple) {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
if (schema instanceof z.ZodUnion) {
|
|
87
|
+
return getDefaultValue(schema.options[0]);
|
|
88
|
+
}
|
|
89
|
+
if (schema instanceof z.ZodUnknown) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
if (schema instanceof z.ZodUndefined) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
if (schema instanceof z.ZodVoid) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
if (schema._def && schema._def.innerType) {
|
|
99
|
+
return getDefaultValue(schema._def.innerType);
|
|
100
|
+
}
|
|
101
|
+
return undefined;
|
|
102
|
+
};
|
|
103
|
+
const processArray = (schema, source) => {
|
|
104
|
+
if (!Array.isArray(source)) {
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
const elementSchema = schema.element;
|
|
108
|
+
return source.map(item => {
|
|
109
|
+
return processValue(elementSchema, item);
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
const processDiscriminatedUnion = (schema, source) => {
|
|
113
|
+
if (typeof source !== 'object' || source === null) {
|
|
114
|
+
return getDefaultValue(schema);
|
|
115
|
+
}
|
|
116
|
+
const discriminator = schema.discriminator;
|
|
117
|
+
const discriminatorValue = source[discriminator];
|
|
118
|
+
const matchingSchema = schema.options.find(option => {
|
|
119
|
+
return option.shape[discriminator] instanceof z.ZodLiteral && option.shape[discriminator].value === discriminatorValue;
|
|
120
|
+
});
|
|
121
|
+
if (!matchingSchema) {
|
|
122
|
+
// If no matching schema is found, use the first option as default
|
|
123
|
+
return processObject(schema.options[0], source);
|
|
124
|
+
}
|
|
125
|
+
return processObject(matchingSchema, source);
|
|
126
|
+
};
|
|
127
|
+
const processValue = (schema, value) => {
|
|
128
|
+
if (schema instanceof z.ZodObject) {
|
|
129
|
+
return processObject(schema, value);
|
|
130
|
+
}
|
|
131
|
+
else if (schema instanceof z.ZodArray) {
|
|
132
|
+
return processArray(schema, value);
|
|
133
|
+
}
|
|
134
|
+
else if (schema instanceof z.ZodDiscriminatedUnion) {
|
|
135
|
+
return processDiscriminatedUnion(schema, value);
|
|
136
|
+
}
|
|
137
|
+
else if (schema instanceof z.ZodUnion) {
|
|
138
|
+
return processUnion(schema, value);
|
|
139
|
+
}
|
|
140
|
+
else if (schema instanceof z.ZodBoolean) {
|
|
141
|
+
return typeof value === 'boolean' ? value : false;
|
|
142
|
+
}
|
|
143
|
+
else if (schema instanceof z.ZodMap) {
|
|
144
|
+
return processMap(schema, value);
|
|
145
|
+
}
|
|
146
|
+
else if (schema instanceof z.ZodNumber) {
|
|
147
|
+
return typeof value === 'number' ? value : (schema.minValue ?? 0);
|
|
148
|
+
}
|
|
149
|
+
else if (schema instanceof z.ZodRecord) {
|
|
150
|
+
return processRecord(schema, value);
|
|
151
|
+
}
|
|
152
|
+
else if (schema instanceof z.ZodSet) {
|
|
153
|
+
return processSet(schema, value);
|
|
154
|
+
}
|
|
155
|
+
else if (schema instanceof z.ZodString) {
|
|
156
|
+
return typeof value === 'string' ? value : '';
|
|
157
|
+
}
|
|
158
|
+
else if (schema instanceof z.ZodNullable) {
|
|
159
|
+
return value === null ? null : processValue(schema.unwrap(), value);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
return value;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
const processMap = (schema, source) => {
|
|
166
|
+
if (!(source instanceof Map)) {
|
|
167
|
+
return new Map();
|
|
168
|
+
}
|
|
169
|
+
const valueSchema = schema._def.valueType;
|
|
170
|
+
const result = new Map();
|
|
171
|
+
source.forEach((value, key) => {
|
|
172
|
+
result.set(key, processValue(valueSchema, value));
|
|
173
|
+
});
|
|
174
|
+
return result;
|
|
175
|
+
};
|
|
176
|
+
const processObject = (schema, source) => {
|
|
177
|
+
const result = {};
|
|
178
|
+
const shape = schema.shape;
|
|
179
|
+
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
180
|
+
if (key in source) {
|
|
181
|
+
result[key] = processValue(fieldSchema, source[key]);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
result[key] = getDefaultValue(fieldSchema);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return result;
|
|
188
|
+
};
|
|
189
|
+
const processRecord = (schema, source) => {
|
|
190
|
+
if (typeof source !== 'object' || source === null) {
|
|
191
|
+
return {};
|
|
192
|
+
}
|
|
193
|
+
const valueSchema = schema._def.valueType;
|
|
194
|
+
const result = {};
|
|
195
|
+
for (const key in source) {
|
|
196
|
+
result[key] = processValue(valueSchema, source[key]);
|
|
197
|
+
}
|
|
198
|
+
return result;
|
|
199
|
+
};
|
|
200
|
+
const processSet = (schema, source) => {
|
|
201
|
+
if (!(source instanceof Set)) {
|
|
202
|
+
return new Set();
|
|
203
|
+
}
|
|
204
|
+
const valueSchema = schema._def.valueType;
|
|
205
|
+
const result = new Set();
|
|
206
|
+
for (const value of source) {
|
|
207
|
+
result.add(processValue(valueSchema, value));
|
|
208
|
+
}
|
|
209
|
+
return result;
|
|
210
|
+
};
|
|
211
|
+
const processUnion = (schema, source) => {
|
|
212
|
+
for (const optionSchema of schema._def.options) {
|
|
213
|
+
try {
|
|
214
|
+
const parsed = optionSchema.safeParse(source);
|
|
215
|
+
if (parsed.success) {
|
|
216
|
+
return processValue(optionSchema, source);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
// If parsing fails, try the next option
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// If no option matches, return the default value of the first option
|
|
224
|
+
return getDefaultValue(schema._def.options[0]);
|
|
225
|
+
};
|
|
226
|
+
if (schema instanceof z.ZodDiscriminatedUnion) {
|
|
227
|
+
return processDiscriminatedUnion(schema, source);
|
|
228
|
+
}
|
|
229
|
+
if (schema instanceof z.ZodEffects) {
|
|
230
|
+
schema = schema.innerType();
|
|
231
|
+
}
|
|
232
|
+
return processValue(schema, source);
|
|
233
|
+
};
|
|
234
|
+
export default defaultInstance;
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dependencies": {
|
|
3
|
+
"zod": "^3.23.8"
|
|
4
|
+
},
|
|
5
|
+
"devDependencies": {
|
|
6
|
+
"@types/lodash": "^4.17.12",
|
|
7
|
+
"@types/node": "^22.7.7",
|
|
8
|
+
"prettier": "^3.3.3",
|
|
9
|
+
"typescript": "^5.6.3",
|
|
10
|
+
"vitest": "^2.1.3"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"main": "dist/index.js",
|
|
17
|
+
"name": "use-zod-default",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/feliperohdee/use-zod-default"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "rm -rf dist && tsc -p tsconfig.json",
|
|
24
|
+
"lint": "prettier --write . && yarn tsc",
|
|
25
|
+
"npm-publish": "yarn test --run && yarn build && yarn version --patch --no-git-tag-version && yarn publish --non-interactive",
|
|
26
|
+
"test": "vitest"
|
|
27
|
+
},
|
|
28
|
+
"version": "1.0.1"
|
|
29
|
+
}
|