@context-action/core 0.7.3 → 0.7.4
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/dist/index.cjs +109 -24
- package/dist/index.d.cts +4 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +109 -24
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -49,6 +49,16 @@ async function executeSequential(context, createController) {
|
|
|
49
49
|
const controller = createController(registration, i);
|
|
50
50
|
try {
|
|
51
51
|
if (context.aborted) break;
|
|
52
|
+
if (registration.config.condition) try {
|
|
53
|
+
const shouldExecute = registration.config.condition(context.payload);
|
|
54
|
+
if (!shouldExecute) {
|
|
55
|
+
i++;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
i++;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
52
62
|
const result = registration.handler(context.payload, controller);
|
|
53
63
|
if (registration.config.blocking) {
|
|
54
64
|
const handlerResult = result instanceof Promise ? await result : result;
|
|
@@ -73,8 +83,20 @@ async function executeSequential(context, createController) {
|
|
|
73
83
|
if (context.terminated) break;
|
|
74
84
|
/** Handle jump to priority AFTER handler execution */
|
|
75
85
|
if (context.jumpToPriority !== void 0) {
|
|
76
|
-
|
|
77
|
-
if (
|
|
86
|
+
context.jumpCount = (context.jumpCount || 0) + 1;
|
|
87
|
+
if (context.jumpCount > (context.maxJumps || 10)) {
|
|
88
|
+
console.error(`[ActionRegister] ERROR: Maximum jump limit (${context.maxJumps || 10}) exceeded. Aborting to prevent infinite loop. Check your jumpToPriority logic and conditions.`);
|
|
89
|
+
context.aborted = true;
|
|
90
|
+
context.abortReason = `Maximum jump limit exceeded (${context.jumpCount} jumps)`;
|
|
91
|
+
context.jumpToPriority = void 0;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
const jumpIndex = context.handlers.findIndex((handler) => (handler.config.priority || 0) <= context.jumpToPriority);
|
|
95
|
+
if (jumpIndex !== -1 && jumpIndex !== i) {
|
|
96
|
+
if (jumpIndex < i) {
|
|
97
|
+
const targetHandler = context.handlers[jumpIndex];
|
|
98
|
+
if (targetHandler && !targetHandler.config.condition) console.warn(`[ActionRegister] WARNING: Backward jumpToPriority to handler '${targetHandler.config.id || "unnamed"}' without condition. This may cause infinite loops! Consider adding a condition to prevent re-execution. Jump count: ${context.jumpCount}/${context.maxJumps || 10}`);
|
|
99
|
+
}
|
|
78
100
|
i = jumpIndex;
|
|
79
101
|
context.jumpToPriority = void 0;
|
|
80
102
|
continue;
|
|
@@ -85,7 +107,9 @@ async function executeSequential(context, createController) {
|
|
|
85
107
|
} else i++;
|
|
86
108
|
} catch (error) {
|
|
87
109
|
const handlerError = handleExecutionError(error, registration);
|
|
88
|
-
|
|
110
|
+
errors.push(handlerError);
|
|
111
|
+
if (registration.config.blocking) throw handlerError.error;
|
|
112
|
+
i++;
|
|
89
113
|
}
|
|
90
114
|
}
|
|
91
115
|
if (nonBlockingPromises.length > 0) await Promise.allSettled(nonBlockingPromises);
|
|
@@ -125,6 +149,24 @@ async function executeParallel(context, createController) {
|
|
|
125
149
|
const handlerPromises = runnableHandlers.map(async (registration, _index) => {
|
|
126
150
|
const controller = createController(registration, _index);
|
|
127
151
|
try {
|
|
152
|
+
if (registration.config.condition) try {
|
|
153
|
+
const shouldExecute = registration.config.condition(context.payload);
|
|
154
|
+
if (!shouldExecute) return {
|
|
155
|
+
success: true,
|
|
156
|
+
handlerId: registration.id,
|
|
157
|
+
result: void 0,
|
|
158
|
+
terminated: false,
|
|
159
|
+
skipped: true
|
|
160
|
+
};
|
|
161
|
+
} catch {
|
|
162
|
+
return {
|
|
163
|
+
success: true,
|
|
164
|
+
handlerId: registration.id,
|
|
165
|
+
result: void 0,
|
|
166
|
+
terminated: false,
|
|
167
|
+
skipped: true
|
|
168
|
+
};
|
|
169
|
+
}
|
|
128
170
|
const result = registration.handler(context.payload, controller);
|
|
129
171
|
let handlerResult;
|
|
130
172
|
if (result instanceof Promise) {
|
|
@@ -199,6 +241,26 @@ async function executeRace(context, createController) {
|
|
|
199
241
|
const handlerPromises = runnableHandlers.map(async (registration, _index) => {
|
|
200
242
|
const controller = createController(registration, _index);
|
|
201
243
|
try {
|
|
244
|
+
if (registration.config.condition) try {
|
|
245
|
+
const shouldExecute = registration.config.condition(context.payload);
|
|
246
|
+
if (!shouldExecute) return {
|
|
247
|
+
success: true,
|
|
248
|
+
handlerId: registration.id,
|
|
249
|
+
registration,
|
|
250
|
+
result: void 0,
|
|
251
|
+
terminated: false,
|
|
252
|
+
skipped: true
|
|
253
|
+
};
|
|
254
|
+
} catch {
|
|
255
|
+
return {
|
|
256
|
+
success: true,
|
|
257
|
+
handlerId: registration.id,
|
|
258
|
+
registration,
|
|
259
|
+
result: void 0,
|
|
260
|
+
terminated: false,
|
|
261
|
+
skipped: true
|
|
262
|
+
};
|
|
263
|
+
}
|
|
202
264
|
const result = registration.handler(context.payload, controller);
|
|
203
265
|
let handlerResult;
|
|
204
266
|
if (result instanceof Promise) {
|
|
@@ -725,6 +787,7 @@ var ActionRegister = class {
|
|
|
725
787
|
this.executionMode = "sequential";
|
|
726
788
|
this.actionExecutionModes = /* @__PURE__ */ new Map();
|
|
727
789
|
this.unregisterFunctions = /* @__PURE__ */ new Map();
|
|
790
|
+
this.lastRegisteredTimestamps = /* @__PURE__ */ new Map();
|
|
728
791
|
this.filterCacheDisabled = true;
|
|
729
792
|
this.handlerIdCounter = 0;
|
|
730
793
|
this.controllerPool = [];
|
|
@@ -845,8 +908,9 @@ var ActionRegister = class {
|
|
|
845
908
|
once: config.once ?? false,
|
|
846
909
|
debounce: config.debounce ?? void 0,
|
|
847
910
|
throttle: config.throttle ?? void 0,
|
|
848
|
-
replaceExisting: config.replaceExisting ??
|
|
849
|
-
cleanup: config.cleanup
|
|
911
|
+
replaceExisting: config.replaceExisting ?? true,
|
|
912
|
+
cleanup: config.cleanup,
|
|
913
|
+
condition: config.condition
|
|
850
914
|
},
|
|
851
915
|
id: handlerId
|
|
852
916
|
};
|
|
@@ -860,18 +924,16 @@ var ActionRegister = class {
|
|
|
860
924
|
if (existingIndex !== -1) {
|
|
861
925
|
const existing = pipeline[existingIndex];
|
|
862
926
|
const existingUnregister = this.unregisterFunctions.get(handlerId);
|
|
863
|
-
if (config.replaceExisting) {
|
|
864
|
-
if (
|
|
865
|
-
|
|
866
|
-
this.unregisterFunctions.delete(handlerId);
|
|
867
|
-
}
|
|
868
|
-
if (existing && typeof existing.cleanup === "function") try {
|
|
869
|
-
existing.cleanup();
|
|
927
|
+
if (registration.config.replaceExisting) {
|
|
928
|
+
if (existing && existing.config.cleanup && typeof existing.config.cleanup === "function") try {
|
|
929
|
+
existing.config.cleanup();
|
|
870
930
|
} catch (cleanupError) {
|
|
871
931
|
this.log(`Cleanup error for replaced handler: ${String(action)}`, cleanupError, "warn");
|
|
872
932
|
}
|
|
933
|
+
if (existingUnregister) this.unregisterFunctions.delete(handlerId);
|
|
873
934
|
pipeline[existingIndex] = registration;
|
|
874
935
|
pipeline.sort((a, b) => b.config.priority - a.config.priority);
|
|
936
|
+
this.lastRegisteredTimestamps.set(action, /* @__PURE__ */ new Date());
|
|
875
937
|
const newUnregister = this.createUnregisterFunction(action, handlerId, registration);
|
|
876
938
|
this.unregisterFunctions.set(handlerId, newUnregister);
|
|
877
939
|
this.log(`Handler replaced: ${String(action)}`, {
|
|
@@ -901,6 +963,7 @@ var ActionRegister = class {
|
|
|
901
963
|
}
|
|
902
964
|
pipeline.push(registration);
|
|
903
965
|
pipeline.sort((a, b) => b.config.priority - a.config.priority);
|
|
966
|
+
this.lastRegisteredTimestamps.set(action, /* @__PURE__ */ new Date());
|
|
904
967
|
const unregister = this.createUnregisterFunction(action, handlerId, registration);
|
|
905
968
|
this.unregisterFunctions.set(handlerId, unregister);
|
|
906
969
|
this.log(`Handler registered: ${String(action)}`, {
|
|
@@ -994,6 +1057,8 @@ var ActionRegister = class {
|
|
|
994
1057
|
abortReason: void 0,
|
|
995
1058
|
currentIndex: 0,
|
|
996
1059
|
jumpToPriority: void 0,
|
|
1060
|
+
jumpCount: 0,
|
|
1061
|
+
maxJumps: 10,
|
|
997
1062
|
executionMode: currentExecutionMode,
|
|
998
1063
|
results: [],
|
|
999
1064
|
terminated: false,
|
|
@@ -1085,6 +1150,8 @@ var ActionRegister = class {
|
|
|
1085
1150
|
abortReason: void 0,
|
|
1086
1151
|
currentIndex: 0,
|
|
1087
1152
|
jumpToPriority: void 0,
|
|
1153
|
+
jumpCount: 0,
|
|
1154
|
+
maxJumps: 10,
|
|
1088
1155
|
executionMode: currentExecutionMode,
|
|
1089
1156
|
results: [],
|
|
1090
1157
|
terminated: false,
|
|
@@ -1271,7 +1338,11 @@ var ActionRegister = class {
|
|
|
1271
1338
|
if (autoAbortController && autoAbortOptions?.allowHandlerAbort) autoAbortController.abort(reason);
|
|
1272
1339
|
};
|
|
1273
1340
|
controller.modifyPayload = (modifier) => {
|
|
1274
|
-
|
|
1341
|
+
try {
|
|
1342
|
+
context.payload = modifier(context.payload);
|
|
1343
|
+
} catch (modificationError) {
|
|
1344
|
+
this.log("Payload modification error", modificationError, "warn");
|
|
1345
|
+
}
|
|
1275
1346
|
};
|
|
1276
1347
|
controller.getPayload = () => context.payload;
|
|
1277
1348
|
controller.jumpToPriority = (priority) => {
|
|
@@ -1320,9 +1391,10 @@ var ActionRegister = class {
|
|
|
1320
1391
|
return filtered;
|
|
1321
1392
|
}
|
|
1322
1393
|
processResults(context, resultOptions) {
|
|
1323
|
-
if (!resultOptions || !resultOptions.collect) return void 0;
|
|
1324
1394
|
const results = context.results;
|
|
1325
1395
|
if (context.terminated && context.terminationResult !== void 0) return context.terminationResult;
|
|
1396
|
+
if (!resultOptions) return results.length > 0 ? results[results.length - 1] : void 0;
|
|
1397
|
+
if (!resultOptions.collect && !resultOptions.strategy) return void 0;
|
|
1326
1398
|
const limitedResults = resultOptions.maxResults ? results.slice(0, resultOptions.maxResults) : results;
|
|
1327
1399
|
if (limitedResults.length === 0) return void 0;
|
|
1328
1400
|
switch (resultOptions.strategy) {
|
|
@@ -1335,7 +1407,9 @@ var ActionRegister = class {
|
|
|
1335
1407
|
case "custom":
|
|
1336
1408
|
if (resultOptions.merger) return resultOptions.merger(limitedResults);
|
|
1337
1409
|
throw new Error("Custom result strategy requires a merger function");
|
|
1338
|
-
default:
|
|
1410
|
+
default:
|
|
1411
|
+
if (resultOptions.collect) return limitedResults;
|
|
1412
|
+
return limitedResults[limitedResults.length - 1];
|
|
1339
1413
|
}
|
|
1340
1414
|
}
|
|
1341
1415
|
async executePipeline(context, autoAbortController, autoAbortOptions) {
|
|
@@ -1372,6 +1446,10 @@ var ActionRegister = class {
|
|
|
1372
1446
|
});
|
|
1373
1447
|
}
|
|
1374
1448
|
});
|
|
1449
|
+
if (pipeline.length === 0) {
|
|
1450
|
+
this.pipelines.delete(action);
|
|
1451
|
+
this.lastRegisteredTimestamps.delete(action);
|
|
1452
|
+
}
|
|
1375
1453
|
}
|
|
1376
1454
|
/**
|
|
1377
1455
|
* Get the number of registered handlers for an action
|
|
@@ -1425,6 +1503,7 @@ var ActionRegister = class {
|
|
|
1425
1503
|
*/
|
|
1426
1504
|
clearAction(action) {
|
|
1427
1505
|
this.pipelines.delete(action);
|
|
1506
|
+
this.lastRegisteredTimestamps.delete(action);
|
|
1428
1507
|
}
|
|
1429
1508
|
/**
|
|
1430
1509
|
* Remove all handlers for all actions
|
|
@@ -1435,6 +1514,7 @@ var ActionRegister = class {
|
|
|
1435
1514
|
*/
|
|
1436
1515
|
clearAll() {
|
|
1437
1516
|
this.pipelines.clear();
|
|
1517
|
+
this.lastRegisteredTimestamps.clear();
|
|
1438
1518
|
}
|
|
1439
1519
|
/**
|
|
1440
1520
|
* Get the name of this action register
|
|
@@ -1488,7 +1568,8 @@ var ActionRegister = class {
|
|
|
1488
1568
|
handlerCount: pipeline.length,
|
|
1489
1569
|
totalHandlers: pipeline.length,
|
|
1490
1570
|
handlersByPriority,
|
|
1491
|
-
executionStats
|
|
1571
|
+
executionStats,
|
|
1572
|
+
lastRegistered: this.lastRegisteredTimestamps.get(action)
|
|
1492
1573
|
};
|
|
1493
1574
|
}
|
|
1494
1575
|
/**
|
|
@@ -1569,6 +1650,10 @@ var ActionRegister = class {
|
|
|
1569
1650
|
if (index !== -1) {
|
|
1570
1651
|
pipeline.splice(index, 1);
|
|
1571
1652
|
this.unregisterFunctions.delete(handlerId);
|
|
1653
|
+
if (pipeline.length === 0) {
|
|
1654
|
+
this.pipelines.delete(action);
|
|
1655
|
+
this.lastRegisteredTimestamps.delete(action);
|
|
1656
|
+
}
|
|
1572
1657
|
if (registration.config.cleanup && typeof registration.config.cleanup === "function") try {
|
|
1573
1658
|
registration.config.cleanup();
|
|
1574
1659
|
} catch (cleanupError) {
|
|
@@ -1576,7 +1661,8 @@ var ActionRegister = class {
|
|
|
1576
1661
|
}
|
|
1577
1662
|
this.log(`Handler unregistered: ${String(action)}`, {
|
|
1578
1663
|
handlerId,
|
|
1579
|
-
remainingHandlers: pipeline.length
|
|
1664
|
+
remainingHandlers: pipeline.length,
|
|
1665
|
+
actionRemoved: pipeline.length === 0
|
|
1580
1666
|
});
|
|
1581
1667
|
}
|
|
1582
1668
|
};
|
|
@@ -1609,15 +1695,14 @@ var ActionRegister = class {
|
|
|
1609
1695
|
* @public
|
|
1610
1696
|
*/
|
|
1611
1697
|
destroy() {
|
|
1612
|
-
this.unregisterFunctions.forEach((unregister) => {
|
|
1613
|
-
try {
|
|
1614
|
-
unregister();
|
|
1615
|
-
} catch (error) {
|
|
1616
|
-
this.log("Error during unregister in destroy", error, "error");
|
|
1617
|
-
}
|
|
1618
|
-
});
|
|
1619
1698
|
this.unregisterFunctions.clear();
|
|
1699
|
+
for (const [action, pipeline] of this.pipelines.entries()) for (const registration of pipeline) if (registration.config.cleanup && typeof registration.config.cleanup === "function") try {
|
|
1700
|
+
registration.config.cleanup();
|
|
1701
|
+
} catch (cleanupError) {
|
|
1702
|
+
this.log(`Cleanup error for handler during destroy: ${String(action)}`, cleanupError, "warn");
|
|
1703
|
+
}
|
|
1620
1704
|
this.pipelines.clear();
|
|
1705
|
+
this.lastRegisteredTimestamps.clear();
|
|
1621
1706
|
this.actionGuard.destroy();
|
|
1622
1707
|
this.dispatchQueue?.clear?.();
|
|
1623
1708
|
this.actionExecutionModes.clear();
|