@beignet/core
Version:
Core framework primitives for Beignet
75 lines • 4.18 kB
TypeScript
import type { HttpContractConfig } from "../contracts/index.js";
import { type MemoInstrumentationEvent } from "../memo/index.js";
import type { AnyPorts } from "../ports/index.js";
import type { ContextSeed } from "./context.js";
import type { Handler, HttpRequestLike, HttpResponse, RouteHook, ServerCaughtErrorHook, ServerHook, ServerUnhandledErrorMapper } from "./http.js";
import type { ServerInstrumentationOptions } from "./instrumentation.js";
import { type RequestBodyOptions } from "./request-preparation.js";
import { type CompiledPath } from "./route-matching.js";
import type { TrustedRequestInfo } from "./trusted-proxy.js";
type RequestExecutorOptions<Ctx> = {
instrumentation?: ServerInstrumentationOptions<Ctx> | false;
validateResponses?: boolean;
requestBody?: RequestBodyOptions;
onCaughtError?: ServerCaughtErrorHook<Ctx>;
mapUnhandledError?: ServerUnhandledErrorMapper<Ctx>;
};
type ExecutionTarget<Ctx, C extends HttpContractConfig> = {
contract: C;
/**
* Compiled route pattern. Only required when the executor is invoked
* without pre-matched params.
*/
compiled?: CompiledPath;
handler: Handler<Ctx, C>;
/**
* Success status whose response schema validation is skipped because the
* use case bound to this route already validated its output against the
* same schema object.
*/
responseValidationExemptStatus?: number;
};
/**
* Build the per-request execution pipeline once.
*
* The returned executor takes the contract, compiled pattern, and user handler
* per invocation so fallback responses (404/405) can reuse a single pipeline
* across requests instead of rebuilding it per unmatched request.
*/
export declare function createRequestExecutor<Ctx, FinalPorts extends AnyPorts, C extends HttpContractConfig>(options: RequestExecutorOptions<Ctx>, finalPorts: FinalPorts, contextRuntime: {
createRequestContext: (req: HttpRequestLike, contract: HttpContractConfig, requestInfo: TrustedRequestInfo) => Promise<Ctx>;
finalizeContext: (seed: ContextSeed<Ctx> | Ctx) => Ctx;
resolveRequestInfo: (req: HttpRequestLike) => TrustedRequestInfo;
}, hooks: ServerHook<Ctx, FinalPorts>[], routeHooks?: readonly RouteHook<unknown, object>[], optionsOverrides?: {
skipRoutePreparation?: boolean;
/**
* Run the route through the full hook pipeline without contract
* preparation: no query/path/header/body parsing or validation, and the
* request body is left unconsumed for the handler.
*/
rawRoute?: boolean;
}): (target: ExecutionTarget<Ctx, C>, req: HttpRequestLike, preMatchedParams?: Record<string, string>) => Promise<HttpResponse>;
/**
* Build a memo instrumentation recorder from the app ports, or undefined when
* no instrumentation sink is wired.
*
* Resolved per execution rather than at route-build time because providers
* contribute `ports.instrumentation`/`ports.devtools` during setup, after
* routes are registered.
*/
export declare function createMemoScopeRecorder(ports: AnyPorts): ((event: MemoInstrumentationEvent) => void) | undefined;
export declare function buildHandler<Ctx, FinalPorts extends AnyPorts, C extends HttpContractConfig>(options: RequestExecutorOptions<Ctx>, finalPorts: FinalPorts, contextRuntime: {
createRequestContext: (req: HttpRequestLike, contract: HttpContractConfig, requestInfo: TrustedRequestInfo) => Promise<Ctx>;
finalizeContext: (seed: ContextSeed<Ctx> | Ctx) => Ctx;
resolveRequestInfo: (req: HttpRequestLike) => TrustedRequestInfo;
}, contract: C, userHandler: Handler<Ctx, C>, hooks: ServerHook<Ctx, FinalPorts>[], routeHooks?: readonly RouteHook<unknown, object>[], optionsOverrides?: {
skipRoutePreparation?: boolean;
/**
* Run the route through the full hook pipeline without contract
* preparation: no query/path/header/body parsing or validation, and the
* request body is left unconsumed for the handler.
*/
rawRoute?: boolean;
}, responseValidationExemptStatus?: number): (req: HttpRequestLike, preMatchedParams?: Record<string, string>) => Promise<HttpResponse>;
export {};
//# sourceMappingURL=request-executor.d.ts.map