feat(core): carry the request context in an AsyncLocalStorage
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user