@zod-utils/core 0.1.0 → 0.2.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/dist/index.d.ts CHANGED
@@ -1,79 +1,314 @@
1
1
  import * as z from 'zod';
2
2
 
3
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
4
+ * Simplifies complex TypeScript types for better IDE hover tooltips and error messages.
5
+ *
6
+ * This utility type flattens intersections and complex type expressions into a single,
7
+ * readable object type. This is especially useful when working with mapped types,
8
+ * conditional types, or type intersections that produce hard-to-read IDE hints.
9
+ *
10
+ * @template T - The type to simplify
11
+ *
12
+ * @example
13
+ * Simplifying intersection types
14
+ * ```typescript
15
+ * type A = { name: string };
16
+ * type B = { age: number };
17
+ * type C = A & B; // Shows as "A & B" in IDE
18
+ * type D = Simplify<A & B>; // Shows as "{ name: string; age: number }" in IDE
19
+ * ```
20
+ *
21
+ * @example
22
+ * Simplifying Partial<> results
23
+ * ```typescript
24
+ * type User = { name: string; age: number; email: string };
25
+ * type PartialUser = Partial<User>; // Shows as "Partial<User>" in IDE
26
+ * type SimplifiedPartialUser = Simplify<Partial<User>>;
27
+ * // Shows as "{ name?: string; age?: number; email?: string }" in IDE
28
+ * ```
29
+ *
30
+ * @example
31
+ * Usage with zod schema inference
32
+ * ```typescript
33
+ * const schema = z.object({ id: z.string() })
34
+ * .merge(z.object({ name: z.string() }));
35
+ *
36
+ * type InferredType = z.infer<typeof schema>; // May show complex type
37
+ * type SimplifiedType = Simplify<z.infer<typeof schema>>;
38
+ * // Shows clear: { id: string; name: string }
39
+ * ```
40
+ *
41
+ * @since 0.1.0
23
42
  */
24
- declare const checkIfFieldIsRequired: <T extends z.ZodTypeAny>(field: T) => boolean;
43
+ type Simplify<T> = {
44
+ [K in keyof T]: T[K];
45
+ } & {};
25
46
 
26
47
  /**
27
- * Extract the default value from a Zod field (recursively unwraps optional/nullable)
48
+ * Extracts the default value from a Zod field, recursively unwrapping optional and nullable layers.
49
+ *
50
+ * This function traverses through wrapper types (like `ZodOptional`, `ZodNullable`) to find
51
+ * the underlying `ZodDefault` and returns its default value. If no default is found, returns `undefined`.
52
+ *
53
+ * @template T - The Zod type to extract default from
28
54
  * @param field - The Zod field to extract default from
29
55
  * @returns The default value if present, undefined otherwise
56
+ *
57
+ * @example
58
+ * Basic usage with default value
59
+ * ```typescript
60
+ * const field = z.string().default('hello');
61
+ * const defaultValue = extractDefault(field);
62
+ * // Result: 'hello'
63
+ * ```
64
+ *
65
+ * @example
66
+ * Unwrapping optional/nullable layers
67
+ * ```typescript
68
+ * const field = z.string().default('world').optional();
69
+ * const defaultValue = extractDefault(field);
70
+ * // Result: 'world' (unwraps optional to find default)
71
+ * ```
72
+ *
73
+ * @example
74
+ * Field without default
75
+ * ```typescript
76
+ * const field = z.string().optional();
77
+ * const defaultValue = extractDefault(field);
78
+ * // Result: undefined
79
+ * ```
80
+ *
81
+ * @see {@link getSchemaDefaults} for extracting defaults from entire schemas
82
+ * @since 0.1.0
30
83
  */
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;
84
+ declare function extractDefault<T extends z.ZodTypeAny>(field: T): z.infer<T> | undefined;
39
85
  /**
40
- * Extract all default values from a Zod object schema
41
- * Recursively handles nested objects and only returns fields with defaults
86
+ * Extracts default values from a Zod object schema while skipping fields without defaults.
87
+ *
88
+ * This function recursively traverses the schema and collects all fields that have
89
+ * explicit default values defined. Fields without defaults are excluded from the result.
90
+ *
91
+ * **Important:** Nested defaults are NOT extracted unless the parent object also has
92
+ * an explicit `.default()`. This is by design to match Zod's default value behavior.
93
+ *
94
+ * @template T - The Zod object schema type
42
95
  * @param schema - The Zod object schema to extract defaults from
43
- * @returns Partial object with only fields that have defaults
96
+ * @returns A partial object containing only fields with default values
44
97
  *
45
98
  * @example
46
- * ```ts
99
+ * Basic usage
100
+ * ```typescript
47
101
  * const schema = z.object({
48
102
  * name: z.string().default('John'),
49
- * age: z.number(), // no default - skipped
103
+ * age: z.number(), // no default - will be skipped
104
+ * email: z.string().email().optional(),
105
+ * });
106
+ *
107
+ * const defaults = getSchemaDefaults(schema);
108
+ * // Result: { name: 'John' }
109
+ * ```
110
+ *
111
+ * @example
112
+ * Nested objects with defaults
113
+ * ```typescript
114
+ * const schema = z.object({
115
+ * user: z.object({
116
+ * name: z.string().default('Guest')
117
+ * }).default({ name: 'Guest' }), // ✅ Extracted because parent has .default()
118
+ *
50
119
  * settings: z.object({
51
120
  * theme: z.string().default('light')
52
- * })
121
+ * }), // ❌ NOT extracted - parent has no .default()
53
122
  * });
54
123
  *
55
- * getSchemaDefaults(schema);
56
- * // Returns: { name: 'John', settings: { theme: 'light' } }
124
+ * const defaults = getSchemaDefaults(schema);
125
+ * // Result: { user: { name: 'Guest' } }
57
126
  * ```
127
+ *
128
+ * @example
129
+ * Unwrapping optional/nullable fields
130
+ * ```typescript
131
+ * const schema = z.object({
132
+ * title: z.string().default('Untitled').optional(),
133
+ * count: z.number().default(0).nullable(),
134
+ * });
135
+ *
136
+ * const defaults = getSchemaDefaults(schema);
137
+ * // Result: { title: 'Untitled', count: 0 }
138
+ * ```
139
+ *
140
+ * @see {@link extractDefault} for extracting defaults from individual fields
141
+ * @since 0.1.0
58
142
  */
59
- declare function getSchemaDefaults<T extends z.ZodObject<any>>(schema: T): Partial<z.infer<T>>;
143
+ declare function getSchemaDefaults<T extends z.ZodObject>(schema: T): Simplify<Partial<z.infer<T>>>;
60
144
 
61
145
  /**
62
- * Extract the element type from an array or undefined
146
+ * Type representing a Zod type that has an unwrap method
147
+ */
148
+ type Unwrappable = {
149
+ unwrap: () => z.ZodTypeAny;
150
+ };
151
+ /**
152
+ * Type guard to check if a Zod field can be unwrapped (has wrapper types like optional, nullable, default).
153
+ *
154
+ * This checks whether a Zod type has an `unwrap()` method, which is present on wrapper types
155
+ * like `ZodOptional`, `ZodNullable`, `ZodDefault`, and others.
156
+ *
157
+ * @param field - The Zod field to check
158
+ * @returns True if the field has an unwrap method, false otherwise
159
+ *
160
+ * @example
161
+ * ```typescript
162
+ * const optionalField = z.string().optional();
163
+ * console.log(canUnwrap(optionalField)); // true
164
+ *
165
+ * const plainField = z.string();
166
+ * console.log(canUnwrap(plainField)); // false
167
+ * ```
168
+ *
169
+ * @since 0.1.0
170
+ */
171
+ declare function canUnwrap(field: z.ZodTypeAny): field is z.ZodTypeAny & Unwrappable;
172
+ /**
173
+ * Gets the underlying primitive type of a Zod field by recursively unwrapping wrapper types.
174
+ *
175
+ * This function removes wrapper layers (optional, nullable, default) to reveal the base type.
176
+ * **Important:** It stops at array types without unwrapping them, treating arrays as primitives.
177
+ *
178
+ * @template T - The Zod type to unwrap
179
+ * @param field - The Zod field to unwrap
180
+ * @returns The unwrapped primitive Zod type
181
+ *
182
+ * @example
183
+ * Unwrapping to string primitive
184
+ * ```typescript
185
+ * const field = z.string().optional().nullable();
186
+ * const primitive = getPrimitiveType(field);
187
+ * // Result: z.string() (unwrapped all wrappers)
188
+ * ```
189
+ *
190
+ * @example
191
+ * Stopping at array type
192
+ * ```typescript
193
+ * const field = z.array(z.string()).optional();
194
+ * const primitive = getPrimitiveType(field);
195
+ * // Result: z.array(z.string()) (stops at array, doesn't unwrap it)
196
+ * ```
197
+ *
198
+ * @example
199
+ * Unwrapping defaults
200
+ * ```typescript
201
+ * const field = z.number().default(0).optional();
202
+ * const primitive = getPrimitiveType(field);
203
+ * // Result: z.number()
204
+ * ```
205
+ *
206
+ * @see {@link canUnwrap} for checking if a field can be unwrapped
207
+ * @since 0.1.0
63
208
  */
64
- type PickArrayObject<TArray extends unknown[] | undefined> = NonNullable<TArray>[number];
209
+ declare const getPrimitiveType: <T extends z.ZodTypeAny>(field: T) => z.ZodTypeAny;
210
+ type StripZodDefault<T> = T extends z.ZodDefault<infer Inner> ? StripZodDefault<Inner> : T extends z.ZodOptional<infer Inner> ? z.ZodOptional<StripZodDefault<Inner>> : T extends z.ZodNullable<infer Inner> ? z.ZodNullable<StripZodDefault<Inner>> : T;
65
211
  /**
66
- * Simplify complex types for better IDE hints
212
+ * Removes default values from a Zod field while preserving other wrapper types.
213
+ *
214
+ * This function recursively removes `ZodDefault` wrappers from a field, while maintaining
215
+ * `optional()` and `nullable()` wrappers. Useful for scenarios where you want to check
216
+ * field requirements without considering default values.
217
+ *
218
+ * @template T - The Zod type to process
219
+ * @param field - The Zod field to remove defaults from
220
+ * @returns The field without defaults but with optional/nullable preserved
221
+ *
222
+ * @example
223
+ * Removing simple default
224
+ * ```typescript
225
+ * const field = z.string().default('hello');
226
+ * const withoutDefault = removeDefault(field);
227
+ * // Result: z.string()
228
+ * ```
229
+ *
230
+ * @example
231
+ * Preserving optional wrapper
232
+ * ```typescript
233
+ * const field = z.string().default('hello').optional();
234
+ * const withoutDefault = removeDefault(field);
235
+ * // Result: z.string().optional()
236
+ * ```
237
+ *
238
+ * @example
239
+ * Nested defaults
240
+ * ```typescript
241
+ * const field = z.string().default('inner').nullable().default('outer');
242
+ * const withoutDefault = removeDefault(field);
243
+ * // Result: z.string().nullable()
244
+ * ```
245
+ *
246
+ * @see {@link checkIfFieldIsRequired} for usage with requirement checking
247
+ * @since 0.1.0
67
248
  */
68
- type Simplify<T> = {
69
- [K in keyof T]: T[K];
70
- } & {};
249
+ declare function removeDefault<T extends z.ZodType>(field: T): StripZodDefault<T>;
71
250
  /**
72
- * Make all properties optional and nullable
73
- * Useful for form input types where fields can be empty
251
+ * Checks if a Zod field is truly required by testing multiple acceptance criteria.
252
+ *
253
+ * A field is considered **not required** if it accepts any of the following:
254
+ * - `undefined` (via `.optional()` or `.default()`)
255
+ * - `null` (via `.nullable()`)
256
+ * - Empty string (plain `z.string()` without `.min(1)` or `.nonempty()`)
257
+ * - Empty array (plain `z.array()` without `.min(1)` or `.nonempty()`)
258
+ *
259
+ * **Note:** Fields with `.default()` are considered not required since they'll have a value
260
+ * even if the user doesn't provide one.
261
+ *
262
+ * @template T - The Zod type to check
263
+ * @param field - The Zod field to check for required status
264
+ * @returns True if the field is required, false otherwise
265
+ *
266
+ * @example
267
+ * Required field
268
+ * ```typescript
269
+ * const field = z.string().min(1);
270
+ * console.log(checkIfFieldIsRequired(field)); // true
271
+ * ```
272
+ *
273
+ * @example
274
+ * Optional field (not required)
275
+ * ```typescript
276
+ * const field = z.string().optional();
277
+ * console.log(checkIfFieldIsRequired(field)); // false
278
+ * ```
279
+ *
280
+ * @example
281
+ * Field with default (not required)
282
+ * ```typescript
283
+ * const field = z.string().default('hello');
284
+ * console.log(checkIfFieldIsRequired(field)); // false
285
+ * ```
286
+ *
287
+ * @example
288
+ * String without min length (not required - accepts empty string)
289
+ * ```typescript
290
+ * const field = z.string();
291
+ * console.log(checkIfFieldIsRequired(field)); // false
292
+ * ```
293
+ *
294
+ * @example
295
+ * String with nonempty (required)
296
+ * ```typescript
297
+ * const field = z.string().nonempty();
298
+ * console.log(checkIfFieldIsRequired(field)); // true
299
+ * ```
300
+ *
301
+ * @example
302
+ * Nullable field (not required)
303
+ * ```typescript
304
+ * const field = z.number().nullable();
305
+ * console.log(checkIfFieldIsRequired(field)); // false
306
+ * ```
307
+ *
308
+ * @see {@link removeDefault} for understanding how defaults are handled
309
+ * @see {@link getPrimitiveType} for understanding type unwrapping
310
+ * @since 0.1.0
74
311
  */
75
- type MakeOptionalAndNullable<T> = {
76
- [K in keyof T]?: T[K] | null;
77
- };
312
+ declare const checkIfFieldIsRequired: <T extends z.ZodType>(field: T) => boolean;
78
313
 
79
- export { type MakeOptionalAndNullable, type PickArrayObject, type Simplify, checkIfFieldIsRequired, extractDefault, getPrimitiveType, getSchemaDefaults, getUnwrappedType, removeDefault };
314
+ export { type Simplify, canUnwrap, checkIfFieldIsRequired, extractDefault, getPrimitiveType, getSchemaDefaults, removeDefault };
package/dist/index.js CHANGED
@@ -22,15 +22,16 @@ function _interopNamespace(e) {
22
22
 
23
23
  var z__namespace = /*#__PURE__*/_interopNamespace(z);
24
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") {
25
+ // src/defaults.ts
26
+ function canUnwrap(field) {
27
+ return "unwrap" in field && typeof field.unwrap === "function";
28
+ }
29
+ var getPrimitiveType = (field) => {
30
+ if (field instanceof z__namespace.ZodArray) {
30
31
  return field;
31
32
  }
32
- if ("unwrap" in field && typeof field.unwrap === "function") {
33
- return getPrimitiveType(field.unwrap(), options);
33
+ if (canUnwrap(field)) {
34
+ return getPrimitiveType(field.unwrap());
34
35
  }
35
36
  return field;
36
37
  };
@@ -38,7 +39,7 @@ function removeDefault(field) {
38
39
  if (field instanceof z__namespace.ZodDefault) {
39
40
  return field.unwrap();
40
41
  }
41
- if ("innerType" in field.def) {
42
+ if ("innerType" in field.def && field.def.innerType instanceof z__namespace.ZodType) {
42
43
  const inner = removeDefault(field.def.innerType);
43
44
  if (field instanceof z__namespace.ZodOptional) {
44
45
  return inner.optional();
@@ -51,56 +52,48 @@ function removeDefault(field) {
51
52
  }
52
53
  var checkIfFieldIsRequired = (field) => {
53
54
  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;
55
+ if (undefinedResult) {
56
+ return false;
57
+ }
58
+ const defaultRemovedField = removeDefault(field);
59
+ if (!(defaultRemovedField instanceof z__namespace.ZodType)) {
60
+ return false;
61
+ }
62
+ const nullResult = defaultRemovedField.safeParse(null).success;
63
+ const primitiveType = getPrimitiveType(defaultRemovedField);
64
+ const emptyStringResult = primitiveType.type === "string" && defaultRemovedField.safeParse("").success;
65
+ const emptyArrayResult = primitiveType.type === "array" && defaultRemovedField.safeParse([]).success;
58
66
  return !undefinedResult && !nullResult && !emptyStringResult && !emptyArrayResult;
59
67
  };
68
+
69
+ // src/defaults.ts
60
70
  function extractDefault(field) {
61
71
  if (field instanceof z__namespace.ZodDefault) {
62
- const defaultValue = field._def.defaultValue;
63
- return typeof defaultValue === "function" ? defaultValue() : defaultValue;
72
+ return field.def.defaultValue;
64
73
  }
65
- if ("unwrap" in field && typeof field.unwrap === "function") {
74
+ if (canUnwrap(field)) {
66
75
  return extractDefault(field.unwrap());
67
76
  }
68
77
  return void 0;
69
78
  }
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
79
  function getSchemaDefaults(schema) {
80
80
  const defaults = {};
81
81
  for (const key in schema.shape) {
82
82
  const field = schema.shape[key];
83
+ if (!field) continue;
83
84
  const defaultValue = extractDefault(field);
84
85
  if (defaultValue !== void 0) {
85
86
  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
87
  }
95
88
  }
96
89
  return defaults;
97
90
  }
98
91
 
92
+ exports.canUnwrap = canUnwrap;
99
93
  exports.checkIfFieldIsRequired = checkIfFieldIsRequired;
100
94
  exports.extractDefault = extractDefault;
101
95
  exports.getPrimitiveType = getPrimitiveType;
102
96
  exports.getSchemaDefaults = getSchemaDefaults;
103
- exports.getUnwrappedType = getUnwrappedType;
104
97
  exports.removeDefault = removeDefault;
105
98
  //# sourceMappingURL=index.js.map
106
99
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +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"]}
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 * Type representing a Zod type that has an unwrap method\n */\ntype Unwrappable = { unwrap: () => z.ZodTypeAny };\n\n/**\n * Type guard to check if a Zod field can be unwrapped (has wrapper types like optional, nullable, default).\n *\n * This checks whether a Zod type has an `unwrap()` method, which is present on wrapper types\n * like `ZodOptional`, `ZodNullable`, `ZodDefault`, and others.\n *\n * @param field - The Zod field to check\n * @returns True if the field has an unwrap method, false otherwise\n *\n * @example\n * ```typescript\n * const optionalField = z.string().optional();\n * console.log(canUnwrap(optionalField)); // true\n *\n * const plainField = z.string();\n * console.log(canUnwrap(plainField)); // false\n * ```\n *\n * @since 0.1.0\n */\nexport function canUnwrap(\n field: z.ZodTypeAny,\n): field is z.ZodTypeAny & Unwrappable {\n return 'unwrap' in field && typeof field.unwrap === 'function';\n}\n\n/**\n * Gets the underlying primitive type of a Zod field by recursively unwrapping wrapper types.\n *\n * This function removes wrapper layers (optional, nullable, default) to reveal the base type.\n * **Important:** It stops at array types without unwrapping them, treating arrays as primitives.\n *\n * @template T - The Zod type to unwrap\n * @param field - The Zod field to unwrap\n * @returns The unwrapped primitive Zod type\n *\n * @example\n * Unwrapping to string primitive\n * ```typescript\n * const field = z.string().optional().nullable();\n * const primitive = getPrimitiveType(field);\n * // Result: z.string() (unwrapped all wrappers)\n * ```\n *\n * @example\n * Stopping at array type\n * ```typescript\n * const field = z.array(z.string()).optional();\n * const primitive = getPrimitiveType(field);\n * // Result: z.array(z.string()) (stops at array, doesn't unwrap it)\n * ```\n *\n * @example\n * Unwrapping defaults\n * ```typescript\n * const field = z.number().default(0).optional();\n * const primitive = getPrimitiveType(field);\n * // Result: z.number()\n * ```\n *\n * @see {@link canUnwrap} for checking if a field can be unwrapped\n * @since 0.1.0\n */\nexport const getPrimitiveType = <T extends z.ZodTypeAny>(\n field: T,\n): z.ZodTypeAny => {\n // Stop at arrays - don't unwrap them\n if (field instanceof z.ZodArray) {\n return field;\n }\n\n if (canUnwrap(field)) {\n return getPrimitiveType(field.unwrap());\n }\n\n return field;\n};\n\ntype StripZodDefault<T> = T extends z.ZodDefault<infer Inner>\n ? StripZodDefault<Inner>\n : T extends z.ZodOptional<infer Inner>\n ? z.ZodOptional<StripZodDefault<Inner>>\n : T extends z.ZodNullable<infer Inner>\n ? z.ZodNullable<StripZodDefault<Inner>>\n : T;\n\n/**\n * Removes default values from a Zod field while preserving other wrapper types.\n *\n * This function recursively removes `ZodDefault` wrappers from a field, while maintaining\n * `optional()` and `nullable()` wrappers. Useful for scenarios where you want to check\n * field requirements without considering default values.\n *\n * @template T - The Zod type to process\n * @param field - The Zod field to remove defaults from\n * @returns The field without defaults but with optional/nullable preserved\n *\n * @example\n * Removing simple default\n * ```typescript\n * const field = z.string().default('hello');\n * const withoutDefault = removeDefault(field);\n * // Result: z.string()\n * ```\n *\n * @example\n * Preserving optional wrapper\n * ```typescript\n * const field = z.string().default('hello').optional();\n * const withoutDefault = removeDefault(field);\n * // Result: z.string().optional()\n * ```\n *\n * @example\n * Nested defaults\n * ```typescript\n * const field = z.string().default('inner').nullable().default('outer');\n * const withoutDefault = removeDefault(field);\n * // Result: z.string().nullable()\n * ```\n *\n * @see {@link checkIfFieldIsRequired} for usage with requirement checking\n * @since 0.1.0\n */\nexport function removeDefault<T extends z.ZodType>(\n field: T,\n): StripZodDefault<T> {\n if (field instanceof z.ZodDefault) {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return field.unwrap() as StripZodDefault<T>;\n }\n\n if ('innerType' in field.def && field.def.innerType instanceof z.ZodType) {\n const inner = removeDefault(field.def.innerType);\n // Reconstruct the wrapper with the modified inner type\n if (field instanceof z.ZodOptional) {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return inner.optional() as unknown as StripZodDefault<T>;\n }\n if (field instanceof z.ZodNullable) {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return inner.nullable() as unknown as StripZodDefault<T>;\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return field as StripZodDefault<T>;\n}\n\n/**\n * Checks if a Zod field is truly required by testing multiple acceptance criteria.\n *\n * A field is considered **not required** if it accepts any of the following:\n * - `undefined` (via `.optional()` or `.default()`)\n * - `null` (via `.nullable()`)\n * - Empty string (plain `z.string()` without `.min(1)` or `.nonempty()`)\n * - Empty array (plain `z.array()` without `.min(1)` or `.nonempty()`)\n *\n * **Note:** Fields with `.default()` are considered not required since they'll have a value\n * even if the user doesn't provide one.\n *\n * @template T - The Zod type to check\n * @param field - The Zod field to check for required status\n * @returns True if the field is required, false otherwise\n *\n * @example\n * Required field\n * ```typescript\n * const field = z.string().min(1);\n * console.log(checkIfFieldIsRequired(field)); // true\n * ```\n *\n * @example\n * Optional field (not required)\n * ```typescript\n * const field = z.string().optional();\n * console.log(checkIfFieldIsRequired(field)); // false\n * ```\n *\n * @example\n * Field with default (not required)\n * ```typescript\n * const field = z.string().default('hello');\n * console.log(checkIfFieldIsRequired(field)); // false\n * ```\n *\n * @example\n * String without min length (not required - accepts empty string)\n * ```typescript\n * const field = z.string();\n * console.log(checkIfFieldIsRequired(field)); // false\n * ```\n *\n * @example\n * String with nonempty (required)\n * ```typescript\n * const field = z.string().nonempty();\n * console.log(checkIfFieldIsRequired(field)); // true\n * ```\n *\n * @example\n * Nullable field (not required)\n * ```typescript\n * const field = z.number().nullable();\n * console.log(checkIfFieldIsRequired(field)); // false\n * ```\n *\n * @see {@link removeDefault} for understanding how defaults are handled\n * @see {@link getPrimitiveType} for understanding type unwrapping\n * @since 0.1.0\n */\nexport const checkIfFieldIsRequired = <T extends z.ZodType>(field: T) => {\n // First check the original field for undefined - this catches fields with defaults\n const undefinedResult = field.safeParse(undefined).success;\n if (undefinedResult) {\n return false;\n }\n\n const defaultRemovedField = removeDefault(field);\n\n if (!(defaultRemovedField instanceof z.ZodType)) {\n return false;\n }\n\n // Check if field accepts null (nullable)\n const nullResult = defaultRemovedField.safeParse(null).success;\n\n const primitiveType = getPrimitiveType(defaultRemovedField);\n\n const emptyStringResult =\n primitiveType.type === 'string' &&\n defaultRemovedField.safeParse('').success;\n\n const emptyArrayResult =\n primitiveType.type === 'array' && defaultRemovedField.safeParse([]).success;\n\n return (\n !undefinedResult && !nullResult && !emptyStringResult && !emptyArrayResult\n );\n};\n","import * as z from 'zod';\nimport { canUnwrap } from './schema';\nimport type { Simplify } from './types';\n\n/**\n * Extracts the default value from a Zod field, recursively unwrapping optional and nullable layers.\n *\n * This function traverses through wrapper types (like `ZodOptional`, `ZodNullable`) to find\n * the underlying `ZodDefault` and returns its default value. If no default is found, returns `undefined`.\n *\n * @template T - The Zod type to extract default from\n * @param field - The Zod field to extract default from\n * @returns The default value if present, undefined otherwise\n *\n * @example\n * Basic usage with default value\n * ```typescript\n * const field = z.string().default('hello');\n * const defaultValue = extractDefault(field);\n * // Result: 'hello'\n * ```\n *\n * @example\n * Unwrapping optional/nullable layers\n * ```typescript\n * const field = z.string().default('world').optional();\n * const defaultValue = extractDefault(field);\n * // Result: 'world' (unwraps optional to find default)\n * ```\n *\n * @example\n * Field without default\n * ```typescript\n * const field = z.string().optional();\n * const defaultValue = extractDefault(field);\n * // Result: undefined\n * ```\n *\n * @see {@link getSchemaDefaults} for extracting defaults from entire schemas\n * @since 0.1.0\n */\nexport function extractDefault<T extends z.ZodTypeAny>(\n field: T,\n): z.infer<T> | undefined {\n if (field instanceof z.ZodDefault) {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return field.def.defaultValue as z.infer<T>;\n }\n\n if (canUnwrap(field)) {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return extractDefault(field.unwrap()) as z.infer<T>;\n }\n\n return undefined;\n}\n\n/**\n * Extracts default values from a Zod object schema while skipping fields without defaults.\n *\n * This function recursively traverses the schema and collects all fields that have\n * explicit default values defined. Fields without defaults are excluded from the result.\n *\n * **Important:** Nested defaults are NOT extracted unless the parent object also has\n * an explicit `.default()`. This is by design to match Zod's default value behavior.\n *\n * @template T - The Zod object schema type\n * @param schema - The Zod object schema to extract defaults from\n * @returns A partial object containing only fields with default values\n *\n * @example\n * Basic usage\n * ```typescript\n * const schema = z.object({\n * name: z.string().default('John'),\n * age: z.number(), // no default - will be skipped\n * email: z.string().email().optional(),\n * });\n *\n * const defaults = getSchemaDefaults(schema);\n * // Result: { name: 'John' }\n * ```\n *\n * @example\n * Nested objects with defaults\n * ```typescript\n * const schema = z.object({\n * user: z.object({\n * name: z.string().default('Guest')\n * }).default({ name: 'Guest' }), // ✅ Extracted because parent has .default()\n *\n * settings: z.object({\n * theme: z.string().default('light')\n * }), // ❌ NOT extracted - parent has no .default()\n * });\n *\n * const defaults = getSchemaDefaults(schema);\n * // Result: { user: { name: 'Guest' } }\n * ```\n *\n * @example\n * Unwrapping optional/nullable fields\n * ```typescript\n * const schema = z.object({\n * title: z.string().default('Untitled').optional(),\n * count: z.number().default(0).nullable(),\n * });\n *\n * const defaults = getSchemaDefaults(schema);\n * // Result: { title: 'Untitled', count: 0 }\n * ```\n *\n * @see {@link extractDefault} for extracting defaults from individual fields\n * @since 0.1.0\n */\nexport function getSchemaDefaults<T extends z.ZodObject>(\n schema: T,\n): Simplify<Partial<z.infer<T>>> {\n const defaults: Record<string, unknown> = {};\n\n for (const key in schema.shape) {\n const field = schema.shape[key];\n if (!field) continue;\n\n // Check if this field has an explicit default value\n const defaultValue = extractDefault(field);\n if (defaultValue !== undefined) {\n defaults[key] = defaultValue;\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return defaults as Partial<z.infer<T>>;\n}\n"]}
package/dist/index.mjs CHANGED
@@ -1,14 +1,15 @@
1
1
  import * as z from 'zod';
2
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") {
3
+ // src/defaults.ts
4
+ function canUnwrap(field) {
5
+ return "unwrap" in field && typeof field.unwrap === "function";
6
+ }
7
+ var getPrimitiveType = (field) => {
8
+ if (field instanceof z.ZodArray) {
8
9
  return field;
9
10
  }
10
- if ("unwrap" in field && typeof field.unwrap === "function") {
11
- return getPrimitiveType(field.unwrap(), options);
11
+ if (canUnwrap(field)) {
12
+ return getPrimitiveType(field.unwrap());
12
13
  }
13
14
  return field;
14
15
  };
@@ -16,7 +17,7 @@ function removeDefault(field) {
16
17
  if (field instanceof z.ZodDefault) {
17
18
  return field.unwrap();
18
19
  }
19
- if ("innerType" in field.def) {
20
+ if ("innerType" in field.def && field.def.innerType instanceof z.ZodType) {
20
21
  const inner = removeDefault(field.def.innerType);
21
22
  if (field instanceof z.ZodOptional) {
22
23
  return inner.optional();
@@ -29,51 +30,43 @@ function removeDefault(field) {
29
30
  }
30
31
  var checkIfFieldIsRequired = (field) => {
31
32
  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;
33
+ if (undefinedResult) {
34
+ return false;
35
+ }
36
+ const defaultRemovedField = removeDefault(field);
37
+ if (!(defaultRemovedField instanceof z.ZodType)) {
38
+ return false;
39
+ }
40
+ const nullResult = defaultRemovedField.safeParse(null).success;
41
+ const primitiveType = getPrimitiveType(defaultRemovedField);
42
+ const emptyStringResult = primitiveType.type === "string" && defaultRemovedField.safeParse("").success;
43
+ const emptyArrayResult = primitiveType.type === "array" && defaultRemovedField.safeParse([]).success;
36
44
  return !undefinedResult && !nullResult && !emptyStringResult && !emptyArrayResult;
37
45
  };
46
+
47
+ // src/defaults.ts
38
48
  function extractDefault(field) {
39
49
  if (field instanceof z.ZodDefault) {
40
- const defaultValue = field._def.defaultValue;
41
- return typeof defaultValue === "function" ? defaultValue() : defaultValue;
50
+ return field.def.defaultValue;
42
51
  }
43
- if ("unwrap" in field && typeof field.unwrap === "function") {
52
+ if (canUnwrap(field)) {
44
53
  return extractDefault(field.unwrap());
45
54
  }
46
55
  return void 0;
47
56
  }
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
57
  function getSchemaDefaults(schema) {
58
58
  const defaults = {};
59
59
  for (const key in schema.shape) {
60
60
  const field = schema.shape[key];
61
+ if (!field) continue;
61
62
  const defaultValue = extractDefault(field);
62
63
  if (defaultValue !== void 0) {
63
64
  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
65
  }
73
66
  }
74
67
  return defaults;
75
68
  }
76
69
 
77
- export { checkIfFieldIsRequired, extractDefault, getPrimitiveType, getSchemaDefaults, getUnwrappedType, removeDefault };
70
+ export { canUnwrap, checkIfFieldIsRequired, extractDefault, getPrimitiveType, getSchemaDefaults, removeDefault };
78
71
  //# sourceMappingURL=index.mjs.map
79
72
  //# sourceMappingURL=index.mjs.map