@context-action/core 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +379 -161
- package/dist/index.cjs +713 -286
- package/dist/index.d.cts +82 -21
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +82 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +707 -286
- package/dist/index.js.map +1 -1
- package/package.json +12 -12
package/README.md
CHANGED
|
@@ -1,33 +1,18 @@
|
|
|
1
1
|
# @context-action/core
|
|
2
2
|
|
|
3
|
-
Type-safe action pipeline management library for JavaScript/TypeScript applications.
|
|
3
|
+
Type-safe action pipeline management library for JavaScript/TypeScript applications with advanced filtering, performance optimizations, and React integration support.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install @context-action/core
|
|
8
|
+
npm install @context-action/core
|
|
9
|
+
# or
|
|
10
|
+
pnpm install @context-action/core
|
|
9
11
|
```
|
|
10
12
|
|
|
11
13
|
## Quick Start
|
|
12
14
|
|
|
13
|
-
### 1. Setup Environment Configuration
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
# Copy sample configuration
|
|
17
|
-
cp .env.sample .env
|
|
18
|
-
|
|
19
|
-
# Quick setup for maximum debugging detail
|
|
20
|
-
echo "NODE_ENV=development" >> .env
|
|
21
|
-
echo "CONTEXT_ACTION_TRACE=true" >> .env
|
|
22
|
-
echo "CONTEXT_ACTION_DEBUG=true" >> .env
|
|
23
|
-
echo "CONTEXT_ACTION_LOGGER_NAME=MyApp" >> .env
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
### 2. Basic Usage
|
|
27
|
-
|
|
28
15
|
```typescript
|
|
29
|
-
// Load environment variables first
|
|
30
|
-
import 'dotenv/config';
|
|
31
16
|
import { ActionRegister } from '@context-action/core';
|
|
32
17
|
|
|
33
18
|
// Define your action types
|
|
@@ -38,235 +23,468 @@ interface MyActions {
|
|
|
38
23
|
}
|
|
39
24
|
|
|
40
25
|
// Create action register
|
|
41
|
-
const actions = new ActionRegister<MyActions>(
|
|
26
|
+
const actions = new ActionRegister<MyActions>({
|
|
27
|
+
name: 'MyApp',
|
|
28
|
+
registry: { debug: true }
|
|
29
|
+
});
|
|
42
30
|
|
|
43
|
-
// Register handlers
|
|
44
|
-
actions.register('increment', (
|
|
31
|
+
// Register handlers with priorities
|
|
32
|
+
actions.register('increment', () => {
|
|
45
33
|
console.log('Increment called');
|
|
46
|
-
|
|
47
|
-
});
|
|
34
|
+
}, { priority: 10 });
|
|
48
35
|
|
|
49
|
-
actions.register('setCount', (count
|
|
36
|
+
actions.register('setCount', (count) => {
|
|
50
37
|
console.log(`Setting count to: ${count}`);
|
|
51
|
-
|
|
52
|
-
});
|
|
38
|
+
}, { priority: 5 });
|
|
53
39
|
|
|
54
40
|
// Dispatch actions
|
|
55
41
|
await actions.dispatch('increment');
|
|
56
42
|
await actions.dispatch('setCount', 42);
|
|
57
43
|
```
|
|
58
44
|
|
|
59
|
-
|
|
45
|
+
### Memory Management
|
|
60
46
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
47
|
+
```typescript
|
|
48
|
+
// Configure handler limits for memory safety (v0.4.1+)
|
|
49
|
+
const actions = new ActionRegister<MyActions>({
|
|
50
|
+
registry: {
|
|
51
|
+
maxHandlersPerAction: 1000 // Default: 1000, prevents memory issues
|
|
52
|
+
// maxHandlersPerAction: 5000 // Higher limit for complex applications
|
|
53
|
+
// maxHandlersPerAction: Infinity // Disable limit (use with caution)
|
|
54
|
+
}
|
|
55
|
+
});
|
|
68
56
|
|
|
69
|
-
|
|
57
|
+
// Use cases for different limits:
|
|
58
|
+
// - 1000 (default): Most applications
|
|
59
|
+
// - 5000-10000: Large enterprise applications
|
|
60
|
+
// - Infinity: Only for controlled environments with trusted code
|
|
61
|
+
```
|
|
70
62
|
|
|
71
|
-
## Features
|
|
63
|
+
## 🚀 New Features (v0.4.0+)
|
|
72
64
|
|
|
73
|
-
|
|
74
|
-
- **Priority-based execution** - Control handler execution order
|
|
75
|
-
- **Pipeline control** - Abort, modify payloads, conditional execution
|
|
76
|
-
- **Event system** - Listen to action lifecycle events
|
|
77
|
-
- **Comprehensive logging** - Detailed trace logging for debugging
|
|
78
|
-
- **Environment-based configuration** - Easy .env setup
|
|
65
|
+
### Advanced Filtering System
|
|
79
66
|
|
|
80
|
-
|
|
67
|
+
Filter handlers by priority, ID, or custom conditions:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// Filter by priority range
|
|
71
|
+
await actions.dispatch('updateUser', userData, {
|
|
72
|
+
filter: {
|
|
73
|
+
priority: { min: 10, max: 50 } // Only handlers with priority 10-50
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Filter by specific handler IDs
|
|
78
|
+
await actions.dispatch('processData', data, {
|
|
79
|
+
filter: {
|
|
80
|
+
handlerIds: ['validation', 'logging'], // Only these handlers
|
|
81
|
+
excludeHandlerIds: ['analytics'] // Exclude analytics handler
|
|
82
|
+
}
|
|
83
|
+
});
|
|
81
84
|
|
|
82
|
-
|
|
85
|
+
// Custom filtering logic
|
|
86
|
+
await actions.dispatch('secureAction', data, {
|
|
87
|
+
filter: {
|
|
88
|
+
custom: (config) => config.blocking === true // Only blocking handlers
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Combined filtering
|
|
93
|
+
await actions.dispatch('complexAction', data, {
|
|
94
|
+
filter: {
|
|
95
|
+
priority: { min: 20 },
|
|
96
|
+
excludeHandlerIds: ['debug'],
|
|
97
|
+
custom: (config) => !config.id.includes('test')
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Enhanced Handler Configuration
|
|
83
103
|
|
|
84
104
|
```typescript
|
|
85
105
|
actions.register('myAction', handler, {
|
|
86
|
-
priority: 10,
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
106
|
+
priority: 10,
|
|
107
|
+
id: 'my-handler',
|
|
108
|
+
blocking: true,
|
|
109
|
+
once: false,
|
|
110
|
+
debounce: 300,
|
|
111
|
+
throttle: 1000,
|
|
112
|
+
replaceExisting: true // 🆕 Replace handler with same ID (great for React HMR)
|
|
91
113
|
});
|
|
92
114
|
```
|
|
93
115
|
|
|
94
|
-
###
|
|
116
|
+
### Immediate Execution & Queue Control
|
|
95
117
|
|
|
96
118
|
```typescript
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
119
|
+
// Bypass queue for immediate execution
|
|
120
|
+
await actions.dispatch('urgentAction', data, {
|
|
121
|
+
immediate: true
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Queue with custom priority
|
|
125
|
+
await actions.dispatch('backgroundTask', data, {
|
|
126
|
+
queuePriority: 5
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Execution timeout
|
|
130
|
+
await actions.dispatch('timedAction', data, {
|
|
131
|
+
timeout: 5000
|
|
106
132
|
});
|
|
107
133
|
```
|
|
108
134
|
|
|
109
|
-
###
|
|
135
|
+
### Result Collection with Strategies
|
|
110
136
|
|
|
111
137
|
```typescript
|
|
112
|
-
actions.
|
|
113
|
-
|
|
138
|
+
const result = await actions.dispatchWithResult('processData', data, {
|
|
139
|
+
result: {
|
|
140
|
+
collect: true,
|
|
141
|
+
strategy: 'all', // 'first' | 'last' | 'all' | 'merge' | 'custom'
|
|
142
|
+
maxResults: 10,
|
|
143
|
+
includeErrors: true
|
|
144
|
+
}
|
|
114
145
|
});
|
|
115
146
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
147
|
+
console.log('Results:', result.results);
|
|
148
|
+
console.log('Execution time:', result.execution.duration);
|
|
149
|
+
console.log('Success:', result.success);
|
|
119
150
|
```
|
|
120
151
|
|
|
121
|
-
|
|
152
|
+
### React Integration Helpers
|
|
122
153
|
|
|
123
|
-
|
|
154
|
+
```typescript
|
|
155
|
+
import {
|
|
156
|
+
useActionHandler,
|
|
157
|
+
createReactDispatcher,
|
|
158
|
+
ReactDevUtils
|
|
159
|
+
} from '@context-action/core';
|
|
160
|
+
|
|
161
|
+
// React hook pattern
|
|
162
|
+
function MyComponent() {
|
|
163
|
+
const registry = useActionRegister();
|
|
164
|
+
|
|
165
|
+
// Auto-cleanup on unmount, HMR support
|
|
166
|
+
const handlerConfig = useActionHandler(
|
|
167
|
+
registry,
|
|
168
|
+
'userAction',
|
|
169
|
+
async (payload) => {
|
|
170
|
+
// Handler logic
|
|
171
|
+
},
|
|
172
|
+
{ priority: 10 },
|
|
173
|
+
[] // dependencies
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
// React-optimized dispatcher
|
|
177
|
+
const dispatch = createReactDispatcher(registry, (error, action) => {
|
|
178
|
+
console.error(`Failed to dispatch ${action}:`, error);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
124
181
|
|
|
125
|
-
|
|
182
|
+
// Development utilities
|
|
183
|
+
ReactDevUtils.enableDebugMode();
|
|
184
|
+
const stats = ReactDevUtils.getStats(registry);
|
|
185
|
+
```
|
|
126
186
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
187
|
+
## Core Features
|
|
188
|
+
|
|
189
|
+
### 🎯 Type-Safe Action Pipeline
|
|
190
|
+
- **Full TypeScript support** with compile-time type checking
|
|
191
|
+
- **Priority-based execution** with configurable handler ordering
|
|
192
|
+
- **Pipeline control** - abort, modify payloads, conditional execution
|
|
193
|
+
- **Multiple execution modes** - sequential, parallel, race
|
|
194
|
+
|
|
195
|
+
### ⚡ Performance & Memory Optimizations
|
|
196
|
+
- **Cached environment checks** for better performance
|
|
197
|
+
- **Optimized handler ID generation** without random numbers
|
|
198
|
+
- **Smart array filtering** - only copies when needed
|
|
199
|
+
- **Automatic memory cleanup** with idle handler cleanup
|
|
200
|
+
- **Optional concurrency queues** for thread safety
|
|
201
|
+
|
|
202
|
+
### 🔧 Advanced Configuration
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
const registry = new ActionRegister<MyActions>({
|
|
206
|
+
name: 'MyApp',
|
|
207
|
+
registry: {
|
|
208
|
+
debug: true,
|
|
209
|
+
autoCleanup: true,
|
|
210
|
+
defaultExecutionMode: 'sequential',
|
|
211
|
+
useConcurrencyQueue: true,
|
|
212
|
+
errorHandler: (error, context) => {
|
|
213
|
+
console.error('Unhandled action error:', error);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
});
|
|
141
217
|
```
|
|
142
218
|
|
|
143
|
-
###
|
|
219
|
+
### 🎛️ Pipeline Controller
|
|
144
220
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
221
|
+
Full control over pipeline execution:
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
actions.register('validate', (data, controller) => {
|
|
225
|
+
// Abort pipeline
|
|
226
|
+
if (!data.isValid) {
|
|
227
|
+
controller.abort('Validation failed');
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Modify payload for next handlers
|
|
232
|
+
controller.modifyPayload(data => ({
|
|
233
|
+
...data,
|
|
234
|
+
validated: true,
|
|
235
|
+
timestamp: Date.now()
|
|
236
|
+
}));
|
|
237
|
+
|
|
238
|
+
// Jump to high-priority handlers
|
|
239
|
+
if (data.urgent) {
|
|
240
|
+
controller.jumpToPriority(100);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Set result for collection
|
|
244
|
+
controller.setResult({ validation: 'passed' });
|
|
245
|
+
|
|
246
|
+
// Early return with result
|
|
247
|
+
if (data.fastPath) {
|
|
248
|
+
controller.return({ fastPath: true });
|
|
249
|
+
}
|
|
250
|
+
});
|
|
161
251
|
```
|
|
162
252
|
|
|
163
|
-
|
|
253
|
+
## Advanced Usage
|
|
164
254
|
|
|
165
|
-
|
|
255
|
+
### Action Guard (Debounce/Throttle)
|
|
166
256
|
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
257
|
+
```typescript
|
|
258
|
+
// Built-in debounce/throttle support
|
|
259
|
+
actions.register('searchUsers', searchHandler, {
|
|
260
|
+
debounce: 300 // Wait 300ms after last call
|
|
261
|
+
});
|
|
171
262
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
console.log('Handler executed:', payload);
|
|
175
|
-
// Handler automatically continues to next handler
|
|
263
|
+
actions.register('scrollHandler', updateUI, {
|
|
264
|
+
throttle: 100 // Max once per 100ms
|
|
176
265
|
});
|
|
177
|
-
await actions.dispatch('test', { message: 'Hello!' });" > test-logging.js
|
|
178
266
|
|
|
179
|
-
|
|
180
|
-
|
|
267
|
+
// Via dispatch options
|
|
268
|
+
await actions.dispatch('search', query, {
|
|
269
|
+
debounce: 500
|
|
270
|
+
});
|
|
181
271
|
```
|
|
182
272
|
|
|
183
|
-
|
|
273
|
+
### Execution Modes
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
// Set execution mode per action
|
|
277
|
+
actions.setActionExecutionMode('logEvent', 'parallel');
|
|
278
|
+
actions.setActionExecutionMode('fetchData', 'race');
|
|
279
|
+
|
|
280
|
+
// Override via dispatch options
|
|
281
|
+
await actions.dispatch('processFiles', files, {
|
|
282
|
+
executionMode: 'parallel'
|
|
283
|
+
});
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Error Handling & Recovery
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
actions.register('riskyOperation', async (data, controller) => {
|
|
290
|
+
try {
|
|
291
|
+
const result = await riskyAPI(data);
|
|
292
|
+
return result;
|
|
293
|
+
} catch (error) {
|
|
294
|
+
if (error.retryable) {
|
|
295
|
+
// Let other handlers try
|
|
296
|
+
return undefined;
|
|
297
|
+
} else {
|
|
298
|
+
// Abort pipeline for critical errors
|
|
299
|
+
controller.abort(`Critical error: ${error.message}`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
// With retry configuration
|
|
305
|
+
await actions.dispatch('apiCall', data, {
|
|
306
|
+
retryOnError: {
|
|
307
|
+
maxAttempts: 3,
|
|
308
|
+
delay: 1000
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
```
|
|
184
312
|
|
|
185
|
-
###
|
|
313
|
+
### Statistics & Monitoring
|
|
186
314
|
|
|
187
|
-
|
|
315
|
+
```typescript
|
|
316
|
+
// Registry information
|
|
317
|
+
const info = actions.getRegistryInfo();
|
|
318
|
+
console.log(`Total actions: ${info.totalActions}`);
|
|
319
|
+
console.log(`Total handlers: ${info.totalHandlers}`);
|
|
320
|
+
|
|
321
|
+
// Action-specific statistics
|
|
322
|
+
const stats = actions.getActionStats('updateUser');
|
|
323
|
+
if (stats) {
|
|
324
|
+
console.log(`Handler count: ${stats.handlerCount}`);
|
|
325
|
+
console.log(`Success rate: ${stats.executionStats?.successRate}%`);
|
|
326
|
+
console.log(`Average duration: ${stats.executionStats?.averageDuration}ms`);
|
|
327
|
+
}
|
|
188
328
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
# or
|
|
193
|
-
pnpm install dotenv
|
|
194
|
-
```
|
|
329
|
+
// Clear statistics
|
|
330
|
+
actions.clearExecutionStats();
|
|
331
|
+
```
|
|
195
332
|
|
|
196
|
-
|
|
197
|
-
```bash
|
|
198
|
-
cat .env
|
|
199
|
-
# Should show: CONTEXT_ACTION_TRACE=true
|
|
200
|
-
```
|
|
333
|
+
### Cleanup & Resource Management
|
|
201
334
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
import { ActionRegister } from '@context-action/core';
|
|
206
|
-
```
|
|
335
|
+
```typescript
|
|
336
|
+
// Explicit cleanup when done
|
|
337
|
+
const registry = new ActionRegister({ name: 'MyApp' });
|
|
207
338
|
|
|
208
|
-
|
|
339
|
+
// Use the registry...
|
|
209
340
|
|
|
210
|
-
|
|
341
|
+
// Clean up all resources
|
|
342
|
+
registry.destroy(); // Cleans up pipelines, guards, queues, stats
|
|
343
|
+
```
|
|
211
344
|
|
|
212
345
|
## API Reference
|
|
213
346
|
|
|
214
347
|
### ActionRegister<T>
|
|
215
348
|
|
|
216
|
-
|
|
217
|
-
|
|
349
|
+
#### Registration Methods
|
|
218
350
|
- `register<K>(action, handler, config?)` - Register action handler
|
|
219
|
-
- `
|
|
220
|
-
- `getHandlerCount(action)` - Get number of handlers for action
|
|
221
|
-
- `hasHandlers(action)` - Check if action has handlers
|
|
222
|
-
- `clearAction(action)` - Remove all handlers for action
|
|
351
|
+
- `clearAction(action)` - Remove all handlers for action
|
|
223
352
|
- `clearAll()` - Remove all handlers
|
|
224
|
-
- `on(event, handler)` - Add event listener
|
|
225
353
|
|
|
226
|
-
|
|
354
|
+
#### Dispatch Methods
|
|
355
|
+
- `dispatch<K>(action, payload?, options?)` - Dispatch action
|
|
356
|
+
- `dispatchWithResult<K>(action, payload?, options?)` - Dispatch with detailed results
|
|
357
|
+
|
|
358
|
+
#### Information Methods
|
|
359
|
+
- `getHandlerCount(action)` - Get handler count for action
|
|
360
|
+
- `hasHandlers(action)` - Check if action has handlers
|
|
361
|
+
- `getRegisteredActions()` - Get all registered action names
|
|
362
|
+
- `getRegistryInfo()` - Get comprehensive registry information
|
|
363
|
+
- `getActionStats(action)` - Get detailed action statistics
|
|
364
|
+
|
|
365
|
+
#### Execution Mode Methods
|
|
366
|
+
- `setActionExecutionMode(action, mode)` - Set execution mode for action
|
|
367
|
+
- `getActionExecutionMode(action)` - Get execution mode for action
|
|
368
|
+
- `removeActionExecutionMode(action)` - Reset to default execution mode
|
|
369
|
+
|
|
370
|
+
#### Utility Methods
|
|
371
|
+
- `getName()` - Get registry name
|
|
372
|
+
- `isDebugEnabled()` - Check if debug mode is enabled
|
|
373
|
+
- `destroy()` - Clean up all resources
|
|
374
|
+
|
|
375
|
+
### Configuration Interfaces
|
|
227
376
|
|
|
228
377
|
```typescript
|
|
229
|
-
interface
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
378
|
+
interface HandlerConfig {
|
|
379
|
+
priority?: number; // Handler priority (higher = first)
|
|
380
|
+
id?: string; // Unique handler identifier
|
|
381
|
+
blocking?: boolean; // Wait for async completion
|
|
382
|
+
once?: boolean; // Remove after first execution
|
|
383
|
+
debounce?: number; // Debounce delay in ms
|
|
384
|
+
throttle?: number; // Throttle delay in ms
|
|
385
|
+
replaceExisting?: boolean; // Replace handler with same ID
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
interface DispatchOptions {
|
|
389
|
+
debounce?: number;
|
|
390
|
+
throttle?: number;
|
|
391
|
+
executionMode?: 'sequential' | 'parallel' | 'race';
|
|
392
|
+
signal?: AbortSignal;
|
|
393
|
+
immediate?: boolean; // Bypass queue
|
|
394
|
+
queuePriority?: number; // Queue priority
|
|
395
|
+
timeout?: number; // Execution timeout
|
|
396
|
+
|
|
397
|
+
retryOnError?: {
|
|
398
|
+
maxAttempts: number;
|
|
399
|
+
delay: number;
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
filter?: {
|
|
403
|
+
handlerIds?: string[];
|
|
404
|
+
excludeHandlerIds?: string[];
|
|
405
|
+
priority?: { min?: number; max?: number };
|
|
406
|
+
custom?: (config: HandlerConfig) => boolean;
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
result?: {
|
|
410
|
+
strategy?: 'first' | 'last' | 'all' | 'merge' | 'custom';
|
|
411
|
+
merger?: <R>(results: R[]) => R;
|
|
412
|
+
collect?: boolean;
|
|
413
|
+
maxResults?: number;
|
|
414
|
+
includeErrors?: boolean;
|
|
415
|
+
};
|
|
234
416
|
}
|
|
235
417
|
```
|
|
236
418
|
|
|
237
419
|
## TypeScript Support
|
|
238
420
|
|
|
239
|
-
Full
|
|
421
|
+
Full type safety with excellent IntelliSense support:
|
|
240
422
|
|
|
241
423
|
```typescript
|
|
242
424
|
interface AppActions {
|
|
243
|
-
//
|
|
425
|
+
// Void actions
|
|
244
426
|
reset: void;
|
|
427
|
+
logout: void;
|
|
245
428
|
|
|
246
|
-
//
|
|
247
|
-
setUser: { id: string; name: string };
|
|
429
|
+
// Actions with payloads
|
|
430
|
+
setUser: { id: string; name: string; email: string };
|
|
431
|
+
updatePreferences: { theme: 'light' | 'dark'; language: string };
|
|
248
432
|
|
|
249
|
-
//
|
|
250
|
-
navigate: string |
|
|
433
|
+
// Union type payloads
|
|
434
|
+
navigate: { route: string } | { url: URL };
|
|
251
435
|
}
|
|
252
436
|
|
|
253
437
|
const actions = new ActionRegister<AppActions>();
|
|
254
438
|
|
|
255
|
-
// ✅ Type-safe
|
|
439
|
+
// ✅ Type-safe - all good
|
|
256
440
|
await actions.dispatch('reset');
|
|
257
|
-
await actions.dispatch('setUser', { id: '1', name: 'John' });
|
|
441
|
+
await actions.dispatch('setUser', { id: '1', name: 'John', email: 'john@example.com' });
|
|
442
|
+
|
|
443
|
+
// ❌ TypeScript errors
|
|
444
|
+
await actions.dispatch('setUser'); // Missing required payload
|
|
445
|
+
await actions.dispatch('setUser', { id: '1' }); // Missing required fields
|
|
446
|
+
await actions.dispatch('invalidAction'); // Unknown action
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
## Migration from v0.3.x
|
|
450
|
+
|
|
451
|
+
Most existing code works without changes. New features are opt-in:
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
// v0.3.x code - still works
|
|
455
|
+
const actions = new ActionRegister();
|
|
456
|
+
actions.register('myAction', handler);
|
|
457
|
+
await actions.dispatch('myAction', payload);
|
|
258
458
|
|
|
259
|
-
//
|
|
260
|
-
|
|
459
|
+
// v0.4.x - new features available
|
|
460
|
+
actions.register('myAction', handler, {
|
|
461
|
+
replaceExisting: true // New option
|
|
462
|
+
});
|
|
261
463
|
|
|
262
|
-
|
|
263
|
-
|
|
464
|
+
await actions.dispatch('myAction', payload, {
|
|
465
|
+
filter: { priority: { min: 10 } } // New filtering
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
// Clean up when done (recommended)
|
|
469
|
+
actions.destroy();
|
|
264
470
|
```
|
|
265
471
|
|
|
472
|
+
## Performance Tips
|
|
473
|
+
|
|
474
|
+
1. **Use handler IDs** for better debugging and filtering
|
|
475
|
+
2. **Enable replaceExisting** for React components to prevent duplicates
|
|
476
|
+
3. **Use immediate: false** (default) to benefit from queue optimizations
|
|
477
|
+
4. **Call destroy()** when registry is no longer needed
|
|
478
|
+
5. **Use priority filtering** instead of excludeHandlerIds for better performance
|
|
479
|
+
6. **Cache ActionRegister instances** - don't create new ones frequently
|
|
480
|
+
|
|
266
481
|
## License
|
|
267
482
|
|
|
268
483
|
Apache-2.0
|
|
269
484
|
|
|
270
|
-
##
|
|
485
|
+
## Links
|
|
271
486
|
|
|
272
|
-
|
|
487
|
+
- [Main Repository](https://github.com/mineclover/context-action)
|
|
488
|
+
- [Documentation](https://mineclover.github.io/context-action/)
|
|
489
|
+
- [React Package](../react/README.md)
|
|
490
|
+
- [Examples](../../example/README.md)
|