UNPKG

next-expose

Version:

A fluent, type-safe API routing and middleware layer for the Next.js App Router.

148 lines 8.69 kB
/** * Defines the supported HTTP methods for the router. */ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD'; /** * The core context object passed through the middleware pipeline. * It is progressively augmented by middleware functions. * @template TParams - The expected shape of the route's URL parameters (e.g., `{ id: string }`). */ export interface ExposeContext<TParams extends Record<string, any> = Record<string, string | string[] | undefined>> { /** The resolved URL parameters from the dynamic route, such as `[id]`. */ params: TParams; } /** * The `next` function passed to a middleware. It must be called to continue the request pipeline. * @template CtxAdditions - The type of the properties that the current middleware will add to the context for the next step. */ export type NextFunction<CtxAdditions = void> = (contextAdditions?: CtxAdditions) => Promise<Response>; /** * Represents a middleware function in the `expose` pipeline. * A middleware must either call `next()` to pass control down the chain or return a `Response` to end the request. * The signature `({ req, ctx, next })` promotes DX by allowing developers to destructure only needed arguments. * * @template CtxIn - The shape of the context object this middleware receives. * @template CtxAdditions - The shape of the properties this middleware adds to the context for the next middleware or handler. * @param {object} args - The middleware arguments. * @param {Request} args.req - The original `Request` object. * @param {CtxIn} args.ctx - The current, augmented `ExposeContext` object. * @param {NextFunction<CtxAdditions>} args.next - The function to call to proceed to the next step in the pipeline. */ export interface ExposeMiddleware<CtxIn extends ExposeContext<any> = ExposeContext, CtxAdditions = void> { (args: { req: Request; ctx: CtxIn; next: NextFunction<CtxAdditions>; }): Promise<Response>; } /** * Represents the final handler function in the `expose` pipeline. It receives the fully augmented context * from all preceding middleware and is responsible for returning the final `Response`. * * @template CtxIn - The final shape of the context object after all middleware have run. * @param {object} args - The final handler arguments. * @param {CtxIn} args.ctx - The fully augmented context object. * @param {Request} args.req - The original Next.js `Request` object. * @returns {Promise<Response> | Response} The final `Response`. */ export interface ExposeFinalHandler<CtxIn extends ExposeContext<any> = ExposeContext> { (args: { ctx: CtxIn; req: Request; }): Promise<Response> | Response; } /** * The standard type for a Next.js App Router API Route Handler. * This is the ultimate output of the `expose` pipeline builder, making it compatible with Next.js. * * --- CHANGE --- * The context.params object is now a Promise in Next.js 15+, especially with Turbopack. * The type has been updated to reflect this, which resolves the build error. */ export type NextJsRouteHandler<TParams extends Record<string, any> = Record<string, string | string[]>> = (req: Request, context: { params: Promise<TParams>; }) => Promise<Response>; /** * A utility type to compute the new context shape after a middleware runs. * It merges the current context with the additions from the middleware, ensuring type safety. * @template CurrentCtx - The context type before the middleware. * @template HandlerCtxAdditions - The type of the data being added by the middleware. * @private */ type EvolvedContext<CurrentCtx extends ExposeContext<any>, HandlerCtxAdditions> = HandlerCtxAdditions extends void ? CurrentCtx : HandlerCtxAdditions extends object ? ExposeContext<CurrentCtx['params']> & Omit<CurrentCtx, keyof HandlerCtxAdditions | 'params'> & HandlerCtxAdditions : CurrentCtx; /** * Builds the middleware chain for a specific HTTP method. * This class is internal to the `expose` library's fluency. * @template BuilderMethod - The HTTP method being built (e.g., 'GET'). * @template TParams - The shape of the route's URL parameters. * @template CurrentPipelineContext - The current, evolving shape of the context object. * @template ParentRouterMethods - The methods already configured on the parent router. * @private */ declare class RouteMethodBuilder<BuilderMethod extends HttpMethod, TParams extends Record<string, any>, CurrentPipelineContext extends ExposeContext<TParams>, ParentRouterMethods extends HttpMethod> { private parentRouter; private httpMethod; private readonly collectedMiddlewares; constructor(parentRouter: ExposeRouter<TParams, ParentRouterMethods>, httpMethod: BuilderMethod); /** * Adds a middleware function to the request-handling pipeline for this specific HTTP method. * @param middleware The `ExposeMiddleware` function to add. * @returns The `RouteMethodBuilder` instance for further chaining, with an evolved context type. */ use<MiddlewareCtxAdditions>(middleware: ExposeMiddleware<CurrentPipelineContext, MiddlewareCtxAdditions>): RouteMethodBuilder<BuilderMethod, TParams, EvolvedContext<CurrentPipelineContext, MiddlewareCtxAdditions>, ParentRouterMethods>; /** * Defines the final handler for the request pipeline. This terminates the chain for this method. * @param finalHandler The `ExposeFinalHandler` that will process the request after all middleware have run. * It receives a single object argument for better ergonomics: `({ ctx, req }) => ...`. * @returns The parent `ExposeRouter` instance, now configured with the new method handler. */ handle(finalHandler: ExposeFinalHandler<CurrentPipelineContext>): ExposeRouter<TParams, ParentRouterMethods | BuilderMethod>; } /** * The main router class that collects handlers for different HTTP methods for a single API endpoint. * @template TParams - The expected shape of the URL parameters for all routes defined on this instance. * @template ConfiguredMethods - A union of HTTP methods that have been configured on this instance. */ declare class ExposeRouter<TParams extends Record<string, any> = Record<string, string | string[] | undefined>, ConfiguredMethods extends HttpMethod = never> { private methodPipelines; /** * Registers a fully built method handler pipeline with the router instance. * @param method - The HTTP method. * @param pipeline - The compiled `NextJsRouteHandler`. * @returns The `ExposeRouter` instance. * @internal */ _registerMethod<M extends HttpMethod>(method: M, pipeline: NextJsRouteHandler<TParams>): ExposeRouter<TParams, ConfiguredMethods | M>; /** Starts building a pipeline for the GET HTTP method. */ get(): RouteMethodBuilder<'GET', TParams, ExposeContext<TParams>, ConfiguredMethods>; /** Starts building a pipeline for the POST HTTP method. */ post(): RouteMethodBuilder<'POST', TParams, ExposeContext<TParams>, ConfiguredMethods>; /** Starts building a pipeline for the PUT HTTP method. */ put(): RouteMethodBuilder<'PUT', TParams, ExposeContext<TParams>, ConfiguredMethods>; /** Starts building a pipeline for the DELETE HTTP method. */ delete(): RouteMethodBuilder<'DELETE', TParams, ExposeContext<TParams>, ConfiguredMethods>; /** Starts building a pipeline for the PATCH HTTP method. */ patch(): RouteMethodBuilder<'PATCH', TParams, ExposeContext<TParams>, ConfiguredMethods>; /** Starts building a pipeline for the OPTIONS HTTP method. */ options(): RouteMethodBuilder<'OPTIONS', TParams, ExposeContext<TParams>, ConfiguredMethods>; /** Starts building a pipeline for the HEAD HTTP method. */ head(): RouteMethodBuilder<'HEAD', TParams, ExposeContext<TParams>, ConfiguredMethods>; /** * Finalizes the router configuration and returns an object containing the compiled route handlers, * ready to be exported from a Next.js `route.ts` file. * @example * export const { GET, POST } = route().get(...).post(...).expose(); */ expose(): { [P in ConfiguredMethods]: NextJsRouteHandler<TParams>; }; } /** * The main factory function to create a new `ExposeRouter` instance for defining an API endpoint. * This is the entry point for building all API routes. * @template TParams - The expected shape of the route's URL parameters (e.g., `{ id: string }`). * @returns A new `ExposeRouter` instance. */ export declare function route<TParams extends Record<string, any> = Record<string, string | string[] | undefined>>(): ExposeRouter<TParams>; export {}; //# sourceMappingURL=core.d.ts.map