Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslnode 18–226 runs
build_error
glibcnode 18–226 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
createContext
✓ import { createContext } from 'unctx'
✗ const { createContext } = require('unctx')
Primary function to create a new, isolated context. Unctx is an ESM-first package.
useContext
✓ import { useContext } from 'unctx'
✗ const useContext = require('unctx').useContext
Used for globally namespaced contexts, accepting a string key to retrieve or create a context.
unctxPlugin
✓ import { unctxPlugin } from 'unctx/plugin'
✗ import { unctxPlugin } from 'unctx'
The build-time transformation plugin is imported from a subpath and requires a bundler like Rollup, Vite, or Webpack.
AsyncLocalStorage
✓ import { AsyncLocalStorage } from 'node:async_hooks'
✗ import AsyncLocalStorage from 'async_hooks'
Used when enabling native async context. Requires Node.js (or a polyfill/runtime with support like Cloudflare Workers).
This quickstart demonstrates creating a context, defining a composable, using `ctx.call` to activate the context, and showing how `AsyncLocalStorage` (if configured) preserves context across `await` statements. It also highlights the error when no context is active.
import { createContext } from 'unctx';
import { AsyncLocalStorage } from 'node:async_hooks'; // Only needed for native async context in Node.js
// Create a context, optionally enabling native async context
const ctx = createContext({
asyncContext: true, // Enable native async context if available
AsyncLocalStorage: typeof AsyncLocalStorage !== 'undefined' ? AsyncLocalStorage : undefined
});
// Define a composable that uses this context
export const useCounter = () => {
const state = ctx.use();
if (!state) {
throw new Error('useCounter must be called within an active context.');
}
return {
increment: () => state.count++,
decrement: () => state.count--,
getCount: () => state.count,
setCount: (value) => { state.count = value; }
};
};
async function runExample() {
console.log('--- Without active context ---');
try {
useCounter().getCount(); // This will throw if no context is active
} catch (e) {
console.error(e.message);
}
console.log('\n--- Running with context ---');
await ctx.call({
count: 0 // Initial context state
}, async () => {
const counter = useCounter();
console.log('Initial count:', counter.getCount()); // Should be 0
counter.increment();
console.log('After increment:', counter.getCount()); // Should be 1
await new Promise(resolve => setTimeout(resolve, 50));
// With asyncContext: true, the context should persist across await
console.log('After await, count:', counter.getCount()); // Should still be 1
counter.increment();
console.log('Final count:', counter.getCount()); // Should be 2
});
console.log('\n--- After context call ends ---');
try {
useCounter().getCount();
} catch (e) {
console.error(e.message);
}
}
runExample();
Debug
Known issues
breakingUnctx v2.4.0 updated its `unplugin` dependency to v2. Users utilizing the `unctx/plugin` for build-time async context transformation might experience issues or need to update their `unplugin` setup to ensure compatibility.fixReview your `unplugin` configuration and update to `unplugin` v2 if necessary. Consult the `unplugin` documentation for migration steps.
affects: >=2.4.0
gotchaCalling `ctx.use()` (or `useAwesome()` in the example) when no context has been set via `ctx.call()` will throw an error.fixAlways ensure `ctx.use()` is called within a `ctx.call()` scope, or use `ctx.tryUse()` if a nullable context is acceptable for tolerant usages.
affects: >=2.0.0
gotchaWithout enabling `asyncContext: true` and providing `AsyncLocalStorage` (or using the build-time transform), context set by `ctx.call()` will be lost across asynchronous operations like `await` or `setTimeout`.fixFor Node.js, enable native async context by passing `{ asyncContext: true, AsyncLocalStorage }` to `createContext` and `import { AsyncLocalStorage } from 'node:async_hooks'`. For other environments, use the `unctx/plugin` for build-time async transformation. affects: <2.3.0 (before native async context support), or >=2.3.0 without explicit `asyncContext: true` configuration
gotchaWhen using `useContext` or `getContext` with namespaces, always provide a verbose and unique string key (e.g., your npm package name) to avoid conflicts within `globalThis` if multiple libraries use `unctx`.fixAdopt a clear naming convention for your context keys, ideally derived from your package's unique identifier to minimize collision risk.
affects: >=1.0.0
deprecatedVersion 2.0.0 introduced strict `ctx.use()` behavior, meaning it now throws errors if no context is found. The `ctx.tryUse()` method was introduced as a non-throwing alternative.fixMigrate usages of `ctx.use()` that previously might have implicitly handled `undefined` to `ctx.tryUse()`, or ensure `ctx.use()` is only called when a context is guaranteed to be active.
affects: <2.0.0
Errors
Common errors & fixes
Error: [unctx] No active context
The `ctx.use()` method was called outside of an active context created by `ctx.call()` or a namespaced context provided by `useContext`/`getContext`.
fixWrap the code that calls `ctx.use()` within a `ctx.call()` block, or ensure a namespaced context has been established using `useContext` or `getContext` and populated with `ctx.call()`.
Context value is undefined (or null) after await/setTimeout
The context was lost across an asynchronous boundary because native async context was not enabled or the build-time transform was not applied.
fixFor Node.js environments, enable native async context by passing `{ asyncContext: true, AsyncLocalStorage }` to `createContext` and importing `AsyncLocalStorage` from `node:async_hooks`. For environments without native `AsyncLocalStorage`, configure and use the `unctx/plugin` within your bundler (e.g., Rollup, Vite, Webpack) to enable build-time async transformation. Audit
Dependencies
node:async_hooksoptionalRequired for native async context support in Node.js environments via `AsyncLocalStorage`.
unpluginoptionalRequired for the build-time async context transformation plugin. Users of the plugin need to ensure compatibility.