jw-automator 4.0.0 → 6.0.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/CHANGELOG.md +0 -0
- package/README.md +392 -99
- package/docs/11a-macro-fix.md +56 -0
- package/docs/ARCHITECTURE.md +88 -73
- package/docs/MIGRATION.md +218 -54
- package/docs/QUICKSTART.md +63 -48
- package/docs/defensive-defaults.md +9 -9
- package/examples/basic-example.js +24 -9
- package/examples/hello-world.js +2 -2
- package/examples/iot-sensor-example.js +6 -6
- package/examples/seed-example.js +6 -6
- package/index.js +0 -0
- package/package.json +2 -2
- package/src/Automator.js +558 -313
- package/src/core/CoreEngine.js +103 -159
- package/src/core/RecurrenceEngine.js +67 -6
- package/src/host/SchedulerHost.js +60 -14
- package/src/storage/FileStorage.js +0 -59
- package/src/storage/MemoryStorage.js +0 -27
package/docs/MIGRATION.md
CHANGED
|
@@ -1,3 +1,85 @@
|
|
|
1
|
+
# Migration Guide
|
|
2
|
+
|
|
3
|
+
## v5.0.0 - Storage API Simplification & Moratorium-Based Persistence
|
|
4
|
+
|
|
5
|
+
### Breaking Change: Storage API Simplified
|
|
6
|
+
|
|
7
|
+
The pluggable storage adapter pattern has been removed in favor of a simpler direct configuration.
|
|
8
|
+
|
|
9
|
+
**Old API (v4):**
|
|
10
|
+
```javascript
|
|
11
|
+
const automator = new Automator({
|
|
12
|
+
storage: Automator.storage.file('./tasks.json')
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const automator = new Automator({
|
|
16
|
+
storage: Automator.storage.memory()
|
|
17
|
+
});
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**New API (v5):**
|
|
21
|
+
```javascript
|
|
22
|
+
// File storage
|
|
23
|
+
const automator = new Automator({
|
|
24
|
+
storageFile: './tasks.json'
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Memory-only mode
|
|
28
|
+
const automator = new Automator({
|
|
29
|
+
// No storageFile option = memory-only
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### New: Moratorium-Based Persistence
|
|
34
|
+
|
|
35
|
+
v5 introduces a moratorium-based persistence state machine that reduces disk wear:
|
|
36
|
+
|
|
37
|
+
- **CRUD operations** (add/update/remove) save immediately and start a moratorium period
|
|
38
|
+
- **Task execution** (state progression) marks state as dirty and saves if moratorium has expired
|
|
39
|
+
- If moratorium is active, dirty state waits until moratorium ends, then saves automatically
|
|
40
|
+
- **Default `saveInterval`** changed from 5000ms to **15000ms (15 seconds)**
|
|
41
|
+
- `saveInterval` now defines the moratorium period (minimum cooling time between saves)
|
|
42
|
+
- `stop()` always saves immediately if dirty, ignoring any active moratorium
|
|
43
|
+
|
|
44
|
+
**Why this matters:** Reduces disk writes from task execution (critical for SD cards/flash media) while ensuring CRUD changes are persisted immediately. The moratorium-based approach eliminates wasteful periodic polling.
|
|
45
|
+
|
|
46
|
+
### Changes Required
|
|
47
|
+
|
|
48
|
+
1. **File storage:** Replace `storage: Automator.storage.file(path)` with `storageFile: path`
|
|
49
|
+
2. **Memory storage:** Remove `storage: Automator.storage.memory()` entirely (omit `storageFile`)
|
|
50
|
+
3. **Custom storage adapters:** No longer supported via plug-in interface
|
|
51
|
+
4. **`saveInterval` default:** Changed from 5000ms to 15000ms (update if you relied on the old default)
|
|
52
|
+
|
|
53
|
+
### Custom Storage Migration
|
|
54
|
+
|
|
55
|
+
If you were using custom storage adapters, use this pattern instead:
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
const automator = new Automator(); // Memory-only
|
|
59
|
+
|
|
60
|
+
// Load from custom source on initialization
|
|
61
|
+
automator.seed(async (auto) => {
|
|
62
|
+
const tasks = await yourCustomLoad();
|
|
63
|
+
tasks.forEach(task => auto.addTask(task));
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Save on updates
|
|
67
|
+
automator.on('update', async () => {
|
|
68
|
+
const tasks = automator.getTasks();
|
|
69
|
+
await yourCustomSave(tasks);
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Removed
|
|
74
|
+
|
|
75
|
+
- `Automator.storage.file()` static method
|
|
76
|
+
- `Automator.storage.memory()` static method
|
|
77
|
+
- `FileStorage` class (integrated into Automator)
|
|
78
|
+
- `MemoryStorage` class (no longer needed)
|
|
79
|
+
- Custom storage adapter interface (`{ load(), save() }`)
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
1
83
|
# Migration Guide: v3 to v4
|
|
2
84
|
|
|
3
85
|
This guide helps you migrate from jw-automator v3 to v4.
|
|
@@ -6,7 +88,7 @@ This guide helps you migrate from jw-automator v3 to v4.
|
|
|
6
88
|
|
|
7
89
|
## Overview
|
|
8
90
|
|
|
9
|
-
jw-automator v4 is a significant refinement of v3's architecture, focusing on making the scheduler's behavior even more predictable and robust out-of-the-box. While v3 represented a complete rewrite, v4 introduces breaking changes by refining default behaviors and error handling for
|
|
91
|
+
jw-automator v4 is a significant refinement of v3's architecture, focusing on making the scheduler's behavior even more predictable and robust out-of-the-box. While v3 represented a complete rewrite, v4 introduces breaking changes by refining default behaviors and error handling for task specifications.
|
|
10
92
|
|
|
11
93
|
v3 was the widely-deployed production version. v4 builds upon that foundation with enhanced predictability.
|
|
12
94
|
|
|
@@ -17,18 +99,18 @@ v3 was the widely-deployed production version. v4 builds upon that foundation wi
|
|
|
17
99
|
### 1. Default `catchUpWindow` Behavior Changed
|
|
18
100
|
|
|
19
101
|
**v3:** If `catchUpWindow` was not specified, it defaulted to `"unlimited"` (catch up all missed executions).
|
|
20
|
-
**v4:** If `catchUpWindow` is not specified, it now uses a **smart default** based on the
|
|
21
|
-
- For **recurring
|
|
22
|
-
- For **one-time
|
|
102
|
+
**v4:** If `catchUpWindow` is not specified, it now uses a **smart default** based on the task type:
|
|
103
|
+
- For **recurring tasks**, it defaults to the **duration of the recurrence interval** (e.g., an hourly task gets a 1-hour `catchUpWindow`).
|
|
104
|
+
- For **one-time tasks**, it defaults to **`0`** (skip all missed executions).
|
|
23
105
|
|
|
24
|
-
**Impact:** User applications that relied on the implicit "unlimited" catch-up for all
|
|
106
|
+
**Impact:** User applications that relied on the implicit "unlimited" catch-up for all tasks in v3 might now see tasks being skipped or fast-forwarded more aggressively. If you desire the old "unlimited" catch-up, you must explicitly set `catchUpWindow: "unlimited"`.
|
|
25
107
|
|
|
26
108
|
### 2. Invalid `repeat.type` Throws a Fatal Error
|
|
27
109
|
|
|
28
110
|
**v3:** If `repeat.type` was missing or invalid (e.g., a typo like `'horu'`), Automator would defensively coerce it to `'day'` and emit an `error` event.
|
|
29
111
|
**v4:** An invalid or missing `repeat.type` now throws a hard `Error` immediately.
|
|
30
112
|
|
|
31
|
-
**Impact:** Code that previously succeeded by silently allowing `repeat.type` coercions will now fail fast, forcing explicit correction. This ensures that the
|
|
113
|
+
**Impact:** Code that previously succeeded by silently allowing `repeat.type` coercions will now fail fast, forcing explicit correction. This ensures that the task's intent is never misinterpreted.
|
|
32
114
|
|
|
33
115
|
### 3. Coercion Events Changed from `error` to `warning`
|
|
34
116
|
|
|
@@ -37,36 +119,64 @@ v3 was the widely-deployed production version. v4 builds upon that foundation wi
|
|
|
37
119
|
|
|
38
120
|
**Impact:** If your application was listening for `automator.on('error', ...)` to catch these coercion notifications, you must now update your event listener to `automator.on('warning', ...)` to continue receiving them.
|
|
39
121
|
|
|
122
|
+
### 4. API Method Names Changed (action → task)
|
|
123
|
+
|
|
124
|
+
**v3:** Methods used "action" terminology: `addAction`, `updateActionByID`, `getActions`, etc.
|
|
125
|
+
**v4:** All methods now use "task" terminology: `addTask`, `updateTaskByID`, `getTasks`, etc.
|
|
126
|
+
|
|
127
|
+
**Impact:** All API calls need to be updated to use the new method names.
|
|
128
|
+
|
|
129
|
+
### 5. Event Name Changed
|
|
130
|
+
|
|
131
|
+
**v3:** Task execution emitted an `'action'` event.
|
|
132
|
+
**v4:** Task execution now emits a `'task'` event.
|
|
133
|
+
|
|
134
|
+
**Impact:** Update event listeners from `automator.on('action', ...)` to `automator.on('task', ...)`.
|
|
135
|
+
|
|
136
|
+
### 6. Event Object Properties Changed
|
|
137
|
+
|
|
138
|
+
**v3:** Event objects contained `actionId` and `action` properties.
|
|
139
|
+
**v4:** Event objects now contain `taskId` and `task` properties.
|
|
140
|
+
|
|
141
|
+
**Impact:** Update code that accesses these properties in event handlers.
|
|
142
|
+
|
|
143
|
+
### 7. State Structure Changed
|
|
144
|
+
|
|
145
|
+
**v3:** State contained an `actions` array.
|
|
146
|
+
**v4:** State now contains a `tasks` array.
|
|
147
|
+
|
|
148
|
+
**Impact:** Custom storage adapters need to return `{ tasks: [...] }` instead of `{ actions: [...] }`. Existing stored state files need migration.
|
|
149
|
+
|
|
40
150
|
---
|
|
41
151
|
|
|
42
|
-
## Breaking Changes from
|
|
152
|
+
## Breaking Changes from v2 to v3
|
|
43
153
|
|
|
44
154
|
### 1. Constructor and Initialization
|
|
45
155
|
|
|
46
156
|
**v2:**
|
|
47
157
|
```javascript
|
|
48
158
|
const automator = require('jw-automator');
|
|
49
|
-
automator.init({ file: './
|
|
159
|
+
automator.init({ file: './tasks.json' });
|
|
50
160
|
```
|
|
51
161
|
|
|
52
162
|
**v3:**
|
|
53
163
|
```javascript
|
|
54
164
|
const Automator = require('jw-automator');
|
|
55
165
|
const automator = new Automator({
|
|
56
|
-
storage: Automator.storage.file('./
|
|
166
|
+
storage: Automator.storage.file('./tasks.json')
|
|
57
167
|
});
|
|
58
168
|
```
|
|
59
169
|
|
|
60
|
-
### 2.
|
|
170
|
+
### 2. Task Structure
|
|
61
171
|
|
|
62
172
|
**v2:**
|
|
63
|
-
|
|
173
|
+
Task structure was less formalized.
|
|
64
174
|
|
|
65
175
|
**v3:**
|
|
66
176
|
```javascript
|
|
67
177
|
{
|
|
68
178
|
id: 1, // Auto-generated
|
|
69
|
-
name: 'My
|
|
179
|
+
name: 'My Task', // Optional
|
|
70
180
|
cmd: 'commandName', // Required
|
|
71
181
|
payload: {}, // Optional
|
|
72
182
|
date: Date, // Required (or null for immediate)
|
|
@@ -105,84 +215,86 @@ Various event names.
|
|
|
105
215
|
**v3:**
|
|
106
216
|
Standardized events:
|
|
107
217
|
- `ready` - Scheduler started
|
|
108
|
-
- `
|
|
109
|
-
- `update` -
|
|
218
|
+
- `task` - Task executed
|
|
219
|
+
- `update` - Task added/updated/removed
|
|
110
220
|
- `error` - Error occurred
|
|
111
221
|
- `debug` - Debug information
|
|
112
222
|
|
|
113
223
|
### 5. API Methods
|
|
114
224
|
|
|
115
|
-
#### Adding
|
|
225
|
+
#### Adding Tasks
|
|
116
226
|
|
|
117
227
|
**v2:**
|
|
118
228
|
```javascript
|
|
119
|
-
automator.
|
|
229
|
+
automator.addTask(taskObject);
|
|
120
230
|
```
|
|
121
231
|
|
|
122
232
|
**v3:**
|
|
123
233
|
```javascript
|
|
124
|
-
const id = automator.
|
|
125
|
-
// Returns the
|
|
234
|
+
const id = automator.addTask(taskSpec);
|
|
235
|
+
// Returns the task ID
|
|
126
236
|
```
|
|
127
237
|
|
|
128
|
-
#### Getting
|
|
238
|
+
#### Getting Tasks
|
|
129
239
|
|
|
130
240
|
**v2:**
|
|
131
241
|
```javascript
|
|
132
|
-
const
|
|
242
|
+
const tasks = automator.getTasks();
|
|
133
243
|
```
|
|
134
244
|
|
|
135
245
|
**v3:**
|
|
136
246
|
```javascript
|
|
137
|
-
const
|
|
138
|
-
const
|
|
139
|
-
const
|
|
247
|
+
const tasks = automator.getTasks(); // Deep copy
|
|
248
|
+
const task = automator.getTaskByID(id);
|
|
249
|
+
const tasks = automator.getTasksByName('name');
|
|
140
250
|
```
|
|
141
251
|
|
|
142
|
-
#### Removing
|
|
252
|
+
#### Removing Tasks
|
|
143
253
|
|
|
144
254
|
**v2:**
|
|
145
255
|
```javascript
|
|
146
|
-
automator.
|
|
256
|
+
automator.removeTask(id);
|
|
147
257
|
```
|
|
148
258
|
|
|
149
259
|
**v3:**
|
|
150
260
|
```javascript
|
|
151
|
-
automator.
|
|
152
|
-
automator.
|
|
261
|
+
automator.removeTaskByID(id);
|
|
262
|
+
automator.removeTaskByName('name'); // Returns count removed
|
|
153
263
|
```
|
|
154
264
|
|
|
155
|
-
#### Updating
|
|
265
|
+
#### Updating Tasks
|
|
156
266
|
|
|
157
267
|
**v2:**
|
|
158
268
|
Limited update capability.
|
|
159
269
|
|
|
160
270
|
**v3:**
|
|
161
271
|
```javascript
|
|
162
|
-
automator.
|
|
272
|
+
automator.updateTaskByID(id, {
|
|
163
273
|
name: 'New Name',
|
|
164
274
|
repeat: { type: 'hour', interval: 2 }
|
|
165
275
|
});
|
|
166
276
|
|
|
167
|
-
automator.
|
|
277
|
+
automator.updateTaskByName('Old Name', {
|
|
168
278
|
name: 'New Name'
|
|
169
279
|
});
|
|
170
280
|
```
|
|
171
281
|
|
|
172
282
|
---
|
|
173
283
|
|
|
174
|
-
## New Features in v3
|
|
175
|
-
|
|
176
284
|
## New Features in v4
|
|
177
285
|
|
|
178
286
|
### 1. Smart `catchUpWindow` Defaults
|
|
179
287
|
|
|
180
|
-
The new intelligent default system for `catchUpWindow` means that for most
|
|
288
|
+
The new intelligent default system for `catchUpWindow` means that for most tasks, you no longer need to explicitly define this property to get predictable, sensible behavior. It automatically adapts based on whether your task is one-time or recurring.
|
|
181
289
|
|
|
182
290
|
### 2. Dedicated `warning` Event
|
|
183
291
|
|
|
184
292
|
A new `warning` event (`automator.on('warning', ...)`) provides a clearer channel for non-fatal feedback about defensive coercions. This allows developers to distinguish between critical runtime errors and minor data corrections.
|
|
185
293
|
|
|
294
|
+
### 3. Cleaner "Task" Terminology
|
|
295
|
+
|
|
296
|
+
The rename from "action" to "task" provides clearer, more intuitive naming throughout the API.
|
|
297
|
+
|
|
186
298
|
---
|
|
187
299
|
|
|
188
300
|
## New Features in v3
|
|
@@ -192,7 +304,7 @@ A new `warning` event (`automator.on('warning', ...)`) provides a clearer channe
|
|
|
192
304
|
Preview future schedules without running them:
|
|
193
305
|
|
|
194
306
|
```javascript
|
|
195
|
-
const events = automator.
|
|
307
|
+
const events = automator.getTasksInRange(
|
|
196
308
|
new Date('2025-05-01'),
|
|
197
309
|
new Date('2025-05-07')
|
|
198
310
|
);
|
|
@@ -212,7 +324,7 @@ const automator = new Automator({
|
|
|
212
324
|
|
|
213
325
|
// File storage
|
|
214
326
|
const automator = new Automator({
|
|
215
|
-
storage: Automator.storage.file('./
|
|
327
|
+
storage: Automator.storage.file('./tasks.json')
|
|
216
328
|
});
|
|
217
329
|
|
|
218
330
|
// Custom storage
|
|
@@ -224,13 +336,13 @@ const automator = new Automator({
|
|
|
224
336
|
});
|
|
225
337
|
```
|
|
226
338
|
|
|
227
|
-
### 3.
|
|
339
|
+
### 3. Task Description
|
|
228
340
|
|
|
229
|
-
Human-readable
|
|
341
|
+
Human-readable task summaries:
|
|
230
342
|
|
|
231
343
|
```javascript
|
|
232
|
-
console.log(automator.
|
|
233
|
-
//
|
|
344
|
+
console.log(automator.describeTask(1));
|
|
345
|
+
// Task #1 - Morning Lights
|
|
234
346
|
// Command: turnLightOn
|
|
235
347
|
// Next run: 5/1/2025, 7:00:00 AM
|
|
236
348
|
// Executions: 15
|
|
@@ -241,15 +353,15 @@ console.log(automator.describeAction(1));
|
|
|
241
353
|
|
|
242
354
|
### 4. Better Event Payloads
|
|
243
355
|
|
|
244
|
-
|
|
356
|
+
Task events include rich metadata:
|
|
245
357
|
|
|
246
358
|
```javascript
|
|
247
|
-
automator.on('
|
|
359
|
+
automator.on('task', (event) => {
|
|
248
360
|
console.log(event);
|
|
249
361
|
// {
|
|
250
|
-
// type: '
|
|
251
|
-
//
|
|
252
|
-
// name: 'My
|
|
362
|
+
// type: 'task',
|
|
363
|
+
// taskId: 1,
|
|
364
|
+
// name: 'My Task',
|
|
253
365
|
// cmd: 'myCmd',
|
|
254
366
|
// payload: {},
|
|
255
367
|
// scheduledTime: Date,
|
|
@@ -265,7 +377,7 @@ Fine-tune persistence:
|
|
|
265
377
|
|
|
266
378
|
```javascript
|
|
267
379
|
const automator = new Automator({
|
|
268
|
-
storage: Automator.storage.file('./
|
|
380
|
+
storage: Automator.storage.file('./tasks.json'),
|
|
269
381
|
autoSave: true,
|
|
270
382
|
saveInterval: 10000 // Save every 10 seconds
|
|
271
383
|
});
|
|
@@ -279,20 +391,69 @@ const automator = new Automator({
|
|
|
279
391
|
|
|
280
392
|
Thoroughly review the "Breaking Changes from v3 to v4" section above. Identify which changes affect your application.
|
|
281
393
|
|
|
282
|
-
### Step 2:
|
|
394
|
+
### Step 2: Update API Method Names
|
|
283
395
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
-
|
|
287
|
-
-
|
|
396
|
+
Replace all "action" method calls with "task" equivalents:
|
|
397
|
+
- `addAction()` → `addTask()`
|
|
398
|
+
- `updateActionByID()` → `updateTaskByID()`
|
|
399
|
+
- `updateActionByName()` → `updateTaskByName()`
|
|
400
|
+
- `removeActionByID()` → `removeTaskByID()`
|
|
401
|
+
- `removeActionByName()` → `removeTaskByName()`
|
|
402
|
+
- `getActions()` → `getTasks()`
|
|
403
|
+
- `getActionsByName()` → `getTasksByName()`
|
|
404
|
+
- `getActionByID()` → `getTaskByID()`
|
|
405
|
+
- `getActionsInRange()` → `getTasksInRange()`
|
|
406
|
+
- `describeAction()` → `describeTask()`
|
|
288
407
|
|
|
289
408
|
### Step 3: Update Event Listeners
|
|
290
409
|
|
|
410
|
+
Change event listeners from `'action'` to `'task'`:
|
|
411
|
+
```javascript
|
|
412
|
+
// v3
|
|
413
|
+
automator.on('action', (event) => { ... });
|
|
414
|
+
|
|
415
|
+
// v4
|
|
416
|
+
automator.on('task', (event) => { ... });
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Step 4: Update Event Property Access
|
|
420
|
+
|
|
421
|
+
Update code that accesses event properties:
|
|
422
|
+
```javascript
|
|
423
|
+
// v3
|
|
424
|
+
event.actionId
|
|
425
|
+
event.action
|
|
426
|
+
|
|
427
|
+
// v4
|
|
428
|
+
event.taskId
|
|
429
|
+
event.task
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Step 5: Migrate Stored State
|
|
433
|
+
|
|
434
|
+
If using file storage, update existing state files:
|
|
435
|
+
```javascript
|
|
436
|
+
// v3 format
|
|
437
|
+
{ "actions": [...] }
|
|
438
|
+
|
|
439
|
+
// v4 format
|
|
440
|
+
{ "tasks": [...] }
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### Step 6: Review `catchUpWindow` Usage
|
|
444
|
+
|
|
445
|
+
If your v3 application relied on the implicit "unlimited" catch-up for tasks where `catchUpWindow` was not explicitly set, you will need to:
|
|
446
|
+
|
|
447
|
+
- **Explicitly set `catchUpWindow: "unlimited"`** for those tasks if you wish to maintain the old behavior.
|
|
448
|
+
- Otherwise, understand that these tasks will now use the new smart defaults (recurrence interval for recurring, `0` for one-time tasks).
|
|
449
|
+
|
|
450
|
+
### Step 7: Update Warning Event Listeners
|
|
451
|
+
|
|
291
452
|
If your application was listening for `automator.on('error', ...)` to catch notifications about defensive coercions (e.g., invalid `repeat.interval`), you must now update your code to listen for `automator.on('warning', ...)` to receive these non-fatal messages.
|
|
292
453
|
|
|
293
|
-
### Step
|
|
454
|
+
### Step 8: Correct Invalid `repeat.type` Definitions
|
|
294
455
|
|
|
295
|
-
If your application previously used
|
|
456
|
+
If your application previously used tasks with invalid or missing `repeat.type` values that were silently corrected in v3, you must now explicitly fix these `repeat.type` values. Failure to do so will result in a hard `Error` when the task is added or updated in v4.
|
|
296
457
|
|
|
297
458
|
---
|
|
298
459
|
|
|
@@ -300,15 +461,18 @@ If your application previously used actions with invalid or missing `repeat.type
|
|
|
300
461
|
|
|
301
462
|
### What's the Same (v3 to v4)
|
|
302
463
|
|
|
303
|
-
- **Core concepts**: Schedule
|
|
464
|
+
- **Core concepts**: Schedule tasks with recurrence
|
|
304
465
|
- **Recurrence types**: `second`, `minute`, `hour`, `day`, `week`, `month`, `year`
|
|
305
466
|
- **Local time**: Still operates in local time
|
|
306
|
-
- **API methods**: Names and signatures of `addAction()`, `updateActionByID()`, etc., remain the same.
|
|
307
467
|
- **Function registration**: Still use `addFunction()`
|
|
308
468
|
- **Legacy `unBuffered`**: Still supported as an alias, mapping to `catchUpWindow`.
|
|
309
469
|
|
|
310
470
|
### What's Different (v3 to v4)
|
|
311
471
|
|
|
472
|
+
- **API terminology**: "action" → "task" throughout
|
|
473
|
+
- **Event name**: `'action'` → `'task'`
|
|
474
|
+
- **Event properties**: `actionId` → `taskId`, `action` → `task`
|
|
475
|
+
- **State structure**: `actions` → `tasks`
|
|
312
476
|
- **`catchUpWindow` Default Behavior**: Now smart and context-aware, instead of always `"unlimited"`.
|
|
313
477
|
- **`repeat.type` Validation**: Invalid types now throw a fatal `Error`.
|
|
314
478
|
- **Event Handling**: Coercions now emit `warning` events instead of `error` events.
|