@statedelta-actions/rules 0.3.0 → 0.5.1
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 +89 -0
- package/LICENSE +21 -0
- package/README.md +178 -19
- package/dist/index.cjs +9 -5
- package/dist/index.d.cts +30 -2
- package/dist/index.d.ts +30 -2
- package/dist/index.js +9 -5
- package/package.json +16 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# @statedelta-actions/rules
|
|
2
|
+
|
|
3
|
+
## 0.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 26c579a: Polish published package metadata and READMEs
|
|
8
|
+
- `@statedelta-actions/core` now ships a README (was missing on npm).
|
|
9
|
+
- `@statedelta-actions/analyzer` README: fixed pervasive missing accents.
|
|
10
|
+
- `graph` and `events` READMEs: titles are now the package name (`# @statedelta-actions/graph` / `# @statedelta-actions/events`) instead of a conceptual name.
|
|
11
|
+
- All packages: added `keywords`, `homepage`, `bugs`; package.json keys reordered to a canonical layout.
|
|
12
|
+
- All packages: `CHANGELOG.md` added to `files` so it ships to npm; a `LICENSE` (MIT) file is included in the repo root and in each package.
|
|
13
|
+
|
|
14
|
+
- Updated dependencies [26c579a]
|
|
15
|
+
- Updated dependencies [a3a818b]
|
|
16
|
+
- @statedelta-actions/core@0.5.1
|
|
17
|
+
- @statedelta-actions/actions@0.6.0
|
|
18
|
+
|
|
19
|
+
## 0.5.0
|
|
20
|
+
|
|
21
|
+
### Minor Changes
|
|
22
|
+
|
|
23
|
+
- f8c2b4a: Fail-fast register errors, controlled `action-not-found`, atomic registration, and events async/interactive modes
|
|
24
|
+
- **actions** — A missing handler for a directive type now throws at register
|
|
25
|
+
time (was a collected error) — fail-fast for typos and forgotten handlers.
|
|
26
|
+
Invoking an unknown action id returns `aborted: true, abortedBy:
|
|
27
|
+
"action-not-found"` instead of a soft failure. `isActionAsync` is exposed on
|
|
28
|
+
the engine ref handed to handlers (symmetric with `isActionInteractive`).
|
|
29
|
+
- **rules** — `register()` is atomic: it builds a staging set, delegates to the
|
|
30
|
+
ActionEngine, then indexes locally only on success. Structural errors from the
|
|
31
|
+
ActionEngine propagate as a throw with no local state mutated.
|
|
32
|
+
- **events** — `register()`/`defineEvents()` are atomic the same way.
|
|
33
|
+
Async detection is now per-listener transitive via the ActionEngine mini-graph,
|
|
34
|
+
so hybrid engines keep `processEvents`/`processEventsAsync` viable for
|
|
35
|
+
listeners whose subtree is fully sync. New `processEventsInteractive()` returns
|
|
36
|
+
a drainable iterator (sync or async generator) — pauses from `type:"pause"` or
|
|
37
|
+
an interactive handler flow via `yield*` up to the consumer; halt scoping is
|
|
38
|
+
preserved (a pause stops the listeners of that event, following events
|
|
39
|
+
continue). New `isInteractive` getter.
|
|
40
|
+
- **core** — `ActionEngineRef` gains an optional `isActionAsync?` accessor.
|
|
41
|
+
- **sdk** — re-exports the new event types/surface; barrel deps moved to
|
|
42
|
+
`dependencies` (`workspace:^`).
|
|
43
|
+
|
|
44
|
+
### Patch Changes
|
|
45
|
+
|
|
46
|
+
- Updated dependencies [f8c2b4a]
|
|
47
|
+
- @statedelta-actions/actions@0.5.0
|
|
48
|
+
- @statedelta-actions/core@0.5.0
|
|
49
|
+
|
|
50
|
+
## 0.3.0
|
|
51
|
+
|
|
52
|
+
### Minor Changes
|
|
53
|
+
|
|
54
|
+
- Split types em definitions + engine em cada package; novo subpath sdk/definitions
|
|
55
|
+
- core: RegisterWarning movido pra core/types/engine.ts (tipo shared entre packages)
|
|
56
|
+
- actions: types.ts → types/definitions.ts + types/engine.ts
|
|
57
|
+
- rules: types.ts → types/definitions.ts + types/engine.ts
|
|
58
|
+
- events: types.ts → types/definitions.ts + types/engine.ts
|
|
59
|
+
- sdk: novo subpath ./definitions com re-export de definition types puros (zero runtime)
|
|
60
|
+
|
|
61
|
+
### Patch Changes
|
|
62
|
+
|
|
63
|
+
- Updated dependencies []:
|
|
64
|
+
- @statedelta-actions/core@0.3.0
|
|
65
|
+
- @statedelta-actions/actions@0.3.0
|
|
66
|
+
|
|
67
|
+
## 0.2.0
|
|
68
|
+
|
|
69
|
+
### Minor Changes
|
|
70
|
+
|
|
71
|
+
- Sync all packages to 0.2.0 (match SDK version)
|
|
72
|
+
|
|
73
|
+
### Patch Changes
|
|
74
|
+
|
|
75
|
+
- Updated dependencies []:
|
|
76
|
+
- @statedelta-actions/core@0.2.0
|
|
77
|
+
- @statedelta-actions/actions@0.2.0
|
|
78
|
+
|
|
79
|
+
## 0.3.0
|
|
80
|
+
|
|
81
|
+
### Minor Changes
|
|
82
|
+
|
|
83
|
+
- Sync all packages to 0.2.0 (match SDK version)
|
|
84
|
+
|
|
85
|
+
### Patch Changes
|
|
86
|
+
|
|
87
|
+
- Updated dependencies []:
|
|
88
|
+
- @statedelta-actions/core@0.3.0
|
|
89
|
+
- @statedelta-actions/actions@0.3.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Anderson D. Rosa
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -22,15 +22,16 @@
|
|
|
22
22
|
11. [JIT Compilation](#jit-compilation)
|
|
23
23
|
12. [Batch Operations](#batch-operations)
|
|
24
24
|
13. [Async Support](#async-support)
|
|
25
|
-
14. [
|
|
26
|
-
15. [
|
|
27
|
-
16. [
|
|
28
|
-
17. [
|
|
29
|
-
18. [
|
|
30
|
-
19. [Use Case:
|
|
31
|
-
20. [Use Case:
|
|
32
|
-
21. [
|
|
33
|
-
22. [
|
|
25
|
+
14. [Modo Interactive](#modo-interactive)
|
|
26
|
+
15. [Error Handling](#error-handling)
|
|
27
|
+
16. [HALT_HANDLER](#halt_handler)
|
|
28
|
+
17. [createInvokerMiddleware](#createinvokermiddleware)
|
|
29
|
+
18. [Full API Reference](#full-api-reference)
|
|
30
|
+
19. [Use Case: RPG Combat Tick](#use-case-rpg-combat-tick)
|
|
31
|
+
20. [Use Case: E-commerce Order Pipeline](#use-case-e-commerce-order-pipeline)
|
|
32
|
+
21. [Use Case: Deployment Approval Workflow](#use-case-deployment-approval-workflow)
|
|
33
|
+
22. [Performance Spectrum](#performance-spectrum)
|
|
34
|
+
23. [Internal Design Notes](#internal-design-notes)
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
---
|
|
@@ -75,6 +76,8 @@ Middleware enriches the `params` envelope (execution scope), not the domain `ctx
|
|
|
75
76
|
|
|
76
77
|
The engine never throws to the consumer during `evaluate()`. All runtime errors are collected in `RuleEvaluationResult.errors`. The only exception is a programmer error: calling `evaluate()` when `isAsync === true`.
|
|
77
78
|
|
|
79
|
+
`register()` is different — structural errors at boot time (missing handler for a directive type) throw an `Error` and abort the registration atomically. See [Registration](#registration).
|
|
80
|
+
|
|
78
81
|
### Feature not used = zero overhead
|
|
79
82
|
|
|
80
83
|
When hooks are not registered, hook code is never executed — not as dead branches, but as absent code paths. The JIT compiler conditionally emits code only for features that are actually configured. Zero middleware means no middleware variables, no pipeline calls, no params allocation.
|
|
@@ -289,12 +292,21 @@ const result = ruleEngine.register([rule1, rule2, ...]);
|
|
|
289
292
|
|
|
290
293
|
### Registration pipeline
|
|
291
294
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
295
|
+
Three phases. Local registries are only mutated after the ActionEngine accepts every hidden action — `register()` is atomic.
|
|
296
|
+
|
|
297
|
+
1. **Build** — validate each rule (id, priority, when, then/rules), collect sub-rules recursively, build hidden action definitions (`rule:{id}` for top-level, dot-separated for sub-rules). Soft validation errors (duplicate id, missing required field) accumulate in `errors[]`. No local indexing yet.
|
|
298
|
+
2. **Delegate to ActionEngine** — `actionEngine.register(hiddenActions)`. Structural errors propagate as throw (handler missing for a directive type). Soft errors from the ActionEngine are mapped back to rule ids and added to `errors[]`.
|
|
299
|
+
3. **Index** — only reached when phase 2 returns. Insert each rule into `_ruleRegistry` and `_rules` (sorted by priority desc), refresh per-rule `isAsync`/`isInteractive` flags from the mini-graph.
|
|
300
|
+
|
|
301
|
+
### Throw vs collected errors
|
|
302
|
+
|
|
303
|
+
| Error | Behavior |
|
|
304
|
+
|-------|----------|
|
|
305
|
+
| Missing handler for a directive type in `then` (any depth, including sub-rules and `catch`) | **Throws `Error`** in `register()`. No local state mutated. Consumer wraps in try/catch if needed. |
|
|
306
|
+
| Duplicate rule id, missing `when`, missing `then`/`rules`, invalid priority | Collected in `errors[]`. Other valid rules in the same call still register. |
|
|
307
|
+
| `validate()` from a handler returns invalid or throws | Collected in `errors[]`. |
|
|
308
|
+
|
|
309
|
+
The throw path is reserved for boot-time structural errors that cannot become valid at runtime — typos, forgotten handler registration, refactor leftovers. Soft errors are domain-level and worth surveying.
|
|
298
310
|
|
|
299
311
|
### RuleRegisterResult
|
|
300
312
|
|
|
@@ -686,13 +698,31 @@ const result = engine.endBatch();
|
|
|
686
698
|
|
|
687
699
|
## Async Support
|
|
688
700
|
|
|
689
|
-
### Detection
|
|
701
|
+
### Detection (per-rule transitivo)
|
|
690
702
|
|
|
691
703
|
```typescript
|
|
692
|
-
const isAsync = ruleHookAnalysis.hasAnyAsync ||
|
|
704
|
+
const isAsync = ruleHookAnalysis.hasAnyAsync || hasAnyAsyncRuleTransitive;
|
|
693
705
|
```
|
|
694
706
|
|
|
695
|
-
|
|
707
|
+
Refrescado em `register()` / `unregister()` / `endBatch()` consultando o **mini-graph interno do ActionEngine** (ADR-026 do actions). Cada `StoredRule` cacheia `isAsync`/`isInteractive` per-rule (refletindo `actionEngine.isActionAsync(rule.actionId)`).
|
|
708
|
+
|
|
709
|
+
**Diferença importante:** antes era `actionEngine.isAsync` (global). Agora é per-rule transitivo. Engine híbrido (handler async + handler sync) com rules **100% sync na sub-árvore** permite `evaluate()` regular — só rules transitivamente async forçam `evaluateAsync()`.
|
|
710
|
+
|
|
711
|
+
```typescript
|
|
712
|
+
// Engine híbrido — handler async existe, mas action `log` (usada em syncRule) é sync
|
|
713
|
+
const engine = createActionEngine({
|
|
714
|
+
handlers: { log, fetchAsync: { async: true, async execute() {...} } },
|
|
715
|
+
});
|
|
716
|
+
const rules = createRuleEngine({ actionEngine: engine });
|
|
717
|
+
|
|
718
|
+
rules.register([
|
|
719
|
+
{ id: "syncRule", priority: 1, when: () => true, then: [{ type: "log", message: "x" }] },
|
|
720
|
+
]);
|
|
721
|
+
|
|
722
|
+
engine.isAsync; // true (engine global async — fetchAsync existe)
|
|
723
|
+
rules.isAsync; // false (rule específica é sync transitivamente)
|
|
724
|
+
rules.evaluate(ctx); // ✅ funciona — não força evaluateAsync
|
|
725
|
+
```
|
|
696
726
|
|
|
697
727
|
### Usage
|
|
698
728
|
|
|
@@ -722,15 +752,141 @@ const ruleEngine = createRuleEngine({
|
|
|
722
752
|
},
|
|
723
753
|
});
|
|
724
754
|
|
|
755
|
+
|
|
725
756
|
// Must use evaluateAsync
|
|
726
757
|
const result = await ruleEngine.evaluateAsync(ctx);
|
|
727
758
|
```
|
|
728
759
|
|
|
729
760
|
---
|
|
730
761
|
|
|
762
|
+
## Modo Interactive
|
|
763
|
+
|
|
764
|
+
Permite **pausar avaliação de rules** e aguardar input externo via generators — espelhamento do modo interactive do ActionEngine. Ortogonal a sync/async.
|
|
765
|
+
|
|
766
|
+
**Habilitação:** ActionEngine precisa estar em modo interactive (`createActionEngine({ ..., interactive: {} })`). Rules detecta automaticamente quando alguma rule registrada tem ação transitivamente interactive.
|
|
767
|
+
|
|
768
|
+
### Detection per-rule
|
|
769
|
+
|
|
770
|
+
`StoredRule.isInteractive` cacheia o resultado de `engine.isActionInteractive(rule.actionId)`. Refrescado em register/unregister/endBatch.
|
|
771
|
+
|
|
772
|
+
```typescript
|
|
773
|
+
rules.isInteractive; // true se qualquer rule é interactive transitivamente
|
|
774
|
+
rules.evaluate(ctx); // throws "use evaluateInteractive"
|
|
775
|
+
rules.evaluateAsync(ctx); // idem
|
|
776
|
+
rules.evaluateInteractive(ctx); // ✅ retorna iterator
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
### evaluateInteractive
|
|
780
|
+
|
|
781
|
+
Retorna `InteractiveRuleSession` (sync) ou `AsyncInteractiveRuleSession` (async, quando `rules.isAsync`). Drenagem via `next(value)`:
|
|
782
|
+
|
|
783
|
+
> Handlers são primitivas Lego (ADR-028 do actions). Use `input` (genérico) com payload domain-specific. **Nunca crie `askUser`, `confirmEmail`, etc** — viola o princípio canonical.
|
|
784
|
+
|
|
785
|
+
```typescript
|
|
786
|
+
const engine = createActionEngine({
|
|
787
|
+
handlers: {
|
|
788
|
+
// Primitiva canonical: yield + schema + retry interno
|
|
789
|
+
input: { interactive: true, *execute(d) {
|
|
790
|
+
const ans = yield { kind: "input", payload: d.payload, schema: d.schema };
|
|
791
|
+
return { ok: true, data: ans };
|
|
792
|
+
} },
|
|
793
|
+
log: { execute: (d, f) => { f.ctx.out.push(d.message); return { ok: true }; } },
|
|
794
|
+
},
|
|
795
|
+
interactive: {},
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
const rules = createRuleEngine({ actionEngine: engine });
|
|
799
|
+
rules.register([
|
|
800
|
+
{ id: "wizard", priority: 1, when: () => true, then: [
|
|
801
|
+
{ type: "log", message: "before" },
|
|
802
|
+
{ type: "pause", message: "Confirmar?", as: "ack" },
|
|
803
|
+
{ type: "input", payload: { kind: "text", label: "Nome" }, as: "name" },
|
|
804
|
+
{ type: "log", resolve: (_c, s) => ({ message: `${s.name} (${s.ack})` }) },
|
|
805
|
+
] },
|
|
806
|
+
]);
|
|
807
|
+
|
|
808
|
+
const ctx = { out: [] };
|
|
809
|
+
const session = rules.evaluateInteractive(ctx);
|
|
810
|
+
|
|
811
|
+
session.next(); // → { source: "pause", payload: { message: "Confirmar?" } }
|
|
812
|
+
// ctx.out: ["before"]
|
|
813
|
+
session.next("yes"); // → { kind: "input", payload: { kind: "text", label: "Nome" } }
|
|
814
|
+
session.next("Anderson"); // → { done: true, value: RuleEvaluationResult }
|
|
815
|
+
// matched: ["wizard"]
|
|
816
|
+
// ctx.out: ["before", "Anderson (yes)"]
|
|
817
|
+
```
|
|
818
|
+
|
|
819
|
+
### Mistura sync + interactive (priority order)
|
|
820
|
+
|
|
821
|
+
Rules sync e interactive coexistem na mesma evaluation, respeitando priority. Rules sync rodam direto (sem yield); rules interactive pausam.
|
|
822
|
+
|
|
823
|
+
```typescript
|
|
824
|
+
rules.register([
|
|
825
|
+
{ id: "first", priority: 10, when: () => true, then: [{ type: "log", message: "first" }] },
|
|
826
|
+
{ id: "wizard", priority: 5, when: () => true, then: [
|
|
827
|
+
{ type: "pause", message: "?" },
|
|
828
|
+
] },
|
|
829
|
+
{ id: "last", priority: 1, when: () => true, then: [{ type: "log", message: "last" }] },
|
|
830
|
+
]);
|
|
831
|
+
|
|
832
|
+
const session = rules.evaluateInteractive(ctx);
|
|
833
|
+
session.next(); // first roda direto, wizard pausa
|
|
834
|
+
// ctx.out: ["first"]
|
|
835
|
+
session.next("ok"); // wizard completa, last roda
|
|
836
|
+
// ctx.out: ["first", "last"]
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
### Async generator (engine async + rule interactive)
|
|
840
|
+
|
|
841
|
+
Quando alguma rule é async transitivamente E alguma é interactive, `evaluateInteractive` retorna `AsyncInteractiveRuleSession`. Drenagem via `await session.next()`:
|
|
842
|
+
|
|
843
|
+
```typescript
|
|
844
|
+
rules.register([
|
|
845
|
+
{ id: "loadData", priority: 10, when: () => true, then: [
|
|
846
|
+
{ type: "fetchAsync", as: "v" },
|
|
847
|
+
{ type: "log", resolve: (_c, s) => ({ message: `loaded ${s.v}` }) },
|
|
848
|
+
] },
|
|
849
|
+
{ id: "getName", priority: 5, when: () => true, then: [
|
|
850
|
+
{ type: "input", payload: { kind: "text", label: "Nome" }, as: "name" },
|
|
851
|
+
] },
|
|
852
|
+
]);
|
|
853
|
+
|
|
854
|
+
const session = rules.evaluateInteractive(ctx); // AsyncIterator
|
|
855
|
+
|
|
856
|
+
await session.next(); // loadData rodou (fetch async), getName yieldou
|
|
857
|
+
await session.next("Anderson"); // matched: ["loadData", "getName"]
|
|
858
|
+
```
|
|
859
|
+
|
|
860
|
+
### Compilação JIT generator
|
|
861
|
+
|
|
862
|
+
Em `mode: "jit"`, `evaluateInteractive` usa **JIT generator compilado** (Fase R6 — `buildInteractiveRuleExecutor`). 4 wrappers possíveis:
|
|
863
|
+
|
|
864
|
+
| `isAsync` | `isInteractive` | Wrapper |
|
|
865
|
+
|-----------|-----------------|---------|
|
|
866
|
+
| false | false | `function ()` (path original — `evaluate`) |
|
|
867
|
+
| true | false | `async function ()` (`evaluateAsync`) |
|
|
868
|
+
| false | true | `function* ()` (`evaluateInteractive` sync) |
|
|
869
|
+
| true | true | `async function* ()` (`evaluateInteractive` async) |
|
|
870
|
+
|
|
871
|
+
JIT emit branch per-rule no loop:
|
|
872
|
+
|
|
873
|
+
```javascript
|
|
874
|
+
if (stored.isInteractive) {
|
|
875
|
+
ir = yield* ae.invokeInteractive(stored.actionId, params);
|
|
876
|
+
} else if (stored.isAsync) {
|
|
877
|
+
ir = await ae.invokeAsync(stored.actionId, params);
|
|
878
|
+
} else {
|
|
879
|
+
ir = ae.invoke(stored.actionId, params);
|
|
880
|
+
}
|
|
881
|
+
```
|
|
882
|
+
|
|
883
|
+
Decisão **per-rule em runtime**, baseada nas flags cached em `StoredRule.isAsync`/`isInteractive`. Em `mode: "interpret"` ou `"auto"` (antes do threshold), usa interpreter generator (mesmo behavior, sem unrolled performance).
|
|
884
|
+
|
|
885
|
+
---
|
|
886
|
+
|
|
731
887
|
## Error Handling
|
|
732
888
|
|
|
733
|
-
The engine **never throws** during evaluation. All errors are collected:
|
|
889
|
+
The engine **never throws** during evaluation. All runtime errors are collected:
|
|
734
890
|
|
|
735
891
|
| Error source | Behavior |
|
|
736
892
|
|-------------|----------|
|
|
@@ -740,9 +896,12 @@ The engine **never throws** during evaluation. All errors are collected:
|
|
|
740
896
|
| `onRulesComplete` throws | Silenced |
|
|
741
897
|
| Middleware throws | Error collected, invoke skipped, next rule |
|
|
742
898
|
| ActionEngine invoke errors | Directive errors accumulated in counters |
|
|
899
|
+
| Hidden action id missing at invoke time | Pipeline aborts with `abortedBy: "action-not-found"`, `success: false` |
|
|
743
900
|
| Sub-rule `when()` throws | Error collected, sub-rule skipped |
|
|
744
901
|
| `maxSubRuleDepth` exceeded | Error collected, sub-tree skipped (no abort) |
|
|
745
902
|
|
|
903
|
+
`register()` follows different rules — see [Registration](#registration). Structural errors at boot (missing handler) throw fail-fast.
|
|
904
|
+
|
|
746
905
|
### Inspecting errors
|
|
747
906
|
|
|
748
907
|
```typescript
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
'use strict';var core=require('@statedelta-actions/core');function M(r,t,e,i,o,h,b,s,u){if(s>=u)return o.push({ruleIndex:h,error:`maxSubRuleDepth (${u}) exceeded`}),i.errors++,false;for(let c=0;c<r.length;c++){let a=r[c];if(a.definition.when){let d;try{d=a.definition.when(t);}catch(g){o.push({ruleIndex:h,error:String(g)}),i.errors++;continue}if(!d)continue}if(a.actionId){let d=e.invoke(a.actionId,b);if(i.directivesApplied+=d.appliedCount,i.directivesSkipped+=d.skippedCount,i.errors+=d.errors.length,d.aborted)return true}if(a.subRules&&a.subRules.length>0&&M(a.subRules,t,e,i,o,h,b,s+1,u))return true}return false}async function $(r,t,e,i,o,h,b,s,u){if(s>=u)return o.push({ruleIndex:h,error:`maxSubRuleDepth (${u}) exceeded`}),i.errors++,false;for(let c=0;c<r.length;c++){let a=r[c];if(a.definition.when){let d;try{d=a.definition.when(t);}catch(g){o.push({ruleIndex:h,error:String(g)}),i.errors++;continue}if(!d)continue}if(a.actionId){let d=await e.invokeAsync(a.actionId,b);if(i.directivesApplied+=d.appliedCount,i.directivesSkipped+=d.skippedCount,i.errors+=d.errors.length,d.aborted)return true}if(a.subRules&&a.subRules.length>0&&await $(a.subRules,t,e,i,o,h,b,s+1,u))return true}return false}function V(){return r=>({$invoker:{ruleId:r.id,priority:r.priority,tags:r.tags??[]}})}function D(r,t,e,i){let o=i?Object.assign({},i):{};for(let h of r)Object.assign(o,h(t,e,o));return o}function L(){return {rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0}}function H(r,t,e,i,o,h,b,s,u,c){return {success:r,aborted:t,abortedBy:e,matched:i,skipped:o,notMatched:h,errors:b,processedCount:s,totalCount:u,counters:c}}function W(r,t){let e=r.filledNames.has("beforeRule"),i=r.filledNames.has("afterRule"),o=r.filledNames.has("onRulesComplete"),h=e||i;return function(s,u,c,a,d){let g=s.length,m=[],n=[],A=[],v=[],p=L(),T=a.length>0,C=true,x=false,_,y=g;c.setContext(u);let k=h?{ctx:u,counters:p}:void 0;for(let f=0;f<g;f++){let R=s[f],E=R.definition.id;if(p.rulesEvaluated++,e)try{let l=d.beforeRule(R.definition,k);if(l==="skip"){n.push(E),p.rulesSkipped++;continue}if(l==="abort"){C=!1,x=!0,_="beforeRule",y=f+1;break}}catch(l){v.push({ruleIndex:f,error:`beforeRule: ${l}`}),p.errors++;}let w;try{w=R.definition.when(u);}catch(l){v.push({ruleIndex:f,error:String(l)}),A.push(E),p.errors++;continue}if(!w){A.push(E);continue}m.push(E),p.rulesMatched++;let S;if(T)try{S=D(a,R.definition,u);}catch(l){v.push({ruleIndex:f,error:`Middleware: ${l}`}),p.errors++;continue}if(R.actionId){let l=c.invoke(R.actionId,S);if(p.directivesApplied+=l.appliedCount,p.directivesSkipped+=l.skippedCount,p.errors+=l.errors.length,i)try{if(d.afterRule(R.definition,l,k)==="abort"){C=!1,x=!0,_="afterRule",y=f+1;break}}catch{}if(l.aborted){C=l.abortedBy==="halt",x=true,_=l.abortedBy,y=f+1;break}}if(R.subRules&&R.subRules.length>0&&M(R.subRules,u,c,p,v,f,S,0,t)){C=false,x=true,_="sub-rule",y=f+1;break}}let I=H(C,x,_,m,n,A,v,y,g,p);if(o)try{d.onRulesComplete(I);}catch{}return I}}function J(r,t){let e=r.filledNames.has("beforeRule"),i=r.filledNames.has("afterRule"),o=r.filledNames.has("onRulesComplete"),h=e||i;return async function(s,u,c,a,d){let g=s.length,m=[],n=[],A=[],v=[],p=L(),T=a.length>0,C=true,x=false,_,y=g;c.setContext(u);let k=h?{ctx:u,counters:p}:void 0;for(let f=0;f<g;f++){let R=s[f],E=R.definition.id;if(p.rulesEvaluated++,e)try{let l=await d.beforeRule(R.definition,k);if(l==="skip"){n.push(E),p.rulesSkipped++;continue}if(l==="abort"){C=!1,x=!0,_="beforeRule",y=f+1;break}}catch(l){v.push({ruleIndex:f,error:`beforeRule: ${l}`}),p.errors++;}let w;try{w=R.definition.when(u);}catch(l){v.push({ruleIndex:f,error:String(l)}),A.push(E),p.errors++;continue}if(!w){A.push(E);continue}m.push(E),p.rulesMatched++;let S;if(T)try{S=D(a,R.definition,u);}catch(l){v.push({ruleIndex:f,error:`Middleware: ${l}`}),p.errors++;continue}if(R.actionId){let l=await c.invokeAsync(R.actionId,S);if(p.directivesApplied+=l.appliedCount,p.directivesSkipped+=l.skippedCount,p.errors+=l.errors.length,i)try{if(await d.afterRule(R.definition,l,k)==="abort"){C=!1,x=!0,_="afterRule",y=f+1;break}}catch{}if(l.aborted){C=l.abortedBy==="halt",x=true,_=l.abortedBy,y=f+1;break}}if(R.subRules&&R.subRules.length>0&&await $(R.subRules,u,c,p,v,f,S,0,t)){C=false,x=true,_="sub-rule",y=f+1;break}}let I=H(C,x,_,m,n,A,v,y,g,p);if(o)try{await d.onRulesComplete(I);}catch{}return I}}function O(r,t,e){return t?J(r,e):W(r,e)}function B(r,t,e,i,o,h,b){r.push(`{const _er={success:${t},aborted:true,abortedBy:${e},matched,skipped,notMatched,errors,processedCount:${i},totalCount:${o},counters};`),h&&r.push(`try{${b}_hookOnComplete(_er);}catch(_e){}`),r.push("return _er;}");}function j(r,t,e,i){let{filledNames:o,asyncNames:h}=r,b=y=>o.has(y),s=y=>h.has(y)?"await ":"",u=b("beforeRule"),c=b("afterRule"),a=b("onRulesComplete"),d=s("beforeRule"),g=s("afterRule"),m=s("onRulesComplete"),n=[];n.push("const len=rules.length;"),n.push("const matched=[];const skipped=[];const notMatched=[];"),n.push("const errors=[];"),n.push("const counters={rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0};"),n.push("ae.setContext(ctx);"),(u||c)&&n.push("const evalCtx={ctx,counters};"),u&&n.push("const _hookBefore=hooks.beforeRule;"),c&&n.push("const _hookAfter=hooks.afterRule;"),a&&n.push("const _hookOnComplete=hooks.onRulesComplete;"),n.push("for(let i=0;i<len;i++){"),n.push("const stored=rules[i];"),n.push("const _rid=stored.definition.id;"),n.push("counters.rulesEvaluated++;"),u&&(n.push("try{"),n.push(`const _bd=${d}_hookBefore(stored.definition,evalCtx);`),n.push('if(_bd==="skip"){skipped.push(_rid);counters.rulesSkipped++;continue;}'),n.push('if(_bd==="abort")'),B(n,"false",'"beforeRule"',"i+1","len",a,m),n.push('}catch(_e){errors.push({ruleIndex:i,error:"beforeRule: "+_e});counters.errors++;}')),n.push("let ev;"),n.push("try{ev=stored.definition.when(ctx);}catch(_e){errors.push({ruleIndex:i,error:String(_e)});notMatched.push(_rid);counters.errors++;continue;}"),n.push("if(!ev){notMatched.push(_rid);continue;}"),n.push("matched.push(_rid);counters.rulesMatched++;"),t&&(n.push("let params;"),n.push('try{params=$.runMw(mw,stored.definition,ctx);}catch(_e){errors.push({ruleIndex:i,error:"Middleware: "+_e});counters.errors++;continue;}'));let A=t?",params":"",v=e?`await ae.invokeAsync(stored.actionId${A})`:`ae.invoke(stored.actionId${A})`;n.push("if(stored.actionId){"),n.push(`const ir=${v};`),n.push("counters.directivesApplied+=ir.appliedCount;counters.directivesSkipped+=ir.skippedCount;counters.errors+=ir.errors.length;"),c&&(n.push("try{"),n.push(`const _ad=${g}_hookAfter(stored.definition,ir,evalCtx);`),n.push('if(_ad==="abort")'),B(n,"false",'"afterRule"',"i+1","len",a,m),n.push("}catch(_e){}")),n.push("if(ir.aborted)"),B(n,'ir.abortedBy==="halt"',"ir.abortedBy","i+1","len",a,m),n.push("}");let p=t?"params":"undefined";n.push("if(stored.subRules&&stored.subRules.length>0){"),n.push(`if(${e?"await ":""}$.evalSub(stored.subRules,ctx,ae,counters,errors,i,${p},0,$.maxDepth))`),B(n,"false",'"sub-rule"',"i+1","len",a,m),n.push("}"),n.push("}"),n.push("const _r={success:true,aborted:false,abortedBy:undefined,matched,skipped,notMatched,errors,processedCount:len,totalCount:len,counters};"),a&&n.push(`try{${m}_hookOnComplete(_r);}catch(_e){}`),n.push("return _r;");let T=n.join(`
|
|
2
|
-
`),
|
|
3
|
-
return(${
|
|
4
|
-
${
|
|
5
|
-
})();`),
|
|
1
|
+
'use strict';var core=require('@statedelta-actions/core');function B(n,r,t,o,c,d,b,R,a){if(R>=a)return c.push({ruleIndex:d,error:`maxSubRuleDepth (${a}) exceeded`}),o.errors++,false;for(let u=0;u<n.length;u++){let s=n[u];if(s.definition.when){let l;try{l=s.definition.when(r);}catch(v){c.push({ruleIndex:d,error:String(v)}),o.errors++;continue}if(!l)continue}if(s.actionId){let l=t.invoke(s.actionId,b);if(o.directivesApplied+=l.appliedCount,o.directivesSkipped+=l.skippedCount,o.errors+=l.errors.length,l.aborted)return true}if(s.subRules&&s.subRules.length>0&&B(s.subRules,r,t,o,c,d,b,R+1,a))return true}return false}async function F(n,r,t,o,c,d,b,R,a){if(R>=a)return c.push({ruleIndex:d,error:`maxSubRuleDepth (${a}) exceeded`}),o.errors++,false;for(let u=0;u<n.length;u++){let s=n[u];if(s.definition.when){let l;try{l=s.definition.when(r);}catch(v){c.push({ruleIndex:d,error:String(v)}),o.errors++;continue}if(!l)continue}if(s.actionId){let l=await t.invokeAsync(s.actionId,b);if(o.directivesApplied+=l.appliedCount,o.directivesSkipped+=l.skippedCount,o.errors+=l.errors.length,l.aborted)return true}if(s.subRules&&s.subRules.length>0&&await F(s.subRules,r,t,o,c,d,b,R+1,a))return true}return false}function Q(){return n=>({$invoker:{ruleId:n.id,priority:n.priority,tags:n.tags??[]}})}function $(n,r,t,o){let c=o?Object.assign({},o):{};for(let d of n)Object.assign(c,d(r,t,c));return c}function q(){return {rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0}}function U(n,r,t,o,c,d,b,R,a,u){return {success:n,aborted:r,abortedBy:t,matched:o,skipped:c,notMatched:d,errors:b,processedCount:R,totalCount:a,counters:u}}function X(n,r){let t=n.filledNames.has("beforeRule"),o=n.filledNames.has("afterRule"),c=n.filledNames.has("onRulesComplete"),d=t||o;return function(R,a,u,s,l){let v=R.length,_=[],e=[],A=[],y=[],h=q(),S=s.length>0,I=true,C=false,g,m=v;u.setContext(a);let E=d?{ctx:a,counters:h}:void 0;for(let f=0;f<v;f++){let p=R[f],k=p.definition.id;if(h.rulesEvaluated++,t)try{let i=l.beforeRule(p.definition,E);if(i==="skip"){e.push(k),h.rulesSkipped++;continue}if(i==="abort"){I=!1,C=!0,g="beforeRule",m=f+1;break}}catch(i){y.push({ruleIndex:f,error:`beforeRule: ${i}`}),h.errors++;}let T;try{T=p.definition.when(a);}catch(i){y.push({ruleIndex:f,error:String(i)}),A.push(k),h.errors++;continue}if(!T){A.push(k);continue}_.push(k),h.rulesMatched++;let x;if(S)try{x=$(s,p.definition,a);}catch(i){y.push({ruleIndex:f,error:`Middleware: ${i}`}),h.errors++;continue}if(p.actionId){let i=u.invoke(p.actionId,x);if(h.directivesApplied+=i.appliedCount,h.directivesSkipped+=i.skippedCount,h.errors+=i.errors.length,o)try{if(l.afterRule(p.definition,i,E)==="abort"){I=!1,C=!0,g="afterRule",m=f+1;break}}catch{}if(i.aborted){I=i.abortedBy==="halt",C=true,g=i.abortedBy,m=f+1;break}}if(p.subRules&&p.subRules.length>0&&B(p.subRules,a,u,h,y,f,x,0,r)){I=false,C=true,g="sub-rule",m=f+1;break}}let w=U(I,C,g,_,e,A,y,m,v,h);if(c)try{l.onRulesComplete(w);}catch{}return w}}function Y(n,r){let t=n.filledNames.has("beforeRule"),o=n.filledNames.has("afterRule"),c=n.filledNames.has("onRulesComplete"),d=t||o;return async function(R,a,u,s,l){let v=R.length,_=[],e=[],A=[],y=[],h=q(),S=s.length>0,I=true,C=false,g,m=v;u.setContext(a);let E=d?{ctx:a,counters:h}:void 0;for(let f=0;f<v;f++){let p=R[f],k=p.definition.id;if(h.rulesEvaluated++,t)try{let i=await l.beforeRule(p.definition,E);if(i==="skip"){e.push(k),h.rulesSkipped++;continue}if(i==="abort"){I=!1,C=!0,g="beforeRule",m=f+1;break}}catch(i){y.push({ruleIndex:f,error:`beforeRule: ${i}`}),h.errors++;}let T;try{T=p.definition.when(a);}catch(i){y.push({ruleIndex:f,error:String(i)}),A.push(k),h.errors++;continue}if(!T){A.push(k);continue}_.push(k),h.rulesMatched++;let x;if(S)try{x=$(s,p.definition,a);}catch(i){y.push({ruleIndex:f,error:`Middleware: ${i}`}),h.errors++;continue}if(p.actionId){let i=await u.invokeAsync(p.actionId,x);if(h.directivesApplied+=i.appliedCount,h.directivesSkipped+=i.skippedCount,h.errors+=i.errors.length,o)try{if(await l.afterRule(p.definition,i,E)==="abort"){I=!1,C=!0,g="afterRule",m=f+1;break}}catch{}if(i.aborted){I=i.abortedBy==="halt",C=true,g=i.abortedBy,m=f+1;break}}if(p.subRules&&p.subRules.length>0&&await F(p.subRules,a,u,h,y,f,x,0,r)){I=false,C=true,g="sub-rule",m=f+1;break}}let w=U(I,C,g,_,e,A,y,m,v,h);if(c)try{await l.onRulesComplete(w);}catch{}return w}}function O(n,r,t){return r?Y(n,t):X(n,t)}function G(){return {rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0}}function V(n,r,t,o,c,d,b,R,a,u){return {success:n,aborted:r,abortedBy:t,matched:o,skipped:c,notMatched:d,errors:b,processedCount:R,totalCount:a,counters:u}}function Z(n){let r=n.filledNames.has("beforeRule"),t=n.filledNames.has("afterRule"),o=n.filledNames.has("onRulesComplete"),c=r||t;return function*(b,R,a,u,s,l){let v=b.length,_=[],e=[],A=[],y=[],h=G(),S=u.length>0,I=true,C=false,g,m=v;a.setContext(R);let E=c?{ctx:R,counters:h}:void 0;for(let f=0;f<v;f++){let p=b[f],k=p.definition.id;if(h.rulesEvaluated++,r)try{let i=s.beforeRule(p.definition,E);if(i==="skip"){e.push(k),h.rulesSkipped++;continue}if(i==="abort"){I=!1,C=!0,g="beforeRule",m=f+1;break}}catch(i){y.push({ruleIndex:f,error:`beforeRule: ${i}`}),h.errors++;}let T;try{T=p.definition.when(R);}catch(i){y.push({ruleIndex:f,error:String(i)}),A.push(k),h.errors++;continue}if(!T){A.push(k);continue}_.push(k),h.rulesMatched++;let x;if(S)try{x=$(u,p.definition,R);}catch(i){y.push({ruleIndex:f,error:`Middleware: ${i}`}),h.errors++;continue}if(p.actionId){let i;if(p.isInteractive?i=yield*a.invokeInteractive(p.actionId,x):i=a.invoke(p.actionId,x),h.directivesApplied+=i.appliedCount,h.directivesSkipped+=i.skippedCount,h.errors+=i.errors.length,t)try{if(s.afterRule(p.definition,i,E)==="abort"){I=!1,C=!0,g="afterRule",m=f+1;break}}catch{}if(i.aborted){I=i.abortedBy==="halt",C=true,g=i.abortedBy,m=f+1;break}}if(p.subRules&&p.subRules.length>0&&(yield*D(p.subRules,R,a,h,y,f,x,0,l))){I=false,C=true,g="sub-rule",m=f+1;break}}let w=V(I,C,g,_,e,A,y,m,v,h);if(o)try{s.onRulesComplete(w);}catch{}return w}}function ee(n){let r=n.filledNames.has("beforeRule"),t=n.filledNames.has("afterRule"),o=n.filledNames.has("onRulesComplete"),c=r||t;return async function*(b,R,a,u,s,l){let v=b.length,_=[],e=[],A=[],y=[],h=G(),S=u.length>0,I=true,C=false,g,m=v;a.setContext(R);let E=c?{ctx:R,counters:h}:void 0;for(let f=0;f<v;f++){let p=b[f],k=p.definition.id;if(h.rulesEvaluated++,r)try{let i=await s.beforeRule(p.definition,E);if(i==="skip"){e.push(k),h.rulesSkipped++;continue}if(i==="abort"){I=!1,C=!0,g="beforeRule",m=f+1;break}}catch(i){y.push({ruleIndex:f,error:`beforeRule: ${i}`}),h.errors++;}let T;try{T=p.definition.when(R);}catch(i){y.push({ruleIndex:f,error:String(i)}),A.push(k),h.errors++;continue}if(!T){A.push(k);continue}_.push(k),h.rulesMatched++;let x;if(S)try{x=$(u,p.definition,R);}catch(i){y.push({ruleIndex:f,error:`Middleware: ${i}`}),h.errors++;continue}if(p.actionId){let i;if(p.isInteractive?i=yield*a.invokeInteractive(p.actionId,x):p.isAsync?i=await a.invokeAsync(p.actionId,x):i=a.invoke(p.actionId,x),h.directivesApplied+=i.appliedCount,h.directivesSkipped+=i.skippedCount,h.errors+=i.errors.length,t)try{if(await s.afterRule(p.definition,i,E)==="abort"){I=!1,C=!0,g="afterRule",m=f+1;break}}catch{}if(i.aborted){I=i.abortedBy==="halt",C=true,g=i.abortedBy,m=f+1;break}}if(p.subRules&&p.subRules.length>0&&(yield*N(p.subRules,R,a,h,y,f,x,0,l))){I=false,C=true,g="sub-rule",m=f+1;break}}let w=V(I,C,g,_,e,A,y,m,v,h);if(o)try{await s.onRulesComplete(w);}catch{}return w}}function*D(n,r,t,o,c,d,b,R,a){if(R>=a)return c.push({ruleIndex:d,error:`maxSubRuleDepth (${a}) exceeded`}),o.errors++,false;for(let u=0;u<n.length;u++){let s=n[u];if(s.definition.when){let l;try{l=s.definition.when(r);}catch(v){c.push({ruleIndex:d,error:String(v)}),o.errors++;continue}if(!l)continue}if(s.actionId){let l;if(s.isInteractive?l=yield*t.invokeInteractive(s.actionId,b):l=t.invoke(s.actionId,b),o.directivesApplied+=l.appliedCount,o.directivesSkipped+=l.skippedCount,o.errors+=l.errors.length,l.aborted)return true}if(s.subRules&&s.subRules.length>0&&(yield*D(s.subRules,r,t,o,c,d,b,R+1,a)))return true}return false}async function*N(n,r,t,o,c,d,b,R,a){if(R>=a)return c.push({ruleIndex:d,error:`maxSubRuleDepth (${a}) exceeded`}),o.errors++,false;for(let u=0;u<n.length;u++){let s=n[u];if(s.definition.when){let l;try{l=s.definition.when(r);}catch(v){c.push({ruleIndex:d,error:String(v)}),o.errors++;continue}if(!l)continue}if(s.actionId){let l;if(s.isInteractive?l=yield*t.invokeInteractive(s.actionId,b):s.isAsync?l=await t.invokeAsync(s.actionId,b):l=t.invoke(s.actionId,b),o.directivesApplied+=l.appliedCount,o.directivesSkipped+=l.skippedCount,o.errors+=l.errors.length,l.aborted)return true}if(s.subRules&&s.subRules.length>0&&(yield*N(s.subRules,r,t,o,c,d,b,R+1,a)))return true}return false}function W(n,r){return r?ee(n):Z(n)}function M(n,r,t,o,c,d,b){n.push(`{const _er={success:${r},aborted:true,abortedBy:${t},matched,skipped,notMatched,errors,processedCount:${o},totalCount:${c},counters};`),d&&n.push(`try{${b}_hookOnComplete(_er);}catch(_e){}`),n.push("return _er;}");}function J(n,r,t,o){let{filledNames:c,asyncNames:d}=n,b=m=>c.has(m),R=m=>d.has(m)?"await ":"",a=b("beforeRule"),u=b("afterRule"),s=b("onRulesComplete"),l=R("beforeRule"),v=R("afterRule"),_=R("onRulesComplete"),e=[];e.push("const len=rules.length;"),e.push("const matched=[];const skipped=[];const notMatched=[];"),e.push("const errors=[];"),e.push("const counters={rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0};"),e.push("ae.setContext(ctx);"),(a||u)&&e.push("const evalCtx={ctx,counters};"),a&&e.push("const _hookBefore=hooks.beforeRule;"),u&&e.push("const _hookAfter=hooks.afterRule;"),s&&e.push("const _hookOnComplete=hooks.onRulesComplete;"),e.push("for(let i=0;i<len;i++){"),e.push("const stored=rules[i];"),e.push("const _rid=stored.definition.id;"),e.push("counters.rulesEvaluated++;"),a&&(e.push("try{"),e.push(`const _bd=${l}_hookBefore(stored.definition,evalCtx);`),e.push('if(_bd==="skip"){skipped.push(_rid);counters.rulesSkipped++;continue;}'),e.push('if(_bd==="abort")'),M(e,"false",'"beforeRule"',"i+1","len",s,_),e.push('}catch(_e){errors.push({ruleIndex:i,error:"beforeRule: "+_e});counters.errors++;}')),e.push("let ev;"),e.push("try{ev=stored.definition.when(ctx);}catch(_e){errors.push({ruleIndex:i,error:String(_e)});notMatched.push(_rid);counters.errors++;continue;}"),e.push("if(!ev){notMatched.push(_rid);continue;}"),e.push("matched.push(_rid);counters.rulesMatched++;"),r&&(e.push("let params;"),e.push('try{params=$.runMw(mw,stored.definition,ctx);}catch(_e){errors.push({ruleIndex:i,error:"Middleware: "+_e});counters.errors++;continue;}'));let A=r?",params":"",y=t?`await ae.invokeAsync(stored.actionId${A})`:`ae.invoke(stored.actionId${A})`;e.push("if(stored.actionId){"),e.push(`const ir=${y};`),e.push("counters.directivesApplied+=ir.appliedCount;counters.directivesSkipped+=ir.skippedCount;counters.errors+=ir.errors.length;"),u&&(e.push("try{"),e.push(`const _ad=${v}_hookAfter(stored.definition,ir,evalCtx);`),e.push('if(_ad==="abort")'),M(e,"false",'"afterRule"',"i+1","len",s,_),e.push("}catch(_e){}")),e.push("if(ir.aborted)"),M(e,'ir.abortedBy==="halt"',"ir.abortedBy","i+1","len",s,_),e.push("}");let h=r?"params":"undefined";e.push("if(stored.subRules&&stored.subRules.length>0){"),e.push(`if(${t?"await ":""}$.evalSub(stored.subRules,ctx,ae,counters,errors,i,${h},0,$.maxDepth))`),M(e,"false",'"sub-rule"',"i+1","len",s,_),e.push("}"),e.push("}"),e.push("const _r={success:true,aborted:false,abortedBy:undefined,matched,skipped,notMatched,errors,processedCount:len,totalCount:len,counters};"),s&&e.push(`try{${_}_hookOnComplete(_r);}catch(_e){}`),e.push("return _r;");let S=e.join(`
|
|
2
|
+
`),I=t?"async ":"",C=new Function("rules","ctx","ae","mw","hooks","$",`"use strict";
|
|
3
|
+
return(${I}()=>{
|
|
4
|
+
${S}
|
|
5
|
+
})();`),g={maxDepth:o};return g.evalSub=t?F:B,r&&(g.runMw=$),function(E,w,f,p,k){return C(E,w,f,p,k,g)}}function P(n,r,t,o){let{filledNames:c,asyncNames:d}=n,b=g=>c.has(g),R=g=>d.has(g)?"await ":"",a=b("beforeRule"),u=b("afterRule"),s=b("onRulesComplete"),l=R("beforeRule"),v=R("afterRule"),_=R("onRulesComplete"),e=[];e.push("const len=rules.length;"),e.push("const matched=[];const skipped=[];const notMatched=[];"),e.push("const errors=[];"),e.push("const counters={rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0};"),e.push("ae.setContext(ctx);"),(a||u)&&e.push("const evalCtx={ctx,counters};"),a&&e.push("const _hookBefore=hooks.beforeRule;"),u&&e.push("const _hookAfter=hooks.afterRule;"),s&&e.push("const _hookOnComplete=hooks.onRulesComplete;"),e.push("for(let i=0;i<len;i++){"),e.push("const stored=rules[i];"),e.push("const _rid=stored.definition.id;"),e.push("counters.rulesEvaluated++;"),a&&(e.push("try{"),e.push(`const _bd=${l}_hookBefore(stored.definition,evalCtx);`),e.push('if(_bd==="skip"){skipped.push(_rid);counters.rulesSkipped++;continue;}'),e.push('if(_bd==="abort")'),M(e,"false",'"beforeRule"',"i+1","len",s,_),e.push('}catch(_e){errors.push({ruleIndex:i,error:"beforeRule: "+_e});counters.errors++;}')),e.push("let ev;"),e.push("try{ev=stored.definition.when(ctx);}catch(_e){errors.push({ruleIndex:i,error:String(_e)});notMatched.push(_rid);counters.errors++;continue;}"),e.push("if(!ev){notMatched.push(_rid);continue;}"),e.push("matched.push(_rid);counters.rulesMatched++;"),r&&(e.push("let params;"),e.push('try{params=$.runMw(mw,stored.definition,ctx);}catch(_e){errors.push({ruleIndex:i,error:"Middleware: "+_e});counters.errors++;continue;}'));let A=r?",params":"";e.push("if(stored.actionId){"),e.push("let ir;"),e.push("if(stored.isInteractive){"),e.push(`ir=yield* ae.invokeInteractive(stored.actionId${A});`),e.push("}else "),t?(e.push("if(stored.isAsync){"),e.push(`ir=await ae.invokeAsync(stored.actionId${A});`),e.push("}else{")):e.push("{"),e.push(`ir=ae.invoke(stored.actionId${A});`),e.push("}"),e.push("counters.directivesApplied+=ir.appliedCount;counters.directivesSkipped+=ir.skippedCount;counters.errors+=ir.errors.length;"),u&&(e.push("try{"),e.push(`const _ad=${v}_hookAfter(stored.definition,ir,evalCtx);`),e.push('if(_ad==="abort")'),M(e,"false",'"afterRule"',"i+1","len",s,_),e.push("}catch(_e){}")),e.push("if(ir.aborted)"),M(e,'ir.abortedBy==="halt"',"ir.abortedBy","i+1","len",s,_),e.push("}");let y=r?"params":"undefined";e.push("if(stored.subRules&&stored.subRules.length>0){"),e.push(`if(yield* $.evalSubInt(stored.subRules,ctx,ae,counters,errors,i,${y},0,$.maxDepth))`),M(e,"false",'"sub-rule"',"i+1","len",s,_),e.push("}"),e.push("}"),e.push("const _r={success:true,aborted:false,abortedBy:undefined,matched,skipped,notMatched,errors,processedCount:len,totalCount:len,counters};"),s&&e.push(`try{${_}_hookOnComplete(_r);}catch(_e){}`),e.push("return _r;");let h=e.join(`
|
|
6
|
+
`),S=t?"async function*()":"function*()",I=new Function("rules","ctx","ae","mw","hooks","$",`"use strict";
|
|
7
|
+
return(${S}{
|
|
8
|
+
${h}
|
|
9
|
+
})();`),C={maxDepth:o};return C.evalSubInt=t?N:D,r&&(C.runMw=$),function(m,E,w,f,p){return I(m,E,w,f,p,C)}}function z(n){if(!n.id||typeof n.id!="string")return {ruleId:n.id??"(missing)",code:"INVALID_RULE",message:"rule must have a string id"};if(typeof n.priority!="number")return {ruleId:n.id,code:"INVALID_RULE",message:"rule must have a numeric priority"};if(typeof n.when!="function")return {ruleId:n.id,code:"INVALID_RULE",message:"rule must have a when function"};let r=Array.isArray(n.then)&&n.then.length>0,t=Array.isArray(n.rules)&&n.rules.length>0;return !r&&!t?{ruleId:n.id,code:"INVALID_RULE",message:"rule must have then or sub-rules (or both)"}:null}function K(n,r){let t=`${r}.${n.id??"(missing)"}`;if(!n.id||typeof n.id!="string")return {ruleId:t,code:"INVALID_RULE",message:"sub-rule must have a string id"};let o=Array.isArray(n.then)&&n.then.length>0,c=Array.isArray(n.rules)&&n.rules.length>0;return !o&&!c?{ruleId:t,code:"INVALID_RULE",message:"sub-rule must have then or sub-rules (or both)"}:null}var L=()=>{},j=class{_actionEngine;_middleware;_ruleHooks;_maxSubRuleDepth;_requestedMode;_ruleHookAnalysis;_hasAnyInteractiveRule=false;_isAsync;_ruleEvaluator;_mode;_maybeAutoPromote;_interactiveEvaluator=null;_interactiveEvaluatorIsAsync=false;_ruleRegistry=new Map;_rules=[];_batch=null;constructor(r){if(this._actionEngine=r.actionEngine,this._middleware=r.middleware??[],this._ruleHooks=r.ruleHooks??{},this._maxSubRuleDepth=r.maxSubRuleDepth??10,this._requestedMode=r.mode??"auto",this._ruleHookAnalysis=core.analyzeSlots(this._ruleHooks,core.RULE_SLOT_NAMES),this._isAsync=this._ruleHookAnalysis.hasAnyAsync,this._requestedMode==="jit")this._ruleEvaluator=this._buildJitRule(),this._mode="jit",this._maybeAutoPromote=L;else if(this._ruleEvaluator=O(this._ruleHookAnalysis,this._isAsync,this._maxSubRuleDepth),this._mode="interpret",this._requestedMode==="auto"){let t=0,o=r.autoJitThreshold??8;this._maybeAutoPromote=()=>{++t>=o&&this._promote();};}else this._maybeAutoPromote=L;}get actionEngine(){return this._actionEngine}get isAsync(){return this._isAsync}get isInteractive(){return this._hasAnyInteractiveRule}get compilationMode(){return this._mode}get size(){return this._rules.length}has(r){return this._ruleRegistry.has(r)}register(r){let t=[],o=[],c=[],d=[];for(let u of r){let s=z(u);if(s){t.push(s);continue}if(this._ruleRegistry.has(u.id)||c.some(y=>y.id===u.id)){t.push({ruleId:u.id,code:"DUPLICATE_ID",message:`rule "${u.id}" is already registered`});continue}let l=`rule:${u.id}`,v=Array.isArray(u.then)&&u.then.length>0,_=v?l:"",e=Array.isArray(u.rules)&&u.rules.length>0?this._collectSubRules(l,u.rules,t,o,d):void 0,A={definition:u,actionId:_,priority:u.priority,subRules:e?.length?e:void 0,isAsync:false,isInteractive:false};if(v){let y=["rule"];u.tags&&y.push(...u.tags),o.push({id:_,tags:y,directives:u.then,declarations:u.declarations});}c.push({id:u.id,stored:A});}let b=[];if(o.length>0){let u=this._actionEngine.register(o);for(let s of u.errors){let l=this._actionIdToRuleId(s.actionId);t.push({ruleId:l??s.actionId,code:s.code??"ACTION_ERROR",message:s.error});}b=u.warnings;}let R=[];for(let{id:u,stored:s}of c)this._ruleRegistry.set(u,s),se(this._rules,s),R.push(u);for(let{qualifiedId:u,stored:s}of d)this._ruleRegistry.set(u,s);let a={registered:R,errors:t,warnings:b};return this._batch?(this._batch.registered.push(...R),this._batch.errors.push(...t),this._batch.warnings.push(...b)):R.length>0&&this._refreshRuleFlags(),a}unregister(r){let t=this._ruleRegistry.get(r);return t?(this._ruleRegistry.delete(r),ie(this._rules,t),t.actionId&&this._actionEngine.unregister(t.actionId),t.subRules&&this._unregisterSubRules(t.subRules),this._refreshRuleFlags(),true):false}beginBatch(){this._batch||(this._batch={depth:0,registered:[],errors:[],warnings:[]}),this._batch.depth++,this._actionEngine.beginBatch();}endBatch(){if(!this._batch||this._batch.depth<=0)throw new Error("endBatch() called without matching beginBatch()");this._batch.depth--;let r=this._actionEngine.endBatch();if(this._batch.depth>0)return {registered:[],errors:[],warnings:[]};let t=this._batch;for(let c of r.errors){let d=this._actionIdToRuleId(c.actionId);t.errors.push({ruleId:d??c.actionId,code:c.code??"ACTION_ERROR",message:c.error});}t.warnings.push(...r.warnings);let o={registered:t.registered,errors:t.errors,warnings:t.warnings};return this._batch=null,this._refreshRuleFlags(),o}batch(r){this.beginBatch();try{return r(this),this.endBatch()}catch(t){try{this.endBatch();}catch{}throw t}}evaluate(r){if(this._hasAnyInteractiveRule)throw new Error("Cannot call evaluate() \u2014 at least one rule is interactive (transitively). Use evaluateInteractive() instead.");if(this._isAsync)throw new Error("Cannot call evaluate() with async hooks or async rules. Use evaluateAsync() instead.");let t=this._ruleEvaluator(this._rules,r,this._actionEngine,this._middleware,this._ruleHooks);return this._maybeAutoPromote(),t}async evaluateAsync(r){if(this._hasAnyInteractiveRule)throw new Error("Cannot call evaluateAsync() \u2014 at least one rule is interactive (transitively). Use evaluateInteractive() instead.");let t=await this._ruleEvaluator(this._rules,r,this._actionEngine,this._middleware,this._ruleHooks);return this._maybeAutoPromote(),t}evaluateInteractive(r){if(!this._hasAnyInteractiveRule)throw new Error("Cannot call evaluateInteractive() \u2014 no registered rule is interactive (transitively). Use evaluate() or evaluateAsync() instead.");return (this._interactiveEvaluator===null||this._interactiveEvaluatorIsAsync!==this._isAsync)&&(this._interactiveEvaluator=this._mode==="jit"?P(this._ruleHookAnalysis,this._middleware.length>0,this._isAsync,this._maxSubRuleDepth):W(this._ruleHookAnalysis,this._isAsync),this._interactiveEvaluatorIsAsync=this._isAsync),this._interactiveEvaluator(this._rules,r,this._actionEngine,this._middleware,this._ruleHooks,this._maxSubRuleDepth)}compile(){this._requestedMode!=="interpret"&&this._mode!=="jit"&&this._promote();}_collectSubRules(r,t,o,c,d){let b=[],R=this._actionIdToRuleId(r);for(let a of t){let u=K(a,R);if(u){o.push(u);continue}let s=`${r}.${a.id}`,l=`${R}.${a.id}`,v=Array.isArray(a.then)&&a.then.length>0,_=Array.isArray(a.rules)&&a.rules.length>0?this._collectSubRules(s,a.rules,o,c,d):void 0,e={definition:a,actionId:v?s:"",subRules:_?.length?_:void 0,isAsync:false,isInteractive:false};if(v){let A=["rule"];a.tags&&A.push(...a.tags),c.push({id:s,tags:A,directives:a.then,declarations:a.declarations});}d.push({qualifiedId:l,stored:e}),b.push(e);}return b}_unregisterSubRules(r){for(let t of r){if(t.actionId){let o=this._actionIdToRuleId(t.actionId);o&&this._ruleRegistry.delete(o),this._actionEngine.unregister(t.actionId);}t.subRules&&this._unregisterSubRules(t.subRules);}}_actionIdToRuleId(r){return r.startsWith("rule:")?r.slice(5):null}_refreshRuleFlags(){let r=false,t=false,o=d=>{if(d.actionId?(d.isAsync=this._actionEngine.isActionAsync(d.actionId)??false,d.isInteractive=this._actionEngine.isActionInteractive(d.actionId)??false,d.isAsync&&(r=true),d.isInteractive&&(t=true)):(d.isAsync=false,d.isInteractive=false),d.subRules)for(let b of d.subRules)o(b);};for(let d of this._rules)o(d);this._hasAnyInteractiveRule=t;let c=this._ruleHookAnalysis.hasAnyAsync||r;c!==this._isAsync?(this._isAsync=c,this._rebuildEvaluator()):this._isAsync=c;}_rebuildEvaluator(){this._mode==="jit"?this._ruleEvaluator=this._buildJitRule():this._ruleEvaluator=O(this._ruleHookAnalysis,this._isAsync,this._maxSubRuleDepth);}_promote(){this._ruleEvaluator=this._buildJitRule(),this._mode="jit",this._maybeAutoPromote=L;}_buildJitRule(){return J(this._ruleHookAnalysis,this._middleware.length>0,this._isAsync,this._maxSubRuleDepth)}};function ne(n){return new j(n)}function se(n,r){let t=0,o=n.length;for(;t<o;){let c=t+o>>>1;n[c].priority>=r.priority?t=c+1:o=c;}n.splice(t,0,r);}function ie(n,r){let t=n.indexOf(r);return t===-1?false:(n.splice(t,1),true)}var oe={analyze:()=>({capabilities:["halt"],dependencies:[]}),execute:()=>({ok:true,halt:true})};exports.HALT_HANDLER=oe;exports.createInvokerMiddleware=Q;exports.createRuleEngine=ne;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Directive,
|
|
1
|
+
import { Directive, RuleError, FrameCounters, RegisterWarning, HookFn, DirectiveResult } from '@statedelta-actions/core';
|
|
2
2
|
import { IActionEngine } from '@statedelta-actions/actions';
|
|
3
3
|
|
|
4
4
|
interface SubRuleDefinition<TCtx = unknown> {
|
|
@@ -69,11 +69,37 @@ interface RuleEngineConfig<TCtx = unknown> {
|
|
|
69
69
|
/** Threshold de evaluate() calls para auto-promote em modo "auto". Default: 8. */
|
|
70
70
|
autoJitThreshold?: number;
|
|
71
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Sessão de avaliação de rules em modo interactive — retornada por
|
|
74
|
+
* `evaluateInteractive(ctx)`. Drena via `next()` igual a `InteractiveSession`
|
|
75
|
+
* do actions, mas o `done.value` final é `RuleEvaluationResult`.
|
|
76
|
+
*/
|
|
77
|
+
interface InteractiveRuleSession extends Iterator<unknown, RuleEvaluationResult, unknown> {
|
|
78
|
+
next(value?: unknown): IteratorResult<unknown, RuleEvaluationResult>;
|
|
79
|
+
return(): IteratorResult<unknown, RuleEvaluationResult>;
|
|
80
|
+
throw(err?: unknown): IteratorResult<unknown, RuleEvaluationResult>;
|
|
81
|
+
[Symbol.iterator](): InteractiveRuleSession;
|
|
82
|
+
}
|
|
83
|
+
interface AsyncInteractiveRuleSession extends AsyncIterator<unknown, RuleEvaluationResult, unknown> {
|
|
84
|
+
next(value?: unknown): Promise<IteratorResult<unknown, RuleEvaluationResult>>;
|
|
85
|
+
return(): Promise<IteratorResult<unknown, RuleEvaluationResult>>;
|
|
86
|
+
throw(err?: unknown): Promise<IteratorResult<unknown, RuleEvaluationResult>>;
|
|
87
|
+
[Symbol.asyncIterator](): AsyncInteractiveRuleSession;
|
|
88
|
+
}
|
|
72
89
|
interface IRuleEngine<TCtx = unknown> {
|
|
73
90
|
register(rules: readonly RuleDefinition<TCtx>[]): RuleRegisterResult;
|
|
74
91
|
unregister(id: string): boolean;
|
|
75
92
|
evaluate(ctx: TCtx): RuleEvaluationResult;
|
|
76
93
|
evaluateAsync(ctx: TCtx): Promise<RuleEvaluationResult>;
|
|
94
|
+
/**
|
|
95
|
+
* Avalia rules em modo interactive — retorna iterator drenável.
|
|
96
|
+
* Lança se nenhuma rule registrada é interactive transitivamente, ou se
|
|
97
|
+
* actionEngine não tem `interactive` configurado.
|
|
98
|
+
*
|
|
99
|
+
* Variante async (AsyncInteractiveRuleSession) é retornada quando alguma
|
|
100
|
+
* rule é async transitivamente OU algum hook é async.
|
|
101
|
+
*/
|
|
102
|
+
evaluateInteractive(ctx: TCtx): InteractiveRuleSession | AsyncInteractiveRuleSession;
|
|
77
103
|
beginBatch(): void;
|
|
78
104
|
endBatch(): RuleRegisterResult;
|
|
79
105
|
/** Executa fn dentro de um batch, com endBatch() garantido (inclusive em throw). */
|
|
@@ -84,6 +110,8 @@ interface IRuleEngine<TCtx = unknown> {
|
|
|
84
110
|
has(id: string): boolean;
|
|
85
111
|
readonly actionEngine: IActionEngine<TCtx>;
|
|
86
112
|
readonly isAsync: boolean;
|
|
113
|
+
/** Alguma rule registrada é interactive transitivamente? Cached. */
|
|
114
|
+
readonly isInteractive: boolean;
|
|
87
115
|
readonly compilationMode: "interpret" | "jit";
|
|
88
116
|
/** Número de rules top-level registradas. */
|
|
89
117
|
readonly size: number;
|
|
@@ -115,4 +143,4 @@ declare const HALT_HANDLER: {
|
|
|
115
143
|
|
|
116
144
|
declare function createInvokerMiddleware<TCtx>(): RuleMiddleware<TCtx>;
|
|
117
145
|
|
|
118
|
-
export { HALT_HANDLER, type IRuleEngine, type RuleDefinition, type RuleEngineConfig, type RuleEvaluationContext, type RuleEvaluationResult, type RuleHooks, type RuleMiddleware, type RuleRegisterError, type RuleRegisterResult, type SubRuleDefinition, createInvokerMiddleware, createRuleEngine };
|
|
146
|
+
export { type AsyncInteractiveRuleSession, HALT_HANDLER, type IRuleEngine, type InteractiveRuleSession, type RuleDefinition, type RuleEngineConfig, type RuleEvaluationContext, type RuleEvaluationResult, type RuleHooks, type RuleMiddleware, type RuleRegisterError, type RuleRegisterResult, type SubRuleDefinition, createInvokerMiddleware, createRuleEngine };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Directive,
|
|
1
|
+
import { Directive, RuleError, FrameCounters, RegisterWarning, HookFn, DirectiveResult } from '@statedelta-actions/core';
|
|
2
2
|
import { IActionEngine } from '@statedelta-actions/actions';
|
|
3
3
|
|
|
4
4
|
interface SubRuleDefinition<TCtx = unknown> {
|
|
@@ -69,11 +69,37 @@ interface RuleEngineConfig<TCtx = unknown> {
|
|
|
69
69
|
/** Threshold de evaluate() calls para auto-promote em modo "auto". Default: 8. */
|
|
70
70
|
autoJitThreshold?: number;
|
|
71
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Sessão de avaliação de rules em modo interactive — retornada por
|
|
74
|
+
* `evaluateInteractive(ctx)`. Drena via `next()` igual a `InteractiveSession`
|
|
75
|
+
* do actions, mas o `done.value` final é `RuleEvaluationResult`.
|
|
76
|
+
*/
|
|
77
|
+
interface InteractiveRuleSession extends Iterator<unknown, RuleEvaluationResult, unknown> {
|
|
78
|
+
next(value?: unknown): IteratorResult<unknown, RuleEvaluationResult>;
|
|
79
|
+
return(): IteratorResult<unknown, RuleEvaluationResult>;
|
|
80
|
+
throw(err?: unknown): IteratorResult<unknown, RuleEvaluationResult>;
|
|
81
|
+
[Symbol.iterator](): InteractiveRuleSession;
|
|
82
|
+
}
|
|
83
|
+
interface AsyncInteractiveRuleSession extends AsyncIterator<unknown, RuleEvaluationResult, unknown> {
|
|
84
|
+
next(value?: unknown): Promise<IteratorResult<unknown, RuleEvaluationResult>>;
|
|
85
|
+
return(): Promise<IteratorResult<unknown, RuleEvaluationResult>>;
|
|
86
|
+
throw(err?: unknown): Promise<IteratorResult<unknown, RuleEvaluationResult>>;
|
|
87
|
+
[Symbol.asyncIterator](): AsyncInteractiveRuleSession;
|
|
88
|
+
}
|
|
72
89
|
interface IRuleEngine<TCtx = unknown> {
|
|
73
90
|
register(rules: readonly RuleDefinition<TCtx>[]): RuleRegisterResult;
|
|
74
91
|
unregister(id: string): boolean;
|
|
75
92
|
evaluate(ctx: TCtx): RuleEvaluationResult;
|
|
76
93
|
evaluateAsync(ctx: TCtx): Promise<RuleEvaluationResult>;
|
|
94
|
+
/**
|
|
95
|
+
* Avalia rules em modo interactive — retorna iterator drenável.
|
|
96
|
+
* Lança se nenhuma rule registrada é interactive transitivamente, ou se
|
|
97
|
+
* actionEngine não tem `interactive` configurado.
|
|
98
|
+
*
|
|
99
|
+
* Variante async (AsyncInteractiveRuleSession) é retornada quando alguma
|
|
100
|
+
* rule é async transitivamente OU algum hook é async.
|
|
101
|
+
*/
|
|
102
|
+
evaluateInteractive(ctx: TCtx): InteractiveRuleSession | AsyncInteractiveRuleSession;
|
|
77
103
|
beginBatch(): void;
|
|
78
104
|
endBatch(): RuleRegisterResult;
|
|
79
105
|
/** Executa fn dentro de um batch, com endBatch() garantido (inclusive em throw). */
|
|
@@ -84,6 +110,8 @@ interface IRuleEngine<TCtx = unknown> {
|
|
|
84
110
|
has(id: string): boolean;
|
|
85
111
|
readonly actionEngine: IActionEngine<TCtx>;
|
|
86
112
|
readonly isAsync: boolean;
|
|
113
|
+
/** Alguma rule registrada é interactive transitivamente? Cached. */
|
|
114
|
+
readonly isInteractive: boolean;
|
|
87
115
|
readonly compilationMode: "interpret" | "jit";
|
|
88
116
|
/** Número de rules top-level registradas. */
|
|
89
117
|
readonly size: number;
|
|
@@ -115,4 +143,4 @@ declare const HALT_HANDLER: {
|
|
|
115
143
|
|
|
116
144
|
declare function createInvokerMiddleware<TCtx>(): RuleMiddleware<TCtx>;
|
|
117
145
|
|
|
118
|
-
export { HALT_HANDLER, type IRuleEngine, type RuleDefinition, type RuleEngineConfig, type RuleEvaluationContext, type RuleEvaluationResult, type RuleHooks, type RuleMiddleware, type RuleRegisterError, type RuleRegisterResult, type SubRuleDefinition, createInvokerMiddleware, createRuleEngine };
|
|
146
|
+
export { type AsyncInteractiveRuleSession, HALT_HANDLER, type IRuleEngine, type InteractiveRuleSession, type RuleDefinition, type RuleEngineConfig, type RuleEvaluationContext, type RuleEvaluationResult, type RuleHooks, type RuleMiddleware, type RuleRegisterError, type RuleRegisterResult, type SubRuleDefinition, createInvokerMiddleware, createRuleEngine };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import {analyzeSlots,RULE_SLOT_NAMES}from'@statedelta-actions/core';function M(r,t,e,i,o,h,b,s,u){if(s>=u)return o.push({ruleIndex:h,error:`maxSubRuleDepth (${u}) exceeded`}),i.errors++,false;for(let c=0;c<r.length;c++){let a=r[c];if(a.definition.when){let d;try{d=a.definition.when(t);}catch(g){o.push({ruleIndex:h,error:String(g)}),i.errors++;continue}if(!d)continue}if(a.actionId){let d=e.invoke(a.actionId,b);if(i.directivesApplied+=d.appliedCount,i.directivesSkipped+=d.skippedCount,i.errors+=d.errors.length,d.aborted)return true}if(a.subRules&&a.subRules.length>0&&M(a.subRules,t,e,i,o,h,b,s+1,u))return true}return false}async function $(r,t,e,i,o,h,b,s,u){if(s>=u)return o.push({ruleIndex:h,error:`maxSubRuleDepth (${u}) exceeded`}),i.errors++,false;for(let c=0;c<r.length;c++){let a=r[c];if(a.definition.when){let d;try{d=a.definition.when(t);}catch(g){o.push({ruleIndex:h,error:String(g)}),i.errors++;continue}if(!d)continue}if(a.actionId){let d=await e.invokeAsync(a.actionId,b);if(i.directivesApplied+=d.appliedCount,i.directivesSkipped+=d.skippedCount,i.errors+=d.errors.length,d.aborted)return true}if(a.subRules&&a.subRules.length>0&&await $(a.subRules,t,e,i,o,h,b,s+1,u))return true}return false}function V(){return r=>({$invoker:{ruleId:r.id,priority:r.priority,tags:r.tags??[]}})}function D(r,t,e,i){let o=i?Object.assign({},i):{};for(let h of r)Object.assign(o,h(t,e,o));return o}function L(){return {rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0}}function H(r,t,e,i,o,h,b,s,u,c){return {success:r,aborted:t,abortedBy:e,matched:i,skipped:o,notMatched:h,errors:b,processedCount:s,totalCount:u,counters:c}}function W(r,t){let e=r.filledNames.has("beforeRule"),i=r.filledNames.has("afterRule"),o=r.filledNames.has("onRulesComplete"),h=e||i;return function(s,u,c,a,d){let g=s.length,m=[],n=[],A=[],v=[],p=L(),T=a.length>0,C=true,x=false,_,y=g;c.setContext(u);let k=h?{ctx:u,counters:p}:void 0;for(let f=0;f<g;f++){let R=s[f],E=R.definition.id;if(p.rulesEvaluated++,e)try{let l=d.beforeRule(R.definition,k);if(l==="skip"){n.push(E),p.rulesSkipped++;continue}if(l==="abort"){C=!1,x=!0,_="beforeRule",y=f+1;break}}catch(l){v.push({ruleIndex:f,error:`beforeRule: ${l}`}),p.errors++;}let w;try{w=R.definition.when(u);}catch(l){v.push({ruleIndex:f,error:String(l)}),A.push(E),p.errors++;continue}if(!w){A.push(E);continue}m.push(E),p.rulesMatched++;let S;if(T)try{S=D(a,R.definition,u);}catch(l){v.push({ruleIndex:f,error:`Middleware: ${l}`}),p.errors++;continue}if(R.actionId){let l=c.invoke(R.actionId,S);if(p.directivesApplied+=l.appliedCount,p.directivesSkipped+=l.skippedCount,p.errors+=l.errors.length,i)try{if(d.afterRule(R.definition,l,k)==="abort"){C=!1,x=!0,_="afterRule",y=f+1;break}}catch{}if(l.aborted){C=l.abortedBy==="halt",x=true,_=l.abortedBy,y=f+1;break}}if(R.subRules&&R.subRules.length>0&&M(R.subRules,u,c,p,v,f,S,0,t)){C=false,x=true,_="sub-rule",y=f+1;break}}let I=H(C,x,_,m,n,A,v,y,g,p);if(o)try{d.onRulesComplete(I);}catch{}return I}}function J(r,t){let e=r.filledNames.has("beforeRule"),i=r.filledNames.has("afterRule"),o=r.filledNames.has("onRulesComplete"),h=e||i;return async function(s,u,c,a,d){let g=s.length,m=[],n=[],A=[],v=[],p=L(),T=a.length>0,C=true,x=false,_,y=g;c.setContext(u);let k=h?{ctx:u,counters:p}:void 0;for(let f=0;f<g;f++){let R=s[f],E=R.definition.id;if(p.rulesEvaluated++,e)try{let l=await d.beforeRule(R.definition,k);if(l==="skip"){n.push(E),p.rulesSkipped++;continue}if(l==="abort"){C=!1,x=!0,_="beforeRule",y=f+1;break}}catch(l){v.push({ruleIndex:f,error:`beforeRule: ${l}`}),p.errors++;}let w;try{w=R.definition.when(u);}catch(l){v.push({ruleIndex:f,error:String(l)}),A.push(E),p.errors++;continue}if(!w){A.push(E);continue}m.push(E),p.rulesMatched++;let S;if(T)try{S=D(a,R.definition,u);}catch(l){v.push({ruleIndex:f,error:`Middleware: ${l}`}),p.errors++;continue}if(R.actionId){let l=await c.invokeAsync(R.actionId,S);if(p.directivesApplied+=l.appliedCount,p.directivesSkipped+=l.skippedCount,p.errors+=l.errors.length,i)try{if(await d.afterRule(R.definition,l,k)==="abort"){C=!1,x=!0,_="afterRule",y=f+1;break}}catch{}if(l.aborted){C=l.abortedBy==="halt",x=true,_=l.abortedBy,y=f+1;break}}if(R.subRules&&R.subRules.length>0&&await $(R.subRules,u,c,p,v,f,S,0,t)){C=false,x=true,_="sub-rule",y=f+1;break}}let I=H(C,x,_,m,n,A,v,y,g,p);if(o)try{await d.onRulesComplete(I);}catch{}return I}}function O(r,t,e){return t?J(r,e):W(r,e)}function B(r,t,e,i,o,h,b){r.push(`{const _er={success:${t},aborted:true,abortedBy:${e},matched,skipped,notMatched,errors,processedCount:${i},totalCount:${o},counters};`),h&&r.push(`try{${b}_hookOnComplete(_er);}catch(_e){}`),r.push("return _er;}");}function j(r,t,e,i){let{filledNames:o,asyncNames:h}=r,b=y=>o.has(y),s=y=>h.has(y)?"await ":"",u=b("beforeRule"),c=b("afterRule"),a=b("onRulesComplete"),d=s("beforeRule"),g=s("afterRule"),m=s("onRulesComplete"),n=[];n.push("const len=rules.length;"),n.push("const matched=[];const skipped=[];const notMatched=[];"),n.push("const errors=[];"),n.push("const counters={rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0};"),n.push("ae.setContext(ctx);"),(u||c)&&n.push("const evalCtx={ctx,counters};"),u&&n.push("const _hookBefore=hooks.beforeRule;"),c&&n.push("const _hookAfter=hooks.afterRule;"),a&&n.push("const _hookOnComplete=hooks.onRulesComplete;"),n.push("for(let i=0;i<len;i++){"),n.push("const stored=rules[i];"),n.push("const _rid=stored.definition.id;"),n.push("counters.rulesEvaluated++;"),u&&(n.push("try{"),n.push(`const _bd=${d}_hookBefore(stored.definition,evalCtx);`),n.push('if(_bd==="skip"){skipped.push(_rid);counters.rulesSkipped++;continue;}'),n.push('if(_bd==="abort")'),B(n,"false",'"beforeRule"',"i+1","len",a,m),n.push('}catch(_e){errors.push({ruleIndex:i,error:"beforeRule: "+_e});counters.errors++;}')),n.push("let ev;"),n.push("try{ev=stored.definition.when(ctx);}catch(_e){errors.push({ruleIndex:i,error:String(_e)});notMatched.push(_rid);counters.errors++;continue;}"),n.push("if(!ev){notMatched.push(_rid);continue;}"),n.push("matched.push(_rid);counters.rulesMatched++;"),t&&(n.push("let params;"),n.push('try{params=$.runMw(mw,stored.definition,ctx);}catch(_e){errors.push({ruleIndex:i,error:"Middleware: "+_e});counters.errors++;continue;}'));let A=t?",params":"",v=e?`await ae.invokeAsync(stored.actionId${A})`:`ae.invoke(stored.actionId${A})`;n.push("if(stored.actionId){"),n.push(`const ir=${v};`),n.push("counters.directivesApplied+=ir.appliedCount;counters.directivesSkipped+=ir.skippedCount;counters.errors+=ir.errors.length;"),c&&(n.push("try{"),n.push(`const _ad=${g}_hookAfter(stored.definition,ir,evalCtx);`),n.push('if(_ad==="abort")'),B(n,"false",'"afterRule"',"i+1","len",a,m),n.push("}catch(_e){}")),n.push("if(ir.aborted)"),B(n,'ir.abortedBy==="halt"',"ir.abortedBy","i+1","len",a,m),n.push("}");let p=t?"params":"undefined";n.push("if(stored.subRules&&stored.subRules.length>0){"),n.push(`if(${e?"await ":""}$.evalSub(stored.subRules,ctx,ae,counters,errors,i,${p},0,$.maxDepth))`),B(n,"false",'"sub-rule"',"i+1","len",a,m),n.push("}"),n.push("}"),n.push("const _r={success:true,aborted:false,abortedBy:undefined,matched,skipped,notMatched,errors,processedCount:len,totalCount:len,counters};"),a&&n.push(`try{${m}_hookOnComplete(_r);}catch(_e){}`),n.push("return _r;");let T=n.join(`
|
|
2
|
-
`),
|
|
3
|
-
return(${
|
|
4
|
-
${
|
|
5
|
-
})();`),
|
|
1
|
+
import {analyzeSlots,RULE_SLOT_NAMES}from'@statedelta-actions/core';function B(n,r,t,o,c,d,b,R,a){if(R>=a)return c.push({ruleIndex:d,error:`maxSubRuleDepth (${a}) exceeded`}),o.errors++,false;for(let u=0;u<n.length;u++){let s=n[u];if(s.definition.when){let l;try{l=s.definition.when(r);}catch(v){c.push({ruleIndex:d,error:String(v)}),o.errors++;continue}if(!l)continue}if(s.actionId){let l=t.invoke(s.actionId,b);if(o.directivesApplied+=l.appliedCount,o.directivesSkipped+=l.skippedCount,o.errors+=l.errors.length,l.aborted)return true}if(s.subRules&&s.subRules.length>0&&B(s.subRules,r,t,o,c,d,b,R+1,a))return true}return false}async function F(n,r,t,o,c,d,b,R,a){if(R>=a)return c.push({ruleIndex:d,error:`maxSubRuleDepth (${a}) exceeded`}),o.errors++,false;for(let u=0;u<n.length;u++){let s=n[u];if(s.definition.when){let l;try{l=s.definition.when(r);}catch(v){c.push({ruleIndex:d,error:String(v)}),o.errors++;continue}if(!l)continue}if(s.actionId){let l=await t.invokeAsync(s.actionId,b);if(o.directivesApplied+=l.appliedCount,o.directivesSkipped+=l.skippedCount,o.errors+=l.errors.length,l.aborted)return true}if(s.subRules&&s.subRules.length>0&&await F(s.subRules,r,t,o,c,d,b,R+1,a))return true}return false}function Q(){return n=>({$invoker:{ruleId:n.id,priority:n.priority,tags:n.tags??[]}})}function $(n,r,t,o){let c=o?Object.assign({},o):{};for(let d of n)Object.assign(c,d(r,t,c));return c}function q(){return {rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0}}function U(n,r,t,o,c,d,b,R,a,u){return {success:n,aborted:r,abortedBy:t,matched:o,skipped:c,notMatched:d,errors:b,processedCount:R,totalCount:a,counters:u}}function X(n,r){let t=n.filledNames.has("beforeRule"),o=n.filledNames.has("afterRule"),c=n.filledNames.has("onRulesComplete"),d=t||o;return function(R,a,u,s,l){let v=R.length,_=[],e=[],A=[],y=[],h=q(),S=s.length>0,I=true,C=false,g,m=v;u.setContext(a);let E=d?{ctx:a,counters:h}:void 0;for(let f=0;f<v;f++){let p=R[f],k=p.definition.id;if(h.rulesEvaluated++,t)try{let i=l.beforeRule(p.definition,E);if(i==="skip"){e.push(k),h.rulesSkipped++;continue}if(i==="abort"){I=!1,C=!0,g="beforeRule",m=f+1;break}}catch(i){y.push({ruleIndex:f,error:`beforeRule: ${i}`}),h.errors++;}let T;try{T=p.definition.when(a);}catch(i){y.push({ruleIndex:f,error:String(i)}),A.push(k),h.errors++;continue}if(!T){A.push(k);continue}_.push(k),h.rulesMatched++;let x;if(S)try{x=$(s,p.definition,a);}catch(i){y.push({ruleIndex:f,error:`Middleware: ${i}`}),h.errors++;continue}if(p.actionId){let i=u.invoke(p.actionId,x);if(h.directivesApplied+=i.appliedCount,h.directivesSkipped+=i.skippedCount,h.errors+=i.errors.length,o)try{if(l.afterRule(p.definition,i,E)==="abort"){I=!1,C=!0,g="afterRule",m=f+1;break}}catch{}if(i.aborted){I=i.abortedBy==="halt",C=true,g=i.abortedBy,m=f+1;break}}if(p.subRules&&p.subRules.length>0&&B(p.subRules,a,u,h,y,f,x,0,r)){I=false,C=true,g="sub-rule",m=f+1;break}}let w=U(I,C,g,_,e,A,y,m,v,h);if(c)try{l.onRulesComplete(w);}catch{}return w}}function Y(n,r){let t=n.filledNames.has("beforeRule"),o=n.filledNames.has("afterRule"),c=n.filledNames.has("onRulesComplete"),d=t||o;return async function(R,a,u,s,l){let v=R.length,_=[],e=[],A=[],y=[],h=q(),S=s.length>0,I=true,C=false,g,m=v;u.setContext(a);let E=d?{ctx:a,counters:h}:void 0;for(let f=0;f<v;f++){let p=R[f],k=p.definition.id;if(h.rulesEvaluated++,t)try{let i=await l.beforeRule(p.definition,E);if(i==="skip"){e.push(k),h.rulesSkipped++;continue}if(i==="abort"){I=!1,C=!0,g="beforeRule",m=f+1;break}}catch(i){y.push({ruleIndex:f,error:`beforeRule: ${i}`}),h.errors++;}let T;try{T=p.definition.when(a);}catch(i){y.push({ruleIndex:f,error:String(i)}),A.push(k),h.errors++;continue}if(!T){A.push(k);continue}_.push(k),h.rulesMatched++;let x;if(S)try{x=$(s,p.definition,a);}catch(i){y.push({ruleIndex:f,error:`Middleware: ${i}`}),h.errors++;continue}if(p.actionId){let i=await u.invokeAsync(p.actionId,x);if(h.directivesApplied+=i.appliedCount,h.directivesSkipped+=i.skippedCount,h.errors+=i.errors.length,o)try{if(await l.afterRule(p.definition,i,E)==="abort"){I=!1,C=!0,g="afterRule",m=f+1;break}}catch{}if(i.aborted){I=i.abortedBy==="halt",C=true,g=i.abortedBy,m=f+1;break}}if(p.subRules&&p.subRules.length>0&&await F(p.subRules,a,u,h,y,f,x,0,r)){I=false,C=true,g="sub-rule",m=f+1;break}}let w=U(I,C,g,_,e,A,y,m,v,h);if(c)try{await l.onRulesComplete(w);}catch{}return w}}function O(n,r,t){return r?Y(n,t):X(n,t)}function G(){return {rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0}}function V(n,r,t,o,c,d,b,R,a,u){return {success:n,aborted:r,abortedBy:t,matched:o,skipped:c,notMatched:d,errors:b,processedCount:R,totalCount:a,counters:u}}function Z(n){let r=n.filledNames.has("beforeRule"),t=n.filledNames.has("afterRule"),o=n.filledNames.has("onRulesComplete"),c=r||t;return function*(b,R,a,u,s,l){let v=b.length,_=[],e=[],A=[],y=[],h=G(),S=u.length>0,I=true,C=false,g,m=v;a.setContext(R);let E=c?{ctx:R,counters:h}:void 0;for(let f=0;f<v;f++){let p=b[f],k=p.definition.id;if(h.rulesEvaluated++,r)try{let i=s.beforeRule(p.definition,E);if(i==="skip"){e.push(k),h.rulesSkipped++;continue}if(i==="abort"){I=!1,C=!0,g="beforeRule",m=f+1;break}}catch(i){y.push({ruleIndex:f,error:`beforeRule: ${i}`}),h.errors++;}let T;try{T=p.definition.when(R);}catch(i){y.push({ruleIndex:f,error:String(i)}),A.push(k),h.errors++;continue}if(!T){A.push(k);continue}_.push(k),h.rulesMatched++;let x;if(S)try{x=$(u,p.definition,R);}catch(i){y.push({ruleIndex:f,error:`Middleware: ${i}`}),h.errors++;continue}if(p.actionId){let i;if(p.isInteractive?i=yield*a.invokeInteractive(p.actionId,x):i=a.invoke(p.actionId,x),h.directivesApplied+=i.appliedCount,h.directivesSkipped+=i.skippedCount,h.errors+=i.errors.length,t)try{if(s.afterRule(p.definition,i,E)==="abort"){I=!1,C=!0,g="afterRule",m=f+1;break}}catch{}if(i.aborted){I=i.abortedBy==="halt",C=true,g=i.abortedBy,m=f+1;break}}if(p.subRules&&p.subRules.length>0&&(yield*D(p.subRules,R,a,h,y,f,x,0,l))){I=false,C=true,g="sub-rule",m=f+1;break}}let w=V(I,C,g,_,e,A,y,m,v,h);if(o)try{s.onRulesComplete(w);}catch{}return w}}function ee(n){let r=n.filledNames.has("beforeRule"),t=n.filledNames.has("afterRule"),o=n.filledNames.has("onRulesComplete"),c=r||t;return async function*(b,R,a,u,s,l){let v=b.length,_=[],e=[],A=[],y=[],h=G(),S=u.length>0,I=true,C=false,g,m=v;a.setContext(R);let E=c?{ctx:R,counters:h}:void 0;for(let f=0;f<v;f++){let p=b[f],k=p.definition.id;if(h.rulesEvaluated++,r)try{let i=await s.beforeRule(p.definition,E);if(i==="skip"){e.push(k),h.rulesSkipped++;continue}if(i==="abort"){I=!1,C=!0,g="beforeRule",m=f+1;break}}catch(i){y.push({ruleIndex:f,error:`beforeRule: ${i}`}),h.errors++;}let T;try{T=p.definition.when(R);}catch(i){y.push({ruleIndex:f,error:String(i)}),A.push(k),h.errors++;continue}if(!T){A.push(k);continue}_.push(k),h.rulesMatched++;let x;if(S)try{x=$(u,p.definition,R);}catch(i){y.push({ruleIndex:f,error:`Middleware: ${i}`}),h.errors++;continue}if(p.actionId){let i;if(p.isInteractive?i=yield*a.invokeInteractive(p.actionId,x):p.isAsync?i=await a.invokeAsync(p.actionId,x):i=a.invoke(p.actionId,x),h.directivesApplied+=i.appliedCount,h.directivesSkipped+=i.skippedCount,h.errors+=i.errors.length,t)try{if(await s.afterRule(p.definition,i,E)==="abort"){I=!1,C=!0,g="afterRule",m=f+1;break}}catch{}if(i.aborted){I=i.abortedBy==="halt",C=true,g=i.abortedBy,m=f+1;break}}if(p.subRules&&p.subRules.length>0&&(yield*N(p.subRules,R,a,h,y,f,x,0,l))){I=false,C=true,g="sub-rule",m=f+1;break}}let w=V(I,C,g,_,e,A,y,m,v,h);if(o)try{await s.onRulesComplete(w);}catch{}return w}}function*D(n,r,t,o,c,d,b,R,a){if(R>=a)return c.push({ruleIndex:d,error:`maxSubRuleDepth (${a}) exceeded`}),o.errors++,false;for(let u=0;u<n.length;u++){let s=n[u];if(s.definition.when){let l;try{l=s.definition.when(r);}catch(v){c.push({ruleIndex:d,error:String(v)}),o.errors++;continue}if(!l)continue}if(s.actionId){let l;if(s.isInteractive?l=yield*t.invokeInteractive(s.actionId,b):l=t.invoke(s.actionId,b),o.directivesApplied+=l.appliedCount,o.directivesSkipped+=l.skippedCount,o.errors+=l.errors.length,l.aborted)return true}if(s.subRules&&s.subRules.length>0&&(yield*D(s.subRules,r,t,o,c,d,b,R+1,a)))return true}return false}async function*N(n,r,t,o,c,d,b,R,a){if(R>=a)return c.push({ruleIndex:d,error:`maxSubRuleDepth (${a}) exceeded`}),o.errors++,false;for(let u=0;u<n.length;u++){let s=n[u];if(s.definition.when){let l;try{l=s.definition.when(r);}catch(v){c.push({ruleIndex:d,error:String(v)}),o.errors++;continue}if(!l)continue}if(s.actionId){let l;if(s.isInteractive?l=yield*t.invokeInteractive(s.actionId,b):s.isAsync?l=await t.invokeAsync(s.actionId,b):l=t.invoke(s.actionId,b),o.directivesApplied+=l.appliedCount,o.directivesSkipped+=l.skippedCount,o.errors+=l.errors.length,l.aborted)return true}if(s.subRules&&s.subRules.length>0&&(yield*N(s.subRules,r,t,o,c,d,b,R+1,a)))return true}return false}function W(n,r){return r?ee(n):Z(n)}function M(n,r,t,o,c,d,b){n.push(`{const _er={success:${r},aborted:true,abortedBy:${t},matched,skipped,notMatched,errors,processedCount:${o},totalCount:${c},counters};`),d&&n.push(`try{${b}_hookOnComplete(_er);}catch(_e){}`),n.push("return _er;}");}function J(n,r,t,o){let{filledNames:c,asyncNames:d}=n,b=m=>c.has(m),R=m=>d.has(m)?"await ":"",a=b("beforeRule"),u=b("afterRule"),s=b("onRulesComplete"),l=R("beforeRule"),v=R("afterRule"),_=R("onRulesComplete"),e=[];e.push("const len=rules.length;"),e.push("const matched=[];const skipped=[];const notMatched=[];"),e.push("const errors=[];"),e.push("const counters={rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0};"),e.push("ae.setContext(ctx);"),(a||u)&&e.push("const evalCtx={ctx,counters};"),a&&e.push("const _hookBefore=hooks.beforeRule;"),u&&e.push("const _hookAfter=hooks.afterRule;"),s&&e.push("const _hookOnComplete=hooks.onRulesComplete;"),e.push("for(let i=0;i<len;i++){"),e.push("const stored=rules[i];"),e.push("const _rid=stored.definition.id;"),e.push("counters.rulesEvaluated++;"),a&&(e.push("try{"),e.push(`const _bd=${l}_hookBefore(stored.definition,evalCtx);`),e.push('if(_bd==="skip"){skipped.push(_rid);counters.rulesSkipped++;continue;}'),e.push('if(_bd==="abort")'),M(e,"false",'"beforeRule"',"i+1","len",s,_),e.push('}catch(_e){errors.push({ruleIndex:i,error:"beforeRule: "+_e});counters.errors++;}')),e.push("let ev;"),e.push("try{ev=stored.definition.when(ctx);}catch(_e){errors.push({ruleIndex:i,error:String(_e)});notMatched.push(_rid);counters.errors++;continue;}"),e.push("if(!ev){notMatched.push(_rid);continue;}"),e.push("matched.push(_rid);counters.rulesMatched++;"),r&&(e.push("let params;"),e.push('try{params=$.runMw(mw,stored.definition,ctx);}catch(_e){errors.push({ruleIndex:i,error:"Middleware: "+_e});counters.errors++;continue;}'));let A=r?",params":"",y=t?`await ae.invokeAsync(stored.actionId${A})`:`ae.invoke(stored.actionId${A})`;e.push("if(stored.actionId){"),e.push(`const ir=${y};`),e.push("counters.directivesApplied+=ir.appliedCount;counters.directivesSkipped+=ir.skippedCount;counters.errors+=ir.errors.length;"),u&&(e.push("try{"),e.push(`const _ad=${v}_hookAfter(stored.definition,ir,evalCtx);`),e.push('if(_ad==="abort")'),M(e,"false",'"afterRule"',"i+1","len",s,_),e.push("}catch(_e){}")),e.push("if(ir.aborted)"),M(e,'ir.abortedBy==="halt"',"ir.abortedBy","i+1","len",s,_),e.push("}");let h=r?"params":"undefined";e.push("if(stored.subRules&&stored.subRules.length>0){"),e.push(`if(${t?"await ":""}$.evalSub(stored.subRules,ctx,ae,counters,errors,i,${h},0,$.maxDepth))`),M(e,"false",'"sub-rule"',"i+1","len",s,_),e.push("}"),e.push("}"),e.push("const _r={success:true,aborted:false,abortedBy:undefined,matched,skipped,notMatched,errors,processedCount:len,totalCount:len,counters};"),s&&e.push(`try{${_}_hookOnComplete(_r);}catch(_e){}`),e.push("return _r;");let S=e.join(`
|
|
2
|
+
`),I=t?"async ":"",C=new Function("rules","ctx","ae","mw","hooks","$",`"use strict";
|
|
3
|
+
return(${I}()=>{
|
|
4
|
+
${S}
|
|
5
|
+
})();`),g={maxDepth:o};return g.evalSub=t?F:B,r&&(g.runMw=$),function(E,w,f,p,k){return C(E,w,f,p,k,g)}}function P(n,r,t,o){let{filledNames:c,asyncNames:d}=n,b=g=>c.has(g),R=g=>d.has(g)?"await ":"",a=b("beforeRule"),u=b("afterRule"),s=b("onRulesComplete"),l=R("beforeRule"),v=R("afterRule"),_=R("onRulesComplete"),e=[];e.push("const len=rules.length;"),e.push("const matched=[];const skipped=[];const notMatched=[];"),e.push("const errors=[];"),e.push("const counters={rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0};"),e.push("ae.setContext(ctx);"),(a||u)&&e.push("const evalCtx={ctx,counters};"),a&&e.push("const _hookBefore=hooks.beforeRule;"),u&&e.push("const _hookAfter=hooks.afterRule;"),s&&e.push("const _hookOnComplete=hooks.onRulesComplete;"),e.push("for(let i=0;i<len;i++){"),e.push("const stored=rules[i];"),e.push("const _rid=stored.definition.id;"),e.push("counters.rulesEvaluated++;"),a&&(e.push("try{"),e.push(`const _bd=${l}_hookBefore(stored.definition,evalCtx);`),e.push('if(_bd==="skip"){skipped.push(_rid);counters.rulesSkipped++;continue;}'),e.push('if(_bd==="abort")'),M(e,"false",'"beforeRule"',"i+1","len",s,_),e.push('}catch(_e){errors.push({ruleIndex:i,error:"beforeRule: "+_e});counters.errors++;}')),e.push("let ev;"),e.push("try{ev=stored.definition.when(ctx);}catch(_e){errors.push({ruleIndex:i,error:String(_e)});notMatched.push(_rid);counters.errors++;continue;}"),e.push("if(!ev){notMatched.push(_rid);continue;}"),e.push("matched.push(_rid);counters.rulesMatched++;"),r&&(e.push("let params;"),e.push('try{params=$.runMw(mw,stored.definition,ctx);}catch(_e){errors.push({ruleIndex:i,error:"Middleware: "+_e});counters.errors++;continue;}'));let A=r?",params":"";e.push("if(stored.actionId){"),e.push("let ir;"),e.push("if(stored.isInteractive){"),e.push(`ir=yield* ae.invokeInteractive(stored.actionId${A});`),e.push("}else "),t?(e.push("if(stored.isAsync){"),e.push(`ir=await ae.invokeAsync(stored.actionId${A});`),e.push("}else{")):e.push("{"),e.push(`ir=ae.invoke(stored.actionId${A});`),e.push("}"),e.push("counters.directivesApplied+=ir.appliedCount;counters.directivesSkipped+=ir.skippedCount;counters.errors+=ir.errors.length;"),u&&(e.push("try{"),e.push(`const _ad=${v}_hookAfter(stored.definition,ir,evalCtx);`),e.push('if(_ad==="abort")'),M(e,"false",'"afterRule"',"i+1","len",s,_),e.push("}catch(_e){}")),e.push("if(ir.aborted)"),M(e,'ir.abortedBy==="halt"',"ir.abortedBy","i+1","len",s,_),e.push("}");let y=r?"params":"undefined";e.push("if(stored.subRules&&stored.subRules.length>0){"),e.push(`if(yield* $.evalSubInt(stored.subRules,ctx,ae,counters,errors,i,${y},0,$.maxDepth))`),M(e,"false",'"sub-rule"',"i+1","len",s,_),e.push("}"),e.push("}"),e.push("const _r={success:true,aborted:false,abortedBy:undefined,matched,skipped,notMatched,errors,processedCount:len,totalCount:len,counters};"),s&&e.push(`try{${_}_hookOnComplete(_r);}catch(_e){}`),e.push("return _r;");let h=e.join(`
|
|
6
|
+
`),S=t?"async function*()":"function*()",I=new Function("rules","ctx","ae","mw","hooks","$",`"use strict";
|
|
7
|
+
return(${S}{
|
|
8
|
+
${h}
|
|
9
|
+
})();`),C={maxDepth:o};return C.evalSubInt=t?N:D,r&&(C.runMw=$),function(m,E,w,f,p){return I(m,E,w,f,p,C)}}function z(n){if(!n.id||typeof n.id!="string")return {ruleId:n.id??"(missing)",code:"INVALID_RULE",message:"rule must have a string id"};if(typeof n.priority!="number")return {ruleId:n.id,code:"INVALID_RULE",message:"rule must have a numeric priority"};if(typeof n.when!="function")return {ruleId:n.id,code:"INVALID_RULE",message:"rule must have a when function"};let r=Array.isArray(n.then)&&n.then.length>0,t=Array.isArray(n.rules)&&n.rules.length>0;return !r&&!t?{ruleId:n.id,code:"INVALID_RULE",message:"rule must have then or sub-rules (or both)"}:null}function K(n,r){let t=`${r}.${n.id??"(missing)"}`;if(!n.id||typeof n.id!="string")return {ruleId:t,code:"INVALID_RULE",message:"sub-rule must have a string id"};let o=Array.isArray(n.then)&&n.then.length>0,c=Array.isArray(n.rules)&&n.rules.length>0;return !o&&!c?{ruleId:t,code:"INVALID_RULE",message:"sub-rule must have then or sub-rules (or both)"}:null}var L=()=>{},j=class{_actionEngine;_middleware;_ruleHooks;_maxSubRuleDepth;_requestedMode;_ruleHookAnalysis;_hasAnyInteractiveRule=false;_isAsync;_ruleEvaluator;_mode;_maybeAutoPromote;_interactiveEvaluator=null;_interactiveEvaluatorIsAsync=false;_ruleRegistry=new Map;_rules=[];_batch=null;constructor(r){if(this._actionEngine=r.actionEngine,this._middleware=r.middleware??[],this._ruleHooks=r.ruleHooks??{},this._maxSubRuleDepth=r.maxSubRuleDepth??10,this._requestedMode=r.mode??"auto",this._ruleHookAnalysis=analyzeSlots(this._ruleHooks,RULE_SLOT_NAMES),this._isAsync=this._ruleHookAnalysis.hasAnyAsync,this._requestedMode==="jit")this._ruleEvaluator=this._buildJitRule(),this._mode="jit",this._maybeAutoPromote=L;else if(this._ruleEvaluator=O(this._ruleHookAnalysis,this._isAsync,this._maxSubRuleDepth),this._mode="interpret",this._requestedMode==="auto"){let t=0,o=r.autoJitThreshold??8;this._maybeAutoPromote=()=>{++t>=o&&this._promote();};}else this._maybeAutoPromote=L;}get actionEngine(){return this._actionEngine}get isAsync(){return this._isAsync}get isInteractive(){return this._hasAnyInteractiveRule}get compilationMode(){return this._mode}get size(){return this._rules.length}has(r){return this._ruleRegistry.has(r)}register(r){let t=[],o=[],c=[],d=[];for(let u of r){let s=z(u);if(s){t.push(s);continue}if(this._ruleRegistry.has(u.id)||c.some(y=>y.id===u.id)){t.push({ruleId:u.id,code:"DUPLICATE_ID",message:`rule "${u.id}" is already registered`});continue}let l=`rule:${u.id}`,v=Array.isArray(u.then)&&u.then.length>0,_=v?l:"",e=Array.isArray(u.rules)&&u.rules.length>0?this._collectSubRules(l,u.rules,t,o,d):void 0,A={definition:u,actionId:_,priority:u.priority,subRules:e?.length?e:void 0,isAsync:false,isInteractive:false};if(v){let y=["rule"];u.tags&&y.push(...u.tags),o.push({id:_,tags:y,directives:u.then,declarations:u.declarations});}c.push({id:u.id,stored:A});}let b=[];if(o.length>0){let u=this._actionEngine.register(o);for(let s of u.errors){let l=this._actionIdToRuleId(s.actionId);t.push({ruleId:l??s.actionId,code:s.code??"ACTION_ERROR",message:s.error});}b=u.warnings;}let R=[];for(let{id:u,stored:s}of c)this._ruleRegistry.set(u,s),se(this._rules,s),R.push(u);for(let{qualifiedId:u,stored:s}of d)this._ruleRegistry.set(u,s);let a={registered:R,errors:t,warnings:b};return this._batch?(this._batch.registered.push(...R),this._batch.errors.push(...t),this._batch.warnings.push(...b)):R.length>0&&this._refreshRuleFlags(),a}unregister(r){let t=this._ruleRegistry.get(r);return t?(this._ruleRegistry.delete(r),ie(this._rules,t),t.actionId&&this._actionEngine.unregister(t.actionId),t.subRules&&this._unregisterSubRules(t.subRules),this._refreshRuleFlags(),true):false}beginBatch(){this._batch||(this._batch={depth:0,registered:[],errors:[],warnings:[]}),this._batch.depth++,this._actionEngine.beginBatch();}endBatch(){if(!this._batch||this._batch.depth<=0)throw new Error("endBatch() called without matching beginBatch()");this._batch.depth--;let r=this._actionEngine.endBatch();if(this._batch.depth>0)return {registered:[],errors:[],warnings:[]};let t=this._batch;for(let c of r.errors){let d=this._actionIdToRuleId(c.actionId);t.errors.push({ruleId:d??c.actionId,code:c.code??"ACTION_ERROR",message:c.error});}t.warnings.push(...r.warnings);let o={registered:t.registered,errors:t.errors,warnings:t.warnings};return this._batch=null,this._refreshRuleFlags(),o}batch(r){this.beginBatch();try{return r(this),this.endBatch()}catch(t){try{this.endBatch();}catch{}throw t}}evaluate(r){if(this._hasAnyInteractiveRule)throw new Error("Cannot call evaluate() \u2014 at least one rule is interactive (transitively). Use evaluateInteractive() instead.");if(this._isAsync)throw new Error("Cannot call evaluate() with async hooks or async rules. Use evaluateAsync() instead.");let t=this._ruleEvaluator(this._rules,r,this._actionEngine,this._middleware,this._ruleHooks);return this._maybeAutoPromote(),t}async evaluateAsync(r){if(this._hasAnyInteractiveRule)throw new Error("Cannot call evaluateAsync() \u2014 at least one rule is interactive (transitively). Use evaluateInteractive() instead.");let t=await this._ruleEvaluator(this._rules,r,this._actionEngine,this._middleware,this._ruleHooks);return this._maybeAutoPromote(),t}evaluateInteractive(r){if(!this._hasAnyInteractiveRule)throw new Error("Cannot call evaluateInteractive() \u2014 no registered rule is interactive (transitively). Use evaluate() or evaluateAsync() instead.");return (this._interactiveEvaluator===null||this._interactiveEvaluatorIsAsync!==this._isAsync)&&(this._interactiveEvaluator=this._mode==="jit"?P(this._ruleHookAnalysis,this._middleware.length>0,this._isAsync,this._maxSubRuleDepth):W(this._ruleHookAnalysis,this._isAsync),this._interactiveEvaluatorIsAsync=this._isAsync),this._interactiveEvaluator(this._rules,r,this._actionEngine,this._middleware,this._ruleHooks,this._maxSubRuleDepth)}compile(){this._requestedMode!=="interpret"&&this._mode!=="jit"&&this._promote();}_collectSubRules(r,t,o,c,d){let b=[],R=this._actionIdToRuleId(r);for(let a of t){let u=K(a,R);if(u){o.push(u);continue}let s=`${r}.${a.id}`,l=`${R}.${a.id}`,v=Array.isArray(a.then)&&a.then.length>0,_=Array.isArray(a.rules)&&a.rules.length>0?this._collectSubRules(s,a.rules,o,c,d):void 0,e={definition:a,actionId:v?s:"",subRules:_?.length?_:void 0,isAsync:false,isInteractive:false};if(v){let A=["rule"];a.tags&&A.push(...a.tags),c.push({id:s,tags:A,directives:a.then,declarations:a.declarations});}d.push({qualifiedId:l,stored:e}),b.push(e);}return b}_unregisterSubRules(r){for(let t of r){if(t.actionId){let o=this._actionIdToRuleId(t.actionId);o&&this._ruleRegistry.delete(o),this._actionEngine.unregister(t.actionId);}t.subRules&&this._unregisterSubRules(t.subRules);}}_actionIdToRuleId(r){return r.startsWith("rule:")?r.slice(5):null}_refreshRuleFlags(){let r=false,t=false,o=d=>{if(d.actionId?(d.isAsync=this._actionEngine.isActionAsync(d.actionId)??false,d.isInteractive=this._actionEngine.isActionInteractive(d.actionId)??false,d.isAsync&&(r=true),d.isInteractive&&(t=true)):(d.isAsync=false,d.isInteractive=false),d.subRules)for(let b of d.subRules)o(b);};for(let d of this._rules)o(d);this._hasAnyInteractiveRule=t;let c=this._ruleHookAnalysis.hasAnyAsync||r;c!==this._isAsync?(this._isAsync=c,this._rebuildEvaluator()):this._isAsync=c;}_rebuildEvaluator(){this._mode==="jit"?this._ruleEvaluator=this._buildJitRule():this._ruleEvaluator=O(this._ruleHookAnalysis,this._isAsync,this._maxSubRuleDepth);}_promote(){this._ruleEvaluator=this._buildJitRule(),this._mode="jit",this._maybeAutoPromote=L;}_buildJitRule(){return J(this._ruleHookAnalysis,this._middleware.length>0,this._isAsync,this._maxSubRuleDepth)}};function ne(n){return new j(n)}function se(n,r){let t=0,o=n.length;for(;t<o;){let c=t+o>>>1;n[c].priority>=r.priority?t=c+1:o=c;}n.splice(t,0,r);}function ie(n,r){let t=n.indexOf(r);return t===-1?false:(n.splice(t,1),true)}var oe={analyze:()=>({capabilities:["halt"],dependencies:[]}),execute:()=>({ok:true,halt:true})};export{oe as HALT_HANDLER,Q as createInvokerMiddleware,ne as createRuleEngine};
|
package/package.json
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statedelta-actions/rules",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Rule evaluation engine with JIT-optimized sequential evaluation and sub-rules",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"statedelta",
|
|
7
|
+
"rule-engine",
|
|
8
|
+
"jit",
|
|
9
|
+
"conditional-evaluation",
|
|
10
|
+
"sub-rules"
|
|
11
|
+
],
|
|
5
12
|
"type": "module",
|
|
6
13
|
"main": "./dist/index.cjs",
|
|
7
14
|
"module": "./dist/index.js",
|
|
@@ -15,11 +22,12 @@
|
|
|
15
22
|
},
|
|
16
23
|
"files": [
|
|
17
24
|
"dist",
|
|
18
|
-
"README.md"
|
|
25
|
+
"README.md",
|
|
26
|
+
"CHANGELOG.md"
|
|
19
27
|
],
|
|
20
28
|
"dependencies": {
|
|
21
|
-
"@statedelta-actions/
|
|
22
|
-
"@statedelta-actions/
|
|
29
|
+
"@statedelta-actions/actions": "0.6.0",
|
|
30
|
+
"@statedelta-actions/core": "0.5.1"
|
|
23
31
|
},
|
|
24
32
|
"devDependencies": {
|
|
25
33
|
"apex-store": "0.4.0"
|
|
@@ -31,6 +39,10 @@
|
|
|
31
39
|
"url": "https://github.com/andersondrosa/statedelta-actions.git",
|
|
32
40
|
"directory": "packages/rules"
|
|
33
41
|
},
|
|
42
|
+
"homepage": "https://github.com/andersondrosa/statedelta-actions/tree/main/packages/rules#readme",
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/andersondrosa/statedelta-actions/issues"
|
|
45
|
+
},
|
|
34
46
|
"sideEffects": false,
|
|
35
47
|
"engines": {
|
|
36
48
|
"node": ">=18"
|