import express, { NextFunction, Request, Response } from "express";
import { StandardSchemaV1 } from "@standard-schema/spec";

//#region src/schema-router.d.ts
type AnyStandardSchema = StandardSchemaV1<any, any>;
type InferOutput<T> = T extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<T> : unknown;
type InferInput<T> = T extends StandardSchemaV1 ? StandardSchemaV1.InferInput<T> : unknown;
type InferFromSafeParse<T> = T extends {
  safeParse: (...args: any[]) => infer R;
} ? R extends {
  success: true;
  data: infer O;
} ? O : R extends Promise<infer PR> ? PR extends {
  success: true;
  data: infer O;
} ? O : never : never : T extends {
  parse: (...args: any[]) => infer R;
} ? R : never;
type InferSchemaOutput<T> = T extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<T> : InferFromSafeParse<T>;
declare function parseSchema<T>(schema: T, data: unknown): InferSchemaOutput<T>;
type SafeParseResult<T> = StandardSchemaV1.Result<InferSchemaOutput<T>> | {
  value: InferSchemaOutput<T>;
} | {
  issues: any[];
} | Promise<StandardSchemaV1.Result<InferSchemaOutput<T>> | {
  value: InferSchemaOutput<T>;
} | {
  issues: any[];
}>;
declare function safeParseSchema<T>(schema: T, data: unknown): SafeParseResult<T>;
declare function isSchemaError(error: unknown): error is {
  issues: any[];
};
/**
 * 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 Name}/${infer After}` ? Name extends "" ? { [K in CountWildcards<_Before, "0">]: string } & ExtractParams<`/${After}`> : { [K in Name]: string[] } & ExtractParams<`/${After}`> : Path extends `${infer _Before}*${infer Name}-${infer After}` ? Name extends "" ? { [K in CountWildcards<_Before, "0">]: string } & ExtractParams<`-${After}`> : { [K in Name]: string[] } & ExtractParams<`-${After}`> : Path extends `${infer _Before}*${infer Name}.${infer After}` ? Name extends "" ? { [K in CountWildcards<_Before, "0">]: string } & ExtractParams<`.${After}`> : { [K in Name]: string[] } & ExtractParams<`.${After}`> : Path extends `${infer _Before}*${infer Name}#${infer After}` ? Name extends "" ? { [K in CountWildcards<_Before, "0">]: string } & ExtractParams<`#${After}`> : { [K in Name]: string[] } & ExtractParams<`#${After}`> : Path extends `${infer _Before}*${infer Name}:${infer After}` ? Name extends "" ? { [K in CountWildcards<_Before, "0">]: string } & ExtractParams<`:${After}`> : { [K in Name]: string[] } & ExtractParams<`:${After}`> : Path extends `${infer _Before}*${infer Name}` ? Name extends "" ? { [K in CountWildcards<_Before, "0">]: string } & ExtractParams<``> : { [K in Name]: string[] } & ExtractParams<``> : 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 Name}` ? Name extends "" ? {} : { [K in Name]?: string[] } : Content extends `/${infer Rest}` ? Rest extends `*${infer Name}` ? Name extends "" ? {} : { [K in Name]?: string[] } : Rest extends `:${infer R}` ? ExtractOptionalParam<R> : {} : 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 SchemaRequest<Path extends string = string, BodySchema extends AnyStandardSchema | unknown = unknown, QuerySchema extends AnyStandardSchema | unknown = unknown, MiddlewareProps extends Record<string, any> = {}> = Omit<Request, "params" | "query" | "body"> & {
  params: ExtractRouteParams<Path>;
  body: BodySchema extends unknown ? InferSchemaOutput<BodySchema> : unknown;
  query: QuerySchema extends unknown ? InferSchemaOutput<QuerySchema> : unknown;
} & MiddlewareProps;
type SchemaRouteHandler<Path extends string = string, BodySchema extends AnyStandardSchema | unknown = unknown, QuerySchema extends AnyStandardSchema | unknown = unknown, MiddlewareProps extends Record<string, any> = {}, ResponseLocals extends Record<string, any> = {}> = (req: SchemaRequest<Path, BodySchema, QuerySchema, MiddlewareProps>, res: Response<any, ResponseLocals>, next?: NextFunction) => void | undefined | Promise<void | undefined> | Response | Promise<Response> | Promise<Response | undefined>;
/**
 * Options for defining a typed route, including schemas and middleware.
 *
 * @template BodySchema - Schema for request body validation.
 * @template QuerySchema - Schema for query parameter validation.
 * @property bodySchema - Optional schema for validating the request body.
 * @property querySchema - Optional schema for validating the query string.
 * @property middleware - Optional array of TypedMiddleware for this route.
 */
interface RouteOptions<BodySchema extends AnyStandardSchema | unknown = unknown, QuerySchema extends AnyStandardSchema | unknown = unknown> {
  bodySchema?: BodySchema;
  querySchema?: QuerySchema;
  middleware?: TypedMiddleware<any, any>[];
  tags?: string[];
  description?: string;
  summary?: string;
  deprecated?: boolean;
  responseSchema?: AnyStandardSchema;
  /** Exclude this route from the generated OpenAPI spec entirely. */
  hidden?: boolean;
}
type DocMeta = Pick<RouteOptions<unknown, unknown>, "tags" | "summary" | "description" | "deprecated" | "responseSchema" | "hidden">;
type HttpMethod = "get" | "post" | "put" | "delete" | "patch" | "options" | "head" | "all";
interface DocsOptions {
  title?: string;
  version?: string;
  description?: string;
  servers?: Array<{
    url: string;
    description?: string;
  }>;
  /**
   * Override the Scalar CDN URL. Use this to pin a specific version or
   * self-host the Scalar bundle to avoid the external CDN dependency.
   * @default "https://cdn.jsdelivr.net/npm/@scalar/api-reference"
   */
  cdnUrl?: string;
  /**
   * File path to write the OpenAPI spec to whenever it is generated.
   * Enables `openapi-typescript --watch` in development — the tool watches
   * the file and regenerates your client types automatically as routes change.
   *
   * The file is written once at startup, so it contains route **schemas only**
   * — never captured response examples. This keeps real response data (which
   * may include PII) out of any file you might commit or share.
   *
   * @example
   * // docs options
   * { specOutputPath: './openapi.json' }
   *
   * // then in a separate terminal (or via concurrently in package.json):
   * // npx openapi-typescript ./openapi.json -o ./src/client.d.ts --watch
   */
  specOutputPath?: string;
  /**
   * Learn response shapes from live traffic and add them to the docs. The
   * library observes real responses and **infers a JSON Schema** from them
   * (field names, types, nullability, required vs optional) — so the docs and
   * generated client types reflect what your API actually returns.
   *
   * Modes:
   * - `true` (default) — **redacted**: infer the schema only. Real values are
   *   discarded at capture time, so no user data is ever stored or shown. Safe
   *   to expose.
   * - `"live"` — infer the schema **and** attach a real captured response as an
   *   example. ⚠️ Examples contain actual data (emails, tokens, IDs). Only use
   *   for trusted/internal docs.
   * - `false` — don't observe responses at all.
   *
   * Use the per-route `hidden: true` option to exclude individual sensitive
   * routes regardless of mode.
   *
   * @default true
   */
  sampleResponses?: boolean | "live";
}
interface RouteMetadata {
  method: HttpMethod;
  path: string;
  bodySchema?: AnyStandardSchema;
  querySchema?: AnyStandardSchema;
  tags?: string[];
  description?: string;
  summary?: string;
  deprecated?: boolean;
  responseSchema?: AnyStandardSchema;
  hidden?: boolean;
  responseSamples: Map<number, {
    schema: Record<string, any>;
    example?: unknown;
  }>;
}
declare function inferJsonSchema(value: unknown): Record<string, any>;
/**
 * Extra properties that middleware has added to the Express `req` object.
 *
 * Starts as `{}` (nothing added yet) and widens automatically with every
 * `.useMiddleware()` call. After `router.useMiddleware(authMiddleware)` where
 * `authMiddleware` contributes `{ userId: string }`, this becomes `{ userId: string }`.
 *
 * You will see this type in router hover text — it is the accumulating "req additions" slot.
 */
type AdditionalReqProps = {};
/**
 * Extra properties that middleware has added to `res.locals`.
 *
 * Starts as `{}` and widens automatically with every `.useMiddleware()` call,
 * mirroring the `TLocals` parameter of each `TypedMiddleware` you attach.
 */
type AdditionalLocals = {};
/**
 * A strongly-typed Express router. The two generic params accumulate as
 * middleware is added via `.useMiddleware()`.
 *
 * @typeParam Req    - Extra properties on `req` contributed by middleware. Starts as {@link AdditionalReqProps}.
 * @typeParam Locals - Extra properties on `res.locals` contributed by middleware. Starts as {@link AdditionalLocals}.
 */
declare class TypedRouter<Req extends Record<string, any> = AdditionalReqProps, Locals extends Record<string, any> = AdditionalLocals> {
  private router;
  private routes;
  private mountedRouters;
  private sampleMode;
  private scheduleSpecWrite?;
  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<Req & TReq, Locals & TLocals>;
  /**
   * Get the underlying Express router, typed as a RequestHandler so it can be
   * passed directly to app.use() without a cast in Express 5.
   */
  getRouter(): express.Router & express.RequestHandler;
  /**
   * Mount middleware or a sub-router at an optional path prefix.
   *
   * When passed the result of another TypedRouter's .getRouter(), it is
   * automatically recognised and tracked for .docs() — no extra wiring needed.
   *
   * @example
   * // v1.routes.ts — pass TypedRouter instances directly, no .getRouter() needed
   * export const v1Routes = createTypedRouter()
   *
   * v1Routes.use('/products', productRoutes)   // tracked ✓
   * v1Routes.use('/profile',  profileRoutes)   // tracked ✓
   * v1Routes.use('/',         callbackRouter)  // plain Express, also works
   *
   * app.use('/v1', v1Routes.getRouter())
   * app.use('/docs', v1Routes.docs({ title: 'My API' }))    // just works
   */
  use(path: string, ...handlers: Array<express.RequestHandler | express.Router | TypedRouter<any, any>>): TypedRouter<Req, Locals>;
  use(...handlers: Array<express.RequestHandler | express.Router | TypedRouter<any, any>>): TypedRouter<Req, Locals>;
  /**
   * Mount a TypedRouter at a path prefix, registering it both on the Express
   * router and in the docs registry so .docs() picks it up automatically.
   *
   * @example
   * const v1 = createTypedRouter()
   *   .mount('/products', productRoutes)
   *   .mount('/profile',  profileRoutes)
   *   .mount('/supplier', supplierRoutes)
   *
   * app.use('/v1', v1.getRouter())
   * app.use('/docs', v1.docs({ title: 'My API' }))
   */
  mount(prefix: string, router: TypedRouter<any, any>): TypedRouter<Req, Locals>;
  mount(router: TypedRouter<any, any>): TypedRouter<Req, Locals>;
  /**
   * Returns the collected route metadata for this router, including all
   * sub-routers registered via .mount() with their prefixes applied.
   * Used internally by .docs() and by createDocs() for multi-router merging.
   */
  getRouteMetadata(): RouteMetadata[];
  /**
   * Turn on response observation for this router and every router mounted under
   * it. Called by .docs() and createDocs() so it happens only when docs are
   * actually generated. The visited set guards against mount cycles.
   * @internal Public only so createDocs() can reach it; not part of the API.
   */
  enableSampling(mode?: "redacted" | "live", writer?: () => void, visited?: Set<TypedRouter<any, any>>): void;
  /**
   * Record a sub-router for docs, de-duplicating identical (prefix, router)
   * pairs and propagating the sample mode if docs were already requested.
   */
  private trackMounted;
  /**
   * Seed in-memory response schemas from a previously written spec, so a server
   * restart doesn't reset the docs/spec file to empty. Only fills statuses we
   * haven't already observed this process, and never overwrites fresher data.
   * @internal
   */
  hydrateResponses(spec: any, prefix?: string, visited?: Set<TypedRouter<any, any>>): void;
  /**
   * Returns an Express router that serves OpenAPI docs.
   * Mount it anywhere on your app — routes are auto-discovered.
   *
   * @example
   * app.use('/docs', router.docs({ title: 'My API', version: '1.0.0' }))
   * // GET /docs           → Scalar UI
   * // GET /docs/openapi.json → raw OpenAPI 3.1 spec
   */
  docs(options?: DocsOptions): express.Router & express.RequestHandler;
  get<Path extends string>(path: Path, handler: SchemaRouteHandler<Path, unknown, unknown, Req, Locals>): TypedRouter<Req, Locals>;
  get<Path extends string, BodySchema extends AnyStandardSchema | unknown, QuerySchema extends AnyStandardSchema | unknown>(path: Path, options: RouteOptions<BodySchema, QuerySchema>, handler: SchemaRouteHandler<Path, BodySchema, QuerySchema, Req, Locals>): TypedRouter<Req, Locals>;
  get<Path extends string, Middleware extends readonly TypedMiddleware<any, any>[]>(path: Path, options: {
    middleware: Middleware;
  }, handler: SchemaRouteHandler<Path, unknown, unknown, Req & InferMiddlewareProps<Middleware>, Locals & InferMiddlewareLocals<Middleware>>): TypedRouter<Req, Locals>;
  get<Path extends string, BodySchema extends AnyStandardSchema | unknown, QuerySchema extends AnyStandardSchema | unknown, M extends TypedMiddleware<any, any>[]>(path: Path, options: RouteOptions<BodySchema, QuerySchema> & {
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, BodySchema, QuerySchema, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  post<Path extends string, BodySchema extends AnyStandardSchema, QuerySchema extends AnyStandardSchema | unknown, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    bodySchema: BodySchema;
    querySchema?: QuerySchema;
    middleware: [...M];
  }, handler: SchemaRouteHandler<Path, BodySchema, QuerySchema, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  post<Path extends string, BodySchema extends AnyStandardSchema, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    bodySchema: BodySchema;
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, BodySchema, unknown, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  post<Path extends string, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, unknown, unknown, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  post<Path extends string, BodySchema extends AnyStandardSchema | unknown, QuerySchema extends AnyStandardSchema | unknown>(path: Path, options: RouteOptions<BodySchema, QuerySchema>, handler: SchemaRouteHandler<Path, BodySchema, QuerySchema, Req, Locals>): TypedRouter<Req, Locals>;
  post<Path extends string>(path: Path, handler: SchemaRouteHandler<Path, unknown, unknown, Req, Locals>): TypedRouter<Req, Locals>;
  put<Path extends string, BodySchema extends AnyStandardSchema, QuerySchema extends AnyStandardSchema | unknown, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    bodySchema: BodySchema;
    querySchema?: QuerySchema;
    middleware: [...M];
  }, handler: SchemaRouteHandler<Path, BodySchema, QuerySchema, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  put<Path extends string, BodySchema extends AnyStandardSchema, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    bodySchema: BodySchema;
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, BodySchema, unknown, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  put<Path extends string, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, unknown, unknown, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  put<Path extends string, BodySchema extends AnyStandardSchema | unknown, QuerySchema extends AnyStandardSchema | unknown>(path: Path, options: RouteOptions<BodySchema, QuerySchema>, handler: SchemaRouteHandler<Path, BodySchema, QuerySchema, Req, Locals>): TypedRouter<Req, Locals>;
  put<Path extends string>(path: Path, handler: SchemaRouteHandler<Path, unknown, unknown, Req, Locals>): TypedRouter<Req, Locals>;
  patch<Path extends string, BodySchema extends AnyStandardSchema, QuerySchema extends AnyStandardSchema | unknown, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    bodySchema: BodySchema;
    querySchema?: QuerySchema;
    middleware: [...M];
  }, handler: SchemaRouteHandler<Path, BodySchema, QuerySchema, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  patch<Path extends string, BodySchema extends AnyStandardSchema, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    bodySchema: BodySchema;
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, BodySchema, unknown, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  patch<Path extends string, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, unknown, unknown, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  patch<Path extends string, BodySchema extends AnyStandardSchema | unknown, QuerySchema extends AnyStandardSchema | unknown>(path: Path, options: RouteOptions<BodySchema, QuerySchema>, handler: SchemaRouteHandler<Path, BodySchema, QuerySchema, Req, Locals>): TypedRouter<Req, Locals>;
  patch<Path extends string>(path: Path, handler: SchemaRouteHandler<Path, unknown, unknown, Req, Locals>): TypedRouter<Req, Locals>;
  delete<Path extends string, QuerySchema extends AnyStandardSchema | unknown, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    querySchema: QuerySchema;
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, unknown, QuerySchema, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  delete<Path extends string, QuerySchema extends AnyStandardSchema | unknown>(path: Path, options: {
    querySchema: QuerySchema;
  }, handler: SchemaRouteHandler<Path, unknown, QuerySchema, Req, Locals>): TypedRouter<Req, Locals>;
  delete<Path extends string>(path: Path, options: DocMeta, handler: SchemaRouteHandler<Path, unknown, unknown, Req, Locals>): TypedRouter<Req, Locals>;
  delete<Path extends string, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, unknown, unknown, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  delete<Path extends string>(path: Path, handler: SchemaRouteHandler<Path, unknown, unknown, Req, Locals>): TypedRouter<Req, Locals>;
  options<Path extends string, QuerySchema extends AnyStandardSchema | unknown, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    querySchema: QuerySchema;
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, unknown, QuerySchema, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  options<Path extends string, QuerySchema extends AnyStandardSchema | unknown>(path: Path, options: {
    querySchema: QuerySchema;
  }, handler: SchemaRouteHandler<Path, unknown, QuerySchema, Req, Locals>): TypedRouter<Req, Locals>;
  options<Path extends string>(path: Path, options: DocMeta, handler: SchemaRouteHandler<Path, unknown, unknown, Req, Locals>): TypedRouter<Req, Locals>;
  options<Path extends string, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, unknown, unknown, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  options<Path extends string>(path: Path, handler: SchemaRouteHandler<Path, unknown, unknown, Req, Locals>): TypedRouter<Req, Locals>;
  head<Path extends string, QuerySchema extends AnyStandardSchema | unknown, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    querySchema: QuerySchema;
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, unknown, QuerySchema, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  head<Path extends string, QuerySchema extends AnyStandardSchema | unknown>(path: Path, options: {
    querySchema: QuerySchema;
  }, handler: SchemaRouteHandler<Path, unknown, QuerySchema, Req, Locals>): TypedRouter<Req, Locals>;
  head<Path extends string>(path: Path, options: DocMeta, handler: SchemaRouteHandler<Path, unknown, unknown, Req, Locals>): TypedRouter<Req, Locals>;
  head<Path extends string, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, unknown, unknown, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  head<Path extends string>(path: Path, handler: SchemaRouteHandler<Path, unknown, unknown, Req, Locals>): TypedRouter<Req, Locals>;
  all<Path extends string, BodySchema extends AnyStandardSchema, QuerySchema extends AnyStandardSchema | unknown, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    bodySchema: BodySchema;
    querySchema?: QuerySchema;
    middleware: [...M];
  }, handler: SchemaRouteHandler<Path, BodySchema, QuerySchema, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  all<Path extends string, BodySchema extends AnyStandardSchema, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    bodySchema: BodySchema;
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, BodySchema, unknown, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  all<Path extends string, QuerySchema extends AnyStandardSchema | unknown, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    querySchema: QuerySchema;
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, unknown, QuerySchema, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  all<Path extends string, BodySchema extends AnyStandardSchema | unknown, QuerySchema extends AnyStandardSchema | unknown>(path: Path, options: RouteOptions<BodySchema, QuerySchema>, handler: SchemaRouteHandler<Path, BodySchema, QuerySchema, Req, Locals>): TypedRouter<Req, Locals>;
  all<Path extends string, M extends TypedMiddleware<any, any>[]>(path: Path, options: DocMeta & {
    middleware: [...M];
  }, // Using tuple spread pattern
  handler: SchemaRouteHandler<Path, unknown, unknown, Req & InferMiddlewareProps<readonly [...M]>, // Make it readonly for type inference
  // Make it readonly for type inference
  Locals & InferMiddlewareLocals<readonly [...M]>>): TypedRouter<Req, Locals>;
  all<Path extends string>(path: Path, handler: SchemaRouteHandler<Path, unknown, unknown, Req, Locals>): TypedRouter<Req, Locals>;
  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<Req extends Record<string, any> = AdditionalReqProps, Locals extends Record<string, any> = AdditionalLocals>(): TypedRouter<Req, Locals>;
/**
 * 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<Req extends Record<string, any> = AdditionalReqProps, Locals extends Record<string, any> = AdditionalLocals>(config?: RouterConfig): TypedRouter<Req, Locals>;
/**
 * 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>;
/**
 * An entry for createDocs(). Either a bare TypedRouter (no prefix prepended)
 * or an object with an explicit prefix matching the mount point in app.use().
 *
 * @example
 * // Routes defined as /users/:id — mount prefix prepends /api
 * { prefix: '/api', router: usersRouter }
 *
 * // Routes already include the full path — no prefix needed
 * authRouter
 */
type RouterDocEntry = TypedRouter<any, any> | {
  prefix: string;
  router: TypedRouter<any, any>;
};
/**
 * Create a unified OpenAPI docs endpoint that merges routes from multiple
 * TypedRouter instances. Use this when routes are split across files.
 *
 * @example
 * // users.router.ts — routes like /users, /users/:id
 * export const usersRouter = createTypedRouter();
 *
 * // auth.router.ts — routes like /login, /logout
 * export const authRouter = createTypedRouter();
 *
 * // app.ts
 * app.use('/api', usersRouter.getRouter());
 * app.use('/api', authRouter.getRouter());
 * app.use('/docs', createDocs(
 *   [
 *     { prefix: '/api', router: usersRouter },
 *     { prefix: '/api', router: authRouter },
 *   ],
 *   { title: 'My API', version: '1.0.0' }
 * ));
 */
declare function createDocs(routers: RouterDocEntry | RouterDocEntry[], options?: DocsOptions): express.Router & express.RequestHandler;
//#endregion
export { AdditionalLocals, AdditionalReqProps, AnyStandardSchema, DocsOptions, ExtractRouteParams, HttpMethod, InferInput, InferOutput, InferSchemaOutput, LocalsOnlyMiddleware, RequestOnlyMiddleware, RouteOptions, RouterConfig, RouterDocEntry, SafeParseResult, SchemaRequest, SchemaRouteHandler, TypedMiddleware, TypedRouter, createDocs, createTypedRouter, createTypedRouterWithConfig, createTypedRouterWithMiddleware, inferJsonSchema, isSchemaError, parseSchema, safeParseSchema };