feat(core): carry the request context in an AsyncLocalStorage

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-20 02:46:24 +05:30
co-authored by Claude Opus 5
parent 953b1cd692
commit 680ea73975
4 changed files with 151 additions and 61 deletions
+5
View File
@@ -11,6 +11,11 @@ export type {
TFunction,
} from "./context.ts";
export { createContext, withContextHeaders } from "./context.ts";
export {
runWithRequestContext,
getRequestContext,
requireRequestContext,
} from "./request-context.ts";
export { createExecutionContext, executionContextFromHttp } from "./execution-context.ts";
export type {
ExecutionContext,
+33
View File
@@ -0,0 +1,33 @@
import { AsyncLocalStorage } from "node:async_hooks";
import type { Context } from "./context.ts";
/**
* The request context for the currently executing server work.
*
* A server-side API call needs the request's cookies, session, and URL, but
* `ctx` is not in scope everywhere server code runs: load blocks have it,
* schema actions take it as a parameter, and plain actions and server
* functions have neither. Threading it through every signature would make the
* call site differ between server and browser, which defeats the point.
*/
const storage = new AsyncLocalStorage<Context>();
export function runWithRequestContext<T>(ctx: Context, fn: () => T): T {
return storage.run(ctx, fn);
}
export function getRequestContext(): Context | undefined {
return storage.getStore();
}
export function requireRequestContext(what: string): Context {
const ctx = storage.getStore();
if (!ctx) {
throw new Error(
`${what} needs a request context. It ran outside a request — server-side API calls are only available while handling one.`,
);
}
return ctx;
}