/** * Request Context - AsyncLocalStorage for passing request-scoped data throughout rendering * * This is the unified context used everywhere: * - Middleware execution * - Route handlers and loaders * - Server components during rendering * - Error boundaries and streaming * * Available via getRequestContext() anywhere in the request lifecycle. */ import type { CookieOptions } from "../router/middleware.js"; import type { LoaderDefinition } from "../types.js"; import type { Handle } from "../handle.js"; import { type HandleStore } from "./handle-store.js"; import type { SegmentCacheStore } from "../cache/types.js"; import type { Theme, ResolvedThemeConfig } from "../theme/types.js"; /** * Unified request context available via getRequestContext() * * This is the same context passed to middleware and handlers. * Use this when you need access to request data outside of route handlers. */ export interface RequestContext> { /** Platform bindings (Cloudflare env, etc.) */ env: TEnv; /** Original HTTP request */ request: Request; /** Parsed URL (system params like _rsc* are NOT filtered here) */ url: URL; /** URL pathname */ pathname: string; /** URL search params (system params like _rsc* are NOT filtered here) */ searchParams: URLSearchParams; /** Variables set by middleware (same as ctx.var) */ var: Record; /** Get a variable set by middleware */ get: (key: K) => any; /** Set a variable (shared with middleware and handlers) */ set: (key: K, value: any) => void; /** * Route params (populated after route matching) * Initially empty, then set to matched params */ params: TParams; /** * Stub response for setting headers/cookies * Headers set here are merged into the final response */ res: Response; /** Get a cookie value from the request */ cookie(name: string): string | undefined; /** Get all cookies from the request */ cookies(): Record; /** Set a cookie on the response */ setCookie(name: string, value: string, options?: CookieOptions): void; /** Delete a cookie */ deleteCookie(name: string, options?: Pick): void; /** Set a response header */ header(name: string, value: string): void; /** * Access loader data or push handle data. * * For loaders: Returns a promise that resolves to the loader data. * Loaders are executed in parallel and memoized per request. * * For handles: Returns a push function to add data for this segment. * Handle data accumulates across all matched route segments. * * @example * ```typescript * // Loader usage * const cart = await ctx.use(CartLoader); * * // Handle usage * const push = ctx.use(Breadcrumbs); * push({ label: "Shop", href: "/shop" }); * ``` */ use: { (loader: LoaderDefinition): Promise; (handle: Handle): (data: TData | Promise | (() => Promise)) => void; }; /** HTTP method (GET, POST, PUT, PATCH, DELETE, etc.) */ method: string; /** @internal Handle store for tracking handle data across segments */ _handleStore: HandleStore; /** @internal Cache store for segment caching (optional, used by CacheScope) */ _cacheStore?: SegmentCacheStore; /** * Schedule work to run after the response is sent. * On Cloudflare Workers, uses ctx.waitUntil(). * On Node.js, runs as fire-and-forget. * * @example * ```typescript * ctx.waitUntil(async () => { * await cacheStore.set(key, data, ttl); * }); * ``` */ waitUntil(fn: () => Promise): void; /** * Register a callback to run when the response is created. * Callbacks are sync and receive the response. They can: * - Inspect response status/headers * - Return a modified response * - Schedule async work via waitUntil * * @example * ```typescript * ctx.onResponse((res) => { * if (res.status === 200) { * ctx.waitUntil(async () => await cacheIt()); * } * return res; * }); * ``` */ onResponse(callback: (response: Response) => Response): void; /** @internal Registered onResponse callbacks */ _onResponseCallbacks: Array<(response: Response) => Response>; /** * Current theme setting (only available when theme is enabled in router config) * * Returns the theme value from the cookie, or the default theme if not set. * This is the user's preference ("light", "dark", or "system"), not the resolved value. * * @example * ```typescript * route("settings", (ctx) => { * const currentTheme = ctx.theme; // "light" | "dark" | "system" | undefined * return ; * }); * ``` */ theme?: Theme; /** * Set the theme (only available when theme is enabled in router config) * * Sets a cookie with the new theme value. The change takes effect on the next request. * * @example * ```typescript * route("settings", (ctx) => { * if (ctx.method === "POST") { * const formData = await ctx.request.formData(); * const newTheme = formData.get("theme") as Theme; * ctx.setTheme(newTheme); * } * return ; * }); * ``` */ setTheme?: (theme: Theme) => void; /** @internal Theme configuration (null if theme not enabled) */ _themeConfig?: ResolvedThemeConfig | null; } /** * Run a function within a request context * Used by the RSC handler to provide context to server actions */ export declare function runWithRequestContext(context: RequestContext, fn: () => T): T; /** * Get the current request context * Returns undefined if not running within a request context */ export declare function getRequestContext(): RequestContext | undefined; /** * Update params on the current request context * Called after route matching to populate route params */ export declare function setRequestContextParams(params: Record): void; /** * Get the current request context, throwing if not available * Use this when context is required (e.g., in loader actions) */ export declare function requireRequestContext(): RequestContext; /** * Cloudflare Workers ExecutionContext (subset we need) */ export interface ExecutionContext { waitUntil(promise: Promise): void; passThroughOnException(): void; } /** * Options for creating a request context */ export interface CreateRequestContextOptions { env: TEnv; request: Request; url: URL; variables: Record; /** Optional cache store for segment caching (used by CacheScope) */ cacheStore?: SegmentCacheStore; /** Optional Cloudflare execution context for waitUntil support */ executionContext?: ExecutionContext; /** Optional theme configuration (enables ctx.theme and ctx.setTheme) */ themeConfig?: ResolvedThemeConfig | null; } /** * Create a full request context with all methods implemented * * This is used by the RSC handler to create the unified context that's: * - Available via getRequestContext() throughout the request * - Passed to middleware as ctx * - Passed to handlers as ctx */ export declare function createRequestContext(options: CreateRequestContextOptions): RequestContext; /** * Options for creating the use() function */ export interface CreateUseFunctionOptions { handleStore: HandleStore; loaderPromises: Map>; getContext: () => RequestContext; } /** * Create the use() function for loader and handle composition. * * This is the unified implementation used by both RequestContext and HandlerContext. * - For loaders: executes and memoizes loader functions * - For handles: returns a push function to add handle data */ export declare function createUseFunction(options: CreateUseFunctionOptions): RequestContext["use"]; //# sourceMappingURL=request-context.d.ts.map