zodselect 1.2.9 โ 1.3.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 +8 -0
- package/dist/refine-schema.d.ts +24 -2
- package/dist/refine-schema.js +25 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -139,6 +139,14 @@ const schema = refineSchema(UserSchema, {
|
|
|
139
139
|
}
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
+
A field the schema doesn't have is a type error, at any depth and even beside valid fields:
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
refineSchema(UserSchema, { firstName: true, lastNmae: true }); // โ 'lastNmae' is not a field of UserSchema
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Code that builds a selection generically, whose type the check can't evaluate, calls `refineSchemaUnchecked` instead: the same refinement, with a field the schema doesn't have skipped.
|
|
149
|
+
|
|
142
150
|
---
|
|
143
151
|
|
|
144
152
|
## ๐งช Refine Field Types Inline
|
package/dist/refine-schema.d.ts
CHANGED
|
@@ -2,6 +2,20 @@ import { core, z, ZodAny, ZodArray, ZodBoolean, ZodDate, ZodLiteral, ZodNever, Z
|
|
|
2
2
|
import { IsAny, IsJsonType } from './types.js';
|
|
3
3
|
type ApplyOptionalNullable<T, U extends ZodType> = IsAny<T, U, unknown extends T ? U : undefined extends T ? null extends T ? ZodOptional<ZodNullable<U>> : ZodOptional<U> : null extends T ? ZodNullable<U> : U>;
|
|
4
4
|
type DepthLimit = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
5
|
+
/** `TShape` with every key `T` doesn't have, at any depth, as `never`, so a misspelt select is a type error even beside valid keys. */
|
|
6
|
+
type Exact<TShape, T> = {
|
|
7
|
+
[K in keyof TShape]: K extends FieldKeys<T> ? TShape[K] extends ((schema: never) => unknown) | boolean | ZodType ? TShape[K] : TShape[K] extends object ? Exact<TShape[K], FieldObjects<FieldAt<T, K>>> : TShape[K] : never;
|
|
8
|
+
};
|
|
9
|
+
/** What {@link refineSchema} takes for `T`: `TShape`, with a key `T` doesn't have, at any depth, a type error even beside valid keys. */
|
|
10
|
+
export type ExactRefineSchema<T extends ZodType<object> | ZodUnion, TShape> = TShape & Exact<TShape, z.infer<T>>;
|
|
11
|
+
/** What the field `TKey` holds in any object of `T`. */
|
|
12
|
+
type FieldAt<T, TKey> = T extends unknown ? TKey extends keyof T ? T[TKey] : never : never;
|
|
13
|
+
/** The declared keys of every object in `T`, each of a union's own. */
|
|
14
|
+
type FieldKeys<T> = T extends unknown ? Extract<keyof {
|
|
15
|
+
[K in keyof T as string extends K ? never : number extends K ? never : K]: unknown;
|
|
16
|
+
}, string> : never;
|
|
17
|
+
/** The objects a field of type `T` holds, through arrays: what a nested select picks within. */
|
|
18
|
+
type FieldObjects<T> = T extends readonly (infer E)[] ? FieldObjects<E> : T extends Date ? never : T extends object ? T : never;
|
|
5
19
|
type InternalZodify<T, TDepth extends number = 0> = TDepth extends 9 ? ZodType : IsAny<T, ZodAny, T extends string ? string extends T ? ZodString : ZodLiteral<T> : T extends number ? number extends T ? ZodNumber : ZodLiteral<T> : T extends boolean ? boolean extends T ? ZodBoolean : ZodLiteral<T> : T extends Date ? ZodDate : unknown extends T ? ZodUnknown : T extends Array<infer U> ? ZodArray<Zodify<U, NextDepth<TDepth>>> : T extends object ? IsJsonType<T, true, ZodObject<{
|
|
6
20
|
[K in keyof T]-?: Zodify<T[K], NextDepth<TDepth>>;
|
|
7
21
|
}, core.$strict>, ZodType<T>> : never>;
|
|
@@ -13,13 +27,15 @@ type ReapplyOptionalNullable<T, U extends z.ZodType> = T extends ZodOptional<Zod
|
|
|
13
27
|
export type RefinedSchema<T extends ZodType<object> | ZodUnion, TShape extends RefineSchema<T, TIsSimple>, TIsSimple extends boolean> = T extends ZodUnion ? RefinedUnionSchema<T, TShape> : T extends ZodType<object> ? RefinedTypeSchema<z.infer<T>, TShape> : never;
|
|
14
28
|
export type RefinedTypeSchema<T extends object, TShape, TDepth extends number = 0> = TDepth extends keyof DepthLimit ? ZodObject<{
|
|
15
29
|
[K in keyof T & keyof TShape]: TShape[K] extends (schema: infer _S) => ZodType ? ReturnType<TShape[K]> : TShape[K] extends ZodType ? TShape[K] : TShape[K] extends boolean ? ZodifyField<T, K> : TShape[K] extends object ? Exclude<T[K], null | undefined> extends Array<infer U> ? [Extract<U, object>] extends [never] ? Zodify<T[K]> : ApplyOptionalNullable<T[K], z.ZodArray<RefinedVariants<Extract<U, object>, TShape[K], NextDepth<TDepth>>>> : [Extract<Exclude<T[K], null | undefined>, object>] extends [never] ? ZodNever : ApplyOptionalNullable<T[K], RefinedVariants<Extract<Exclude<T[K], null | undefined>, object>, TShape[K], NextDepth<TDepth>>> : ZodNever;
|
|
16
|
-
}, core.$
|
|
30
|
+
}, core.$strip> : any;
|
|
17
31
|
export type RefinedUnionSchema<T extends ZodUnion, TShape> = ZodUnion<T['options'] extends Readonly<[infer A, ...infer Rest]> ? Rest extends ZodType[] ? [
|
|
18
32
|
ReapplyOptionalNullable<A, A extends ZodType<object> ? RefinedTypeSchema<z.infer<A>, TShape> : Extract<A, ZodType>>,
|
|
19
33
|
...{
|
|
20
34
|
[K in keyof Rest]: Rest[K] extends ZodType ? z.infer<Rest[K]> extends object ? RefinedTypeSchema<z.infer<Rest[K]>, TShape> : Extract<Rest[K], ZodType> : Extract<Rest[K], ZodType>;
|
|
21
35
|
}
|
|
22
36
|
] : never : never>;
|
|
37
|
+
/** The value of the fields of `T` that `TShape` picks: the output of {@link RefinedTypeSchema}. */
|
|
38
|
+
export type RefinedValue<T extends object, TShape> = z.output<RefinedTypeSchema<T, TShape>>;
|
|
23
39
|
/** One refined schema per variant of a union of objects (a plain object is its own one variant), so the result narrows by variant. */
|
|
24
40
|
type RefinedVariants<T, TShape, TDepth extends number> = T extends object ? RefinedTypeSchema<T, TShape, TDepth> : never;
|
|
25
41
|
type Refinement<T extends ZodType, TIsSimple extends boolean> = TIsSimple extends true ? boolean : ((schema: T) => ZodType) | boolean | ZodType;
|
|
@@ -43,5 +59,11 @@ type ZodifyField<T, TKey extends keyof T> = unknown extends T[TKey] ? Partial<Pi
|
|
|
43
59
|
type ZodifyLiteral<T, TElse> = [
|
|
44
60
|
T
|
|
45
61
|
] extends [boolean | number | string] ? [T] extends [boolean] ? boolean extends T ? ZodBoolean : ZodLiteral<T> : string extends T ? [T] extends [string] ? ZodString : TElse : number extends T ? [T] extends [number] ? ZodNumber : TElse : ZodLiteral<T> : TElse;
|
|
46
|
-
|
|
62
|
+
/** `shape`'s fields of `schema`. A key the schema doesn't have, at any depth, is a type error. */
|
|
63
|
+
export declare function refineSchema<T extends ZodType<object> | ZodUnion, TShape extends RefineSchema<T, false>>(schema: T, shape: ExactRefineSchema<T, TShape>): RefinedSchema<T, TShape, false>;
|
|
64
|
+
/**
|
|
65
|
+
* {@link refineSchema} for a shape whose type is still generic, which the exact key check can't evaluate.
|
|
66
|
+
* Prefer {@link refineSchema}: a key the schema doesn't have is skipped here, not refused.
|
|
67
|
+
*/
|
|
68
|
+
export declare function refineSchemaUnchecked<T extends ZodType<object> | ZodUnion, TShape extends RefineSchema<T, false>>(schema: T, shape: TShape): RefinedSchema<T, TShape, false>;
|
|
47
69
|
export {};
|
package/dist/refine-schema.js
CHANGED
|
@@ -1,22 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { isZodArray, isZodCatch, isZodDefault, isZodLazy, isZodNullable, isZodObject, isZodOptional, isZodType, isZodUnion } from './utilities.js';
|
|
3
|
-
|
|
3
|
+
/** `shape`'s fields of `schema`. A key the schema doesn't have, at any depth, is a type error. */
|
|
4
4
|
export function refineSchema(schema, shape) {
|
|
5
|
-
|
|
6
|
-
const refinedShape = {};
|
|
7
|
-
const schemaShape = schema.shape;
|
|
8
|
-
for (const key in shape) {
|
|
9
|
-
if (key in schemaShape && shape[key] !== false) {
|
|
10
|
-
refinedShape[key] = refineSchemaField(schemaShape[key], shape[key]);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
return z.object(refinedShape);
|
|
14
|
-
}
|
|
15
|
-
else if (isZodUnion(schema)) {
|
|
16
|
-
const refinedOptions = schema.options.map(option => refineSchemaField(option, shape));
|
|
17
|
-
return z.union(refinedOptions);
|
|
18
|
-
}
|
|
19
|
-
throw new Error('Unsupported schema type for refinement');
|
|
5
|
+
return refineSchemaUnchecked(schema, shape);
|
|
20
6
|
}
|
|
21
7
|
// Helper function to refine a single schema field
|
|
22
8
|
function refineSchemaField(fieldSchema, fieldShape) {
|
|
@@ -30,10 +16,10 @@ function refineSchemaField(fieldSchema, fieldShape) {
|
|
|
30
16
|
return fieldShape; // Use redefined type
|
|
31
17
|
}
|
|
32
18
|
else if (isZodObject(fieldSchema)) {
|
|
33
|
-
return
|
|
19
|
+
return refineSchemaUnchecked(fieldSchema, fieldShape); // Recursively refine nested objects
|
|
34
20
|
}
|
|
35
21
|
else if (isZodUnion(fieldSchema)) {
|
|
36
|
-
return
|
|
22
|
+
return refineSchemaUnchecked(fieldSchema, fieldShape);
|
|
37
23
|
}
|
|
38
24
|
else if (isZodArray(fieldSchema)) {
|
|
39
25
|
// Recursively refine array items
|
|
@@ -54,3 +40,24 @@ function refineSchemaField(fieldSchema, fieldShape) {
|
|
|
54
40
|
}
|
|
55
41
|
return fieldSchema;
|
|
56
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* {@link refineSchema} for a shape whose type is still generic, which the exact key check can't evaluate.
|
|
45
|
+
* Prefer {@link refineSchema}: a key the schema doesn't have is skipped here, not refused.
|
|
46
|
+
*/
|
|
47
|
+
export function refineSchemaUnchecked(schema, shape) {
|
|
48
|
+
if (isZodObject(schema)) {
|
|
49
|
+
const refinedShape = {};
|
|
50
|
+
const schemaShape = schema.shape;
|
|
51
|
+
for (const key in shape) {
|
|
52
|
+
if (key in schemaShape && shape[key] !== false) {
|
|
53
|
+
refinedShape[key] = refineSchemaField(schemaShape[key], shape[key]);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return z.object(refinedShape);
|
|
57
|
+
}
|
|
58
|
+
else if (isZodUnion(schema)) {
|
|
59
|
+
const refinedOptions = schema.options.map(option => refineSchemaField(option, shape));
|
|
60
|
+
return z.union(refinedOptions);
|
|
61
|
+
}
|
|
62
|
+
throw new Error('Unsupported schema type for refinement');
|
|
63
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zodselect",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Type-safe selection utility built on top of Zod. Allows for strongly typed field selection, schema merging, and runtime refinement for frontend or backend use.",
|
|
5
5
|
"author": "SecureDataSystems",
|
|
6
6
|
"license": "MIT",
|