@zodios/express
Version:
Typescript express server
114 lines (109 loc) • 7.88 kB
TypeScript
import express, { Request, Response, RouterOptions } from 'express';
import { ZodObject, ZodAny, z } from 'zod';
import { ZodiosEndpointDefinitions, Method, ZodiosPathsByMethod, ZodiosPathParamsByPath, ZodiosBodyByPath, ZodiosQueryParamsByPath, ZodiosResponseByPath, ZodiosEndpointDefinition, ZodiosErrorByPath } from '@zodios/core';
import { IfEquals, Narrow } from '@zodios/core/lib/utils.types';
import http from 'http';
type ZodiosSuccessCodes = 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 226;
type WithZodiosContext<T, Context extends ZodObject<any>> = Context extends ZodAny ? T : T & z.infer<Context>;
interface ZodiosRequestHandler<Api extends ZodiosEndpointDefinitions, Context extends ZodObject<any>, M extends Method, Path extends ZodiosPathsByMethod<Api, M>, ReqPath = ZodiosPathParamsByPath<Api, M, Path, false>, ReqBody = ZodiosBodyByPath<Api, M, Path, false>, ReqQuery = ZodiosQueryParamsByPath<Api, M, Path, false>, Res = ZodiosResponseByPath<Api, M, Path, false>> {
(req: WithZodiosContext<express.Request<ReqPath, Res, ReqBody, ReqQuery>, Context>, res: Omit<express.Response<Res>, "status"> & {
status<StatusCode extends number, API extends ZodiosEndpointDefinition[] = Api, METHOD extends Method = M, PATH extends ZodiosPathsByMethod<Api, M> = Path>(status: StatusCode): StatusCode extends ZodiosSuccessCodes ? express.Response<Res> : express.Response<ZodiosErrorByPath<API, METHOD, PATH, StatusCode, false>>;
}, next: express.NextFunction): void;
}
type ZodiosHandler<Router, Context extends ZodObject<any>, Api extends ZodiosEndpointDefinitions, M extends Method> = <Path extends ZodiosPathsByMethod<Api, M>>(path: Path, ...handlers: Array<ZodiosRequestHandler<Api, Context, M, Path>>) => Router;
type ZodiosRouterContextRequestHandler<Context extends ZodObject<any>> = (req: WithZodiosContext<express.Request, Context>, res: express.Response, next: express.NextFunction) => void;
type ZodiosRouterContextErrorHandler<Context extends ZodObject<any>> = (error: any, req: WithZodiosContext<express.Request, Context>, res: express.Response, next: express.NextFunction) => void;
type ZodiosRouterValidationErrorHandler<Context extends ZodObject<any>> = (error: {
context: string;
error: z.ZodIssue[];
}, req: WithZodiosContext<express.Request, Context>, res: express.Response, next: express.NextFunction) => void;
interface ZodiosUse<Context extends ZodObject<any>> {
use(...handlers: Array<ZodiosRouterContextRequestHandler<Context>>): this;
use(handlers: Array<ZodiosRouterContextRequestHandler<Context>>): this;
use(errorHandler: ZodiosRouterContextErrorHandler<Context>): this;
use(path: string, ...handlers: Array<ZodiosRouterContextRequestHandler<Context>>): this;
use(path: string, handlers: Array<ZodiosRouterContextRequestHandler<Context>>): this;
}
interface ZodiosHandlers<Api extends ZodiosEndpointDefinitions, Context extends ZodObject<any>> extends ZodiosUse<Context> {
get: ZodiosHandler<this, Context, Api, "get">;
post: ZodiosHandler<this, Context, Api, "post">;
put: ZodiosHandler<this, Context, Api, "put">;
patch: ZodiosHandler<this, Context, Api, "patch">;
delete: ZodiosHandler<this, Context, Api, "delete">;
options: ZodiosHandler<this, Context, Api, "options">;
head: ZodiosHandler<this, Context, Api, "head">;
}
interface ZodiosValidationOptions {
/**
* validate request parameters - default is true
*/
validate?: boolean;
/**
* transform request parameters - default is false
*/
transform?: boolean;
}
interface ZodiosAppOptions<Context extends ZodObject<any>> extends ZodiosValidationOptions {
/**
* express app intance - default is express()
*/
express?: ReturnType<typeof express>;
/**
* enable express json body parser - default is true
*/
enableJsonBodyParser?: boolean;
context?: Context;
validationErrorHandler?: ZodiosRouterValidationErrorHandler<Context>;
}
interface ZodiosRouterOptions<Context extends ZodObject<any>> extends ZodiosValidationOptions {
/**
* express router instance - default is express.Router
*/
router?: ReturnType<typeof express.Router>;
context?: Context;
validationErrorHandler?: ZodiosRouterValidationErrorHandler<Context>;
}
interface ZodiosUnknownApp<Context extends ZodObject<any>> extends Omit<ReturnType<typeof express>, "use">, ZodiosUse<Context> {
(req: Request | http.IncomingMessage, res: Response | http.ServerResponse): any;
}
interface ZodiosApiApp<Api extends ZodiosEndpointDefinition[], Context extends ZodObject<any>> extends Omit<ReturnType<typeof express>, Method | "use">, ZodiosHandlers<Api, Context> {
(req: Request | http.IncomingMessage, res: Response | http.ServerResponse): any;
}
type ZodiosApp<Api extends ZodiosEndpointDefinitions, Context extends ZodObject<any>> = IfEquals<Api, any, ZodiosUnknownApp<Context>, ZodiosApiApp<Api, Context>>;
type ZodiosRouter<Api extends ZodiosEndpointDefinitions, Context extends ZodObject<any>> = IfEquals<Api, any, Omit<ReturnType<typeof express.Router>, "use"> & ZodiosUse<Context> & ZodiosRouterContextRequestHandler<Context>, Omit<ReturnType<typeof express.Router>, Method | "use"> & ZodiosHandlers<Api, Context> & ZodiosRouterContextRequestHandler<Context>>;
/**
* create a zodios app based on the given api and express
* @param api - api definition
* @param options - options to configure the app
* @returns
*/
declare function zodiosApp<Api extends ZodiosEndpointDefinitions = any, Context extends ZodObject<any> = ZodObject<any>>(api?: Narrow<Api>, options?: ZodiosAppOptions<Context>): ZodiosApp<Api, Context>;
/**
* create a zodios router based on the given api and express router
* @param api - api definition
* @param options - options to configure the router
* @returns
*/
declare function zodiosRouter<Api extends ZodiosEndpointDefinitions, Context extends ZodObject<any> = ZodObject<any>>(api: Narrow<Api>, options?: RouterOptions & ZodiosRouterOptions<Context>): ZodiosRouter<Api, Context>;
/**
* create a zodios app for nextjs
* @param options - options to configure the app
* @returns - a zodios app
*/
declare function zodiosNextApp<Api extends ZodiosEndpointDefinitions = any, Context extends ZodObject<any> = ZodObject<any>>(api?: Narrow<Api>, options?: ZodiosAppOptions<Context>): ZodiosApp<Api, Context>;
declare class ZodiosContext<Context extends ZodObject<any>> {
context?: Context | undefined;
constructor(context?: Context | undefined);
app<Api extends ZodiosEndpointDefinitions = any>(api?: Narrow<Api>, options?: ZodiosAppOptions<Context>): ZodiosApp<Api, Context>;
nextApp<Api extends ZodiosEndpointDefinitions = any>(api?: Narrow<Api>, options?: ZodiosAppOptions<Context>): ZodiosApp<Api, Context>;
router<Api extends ZodiosEndpointDefinitions>(api: Narrow<Api>, options?: RouterOptions & ZodiosRouterOptions<Context>): ZodiosRouter<Api, Context>;
}
declare function zodiosContext<Context extends ZodObject<any> = ZodObject<any>>(context?: Context): ZodiosContext<Context>;
type MapPrefixPath<T extends readonly unknown[], PrefixValue extends string, ACC extends unknown[] = []> = T extends readonly [infer Head, ...infer Tail] ? MapPrefixPath<Tail, PrefixValue, [
...ACC,
{
[K in keyof Head]: K extends "path" ? Head[K] extends string ? `${PrefixValue}${Head[K]}` : Head[K] : Head[K];
}
]> : ACC;
declare function prefixApi<Prefix extends string, Api extends readonly any[]>(prefix: Prefix, api: Api): MapPrefixPath<Api, Prefix, []>;
export { WithZodiosContext, ZodiosApp, ZodiosAppOptions, ZodiosContext, ZodiosHandler, ZodiosHandlers, ZodiosRequestHandler, ZodiosRouter, ZodiosRouterContextRequestHandler, ZodiosRouterOptions, ZodiosSuccessCodes, ZodiosUse, ZodiosValidationOptions, prefixApi, zodiosApp, zodiosContext, zodiosNextApp, zodiosRouter };