@context-action/core 0.8.4 → 0.8.8

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 CHANGED
@@ -1,6 +1,8 @@
1
1
  # @context-action/core
2
2
 
3
- Type-safe action pipeline management library for JavaScript/TypeScript applications with advanced filtering, performance optimizations, and React integration support.
3
+ Type-safe action pipeline management library for **vanilla JavaScript/TypeScript** applications with advanced filtering, performance optimizations, and optional React integration support.
4
+
5
+ > **✨ Framework-Agnostic**: Works with vanilla JavaScript, React, Vue, Svelte, or any JavaScript environment. No framework dependencies required!
4
6
 
5
7
  ## Installation
6
8
 
@@ -10,6 +12,15 @@ npm install @context-action/core
10
12
  pnpm install @context-action/core
11
13
  ```
12
14
 
15
+ ### CDN (for quick prototyping)
16
+
17
+ ```html
18
+ <script type="module">
19
+ import { ActionRegister } from 'https://esm.sh/@context-action/core@latest';
20
+ // Your code here
21
+ </script>
22
+ ```
23
+
13
24
  ## Quick Start
14
25
 
15
26
  ```typescript
@@ -42,6 +53,94 @@ await actions.dispatch('increment');
42
53
  await actions.dispatch('setCount', 42);
43
54
  ```
44
55
 
56
+ ## 🌟 Vanilla JavaScript Support
57
+
58
+ **@context-action/core works perfectly with vanilla JavaScript!** No React, Vue, or any framework required.
59
+
60
+ ### Browser Example (HTML + JavaScript)
61
+
62
+ ```html
63
+ <!DOCTYPE html>
64
+ <html>
65
+ <head>
66
+ <title>Context-Action Example</title>
67
+ </head>
68
+ <body>
69
+ <div id="counter">0</div>
70
+ <button id="increment">Increment</button>
71
+
72
+ <script type="module">
73
+ import { ActionRegister } from 'https://esm.sh/@context-action/core@latest';
74
+
75
+ // Simple store
76
+ class Store {
77
+ constructor(initialState) {
78
+ this.state = initialState;
79
+ this.listeners = new Set();
80
+ }
81
+ getValue() { return this.state; }
82
+ setValue(newState) {
83
+ this.state = newState;
84
+ this.listeners.forEach(fn => fn(this.state));
85
+ }
86
+ subscribe(listener) {
87
+ this.listeners.add(listener);
88
+ return () => this.listeners.delete(listener);
89
+ }
90
+ }
91
+
92
+ // Create store and actions
93
+ const counterStore = new Store({ count: 0 });
94
+ const actions = new ActionRegister({ name: 'Counter' });
95
+
96
+ // Register handler
97
+ actions.register('increment', () => {
98
+ const current = counterStore.getValue();
99
+ counterStore.setValue({ count: current.count + 1 });
100
+ });
101
+
102
+ // Subscribe to updates
103
+ counterStore.subscribe(state => {
104
+ document.getElementById('counter').textContent = state.count;
105
+ });
106
+
107
+ // Wire up button
108
+ document.getElementById('increment').onclick = () => {
109
+ actions.dispatch('increment');
110
+ };
111
+ </script>
112
+ </body>
113
+ </html>
114
+ ```
115
+
116
+ ### Node.js Example
117
+
118
+ ```javascript
119
+ import { ActionRegister } from '@context-action/core';
120
+
121
+ const actions = new ActionRegister({ name: 'MyApp' });
122
+
123
+ actions.register('processData', async (data, controller) => {
124
+ console.log('Processing:', data);
125
+
126
+ // Business logic here
127
+ const result = await someAsyncOperation(data);
128
+
129
+ controller.setResult(result);
130
+ }, { priority: 100 });
131
+
132
+ // Dispatch action
133
+ const result = await actions.dispatchWithResult('processData', {
134
+ input: 'example'
135
+ });
136
+
137
+ console.log('Result:', result.successResults);
138
+ ```
139
+
140
+ **📚 Learn More:**
141
+ - [Vanilla JavaScript Guide](../../docs/en/guide/vanilla-js-guide.md) - Complete guide with examples
142
+ - [Live Examples](../../examples/vanilla-js/) - Interactive HTML examples (counter, todo app)
143
+
45
144
  ### Memory Management
46
145
 
47
146
  ```typescript
@@ -126,12 +225,21 @@ await actions.dispatch('backgroundTask', data, {
126
225
  queuePriority: 5
127
226
  });
128
227
 
129
- // Execution timeout
130
- await actions.dispatch('timedAction', data, {
131
- timeout: 5000
132
- });
228
+ // Wall-clock timeout (queue wait + retry delay included).
229
+ // Rejects with ActionTimeoutError while the internal operation drains safely.
230
+ await actions.dispatch('timedAction', data, { timeout: 5000 });
133
231
  ```
134
232
 
233
+ The default queue is single-slot. When a handler awaits another dispatch on
234
+ the **same** register, make that nested call explicit with `{ immediate: true }`
235
+ so it can run inside the current queue turn. Likewise, do not set
236
+ `queuePriority` on an awaited nested `dispatchWithResult` call. Independent
237
+ top-level dispatches should keep the queue defaults.
238
+
239
+ Handlers that perform cancellable I/O can observe `controller.signal`. It is
240
+ aborted for caller cancellation, timeout, provider teardown, and register
241
+ shutdown.
242
+
135
243
  ### Result Collection with Strategies
136
244
 
137
245
  ```typescript
@@ -307,7 +415,7 @@ actions.register('riskyOperation', async (data, controller) => {
307
415
  // With retry configuration
308
416
  await actions.dispatch('apiCall', data, {
309
417
  retryOnError: {
310
- maxAttempts: 3,
418
+ maxAttempts: 3, // Total attempts, including the first call
311
419
  delay: 1000
312
420
  }
313
421
  });
@@ -341,8 +449,11 @@ const registry = new ActionRegister({ name: 'MyApp' });
341
449
 
342
450
  // Use the registry...
343
451
 
344
- // Clean up all resources
345
- registry.destroy(); // Cleans up pipelines, guards, queues, stats
452
+ // Begin terminal cleanup. New work is rejected immediately.
453
+ registry.destroy();
454
+
455
+ // Or await proof that started handlers settled and cleanup callbacks ran.
456
+ await registry.destroyAsync();
346
457
  ```
347
458
 
348
459
  ## API Reference
@@ -373,7 +484,8 @@ registry.destroy(); // Cleans up pipelines, guards, queues, stats
373
484
  #### Utility Methods
374
485
  - `getName()` - Get registry name
375
486
  - `isDebugEnabled()` - Check if debug mode is enabled
376
- - `destroy()` - Clean up all resources
487
+ - `destroy()` - Begin terminal cleanup without waiting
488
+ - `destroyAsync()` - Resolve after started handlers settle and cleanup completes
377
489
 
378
490
  ### Configuration Interfaces
379
491
 
@@ -477,7 +589,7 @@ actions.destroy();
477
589
  1. **Use handler IDs** for better debugging and filtering
478
590
  2. **Enable replaceExisting** for React components to prevent duplicates
479
591
  3. **Use immediate: false** (default) to benefit from queue optimizations
480
- 4. **Call destroy()** when registry is no longer needed
592
+ 4. **Await destroyAsync()** when shutdown completion must be guaranteed
481
593
  5. **Use priority filtering** instead of excludeHandlerIds for better performance
482
594
  6. **Cache ActionRegister instances** - don't create new ones frequently
483
595
 
@@ -489,5 +601,7 @@ Apache-2.0
489
601
 
490
602
  - [Main Repository](https://github.com/mineclover/context-action)
491
603
  - [Documentation](https://mineclover.github.io/context-action/)
492
- - [React Package](../react/README.md)
493
- - [Examples](../../example/README.md)
604
+ - [Vanilla JS Guide](../../docs/en/guide/vanilla-js-guide.md) - Complete vanilla JavaScript guide
605
+ - [Vanilla JS Examples](../../examples/vanilla-js/) - Interactive examples (counter, todo app)
606
+ - [React Package](../react/README.md) - React integration
607
+ - [Examples](../../example/README.md) - React example application