/** * defineMiddleware() — Context Derivation (tRPC-style) * * Middlewares that return data have that data merged into the context * for downstream handlers. TypeScript infers the derived context type * automatically, so removing a middleware causes a compile error * if the handler accesses properties that middleware provided. * * @example * ```typescript * const requireAuth = defineMiddleware(async (ctx: BaseCtx) => { * const user = await db.getUser(ctx.token); * if (!user) throw new Error('Unauthorized'); * return { user }; // ← TS infers: { user: User } * }); * * const billing = defineTool('billing', { * middleware: [requireAuth], * actions: { * refund: { * handler: async (ctx, args) => { * // ctx.user EXISTS and is typed! ✅ * return success(`Refunded by ${ctx.user.id}`); * }, * }, * }, * }); * ``` * * @module */ import { type MiddlewareFn } from '../types.js'; /** * A middleware definition that derives additional context. * * The `derive` function receives the current context and returns * an object whose properties are merged into the context for * downstream middleware and the final handler. * * @typeParam TContextIn - The input context type * @typeParam TDerived - The derived properties to merge */ export interface MiddlewareDefinition> { /** Brand for type discrimination */ readonly __brand: 'MiddlewareDefinition'; /** The derive function */ readonly derive: (ctx: TContextIn) => Promise | TDerived; /** * Convert to a standard MiddlewareFn for use in existing pipelines. * The derived properties are merged into `ctx` before calling `next()`. */ readonly toMiddlewareFn: () => MiddlewareFn; } /** * Utility type: merge a base context with derived properties. * * @example * ```typescript * type Base = { token: string }; * type Derived = { user: User }; * type Result = MergeContext; * // Result = { token: string; user: User } * ``` */ export type MergeContext = TBase & TDerived; /** * Utility type: infer the output context from a MiddlewareDefinition. * * @example * ```typescript * const auth = defineMiddleware(async (ctx: Base) => ({ user })); * type Ctx = InferContextOut; * // Ctx = Base & { user: User } * ``` */ export type InferContextOut>> = TMw extends MiddlewareDefinition ? TContextIn & TDerived : never; /** * Define a context-deriving middleware. * * The returned object can be used in two ways: * 1. As a type-level constraint (the generics carry the derived context) * 2. As a runtime middleware via `.toMiddlewareFn()` (for the existing pipeline) * * @typeParam TContextIn - The input context type * @typeParam TDerived - Auto-inferred derived properties * @param derive - Function that inspects context and returns derived data * @returns A {@link MiddlewareDefinition} with the derived type encoded * * @example * ```typescript * // Auth middleware that derives `user` * const requireAuth = defineMiddleware(async (ctx: { token: string }) => { * const user = await db.getUser(ctx.token); * if (!user) throw new Error('Unauthorized'); * return { user }; * }); * * // Rate limit middleware that derives `rateLimitInfo` * const rateLimit = defineMiddleware(async (ctx: { ip: string }) => { * const info = await checkRateLimit(ctx.ip); * if (info.exceeded) throw new Error('Rate limited'); * return { rateLimitInfo: info }; * }); * ``` * * @see {@link MiddlewareFn} for the standard middleware type */ export declare function defineMiddleware>(derive: (ctx: TContextIn) => Promise | TDerived): MiddlewareDefinition; /** * Type guard: check if a value is a MiddlewareDefinition. * * Used internally to auto-convert MiddlewareDefinitions to MiddlewareFns * when passed to `defineTool({ middleware: [...] })`. * * @internal */ export declare function isMiddlewareDefinition(value: unknown): value is MiddlewareDefinition>; /** * Convert a middleware arg (either MiddlewareFn or MiddlewareDefinition) to MiddlewareFn. * * @internal */ export declare function resolveMiddleware(mw: MiddlewareFn | MiddlewareDefinition>): MiddlewareFn; //# sourceMappingURL=ContextDerivation.d.ts.map