@zod-utils/core 0.1.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 ADDED
@@ -0,0 +1,196 @@
1
+ # @zod-utils/core
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@zod-utils/core.svg)](https://www.npmjs.com/package/@zod-utils/core)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@zod-utils/core.svg)](https://www.npmjs.com/package/@zod-utils/core)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0-blue.svg)](https://www.typescriptlang.org/)
7
+ [![CI](https://github.com/thu-san/zod-utils/workflows/CI/badge.svg)](https://github.com/thu-san/zod-utils/actions)
8
+
9
+ Pure TypeScript utilities for Zod schema manipulation and default extraction. No React dependencies.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @zod-utils/core zod
15
+ ```
16
+
17
+ ## Features
18
+
19
+ - 🎯 **Extract defaults** - Get default values from Zod schemas
20
+ - ✅ **Check required fields** - Determine if fields are required
21
+ - 🔧 **Schema utilities** - Unwrap and manipulate schema types
22
+ - 📦 **Zero dependencies** - Only requires Zod as a peer dependency
23
+ - 🌐 **Universal** - Works in Node.js, browsers, and any TypeScript project
24
+
25
+ ## API Reference
26
+
27
+ ### `getSchemaDefaults(schema)`
28
+
29
+ Extract all default values from a Zod object schema. Recursively handles nested objects.
30
+
31
+ ```typescript
32
+ import { getSchemaDefaults } from '@zod-utils/core';
33
+ import { z } from 'zod';
34
+
35
+ const schema = z.object({
36
+ name: z.string().default('John Doe'),
37
+ age: z.number().default(25),
38
+ email: z.string().email(), // no default - skipped
39
+ settings: z.object({
40
+ theme: z.string().default('light'),
41
+ notifications: z.boolean().default(true),
42
+ }),
43
+ tags: z.array(z.string()).default([]),
44
+ });
45
+
46
+ const defaults = getSchemaDefaults(schema);
47
+ // {
48
+ // name: 'John Doe',
49
+ // age: 25,
50
+ // settings: { theme: 'light', notifications: true },
51
+ // tags: []
52
+ // }
53
+ ```
54
+
55
+ **Handles:**
56
+ - Nested objects at any depth
57
+ - Optional fields with defaults: `.optional().default(value)`
58
+ - Arrays with defaults: `.array().default([])`
59
+ - Skips fields without defaults
60
+
61
+ ---
62
+
63
+ ### `checkIfFieldIsRequired(field)`
64
+
65
+ Check if a Zod field is required (not optional/nullable and doesn't accept empty values).
66
+
67
+ ```typescript
68
+ import { checkIfFieldIsRequired } from '@zod-utils/core';
69
+ import { z } from 'zod';
70
+
71
+ const requiredField = z.string();
72
+ const optionalField = z.string().optional();
73
+ const emptyStringAllowed = z.string().min(0);
74
+
75
+ checkIfFieldIsRequired(requiredField); // true
76
+ checkIfFieldIsRequired(optionalField); // false
77
+ checkIfFieldIsRequired(emptyStringAllowed); // false
78
+ ```
79
+
80
+ ---
81
+
82
+ ### `getPrimitiveType(field, options?)`
83
+
84
+ Get the primitive type of a Zod field by unwrapping optional/nullable wrappers.
85
+
86
+ ```typescript
87
+ import { getPrimitiveType } from '@zod-utils/core';
88
+ import { z } from 'zod';
89
+
90
+ const field = z.string().optional().nullable();
91
+ const primitive = getPrimitiveType(field);
92
+ // Returns the underlying string schema
93
+
94
+ // Options
95
+ getPrimitiveType(z.array(z.string()), { unwrapArrays: false }); // Stops at array
96
+ getPrimitiveType(z.array(z.string()), { unwrapArrays: true }); // Continues unwrapping
97
+ ```
98
+
99
+ ---
100
+
101
+ ### `removeDefault(field)`
102
+
103
+ Remove default values from a Zod field.
104
+
105
+ ```typescript
106
+ import { removeDefault } from '@zod-utils/core';
107
+ import { z } from 'zod';
108
+
109
+ const withDefault = z.string().default('hello');
110
+ const withoutDefault = removeDefault(withDefault);
111
+
112
+ withDefault.parse(undefined); // 'hello'
113
+ withoutDefault.parse(undefined); // throws error
114
+ ```
115
+
116
+ ---
117
+
118
+ ### `extractDefault(field)`
119
+
120
+ Extract the default value from a Zod field (recursively unwraps optional/nullable).
121
+
122
+ ```typescript
123
+ import { extractDefault } from '@zod-utils/core';
124
+ import { z } from 'zod';
125
+
126
+ const field = z.string().optional().default('hello');
127
+ extractDefault(field); // 'hello'
128
+
129
+ const noDefault = z.string();
130
+ extractDefault(noDefault); // undefined
131
+ ```
132
+
133
+ ---
134
+
135
+ ### `getUnwrappedType(field)`
136
+
137
+ Get the unwrapped type without going through defaults. Useful for detecting nested objects/arrays.
138
+
139
+ ```typescript
140
+ import { getUnwrappedType } from '@zod-utils/core';
141
+ import { z } from 'zod';
142
+
143
+ const field = z.object({ name: z.string() }).optional().default({});
144
+ const unwrapped = getUnwrappedType(field);
145
+ // Returns the ZodObject (preserves the default wrapper)
146
+ ```
147
+
148
+ ---
149
+
150
+ ## Type Utilities
151
+
152
+ ### `MakeOptionalAndNullable<T>`
153
+
154
+ Make all properties optional and nullable. Useful for form input types.
155
+
156
+ ```typescript
157
+ import type { MakeOptionalAndNullable } from '@zod-utils/core';
158
+
159
+ type User = {
160
+ name: string;
161
+ age: number;
162
+ };
163
+
164
+ type FormInput = MakeOptionalAndNullable<User>;
165
+ // { name?: string | null; age?: number | null; }
166
+ ```
167
+
168
+ ### `Simplify<T>`
169
+
170
+ Simplify complex types for better IDE hints.
171
+
172
+ ```typescript
173
+ import type { Simplify } from '@zod-utils/core';
174
+
175
+ type Complex = { a: string } & { b: number };
176
+ type Simple = Simplify<Complex>;
177
+ // { a: string; b: number }
178
+ ```
179
+
180
+ ### `PickArrayObject<T>`
181
+
182
+ Extract the element type from an array.
183
+
184
+ ```typescript
185
+ import type { PickArrayObject } from '@zod-utils/core';
186
+
187
+ type Users = Array<{ name: string }>;
188
+ type User = PickArrayObject<Users>;
189
+ // { name: string }
190
+ ```
191
+
192
+ ---
193
+
194
+ ## License
195
+
196
+ MIT
@@ -0,0 +1,79 @@
1
+ import * as z from 'zod';
2
+
3
+ /**
4
+ * Get the primitive type of a Zod field by unwrapping optional/nullable wrappers
5
+ * @param field - The Zod field to unwrap
6
+ * @param options - Options for unwrapping
7
+ * @param options.unwrapArrays - If true, continues unwrapping arrays. If false (default), stops at arrays
8
+ * @returns The unwrapped primitive type
9
+ */
10
+ declare const getPrimitiveType: <T extends z.ZodTypeAny>(field: T, options?: {
11
+ unwrapArrays?: boolean;
12
+ }) => z.ZodTypeAny;
13
+ /**
14
+ * Remove default values from a Zod field
15
+ * @param field - The Zod field to remove defaults from
16
+ * @returns The field without defaults
17
+ */
18
+ declare function removeDefault(field: z.ZodType): z.ZodType;
19
+ /**
20
+ * Check if a Zod field is required (not optional/nullable and doesn't accept empty values)
21
+ * @param field - The Zod field to check
22
+ * @returns True if the field is required
23
+ */
24
+ declare const checkIfFieldIsRequired: <T extends z.ZodTypeAny>(field: T) => boolean;
25
+
26
+ /**
27
+ * Extract the default value from a Zod field (recursively unwraps optional/nullable)
28
+ * @param field - The Zod field to extract default from
29
+ * @returns The default value if present, undefined otherwise
30
+ */
31
+ declare function extractDefault(field: z.ZodTypeAny): any;
32
+ /**
33
+ * Get the unwrapped type without going through defaults
34
+ * Useful for detecting nested objects/arrays while preserving defaults
35
+ * @param field - The Zod field to unwrap
36
+ * @returns The unwrapped type
37
+ */
38
+ declare function getUnwrappedType(field: z.ZodTypeAny): z.ZodTypeAny;
39
+ /**
40
+ * Extract all default values from a Zod object schema
41
+ * Recursively handles nested objects and only returns fields with defaults
42
+ * @param schema - The Zod object schema to extract defaults from
43
+ * @returns Partial object with only fields that have defaults
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * const schema = z.object({
48
+ * name: z.string().default('John'),
49
+ * age: z.number(), // no default - skipped
50
+ * settings: z.object({
51
+ * theme: z.string().default('light')
52
+ * })
53
+ * });
54
+ *
55
+ * getSchemaDefaults(schema);
56
+ * // Returns: { name: 'John', settings: { theme: 'light' } }
57
+ * ```
58
+ */
59
+ declare function getSchemaDefaults<T extends z.ZodObject<any>>(schema: T): Partial<z.infer<T>>;
60
+
61
+ /**
62
+ * Extract the element type from an array or undefined
63
+ */
64
+ type PickArrayObject<TArray extends unknown[] | undefined> = NonNullable<TArray>[number];
65
+ /**
66
+ * Simplify complex types for better IDE hints
67
+ */
68
+ type Simplify<T> = {
69
+ [K in keyof T]: T[K];
70
+ } & {};
71
+ /**
72
+ * Make all properties optional and nullable
73
+ * Useful for form input types where fields can be empty
74
+ */
75
+ type MakeOptionalAndNullable<T> = {
76
+ [K in keyof T]?: T[K] | null;
77
+ };
78
+
79
+ export { type MakeOptionalAndNullable, type PickArrayObject, type Simplify, checkIfFieldIsRequired, extractDefault, getPrimitiveType, getSchemaDefaults, getUnwrappedType, removeDefault };
@@ -0,0 +1,79 @@
1
+ import * as z from 'zod';
2
+
3
+ /**
4
+ * Get the primitive type of a Zod field by unwrapping optional/nullable wrappers
5
+ * @param field - The Zod field to unwrap
6
+ * @param options - Options for unwrapping
7
+ * @param options.unwrapArrays - If true, continues unwrapping arrays. If false (default), stops at arrays
8
+ * @returns The unwrapped primitive type
9
+ */
10
+ declare const getPrimitiveType: <T extends z.ZodTypeAny>(field: T, options?: {
11
+ unwrapArrays?: boolean;
12
+ }) => z.ZodTypeAny;
13
+ /**
14
+ * Remove default values from a Zod field
15
+ * @param field - The Zod field to remove defaults from
16
+ * @returns The field without defaults
17
+ */
18
+ declare function removeDefault(field: z.ZodType): z.ZodType;
19
+ /**
20
+ * Check if a Zod field is required (not optional/nullable and doesn't accept empty values)
21
+ * @param field - The Zod field to check
22
+ * @returns True if the field is required
23
+ */
24
+ declare const checkIfFieldIsRequired: <T extends z.ZodTypeAny>(field: T) => boolean;
25
+
26
+ /**
27
+ * Extract the default value from a Zod field (recursively unwraps optional/nullable)
28
+ * @param field - The Zod field to extract default from
29
+ * @returns The default value if present, undefined otherwise
30
+ */
31
+ declare function extractDefault(field: z.ZodTypeAny): any;
32
+ /**
33
+ * Get the unwrapped type without going through defaults
34
+ * Useful for detecting nested objects/arrays while preserving defaults
35
+ * @param field - The Zod field to unwrap
36
+ * @returns The unwrapped type
37
+ */
38
+ declare function getUnwrappedType(field: z.ZodTypeAny): z.ZodTypeAny;
39
+ /**
40
+ * Extract all default values from a Zod object schema
41
+ * Recursively handles nested objects and only returns fields with defaults
42
+ * @param schema - The Zod object schema to extract defaults from
43
+ * @returns Partial object with only fields that have defaults
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * const schema = z.object({
48
+ * name: z.string().default('John'),
49
+ * age: z.number(), // no default - skipped
50
+ * settings: z.object({
51
+ * theme: z.string().default('light')
52
+ * })
53
+ * });
54
+ *
55
+ * getSchemaDefaults(schema);
56
+ * // Returns: { name: 'John', settings: { theme: 'light' } }
57
+ * ```
58
+ */
59
+ declare function getSchemaDefaults<T extends z.ZodObject<any>>(schema: T): Partial<z.infer<T>>;
60
+
61
+ /**
62
+ * Extract the element type from an array or undefined
63
+ */
64
+ type PickArrayObject<TArray extends unknown[] | undefined> = NonNullable<TArray>[number];
65
+ /**
66
+ * Simplify complex types for better IDE hints
67
+ */
68
+ type Simplify<T> = {
69
+ [K in keyof T]: T[K];
70
+ } & {};
71
+ /**
72
+ * Make all properties optional and nullable
73
+ * Useful for form input types where fields can be empty
74
+ */
75
+ type MakeOptionalAndNullable<T> = {
76
+ [K in keyof T]?: T[K] | null;
77
+ };
78
+
79
+ export { type MakeOptionalAndNullable, type PickArrayObject, type Simplify, checkIfFieldIsRequired, extractDefault, getPrimitiveType, getSchemaDefaults, getUnwrappedType, removeDefault };
package/dist/index.js ADDED
@@ -0,0 +1,106 @@
1
+ 'use strict';
2
+
3
+ var z = require('zod');
4
+
5
+ function _interopNamespace(e) {
6
+ if (e && e.__esModule) return e;
7
+ var n = Object.create(null);
8
+ if (e) {
9
+ Object.keys(e).forEach(function (k) {
10
+ if (k !== 'default') {
11
+ var d = Object.getOwnPropertyDescriptor(e, k);
12
+ Object.defineProperty(n, k, d.get ? d : {
13
+ enumerable: true,
14
+ get: function () { return e[k]; }
15
+ });
16
+ }
17
+ });
18
+ }
19
+ n.default = e;
20
+ return Object.freeze(n);
21
+ }
22
+
23
+ var z__namespace = /*#__PURE__*/_interopNamespace(z);
24
+
25
+ // src/schema.ts
26
+ var getPrimitiveType = (field, options) => {
27
+ var _a;
28
+ const unwrapArrays = (_a = options == null ? void 0 : options.unwrapArrays) != null ? _a : false;
29
+ if (!unwrapArrays && field.type === "array") {
30
+ return field;
31
+ }
32
+ if ("unwrap" in field && typeof field.unwrap === "function") {
33
+ return getPrimitiveType(field.unwrap(), options);
34
+ }
35
+ return field;
36
+ };
37
+ function removeDefault(field) {
38
+ if (field instanceof z__namespace.ZodDefault) {
39
+ return field.unwrap();
40
+ }
41
+ if ("innerType" in field.def) {
42
+ const inner = removeDefault(field.def.innerType);
43
+ if (field instanceof z__namespace.ZodOptional) {
44
+ return inner.optional();
45
+ }
46
+ if (field instanceof z__namespace.ZodNullable) {
47
+ return inner.nullable();
48
+ }
49
+ }
50
+ return field;
51
+ }
52
+ var checkIfFieldIsRequired = (field) => {
53
+ const undefinedResult = field.safeParse(void 0).success;
54
+ const nullResult = field.safeParse(null).success;
55
+ const primitiveType = getPrimitiveType(field);
56
+ const emptyStringResult = primitiveType.type === "string" && field.safeParse("").success;
57
+ const emptyArrayResult = primitiveType.type === "array" && field.safeParse([]).success;
58
+ return !undefinedResult && !nullResult && !emptyStringResult && !emptyArrayResult;
59
+ };
60
+ function extractDefault(field) {
61
+ if (field instanceof z__namespace.ZodDefault) {
62
+ const defaultValue = field._def.defaultValue;
63
+ return typeof defaultValue === "function" ? defaultValue() : defaultValue;
64
+ }
65
+ if ("unwrap" in field && typeof field.unwrap === "function") {
66
+ return extractDefault(field.unwrap());
67
+ }
68
+ return void 0;
69
+ }
70
+ function getUnwrappedType(field) {
71
+ if (field instanceof z__namespace.ZodDefault) {
72
+ return field;
73
+ }
74
+ if ("unwrap" in field && typeof field.unwrap === "function") {
75
+ return getUnwrappedType(field.unwrap());
76
+ }
77
+ return field;
78
+ }
79
+ function getSchemaDefaults(schema) {
80
+ const defaults = {};
81
+ for (const key in schema.shape) {
82
+ const field = schema.shape[key];
83
+ const defaultValue = extractDefault(field);
84
+ if (defaultValue !== void 0) {
85
+ defaults[key] = defaultValue;
86
+ continue;
87
+ }
88
+ const unwrapped = getUnwrappedType(field);
89
+ if (unwrapped instanceof z__namespace.ZodObject) {
90
+ const nestedDefaults = getSchemaDefaults(unwrapped);
91
+ if (Object.keys(nestedDefaults).length > 0) {
92
+ defaults[key] = nestedDefaults;
93
+ }
94
+ }
95
+ }
96
+ return defaults;
97
+ }
98
+
99
+ exports.checkIfFieldIsRequired = checkIfFieldIsRequired;
100
+ exports.extractDefault = extractDefault;
101
+ exports.getPrimitiveType = getPrimitiveType;
102
+ exports.getSchemaDefaults = getSchemaDefaults;
103
+ exports.getUnwrappedType = getUnwrappedType;
104
+ exports.removeDefault = removeDefault;
105
+ //# sourceMappingURL=index.js.map
106
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schema.ts","../src/defaults.ts"],"names":["z","z2"],"mappings":"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","file":"index.js","sourcesContent":["import * as z from 'zod';\n\n/**\n * Get the primitive type of a Zod field by unwrapping optional/nullable wrappers\n * @param field - The Zod field to unwrap\n * @param options - Options for unwrapping\n * @param options.unwrapArrays - If true, continues unwrapping arrays. If false (default), stops at arrays\n * @returns The unwrapped primitive type\n */\nexport const getPrimitiveType = <T extends z.ZodTypeAny>(\n field: T,\n options?: {\n unwrapArrays?: boolean;\n },\n): z.ZodTypeAny => {\n const unwrapArrays = options?.unwrapArrays ?? false;\n\n if (!unwrapArrays && field.type === 'array') {\n return field;\n }\n\n if ('unwrap' in field && typeof field.unwrap === 'function') {\n return getPrimitiveType(field.unwrap(), options);\n }\n\n return field;\n};\n\n/**\n * Remove default values from a Zod field\n * @param field - The Zod field to remove defaults from\n * @returns The field without defaults\n */\nexport function removeDefault(field: z.ZodType): z.ZodType {\n if (field instanceof z.ZodDefault) {\n return field.unwrap() as z.ZodType;\n }\n\n if ('innerType' in field.def) {\n const inner = removeDefault(field.def.innerType as z.ZodType);\n // Reconstruct the wrapper with the modified inner type\n if (field instanceof z.ZodOptional) {\n return inner.optional();\n }\n if (field instanceof z.ZodNullable) {\n return inner.nullable();\n }\n }\n\n return field;\n}\n\n/**\n * Check if a Zod field is required (not optional/nullable and doesn't accept empty values)\n * @param field - The Zod field to check\n * @returns True if the field is required\n */\nexport const checkIfFieldIsRequired = <T extends z.ZodTypeAny>(field: T) => {\n // Check with defaults intact - if a field has a default, it's not required\n const undefinedResult = field.safeParse(undefined).success;\n const nullResult = field.safeParse(null).success;\n\n const primitiveType = getPrimitiveType(field);\n\n const emptyStringResult =\n primitiveType.type === 'string' && field.safeParse('').success;\n\n const emptyArrayResult =\n primitiveType.type === 'array' && field.safeParse([]).success;\n\n return (\n !undefinedResult && !nullResult && !emptyStringResult && !emptyArrayResult\n );\n};\n","import * as z from 'zod';\n\n/**\n * Extract the default value from a Zod field (recursively unwraps optional/nullable)\n * @param field - The Zod field to extract default from\n * @returns The default value if present, undefined otherwise\n */\nexport function extractDefault(field: z.ZodTypeAny): any {\n if (field instanceof z.ZodDefault) {\n const defaultValue = field._def.defaultValue;\n return typeof defaultValue === 'function' ? defaultValue() : defaultValue;\n }\n\n if ('unwrap' in field && typeof field.unwrap === 'function') {\n return extractDefault(field.unwrap());\n }\n\n return undefined;\n}\n\n/**\n * Get the unwrapped type without going through defaults\n * Useful for detecting nested objects/arrays while preserving defaults\n * @param field - The Zod field to unwrap\n * @returns The unwrapped type\n */\nexport function getUnwrappedType(field: z.ZodTypeAny): z.ZodTypeAny {\n if (field instanceof z.ZodDefault) {\n // Don't unwrap defaults - we want to preserve them\n return field;\n }\n\n if ('unwrap' in field && typeof field.unwrap === 'function') {\n return getUnwrappedType(field.unwrap());\n }\n\n return field;\n}\n\n/**\n * Extract all default values from a Zod object schema\n * Recursively handles nested objects and only returns fields with defaults\n * @param schema - The Zod object schema to extract defaults from\n * @returns Partial object with only fields that have defaults\n *\n * @example\n * ```ts\n * const schema = z.object({\n * name: z.string().default('John'),\n * age: z.number(), // no default - skipped\n * settings: z.object({\n * theme: z.string().default('light')\n * })\n * });\n *\n * getSchemaDefaults(schema);\n * // Returns: { name: 'John', settings: { theme: 'light' } }\n * ```\n */\nexport function getSchemaDefaults<T extends z.ZodObject<any>>(\n schema: T,\n): Partial<z.infer<T>> {\n const defaults: Record<string, any> = {};\n\n for (const key in schema.shape) {\n const field = schema.shape[key];\n\n // First, check if this field has an explicit default value\n const defaultValue = extractDefault(field);\n if (defaultValue !== undefined) {\n defaults[key] = defaultValue;\n continue;\n }\n\n // If no explicit default, check if it's a nested object with defaults\n const unwrapped = getUnwrappedType(field);\n if (unwrapped instanceof z.ZodObject) {\n const nestedDefaults = getSchemaDefaults(unwrapped);\n if (Object.keys(nestedDefaults).length > 0) {\n defaults[key] = nestedDefaults;\n }\n }\n }\n\n return defaults as Partial<z.infer<T>>;\n}\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,79 @@
1
+ import * as z from 'zod';
2
+
3
+ // src/schema.ts
4
+ var getPrimitiveType = (field, options) => {
5
+ var _a;
6
+ const unwrapArrays = (_a = options == null ? void 0 : options.unwrapArrays) != null ? _a : false;
7
+ if (!unwrapArrays && field.type === "array") {
8
+ return field;
9
+ }
10
+ if ("unwrap" in field && typeof field.unwrap === "function") {
11
+ return getPrimitiveType(field.unwrap(), options);
12
+ }
13
+ return field;
14
+ };
15
+ function removeDefault(field) {
16
+ if (field instanceof z.ZodDefault) {
17
+ return field.unwrap();
18
+ }
19
+ if ("innerType" in field.def) {
20
+ const inner = removeDefault(field.def.innerType);
21
+ if (field instanceof z.ZodOptional) {
22
+ return inner.optional();
23
+ }
24
+ if (field instanceof z.ZodNullable) {
25
+ return inner.nullable();
26
+ }
27
+ }
28
+ return field;
29
+ }
30
+ var checkIfFieldIsRequired = (field) => {
31
+ const undefinedResult = field.safeParse(void 0).success;
32
+ const nullResult = field.safeParse(null).success;
33
+ const primitiveType = getPrimitiveType(field);
34
+ const emptyStringResult = primitiveType.type === "string" && field.safeParse("").success;
35
+ const emptyArrayResult = primitiveType.type === "array" && field.safeParse([]).success;
36
+ return !undefinedResult && !nullResult && !emptyStringResult && !emptyArrayResult;
37
+ };
38
+ function extractDefault(field) {
39
+ if (field instanceof z.ZodDefault) {
40
+ const defaultValue = field._def.defaultValue;
41
+ return typeof defaultValue === "function" ? defaultValue() : defaultValue;
42
+ }
43
+ if ("unwrap" in field && typeof field.unwrap === "function") {
44
+ return extractDefault(field.unwrap());
45
+ }
46
+ return void 0;
47
+ }
48
+ function getUnwrappedType(field) {
49
+ if (field instanceof z.ZodDefault) {
50
+ return field;
51
+ }
52
+ if ("unwrap" in field && typeof field.unwrap === "function") {
53
+ return getUnwrappedType(field.unwrap());
54
+ }
55
+ return field;
56
+ }
57
+ function getSchemaDefaults(schema) {
58
+ const defaults = {};
59
+ for (const key in schema.shape) {
60
+ const field = schema.shape[key];
61
+ const defaultValue = extractDefault(field);
62
+ if (defaultValue !== void 0) {
63
+ defaults[key] = defaultValue;
64
+ continue;
65
+ }
66
+ const unwrapped = getUnwrappedType(field);
67
+ if (unwrapped instanceof z.ZodObject) {
68
+ const nestedDefaults = getSchemaDefaults(unwrapped);
69
+ if (Object.keys(nestedDefaults).length > 0) {
70
+ defaults[key] = nestedDefaults;
71
+ }
72
+ }
73
+ }
74
+ return defaults;
75
+ }
76
+
77
+ export { checkIfFieldIsRequired, extractDefault, getPrimitiveType, getSchemaDefaults, getUnwrappedType, removeDefault };
78
+ //# sourceMappingURL=index.mjs.map
79
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schema.ts","../src/defaults.ts"],"names":["z2"],"mappings":"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","file":"index.mjs","sourcesContent":["import * as z from 'zod';\n\n/**\n * Get the primitive type of a Zod field by unwrapping optional/nullable wrappers\n * @param field - The Zod field to unwrap\n * @param options - Options for unwrapping\n * @param options.unwrapArrays - If true, continues unwrapping arrays. If false (default), stops at arrays\n * @returns The unwrapped primitive type\n */\nexport const getPrimitiveType = <T extends z.ZodTypeAny>(\n field: T,\n options?: {\n unwrapArrays?: boolean;\n },\n): z.ZodTypeAny => {\n const unwrapArrays = options?.unwrapArrays ?? false;\n\n if (!unwrapArrays && field.type === 'array') {\n return field;\n }\n\n if ('unwrap' in field && typeof field.unwrap === 'function') {\n return getPrimitiveType(field.unwrap(), options);\n }\n\n return field;\n};\n\n/**\n * Remove default values from a Zod field\n * @param field - The Zod field to remove defaults from\n * @returns The field without defaults\n */\nexport function removeDefault(field: z.ZodType): z.ZodType {\n if (field instanceof z.ZodDefault) {\n return field.unwrap() as z.ZodType;\n }\n\n if ('innerType' in field.def) {\n const inner = removeDefault(field.def.innerType as z.ZodType);\n // Reconstruct the wrapper with the modified inner type\n if (field instanceof z.ZodOptional) {\n return inner.optional();\n }\n if (field instanceof z.ZodNullable) {\n return inner.nullable();\n }\n }\n\n return field;\n}\n\n/**\n * Check if a Zod field is required (not optional/nullable and doesn't accept empty values)\n * @param field - The Zod field to check\n * @returns True if the field is required\n */\nexport const checkIfFieldIsRequired = <T extends z.ZodTypeAny>(field: T) => {\n // Check with defaults intact - if a field has a default, it's not required\n const undefinedResult = field.safeParse(undefined).success;\n const nullResult = field.safeParse(null).success;\n\n const primitiveType = getPrimitiveType(field);\n\n const emptyStringResult =\n primitiveType.type === 'string' && field.safeParse('').success;\n\n const emptyArrayResult =\n primitiveType.type === 'array' && field.safeParse([]).success;\n\n return (\n !undefinedResult && !nullResult && !emptyStringResult && !emptyArrayResult\n );\n};\n","import * as z from 'zod';\n\n/**\n * Extract the default value from a Zod field (recursively unwraps optional/nullable)\n * @param field - The Zod field to extract default from\n * @returns The default value if present, undefined otherwise\n */\nexport function extractDefault(field: z.ZodTypeAny): any {\n if (field instanceof z.ZodDefault) {\n const defaultValue = field._def.defaultValue;\n return typeof defaultValue === 'function' ? defaultValue() : defaultValue;\n }\n\n if ('unwrap' in field && typeof field.unwrap === 'function') {\n return extractDefault(field.unwrap());\n }\n\n return undefined;\n}\n\n/**\n * Get the unwrapped type without going through defaults\n * Useful for detecting nested objects/arrays while preserving defaults\n * @param field - The Zod field to unwrap\n * @returns The unwrapped type\n */\nexport function getUnwrappedType(field: z.ZodTypeAny): z.ZodTypeAny {\n if (field instanceof z.ZodDefault) {\n // Don't unwrap defaults - we want to preserve them\n return field;\n }\n\n if ('unwrap' in field && typeof field.unwrap === 'function') {\n return getUnwrappedType(field.unwrap());\n }\n\n return field;\n}\n\n/**\n * Extract all default values from a Zod object schema\n * Recursively handles nested objects and only returns fields with defaults\n * @param schema - The Zod object schema to extract defaults from\n * @returns Partial object with only fields that have defaults\n *\n * @example\n * ```ts\n * const schema = z.object({\n * name: z.string().default('John'),\n * age: z.number(), // no default - skipped\n * settings: z.object({\n * theme: z.string().default('light')\n * })\n * });\n *\n * getSchemaDefaults(schema);\n * // Returns: { name: 'John', settings: { theme: 'light' } }\n * ```\n */\nexport function getSchemaDefaults<T extends z.ZodObject<any>>(\n schema: T,\n): Partial<z.infer<T>> {\n const defaults: Record<string, any> = {};\n\n for (const key in schema.shape) {\n const field = schema.shape[key];\n\n // First, check if this field has an explicit default value\n const defaultValue = extractDefault(field);\n if (defaultValue !== undefined) {\n defaults[key] = defaultValue;\n continue;\n }\n\n // If no explicit default, check if it's a nested object with defaults\n const unwrapped = getUnwrappedType(field);\n if (unwrapped instanceof z.ZodObject) {\n const nestedDefaults = getSchemaDefaults(unwrapped);\n if (Object.keys(nestedDefaults).length > 0) {\n defaults[key] = nestedDefaults;\n }\n }\n }\n\n return defaults as Partial<z.infer<T>>;\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@zod-utils/core",
3
+ "version": "0.1.0",
4
+ "description": "Pure TypeScript utilities for Zod schema manipulation and default extraction",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": ["dist", "README.md"],
16
+ "scripts": {
17
+ "build": "tsup",
18
+ "dev": "tsup --watch",
19
+ "type-check": "tsc --noEmit",
20
+ "test": "vitest run",
21
+ "test:watch": "vitest",
22
+ "test:coverage": "vitest run --coverage",
23
+ "prepublishOnly": "npm run build"
24
+ },
25
+ "keywords": [
26
+ "zod",
27
+ "schema",
28
+ "validation",
29
+ "typescript",
30
+ "defaults",
31
+ "utilities"
32
+ ],
33
+ "author": "thu-san",
34
+ "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/thu-san/zod-utils.git",
38
+ "directory": "packages/core"
39
+ },
40
+ "bugs": {
41
+ "url": "https://github.com/thu-san/zod-utils/issues"
42
+ },
43
+ "homepage": "https://github.com/thu-san/zod-utils/tree/main/packages/core#readme",
44
+ "publishConfig": {
45
+ "access": "public"
46
+ },
47
+ "peerDependencies": {
48
+ "zod": "^4.0.0"
49
+ },
50
+ "devDependencies": {
51
+ "@vitest/coverage-v8": "^2.1.0",
52
+ "tsup": "^8.3.5",
53
+ "typescript": "^5",
54
+ "vitest": "^2.1.0",
55
+ "zod": "^4.1.12"
56
+ }
57
+ }