@nwire/app 0.8.17 → 0.9.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.
@@ -5,25 +5,29 @@
5
5
  * and modules subscribe with `bus.on(Event, handler)`; the runtime fires
6
6
  * events at the appropriate lifecycle points with `bus.fire(Event, payload)`.
7
7
  *
8
- * Dispatch semantics come from the event's `mode`:
8
+ * Internals: every event delegates to a `hook<TPayload>(name)` from
9
+ * `@nwire/hooks`. Subscribers attach as hook chain steps (series /
10
+ * series-bail) or hook listeners (parallel). Dispatch is `hook.run()` —
11
+ * no parallel subscription map. Telemetry, replay, .tap observation,
12
+ * cancellation all come from hooks substrate by construction.
9
13
  *
10
- * parallel → all handlers concurrently; one failing doesn't affect
11
- * others; errors are logged via the supplied logger.
12
- * series → sequential await; one failing stops the chain and throws.
13
- * series-bail → sequential await; a handler returning `false` stops the
14
- * chain cleanly (no throw) and `fire` returns false to
15
- * signal "prevented". Returning anything else (including
16
- * undefined/void) is treated as "ok, continue".
14
+ * Dispatch semantics come from the event's `mode`:
17
15
  *
18
- * The series-bail mode is the interceptable hook `*-ing` events use it
19
- * so plugins can veto an action, refuse a shutdown, etc.
16
+ * parallel → handlers fire as hook listeners (Promise.allSettled);
17
+ * one failing doesn't affect others; errors are logged.
18
+ * series → handlers fire as chain steps in priority order;
19
+ * one throwing stops the chain.
20
+ * series-bail → handlers fire as chain steps in priority order;
21
+ * returning `false` short-circuits (don't call next()).
22
+ * `fire()` returns false to signal "prevented".
20
23
  *
21
24
  * The bus lives in `@nwire/app` (the "managed Container with lifecycle"
22
25
  * layer). `@nwire/forge` re-exports the same surface so consumers that
23
26
  * pull from forge get one import line.
24
27
  */
25
- import type { FrameworkEventDefinition } from "./framework-events.js";
28
+ import { type Hook } from "@nwire/hooks";
26
29
  import type { Logger } from "@nwire/logger";
30
+ import type { FrameworkEventDefinition } from "./framework-events.js";
27
31
  /**
28
32
  * Handler signature. The handler MAY:
29
33
  * - return nothing → "continue"
@@ -56,18 +60,14 @@ export type FrameworkEventObserver = (record: FrameworkEventObservation) => void
56
60
  * focused on the domain pipeline. Designed to be reusable — Studio, the
57
61
  * orchestrator, and external plugins all hit the same surface.
58
62
  */
59
- import { type Hook } from "@nwire/hooks";
60
63
  export declare class FrameworkEventBus {
61
- private readonly subs;
62
64
  private readonly observers;
63
65
  private readonly logger;
64
66
  /**
65
- * One hook per event name, lazily created on first `fire()`. Each hook has
66
- * a single no-op chain step named "dispatch" so every fire emits start +
67
- * end taps under `framework.event:<eventName>`. The dispatch logic in
68
- * `fire()` is unchanged these hooks are an observation surface so
69
- * `listHooks()` + scan + Studio see every framework event in the
70
- * registry, not a replacement for the existing dispatcher.
67
+ * One hook per event name. Each event's subscribers attach as chain
68
+ * steps (series / series-bail) or listeners (parallel) on its hook;
69
+ * dispatch is `hook.run()`. `listHooks()` + scan + Studio see every
70
+ * framework event in the registry by construction.
71
71
  *
72
72
  * Runtime can pass an `adoptHook` callback in the constructor; each
73
73
  * lazily-created hook is adopted so taps flow into the canonical
@@ -87,7 +87,7 @@ export declare class FrameworkEventBus {
87
87
  readonly name: string;
88
88
  }>;
89
89
  });
90
- /** Lazily create + adopt the per-event hook. Called from `fire()`. */
90
+ /** Lazily create + adopt the per-event hook. Bus dispatches through these. */
91
91
  private ensureEventHook;
92
92
  /**
93
93
  * Subscribe to EVERY framework-event firing on this bus. Used by the
@@ -103,15 +103,27 @@ export declare class FrameworkEventBus {
103
103
  * series-bail / series modes (higher runs first; default 0). Framework
104
104
  * built-ins should subscribe at priority 100+; debug/observer plugins
105
105
  * at -100 so they see the final post-mutation state.
106
+ *
107
+ * Attaches to the per-event hook: as a listener (parallel mode) or as
108
+ * a chain step (series / series-bail). The returned handle calls
109
+ * `hook.off()` to detach.
106
110
  */
107
111
  on<TPayload>(event: FrameworkEventDefinition<TPayload>, handler: FrameworkEventHandler<TPayload>, priority?: number): () => void;
108
112
  /**
109
113
  * Fire a framework event. Resolves to `false` when a series-bail handler
110
114
  * vetoed; `true` otherwise. The boolean is irrelevant for parallel /
111
- * series modes and always returns `true` there for them.
115
+ * series modes and always returns `true` there.
116
+ *
117
+ * Internally: delegates to the per-event hook's `.run()` (parallel /
118
+ * series) or `.runDetailed()` (series-bail, to detect "prevented"
119
+ * outcome from short-circuit). The hook's observability surface (.tap,
120
+ * StepObservation) lights up automatically.
112
121
  */
113
122
  fire<TPayload>(event: FrameworkEventDefinition<TPayload>, payload: TPayload): Promise<boolean>;
114
- /** Count subscribers for an event — diagnostic surface (Studio, tests). */
123
+ /**
124
+ * Count subscribers for an event — diagnostic surface (Studio, tests).
125
+ * Sums chain steps and listeners attached to the per-event hook.
126
+ */
115
127
  subscriberCount(event: FrameworkEventDefinition): number;
116
128
  }
117
129
  //# sourceMappingURL=framework-event-bus.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"framework-event-bus.d.ts","sourceRoot":"","sources":["../src/framework-event-bus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,CAAC,QAAQ,IAAI,CAC5C,OAAO,EAAE,QAAQ,KACd,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC;AAO9C;;;;;;;GAOG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,aAAa,CAAC;IACrD,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAAC;IACtC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,MAAM,sBAAsB,GAAG,CAAC,MAAM,EAAE,yBAAyB,KAAK,IAAI,CAAC;AAEjF;;;;GAIG;AACH,OAAO,EAAQ,KAAK,IAAI,EAAE,MAAM,cAAc,CAAC;AAE/C,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA8C;IACnE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoC;IAC/D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAA6B;gBAGtD,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;QACP,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;QACvC;;;;;WAKG;QACH,MAAM,CAAC,EAAE,aAAa,CAAC;YAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC9C;IASR,sEAAsE;IACtE,OAAO,CAAC,eAAe;IAevB;;;;;;OAMG;IACH,MAAM,CAAC,QAAQ,EAAE,sBAAsB,GAAG,MAAM,IAAI;IAQpD,OAAO,CAAC,MAAM;IAgBd;;;;;OAKG;IACH,EAAE,CAAC,QAAQ,EACT,KAAK,EAAE,wBAAwB,CAAC,QAAQ,CAAC,EACzC,OAAO,EAAE,qBAAqB,CAAC,QAAQ,CAAC,EACxC,QAAQ,GAAE,MAAU,GACnB,MAAM,IAAI;IAgBb;;;;OAIG;IACG,IAAI,CAAC,QAAQ,EACjB,KAAK,EAAE,wBAAwB,CAAC,QAAQ,CAAC,EACzC,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,OAAO,CAAC;IAmEnB,2EAA2E;IAC3E,eAAe,CAAC,KAAK,EAAE,wBAAwB,GAAG,MAAM;CAGzD"}
1
+ {"version":3,"file":"framework-event-bus.d.ts","sourceRoot":"","sources":["../src/framework-event-bus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAQ,KAAK,IAAI,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAEnE;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,CAAC,QAAQ,IAAI,CAC5C,OAAO,EAAE,QAAQ,KACd,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC;AAE9C;;;;;;;GAOG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,aAAa,CAAC;IACrD,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAAC;IACtC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,MAAM,sBAAsB,GAAG,CAAC,MAAM,EAAE,yBAAyB,KAAK,IAAI,CAAC;AAEjF;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;;;;;;;;OASG;IACH,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoC;IAC/D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAA6B;gBAGtD,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;QACP,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;QACvC;;;;;WAKG;QACH,MAAM,CAAC,EAAE,aAAa,CAAC;YAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC9C;IASR,8EAA8E;IAC9E,OAAO,CAAC,eAAe;IASvB;;;;;;OAMG;IACH,MAAM,CAAC,QAAQ,EAAE,sBAAsB,GAAG,MAAM,IAAI;IAQpD,OAAO,CAAC,MAAM;IAgBd;;;;;;;;;OASG;IACH,EAAE,CAAC,QAAQ,EACT,KAAK,EAAE,wBAAwB,CAAC,QAAQ,CAAC,EACzC,OAAO,EAAE,qBAAqB,CAAC,QAAQ,CAAC,EACxC,QAAQ,GAAE,MAAU,GACnB,MAAM,IAAI;IAiCb;;;;;;;;;OASG;IACG,IAAI,CAAC,QAAQ,EACjB,KAAK,EAAE,wBAAwB,CAAC,QAAQ,CAAC,EACzC,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,OAAO,CAAC;IAgCnB;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE,wBAAwB,GAAG,MAAM;CAMzD"}
@@ -5,40 +5,40 @@
5
5
  * and modules subscribe with `bus.on(Event, handler)`; the runtime fires
6
6
  * events at the appropriate lifecycle points with `bus.fire(Event, payload)`.
7
7
  *
8
- * Dispatch semantics come from the event's `mode`:
8
+ * Internals: every event delegates to a `hook<TPayload>(name)` from
9
+ * `@nwire/hooks`. Subscribers attach as hook chain steps (series /
10
+ * series-bail) or hook listeners (parallel). Dispatch is `hook.run()` —
11
+ * no parallel subscription map. Telemetry, replay, .tap observation,
12
+ * cancellation all come from hooks substrate by construction.
9
13
  *
10
- * parallel → all handlers concurrently; one failing doesn't affect
11
- * others; errors are logged via the supplied logger.
12
- * series → sequential await; one failing stops the chain and throws.
13
- * series-bail → sequential await; a handler returning `false` stops the
14
- * chain cleanly (no throw) and `fire` returns false to
15
- * signal "prevented". Returning anything else (including
16
- * undefined/void) is treated as "ok, continue".
14
+ * Dispatch semantics come from the event's `mode`:
17
15
  *
18
- * The series-bail mode is the interceptable hook `*-ing` events use it
19
- * so plugins can veto an action, refuse a shutdown, etc.
16
+ * parallel → handlers fire as hook listeners (Promise.allSettled);
17
+ * one failing doesn't affect others; errors are logged.
18
+ * series → handlers fire as chain steps in priority order;
19
+ * one throwing stops the chain.
20
+ * series-bail → handlers fire as chain steps in priority order;
21
+ * returning `false` short-circuits (don't call next()).
22
+ * `fire()` returns false to signal "prevented".
20
23
  *
21
24
  * The bus lives in `@nwire/app` (the "managed Container with lifecycle"
22
25
  * layer). `@nwire/forge` re-exports the same surface so consumers that
23
26
  * pull from forge get one import line.
24
27
  */
28
+ import { hook } from "@nwire/hooks";
25
29
  /**
26
30
  * The bus. Subscriptions and dispatch live here so an app's runtime stays
27
31
  * focused on the domain pipeline. Designed to be reusable — Studio, the
28
32
  * orchestrator, and external plugins all hit the same surface.
29
33
  */
30
- import { hook } from "@nwire/hooks";
31
34
  export class FrameworkEventBus {
32
- subs = new Map();
33
35
  observers = [];
34
36
  logger;
35
37
  /**
36
- * One hook per event name, lazily created on first `fire()`. Each hook has
37
- * a single no-op chain step named "dispatch" so every fire emits start +
38
- * end taps under `framework.event:<eventName>`. The dispatch logic in
39
- * `fire()` is unchanged these hooks are an observation surface so
40
- * `listHooks()` + scan + Studio see every framework event in the
41
- * registry, not a replacement for the existing dispatcher.
38
+ * One hook per event name. Each event's subscribers attach as chain
39
+ * steps (series / series-bail) or listeners (parallel) on its hook;
40
+ * dispatch is `hook.run()`. `listHooks()` + scan + Studio see every
41
+ * framework event in the registry by construction.
42
42
  *
43
43
  * Runtime can pass an `adoptHook` callback in the constructor; each
44
44
  * lazily-created hook is adopted so taps flow into the canonical
@@ -53,15 +53,12 @@ export class FrameworkEventBus {
53
53
  this.ensureEventHook(event.name);
54
54
  }
55
55
  }
56
- /** Lazily create + adopt the per-event hook. Called from `fire()`. */
56
+ /** Lazily create + adopt the per-event hook. Bus dispatches through these. */
57
57
  ensureEventHook(eventName) {
58
58
  let h = this.eventHooks.get(eventName);
59
59
  if (h)
60
60
  return h;
61
61
  h = hook(`framework.event:${eventName}`);
62
- h.use(async (_, next) => {
63
- await next();
64
- }, { name: "dispatch" });
65
62
  this.eventHooks.set(eventName, h);
66
63
  this.adoptHook?.(h);
67
64
  return h;
@@ -102,38 +99,54 @@ export class FrameworkEventBus {
102
99
  * series-bail / series modes (higher runs first; default 0). Framework
103
100
  * built-ins should subscribe at priority 100+; debug/observer plugins
104
101
  * at -100 so they see the final post-mutation state.
102
+ *
103
+ * Attaches to the per-event hook: as a listener (parallel mode) or as
104
+ * a chain step (series / series-bail). The returned handle calls
105
+ * `hook.off()` to detach.
105
106
  */
106
107
  on(event, handler, priority = 0) {
107
- const list = this.subs.get(event.name) ?? [];
108
- const sub = { handler, priority };
109
- list.push(sub);
110
- // Sort by priority desc so higher-priority handlers run first.
111
- list.sort((a, b) => b.priority - a.priority);
112
- this.subs.set(event.name, list);
113
- return () => {
114
- const current = this.subs.get(event.name);
115
- if (!current)
108
+ const eventHook = this.ensureEventHook(event.name);
109
+ if (event.mode === "parallel") {
110
+ const listener = async (payload) => {
111
+ try {
112
+ await handler(payload);
113
+ }
114
+ catch (err) {
115
+ this.logger.error?.("framework-event handler threw (parallel)", {
116
+ event: event.name,
117
+ error: err?.message ?? String(err),
118
+ });
119
+ }
120
+ };
121
+ eventHook.on(listener, { priority });
122
+ return () => eventHook.off(listener);
123
+ }
124
+ // series + series-bail both run as chain steps; series-bail returning
125
+ // false short-circuits by not calling next().
126
+ const step = async (ctx, next) => {
127
+ const result = await handler(ctx);
128
+ if (event.mode === "series-bail" && result === false) {
129
+ // Don't call next() — short-circuits the chain. fire() sees
130
+ // outcome === "prevented" via runDetailed.
116
131
  return;
117
- const i = current.indexOf(sub);
118
- if (i >= 0)
119
- current.splice(i, 1);
132
+ }
133
+ await next();
120
134
  };
135
+ eventHook.use(step, { priority });
136
+ return () => eventHook.off(step);
121
137
  }
122
138
  /**
123
139
  * Fire a framework event. Resolves to `false` when a series-bail handler
124
140
  * vetoed; `true` otherwise. The boolean is irrelevant for parallel /
125
- * series modes and always returns `true` there for them.
141
+ * series modes and always returns `true` there.
142
+ *
143
+ * Internally: delegates to the per-event hook's `.run()` (parallel /
144
+ * series) or `.runDetailed()` (series-bail, to detect "prevented"
145
+ * outcome from short-circuit). The hook's observability surface (.tap,
146
+ * StepObservation) lights up automatically.
126
147
  */
127
148
  async fire(event, payload) {
128
- const handlers = (this.subs.get(event.name) ?? []);
129
- // Observation surface — emit start + end taps via the per-event hook.
130
- // Cheap (one closure invocation per fire) and adds the event to
131
- // `listHooks()` for scan + Studio + CLI visibility.
132
149
  const eventHook = this.ensureEventHook(event.name);
133
- await eventHook.run(payload);
134
- // Always notify observers — even when no subscribers exist for this
135
- // event. The lifecycle is the signal worth recording; subscribers are
136
- // an orthogonal concern (could be none in dev, several in prod).
137
150
  const ts = new Date().toISOString();
138
151
  const obsRec = (phase) => ({
139
152
  eventName: event.name,
@@ -142,50 +155,34 @@ export class FrameworkEventBus {
142
155
  phase,
143
156
  ts,
144
157
  });
145
- if (handlers.length === 0) {
146
- this.notify(obsRec("fired"));
147
- return true;
148
- }
149
- switch (event.mode) {
150
- case "parallel": {
151
- const settled = await Promise.allSettled(handlers.map(({ handler }) => Promise.resolve().then(() => handler(payload))));
152
- for (const r of settled) {
153
- if (r.status === "rejected") {
154
- this.logger.error?.("framework-event handler threw (parallel)", {
155
- event: event.name,
156
- error: r.reason?.message ?? String(r.reason),
157
- });
158
- }
159
- }
160
- this.notify(obsRec("fired"));
161
- return true;
162
- }
163
- case "series": {
164
- for (const { handler } of handlers) {
165
- await handler(payload);
166
- }
167
- this.notify(obsRec("fired"));
168
- return true;
169
- }
170
- case "series-bail": {
171
- for (const { handler } of handlers) {
172
- const result = await handler(payload);
173
- if (result === false) {
174
- this.logger.info?.("framework-event prevented by handler", {
175
- event: event.name,
176
- });
177
- this.notify(obsRec("prevented"));
178
- return false;
179
- }
180
- }
181
- this.notify(obsRec("fired"));
182
- return true;
158
+ if (event.mode === "series-bail") {
159
+ const result = await eventHook.runDetailed(payload);
160
+ const fired = result.outcome === "completed";
161
+ if (!fired) {
162
+ this.logger.info?.("framework-event prevented by handler", {
163
+ event: event.name,
164
+ });
183
165
  }
166
+ this.notify(obsRec(fired ? "fired" : "prevented"));
167
+ return fired;
184
168
  }
169
+ // parallel + series: hook.run handles dispatch; listener errors in
170
+ // parallel mode are swallowed by the listener wrapper in on(); chain
171
+ // errors in series mode propagate (matches old behaviour).
172
+ await eventHook.run(payload);
173
+ this.notify(obsRec("fired"));
174
+ return true;
185
175
  }
186
- /** Count subscribers for an event — diagnostic surface (Studio, tests). */
176
+ /**
177
+ * Count subscribers for an event — diagnostic surface (Studio, tests).
178
+ * Sums chain steps and listeners attached to the per-event hook.
179
+ */
187
180
  subscriberCount(event) {
188
- return this.subs.get(event.name)?.length ?? 0;
181
+ const h = this.eventHooks.get(event.name);
182
+ if (!h)
183
+ return 0;
184
+ const counts = h.stepCounts();
185
+ return counts.chain + counts.listeners;
189
186
  }
190
187
  }
191
188
  //# sourceMappingURL=framework-event-bus.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"framework-event-bus.js","sourceRoot":"","sources":["../src/framework-event-bus.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"framework-event-bus.js","sourceRoot":"","sources":["../src/framework-event-bus.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Runtime — generic dispatch + observation substrate.
3
+ *
4
+ * The "app" half of the runtime: a managed Container, a hooks-backed
5
+ * dispatch chain, a framework-event bus, and a canonical telemetry stream.
6
+ * Domain engines (`@nwire/forge.Runtime`) extend this class and layer their
7
+ * own registries (actors, workflows, projections, queries, event store)
8
+ * on top.
9
+ *
10
+ * What this class owns:
11
+ * - A Container (default `createContainer()`).
12
+ * - The `runtime.dispatch` hook from `@nwire/hooks` — middleware substrate
13
+ * for any sub-class's per-action pipeline. Subclasses register the
14
+ * pinned innermost step that calls their handler; this base only owns
15
+ * the hook itself, the user-middleware adapter, and the tap into the
16
+ * telemetry stream.
17
+ * - The `FrameworkEventBus` — lifecycle events (`AppBooting`,
18
+ * `PluginRegistered`, …). Subclasses add per-action / per-actor events
19
+ * by registering more event definitions.
20
+ * - `onTelemetry` / `offTelemetry` / `emit` — the canonical observation
21
+ * stream every consumer (dev logger, Studio Live SSE, OTel exporter)
22
+ * listens on. Subclasses widen the `Telemetry` union with their own
23
+ * domain kinds (e.g. `action.dispatched`, `actor.transitioned`) and
24
+ * call `this.emit(record)` to push them through the same channel.
25
+ */
26
+ import { type Container } from "@nwire/container";
27
+ import { type Hook } from "@nwire/hooks";
28
+ import { type Logger } from "@nwire/logger";
29
+ import { FrameworkEventBus, type FrameworkEventHandler } from "./framework-event-bus.js";
30
+ import type { FrameworkEventDefinition } from "./framework-events.js";
31
+ /**
32
+ * Serialized form of any thrown value — `Error` instances keep `name` /
33
+ * `message` / `stack` plus any own enumerable properties; non-Error throws
34
+ * round-trip as `{ name: "NonError", message: String(err) }`. Used by every
35
+ * telemetry record that carries an error payload.
36
+ */
37
+ export type SerializedError = {
38
+ readonly name: string;
39
+ readonly message: string;
40
+ readonly stack?: string;
41
+ readonly [k: string]: unknown;
42
+ };
43
+ export declare function serializeError(err: unknown): SerializedError;
44
+ /**
45
+ * `hook.step` — one record per chain/listener phase on any adopted hook.
46
+ * `runId` / `parentRunId` link nested hook invocations into a causal tree
47
+ * — that's what Studio's Trace page uses.
48
+ */
49
+ export interface HookStepTelemetry {
50
+ readonly kind: "hook.step";
51
+ readonly hookName: string;
52
+ readonly hookId: string;
53
+ readonly runId: string;
54
+ readonly parentRunId?: string;
55
+ readonly stepId: number;
56
+ readonly stepKind: "chain" | "listener";
57
+ readonly stepName?: string;
58
+ readonly phase: "start" | "end" | "error";
59
+ readonly durationMs?: number;
60
+ readonly error?: SerializedError;
61
+ readonly appName: string;
62
+ readonly ts: string;
63
+ }
64
+ /**
65
+ * `lifecycle` — one record per framework-event firing on the bus. The
66
+ * runtime bridges every fire into the telemetry stream so dev logger,
67
+ * Studio Live, and OTel exporter all see lifecycle activity through the
68
+ * same channel as domain events. `phase: "prevented"` flags series-bail
69
+ * handlers that vetoed.
70
+ */
71
+ export interface LifecycleTelemetry {
72
+ readonly kind: "lifecycle";
73
+ readonly event: string;
74
+ readonly namespace: string;
75
+ readonly payload: unknown;
76
+ readonly phase: "fired" | "prevented";
77
+ readonly appName: string;
78
+ readonly ts: string;
79
+ }
80
+ /**
81
+ * Base `Telemetry` union — generic kinds only. Subclasses (forge) WIDEN
82
+ * this with their own domain kinds (`action.dispatched`, `event.published`,
83
+ * `actor.transitioned`, …) and re-export the wider union as their own
84
+ * `Telemetry` alias. Consumers that listen on the base accept everything;
85
+ * consumers that care about discriminants narrow with `switch (rec.kind)`.
86
+ */
87
+ export type Telemetry = HookStepTelemetry | LifecycleTelemetry;
88
+ export type TelemetryListener<T = Telemetry> = (record: T) => void;
89
+ /**
90
+ * Per-dispatch context passed through the `runtime.dispatch` hook. Subclass
91
+ * dispatchers populate `coreFn` with their retry-loop + handler-invocation
92
+ * closure; the pinned innermost chain step calls it and writes `result`.
93
+ * User middlewares attached via `runtime.use()` see this ctx via adapters
94
+ * that re-expose the legacy `(next, action, input, ctx)` shape.
95
+ *
96
+ * Types here are deliberately structural / unknown — the base runtime
97
+ * doesn't know what an "action" or "context" looks like; forge tightens
98
+ * the generics in its own re-export.
99
+ */
100
+ export interface DispatchHookCtx {
101
+ readonly action: unknown;
102
+ readonly input: unknown;
103
+ readonly ctx: unknown;
104
+ readonly coreFn: () => Promise<unknown>;
105
+ result?: unknown;
106
+ }
107
+ /**
108
+ * Onion-style extension point around action dispatch. Outermost first;
109
+ * registration order is execution order (matches Koa/express semantics).
110
+ * Middlewares run OUTSIDE any retry loop — one pass per dispatch.
111
+ */
112
+ export type DispatchMiddleware = (next: () => Promise<unknown>, action: unknown, input: unknown, ctx: unknown) => Promise<unknown>;
113
+ export interface RuntimeOptions {
114
+ readonly container?: Container;
115
+ readonly logger?: Logger;
116
+ /**
117
+ * App / service name. Stamped on every telemetry record so a single
118
+ * multi-tenant observer can demux records by origin.
119
+ */
120
+ readonly appName?: string;
121
+ /**
122
+ * Framework events to pre-create hooks for. The bus also lazily creates
123
+ * a hook the first time `bus.on(Event, …)` or `bus.fire(Event, …)` runs
124
+ * — but eager creation surfaces every known event in `listHooks()` +
125
+ * scan + Studio before any subscription has happened.
126
+ */
127
+ readonly events?: readonly FrameworkEventDefinition<unknown>[];
128
+ }
129
+ export declare class Runtime {
130
+ protected readonly container: Container;
131
+ protected readonly logger: Logger;
132
+ readonly appName: string;
133
+ /**
134
+ * Dispatch substrate. Subclasses register their pinned `handler` step at
135
+ * priority `-Infinity` and call `dispatchHook.run(ctx)` from their own
136
+ * `dispatch` method. The tap forwards every chain step to the canonical
137
+ * telemetry stream.
138
+ */
139
+ protected readonly dispatchHook: Hook<DispatchHookCtx>;
140
+ private userMiddlewareCount;
141
+ readonly frameworkEvents: FrameworkEventBus;
142
+ private readonly telemetryListeners;
143
+ constructor(options?: RuntimeOptions);
144
+ /**
145
+ * Subscribe to a framework event. Sugar over `runtime.frameworkEvents.on`
146
+ * so plugins can write `runtime.onFramework(ActionDispatching, ...)`.
147
+ * Returns an unsubscribe function.
148
+ */
149
+ onFramework<TPayload>(event: FrameworkEventDefinition<TPayload>, handler: FrameworkEventHandler<TPayload>, priority?: number): () => void;
150
+ /**
151
+ * Register a dispatch middleware. Outermost first — the order you call
152
+ * `use()` is the order layers wrap (first `use` is the outermost layer).
153
+ * Middlewares run once per dispatch, outside the retry loop.
154
+ *
155
+ * Each user middleware gets a distinct negative priority so the chain
156
+ * order matches registration order; the pinned subclass-owned "handler"
157
+ * step at `-Infinity` stays strictly innermost.
158
+ */
159
+ use(middleware: DispatchMiddleware): void;
160
+ /**
161
+ * Wire a hook's per-step tap into the canonical telemetry stream. After
162
+ * this call, every `.use()` / `.on()` step on the hook emits a
163
+ * `kind: "hook.step"` record through `runtime.onTelemetry`, the same way
164
+ * the built-in `runtime.dispatch` hook does.
165
+ *
166
+ * The framework calls this for every per-plugin / per-module lifecycle
167
+ * hook; plugin authors can call it on their own hooks if they want their
168
+ * extension points surfaced in Studio / dev-logger / OTel for free.
169
+ */
170
+ adoptHook<TCtx>(hook: Hook<TCtx>): void;
171
+ /**
172
+ * Subscribe to the canonical telemetry stream. Returns an unsubscribe.
173
+ * Throwing in a listener is caught and logged; never breaks dispatch.
174
+ */
175
+ onTelemetry<T = Telemetry>(listener: TelemetryListener<T>): () => void;
176
+ offTelemetry<T = Telemetry>(listener: TelemetryListener<T>): void;
177
+ /**
178
+ * Push a record onto the telemetry stream. Accepts `unknown` so
179
+ * subclass-widened records (CQRS kinds in forge) don't need cast
180
+ * gymnastics — listeners narrow with `switch (rec.kind)`.
181
+ */
182
+ protected emit(record: unknown): void;
183
+ getContainer(): Container;
184
+ }
185
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}