or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-context.mdbuild-plugins.mdcontext-creation.mdindex.mdnamespace-management.md

context-creation.mddocs/

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

```