@apiratorjs/async-context
v1.1.5
Published
A Node.js async context library leveraging the node:async_hooks module, supporting context merging and overriding.
Maintainers
Readme
@apiratorjs/async-context
A lightweight Node.js library for managing asynchronous contexts using the built-in node:async_hooks module. This package allows you to share, merge, and override context data throughout your asynchronous code execution. It’s especially useful for per-request or per-transaction state management, logging, and debugging.
Note: Requires Node.js version >=16.4.0
Features
- Async Context Management: Seamlessly pass context data across asynchronous calls.
- Context Merging: Automatically merge context data for common data types (plain objects, arrays, Maps, and Sets).
- Context Overriding: Override existing context data when needed.
- Typed Context Store: Built with TypeScript to provide type safety.
- Easy Integration: Works out-of-the-box with Node.js asynchronous operations.
- Extended Map Functionality:
AsyncContextStoreextends the nativeMapclass, so all Map methods (such asset,get,has,delete, etc.) are available and it supports any type as a key—including classes.
Installation
Install the package via npm:
npm install @apiratorjs/async-contextOr using yarn:
yarn add @apiratorjs/async-contextUsage
Basic Example
Use withContext to run a callback within an asynchronous context:
import { AsyncContext } from "@apiratorjs/async-context";
async function main() {
await AsyncContext.withContext("user", { id: 123 }, () => {
// Inside this callback the context is available.
const user = AsyncContext.getContext("user");
console.log("User Context:", user); // { id: 123 }
});
}
main();Merging Context
If you nest context calls using the same key, the package will merge the data if they are compatible (e.g., plain objects, arrays, Maps, or Sets):
import { AsyncContext } from "@apiratorjs/async-context";
AsyncContext.withContext("config", { theme: "dark" }, () => {
console.log(AsyncContext.getContext("config")); // { theme: "dark" }
AsyncContext.withContext("config", { language: "en" }, () => {
console.log(AsyncContext.getContext("config")); // { theme: "dark", language: "en" }
});
});Overriding Context
Use withContextOverride to completely override a value in the context rather than merging:
import { AsyncContext } from "@apiratorjs/async-context";
AsyncContext.withContext("user", { id: 123, name: "Alice" }, () => {
AsyncContext.withContextOverride("user", { id: 999 }, () => {
console.log(AsyncContext.getContext("user")); // { id: 999 }
});
});Working with Multiple Keys
You can work with multiple context keys at once by passing an AsyncContextStore. For example:
import { AsyncContext, AsyncContextStore } from "@apiratorjs/async-context";
// Create a context store from a plain object.
const contextStore = AsyncContextStore.fromObject({
user: { id: 1 },
session: { token: "abc" }
});
AsyncContext.withContext(contextStore, () => {
const user = AsyncContext.getContext("user");
const session = AsyncContext.getContext("session");
console.log("User:", user); // { id: 1 }
console.log("Session:", session); // { token: "abc" }
});Retrieving Context Data
- Entire Context: Call AsyncContext.getContext() with no arguments.
- Specific Key: Call AsyncContext.getContext("key") to get the value associated with that key.
- Partial Context: Use AsyncContext.getMultiContext(["key1", "key2"]) to obtain a subset of the context.
// Get the entire context store.
const store = AsyncContext.getContext();
// Get a specific context value.
const user = AsyncContext.getContext("user");
// Get a partial context containing selected keys.
const partialStore = AsyncContext.getMultiContext(["user", "session"]);Running Tests
To run the tests locally:
- Clone the repository.
- Install the dependencies using
npm installoryarn install. - Run the tests using
npm testoryarn test.
Contributing
Contributions, issues, and feature requests are welcome! Please open an issue or submit a pull request on GitHub.
