0
# Context Management
1
2
Core dependency injection and state management system through Container and Slice patterns. Provides type-safe reactive state management with watcher support, ideal for building plugin-based architectures where components need to share and react to state changes.
3
4
## Capabilities
5
6
### Container Class
7
8
Central registry that manages typed slices for dependency injection. Acts as a type-safe container where slices can be stored, retrieved, and managed by type or name.
9
10
```typescript { .api }
11
/**
12
* Container manages a collection of typed slices for dependency injection
13
*/
14
class Container {
15
/** Get a slice from the container by slice type or slice name */
16
get<T, N extends string = string>(slice: SliceType<T, N> | N): Slice<T, N>;
17
/** Remove a slice from the container by slice type or slice name */
18
remove<T, N extends string = string>(slice: SliceType<T, N> | N): void;
19
/** Check if the container has a slice by slice type or slice name */
20
has<T, N extends string = string>(slice: SliceType<T, N> | N): boolean;
21
}
22
```
23
24
**Usage Examples:**
25
26
```typescript
27
import { Container, createSlice } from "@milkdown/ctx";
28
29
const container = new Container();
30
const userSlice = createSlice({ name: "Anonymous" }, "user");
31
32
// Create and add slice to container
33
userSlice.create(container.sliceMap, { name: "Alice" });
34
35
// Check if slice exists
36
if (container.has(userSlice)) {
37
const slice = container.get(userSlice);
38
console.log(slice.get()); // { name: "Alice" }
39
}
40
41
// Remove slice
42
container.remove(userSlice);
43
```
44
45
### Slice Class
46
47
Container for typed values with reactive update capabilities. Supports watchers for reactive programming patterns and provides methods for value management.
48
49
```typescript { .api }
50
/**
51
* Slice holds a typed value and supports reactive updates through watchers
52
*/
53
class Slice<T = any, N extends string = string> {
54
/** The type of the slice */
55
readonly type: SliceType<T, N>;
56
57
/** Add a watcher for changes in the slice, returns unsubscribe function */
58
on(watcher: (value: T) => unknown): () => void;
59
/** Add a one-time watcher that removes itself after first call */
60
once(watcher: (value: T) => unknown): () => void;
61
/** Remove a specific watcher */
62
off(watcher: (value: T) => unknown): void;
63
/** Remove all watchers */
64
offAll(): void;
65
/** Set the value of the slice and notify all watchers */
66
set(value: T): void;
67
/** Get the current value of the slice */
68
get(): T;
69
/** Update the value using a callback function and notify watchers */
70
update(updater: (prev: T) => T): void;
71
}
72
```
73
74
**Usage Examples:**
75
76
```typescript
77
import { Container, createSlice } from "@milkdown/ctx";
78
79
const container = new Container();
80
const counterSlice = createSlice(0, "counter");
81
const slice = counterSlice.create(container.sliceMap);
82
83
// Watch for changes
84
const unsubscribe = slice.on((value) => {
85
console.log("Counter updated:", value);
86
});
87
88
// Update values
89
slice.set(5); // Logs: "Counter updated: 5"
90
slice.update((prev) => prev + 1); // Logs: "Counter updated: 6"
91
92
// One-time watcher
93
slice.once((value) => {
94
console.log("This will only log once:", value);
95
});
96
97
slice.set(10); // Logs both watchers
98
slice.set(20); // Only logs the persistent watcher
99
100
// Cleanup
101
unsubscribe();
102
slice.offAll();
103
```
104
105
### SliceType Class
106
107
Type definition for creating slices across different containers. Defines the structure and default value for slices while maintaining type safety.
108
109
```typescript { .api }
110
/**
111
* SliceType defines the structure for creating typed slices
112
*/
113
class SliceType<T = any, N extends string = string> {
114
/** Unique identifier for the slice type */
115
readonly id: symbol;
116
/** Human-readable name for the slice type */
117
readonly name: N;
118
119
/** Create a slice type with a default value and unique name */
120
constructor(value: T, name: N);
121
/** Create a slice instance in the specified container */
122
create(container: SliceMap, value?: T): Slice<T, N>;
123
}
124
```
125
126
**Usage Examples:**
127
128
```typescript
129
import { Container, SliceType } from "@milkdown/ctx";
130
131
// Create slice type
132
const configSliceType = new SliceType(
133
{ theme: "light", language: "en" },
134
"config"
135
);
136
137
const container = new Container();
138
139
// Create slice with default value
140
const configSlice = configSliceType.create(container.sliceMap);
141
console.log(configSlice.get()); // { theme: "light", language: "en" }
142
143
// Create slice with custom value
144
const customConfigSlice = configSliceType.create(
145
container.sliceMap,
146
{ theme: "dark", language: "es" }
147
);
148
console.log(customConfigSlice.get()); // { theme: "dark", language: "es" }
149
```
150
151
### createSlice Function
152
153
Factory function for creating SliceType instances with cleaner syntax.
154
155
```typescript { .api }
156
/**
157
* Factory function for creating SliceType instances
158
* @param value - Default value for the slice
159
* @param name - Unique name for the slice type
160
* @returns New SliceType instance
161
*/
162
function createSlice<T = any, N extends string = string>(
163
value: T,
164
name: N
165
): SliceType<T, N>;
166
```
167
168
**Usage Examples:**
169
170
```typescript
171
import { createSlice, Container } from "@milkdown/ctx";
172
173
// Create different types of slices
174
const stringSlice = createSlice("hello", "greeting");
175
const numberSlice = createSlice(42, "answer");
176
const arraySlice = createSlice<string[]>([], "items");
177
const objectSlice = createSlice({ x: 0, y: 0 }, "position");
178
179
const container = new Container();
180
181
// Use them in containers
182
const greeting = stringSlice.create(container.sliceMap);
183
const position = objectSlice.create(container.sliceMap, { x: 10, y: 20 });
184
185
console.log(greeting.get()); // "hello"
186
console.log(position.get()); // { x: 10, y: 20 }
187
```
188
189
## Types
190
191
```typescript { .api }
192
/** Internal type for the container's slice storage */
193
type SliceMap = Map<symbol, Slice>;
194
```
195
196
## Error Handling
197
198
The context management system throws specific errors from `@milkdown/exception`:
199
200
- **contextNotFound**: Thrown when attempting to get a slice that doesn't exist in the container
201
- **ctxCallOutOfScope**: Thrown when calling slice type methods outside of proper context
202
203
```typescript
204
import { Container, createSlice } from "@milkdown/ctx";
205
206
const container = new Container();
207
const missingSlice = createSlice("test", "missing");
208
209
try {
210
container.get(missingSlice); // Throws contextNotFound error
211
} catch (error) {
212
console.error("Slice not found:", error.message);
213
}
214
```