/** * What a compiled route IS, and the registration-time decision that produces it. * * ## Why this is not in the server kernel * * `compileExecutionPlan` is BOOT work: it runs from `register`/`registerBatch`, both gated by * `assertConfigurable`, so nothing here is reachable once the server is serving. Moving it costs the * request path nothing - per-request code still calls the same frozen `run` closure it always did. * * ## Why `internal/` * * These types are the engine's vocabulary, not the package's API. They lived in `server.ts`, which IS * published as `./server`, so every attempt to split the kernel had the same choice: export the engine's * internals as public types, or not split. `internal/` is not a published subpath, so this moves the * vocabulary somewhere it can be shared without becoming API. That is the step that unblocks the rest. * * The `Server` import is type-only and erased, so there is no runtime cycle back into the kernel. */ import type { RequestBudget } from "../budget.js"; import type { StandardSchemaV1 } from "../schema/standard.js"; import type { Platform, RouteSchema } from "../server/context.js"; import type { ResolvedIdempotency } from "../server/idempotency-lane.js"; import type { ResolvedEffectLedger } from "../server/ledger-lane.js"; import type { Registry } from "../server/registry.js"; import type { ResponseContractRuntime } from "../server/response-contract-lane.js"; import type { HandlerResult, ResponseResult } from "../server/runtime-core.js"; import type { CtxSet, MaybePromise, RawContext, RequestSource, Server } from "../server/server.js"; import type { RouteProgram } from "./route-program.js"; export type InternalHandler = (ctx: RawContext) => MaybePromise; /** A `derive` computes per-request context extensions; stored path-erased. */ export type RawDerive = (ctx: RawContext) => MaybePromise; export type RawBeforeHandle = (ctx: RawContext) => MaybePromise; export type RawAfterHandle = (result: unknown, ctx: RawContext) => MaybePromise; export type RawErrorHandler = (error: unknown, ctx: RawContext) => MaybePromise; export type RawAround = (ctx: RawContext, next: () => MaybePromise) => MaybePromise; export type RouteExecutionRunner = (runtime: Server, entry: RouteEntry, source: RequestSource, params: Record, search: string | undefined, signal: AbortSignal, budget: RequestBudget, platform: Platform | undefined, nativeContext: boolean, finalize: (result: unknown, set: CtxSet) => T, wrapResponse: (response: Response | ResponseResult) => T) => MaybePromise; export type ContextRouteRunner = (runtime: Server, entry: RouteEntry, source: RequestSource, ctx: RawContext, finalize: (result: unknown, set: CtxSet) => T, wrapResponse: (response: Response | ResponseResult) => T) => MaybePromise; export type RouteExecutionLane = "bare" | "body" | "query" | "lifecycle"; export type LifecycleExecutionLane = "hooks" | "query" | "body" | "body-query" | undefined; /** Compile the one immutable route decision at registration time. The request path only invokes the * selected closure; it never repeats this eligibility ladder. The closures reach the kernel's private * runners through the {@link RouteExecutionRuntime} mirror - a compile-time cast, not a dispatch * object, so the emitted request path is a direct method call on the server. */ export declare function compileRouteExecutionPlan(options: { readonly lane: RouteExecutionLane; readonly contextless: boolean; readonly hasAround: boolean; readonly hasLedger: boolean; readonly fusedWeb: FusedWebRunner | undefined; readonly fusedBody: FusedBodyRunner | undefined; readonly fusedLane: "bare" | "body" | "query" | "derive-before" | "derive-before-after" | "body-derive-before" | "body-derive-before-after" | undefined; }): RouteExecutionPlan; /** Registration-compiled route behavior. Every adapter invokes the same runner; the optional fused * renderer is only a response-format specialization of that same selected route semantics. */ export interface RouteExecutionPlan { readonly run: RouteExecutionRunner; readonly fusedWeb: FusedWebRunner | undefined; readonly fusedBody: FusedBodyRunner | undefined; /** Which builder produced {@link fusedWeb} - a merge rebinds the closure to the executing server * and must rebuild it with the SAME semantics (a query-fused route rebuilt as bare would skip its * validation). `undefined` iff `fusedWeb` is. */ readonly fusedLane: "bare" | "body" | "query" | "derive-before" | "derive-before-after" | "body-derive-before" | "body-derive-before-after" | undefined; } export interface RouteEntry { readonly handler: InternalHandler; readonly schema: RouteSchema | undefined; /** * Effective transport body cap, already resolved at registration: the route's own * `schema.bodyLimit` when it declared one, the server's `maxBodyBytes` otherwise. `undefined` is * an explicit streaming/upload exemption (`bodyLimit: "unlimited"`) and means NO cap - readers * must fall back to {@link UNLIMITED_BODY_BYTES}, never to the server default, which would be a * tighter bound than the route asked for. */ readonly bodyLimit: number | undefined; /** Resolved idempotency config; `undefined` = off (the dedupe lane is never entered). */ readonly idempotent: ResolvedIdempotency | undefined; /** Resolved effect-ledger wiring; `undefined` = off (no per-request ledger, no settle step). */ readonly ledgered: ResolvedEffectLedger | undefined; /** The installed response-contract runtime paired with this route's declared schema, resolved once * at registration; `undefined` = not checked (the default, and the only state in which the route can * still take the fused/native lanes). */ readonly responseContract: { readonly runtime: ResponseContractRuntime; readonly schema: StandardSchemaV1; } | undefined; /** Per-request context extensions captured at registration (order-scoped). */ readonly derives: ReadonlyArray; /** Static context extensions captured at registration. */ readonly decorations: Record; /** Whether {@link decorations} has any keys - precomputed so the hot path skips a no-op * `Object.assign` on the (common) no-decoration route. */ readonly hasDecorations: boolean; /** Lifecycle hooks captured at registration (order-scoped). */ readonly beforeHandle: ReadonlyArray; readonly afterHandle: ReadonlyArray; readonly onError: ReadonlyArray; /** Registration-specialized hook shape for the common derive + before middleware route. */ readonly lifecycleHookLane: "derive-before" | "derive-before-after" | undefined; /** Wraps the matched route lifecycle. Empty for the common no-around path. */ readonly around: ReadonlyArray; /** The single immutable execution decision consumed by portable, Node-direct, and Bun-native paths. */ readonly execution: RouteExecutionPlan; /** One immutable general lifecycle program compiled at registration. */ readonly program: RouteProgram; } /** The fused Web lane: same inputs `routeAndRun` would hand the generic path, a `Response` out. */ export type FusedWebRunner = (source: RequestSource, params: Record, search: string | undefined, signal: AbortSignal, budget: RequestBudget, platform: Platform | undefined, nativeContext: boolean) => MaybePromise; /** Registration-compiled body lane. The finalizer receives the live context so Web can preserve lazy * response controls while Node can emit its native outcome directly. */ export type FusedBodyRunner = (source: RequestSource, params: Record, search: string | undefined, signal: AbortSignal, budget: RequestBudget, platform: Platform | undefined, nativeContext: boolean, finalize: (result: unknown, set: CtxSet, ctx: RawContext) => T, wrapResponse: (response: Response | ResponseResult) => T) => MaybePromise; //# sourceMappingURL=route-execution.d.ts.map