als-registry
v0.0.0
Published
A lightweight utility for managing multiple AsyncLocalStorage instances in Node.js, simplifying context propagation.
Maintainers
Readme
ALS Registry
A lightweight utility for managing multiple AsyncLocalStorage instances in Node.js. This module simplifies the registration, retrieval, and application of asynchronous contexts, making it easier to propagate context across different parts of your application.
Features
- Register and manage multiple
AsyncLocalStorageinstances with unique identifiers. - Check for registered contexts.
- Retrieve current store values from all registered contexts.
- Apply contexts to existing asynchronous flows.
- Run callbacks within a new asynchronous execution context with specified context data.
- Lightweight and dependency-free.
Installation
npm install als-registryUsage
First, import the necessary functions from the module:
import {
registerContext,
isContextRegistered,
getAllContextData,
applyContexts,
runWithContexts
} from 'als-registry';
import { AsyncLocalStorage } from 'node:async_hooks';
// 1. Create and register your AsyncLocalStorage instances
const requestIdContext = new AsyncLocalStorage();
const userContext = new AsyncLocalStorage();
registerContext('requestId', requestIdContext);
registerContext('user', userContext);runWithContexts(contextData, callback)
Use this to start a new asynchronous execution context. This is ideal for entry points like handling an incoming HTTP request.
async function handleRequest(req, res) {
const contextData = {
requestId: req.headers['x-request-id'],
user: { id: 'user-123', name: 'John Doe' }
};
await runWithContexts(contextData, async () => {
// The context is now set and available in any function called from here
await processOrder();
res.send('Request processed');
});
}
async function processOrder() {
// You can retrieve the context data anywhere in the call stack
const allData = getAllContextData();
console.log(allData); // { requestId: '...', user: { ... } }
// Or get a specific context's store
console.log(userContext.getStore()); // { id: 'user-123', name: 'John Doe' }
}applyContexts(contextData)
Use this when you need to apply context within an existing asynchronous flow, without creating a new top-level execution context. This is useful for middleware or functions that enrich an already established context.
// Middleware that adds authentication data to the context
async function authMiddleware() {
// Assume some authentication logic here...
const authData = {
traceId: 'trace-abc-123'
// Note: We are not re-applying 'requestId' or 'user' here
};
// Create and register the traceId context if it doesn't exist
if (!isContextRegistered('traceId')) {
registerContext('traceId', new AsyncLocalStorage());
}
applyContexts(authData);
// Now, any subsequent function in this async flow can access 'traceId'
await next();
}getAllContextData()
This function collects the store from every registered AsyncLocalStorage instance and returns them in a single object. This is useful for logging, debugging, or passing the entire context to another system.
function logCurrentContext() {
const contextData = getAllContextData();
console.log('Current async context:', contextData);
// Example output: { requestId: '...', user: { ... }, traceId: '...' }
}API Reference
registerContext(uid, context)
Registers an AsyncLocalStorage instance with a unique identifier.
uid(string): The unique identifier for the context.context(AsyncLocalStorage): TheAsyncLocalStorageinstance to register.
isContextRegistered(uid)
Checks if a context with the given uid has been registered.
uid(string): The unique identifier to check.- Returns:
boolean
getAllContextData()
Gets the current store value from all registered contexts.
- Returns:
Record<string, any>- An object where keys are theuids and values are the corresponding store values.
applyContexts(contextData)
Enters a new asynchronous state for all matching contexts without creating a new execution boundary.
contextData(Record<string, any>): An object where keys areuids and values are the store values to set.
runWithContexts(contextData, callback)
Creates a new asynchronous execution context boundary and runs the callback within it.
contextData(Record<string, any>): The context data to set for the callback's execution.callback(() => Promise<T>): The asynchronous function to execute.- Returns:
Promise<T>
Contributing
Contributions are welcome! Please open an issue or submit a pull request on the GitHub repository.
