-
-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathio-schema.ts
54 lines (47 loc) · 2.01 KB
/
io-schema.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import { z } from "zod";
import { FlatObject } from "./common-helpers";
import { copyMeta } from "./metadata";
import { AbstractMiddleware } from "./middleware";
import { RawSchema } from "./raw-schema";
type BaseObject<U extends z.UnknownKeysParam> = z.ZodObject<z.ZodRawShape, U>;
// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- workaround for TS2456, circular reference
interface ObjectBasedEffect<T extends z.ZodTypeAny>
extends z.ZodEffects<T, FlatObject> {}
type EffectsChain<U extends z.UnknownKeysParam> = ObjectBasedEffect<
BaseObject<U> | EffectsChain<U>
>;
/**
* @desc The type allowed on the top level of Middlewares and Endpoints
* @param U — only "strip" is allowed for Middlewares due to intersection issue (Zod) #600
* */
export type IOSchema<U extends z.UnknownKeysParam = z.UnknownKeysParam> =
| BaseObject<U> // z.object()
| EffectsChain<U> // z.object().refine(), z.object().transform(), z.object().preprocess()
| RawSchema // ez.raw()
| z.ZodUnion<[IOSchema<U>, ...IOSchema<U>[]]> // z.object().or()
| z.ZodIntersection<IOSchema<U>, IOSchema<U>> // z.object().and()
| z.ZodDiscriminatedUnion<string, BaseObject<U>[]> // z.discriminatedUnion()
| z.ZodPipeline<ObjectBasedEffect<BaseObject<U>>, BaseObject<U>>; // z.object().remap()
/**
* @description intersects input schemas of middlewares and the endpoint
* @since 07.03.2022 former combineEndpointAndMiddlewareInputSchemas()
* @since 05.03.2023 is immutable to metadata
* @since 26.05.2024 uses the regular ZodIntersection
* @see copyMeta
*/
export const getFinalEndpointInputSchema = <
MIN extends IOSchema<"strip">,
IN extends IOSchema,
>(
middlewares: AbstractMiddleware[],
input: IN,
): z.ZodIntersection<MIN, IN> => {
const allSchemas = middlewares
.map((mw) => mw.getSchema() as IOSchema)
.concat(input);
const finalSchema = allSchemas.reduce((acc, schema) => acc.and(schema));
return allSchemas.reduce(
(acc, schema) => copyMeta(schema, acc),
finalSchema,
) as z.ZodIntersection<MIN, IN>;
};