UNPKG

@ws-kit/zod

Version:

Zod validator adapter for WS-Kit with runtime schema validation and full TypeScript inference

174 lines 7.35 kB
/** * Runtime envelope builders for message schemas. * Provides two forms: object-oriented (primary) and positional (compact). * * Both return strict Zod root objects with non-enumerable hints for the router * and per-schema options (validateOutgoing, strict) for granular control. * * Users can compose schemas before wrapping to preserve type safety: * const JoinPayload = z.object({roomId: z.string()}).transform(...); * const Join = message({ type: "JOIN", payload: JoinPayload, options: {...} }); */ import { type SchemaOpts } from "@ws-kit/core/internal"; import { z, type ZodDefault, type ZodLiteral, type ZodObject, type ZodOptional, type ZodRawShape, type ZodType } from "zod"; import type { BrandedSchema } from "./types.js"; /** * Symbol for Zod payload schema (validator-specific). * Stores the Zod schema for the payload field. */ export declare const ZOD_PAYLOAD: unique symbol; /** * Standard meta fields that are always allowed. * Users can extend with additional required or optional fields. */ declare const STANDARD_META_FIELDS: { timestamp: z.ZodOptional<z.ZodNumber>; correlationId: z.ZodOptional<z.ZodString>; }; /** * Helper type to infer actual types from ZodRawShape or ZodObject. * Converts each Zod schema in a shape to its inferred type. * * @internal */ type InferPayloadShape<P extends ZodRawShape | ZodObject<any> | undefined> = P extends undefined ? never : P extends ZodRawShape ? { [K in keyof P]: P[K] extends ZodType<infer U> ? U : never; } : P extends ZodObject<any> ? z.infer<P> : never; /** * Helper to construct the Zod shape for the message root object. * This ensures z.infer<typeof Message> returns the correct structure. */ type MessageZodShape<T extends string, P extends ZodRawShape | ZodObject<any> | undefined, M extends ZodRawShape | undefined> = { type: ZodLiteral<T>; meta: ZodDefault<ZodOptional<ZodObject<M extends ZodRawShape ? Omit<typeof STANDARD_META_FIELDS, keyof M> & M : typeof STANDARD_META_FIELDS>>>; } & (P extends undefined ? {} : { payload: P extends ZodObject<any> ? P : P extends ZodRawShape ? ZodObject<P> : never; }); /** * Creates a strict Zod root message schema. * Supports two forms: object-oriented (primary) and positional (compact). * * Object form (recommended for clarity and extensibility): * ```typescript * const Join = message({ * type: "USER_JOIN", * payload: z.object({ roomId: z.string() }), * options: { strict: true } * }); * ``` * * Positional form (for small, one-off schemas): * ```typescript * const Ping = message("PING"); * const Join = message("USER_JOIN", { roomId: z.string() }); * ``` */ export declare function message<const T extends string, P extends ZodRawShape | ZodObject<any> | undefined = undefined, M extends ZodRawShape | undefined = undefined>(spec: { type: T; payload?: P; meta?: M; options?: SchemaOpts; }): ZodObject<MessageZodShape<T, P, M>> & BrandedSchema<T, P extends undefined ? never : InferPayloadShape<P>, never, M extends ZodRawShape ? { [K in keyof M]: M[K] extends ZodType<infer U> ? U : never; } : {}> & { readonly messageType: T; readonly __zod_payload: P; readonly __descriptor: { readonly messageType: T; readonly kind: "event"; }; readonly __runtime: "ws-kit-schema"; }; export declare function message<const T extends string, P extends ZodRawShape | ZodObject<any> | undefined = undefined, M extends ZodRawShape | undefined = undefined>(type: T, payload?: P, metaShape?: M): ZodObject<MessageZodShape<T, P, M>> & BrandedSchema<T, P extends undefined ? never : InferPayloadShape<P>, never, M extends ZodRawShape ? { [K in keyof M]: M[K] extends ZodType<infer U> ? U : never; } : {}> & { readonly messageType: T; readonly __zod_payload: P; readonly __descriptor: { readonly messageType: T; readonly kind: "event"; }; readonly __runtime: "ws-kit-schema"; }; /** * Creates an RPC schema with separate request and response message definitions. * Supports two forms: object-oriented (primary) and positional (compact). * * Object form (recommended for granular control): * ```typescript * const GetUser = rpc({ * req: { * type: "GET_USER", * payload: z.object({ id: z.string() }) * }, * res: { * type: "USER", * payload: z.object({ id: z.string(), name: z.string() }), * options: { validateOutgoing: true } * } * }); * ``` * * Positional form (for simple, compact contracts): * ```typescript * const GetUser = rpc( * "GET_USER", { id: z.string() }, * "USER", { id: z.string(), name: z.string() } * ); * ``` */ export declare function rpc<const ReqT extends string, ReqP extends ZodRawShape | ZodObject<any> | undefined, ResT extends string, ResP extends ZodRawShape | ZodObject<any> | undefined, ReqM extends ZodRawShape | undefined = undefined, ResM extends ZodRawShape | undefined = undefined>(spec: { req: { type: ReqT; payload?: ReqP; meta?: ReqM; options?: SchemaOpts; }; res: { type: ResT; payload?: ResP; meta?: ResM; options?: SchemaOpts; }; }): ZodObject<MessageZodShape<ReqT, ReqP, ReqM>> & BrandedSchema<ReqT, ReqP extends undefined ? never : InferPayloadShape<ReqP>, ResP extends undefined ? never : InferPayloadShape<ResP>, ReqM extends ZodRawShape ? { [K in keyof ReqM]: ReqM[K] extends ZodType<infer U> ? U : never; } : {}> & { readonly response: ZodObject<MessageZodShape<ResT, ResP, ResM>> & BrandedSchema<ResT, ResP extends undefined ? never : InferPayloadShape<ResP>, never, ResM extends ZodRawShape ? { [K in keyof ResM]: ResM[K] extends ZodType<infer U> ? U : never; } : {}> & { readonly messageType: ResT; readonly __zod_payload: ResP; readonly __descriptor: { readonly messageType: ResT; readonly kind: "event"; }; readonly __runtime: "ws-kit-schema"; }; readonly messageType: ReqT; readonly __zod_payload: ReqP; readonly __descriptor: { readonly messageType: ReqT; readonly kind: "rpc"; }; readonly __runtime: "ws-kit-schema"; }; export declare function rpc<const ReqT extends string, ReqP extends ZodRawShape | ZodObject<any> | undefined, ResT extends string, ResP extends ZodRawShape | ZodObject<any> | undefined>(requestType: ReqT, requestPayload: ReqP, responseType: ResT, responsePayload: ResP): ZodObject<MessageZodShape<ReqT, ReqP, undefined>> & BrandedSchema<ReqT, ReqP extends undefined ? never : InferPayloadShape<ReqP>, ResP extends undefined ? never : InferPayloadShape<ResP>, {}> & { readonly response: ZodObject<MessageZodShape<ResT, ResP, undefined>> & BrandedSchema<ResT, ResP extends undefined ? never : InferPayloadShape<ResP>, never, {}> & { readonly messageType: ResT; readonly __zod_payload: ResP; readonly __descriptor: { readonly messageType: ResT; readonly kind: "event"; }; readonly __runtime: "ws-kit-schema"; }; readonly messageType: ReqT; readonly __zod_payload: ReqP; readonly __descriptor: { readonly messageType: ReqT; readonly kind: "rpc"; }; readonly __runtime: "ws-kit-schema"; }; export {}; //# sourceMappingURL=runtime.d.ts.map