0
# Context Creation & Management
1
2
Context creation and management provides the core functionality for creating typed context instances that can inject values throughout a call stack.
3
4
## API Reference
5
6
```typescript { .api }
7
/**
8
* Creates a new context instance with optional async context support
9
* @param opts - Configuration options for the context
10
* @returns Context instance with getter, setter, and execution methods
11
*/
12
function createContext<T = any>(opts: ContextOptions): UseContext<T>;
13
14
interface UseContext<T> {
15
/**
16
* Get the current context. Throws if no context is set.
17
* @throws Error when context is not available
18
*/
19
use(): T;
20
21
/**
22
* Get the current context. Returns null when no context is set.
23
* @returns Current context instance or null if not set
24
*/
25
tryUse(): T | null;
26
27
/**
28
* Set the context as Singleton Pattern.
29
* @param instance - The context instance to set
30
* @param replace - Whether to replace existing conflicting context
31
* @throws Error if context conflict occurs and replace is false
32
*/
33
set(instance?: T, replace?: boolean): void;
34
35
/**
36
* Clear current context.
37
*/
38
unset(): void;
39
40
/**
41
* Execute a synchronous function with the provided context.
42
* @param instance - Context instance to provide during execution
43
* @param callback - Function to execute with context
44
* @returns Result of callback execution
45
* @throws Error if context conflict occurs
46
*/
47
call<R>(instance: T, callback: () => R): R;
48
49
/**
50
* Execute an asynchronous function with the provided context.
51
* Requires installing the transform plugin to work properly.
52
* @param instance - Context instance to provide during execution
53
* @param callback - Async function to execute with context
54
* @returns Promise resolving to callback result
55
*/
56
callAsync<R>(instance: T, callback: () => R | Promise<R>): Promise<R>;
57
}
58
59
interface ContextOptions {
60
/**
61
* Enable async context support using AsyncLocalStorage
62
*/
63
asyncContext?: boolean;
64
65
/**
66
* AsyncLocalStorage implementation for async context
67
*/
68
AsyncLocalStorage?: typeof AsyncLocalStorage;
69
}
70
```
71
72
## Basic Usage
73
74
### Creating and Using Context
75
76
```typescript
77
import { createContext } from "unctx";
78
79
interface User {
80
id: number;
81
name: string;
82
email: string;
83
}
84
85
// Create a typed context
86
const userContext = createContext<User>();
87
88
// Execute code with context
89
const result = userContext.call(
90
{ id: 1, name: "Alice", email: "alice@example.com" },
91
() => {
92
// Context is available throughout the call stack
93
const currentUser = userContext.use();
94
console.log(`Processing user: ${currentUser.name}`);
95
96
// Call other functions that can access the same context
97
return processUserData();
98
}
99
);
100
101
function processUserData() {
102
// Context is still available in nested functions
103
const user = userContext.use();
104
return `Processed data for ${user.email}`;
105
}
106
```
107
108
### Error Handling
109
110
```typescript
111
const myContext = createContext<string>();
112
113
// This will throw an error - no context set
114
try {
115
myContext.use();
116
} catch (error) {
117
console.error("Context not available:", error.message);
118
}
119
120
// Safe usage - returns null instead of throwing
121
const safeValue = myContext.tryUse(); // null
122
```
123
124
### Context Conflicts
125
126
```typescript
127
const ctx = createContext<string>();
128
129
ctx.call("A", () => {
130
// This will throw "Context conflict" error
131
try {
132
ctx.call("B", () => {
133
console.log("This won't execute");
134
});
135
} catch (error) {
136
console.error(error.message); // "Context conflict"
137
}
138
});
139
```
140
141
## Singleton Pattern
142
143
For shared instances that don't depend on request context:
144
145
```typescript
146
import { createContext } from "unctx";
147
148
interface AppConfig {
149
apiUrl: string;
150
version: string;
151
}
152
153
const configContext = createContext<AppConfig>();
154
155
// Set global configuration
156
configContext.set({
157
apiUrl: "https://api.example.com",
158
version: "1.0.0"
159
});
160
161
// Use throughout the application
162
function makeApiCall() {
163
const config = configContext.use();
164
return fetch(`${config.apiUrl}/data`);
165
}
166
167
// Clear singleton when needed
168
configContext.unset();
169
170
// Replace singleton configuration
171
configContext.set(newConfig, true); // true = replace existing
172
```
173
174
## Async Context with AsyncLocalStorage
175
176
```typescript
177
import { createContext } from "unctx";
178
import { AsyncLocalStorage } from "node:async_hooks";
179
180
interface RequestContext {
181
requestId: string;
182
userId: number;
183
}
184
185
const requestContext = createContext<RequestContext>({
186
asyncContext: true,
187
AsyncLocalStorage
188
});
189
190
// Context persists across async boundaries
191
await requestContext.callAsync(
192
{ requestId: "req-123", userId: 42 },
193
async () => {
194
console.log(requestContext.use().requestId); // "req-123"
195
196
await new Promise(resolve => setTimeout(resolve, 100));
197
198
// Context is still available after await
199
console.log(requestContext.use().requestId); // "req-123"
200
201
await processRequest();
202
}
203
);
204
205
async function processRequest() {
206
// Context available in async nested functions
207
const ctx = requestContext.use();
208
await fetch(`/api/users/${ctx.userId}`);
209
}
210
```
211
212
## Error Recovery
213
214
```typescript
215
const ctx = createContext<string>();
216
217
// Context is properly cleaned up even if callback throws
218
try {
219
ctx.call("test", () => {
220
throw new Error("Something went wrong");
221
});
222
} catch (error) {
223
console.error("Callback failed:", error.message);
224
}
225
226
// Context is cleared, can use with different value
227
ctx.call("new-value", () => {
228
console.log(ctx.use()); // "new-value"
229
});
230
```