@pfeiferio/ctx
v1.0.0
Published
Minimal, type-safe execution context utilities for Node.js based on AsyncLocalStorage
Maintainers
Readme
@pfeiferio/ctx
Minimal utilities for execution-scoped context in Node.js using AsyncLocalStorage.
@pfeiferio/ctx lets you safely create, access and bind logic to an asynchronous execution context — without passing state through every function.
Features
- Execution-scoped context via
AsyncLocalStorage - Fully type-safe & generic
- Context guards (
bindToCurrentContext) - Works with sync and async code
- No dependencies
Installation
npm install @pfeiferio/ctxCore Concepts
A context is data that is bound to the current asynchronous execution flow.
Typical use cases:
- request / job scoped state
- authentication or tenant data
- correlation IDs
- logging & tracing
Defining a Context
type RequestContext = {
requestId: string
userId?: string
}Running Code in a Context
import { runWithContext } from '@pfeiferio/ctx'
await runWithContext<RequestContext>(
{
requestId: 'req-123',
userId: 'u-42',
},
async () => {
// all code here shares the same context
}
)Accessing the Current Context
import { getContext } from '@pfeiferio/ctx'
const ctx = getContext<RequestContext>()
if (ctx) {
console.log(ctx.requestId)
}getContext returns undefined when called outside a context.
Binding Logic to a Context
bindToCurrentContext ensures a function can only execute
inside the context it was created in.
import { bindToCurrentContext } from '@pfeiferio/ctx'
const sendResponse = bindToCurrentContext<
RequestContext,
[string],
void
>((message) => {
console.log('response:', message)
})Later:
sendResponse('ok') // executed (same context)
sendResponse('invalid') // no-op if context changedExample: Request-Scoped Logger
type LogContext = {
requestId: string
}
const log = (msg: string) => {
const ctx = getContext<LogContext>()
console.log(`[${ctx?.requestId ?? 'global'}]`, msg)
}
await runWithContext<LogContext>(
{ requestId: 'req-99' },
async () => {
log('start')
await doSomethingAsync()
log('done')
}
)Example: Context Guard
const guardedFn = bindToCurrentContext<
unknown,
[],
void
>(() => {
console.log('safe execution')
})
// calling outside the context → no-op
guardedFn()API
runWithContext<T, R>(ctx: T, fn: () => R): R
Runs fn inside a new execution context.
getContext<T>(): T | undefined
Returns the current context or undefined.
bindToCurrentContext<T, Args, R>(fn: (...args: Args) => R)
Binds a function to the current execution context.
Design Goals
- explicit over implicit
- runtime safety over magic
- no global mutable state exposure
- minimal surface area
Non-Goals
- framework integration
- request lifecycle management
- cross-process context propagation
License
MIT
