@minisylar/express-typed-router
Version:
A strongly-typed Express router with Zod validation and automatic type inference for params, body, query, and middleware
321 lines (319 loc) • 27.6 kB
TypeScript
import express, { NextFunction, Request, Response } from "express";
import * as z3 from "zod/v3";
import * as z4 from "zod/v4/core";
//#region src/zod-router.d.ts
type AnyZodType = z3.ZodTypeAny | z4.$ZodType;
declare function isZod4Schema(schema: AnyZodType): schema is z4.$ZodType;
type InferOutput<T> = T extends z4.$ZodType ? z4.output<T> : T extends z3.ZodTypeAny ? z3.output<T> : T extends {
_output: infer O;
} ? O : T extends {
_type: infer O;
} ? O : unknown;
type InferInput<T> = T extends z4.$ZodType ? z4.input<T> : T extends z3.ZodTypeAny ? z3.input<T> : T extends {
_input: infer I;
} ? I : T extends {
_type: infer I;
} ? I : unknown;
declare function parseSchema<T extends AnyZodType>(schema: T, data: unknown): InferOutput<T>;
type SafeParseResult<T extends AnyZodType> = T extends z4.$ZodType ? ReturnType<typeof z4.safeParse<T>> : T extends z3.ZodTypeAny ? z3.SafeParseReturnType<z3.input<T>, z3.output<T>> : never;
declare function safeParseSchema<T extends AnyZodType>(schema: T, data: unknown): SafeParseResult<T>;
declare function isZodError(error: unknown): error is z3.ZodError;
/**
* Extract route parameters from Express.js route patterns.
*
* Supports all Express.js routing patterns:
* - Named parameters: /users/:userId → { userId: string }
* - Multiple parameters: /users/:userId/books/:bookId → { userId: string; bookId: string }
* - Parameters with separators: /flights/:from-:to → { from: string; to: string }
* - Dot notation: /plantae/:genus.:species → { genus: string; species: string }
* - Regex constraints: /user/:id(\\d+) → { id: string }
* - Optional parameters: /posts/:year/:month? → { year: string; month?: string }
* - Wildcard parameters: /files/* → { "0": string }
* - Multiple wildcards: /a/star/b/star → { "0": string; "1": string }
*/
type ExtractRouteParams<Path extends string> = string extends Path ? Record<string, string> : ExtractParams<Path>;
/**
* Main parameter extraction logic - enhanced for Express 5 support with recursion depth limit
*/
type ExtractParams<Path extends string> = Path extends `${infer Before}{${infer OptionalContent}}${infer After}` ? ExtractOptionalSegment<OptionalContent> & ExtractParams<`${Before}${After}`> : Path extends `${infer _Before}:${infer Rest}` ? ExtractSingleParam<Rest> & ExtractParams<RemoveFirstParam<Path>> : Path extends `${infer _Before}*${infer After}` ? { [K in CountWildcards<_Before, "0">]: string } & ExtractParams<After> : {};
/**
* Extract parameters from Express 5 optional segments in braces
* Handles patterns like {/:param}, {.:ext}, {/optional/:param}
*/
type ExtractOptionalSegment<Content extends string> = Content extends `/:${infer Rest}` ? ExtractOptionalParam<Rest> : Content extends `.:${infer Rest}` ? ExtractOptionalParam<Rest> : Content extends `${infer _Path}:${infer Rest}` ? ExtractOptionalParam<Rest> : {};
/**
* Extract a single optional parameter from brace content
*/
type ExtractOptionalParam<Rest extends string> = Rest extends `${infer ParamName}/${infer _After}` ? { [K in ParamName]?: string } : Rest extends `${infer ParamName}-${infer _After}` ? { [K in ParamName]?: string } : Rest extends `${infer ParamName}.${infer _After}` ? { [K in ParamName]?: string } : Rest extends `${infer ParamName}` ? { [K in ParamName]?: string } : {};
/**
* Extract a single parameter name from the rest of the path
* Enhanced to handle Express 5 patterns and optional parameters correctly
* Special handling for consecutive parameters like :from-:to
* Order matters: regex constraints must be handled before repeating parameters
*/
type ExtractSingleParam<Rest extends string> = Rest extends `${infer ParamName}(${infer _Constraint})${infer _After}` ? { [K in ParamName]: string } : Rest extends `${infer ParamName}-:${infer _NextParam}` ? { [K in ParamName]: string } : Rest extends `${infer ParamName}.:${infer _NextParam}` ? { [K in ParamName]: string } : Rest extends `${infer ParamName}?/${infer _After}` ? { [K in ParamName]?: string } : Rest extends `${infer ParamName}?-${infer _After}` ? { [K in ParamName]?: string } : Rest extends `${infer ParamName}?.${infer _After}` ? { [K in ParamName]?: string } : Rest extends `${infer ParamName}?#${infer _After}` ? { [K in ParamName]?: string } : Rest extends `${infer ParamName}?:${infer _After}` ? { [K in ParamName]?: string } : Rest extends `${infer ParamName}/${infer _After}` ? { [K in ParamName]: string } : Rest extends `${infer ParamName}-${infer _After}` ? { [K in ParamName]: string } : Rest extends `${infer ParamName}.${infer _After}` ? { [K in ParamName]: string } : Rest extends `${infer ParamName}#${infer _After}` ? { [K in ParamName]: string } : Rest extends `${infer ParamName}:${infer _After}` ? { [K in ParamName]: string } : Rest extends `${infer ParamName}+${infer _After}` ? { [K in ParamName]: string[] } : Rest extends `${infer ParamName}*${infer _After}` ? { [K in ParamName]?: string[] } : Rest extends `${infer ParamName}?${infer _After}` ? { [K in ParamName]?: string } : Rest extends string ? Rest extends "" ? {} : Rest extends `${infer ParamName}?` ? { [K in ParamName]?: string } : Rest extends `${infer ParamName}+` ? { [K in ParamName]: string[] } : Rest extends `${infer ParamName}*` ? { [K in ParamName]?: string[] } : { [K in Rest]: string } : {};
/**
* Remove the first parameter from path to continue parsing
* Enhanced to handle Express 5 patterns and optional parameters
* Handles patterns like :from-:to by removing just :from and keeping -:to
* Order matters: regex constraints must be handled before repeating parameters
*/
type RemoveFirstParam<Path extends string> = Path extends `${infer Before}:${infer Rest}` ? Rest extends `${infer _ParamName}(${infer _Constraint})${infer After}` ? `${Before}${After}` : Rest extends `${infer _ParamName}-:${infer After}` ? `${Before}-:${After}` : Rest extends `${infer _ParamName}.:${infer After}` ? `${Before}.:${After}` : Rest extends `${infer _ParamName}?/${infer After}` ? `${Before}/${After}` : Rest extends `${infer _ParamName}?-${infer After}` ? `${Before}${After}` : Rest extends `${infer _ParamName}?.${infer After}` ? `${Before}${After}` : Rest extends `${infer _ParamName}?#${infer After}` ? `${Before}${After}` : Rest extends `${infer _ParamName}?:${infer After}` ? `${Before}:${After}` : Rest extends `${infer _ParamName}/${infer After}` ? `${Before}/${After}` : Rest extends `${infer _ParamName}-${infer After}` ? `${Before}${After}` : Rest extends `${infer _ParamName}.${infer After}` ? `${Before}${After}` : Rest extends `${infer _ParamName}#${infer After}` ? `${Before}${After}` : Rest extends `${infer _ParamName}:${infer After}` ? `${Before}:${After}` : Rest extends `${infer _ParamName}+${infer After}` ? `${Before}${After}` : Rest extends `${infer _ParamName}*${infer After}` ? `${Before}${After}` : Rest extends `${infer _ParamName}?${infer After}` ? `${Before}${After}` : Before : Path;
/**
* Count wildcards to assign proper numeric indices with recursion depth limit
*/
type CountWildcards<Path extends string, Count extends string = "0"> = Path extends `${infer _Before}*${infer Rest}` ? CountWildcards<Rest, IncrementWildcard<Count>> : Count;
/**
* Helper type to increment wildcard count as string
*/
type IncrementWildcard<T extends string> = T extends "0" ? "1" : T extends "1" ? "2" : T extends "2" ? "3" : T extends "3" ? "4" : T extends "4" ? "5" : T extends "5" ? "6" : T extends "6" ? "7" : T extends "7" ? "8" : T extends "8" ? "9" : "10";
/**
* Express middleware that adds custom properties to the request object and/or response locals.
*
* @template TReq - The shape of the properties added to the request object.
* @template TLocals - The shape of the properties added to response.locals.
* @param req - The Express request object, extended with TReq.
* @param res - The Express response object with typed locals.
* @param next - The next middleware function.
*/
type TypedMiddleware<TReq extends Record<string, any> = {}, TLocals extends Record<string, any> = {}> = (req: Request & TReq, res: Response<any, TLocals>, next: NextFunction) => void | Promise<void>;
/**
* Simplified TypedMiddleware for request-only extensions (backward compatibility)
*/
type RequestOnlyMiddleware<TReq extends Record<string, any>> = TypedMiddleware<TReq, {}>;
/**
* Simplified TypedMiddleware for response locals-only extensions
*/
type LocalsOnlyMiddleware<TLocals extends Record<string, any>> = TypedMiddleware<{}, TLocals>;
type InferMiddlewareProps<T extends readonly TypedMiddleware<any, any>[]> = T extends readonly [infer First, ...infer Rest] ? First extends TypedMiddleware<infer FirstReq, any> ? Rest extends readonly TypedMiddleware<any, any>[] ? FirstReq & InferMiddlewareProps<Rest> : FirstReq : {} : {};
type InferMiddlewareLocals<T extends readonly TypedMiddleware<any, any>[]> = T extends readonly [infer First, ...infer Rest] ? First extends TypedMiddleware<any, infer FirstLocals> ? Rest extends readonly TypedMiddleware<any, any>[] ? FirstLocals & InferMiddlewareLocals<Rest> : FirstLocals : {} : {};
type ZodRequest<Path extends string = string, BodySchema extends AnyZodType | unknown = unknown, QuerySchema extends AnyZodType | unknown = unknown, MiddlewareProps extends Record<string, any> = {}> = Omit<Request, "params" | "query" | "body"> & {
params: ExtractRouteParams<Path>;
body: BodySchema extends AnyZodType ? InferOutput<BodySchema> : unknown;
query: QuerySchema extends AnyZodType ? InferOutput<QuerySchema> : unknown;
} & MiddlewareProps;
type ZodRouteHandler<Path extends string = string, BodySchema extends AnyZodType | unknown = unknown, QuerySchema extends AnyZodType | unknown = unknown, MiddlewareProps extends Record<string, any> = {}, ResponseLocals extends Record<string, any> = {}> = (req: ZodRequest<Path, BodySchema, QuerySchema, MiddlewareProps>, res: Response<any, ResponseLocals>, next?: NextFunction) => void | Promise<void> | Response | Promise<Response>;
/**
* Options for defining a typed route, including schemas and middleware.
*
* @template BodySchema - Zod schema for request body validation.
* @template QuerySchema - Zod schema for query parameter validation.
* @property bodySchema - Optional Zod schema for validating the request body.
* @property querySchema - Optional Zod schema for validating the query string.
* @property middleware - Optional array of TypedMiddleware for this route.
*/
interface RouteOptions<BodySchema extends AnyZodType | unknown = unknown, QuerySchema extends AnyZodType | unknown = unknown> {
bodySchema?: BodySchema;
querySchema?: QuerySchema;
middleware?: TypedMiddleware<any, any>[];
}
type HttpMethod = "get" | "post" | "put" | "delete" | "patch" | "options" | "head" | "all";
declare class TypedRouter<RouterMiddlewareProps extends Record<string, any> = {}, RouterLocals extends Record<string, any> = {}> {
private router;
constructor();
/**
* Add typed middleware that extends the request with additional properties
* and/or adds properties to response.locals
*/ /**
* Add typed middleware to the router.
* This middleware will apply to all routes defined after this call.
*
* @template TReq - Type extensions for the request object
* @template TLocals - Type extensions for response.locals
* @param middleware - The typed middleware function
* @returns A new router instance with updated types
*/
useMiddleware<TReq extends Record<string, any> = {}, TLocals extends Record<string, any> = {}>(middleware: TypedMiddleware<TReq, TLocals>): TypedRouter<RouterMiddlewareProps & TReq, RouterLocals & TLocals>;
/**
* Get the underlying Express router
*/
getRouter(): express.Router;
get<Path extends string>(path: Path, handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
get<Path extends string, BodySchema extends AnyZodType | unknown, QuerySchema extends AnyZodType | unknown>(path: Path, options: RouteOptions<BodySchema, QuerySchema>, handler: ZodRouteHandler<Path, BodySchema, QuerySchema, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
get<Path extends string, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
middleware: Middleware;
}, handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
get<Path extends string, BodySchema extends AnyZodType | unknown, QuerySchema extends AnyZodType | unknown, M extends TypedMiddleware<any, any>[]>(path: Path, options: RouteOptions<BodySchema, QuerySchema> & {
middleware: [...M];
},
// Using tuple spread pattern
handler: ZodRouteHandler<Path, BodySchema, QuerySchema, RouterMiddlewareProps & InferMiddlewareProps<readonly [...M]>,
// Make it readonly for type inference
// Make it readonly for type inference
RouterLocals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
post<Path extends string, BodySchema extends AnyZodType, QuerySchema extends AnyZodType | unknown, M extends TypedMiddleware<any, any>[]>(path: Path, options: {
bodySchema: BodySchema;
querySchema?: QuerySchema;
middleware: [...M];
}, handler: ZodRouteHandler<Path, BodySchema, QuerySchema, RouterMiddlewareProps & InferMiddlewareProps<readonly [...M]>,
// Make it readonly for type inference
// Make it readonly for type inference
RouterLocals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
post<Path extends string, BodySchema extends AnyZodType, M extends TypedMiddleware<any, any>[]>(path: Path, options: {
bodySchema: BodySchema;
middleware: [...M];
},
// Using tuple spread pattern
handler: ZodRouteHandler<Path, BodySchema, unknown, RouterMiddlewareProps & InferMiddlewareProps<readonly [...M]>,
// Make it readonly for type inference
// Make it readonly for type inference
RouterLocals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
post<Path extends string, M extends TypedMiddleware<any, any>[]>(path: Path, options: {
middleware: [...M];
},
// Using tuple spread pattern
handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps & InferMiddlewareProps<readonly [...M]>,
// Make it readonly for type inference
// Make it readonly for type inference
RouterLocals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
post<Path extends string, BodySchema extends AnyZodType | unknown, QuerySchema extends AnyZodType | unknown>(path: Path, options: RouteOptions<BodySchema, QuerySchema>, handler: ZodRouteHandler<Path, BodySchema, QuerySchema, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
post<Path extends string>(path: Path, handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
put<Path extends string, BodySchema extends AnyZodType, QuerySchema extends AnyZodType | unknown, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
bodySchema: BodySchema;
querySchema?: QuerySchema;
middleware: Middleware;
}, handler: ZodRouteHandler<Path, BodySchema, QuerySchema, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
put<Path extends string, BodySchema extends AnyZodType, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
bodySchema: BodySchema;
middleware: Middleware;
}, handler: ZodRouteHandler<Path, BodySchema, unknown, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
put<Path extends string, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
middleware: Middleware;
}, handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
put<Path extends string, BodySchema extends AnyZodType | unknown, QuerySchema extends AnyZodType | unknown>(path: Path, options: RouteOptions<BodySchema, QuerySchema>, handler: ZodRouteHandler<Path, BodySchema, QuerySchema, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
put<Path extends string>(path: Path, handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
patch<Path extends string, BodySchema extends AnyZodType, QuerySchema extends AnyZodType | unknown, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
bodySchema: BodySchema;
querySchema?: QuerySchema;
middleware: Middleware;
}, handler: ZodRouteHandler<Path, BodySchema, QuerySchema, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
patch<Path extends string, BodySchema extends AnyZodType, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
bodySchema: BodySchema;
middleware: Middleware;
}, handler: ZodRouteHandler<Path, BodySchema, unknown, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
patch<Path extends string, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
middleware: Middleware;
}, handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
patch<Path extends string, BodySchema extends AnyZodType | unknown, QuerySchema extends AnyZodType | unknown>(path: Path, options: RouteOptions<BodySchema, QuerySchema>, handler: ZodRouteHandler<Path, BodySchema, QuerySchema, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
patch<Path extends string>(path: Path, handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
delete<Path extends string, QuerySchema extends AnyZodType | unknown, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
querySchema: QuerySchema;
middleware: Middleware;
}, handler: ZodRouteHandler<Path, unknown, QuerySchema, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
delete<Path extends string, QuerySchema extends AnyZodType | unknown>(path: Path, options: {
querySchema: QuerySchema;
}, handler: ZodRouteHandler<Path, unknown, QuerySchema, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
delete<Path extends string, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
middleware: Middleware;
}, handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
delete<Path extends string>(path: Path, handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
options<Path extends string, QuerySchema extends AnyZodType | unknown, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
querySchema: QuerySchema;
middleware: Middleware;
}, handler: ZodRouteHandler<Path, unknown, QuerySchema, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
options<Path extends string, QuerySchema extends AnyZodType | unknown>(path: Path, options: {
querySchema: QuerySchema;
}, handler: ZodRouteHandler<Path, unknown, QuerySchema, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
options<Path extends string, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
middleware: Middleware;
}, handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
options<Path extends string>(path: Path, handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
head<Path extends string, QuerySchema extends AnyZodType | unknown, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
querySchema: QuerySchema;
middleware: Middleware;
}, handler: ZodRouteHandler<Path, unknown, QuerySchema, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
head<Path extends string, QuerySchema extends AnyZodType | unknown>(path: Path, options: {
querySchema: QuerySchema;
}, handler: ZodRouteHandler<Path, unknown, QuerySchema, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
head<Path extends string, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
middleware: Middleware;
}, handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
head<Path extends string>(path: Path, handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
all<Path extends string, BodySchema extends AnyZodType, QuerySchema extends AnyZodType | unknown, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
bodySchema: BodySchema;
querySchema?: QuerySchema;
middleware: Middleware;
}, handler: ZodRouteHandler<Path, BodySchema, QuerySchema, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
all<Path extends string, BodySchema extends AnyZodType, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
bodySchema: BodySchema;
middleware: Middleware;
}, handler: ZodRouteHandler<Path, BodySchema, unknown, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
all<Path extends string, QuerySchema extends AnyZodType | unknown, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
querySchema: QuerySchema;
middleware: Middleware;
}, handler: ZodRouteHandler<Path, unknown, QuerySchema, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
all<Path extends string, BodySchema extends AnyZodType | unknown, QuerySchema extends AnyZodType | unknown>(path: Path, options: RouteOptions<BodySchema, QuerySchema>, handler: ZodRouteHandler<Path, BodySchema, QuerySchema, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
all<Path extends string, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
middleware: Middleware;
}, handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps & InferMiddlewareProps<Middleware>, RouterLocals & InferMiddlewareLocals<Middleware>>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
all<Path extends string>(path: Path, handler: ZodRouteHandler<Path, unknown, unknown, RouterMiddlewareProps, RouterLocals>): TypedRouter<RouterMiddlewareProps, RouterLocals>;
private registerRoute;
private createBodyValidationMiddleware;
private createQueryValidationMiddleware;
}
/**
* Create a new strongly-typed Express router instance.
*
* This is the simplest way to get started with @minisylar/express-typed-router.
*
* @example
* import { createTypedRouter } from '@minisylar/express-typed-router';
*
* // Create a router and add a typed GET route
* const router = createTypedRouter();
* router.get('/hello/:name', (req, res) => {
* // req.params.name is typed as string
* res.json({ message: `Hello, ${req.params.name}!` });
* });
*
* // Use with Express
* import express from 'express';
* const app = express();
* app.use('/api', router.getRouter());
*/
declare function createTypedRouter<RouterMiddlewareProps extends Record<string, any> = {}, RouterLocals extends Record<string, any> = {}>(): TypedRouter<RouterMiddlewareProps, RouterLocals>;
/**
* Configuration options for createTypedRouterWithConfig.
*
* @property validateInput - (Future) Whether to enable global input validation.
* @property errorHandler - Optional global error handler middleware for the router.
*/
interface RouterConfig {
validateInput?: boolean;
errorHandler?: (error: any, req: Request, res: Response, next: NextFunction) => void;
}
/**
* Create a new typed router with optional configuration.
*
* Use this if you want to add a global error handler or future global options.
*
* @param config - Optional configuration for the router (e.g. error handler).
* @returns A new TypedRouter instance.
*
* @example
* import { createTypedRouterWithConfig } from '@minisylar/express-typed-router';
*
* const router = createTypedRouterWithConfig({
* errorHandler: (err, req, res, next) => {
* res.status(500).json({ error: 'Something went wrong', details: err });
* }
* });
*/
declare function createTypedRouterWithConfig<RouterMiddlewareProps extends Record<string, any> = {}, RouterLocals extends Record<string, any> = {}>(config?: RouterConfig): TypedRouter<RouterMiddlewareProps, RouterLocals>;
/**
* Create a new typed router with pre-configured middleware.
*
* This is useful for setting up router-level middleware in a single call.
*
* @param middleware - One or more TypedMiddleware functions to apply to all routes.
* @returns A new TypedRouter instance with the middleware applied.
*
* @example
* import { createTypedRouterWithMiddleware } from '@minisylar/express-typed-router';
*
* const router = createTypedRouterWithMiddleware(authMiddleware, loggingMiddleware);
*/
declare function createTypedRouterWithMiddleware<T extends Record<string, any>>(...middleware: TypedMiddleware<any, any>[]): TypedRouter<T>;
//#endregion
export { AnyZodType, ExtractRouteParams, HttpMethod, InferInput, InferOutput, LocalsOnlyMiddleware, RequestOnlyMiddleware, RouteOptions, RouterConfig, SafeParseResult, TypedMiddleware, ZodRequest, ZodRouteHandler, createTypedRouter, createTypedRouterWithConfig, createTypedRouterWithMiddleware, isZod4Schema, isZodError, parseSchema, safeParseSchema };
//# sourceMappingURL=zod-router.d.ts.map