UNPKG

@assassinonz/exzodus-router

Version:

Express router wrapper with end to end type safety

32 lines 2.4 kB
import express from "express"; import { z } from "zod"; import type { Api, EndpointInputs, MethodByPath, Path, PathByMethod, ResponseBody, ResponseCode } from "./index.js"; declare module "express-serve-static-core" { interface IRouterMatcher<T, Method extends "all" | "get" | "post" | "put" | "delete" | "patch" | "options" | "head" = any> { (path: PathParams, ...handlers: (RequestHandlerParams | TypedRouter<never, unknown>)[]): T; } } type ZodParsedEndpointInputs<A extends Api, M extends MethodByPath<A, P>, P extends Path<A>> = { [K in keyof EndpointInputs<A, M, P>]: EndpointInputs<A, M, P>[K] extends z.ZodType ? z.output<EndpointInputs<A, M, P>[K]> : never; }; type ValidatorParsedEndpointInputs<A extends Api, M extends MethodByPath<A, P>, P extends Path<A>> = { [K in keyof ZodParsedEndpointInputs<A, M, P>]: NonNullable<ZodParsedEndpointInputs<A, M, P>[K]>; }; export type TypedRequestHandler<A extends Api, M extends MethodByPath<A, P>, P extends Path<A>, Extras> = (req: ValidatorParsedEndpointInputs<A, M, P> extends { path: infer ReqP; body: infer ReqB; query: infer ReqQ; } ? express.Request<ReqP, unknown, ReqB, ReqQ> & Extras : express.Request<never, never, never, never> & Extras, res: Omit<express.Response, "status"> & { status: <C extends ResponseCode<A, M, P>>(code: C) => express.Response<ResponseBody<A, M, P, C>>; }, next: express.NextFunction) => unknown | Promise<unknown>; export type RequestHandlerWithExtras<Extras> = (req: express.Request & Extras, res: express.Response, next: express.NextFunction) => unknown | Promise<unknown>; export interface TypedRouter<A extends Api, Extras> { get: <P extends PathByMethod<A, "get">>(path: P, ...handlers: TypedRequestHandler<A, "get", P, Extras>[]) => this; post: <P extends PathByMethod<A, "post">>(path: P, ...handlers: TypedRequestHandler<A, "post", P, Extras>[]) => this; put: <P extends PathByMethod<A, "put">>(path: P, ...handlers: TypedRequestHandler<A, "put", P, Extras>[]) => this; patch: <P extends PathByMethod<A, "patch">>(path: P, ...handlers: TypedRequestHandler<A, "patch", P, Extras>[]) => this; delete: <P extends PathByMethod<A, "delete">>(path: P, ...handlers: TypedRequestHandler<A, "delete", P, Extras>[]) => this; use: (path: string, ...handlers: RequestHandlerWithExtras<never>[]) => this; } export {}; //# sourceMappingURL=router.d.ts.map