@nwire/app 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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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"}
@@ -0,0 +1,197 @@
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 { createContainer } from "@nwire/container";
27
+ import { hook } from "@nwire/hooks";
28
+ import { NoopLogger } from "@nwire/logger";
29
+ import { FrameworkEventBus, } from "./framework-event-bus.js";
30
+ export function serializeError(err) {
31
+ if (err instanceof Error) {
32
+ const out = {
33
+ name: err.name,
34
+ message: err.message,
35
+ stack: err.stack,
36
+ };
37
+ for (const k of Object.keys(err)) {
38
+ if (k === "name" || k === "message" || k === "stack")
39
+ continue;
40
+ out[k] = err[k];
41
+ }
42
+ return out;
43
+ }
44
+ return { name: "NonError", message: String(err) };
45
+ }
46
+ export class Runtime {
47
+ container;
48
+ logger;
49
+ appName;
50
+ /**
51
+ * Dispatch substrate. Subclasses register their pinned `handler` step at
52
+ * priority `-Infinity` and call `dispatchHook.run(ctx)` from their own
53
+ * `dispatch` method. The tap forwards every chain step to the canonical
54
+ * telemetry stream.
55
+ */
56
+ dispatchHook;
57
+ userMiddlewareCount = 0;
58
+ frameworkEvents;
59
+ telemetryListeners = [];
60
+ constructor(options = {}) {
61
+ this.container = options.container ?? createContainer();
62
+ this.logger = options.logger ?? new NoopLogger();
63
+ this.appName = options.appName ?? "app";
64
+ this.frameworkEvents = new FrameworkEventBus(this.logger, {
65
+ adoptHook: (h) => this.adoptHook(h),
66
+ events: options.events ?? [],
67
+ });
68
+ // Bridge framework-event firings into the telemetry stream so every
69
+ // existing telemetry consumer (dev logger, Studio Live SSE, OTel
70
+ // exporter) sees lifecycle activity through the same channel as
71
+ // domain events. `namespace` = the second dotted segment so dev
72
+ // logger / Studio can group by phase (app / plugin / wire / …).
73
+ this.frameworkEvents.onFire((rec) => {
74
+ const parts = rec.eventName.split(".");
75
+ const namespace = parts.length >= 2 ? parts[1] : "framework";
76
+ this.emit({
77
+ kind: "lifecycle",
78
+ event: rec.eventName,
79
+ namespace,
80
+ payload: rec.payload,
81
+ phase: rec.phase,
82
+ appName: this.appName,
83
+ ts: rec.ts,
84
+ });
85
+ });
86
+ this.dispatchHook = hook("runtime.dispatch");
87
+ this.dispatchHook.tap((obs) => {
88
+ this.emit({
89
+ kind: "hook.step",
90
+ hookName: obs.hookName,
91
+ hookId: obs.hookId,
92
+ runId: obs.runId,
93
+ parentRunId: obs.parentRunId,
94
+ stepId: obs.stepId,
95
+ stepKind: obs.stepKind,
96
+ stepName: obs.stepName,
97
+ phase: obs.phase,
98
+ durationMs: obs.durationMs,
99
+ error: obs.error ? serializeError(obs.error) : undefined,
100
+ appName: this.appName,
101
+ ts: new Date().toISOString(),
102
+ });
103
+ });
104
+ }
105
+ /**
106
+ * Subscribe to a framework event. Sugar over `runtime.frameworkEvents.on`
107
+ * so plugins can write `runtime.onFramework(ActionDispatching, ...)`.
108
+ * Returns an unsubscribe function.
109
+ */
110
+ onFramework(event, handler, priority = 0) {
111
+ return this.frameworkEvents.on(event, handler, priority);
112
+ }
113
+ /**
114
+ * Register a dispatch middleware. Outermost first — the order you call
115
+ * `use()` is the order layers wrap (first `use` is the outermost layer).
116
+ * Middlewares run once per dispatch, outside the retry loop.
117
+ *
118
+ * Each user middleware gets a distinct negative priority so the chain
119
+ * order matches registration order; the pinned subclass-owned "handler"
120
+ * step at `-Infinity` stays strictly innermost.
121
+ */
122
+ use(middleware) {
123
+ const priority = -this.userMiddlewareCount;
124
+ this.userMiddlewareCount += 1;
125
+ this.dispatchHook.use(async (hctx, next) => {
126
+ hctx.result = await middleware(async () => {
127
+ await next();
128
+ return hctx.result;
129
+ }, hctx.action, hctx.input, hctx.ctx);
130
+ }, { name: middleware.name || `middleware#${this.userMiddlewareCount}`, priority });
131
+ }
132
+ /**
133
+ * Wire a hook's per-step tap into the canonical telemetry stream. After
134
+ * this call, every `.use()` / `.on()` step on the hook emits a
135
+ * `kind: "hook.step"` record through `runtime.onTelemetry`, the same way
136
+ * the built-in `runtime.dispatch` hook does.
137
+ *
138
+ * The framework calls this for every per-plugin / per-module lifecycle
139
+ * hook; plugin authors can call it on their own hooks if they want their
140
+ * extension points surfaced in Studio / dev-logger / OTel for free.
141
+ */
142
+ adoptHook(hook) {
143
+ hook.tap((obs) => {
144
+ this.emit({
145
+ kind: "hook.step",
146
+ hookName: obs.hookName,
147
+ hookId: obs.hookId,
148
+ runId: obs.runId,
149
+ parentRunId: obs.parentRunId,
150
+ stepId: obs.stepId,
151
+ stepKind: obs.stepKind,
152
+ stepName: obs.stepName,
153
+ phase: obs.phase,
154
+ durationMs: obs.durationMs,
155
+ error: obs.error ? serializeError(obs.error) : undefined,
156
+ appName: this.appName,
157
+ ts: new Date().toISOString(),
158
+ });
159
+ });
160
+ }
161
+ /**
162
+ * Subscribe to the canonical telemetry stream. Returns an unsubscribe.
163
+ * Throwing in a listener is caught and logged; never breaks dispatch.
164
+ */
165
+ onTelemetry(listener) {
166
+ this.telemetryListeners.push(listener);
167
+ return () => this.offTelemetry(listener);
168
+ }
169
+ offTelemetry(listener) {
170
+ const i = this.telemetryListeners.indexOf(listener);
171
+ if (i >= 0)
172
+ this.telemetryListeners.splice(i, 1);
173
+ }
174
+ /**
175
+ * Push a record onto the telemetry stream. Accepts `unknown` so
176
+ * subclass-widened records (CQRS kinds in forge) don't need cast
177
+ * gymnastics — listeners narrow with `switch (rec.kind)`.
178
+ */
179
+ emit(record) {
180
+ if (this.telemetryListeners.length === 0)
181
+ return;
182
+ for (const listener of this.telemetryListeners) {
183
+ try {
184
+ listener(record);
185
+ }
186
+ catch (err) {
187
+ // Best-effort — don't let a bad listener break dispatch.
188
+ // eslint-disable-next-line no-console
189
+ console.error("Runtime.onTelemetry listener threw:", err);
190
+ }
191
+ }
192
+ }
193
+ getContainer() {
194
+ return this.container;
195
+ }
196
+ }
197
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nwire/app",
3
- "version": "0.8.0",
4
- "description": "Nwire — managed Container with plugin lifecycle, framework events, and DI hooks. The 'app' in the sealed architecture: composes modules + plugins, boots in order, exposes a Container, fires framework events at every lifecycle transition. Phase 69 extraction in progress; currently ships the framework events + bus.",
3
+ "version": "0.9.0",
4
+ "description": "Nwire — managed Container with plugin lifecycle, framework events, and DI hooks. Composes modules + plugins, boots in order, exposes a Container, fires framework events at every lifecycle transition.",
5
5
  "keywords": [
6
6
  "app",
7
7
  "container",
@@ -29,10 +29,10 @@
29
29
  "access": "public"
30
30
  },
31
31
  "dependencies": {
32
- "@nwire/container": "0.8.0",
33
- "@nwire/logger": "0.8.0",
34
- "@nwire/messages": "0.8.0",
35
- "@nwire/hooks": "0.8.0"
32
+ "@nwire/hooks": "0.8.17",
33
+ "@nwire/messages": "0.8.17",
34
+ "@nwire/container": "0.8.17",
35
+ "@nwire/logger": "0.8.17"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/node": "^22.19.9",