API reference
Two exports — the abstract Context<TStore> class and the ContextManager class (plus its contextManager singleton). That’s the whole surface.
import { Context, ContextManager, contextManager } from "@warlock.js/context";Context<TStore>
Section titled “Context<TStore>”Abstract base class. Extend it to declare a typed AsyncLocalStorage-backed context.
abstract class Context<TStore extends Record<string, any>>buildStore(payload?)
Section titled “buildStore(payload?)”Abstract. Provides the initial store. Called by ContextManager.buildStores(payload).
public abstract buildStore(payload?: Record<string, any>): TStore;public buildStore(payload?: Record<string, any>): UserStore { return { userId: payload?.userId ?? "", role: payload?.role ?? "guest" };}run(store, callback)
Section titled “run(store, callback)”Run a callback inside a new context scope. The store auto-clears when the callback resolves or rejects.
public run<T>(store: TStore, callback: () => Promise<T>): Promise<T>;await userContext.run({ userId: "u-1", role: "admin" }, async () => { await doWork();});enter(store)
Section titled “enter(store)”Set the store and return — no callback, no auto-cleanup. Use for legacy middleware that calls next() and returns synchronously.
public enter(store: TStore): void;function middleware(req, res, next) { userContext.enter({ userId: req.user.id, role: req.user.role }); next();}update(updates)
Section titled “update(updates)”Merge a partial into the current store via Object.assign. If no store is active, enters a new one with the partial cast to TStore.
public update(updates: Partial<TStore>): void;userContext.update({ role: "admin" });get(key)
Section titled “get(key)”Read one key from the current store. Returns undefined if no context is active.
public get<K extends keyof TStore>(key: K): TStore[K] | undefined;const userId = userContext.get("userId"); // string | undefinedset(key, value)
Section titled “set(key, value)”Sugar for update({ [key]: value }). Same caveat — calling it outside an active context enters a new one with just that key.
public set<K extends keyof TStore>(key: K, value: TStore[K]): void;userContext.set("role", "admin");getStore()
Section titled “getStore()”Return the whole store record, or undefined if no context is active.
public getStore(): TStore | undefined;const store = userContext.getStore();clear()
Section titled “clear()”Replace the current store with {} cast to TStore. Does not exit the scope — hasContext() still returns true afterwards.
public clear(): void;userContext.clear();hasContext()
Section titled “hasContext()”Returns true if a store is active in the current async scope. Distinguishes “no value” from “no context”.
public hasContext(): boolean;if (!userContext.hasContext()) { throw new Error("called outside a request scope");}ContextManager
Section titled “ContextManager”Orchestrates multiple registered Context instances. The package exports a singleton contextManager; you can also instantiate new ContextManager() if you need a separate orchestrator.
class ContextManagerregister(name, context)
Section titled “register(name, context)”Register a context under a name. Returns the manager for chaining. Re-registering the same name overwrites.
public register(name: string, context: Context<any>): this;contextManager .register("trace", traceContext) .register("user", userContext);unregister(name)
Section titled “unregister(name)”Remove a registration. Returns true if a registration existed.
public unregister(name: string): boolean;contextManager.unregister("debug");buildStores(payload?)
Section titled “buildStores(payload?)”Call every registered context’s buildStore(payload) and return the results keyed by registration name.
public buildStores(payload?: Record<string, any>): Record<string, any>;const stores = contextManager.buildStores({ request: req, response: res });runAll(stores, callback)
Section titled “runAll(stores, callback)”Nest every registered context’s run() in registration order, invoke the callback at the innermost layer.
public runAll<T>(stores: Record<string, any>, callback: () => Promise<T>): Promise<T>;await contextManager.runAll(stores, async () => { await handleRequest(req, res);});enterAll(stores)
Section titled “enterAll(stores)”Call enter() on every context whose name has a truthy value in stores. No auto-cleanup.
public enterAll(stores: Record<string, any>): void;function middleware(req, res, next) { contextManager.enterAll(contextManager.buildStores({ user: req.user })); next();}clearAll()
Section titled “clearAll()”Call clear() on every registered context.
public clearAll(): void;contextManager.clearAll();getContext<T>(name)
Section titled “getContext<T>(name)”Look up a registered context by name. The generic parameter narrows the return type.
public getContext<T extends Context<any>>(name: string): T | undefined;const tenant = contextManager.getContext<TenantContext>("tenant");hasContext(name)
Section titled “hasContext(name)”Check whether a context is registered (not whether it has an active store).
public hasContext(name: string): boolean;if (!contextManager.hasContext("trace")) { contextManager.register("trace", traceContext);}contextManager
Section titled “contextManager”The singleton instance of ContextManager exported from the package.
const contextManager: ContextManager;import { contextManager } from "@warlock.js/context";
contextManager.register("user", userContext);Source
Section titled “Source”src/base-context.ts—Context<TStore>.src/context-manager.ts—ContextManager+contextManager.
Related
Section titled “Related”- Define a context — patterns for typed contexts.
- Orchestrate contexts — registering and running multiple together.