@statedelta-actions/events 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 ADDED
@@ -0,0 +1,89 @@
1
+ # @statedelta-actions/events
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
@@ -1,7 +1,6 @@
1
- # EventProcessor — Eventos como Actions Deferidas
1
+ # @statedelta-actions/events
2
2
 
3
- > **Módulo:** `events/`
4
- > **Escopo:** Dispatcher de listeners sobre o ActionEngine. Listeners reagem a eventos nomeados, executando diretivas via hidden actions.
3
+ > **EventProcessor** — eventos como actions deferidas. Dispatcher de listeners sobre o ActionEngine: listeners reagem a eventos nomeados, executando diretivas via hidden actions.
5
4
  > **Dependências:** `core/` (tipos, slot analysis), `actions/` (IActionEngine). Zero dependência de `rules/`.
6
5
  >
7
6
  > Para arquitetura interna, pipelines e fluxos, ver [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md).
@@ -90,22 +89,45 @@ const result = ep.register([
90
89
  ep.unregister("on-save"); // true se existia, false se não
91
90
  ```
92
91
 
92
+ #### Throw vs collected errors
93
+
94
+ `register` e `defineEvents` são atômicos: o registro local só é aplicado depois que o ActionEngine aceita todas as hidden actions. Comportamento por tipo de erro:
95
+
96
+ | Erro | Comportamento |
97
+ |------|---------------|
98
+ | Handler ausente para um tipo de diretiva em `then` (qualquer profundidade, inclusive `catch`) | **Lança `Error`** propagado do `actionEngine.register`. Estado local intocado. |
99
+ | Listener/event duplicado, missing required field, tier violation contra `EventDefinition` | Coletado em `errors[]`. Outros itens válidos no mesmo call ainda registram. |
100
+ | `validate()` de handler retorna invalid ou lança | Coletado em `errors[]`. |
101
+
102
+ Throw é reservado pra erros estruturais que não viram válidos em runtime — typo, handler esquecido, refactor incompleto. Soft errors são domain-level e merecem inspeção pelo consumer.
103
+
93
104
  ### Processing
94
105
 
95
106
  ```typescript
96
- // Sync (throws se isAsync = true)
107
+ // Sync (throws se algum listener é async ou interactive transitivamente)
97
108
  const result = ep.processEvents(
98
109
  [{ event: "save" }, { event: "damage", data: { amount: 10 } }],
99
110
  ctx,
100
111
  );
101
112
 
102
- // Async (sempre funciona)
113
+ // Async (throws se algum listener é interactive transitivamente)
103
114
  const result = await ep.processEventsAsync(
104
115
  [{ event: "save" }],
105
116
  ctx,
106
117
  );
118
+
119
+ // Interactive — retorna iterator drenável (sync ou async generator)
120
+ const session = ep.processEventsInteractive([{ event: "save" }], ctx);
121
+ let step = session.next();
122
+ while (!step.done) {
123
+ // step.value = payload do yield (PauseEvent ou payload de handler interactive)
124
+ step = session.next(/* resposta do consumer */);
125
+ }
126
+ // step.value = EventProcessingResult
107
127
  ```
108
128
 
129
+ `processEventsInteractive` lança se nenhum listener registrado é interactive transitivamente. Pausas fluem via `yield*` em 3 níveis (consumer → events generator → `actionEngine.invokeInteractive`). Halt scoping preservado: pause/halt num listener para os listeners daquele evento; próximos eventos na fila continuam.
130
+
109
131
  ### Batch
110
132
 
111
133
  ```typescript
@@ -124,9 +146,12 @@ ep.compile();
124
146
 
125
147
  // Consultar modo atual
126
148
  ep.compilationMode; // "interpret" | "jit"
127
- ep.isAsync; // true se hooks ou actionEngine são async
149
+ ep.isAsync; // true se hooks são async OU se algum listener é async transitivamente
150
+ ep.isInteractive; // true se algum listener é interactive transitivamente
128
151
  ```
129
152
 
153
+ `isAsync` e `isInteractive` são per-listener transitivos. Engine híbrido (handler async + listener cuja sub-árvore é 100% sync) mantém `processEvents` (sync) viável — só listeners que invocam handler async transitivamente forçam `processEventsAsync`, só listeners interactive transitivamente forçam `processEventsInteractive`. Detecção via mini-graph do ActionEngine, refrescada em register/unregister/endBatch. O dispatcher interactive é lazy — só construído na primeira chamada de `processEventsInteractive` (custo zero pra engines sem nada interactive).
154
+
130
155
  ---
131
156
 
132
157
  ## Hooks — EventHooks
package/dist/index.cjs CHANGED
@@ -1,5 +1,9 @@
1
- 'use strict';var core=require('@statedelta-actions/core');function L(){return {rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0}}function O(e,s){e.rulesEvaluated+=s.rulesEvaluated,e.rulesMatched+=s.rulesMatched,e.rulesSkipped+=s.rulesSkipped,e.directivesApplied+=s.directivesApplied,e.directivesSkipped+=s.directivesSkipped,e.subRunsCreated+=s.subRunsCreated,e.errors+=s.errors;}function M(e,s,r,i){let o=i?Object.assign({},i):{};for(let d of e)Object.assign(o,d(s,r,o));return o}function q(e){let s=e.filledNames.has("beforeEvent"),r=e.filledNames.has("afterEvent"),i=e.filledNames.has("onEventsComplete");return function(d,g,n,a,u,m){let _=[],b=[],t=[],l=L(),h=u.length>0;a.setContext(n);for(let p of g){let y=d.get(p.event);if(!y||y.length===0){b.push(p.event);continue}let x=[],R=[],S=[],C=[],c=L(),k=false,T,D={ctx:n,counters:c,event:p.event},N={$event:{type:p.event,data:p.data}};for(let v=0;v<y.length;v++){let I=y[v];if(c.rulesEvaluated++,s)try{let f=m.beforeEvent(I.definition,D);if(f==="skip"){R.push(v),c.rulesSkipped++;continue}if(f==="abort")break}catch(f){C.push({ruleIndex:v,error:`beforeEvent: ${f}`}),c.errors++;}x.push(v),c.rulesMatched++;let w;if(h)try{w=M(u,I.definition,n,N);}catch(f){C.push({ruleIndex:v,error:`Middleware: ${f}`}),c.errors++;continue}else w=N;let E=a.invoke(I.actionId,w);if(c.directivesApplied+=E.appliedCount,c.directivesSkipped+=E.skippedCount,c.errors+=E.errors.length,r)try{if(m.afterEvent(I.definition,E,D)==="abort")break}catch{}if(E.aborted){k=true,T=E.abortedBy;break}}t.push(...C),O(l,c),_.push({event:p.event,matched:x,skipped:R,notMatched:S,errors:C,halted:k,haltedBy:T,counters:c});}let A={eventResults:_,unprocessedEvents:b,errors:t,counters:l,totalEvents:g.length,processedEvents:_.length};if(i)try{m.onEventsComplete(A);}catch{}return A}}function Q(e){let s=e.filledNames.has("beforeEvent"),r=e.filledNames.has("afterEvent"),i=e.filledNames.has("onEventsComplete");return async function(d,g,n,a,u,m){let _=[],b=[],t=[],l=L(),h=u.length>0;a.setContext(n);for(let p of g){let y=d.get(p.event);if(!y||y.length===0){b.push(p.event);continue}let x=[],R=[],S=[],C=[],c=L(),k=false,T,D={ctx:n,counters:c,event:p.event},N={$event:{type:p.event,data:p.data}};for(let v=0;v<y.length;v++){let I=y[v];if(c.rulesEvaluated++,s)try{let f=await m.beforeEvent(I.definition,D);if(f==="skip"){R.push(v),c.rulesSkipped++;continue}if(f==="abort")break}catch(f){C.push({ruleIndex:v,error:`beforeEvent: ${f}`}),c.errors++;}x.push(v),c.rulesMatched++;let w;if(h)try{w=M(u,I.definition,n,N);}catch(f){C.push({ruleIndex:v,error:`Middleware: ${f}`}),c.errors++;continue}else w=N;let E=await a.invokeAsync(I.actionId,w);if(c.directivesApplied+=E.appliedCount,c.directivesSkipped+=E.skippedCount,c.errors+=E.errors.length,r)try{if(await m.afterEvent(I.definition,E,D)==="abort")break}catch{}if(E.aborted){k=true,T=E.abortedBy;break}}t.push(...C),O(l,c),_.push({event:p.event,matched:x,skipped:R,notMatched:S,errors:C,halted:k,haltedBy:T,counters:c});}let A={eventResults:_,unprocessedEvents:b,errors:t,counters:l,totalEvents:g.length,processedEvents:_.length};if(i)try{await m.onEventsComplete(A);}catch{}return A}}function B(e,s){return s?Q(e):q(e)}function F(e,s,r){let{filledNames:i,asyncNames:o}=e,d=R=>i.has(R),g=R=>o.has(R)?"await ":"",n=d("beforeEvent"),a=d("afterEvent"),u=d("onEventsComplete"),m=g("beforeEvent"),_=g("afterEvent"),b=g("onEventsComplete"),t=[];t.push("const eventResults=[];"),t.push("const unprocessedEvents=[];"),t.push("const aggErrors=[];"),t.push("const aggCounters={rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0};"),t.push("ae.setContext(ctx);"),u&&t.push("const _hookOnComplete=hooks.onEventsComplete;"),t.push("for(let _ei=0;_ei<events.length;_ei++){"),t.push("const ev=events[_ei];"),t.push("const _evListeners=listenerIndex.get(ev.event);"),t.push("if(!_evListeners||_evListeners.length===0){unprocessedEvents.push(ev.event);continue;}"),t.push("const matched=[];const skipped=[];const notMatched=[];"),t.push("const errors=[];"),t.push("const counters={rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0};"),t.push("let halted=false;let haltedBy;"),(n||a)&&t.push("const evalCtx={ctx,counters,event:ev.event};"),n&&t.push("const _hookBefore=hooks.beforeEvent;"),a&&t.push("const _hookAfter=hooks.afterEvent;"),t.push("const _ep={$event:{type:ev.event,data:ev.data}};"),t.push("for(let _ri=0;_ri<_evListeners.length;_ri++){"),t.push("const stored=_evListeners[_ri];"),t.push("counters.rulesEvaluated++;"),n&&(t.push("try{"),t.push(`const _bd=${m}_hookBefore(stored.definition,evalCtx);`),t.push('if(_bd==="skip"){skipped.push(_ri);counters.rulesSkipped++;continue;}'),t.push('if(_bd==="abort"){break;}'),t.push('}catch(_e){errors.push({ruleIndex:_ri,error:"beforeEvent: "+_e});counters.errors++;}')),t.push("matched.push(_ri);counters.rulesMatched++;"),s&&(t.push("let params;"),t.push('try{params=$.runMw(mw,stored.definition,ctx,_ep);}catch(_e){errors.push({ruleIndex:_ri,error:"Middleware: "+_e});counters.errors++;continue;}'));let l=s?"params":"_ep",h=r?`await ae.invokeAsync(stored.actionId,${l})`:`ae.invoke(stored.actionId,${l})`;t.push(`const ir=${h};`),t.push("counters.directivesApplied+=ir.appliedCount;counters.directivesSkipped+=ir.skippedCount;counters.errors+=ir.errors.length;"),a&&(t.push("try{"),t.push(`const _ad=${_}_hookAfter(stored.definition,ir,evalCtx);`),t.push('if(_ad==="abort"){break;}'),t.push("}catch(_e){}")),t.push("if(ir.aborted){halted=true;haltedBy=ir.abortedBy;break;}"),t.push("}"),t.push("aggCounters.rulesEvaluated+=counters.rulesEvaluated;"),t.push("aggCounters.rulesMatched+=counters.rulesMatched;"),t.push("aggCounters.rulesSkipped+=counters.rulesSkipped;"),t.push("aggCounters.directivesApplied+=counters.directivesApplied;"),t.push("aggCounters.directivesSkipped+=counters.directivesSkipped;"),t.push("aggCounters.subRunsCreated+=counters.subRunsCreated;"),t.push("aggCounters.errors+=counters.errors;"),t.push("for(let _k=0;_k<errors.length;_k++)aggErrors.push(errors[_k]);"),t.push("eventResults.push({event:ev.event,matched,skipped,notMatched,errors,halted,haltedBy,counters});"),t.push("}"),t.push("const _r={eventResults,unprocessedEvents,errors:aggErrors,counters:aggCounters,totalEvents:events.length,processedEvents:eventResults.length};"),u&&t.push(`try{${b}_hookOnComplete(_r);}catch(_e){}`),t.push("return _r;");let A=t.join(`
2
- `),p=r?"async ":"",y=new Function("listenerIndex","events","ctx","ae","mw","hooks","$",`"use strict";
1
+ 'use strict';var core=require('@statedelta-actions/core');function N(){return {rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0}}function O(t,n){t.rulesEvaluated+=n.rulesEvaluated,t.rulesMatched+=n.rulesMatched,t.rulesSkipped+=n.rulesSkipped,t.directivesApplied+=n.directivesApplied,t.directivesSkipped+=n.directivesSkipped,t.subRunsCreated+=n.subRunsCreated,t.errors+=n.errors;}function M(t,n,r,o){let a=o?Object.assign({},o):{};for(let d of t)Object.assign(a,d(n,r,a));return a}function J(t){let n=t.filledNames.has("beforeEvent"),r=t.filledNames.has("afterEvent"),o=t.filledNames.has("onEventsComplete");return function(d,f,g,s,c,l){let E=[],y=[],e=[],k=N(),R=c.length>0;s.setContext(g);for(let p of f){let _=d.get(p.event);if(!_||_.length===0){y.push(p.event);continue}let b=[],A=[],S=[],C=[],i=N(),w=false,T,D={ctx:g,counters:i,event:p.event},L={$event:{type:p.event,data:p.data}};for(let h=0;h<_.length;h++){let m=_[h];if(i.rulesEvaluated++,n)try{let v=l.beforeEvent(m.definition,D);if(v==="skip"){A.push(h),i.rulesSkipped++;continue}if(v==="abort")break}catch(v){C.push({ruleIndex:h,error:`beforeEvent: ${v}`}),i.errors++;}b.push(h),i.rulesMatched++;let x;if(R)try{x=M(c,m.definition,g,L);}catch(v){C.push({ruleIndex:h,error:`Middleware: ${v}`}),i.errors++;continue}else x=L;let u=s.invoke(m.actionId,x);if(i.directivesApplied+=u.appliedCount,i.directivesSkipped+=u.skippedCount,i.errors+=u.errors.length,r)try{if(l.afterEvent(m.definition,u,D)==="abort")break}catch{}if(u.aborted){w=true,T=u.abortedBy;break}}e.push(...C),O(k,i),E.push({event:p.event,matched:b,skipped:A,notMatched:S,errors:C,halted:w,haltedBy:T,counters:i});}let I={eventResults:E,unprocessedEvents:y,errors:e,counters:k,totalEvents:f.length,processedEvents:E.length};if(o)try{l.onEventsComplete(I);}catch{}return I}}function z(t){let n=t.filledNames.has("beforeEvent"),r=t.filledNames.has("afterEvent"),o=t.filledNames.has("onEventsComplete");return async function(d,f,g,s,c,l){let E=[],y=[],e=[],k=N(),R=c.length>0;s.setContext(g);for(let p of f){let _=d.get(p.event);if(!_||_.length===0){y.push(p.event);continue}let b=[],A=[],S=[],C=[],i=N(),w=false,T,D={ctx:g,counters:i,event:p.event},L={$event:{type:p.event,data:p.data}};for(let h=0;h<_.length;h++){let m=_[h];if(i.rulesEvaluated++,n)try{let v=await l.beforeEvent(m.definition,D);if(v==="skip"){A.push(h),i.rulesSkipped++;continue}if(v==="abort")break}catch(v){C.push({ruleIndex:h,error:`beforeEvent: ${v}`}),i.errors++;}b.push(h),i.rulesMatched++;let x;if(R)try{x=M(c,m.definition,g,L);}catch(v){C.push({ruleIndex:h,error:`Middleware: ${v}`}),i.errors++;continue}else x=L;let u=await s.invokeAsync(m.actionId,x);if(i.directivesApplied+=u.appliedCount,i.directivesSkipped+=u.skippedCount,i.errors+=u.errors.length,r)try{if(await l.afterEvent(m.definition,u,D)==="abort")break}catch{}if(u.aborted){w=true,T=u.abortedBy;break}}e.push(...C),O(k,i),E.push({event:p.event,matched:b,skipped:A,notMatched:S,errors:C,halted:w,haltedBy:T,counters:i});}let I={eventResults:E,unprocessedEvents:y,errors:e,counters:k,totalEvents:f.length,processedEvents:E.length};if(o)try{await l.onEventsComplete(I);}catch{}return I}}function $(t,n){return n?z(t):J(t)}function P(){return {rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0}}function j(t,n){t.rulesEvaluated+=n.rulesEvaluated,t.rulesMatched+=n.rulesMatched,t.rulesSkipped+=n.rulesSkipped,t.directivesApplied+=n.directivesApplied,t.directivesSkipped+=n.directivesSkipped,t.subRunsCreated+=n.subRunsCreated,t.errors+=n.errors;}function K(t){let n=t.filledNames.has("beforeEvent"),r=t.filledNames.has("afterEvent"),o=t.filledNames.has("onEventsComplete");return function*(d,f,g,s,c,l){let E=[],y=[],e=[],k=P(),R=c.length>0;s.setContext(g);for(let p of f){let _=d.get(p.event);if(!_||_.length===0){y.push(p.event);continue}let b=[],A=[],S=[],C=[],i=P(),w=false,T,D={ctx:g,counters:i,event:p.event},L={$event:{type:p.event,data:p.data}};for(let h=0;h<_.length;h++){let m=_[h];if(i.rulesEvaluated++,n)try{let v=l.beforeEvent(m.definition,D);if(v==="skip"){A.push(h),i.rulesSkipped++;continue}if(v==="abort")break}catch(v){C.push({ruleIndex:h,error:`beforeEvent: ${v}`}),i.errors++;}b.push(h),i.rulesMatched++;let x;if(R)try{x=M(c,m.definition,g,L);}catch(v){C.push({ruleIndex:h,error:`Middleware: ${v}`}),i.errors++;continue}else x=L;let u;if(m.isInteractive?u=yield*s.invokeInteractive(m.actionId,x):u=s.invoke(m.actionId,x),i.directivesApplied+=u.appliedCount,i.directivesSkipped+=u.skippedCount,i.errors+=u.errors.length,r)try{if(l.afterEvent(m.definition,u,D)==="abort")break}catch{}if(u.aborted){w=true,T=u.abortedBy;break}}e.push(...C),j(k,i),E.push({event:p.event,matched:b,skipped:A,notMatched:S,errors:C,halted:w,haltedBy:T,counters:i});}let I={eventResults:E,unprocessedEvents:y,errors:e,counters:k,totalEvents:f.length,processedEvents:E.length};if(o)try{l.onEventsComplete(I);}catch{}return I}}function X(t){let n=t.filledNames.has("beforeEvent"),r=t.filledNames.has("afterEvent"),o=t.filledNames.has("onEventsComplete");return async function*(d,f,g,s,c,l){let E=[],y=[],e=[],k=P(),R=c.length>0;s.setContext(g);for(let p of f){let _=d.get(p.event);if(!_||_.length===0){y.push(p.event);continue}let b=[],A=[],S=[],C=[],i=P(),w=false,T,D={ctx:g,counters:i,event:p.event},L={$event:{type:p.event,data:p.data}};for(let h=0;h<_.length;h++){let m=_[h];if(i.rulesEvaluated++,n)try{let v=await l.beforeEvent(m.definition,D);if(v==="skip"){A.push(h),i.rulesSkipped++;continue}if(v==="abort")break}catch(v){C.push({ruleIndex:h,error:`beforeEvent: ${v}`}),i.errors++;}b.push(h),i.rulesMatched++;let x;if(R)try{x=M(c,m.definition,g,L);}catch(v){C.push({ruleIndex:h,error:`Middleware: ${v}`}),i.errors++;continue}else x=L;let u;if(m.isInteractive?u=yield*s.invokeInteractive(m.actionId,x):m.isAsync?u=await s.invokeAsync(m.actionId,x):u=s.invoke(m.actionId,x),i.directivesApplied+=u.appliedCount,i.directivesSkipped+=u.skippedCount,i.errors+=u.errors.length,r)try{if(await l.afterEvent(m.definition,u,D)==="abort")break}catch{}if(u.aborted){w=true,T=u.abortedBy;break}}e.push(...C),j(k,i),E.push({event:p.event,matched:b,skipped:A,notMatched:S,errors:C,halted:w,haltedBy:T,counters:i});}let I={eventResults:E,unprocessedEvents:y,errors:e,counters:k,totalEvents:f.length,processedEvents:E.length};if(o)try{await l.onEventsComplete(I);}catch{}return I}}function V(t,n){return n?X(t):K(t)}function H(t,n,r){let{filledNames:o,asyncNames:a}=t,d=A=>o.has(A),f=A=>a.has(A)?"await ":"",g=d("beforeEvent"),s=d("afterEvent"),c=d("onEventsComplete"),l=f("beforeEvent"),E=f("afterEvent"),y=f("onEventsComplete"),e=[];e.push("const eventResults=[];"),e.push("const unprocessedEvents=[];"),e.push("const aggErrors=[];"),e.push("const aggCounters={rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0};"),e.push("ae.setContext(ctx);"),c&&e.push("const _hookOnComplete=hooks.onEventsComplete;"),e.push("for(let _ei=0;_ei<events.length;_ei++){"),e.push("const ev=events[_ei];"),e.push("const _evListeners=listenerIndex.get(ev.event);"),e.push("if(!_evListeners||_evListeners.length===0){unprocessedEvents.push(ev.event);continue;}"),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("let halted=false;let haltedBy;"),(g||s)&&e.push("const evalCtx={ctx,counters,event:ev.event};"),g&&e.push("const _hookBefore=hooks.beforeEvent;"),s&&e.push("const _hookAfter=hooks.afterEvent;"),e.push("const _ep={$event:{type:ev.event,data:ev.data}};"),e.push("for(let _ri=0;_ri<_evListeners.length;_ri++){"),e.push("const stored=_evListeners[_ri];"),e.push("counters.rulesEvaluated++;"),g&&(e.push("try{"),e.push(`const _bd=${l}_hookBefore(stored.definition,evalCtx);`),e.push('if(_bd==="skip"){skipped.push(_ri);counters.rulesSkipped++;continue;}'),e.push('if(_bd==="abort"){break;}'),e.push('}catch(_e){errors.push({ruleIndex:_ri,error:"beforeEvent: "+_e});counters.errors++;}')),e.push("matched.push(_ri);counters.rulesMatched++;"),n&&(e.push("let params;"),e.push('try{params=$.runMw(mw,stored.definition,ctx,_ep);}catch(_e){errors.push({ruleIndex:_ri,error:"Middleware: "+_e});counters.errors++;continue;}'));let k=n?"params":"_ep",R=r?`await ae.invokeAsync(stored.actionId,${k})`:`ae.invoke(stored.actionId,${k})`;e.push(`const ir=${R};`),e.push("counters.directivesApplied+=ir.appliedCount;counters.directivesSkipped+=ir.skippedCount;counters.errors+=ir.errors.length;"),s&&(e.push("try{"),e.push(`const _ad=${E}_hookAfter(stored.definition,ir,evalCtx);`),e.push('if(_ad==="abort"){break;}'),e.push("}catch(_e){}")),e.push("if(ir.aborted){halted=true;haltedBy=ir.abortedBy;break;}"),e.push("}"),e.push("aggCounters.rulesEvaluated+=counters.rulesEvaluated;"),e.push("aggCounters.rulesMatched+=counters.rulesMatched;"),e.push("aggCounters.rulesSkipped+=counters.rulesSkipped;"),e.push("aggCounters.directivesApplied+=counters.directivesApplied;"),e.push("aggCounters.directivesSkipped+=counters.directivesSkipped;"),e.push("aggCounters.subRunsCreated+=counters.subRunsCreated;"),e.push("aggCounters.errors+=counters.errors;"),e.push("for(let _k=0;_k<errors.length;_k++)aggErrors.push(errors[_k]);"),e.push("eventResults.push({event:ev.event,matched,skipped,notMatched,errors,halted,haltedBy,counters});"),e.push("}"),e.push("const _r={eventResults,unprocessedEvents,errors:aggErrors,counters:aggCounters,totalEvents:events.length,processedEvents:eventResults.length};"),c&&e.push(`try{${y}_hookOnComplete(_r);}catch(_e){}`),e.push("return _r;");let I=e.join(`
2
+ `),p=r?"async ":"",_=new Function("listenerIndex","events","ctx","ae","mw","hooks","$",`"use strict";
3
3
  return(${p}()=>{
4
- ${A}
5
- })();`),x={};return s&&(x.runMw=M),function(S,C,c,k,T,D){return y(S,C,c,k,T,D,x)}}function V(e){return !e.event||typeof e.event!="string"?{event:e.event??"(missing)",code:"INVALID_DEFINITION",message:"event definition must have a non-empty string event name"}:e.tags!==void 0&&!Array.isArray(e.tags)?{event:e.event,code:"INVALID_DEFINITION",message:"event definition tags must be an array of strings"}:e.tier!==void 0&&typeof e.tier!="number"?{event:e.event,code:"INVALID_DEFINITION",message:"event definition tier must be a number"}:null}function j(e){if(!e.id||typeof e.id!="string")return {listenerId:e.id??"(missing)",code:"INVALID_LISTENER",message:"listener must have a string id"};if(typeof e.priority!="number")return {listenerId:e.id,code:"INVALID_LISTENER",message:"listener must have a numeric priority"};if(typeof e.on=="string"){if(!e.on)return {listenerId:e.id,code:"INVALID_LISTENER",message:"listener.on must be a non-empty string or string[]"}}else if(Array.isArray(e.on)){if(e.on.length===0||e.on.some(s=>typeof s!="string"||!s))return {listenerId:e.id,code:"INVALID_LISTENER",message:"listener.on must be a non-empty string or string[] of non-empty strings"}}else return {listenerId:e.id,code:"INVALID_LISTENER",message:"listener.on must be a string or string[]"};return !Array.isArray(e.then)||e.then.length===0?{listenerId:e.id,code:"INVALID_LISTENER",message:"listener must have a non-empty then array"}:null}function H(e,s){let r=0,i=e.length;for(;r<i;){let o=r+i>>>1;e[o].priority>=s.priority?r=o+1:i=o;}e.splice(r,0,s);}function W(e,s){let r=e.indexOf(s);return r===-1?false:(e.splice(r,1),true)}var P=()=>{},$=class{_actionEngine;_middleware;_eventHooks;_isAsync;_requestedMode;_hookAnalysis;_dispatcher;_mode;_maybeAutoPromote;_eventDefinitions=new Map;_listenerRegistry=new Map;_listenerIndex=new Map;_batch=null;constructor(s){if(this._actionEngine=s.actionEngine,this._middleware=s.middleware??[],this._eventHooks=s.eventHooks??{},this._requestedMode=s.mode??"auto",this._hookAnalysis=core.analyzeSlots(this._eventHooks,core.EVENT_SLOT_NAMES),this._isAsync=this._hookAnalysis.hasAnyAsync||this._actionEngine.isAsync,this._requestedMode==="jit")this._dispatcher=this._buildJit(),this._mode="jit",this._maybeAutoPromote=P;else if(this._dispatcher=B(this._hookAnalysis,this._isAsync),this._mode="interpret",this._requestedMode==="auto"){let r=0,i=s.autoJitThreshold??8;this._maybeAutoPromote=()=>{++r>=i&&this._promote();};}else this._maybeAutoPromote=P;}get actionEngine(){return this._actionEngine}get isAsync(){return this._isAsync}get compilationMode(){return this._mode}get eventDefinitions(){return this._eventDefinitions}getEventDefinition(s){return this._eventDefinitions.get(s)}defineEvents(s){let r=[],i=[],o=[];for(let n of s){let a=V(n);if(a){i.push(a);continue}if(this._eventDefinitions.has(n.event)){i.push({event:n.event,code:"DUPLICATE_EVENT",message:`event definition "${n.event}" is already registered`});continue}this._eventDefinitions.set(n.event,n);let u=["eventdef"];n.tags&&u.push(...n.tags),o.push({id:`eventdef:${n.event}`,directives:[],tags:u,declarations:n.declarations,tier:n.tier,metadata:{...n.schema!==void 0&&{schema:n.schema},...n.description!==void 0&&{description:n.description}}}),r.push(n.event);}let d=[];if(o.length>0){let n=this._actionEngine.register(o);for(let a of n.errors){let u=this._actionIdToEventName(a.actionId);i.push({event:u??a.actionId,code:a.code??"ACTION_ERROR",message:a.error});}d=n.warnings;}let g={defined:r,errors:i,warnings:d};return this._batch&&(this._batch.definedEvents.push(...r),this._batch.defineErrors.push(...i),this._batch.warnings.push(...d)),g}register(s){let r=[],i=[],o=[],d=[];for(let n of s){let a=j(n);if(a){i.push(a);continue}if(this._listenerRegistry.has(n.id)){i.push({listenerId:n.id,code:"DUPLICATE_ID",message:`listener "${n.id}" is already registered`});continue}let u=typeof n.on=="string"?[n.on]:n.on,m=false;for(let l of u){let h=this._eventDefinitions.get(l);if(!h){o.push({actionId:`event:${n.id}`,code:"NO_EVENT_DEFINITION",message:`listener "${n.id}" listens to "${l}" but no event definition is registered for it`});continue}h.tier!==void 0&&n.declarations?.tier!==void 0&&n.declarations.tier<h.tier&&(i.push({listenerId:n.id,code:"TIER_VIOLATION",message:`listener "${n.id}" declares tier ${n.declarations.tier} but event "${l}" requires tier >= ${h.tier}`}),m=true);}if(m)continue;let _=`event:${n.id}`,b={definition:n,actionId:_,priority:n.priority};this._listenerRegistry.set(n.id,b);for(let l of u){let h=this._listenerIndex.get(l);h||(h=[],this._listenerIndex.set(l,h)),H(h,b);}let t=["event"];n.tags&&t.push(...n.tags),d.push({id:_,tags:t,directives:n.then,declarations:n.declarations}),r.push(n.id);}if(d.length>0){let n=this._actionEngine.register(d);for(let a of n.errors){let u=this._actionIdToListenerId(a.actionId);i.push({listenerId:u??a.actionId,code:a.code??"ACTION_ERROR",message:a.error});}o.push(...n.warnings);}let g={registered:r,errors:i,warnings:o};return this._batch&&(this._batch.registered.push(...r),this._batch.errors.push(...i),this._batch.warnings.push(...o)),g}unregister(s){let r=this._listenerRegistry.get(s);if(!r)return false;this._listenerRegistry.delete(s);let i=typeof r.definition.on=="string"?[r.definition.on]:r.definition.on;for(let o of i){let d=this._listenerIndex.get(o);d&&(W(d,r),d.length===0&&this._listenerIndex.delete(o));}return this._actionEngine.unregister(r.actionId),true}processEvents(s,r){if(this._isAsync)throw new Error("Cannot call processEvents() with async hooks. Use processEventsAsync() instead.");let i=this._dispatcher(this._listenerIndex,s,r,this._actionEngine,this._middleware,this._eventHooks);return this._maybeAutoPromote(),i}async processEventsAsync(s,r){let i=await this._dispatcher(this._listenerIndex,s,r,this._actionEngine,this._middleware,this._eventHooks);return this._maybeAutoPromote(),i}beginBatch(){this._batch||(this._batch={depth:0,registered:[],errors:[],warnings:[],definedEvents:[],defineErrors:[]}),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 s=this._actionEngine.endBatch();if(this._batch.depth>0)return {registered:[],errors:[],warnings:[]};let r=this._batch;for(let o of s.errors){let d=this._actionIdToListenerId(o.actionId);r.errors.push({listenerId:d??o.actionId,code:o.code??"ACTION_ERROR",message:o.error});}r.warnings.push(...s.warnings);let i={registered:r.registered,errors:r.errors,warnings:r.warnings};return this._batch=null,i}compile(){this._requestedMode!=="interpret"&&this._mode!=="jit"&&this._promote();}_promote(){this._dispatcher=this._buildJit(),this._mode="jit",this._maybeAutoPromote=P;}_buildJit(){return F(this._hookAnalysis,this._middleware.length>0,this._isAsync)}_actionIdToListenerId(s){return s.startsWith("event:")?s.slice(6):null}_actionIdToEventName(s){return s.startsWith("eventdef:")?s.slice(9):null}};function z(e){return new $(e)}function re(e="event"){return s=>{let r=s[e],i=typeof r=="string"&&r?[`eventdef:${r}`]:[];return {capabilities:["emit"],dependencies:i}}}exports.createEmitAnalyzer=re;exports.createEventProcessor=z;
4
+ ${I}
5
+ })();`),b={};return n&&(b.runMw=M),function(S,C,i,w,T,D){return _(S,C,i,w,T,D,b)}}function Q(t,n,r){let{filledNames:o,asyncNames:a}=t,d=b=>o.has(b),f=b=>a.has(b)?"await ":"",g=d("beforeEvent"),s=d("afterEvent"),c=d("onEventsComplete"),l=f("beforeEvent"),E=f("afterEvent"),y=f("onEventsComplete"),e=[];e.push("const eventResults=[];"),e.push("const unprocessedEvents=[];"),e.push("const aggErrors=[];"),e.push("const aggCounters={rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0};"),e.push("ae.setContext(ctx);"),c&&e.push("const _hookOnComplete=hooks.onEventsComplete;"),e.push("for(let _ei=0;_ei<events.length;_ei++){"),e.push("const ev=events[_ei];"),e.push("const _evListeners=listenerIndex.get(ev.event);"),e.push("if(!_evListeners||_evListeners.length===0){unprocessedEvents.push(ev.event);continue;}"),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("let halted=false;let haltedBy;"),(g||s)&&e.push("const evalCtx={ctx,counters,event:ev.event};"),g&&e.push("const _hookBefore=hooks.beforeEvent;"),s&&e.push("const _hookAfter=hooks.afterEvent;"),e.push("const _ep={$event:{type:ev.event,data:ev.data}};"),e.push("for(let _ri=0;_ri<_evListeners.length;_ri++){"),e.push("const stored=_evListeners[_ri];"),e.push("counters.rulesEvaluated++;"),g&&(e.push("try{"),e.push(`const _bd=${l}_hookBefore(stored.definition,evalCtx);`),e.push('if(_bd==="skip"){skipped.push(_ri);counters.rulesSkipped++;continue;}'),e.push('if(_bd==="abort"){break;}'),e.push('}catch(_e){errors.push({ruleIndex:_ri,error:"beforeEvent: "+_e});counters.errors++;}')),e.push("matched.push(_ri);counters.rulesMatched++;"),n&&(e.push("let params;"),e.push('try{params=$.runMw(mw,stored.definition,ctx,_ep);}catch(_e){errors.push({ruleIndex:_ri,error:"Middleware: "+_e});counters.errors++;continue;}'));let k=n?"params":"_ep";e.push("let ir;"),e.push("if(stored.isInteractive){"),e.push(`ir=yield* ae.invokeInteractive(stored.actionId,${k});`),r&&(e.push("}else if(stored.isAsync){"),e.push(`ir=await ae.invokeAsync(stored.actionId,${k});`)),e.push("}else{"),e.push(`ir=ae.invoke(stored.actionId,${k});`),e.push("}"),e.push("counters.directivesApplied+=ir.appliedCount;counters.directivesSkipped+=ir.skippedCount;counters.errors+=ir.errors.length;"),s&&(e.push("try{"),e.push(`const _ad=${E}_hookAfter(stored.definition,ir,evalCtx);`),e.push('if(_ad==="abort"){break;}'),e.push("}catch(_e){}")),e.push("if(ir.aborted){halted=true;haltedBy=ir.abortedBy;break;}"),e.push("}"),e.push("aggCounters.rulesEvaluated+=counters.rulesEvaluated;"),e.push("aggCounters.rulesMatched+=counters.rulesMatched;"),e.push("aggCounters.rulesSkipped+=counters.rulesSkipped;"),e.push("aggCounters.directivesApplied+=counters.directivesApplied;"),e.push("aggCounters.directivesSkipped+=counters.directivesSkipped;"),e.push("aggCounters.subRunsCreated+=counters.subRunsCreated;"),e.push("aggCounters.errors+=counters.errors;"),e.push("for(let _k=0;_k<errors.length;_k++)aggErrors.push(errors[_k]);"),e.push("eventResults.push({event:ev.event,matched,skipped,notMatched,errors,halted,haltedBy,counters});"),e.push("}"),e.push("const _r={eventResults,unprocessedEvents,errors:aggErrors,counters:aggCounters,totalEvents:events.length,processedEvents:eventResults.length};"),c&&e.push(`try{${y}_hookOnComplete(_r);}catch(_e){}`),e.push("return _r;");let R=e.join(`
6
+ `),I=r?"async function* ":"function* ",p=new Function("listenerIndex","events","ctx","ae","mw","hooks","$",`"use strict";
7
+ return(${I}(){
8
+ ${R}
9
+ })();`),_={};return n&&(_.runMw=M),function(A,S,C,i,w,T){return p(A,S,C,i,w,T,_)}}function W(t){return !t.event||typeof t.event!="string"?{event:t.event??"(missing)",code:"INVALID_DEFINITION",message:"event definition must have a non-empty string event name"}:t.tags!==void 0&&!Array.isArray(t.tags)?{event:t.event,code:"INVALID_DEFINITION",message:"event definition tags must be an array of strings"}:t.tier!==void 0&&typeof t.tier!="number"?{event:t.event,code:"INVALID_DEFINITION",message:"event definition tier must be a number"}:null}function G(t){if(!t.id||typeof t.id!="string")return {listenerId:t.id??"(missing)",code:"INVALID_LISTENER",message:"listener must have a string id"};if(typeof t.priority!="number")return {listenerId:t.id,code:"INVALID_LISTENER",message:"listener must have a numeric priority"};if(typeof t.on=="string"){if(!t.on)return {listenerId:t.id,code:"INVALID_LISTENER",message:"listener.on must be a non-empty string or string[]"}}else if(Array.isArray(t.on)){if(t.on.length===0||t.on.some(n=>typeof n!="string"||!n))return {listenerId:t.id,code:"INVALID_LISTENER",message:"listener.on must be a non-empty string or string[] of non-empty strings"}}else return {listenerId:t.id,code:"INVALID_LISTENER",message:"listener.on must be a string or string[]"};return !Array.isArray(t.then)||t.then.length===0?{listenerId:t.id,code:"INVALID_LISTENER",message:"listener must have a non-empty then array"}:null}function q(t,n){let r=0,o=t.length;for(;r<o;){let a=r+o>>>1;t[a].priority>=n.priority?r=a+1:o=a;}t.splice(r,0,n);}function U(t,n){let r=t.indexOf(n);return r===-1?false:(t.splice(r,1),true)}var F=()=>{},B=class{_actionEngine;_middleware;_eventHooks;_requestedMode;_hookAnalysis;_isAsync;_hasAnyInteractiveListener=false;_dispatcher;_mode;_maybeAutoPromote;_interactiveDispatcher=null;_interactiveDispatcherIsAsync=false;_eventDefinitions=new Map;_listenerRegistry=new Map;_listenerIndex=new Map;_batch=null;constructor(n){if(this._actionEngine=n.actionEngine,this._middleware=n.middleware??[],this._eventHooks=n.eventHooks??{},this._requestedMode=n.mode??"auto",this._hookAnalysis=core.analyzeSlots(this._eventHooks,core.EVENT_SLOT_NAMES),this._isAsync=this._hookAnalysis.hasAnyAsync,this._requestedMode==="jit")this._dispatcher=this._buildJit(),this._mode="jit",this._maybeAutoPromote=F;else if(this._dispatcher=$(this._hookAnalysis,this._isAsync),this._mode="interpret",this._requestedMode==="auto"){let r=0,o=n.autoJitThreshold??8;this._maybeAutoPromote=()=>{++r>=o&&this._promote();};}else this._maybeAutoPromote=F;}get actionEngine(){return this._actionEngine}get isAsync(){return this._isAsync}get isInteractive(){return this._hasAnyInteractiveListener}get compilationMode(){return this._mode}get eventDefinitions(){return this._eventDefinitions}getEventDefinition(n){return this._eventDefinitions.get(n)}defineEvents(n){let r=[],o=[],a=[];for(let s of n){let c=W(s);if(c){r.push(c);continue}if(this._eventDefinitions.has(s.event)||a.some(E=>E.name===s.event)){r.push({event:s.event,code:"DUPLICATE_EVENT",message:`event definition "${s.event}" is already registered`});continue}let l=["eventdef"];s.tags&&l.push(...s.tags),o.push({id:`eventdef:${s.event}`,directives:[],tags:l,declarations:s.declarations,tier:s.tier,metadata:{...s.schema!==void 0&&{schema:s.schema},...s.description!==void 0&&{description:s.description}}}),a.push({name:s.event,def:s});}let d=[];if(o.length>0){let s=this._actionEngine.register(o);for(let c of s.errors){let l=this._actionIdToEventName(c.actionId);r.push({event:l??c.actionId,code:c.code??"ACTION_ERROR",message:c.error});}d=s.warnings;}let f=[];for(let{name:s,def:c}of a)this._eventDefinitions.set(s,c),f.push(s);let g={defined:f,errors:r,warnings:d};return this._batch&&(this._batch.definedEvents.push(...f),this._batch.defineErrors.push(...r),this._batch.warnings.push(...d)),g}register(n){let r=[],o=[],a=[],d=[];for(let s of n){let c=G(s);if(c){r.push(c);continue}if(this._listenerRegistry.has(s.id)||d.some(R=>R.id===s.id)){r.push({listenerId:s.id,code:"DUPLICATE_ID",message:`listener "${s.id}" is already registered`});continue}let l=typeof s.on=="string"?[s.on]:s.on,E=false;for(let R of l){let I=this._eventDefinitions.get(R);if(!I){o.push({actionId:`event:${s.id}`,code:"NO_EVENT_DEFINITION",message:`listener "${s.id}" listens to "${R}" but no event definition is registered for it`});continue}I.tier!==void 0&&s.declarations?.tier!==void 0&&s.declarations.tier<I.tier&&(r.push({listenerId:s.id,code:"TIER_VIOLATION",message:`listener "${s.id}" declares tier ${s.declarations.tier} but event "${R}" requires tier >= ${I.tier}`}),E=true);}if(E)continue;let y=`event:${s.id}`,e={definition:s,actionId:y,priority:s.priority,isAsync:false,isInteractive:false},k=["event"];s.tags&&k.push(...s.tags),a.push({id:y,tags:k,directives:s.then,declarations:s.declarations}),d.push({id:s.id,stored:e,eventNames:l});}if(a.length>0){let s=this._actionEngine.register(a);for(let c of s.errors){let l=this._actionIdToListenerId(c.actionId);r.push({listenerId:l??c.actionId,code:c.code??"ACTION_ERROR",message:c.error});}o.push(...s.warnings);}let f=[];for(let{id:s,stored:c,eventNames:l}of d){this._listenerRegistry.set(s,c);for(let E of l){let y=this._listenerIndex.get(E);y||(y=[],this._listenerIndex.set(E,y)),q(y,c);}f.push(s);}let g={registered:f,errors:r,warnings:o};return this._batch?(this._batch.registered.push(...f),this._batch.errors.push(...r),this._batch.warnings.push(...o)):f.length>0&&this._refreshListenerFlags(),g}unregister(n){let r=this._listenerRegistry.get(n);if(!r)return false;this._listenerRegistry.delete(n);let o=typeof r.definition.on=="string"?[r.definition.on]:r.definition.on;for(let a of o){let d=this._listenerIndex.get(a);d&&(U(d,r),d.length===0&&this._listenerIndex.delete(a));}return this._actionEngine.unregister(r.actionId),this._refreshListenerFlags(),true}processEvents(n,r){if(this._hasAnyInteractiveListener)throw new Error("Cannot call processEvents() \u2014 at least one listener is interactive (transitively). Use processEventsInteractive() instead.");if(this._isAsync)throw new Error("Cannot call processEvents() with async hooks or async listeners. Use processEventsAsync() instead.");let o=this._dispatcher(this._listenerIndex,n,r,this._actionEngine,this._middleware,this._eventHooks);return this._maybeAutoPromote(),o}async processEventsAsync(n,r){if(this._hasAnyInteractiveListener)throw new Error("Cannot call processEventsAsync() \u2014 at least one listener is interactive (transitively). Use processEventsInteractive() instead.");let o=await this._dispatcher(this._listenerIndex,n,r,this._actionEngine,this._middleware,this._eventHooks);return this._maybeAutoPromote(),o}processEventsInteractive(n,r){if(!this._hasAnyInteractiveListener)throw new Error("Cannot call processEventsInteractive() \u2014 no registered listener is interactive (transitively). Use processEvents() or processEventsAsync() instead.");return (this._interactiveDispatcher===null||this._interactiveDispatcherIsAsync!==this._isAsync)&&(this._interactiveDispatcher=this._mode==="jit"?Q(this._hookAnalysis,this._middleware.length>0,this._isAsync):V(this._hookAnalysis,this._isAsync),this._interactiveDispatcherIsAsync=this._isAsync),this._interactiveDispatcher(this._listenerIndex,n,r,this._actionEngine,this._middleware,this._eventHooks)}beginBatch(){this._batch||(this._batch={depth:0,registered:[],errors:[],warnings:[],definedEvents:[],defineErrors:[]}),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 n=this._actionEngine.endBatch();if(this._batch.depth>0)return {registered:[],errors:[],warnings:[]};let r=this._batch;for(let a of n.errors){let d=this._actionIdToListenerId(a.actionId);r.errors.push({listenerId:d??a.actionId,code:a.code??"ACTION_ERROR",message:a.error});}r.warnings.push(...n.warnings);let o={registered:r.registered,errors:r.errors,warnings:r.warnings};return this._batch=null,this._refreshListenerFlags(),o}compile(){this._requestedMode!=="interpret"&&this._mode!=="jit"&&this._promote();}_promote(){this._dispatcher=this._buildJit(),this._mode="jit",this._maybeAutoPromote=F,this._interactiveDispatcher=null;}_buildJit(){return H(this._hookAnalysis,this._middleware.length>0,this._isAsync)}_refreshListenerFlags(){let n=false,r=false;for(let a of this._listenerRegistry.values())a.isAsync=this._actionEngine.isActionAsync(a.actionId)??false,a.isInteractive=this._actionEngine.isActionInteractive?.(a.actionId)??false,a.isAsync&&(n=true),a.isInteractive&&(r=true);this._hasAnyInteractiveListener=r;let o=this._hookAnalysis.hasAnyAsync||n;o!==this._isAsync&&(this._isAsync=o,this._rebuildDispatcher());}_rebuildDispatcher(){this._dispatcher=this._mode==="jit"?this._buildJit():$(this._hookAnalysis,this._isAsync);}_actionIdToListenerId(n){return n.startsWith("event:")?n.slice(6):null}_actionIdToEventName(n){return n.startsWith("eventdef:")?n.slice(9):null}};function ee(t){return new B(t)}function he(t="event"){return n=>{let r=n[t],o=typeof r=="string"&&r?[`eventdef:${r}`]:[];return {capabilities:["emit"],dependencies:o}}}exports.createEmitAnalyzer=he;exports.createEventProcessor=ee;
package/dist/index.d.cts CHANGED
@@ -92,6 +92,24 @@ interface EventProcessorConfig<TCtx = unknown> {
92
92
  mode?: "interpret" | "jit" | "auto";
93
93
  autoJitThreshold?: number;
94
94
  }
95
+ /**
96
+ * Sessão de processamento de events em modo interactive — retornada por
97
+ * `processEventsInteractive(events, ctx)`. Drena via `next()`. O `done.value`
98
+ * final é `EventProcessingResult`. Halt scoping: pause em listener para os
99
+ * listeners daquele evento; próximos eventos na fila continuam normalmente.
100
+ */
101
+ interface InteractiveEventSession extends Iterator<unknown, EventProcessingResult, unknown> {
102
+ next(value?: unknown): IteratorResult<unknown, EventProcessingResult>;
103
+ return(): IteratorResult<unknown, EventProcessingResult>;
104
+ throw(err?: unknown): IteratorResult<unknown, EventProcessingResult>;
105
+ [Symbol.iterator](): InteractiveEventSession;
106
+ }
107
+ interface AsyncInteractiveEventSession extends AsyncIterator<unknown, EventProcessingResult, unknown> {
108
+ next(value?: unknown): Promise<IteratorResult<unknown, EventProcessingResult>>;
109
+ return(): Promise<IteratorResult<unknown, EventProcessingResult>>;
110
+ throw(err?: unknown): Promise<IteratorResult<unknown, EventProcessingResult>>;
111
+ [Symbol.asyncIterator](): AsyncInteractiveEventSession;
112
+ }
95
113
  interface IEventProcessor<TCtx = unknown> {
96
114
  defineEvents(definitions: readonly EventDefinition[]): EventDefineResult;
97
115
  getEventDefinition(event: string): EventDefinition | undefined;
@@ -100,11 +118,22 @@ interface IEventProcessor<TCtx = unknown> {
100
118
  unregister(id: string): boolean;
101
119
  processEvents(events: readonly QueuedEvent[], ctx: TCtx): EventProcessingResult;
102
120
  processEventsAsync(events: readonly QueuedEvent[], ctx: TCtx): Promise<EventProcessingResult>;
121
+ /**
122
+ * Processa events em modo interactive — retorna iterator drenável.
123
+ * Lança se nenhum listener registrado é interactive transitivamente, ou se
124
+ * actionEngine não tem `interactive` configurado.
125
+ *
126
+ * Variante async (AsyncInteractiveEventSession) é retornada quando algum
127
+ * listener é async transitivamente OU algum hook é async.
128
+ */
129
+ processEventsInteractive(events: readonly QueuedEvent[], ctx: TCtx): InteractiveEventSession | AsyncInteractiveEventSession;
103
130
  beginBatch(): void;
104
131
  endBatch(): EventRegisterResult;
105
132
  compile(): void;
106
133
  readonly actionEngine: IActionEngine<TCtx>;
107
134
  readonly isAsync: boolean;
135
+ /** Algum listener registrado é interactive transitivamente? Cached. */
136
+ readonly isInteractive: boolean;
108
137
  readonly compilationMode: "interpret" | "jit";
109
138
  }
110
139
 
package/dist/index.d.ts CHANGED
@@ -92,6 +92,24 @@ interface EventProcessorConfig<TCtx = unknown> {
92
92
  mode?: "interpret" | "jit" | "auto";
93
93
  autoJitThreshold?: number;
94
94
  }
95
+ /**
96
+ * Sessão de processamento de events em modo interactive — retornada por
97
+ * `processEventsInteractive(events, ctx)`. Drena via `next()`. O `done.value`
98
+ * final é `EventProcessingResult`. Halt scoping: pause em listener para os
99
+ * listeners daquele evento; próximos eventos na fila continuam normalmente.
100
+ */
101
+ interface InteractiveEventSession extends Iterator<unknown, EventProcessingResult, unknown> {
102
+ next(value?: unknown): IteratorResult<unknown, EventProcessingResult>;
103
+ return(): IteratorResult<unknown, EventProcessingResult>;
104
+ throw(err?: unknown): IteratorResult<unknown, EventProcessingResult>;
105
+ [Symbol.iterator](): InteractiveEventSession;
106
+ }
107
+ interface AsyncInteractiveEventSession extends AsyncIterator<unknown, EventProcessingResult, unknown> {
108
+ next(value?: unknown): Promise<IteratorResult<unknown, EventProcessingResult>>;
109
+ return(): Promise<IteratorResult<unknown, EventProcessingResult>>;
110
+ throw(err?: unknown): Promise<IteratorResult<unknown, EventProcessingResult>>;
111
+ [Symbol.asyncIterator](): AsyncInteractiveEventSession;
112
+ }
95
113
  interface IEventProcessor<TCtx = unknown> {
96
114
  defineEvents(definitions: readonly EventDefinition[]): EventDefineResult;
97
115
  getEventDefinition(event: string): EventDefinition | undefined;
@@ -100,11 +118,22 @@ interface IEventProcessor<TCtx = unknown> {
100
118
  unregister(id: string): boolean;
101
119
  processEvents(events: readonly QueuedEvent[], ctx: TCtx): EventProcessingResult;
102
120
  processEventsAsync(events: readonly QueuedEvent[], ctx: TCtx): Promise<EventProcessingResult>;
121
+ /**
122
+ * Processa events em modo interactive — retorna iterator drenável.
123
+ * Lança se nenhum listener registrado é interactive transitivamente, ou se
124
+ * actionEngine não tem `interactive` configurado.
125
+ *
126
+ * Variante async (AsyncInteractiveEventSession) é retornada quando algum
127
+ * listener é async transitivamente OU algum hook é async.
128
+ */
129
+ processEventsInteractive(events: readonly QueuedEvent[], ctx: TCtx): InteractiveEventSession | AsyncInteractiveEventSession;
103
130
  beginBatch(): void;
104
131
  endBatch(): EventRegisterResult;
105
132
  compile(): void;
106
133
  readonly actionEngine: IActionEngine<TCtx>;
107
134
  readonly isAsync: boolean;
135
+ /** Algum listener registrado é interactive transitivamente? Cached. */
136
+ readonly isInteractive: boolean;
108
137
  readonly compilationMode: "interpret" | "jit";
109
138
  }
110
139
 
package/dist/index.js CHANGED
@@ -1,5 +1,9 @@
1
- import {analyzeSlots,EVENT_SLOT_NAMES}from'@statedelta-actions/core';function L(){return {rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0}}function O(e,s){e.rulesEvaluated+=s.rulesEvaluated,e.rulesMatched+=s.rulesMatched,e.rulesSkipped+=s.rulesSkipped,e.directivesApplied+=s.directivesApplied,e.directivesSkipped+=s.directivesSkipped,e.subRunsCreated+=s.subRunsCreated,e.errors+=s.errors;}function M(e,s,r,i){let o=i?Object.assign({},i):{};for(let d of e)Object.assign(o,d(s,r,o));return o}function q(e){let s=e.filledNames.has("beforeEvent"),r=e.filledNames.has("afterEvent"),i=e.filledNames.has("onEventsComplete");return function(d,g,n,a,u,m){let _=[],b=[],t=[],l=L(),h=u.length>0;a.setContext(n);for(let p of g){let y=d.get(p.event);if(!y||y.length===0){b.push(p.event);continue}let x=[],R=[],S=[],C=[],c=L(),k=false,T,D={ctx:n,counters:c,event:p.event},N={$event:{type:p.event,data:p.data}};for(let v=0;v<y.length;v++){let I=y[v];if(c.rulesEvaluated++,s)try{let f=m.beforeEvent(I.definition,D);if(f==="skip"){R.push(v),c.rulesSkipped++;continue}if(f==="abort")break}catch(f){C.push({ruleIndex:v,error:`beforeEvent: ${f}`}),c.errors++;}x.push(v),c.rulesMatched++;let w;if(h)try{w=M(u,I.definition,n,N);}catch(f){C.push({ruleIndex:v,error:`Middleware: ${f}`}),c.errors++;continue}else w=N;let E=a.invoke(I.actionId,w);if(c.directivesApplied+=E.appliedCount,c.directivesSkipped+=E.skippedCount,c.errors+=E.errors.length,r)try{if(m.afterEvent(I.definition,E,D)==="abort")break}catch{}if(E.aborted){k=true,T=E.abortedBy;break}}t.push(...C),O(l,c),_.push({event:p.event,matched:x,skipped:R,notMatched:S,errors:C,halted:k,haltedBy:T,counters:c});}let A={eventResults:_,unprocessedEvents:b,errors:t,counters:l,totalEvents:g.length,processedEvents:_.length};if(i)try{m.onEventsComplete(A);}catch{}return A}}function Q(e){let s=e.filledNames.has("beforeEvent"),r=e.filledNames.has("afterEvent"),i=e.filledNames.has("onEventsComplete");return async function(d,g,n,a,u,m){let _=[],b=[],t=[],l=L(),h=u.length>0;a.setContext(n);for(let p of g){let y=d.get(p.event);if(!y||y.length===0){b.push(p.event);continue}let x=[],R=[],S=[],C=[],c=L(),k=false,T,D={ctx:n,counters:c,event:p.event},N={$event:{type:p.event,data:p.data}};for(let v=0;v<y.length;v++){let I=y[v];if(c.rulesEvaluated++,s)try{let f=await m.beforeEvent(I.definition,D);if(f==="skip"){R.push(v),c.rulesSkipped++;continue}if(f==="abort")break}catch(f){C.push({ruleIndex:v,error:`beforeEvent: ${f}`}),c.errors++;}x.push(v),c.rulesMatched++;let w;if(h)try{w=M(u,I.definition,n,N);}catch(f){C.push({ruleIndex:v,error:`Middleware: ${f}`}),c.errors++;continue}else w=N;let E=await a.invokeAsync(I.actionId,w);if(c.directivesApplied+=E.appliedCount,c.directivesSkipped+=E.skippedCount,c.errors+=E.errors.length,r)try{if(await m.afterEvent(I.definition,E,D)==="abort")break}catch{}if(E.aborted){k=true,T=E.abortedBy;break}}t.push(...C),O(l,c),_.push({event:p.event,matched:x,skipped:R,notMatched:S,errors:C,halted:k,haltedBy:T,counters:c});}let A={eventResults:_,unprocessedEvents:b,errors:t,counters:l,totalEvents:g.length,processedEvents:_.length};if(i)try{await m.onEventsComplete(A);}catch{}return A}}function B(e,s){return s?Q(e):q(e)}function F(e,s,r){let{filledNames:i,asyncNames:o}=e,d=R=>i.has(R),g=R=>o.has(R)?"await ":"",n=d("beforeEvent"),a=d("afterEvent"),u=d("onEventsComplete"),m=g("beforeEvent"),_=g("afterEvent"),b=g("onEventsComplete"),t=[];t.push("const eventResults=[];"),t.push("const unprocessedEvents=[];"),t.push("const aggErrors=[];"),t.push("const aggCounters={rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0};"),t.push("ae.setContext(ctx);"),u&&t.push("const _hookOnComplete=hooks.onEventsComplete;"),t.push("for(let _ei=0;_ei<events.length;_ei++){"),t.push("const ev=events[_ei];"),t.push("const _evListeners=listenerIndex.get(ev.event);"),t.push("if(!_evListeners||_evListeners.length===0){unprocessedEvents.push(ev.event);continue;}"),t.push("const matched=[];const skipped=[];const notMatched=[];"),t.push("const errors=[];"),t.push("const counters={rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0};"),t.push("let halted=false;let haltedBy;"),(n||a)&&t.push("const evalCtx={ctx,counters,event:ev.event};"),n&&t.push("const _hookBefore=hooks.beforeEvent;"),a&&t.push("const _hookAfter=hooks.afterEvent;"),t.push("const _ep={$event:{type:ev.event,data:ev.data}};"),t.push("for(let _ri=0;_ri<_evListeners.length;_ri++){"),t.push("const stored=_evListeners[_ri];"),t.push("counters.rulesEvaluated++;"),n&&(t.push("try{"),t.push(`const _bd=${m}_hookBefore(stored.definition,evalCtx);`),t.push('if(_bd==="skip"){skipped.push(_ri);counters.rulesSkipped++;continue;}'),t.push('if(_bd==="abort"){break;}'),t.push('}catch(_e){errors.push({ruleIndex:_ri,error:"beforeEvent: "+_e});counters.errors++;}')),t.push("matched.push(_ri);counters.rulesMatched++;"),s&&(t.push("let params;"),t.push('try{params=$.runMw(mw,stored.definition,ctx,_ep);}catch(_e){errors.push({ruleIndex:_ri,error:"Middleware: "+_e});counters.errors++;continue;}'));let l=s?"params":"_ep",h=r?`await ae.invokeAsync(stored.actionId,${l})`:`ae.invoke(stored.actionId,${l})`;t.push(`const ir=${h};`),t.push("counters.directivesApplied+=ir.appliedCount;counters.directivesSkipped+=ir.skippedCount;counters.errors+=ir.errors.length;"),a&&(t.push("try{"),t.push(`const _ad=${_}_hookAfter(stored.definition,ir,evalCtx);`),t.push('if(_ad==="abort"){break;}'),t.push("}catch(_e){}")),t.push("if(ir.aborted){halted=true;haltedBy=ir.abortedBy;break;}"),t.push("}"),t.push("aggCounters.rulesEvaluated+=counters.rulesEvaluated;"),t.push("aggCounters.rulesMatched+=counters.rulesMatched;"),t.push("aggCounters.rulesSkipped+=counters.rulesSkipped;"),t.push("aggCounters.directivesApplied+=counters.directivesApplied;"),t.push("aggCounters.directivesSkipped+=counters.directivesSkipped;"),t.push("aggCounters.subRunsCreated+=counters.subRunsCreated;"),t.push("aggCounters.errors+=counters.errors;"),t.push("for(let _k=0;_k<errors.length;_k++)aggErrors.push(errors[_k]);"),t.push("eventResults.push({event:ev.event,matched,skipped,notMatched,errors,halted,haltedBy,counters});"),t.push("}"),t.push("const _r={eventResults,unprocessedEvents,errors:aggErrors,counters:aggCounters,totalEvents:events.length,processedEvents:eventResults.length};"),u&&t.push(`try{${b}_hookOnComplete(_r);}catch(_e){}`),t.push("return _r;");let A=t.join(`
2
- `),p=r?"async ":"",y=new Function("listenerIndex","events","ctx","ae","mw","hooks","$",`"use strict";
1
+ import {analyzeSlots,EVENT_SLOT_NAMES}from'@statedelta-actions/core';function N(){return {rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0}}function O(t,n){t.rulesEvaluated+=n.rulesEvaluated,t.rulesMatched+=n.rulesMatched,t.rulesSkipped+=n.rulesSkipped,t.directivesApplied+=n.directivesApplied,t.directivesSkipped+=n.directivesSkipped,t.subRunsCreated+=n.subRunsCreated,t.errors+=n.errors;}function M(t,n,r,o){let a=o?Object.assign({},o):{};for(let d of t)Object.assign(a,d(n,r,a));return a}function J(t){let n=t.filledNames.has("beforeEvent"),r=t.filledNames.has("afterEvent"),o=t.filledNames.has("onEventsComplete");return function(d,f,g,s,c,l){let E=[],y=[],e=[],k=N(),R=c.length>0;s.setContext(g);for(let p of f){let _=d.get(p.event);if(!_||_.length===0){y.push(p.event);continue}let b=[],A=[],S=[],C=[],i=N(),w=false,T,D={ctx:g,counters:i,event:p.event},L={$event:{type:p.event,data:p.data}};for(let h=0;h<_.length;h++){let m=_[h];if(i.rulesEvaluated++,n)try{let v=l.beforeEvent(m.definition,D);if(v==="skip"){A.push(h),i.rulesSkipped++;continue}if(v==="abort")break}catch(v){C.push({ruleIndex:h,error:`beforeEvent: ${v}`}),i.errors++;}b.push(h),i.rulesMatched++;let x;if(R)try{x=M(c,m.definition,g,L);}catch(v){C.push({ruleIndex:h,error:`Middleware: ${v}`}),i.errors++;continue}else x=L;let u=s.invoke(m.actionId,x);if(i.directivesApplied+=u.appliedCount,i.directivesSkipped+=u.skippedCount,i.errors+=u.errors.length,r)try{if(l.afterEvent(m.definition,u,D)==="abort")break}catch{}if(u.aborted){w=true,T=u.abortedBy;break}}e.push(...C),O(k,i),E.push({event:p.event,matched:b,skipped:A,notMatched:S,errors:C,halted:w,haltedBy:T,counters:i});}let I={eventResults:E,unprocessedEvents:y,errors:e,counters:k,totalEvents:f.length,processedEvents:E.length};if(o)try{l.onEventsComplete(I);}catch{}return I}}function z(t){let n=t.filledNames.has("beforeEvent"),r=t.filledNames.has("afterEvent"),o=t.filledNames.has("onEventsComplete");return async function(d,f,g,s,c,l){let E=[],y=[],e=[],k=N(),R=c.length>0;s.setContext(g);for(let p of f){let _=d.get(p.event);if(!_||_.length===0){y.push(p.event);continue}let b=[],A=[],S=[],C=[],i=N(),w=false,T,D={ctx:g,counters:i,event:p.event},L={$event:{type:p.event,data:p.data}};for(let h=0;h<_.length;h++){let m=_[h];if(i.rulesEvaluated++,n)try{let v=await l.beforeEvent(m.definition,D);if(v==="skip"){A.push(h),i.rulesSkipped++;continue}if(v==="abort")break}catch(v){C.push({ruleIndex:h,error:`beforeEvent: ${v}`}),i.errors++;}b.push(h),i.rulesMatched++;let x;if(R)try{x=M(c,m.definition,g,L);}catch(v){C.push({ruleIndex:h,error:`Middleware: ${v}`}),i.errors++;continue}else x=L;let u=await s.invokeAsync(m.actionId,x);if(i.directivesApplied+=u.appliedCount,i.directivesSkipped+=u.skippedCount,i.errors+=u.errors.length,r)try{if(await l.afterEvent(m.definition,u,D)==="abort")break}catch{}if(u.aborted){w=true,T=u.abortedBy;break}}e.push(...C),O(k,i),E.push({event:p.event,matched:b,skipped:A,notMatched:S,errors:C,halted:w,haltedBy:T,counters:i});}let I={eventResults:E,unprocessedEvents:y,errors:e,counters:k,totalEvents:f.length,processedEvents:E.length};if(o)try{await l.onEventsComplete(I);}catch{}return I}}function $(t,n){return n?z(t):J(t)}function P(){return {rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0}}function j(t,n){t.rulesEvaluated+=n.rulesEvaluated,t.rulesMatched+=n.rulesMatched,t.rulesSkipped+=n.rulesSkipped,t.directivesApplied+=n.directivesApplied,t.directivesSkipped+=n.directivesSkipped,t.subRunsCreated+=n.subRunsCreated,t.errors+=n.errors;}function K(t){let n=t.filledNames.has("beforeEvent"),r=t.filledNames.has("afterEvent"),o=t.filledNames.has("onEventsComplete");return function*(d,f,g,s,c,l){let E=[],y=[],e=[],k=P(),R=c.length>0;s.setContext(g);for(let p of f){let _=d.get(p.event);if(!_||_.length===0){y.push(p.event);continue}let b=[],A=[],S=[],C=[],i=P(),w=false,T,D={ctx:g,counters:i,event:p.event},L={$event:{type:p.event,data:p.data}};for(let h=0;h<_.length;h++){let m=_[h];if(i.rulesEvaluated++,n)try{let v=l.beforeEvent(m.definition,D);if(v==="skip"){A.push(h),i.rulesSkipped++;continue}if(v==="abort")break}catch(v){C.push({ruleIndex:h,error:`beforeEvent: ${v}`}),i.errors++;}b.push(h),i.rulesMatched++;let x;if(R)try{x=M(c,m.definition,g,L);}catch(v){C.push({ruleIndex:h,error:`Middleware: ${v}`}),i.errors++;continue}else x=L;let u;if(m.isInteractive?u=yield*s.invokeInteractive(m.actionId,x):u=s.invoke(m.actionId,x),i.directivesApplied+=u.appliedCount,i.directivesSkipped+=u.skippedCount,i.errors+=u.errors.length,r)try{if(l.afterEvent(m.definition,u,D)==="abort")break}catch{}if(u.aborted){w=true,T=u.abortedBy;break}}e.push(...C),j(k,i),E.push({event:p.event,matched:b,skipped:A,notMatched:S,errors:C,halted:w,haltedBy:T,counters:i});}let I={eventResults:E,unprocessedEvents:y,errors:e,counters:k,totalEvents:f.length,processedEvents:E.length};if(o)try{l.onEventsComplete(I);}catch{}return I}}function X(t){let n=t.filledNames.has("beforeEvent"),r=t.filledNames.has("afterEvent"),o=t.filledNames.has("onEventsComplete");return async function*(d,f,g,s,c,l){let E=[],y=[],e=[],k=P(),R=c.length>0;s.setContext(g);for(let p of f){let _=d.get(p.event);if(!_||_.length===0){y.push(p.event);continue}let b=[],A=[],S=[],C=[],i=P(),w=false,T,D={ctx:g,counters:i,event:p.event},L={$event:{type:p.event,data:p.data}};for(let h=0;h<_.length;h++){let m=_[h];if(i.rulesEvaluated++,n)try{let v=await l.beforeEvent(m.definition,D);if(v==="skip"){A.push(h),i.rulesSkipped++;continue}if(v==="abort")break}catch(v){C.push({ruleIndex:h,error:`beforeEvent: ${v}`}),i.errors++;}b.push(h),i.rulesMatched++;let x;if(R)try{x=M(c,m.definition,g,L);}catch(v){C.push({ruleIndex:h,error:`Middleware: ${v}`}),i.errors++;continue}else x=L;let u;if(m.isInteractive?u=yield*s.invokeInteractive(m.actionId,x):m.isAsync?u=await s.invokeAsync(m.actionId,x):u=s.invoke(m.actionId,x),i.directivesApplied+=u.appliedCount,i.directivesSkipped+=u.skippedCount,i.errors+=u.errors.length,r)try{if(await l.afterEvent(m.definition,u,D)==="abort")break}catch{}if(u.aborted){w=true,T=u.abortedBy;break}}e.push(...C),j(k,i),E.push({event:p.event,matched:b,skipped:A,notMatched:S,errors:C,halted:w,haltedBy:T,counters:i});}let I={eventResults:E,unprocessedEvents:y,errors:e,counters:k,totalEvents:f.length,processedEvents:E.length};if(o)try{await l.onEventsComplete(I);}catch{}return I}}function V(t,n){return n?X(t):K(t)}function H(t,n,r){let{filledNames:o,asyncNames:a}=t,d=A=>o.has(A),f=A=>a.has(A)?"await ":"",g=d("beforeEvent"),s=d("afterEvent"),c=d("onEventsComplete"),l=f("beforeEvent"),E=f("afterEvent"),y=f("onEventsComplete"),e=[];e.push("const eventResults=[];"),e.push("const unprocessedEvents=[];"),e.push("const aggErrors=[];"),e.push("const aggCounters={rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0};"),e.push("ae.setContext(ctx);"),c&&e.push("const _hookOnComplete=hooks.onEventsComplete;"),e.push("for(let _ei=0;_ei<events.length;_ei++){"),e.push("const ev=events[_ei];"),e.push("const _evListeners=listenerIndex.get(ev.event);"),e.push("if(!_evListeners||_evListeners.length===0){unprocessedEvents.push(ev.event);continue;}"),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("let halted=false;let haltedBy;"),(g||s)&&e.push("const evalCtx={ctx,counters,event:ev.event};"),g&&e.push("const _hookBefore=hooks.beforeEvent;"),s&&e.push("const _hookAfter=hooks.afterEvent;"),e.push("const _ep={$event:{type:ev.event,data:ev.data}};"),e.push("for(let _ri=0;_ri<_evListeners.length;_ri++){"),e.push("const stored=_evListeners[_ri];"),e.push("counters.rulesEvaluated++;"),g&&(e.push("try{"),e.push(`const _bd=${l}_hookBefore(stored.definition,evalCtx);`),e.push('if(_bd==="skip"){skipped.push(_ri);counters.rulesSkipped++;continue;}'),e.push('if(_bd==="abort"){break;}'),e.push('}catch(_e){errors.push({ruleIndex:_ri,error:"beforeEvent: "+_e});counters.errors++;}')),e.push("matched.push(_ri);counters.rulesMatched++;"),n&&(e.push("let params;"),e.push('try{params=$.runMw(mw,stored.definition,ctx,_ep);}catch(_e){errors.push({ruleIndex:_ri,error:"Middleware: "+_e});counters.errors++;continue;}'));let k=n?"params":"_ep",R=r?`await ae.invokeAsync(stored.actionId,${k})`:`ae.invoke(stored.actionId,${k})`;e.push(`const ir=${R};`),e.push("counters.directivesApplied+=ir.appliedCount;counters.directivesSkipped+=ir.skippedCount;counters.errors+=ir.errors.length;"),s&&(e.push("try{"),e.push(`const _ad=${E}_hookAfter(stored.definition,ir,evalCtx);`),e.push('if(_ad==="abort"){break;}'),e.push("}catch(_e){}")),e.push("if(ir.aborted){halted=true;haltedBy=ir.abortedBy;break;}"),e.push("}"),e.push("aggCounters.rulesEvaluated+=counters.rulesEvaluated;"),e.push("aggCounters.rulesMatched+=counters.rulesMatched;"),e.push("aggCounters.rulesSkipped+=counters.rulesSkipped;"),e.push("aggCounters.directivesApplied+=counters.directivesApplied;"),e.push("aggCounters.directivesSkipped+=counters.directivesSkipped;"),e.push("aggCounters.subRunsCreated+=counters.subRunsCreated;"),e.push("aggCounters.errors+=counters.errors;"),e.push("for(let _k=0;_k<errors.length;_k++)aggErrors.push(errors[_k]);"),e.push("eventResults.push({event:ev.event,matched,skipped,notMatched,errors,halted,haltedBy,counters});"),e.push("}"),e.push("const _r={eventResults,unprocessedEvents,errors:aggErrors,counters:aggCounters,totalEvents:events.length,processedEvents:eventResults.length};"),c&&e.push(`try{${y}_hookOnComplete(_r);}catch(_e){}`),e.push("return _r;");let I=e.join(`
2
+ `),p=r?"async ":"",_=new Function("listenerIndex","events","ctx","ae","mw","hooks","$",`"use strict";
3
3
  return(${p}()=>{
4
- ${A}
5
- })();`),x={};return s&&(x.runMw=M),function(S,C,c,k,T,D){return y(S,C,c,k,T,D,x)}}function V(e){return !e.event||typeof e.event!="string"?{event:e.event??"(missing)",code:"INVALID_DEFINITION",message:"event definition must have a non-empty string event name"}:e.tags!==void 0&&!Array.isArray(e.tags)?{event:e.event,code:"INVALID_DEFINITION",message:"event definition tags must be an array of strings"}:e.tier!==void 0&&typeof e.tier!="number"?{event:e.event,code:"INVALID_DEFINITION",message:"event definition tier must be a number"}:null}function j(e){if(!e.id||typeof e.id!="string")return {listenerId:e.id??"(missing)",code:"INVALID_LISTENER",message:"listener must have a string id"};if(typeof e.priority!="number")return {listenerId:e.id,code:"INVALID_LISTENER",message:"listener must have a numeric priority"};if(typeof e.on=="string"){if(!e.on)return {listenerId:e.id,code:"INVALID_LISTENER",message:"listener.on must be a non-empty string or string[]"}}else if(Array.isArray(e.on)){if(e.on.length===0||e.on.some(s=>typeof s!="string"||!s))return {listenerId:e.id,code:"INVALID_LISTENER",message:"listener.on must be a non-empty string or string[] of non-empty strings"}}else return {listenerId:e.id,code:"INVALID_LISTENER",message:"listener.on must be a string or string[]"};return !Array.isArray(e.then)||e.then.length===0?{listenerId:e.id,code:"INVALID_LISTENER",message:"listener must have a non-empty then array"}:null}function H(e,s){let r=0,i=e.length;for(;r<i;){let o=r+i>>>1;e[o].priority>=s.priority?r=o+1:i=o;}e.splice(r,0,s);}function W(e,s){let r=e.indexOf(s);return r===-1?false:(e.splice(r,1),true)}var P=()=>{},$=class{_actionEngine;_middleware;_eventHooks;_isAsync;_requestedMode;_hookAnalysis;_dispatcher;_mode;_maybeAutoPromote;_eventDefinitions=new Map;_listenerRegistry=new Map;_listenerIndex=new Map;_batch=null;constructor(s){if(this._actionEngine=s.actionEngine,this._middleware=s.middleware??[],this._eventHooks=s.eventHooks??{},this._requestedMode=s.mode??"auto",this._hookAnalysis=analyzeSlots(this._eventHooks,EVENT_SLOT_NAMES),this._isAsync=this._hookAnalysis.hasAnyAsync||this._actionEngine.isAsync,this._requestedMode==="jit")this._dispatcher=this._buildJit(),this._mode="jit",this._maybeAutoPromote=P;else if(this._dispatcher=B(this._hookAnalysis,this._isAsync),this._mode="interpret",this._requestedMode==="auto"){let r=0,i=s.autoJitThreshold??8;this._maybeAutoPromote=()=>{++r>=i&&this._promote();};}else this._maybeAutoPromote=P;}get actionEngine(){return this._actionEngine}get isAsync(){return this._isAsync}get compilationMode(){return this._mode}get eventDefinitions(){return this._eventDefinitions}getEventDefinition(s){return this._eventDefinitions.get(s)}defineEvents(s){let r=[],i=[],o=[];for(let n of s){let a=V(n);if(a){i.push(a);continue}if(this._eventDefinitions.has(n.event)){i.push({event:n.event,code:"DUPLICATE_EVENT",message:`event definition "${n.event}" is already registered`});continue}this._eventDefinitions.set(n.event,n);let u=["eventdef"];n.tags&&u.push(...n.tags),o.push({id:`eventdef:${n.event}`,directives:[],tags:u,declarations:n.declarations,tier:n.tier,metadata:{...n.schema!==void 0&&{schema:n.schema},...n.description!==void 0&&{description:n.description}}}),r.push(n.event);}let d=[];if(o.length>0){let n=this._actionEngine.register(o);for(let a of n.errors){let u=this._actionIdToEventName(a.actionId);i.push({event:u??a.actionId,code:a.code??"ACTION_ERROR",message:a.error});}d=n.warnings;}let g={defined:r,errors:i,warnings:d};return this._batch&&(this._batch.definedEvents.push(...r),this._batch.defineErrors.push(...i),this._batch.warnings.push(...d)),g}register(s){let r=[],i=[],o=[],d=[];for(let n of s){let a=j(n);if(a){i.push(a);continue}if(this._listenerRegistry.has(n.id)){i.push({listenerId:n.id,code:"DUPLICATE_ID",message:`listener "${n.id}" is already registered`});continue}let u=typeof n.on=="string"?[n.on]:n.on,m=false;for(let l of u){let h=this._eventDefinitions.get(l);if(!h){o.push({actionId:`event:${n.id}`,code:"NO_EVENT_DEFINITION",message:`listener "${n.id}" listens to "${l}" but no event definition is registered for it`});continue}h.tier!==void 0&&n.declarations?.tier!==void 0&&n.declarations.tier<h.tier&&(i.push({listenerId:n.id,code:"TIER_VIOLATION",message:`listener "${n.id}" declares tier ${n.declarations.tier} but event "${l}" requires tier >= ${h.tier}`}),m=true);}if(m)continue;let _=`event:${n.id}`,b={definition:n,actionId:_,priority:n.priority};this._listenerRegistry.set(n.id,b);for(let l of u){let h=this._listenerIndex.get(l);h||(h=[],this._listenerIndex.set(l,h)),H(h,b);}let t=["event"];n.tags&&t.push(...n.tags),d.push({id:_,tags:t,directives:n.then,declarations:n.declarations}),r.push(n.id);}if(d.length>0){let n=this._actionEngine.register(d);for(let a of n.errors){let u=this._actionIdToListenerId(a.actionId);i.push({listenerId:u??a.actionId,code:a.code??"ACTION_ERROR",message:a.error});}o.push(...n.warnings);}let g={registered:r,errors:i,warnings:o};return this._batch&&(this._batch.registered.push(...r),this._batch.errors.push(...i),this._batch.warnings.push(...o)),g}unregister(s){let r=this._listenerRegistry.get(s);if(!r)return false;this._listenerRegistry.delete(s);let i=typeof r.definition.on=="string"?[r.definition.on]:r.definition.on;for(let o of i){let d=this._listenerIndex.get(o);d&&(W(d,r),d.length===0&&this._listenerIndex.delete(o));}return this._actionEngine.unregister(r.actionId),true}processEvents(s,r){if(this._isAsync)throw new Error("Cannot call processEvents() with async hooks. Use processEventsAsync() instead.");let i=this._dispatcher(this._listenerIndex,s,r,this._actionEngine,this._middleware,this._eventHooks);return this._maybeAutoPromote(),i}async processEventsAsync(s,r){let i=await this._dispatcher(this._listenerIndex,s,r,this._actionEngine,this._middleware,this._eventHooks);return this._maybeAutoPromote(),i}beginBatch(){this._batch||(this._batch={depth:0,registered:[],errors:[],warnings:[],definedEvents:[],defineErrors:[]}),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 s=this._actionEngine.endBatch();if(this._batch.depth>0)return {registered:[],errors:[],warnings:[]};let r=this._batch;for(let o of s.errors){let d=this._actionIdToListenerId(o.actionId);r.errors.push({listenerId:d??o.actionId,code:o.code??"ACTION_ERROR",message:o.error});}r.warnings.push(...s.warnings);let i={registered:r.registered,errors:r.errors,warnings:r.warnings};return this._batch=null,i}compile(){this._requestedMode!=="interpret"&&this._mode!=="jit"&&this._promote();}_promote(){this._dispatcher=this._buildJit(),this._mode="jit",this._maybeAutoPromote=P;}_buildJit(){return F(this._hookAnalysis,this._middleware.length>0,this._isAsync)}_actionIdToListenerId(s){return s.startsWith("event:")?s.slice(6):null}_actionIdToEventName(s){return s.startsWith("eventdef:")?s.slice(9):null}};function z(e){return new $(e)}function re(e="event"){return s=>{let r=s[e],i=typeof r=="string"&&r?[`eventdef:${r}`]:[];return {capabilities:["emit"],dependencies:i}}}export{re as createEmitAnalyzer,z as createEventProcessor};
4
+ ${I}
5
+ })();`),b={};return n&&(b.runMw=M),function(S,C,i,w,T,D){return _(S,C,i,w,T,D,b)}}function Q(t,n,r){let{filledNames:o,asyncNames:a}=t,d=b=>o.has(b),f=b=>a.has(b)?"await ":"",g=d("beforeEvent"),s=d("afterEvent"),c=d("onEventsComplete"),l=f("beforeEvent"),E=f("afterEvent"),y=f("onEventsComplete"),e=[];e.push("const eventResults=[];"),e.push("const unprocessedEvents=[];"),e.push("const aggErrors=[];"),e.push("const aggCounters={rulesEvaluated:0,rulesMatched:0,rulesSkipped:0,directivesApplied:0,directivesSkipped:0,subRunsCreated:0,errors:0};"),e.push("ae.setContext(ctx);"),c&&e.push("const _hookOnComplete=hooks.onEventsComplete;"),e.push("for(let _ei=0;_ei<events.length;_ei++){"),e.push("const ev=events[_ei];"),e.push("const _evListeners=listenerIndex.get(ev.event);"),e.push("if(!_evListeners||_evListeners.length===0){unprocessedEvents.push(ev.event);continue;}"),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("let halted=false;let haltedBy;"),(g||s)&&e.push("const evalCtx={ctx,counters,event:ev.event};"),g&&e.push("const _hookBefore=hooks.beforeEvent;"),s&&e.push("const _hookAfter=hooks.afterEvent;"),e.push("const _ep={$event:{type:ev.event,data:ev.data}};"),e.push("for(let _ri=0;_ri<_evListeners.length;_ri++){"),e.push("const stored=_evListeners[_ri];"),e.push("counters.rulesEvaluated++;"),g&&(e.push("try{"),e.push(`const _bd=${l}_hookBefore(stored.definition,evalCtx);`),e.push('if(_bd==="skip"){skipped.push(_ri);counters.rulesSkipped++;continue;}'),e.push('if(_bd==="abort"){break;}'),e.push('}catch(_e){errors.push({ruleIndex:_ri,error:"beforeEvent: "+_e});counters.errors++;}')),e.push("matched.push(_ri);counters.rulesMatched++;"),n&&(e.push("let params;"),e.push('try{params=$.runMw(mw,stored.definition,ctx,_ep);}catch(_e){errors.push({ruleIndex:_ri,error:"Middleware: "+_e});counters.errors++;continue;}'));let k=n?"params":"_ep";e.push("let ir;"),e.push("if(stored.isInteractive){"),e.push(`ir=yield* ae.invokeInteractive(stored.actionId,${k});`),r&&(e.push("}else if(stored.isAsync){"),e.push(`ir=await ae.invokeAsync(stored.actionId,${k});`)),e.push("}else{"),e.push(`ir=ae.invoke(stored.actionId,${k});`),e.push("}"),e.push("counters.directivesApplied+=ir.appliedCount;counters.directivesSkipped+=ir.skippedCount;counters.errors+=ir.errors.length;"),s&&(e.push("try{"),e.push(`const _ad=${E}_hookAfter(stored.definition,ir,evalCtx);`),e.push('if(_ad==="abort"){break;}'),e.push("}catch(_e){}")),e.push("if(ir.aborted){halted=true;haltedBy=ir.abortedBy;break;}"),e.push("}"),e.push("aggCounters.rulesEvaluated+=counters.rulesEvaluated;"),e.push("aggCounters.rulesMatched+=counters.rulesMatched;"),e.push("aggCounters.rulesSkipped+=counters.rulesSkipped;"),e.push("aggCounters.directivesApplied+=counters.directivesApplied;"),e.push("aggCounters.directivesSkipped+=counters.directivesSkipped;"),e.push("aggCounters.subRunsCreated+=counters.subRunsCreated;"),e.push("aggCounters.errors+=counters.errors;"),e.push("for(let _k=0;_k<errors.length;_k++)aggErrors.push(errors[_k]);"),e.push("eventResults.push({event:ev.event,matched,skipped,notMatched,errors,halted,haltedBy,counters});"),e.push("}"),e.push("const _r={eventResults,unprocessedEvents,errors:aggErrors,counters:aggCounters,totalEvents:events.length,processedEvents:eventResults.length};"),c&&e.push(`try{${y}_hookOnComplete(_r);}catch(_e){}`),e.push("return _r;");let R=e.join(`
6
+ `),I=r?"async function* ":"function* ",p=new Function("listenerIndex","events","ctx","ae","mw","hooks","$",`"use strict";
7
+ return(${I}(){
8
+ ${R}
9
+ })();`),_={};return n&&(_.runMw=M),function(A,S,C,i,w,T){return p(A,S,C,i,w,T,_)}}function W(t){return !t.event||typeof t.event!="string"?{event:t.event??"(missing)",code:"INVALID_DEFINITION",message:"event definition must have a non-empty string event name"}:t.tags!==void 0&&!Array.isArray(t.tags)?{event:t.event,code:"INVALID_DEFINITION",message:"event definition tags must be an array of strings"}:t.tier!==void 0&&typeof t.tier!="number"?{event:t.event,code:"INVALID_DEFINITION",message:"event definition tier must be a number"}:null}function G(t){if(!t.id||typeof t.id!="string")return {listenerId:t.id??"(missing)",code:"INVALID_LISTENER",message:"listener must have a string id"};if(typeof t.priority!="number")return {listenerId:t.id,code:"INVALID_LISTENER",message:"listener must have a numeric priority"};if(typeof t.on=="string"){if(!t.on)return {listenerId:t.id,code:"INVALID_LISTENER",message:"listener.on must be a non-empty string or string[]"}}else if(Array.isArray(t.on)){if(t.on.length===0||t.on.some(n=>typeof n!="string"||!n))return {listenerId:t.id,code:"INVALID_LISTENER",message:"listener.on must be a non-empty string or string[] of non-empty strings"}}else return {listenerId:t.id,code:"INVALID_LISTENER",message:"listener.on must be a string or string[]"};return !Array.isArray(t.then)||t.then.length===0?{listenerId:t.id,code:"INVALID_LISTENER",message:"listener must have a non-empty then array"}:null}function q(t,n){let r=0,o=t.length;for(;r<o;){let a=r+o>>>1;t[a].priority>=n.priority?r=a+1:o=a;}t.splice(r,0,n);}function U(t,n){let r=t.indexOf(n);return r===-1?false:(t.splice(r,1),true)}var F=()=>{},B=class{_actionEngine;_middleware;_eventHooks;_requestedMode;_hookAnalysis;_isAsync;_hasAnyInteractiveListener=false;_dispatcher;_mode;_maybeAutoPromote;_interactiveDispatcher=null;_interactiveDispatcherIsAsync=false;_eventDefinitions=new Map;_listenerRegistry=new Map;_listenerIndex=new Map;_batch=null;constructor(n){if(this._actionEngine=n.actionEngine,this._middleware=n.middleware??[],this._eventHooks=n.eventHooks??{},this._requestedMode=n.mode??"auto",this._hookAnalysis=analyzeSlots(this._eventHooks,EVENT_SLOT_NAMES),this._isAsync=this._hookAnalysis.hasAnyAsync,this._requestedMode==="jit")this._dispatcher=this._buildJit(),this._mode="jit",this._maybeAutoPromote=F;else if(this._dispatcher=$(this._hookAnalysis,this._isAsync),this._mode="interpret",this._requestedMode==="auto"){let r=0,o=n.autoJitThreshold??8;this._maybeAutoPromote=()=>{++r>=o&&this._promote();};}else this._maybeAutoPromote=F;}get actionEngine(){return this._actionEngine}get isAsync(){return this._isAsync}get isInteractive(){return this._hasAnyInteractiveListener}get compilationMode(){return this._mode}get eventDefinitions(){return this._eventDefinitions}getEventDefinition(n){return this._eventDefinitions.get(n)}defineEvents(n){let r=[],o=[],a=[];for(let s of n){let c=W(s);if(c){r.push(c);continue}if(this._eventDefinitions.has(s.event)||a.some(E=>E.name===s.event)){r.push({event:s.event,code:"DUPLICATE_EVENT",message:`event definition "${s.event}" is already registered`});continue}let l=["eventdef"];s.tags&&l.push(...s.tags),o.push({id:`eventdef:${s.event}`,directives:[],tags:l,declarations:s.declarations,tier:s.tier,metadata:{...s.schema!==void 0&&{schema:s.schema},...s.description!==void 0&&{description:s.description}}}),a.push({name:s.event,def:s});}let d=[];if(o.length>0){let s=this._actionEngine.register(o);for(let c of s.errors){let l=this._actionIdToEventName(c.actionId);r.push({event:l??c.actionId,code:c.code??"ACTION_ERROR",message:c.error});}d=s.warnings;}let f=[];for(let{name:s,def:c}of a)this._eventDefinitions.set(s,c),f.push(s);let g={defined:f,errors:r,warnings:d};return this._batch&&(this._batch.definedEvents.push(...f),this._batch.defineErrors.push(...r),this._batch.warnings.push(...d)),g}register(n){let r=[],o=[],a=[],d=[];for(let s of n){let c=G(s);if(c){r.push(c);continue}if(this._listenerRegistry.has(s.id)||d.some(R=>R.id===s.id)){r.push({listenerId:s.id,code:"DUPLICATE_ID",message:`listener "${s.id}" is already registered`});continue}let l=typeof s.on=="string"?[s.on]:s.on,E=false;for(let R of l){let I=this._eventDefinitions.get(R);if(!I){o.push({actionId:`event:${s.id}`,code:"NO_EVENT_DEFINITION",message:`listener "${s.id}" listens to "${R}" but no event definition is registered for it`});continue}I.tier!==void 0&&s.declarations?.tier!==void 0&&s.declarations.tier<I.tier&&(r.push({listenerId:s.id,code:"TIER_VIOLATION",message:`listener "${s.id}" declares tier ${s.declarations.tier} but event "${R}" requires tier >= ${I.tier}`}),E=true);}if(E)continue;let y=`event:${s.id}`,e={definition:s,actionId:y,priority:s.priority,isAsync:false,isInteractive:false},k=["event"];s.tags&&k.push(...s.tags),a.push({id:y,tags:k,directives:s.then,declarations:s.declarations}),d.push({id:s.id,stored:e,eventNames:l});}if(a.length>0){let s=this._actionEngine.register(a);for(let c of s.errors){let l=this._actionIdToListenerId(c.actionId);r.push({listenerId:l??c.actionId,code:c.code??"ACTION_ERROR",message:c.error});}o.push(...s.warnings);}let f=[];for(let{id:s,stored:c,eventNames:l}of d){this._listenerRegistry.set(s,c);for(let E of l){let y=this._listenerIndex.get(E);y||(y=[],this._listenerIndex.set(E,y)),q(y,c);}f.push(s);}let g={registered:f,errors:r,warnings:o};return this._batch?(this._batch.registered.push(...f),this._batch.errors.push(...r),this._batch.warnings.push(...o)):f.length>0&&this._refreshListenerFlags(),g}unregister(n){let r=this._listenerRegistry.get(n);if(!r)return false;this._listenerRegistry.delete(n);let o=typeof r.definition.on=="string"?[r.definition.on]:r.definition.on;for(let a of o){let d=this._listenerIndex.get(a);d&&(U(d,r),d.length===0&&this._listenerIndex.delete(a));}return this._actionEngine.unregister(r.actionId),this._refreshListenerFlags(),true}processEvents(n,r){if(this._hasAnyInteractiveListener)throw new Error("Cannot call processEvents() \u2014 at least one listener is interactive (transitively). Use processEventsInteractive() instead.");if(this._isAsync)throw new Error("Cannot call processEvents() with async hooks or async listeners. Use processEventsAsync() instead.");let o=this._dispatcher(this._listenerIndex,n,r,this._actionEngine,this._middleware,this._eventHooks);return this._maybeAutoPromote(),o}async processEventsAsync(n,r){if(this._hasAnyInteractiveListener)throw new Error("Cannot call processEventsAsync() \u2014 at least one listener is interactive (transitively). Use processEventsInteractive() instead.");let o=await this._dispatcher(this._listenerIndex,n,r,this._actionEngine,this._middleware,this._eventHooks);return this._maybeAutoPromote(),o}processEventsInteractive(n,r){if(!this._hasAnyInteractiveListener)throw new Error("Cannot call processEventsInteractive() \u2014 no registered listener is interactive (transitively). Use processEvents() or processEventsAsync() instead.");return (this._interactiveDispatcher===null||this._interactiveDispatcherIsAsync!==this._isAsync)&&(this._interactiveDispatcher=this._mode==="jit"?Q(this._hookAnalysis,this._middleware.length>0,this._isAsync):V(this._hookAnalysis,this._isAsync),this._interactiveDispatcherIsAsync=this._isAsync),this._interactiveDispatcher(this._listenerIndex,n,r,this._actionEngine,this._middleware,this._eventHooks)}beginBatch(){this._batch||(this._batch={depth:0,registered:[],errors:[],warnings:[],definedEvents:[],defineErrors:[]}),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 n=this._actionEngine.endBatch();if(this._batch.depth>0)return {registered:[],errors:[],warnings:[]};let r=this._batch;for(let a of n.errors){let d=this._actionIdToListenerId(a.actionId);r.errors.push({listenerId:d??a.actionId,code:a.code??"ACTION_ERROR",message:a.error});}r.warnings.push(...n.warnings);let o={registered:r.registered,errors:r.errors,warnings:r.warnings};return this._batch=null,this._refreshListenerFlags(),o}compile(){this._requestedMode!=="interpret"&&this._mode!=="jit"&&this._promote();}_promote(){this._dispatcher=this._buildJit(),this._mode="jit",this._maybeAutoPromote=F,this._interactiveDispatcher=null;}_buildJit(){return H(this._hookAnalysis,this._middleware.length>0,this._isAsync)}_refreshListenerFlags(){let n=false,r=false;for(let a of this._listenerRegistry.values())a.isAsync=this._actionEngine.isActionAsync(a.actionId)??false,a.isInteractive=this._actionEngine.isActionInteractive?.(a.actionId)??false,a.isAsync&&(n=true),a.isInteractive&&(r=true);this._hasAnyInteractiveListener=r;let o=this._hookAnalysis.hasAnyAsync||n;o!==this._isAsync&&(this._isAsync=o,this._rebuildDispatcher());}_rebuildDispatcher(){this._dispatcher=this._mode==="jit"?this._buildJit():$(this._hookAnalysis,this._isAsync);}_actionIdToListenerId(n){return n.startsWith("event:")?n.slice(6):null}_actionIdToEventName(n){return n.startsWith("eventdef:")?n.slice(9):null}};function ee(t){return new B(t)}function he(t="event"){return n=>{let r=n[t],o=typeof r=="string"&&r?[`eventdef:${r}`]:[];return {capabilities:["emit"],dependencies:o}}}export{he as createEmitAnalyzer,ee as createEventProcessor};
package/package.json CHANGED
@@ -1,7 +1,14 @@
1
1
  {
2
2
  "name": "@statedelta-actions/events",
3
- "version": "0.3.0",
3
+ "version": "0.5.1",
4
4
  "description": "Event processing engine with listener dispatch and JIT optimization",
5
+ "keywords": [
6
+ "statedelta",
7
+ "event-processing",
8
+ "listeners",
9
+ "jit",
10
+ "event-driven"
11
+ ],
5
12
  "type": "module",
6
13
  "main": "./dist/index.cjs",
7
14
  "module": "./dist/index.js",
@@ -15,15 +22,16 @@
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/core": "0.3.0",
22
- "@statedelta-actions/actions": "0.3.0"
29
+ "@statedelta-actions/actions": "0.6.0",
30
+ "@statedelta-actions/core": "0.5.1"
23
31
  },
24
32
  "devDependencies": {
25
- "@statedelta-actions/analyzer": "0.3.0",
26
- "@statedelta-actions/graph": "0.3.0"
33
+ "@statedelta-actions/graph": "0.4.2",
34
+ "@statedelta-actions/analyzer": "0.4.2"
27
35
  },
28
36
  "author": "Anderson D. Rosa <andersondrosa@outlook.com>",
29
37
  "license": "MIT",
@@ -32,6 +40,10 @@
32
40
  "url": "https://github.com/andersondrosa/statedelta-actions.git",
33
41
  "directory": "packages/events"
34
42
  },
43
+ "homepage": "https://github.com/andersondrosa/statedelta-actions/tree/main/packages/events#readme",
44
+ "bugs": {
45
+ "url": "https://github.com/andersondrosa/statedelta-actions/issues"
46
+ },
35
47
  "sideEffects": false,
36
48
  "engines": {
37
49
  "node": ">=18"