Reference
yieldless/context
AsyncLocalStorage-based context and a small tracing helper for Node.js.
yieldless/context wraps Node's AsyncLocalStorage without turning it into a global application container.
Exports
createContext<T>(): YieldlessContext<T>createTraceContext<Span>(): YieldlessContext<Span>withSpan(tracer, context, name, fn): Promise<Return>
YieldlessContext<T>
| Method | Description |
|---|---|
run(value, fn) | Execute a function with the given context value |
get() | Return the current value or undefined |
expect(message?) | Return the current value or throw with an optional message |
bind(fn) | Capture the current context and bind it to a function |
Example
import { createContext, withSpan } from "yieldless/context";
const requestContext = createContext<{ requestId: string }>();
await requestContext.run({ requestId: crypto.randomUUID() }, async () => {
console.log(requestContext.expect().requestId);
});Tracing shape
withSpan() expects a tracer with startActiveSpan() and a span with end(). That matches the OpenTelemetry style API closely without taking a hard runtime dependency on it.
Use it for
- Request IDs
- Trace spans
- User session metadata
- Transaction handles
Do not use it for
- Static application dependencies
- Feature flags that are known at startup
- Anything that would be clearer as a regular function argument
Good
Use context for metadata that naturally follows asynchronous work.
const requestContext = createContext<{ requestId: string }>();
await requestContext.run({ requestId }, async () => {
logger.info(requestContext.expect().requestId);
await handleRequest();
});Use bind() when a callback will run later but should keep the current store.
const onComplete = requestContext.bind(() => {
logger.info(requestContext.expect().requestId);
});Avoid
Do not use async context as a dependency container.
const appContext = createContext<{ database: Database; logger: Logger }>();
export async function loadUser(id: string) {
return await appContext.expect().database.findUser(id);
}Stable dependencies are clearer as function parameters or yieldless/di inputs.