@nwire/forge 0.7.1 → 0.8.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.
Files changed (75) hide show
  1. package/README.md +88 -59
  2. package/dist/__tests__/action-hooks.test.d.ts +8 -0
  3. package/dist/__tests__/action-hooks.test.d.ts.map +1 -0
  4. package/dist/__tests__/action-hooks.test.js +95 -0
  5. package/dist/__tests__/action-hooks.test.js.map +1 -0
  6. package/dist/__tests__/actor-workflow-hooks.test.d.ts +8 -0
  7. package/dist/__tests__/actor-workflow-hooks.test.d.ts.map +1 -0
  8. package/dist/__tests__/actor-workflow-hooks.test.js +104 -0
  9. package/dist/__tests__/actor-workflow-hooks.test.js.map +1 -0
  10. package/dist/__tests__/lifecycle-logging.test.js +4 -2
  11. package/dist/__tests__/lifecycle-logging.test.js.map +1 -1
  12. package/dist/__tests__/plugin-stress.test.d.ts +21 -0
  13. package/dist/__tests__/plugin-stress.test.d.ts.map +1 -0
  14. package/dist/__tests__/plugin-stress.test.js +203 -0
  15. package/dist/__tests__/plugin-stress.test.js.map +1 -0
  16. package/dist/actor-store.d.ts +24 -0
  17. package/dist/actor-store.d.ts.map +1 -1
  18. package/dist/actor-store.js +29 -0
  19. package/dist/actor-store.js.map +1 -1
  20. package/dist/create-app.d.ts +7 -0
  21. package/dist/create-app.d.ts.map +1 -1
  22. package/dist/create-app.js +101 -10
  23. package/dist/create-app.js.map +1 -1
  24. package/dist/define-action.d.ts +4 -2
  25. package/dist/define-action.d.ts.map +1 -1
  26. package/dist/define-action.js +9 -6
  27. package/dist/define-action.js.map +1 -1
  28. package/dist/define-actor.d.ts +3 -1
  29. package/dist/define-actor.d.ts.map +1 -1
  30. package/dist/define-actor.js +11 -4
  31. package/dist/define-actor.js.map +1 -1
  32. package/dist/define-handler.d.ts +21 -2
  33. package/dist/define-handler.d.ts.map +1 -1
  34. package/dist/define-handler.js +3 -1
  35. package/dist/define-handler.js.map +1 -1
  36. package/dist/define-module.d.ts +3 -0
  37. package/dist/define-module.d.ts.map +1 -1
  38. package/dist/define-module.js +3 -0
  39. package/dist/define-module.js.map +1 -1
  40. package/dist/define-plugin.d.ts +4 -1
  41. package/dist/define-plugin.d.ts.map +1 -1
  42. package/dist/define-plugin.js +34 -14
  43. package/dist/define-plugin.js.map +1 -1
  44. package/dist/define-projection.d.ts +3 -1
  45. package/dist/define-projection.d.ts.map +1 -1
  46. package/dist/define-projection.js +3 -0
  47. package/dist/define-projection.js.map +1 -1
  48. package/dist/define-query.d.ts +3 -1
  49. package/dist/define-query.d.ts.map +1 -1
  50. package/dist/define-query.js +2 -0
  51. package/dist/define-query.js.map +1 -1
  52. package/dist/define-workflow.d.ts +19 -1
  53. package/dist/define-workflow.d.ts.map +1 -1
  54. package/dist/define-workflow.js +4 -0
  55. package/dist/define-workflow.js.map +1 -1
  56. package/dist/dev-logger.d.ts.map +1 -1
  57. package/dist/dev-logger.js +19 -1
  58. package/dist/dev-logger.js.map +1 -1
  59. package/dist/framework-events.d.ts +1 -64
  60. package/dist/framework-events.d.ts.map +1 -1
  61. package/dist/framework-events.js +3 -0
  62. package/dist/framework-events.js.map +1 -1
  63. package/dist/idempotency-store.d.ts +35 -0
  64. package/dist/idempotency-store.d.ts.map +1 -0
  65. package/dist/idempotency-store.js +32 -0
  66. package/dist/idempotency-store.js.map +1 -0
  67. package/dist/index.d.ts +2 -0
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +1 -0
  70. package/dist/index.js.map +1 -1
  71. package/dist/runtime.d.ts +197 -3
  72. package/dist/runtime.d.ts.map +1 -1
  73. package/dist/runtime.js +495 -44
  74. package/dist/runtime.js.map +1 -1
  75. package/package.json +11 -10
package/README.md CHANGED
@@ -1,39 +1,36 @@
1
1
  # @nwire/forge
2
2
 
3
- > The framework's domain primitives — one import for actions, actors, events, workflows, projections, modules, and the runtime that ties them together.
3
+ > The framework's domain primitives — actions, actors, events, workflows, projections, modules, plugins, and the runtime that fires them.
4
4
 
5
- ## What it does
6
-
7
- Provides the `define*` surface that domain code uses every day, plus the
8
- runtime that fires them. Forge composes lower packages (`@nwire/messages`,
9
- `@nwire/handler`, `@nwire/app`) into one ergonomic API; you can also use
10
- the lower packages directly when you want a narrower surface.
11
-
12
- ## Install
5
+ Forge composes the lower packages (`@nwire/messages`, `@nwire/handler`,
6
+ `@nwire/app`) into one ergonomic surface. You can drop down to any of
7
+ them when you want a narrower import; forge stays the default for app code.
13
8
 
14
9
  ```bash
15
10
  pnpm add @nwire/forge zod
16
11
  ```
17
12
 
18
- ## Quick start
13
+ ## Quick example
19
14
 
20
15
  ```ts
21
16
  import { z } from "zod";
22
17
  import { defineEvent } from "@nwire/messages";
23
- import { defineAction, defineActor, defineModule, createApp } from "@nwire/forge";
18
+ import {
19
+ defineAction,
20
+ defineActor,
21
+ defineModule,
22
+ createApp,
23
+ AppBooted,
24
+ ActionCompleted,
25
+ } from "@nwire/forge";
24
26
 
25
- // 1. A past-tense fact the domain cares about.
26
27
  export const StudentWasEnrolled = defineEvent({
27
28
  name: "enrollments.student-was-enrolled",
28
29
  schema: z.object({ studentId: z.string(), courseId: z.string() }),
29
30
  });
30
31
 
31
- // 2. An aggregate that holds state + invariants.
32
32
  export const Student = defineActor("Student", {
33
- schema: z.object({
34
- studentId: z.string(),
35
- enrolments: z.array(z.string()),
36
- }),
33
+ schema: z.object({ studentId: z.string(), enrolments: z.array(z.string()) }),
37
34
  initial: (id: string) => ({ studentId: id, enrolments: [] }),
38
35
  methods: {
39
36
  enrol(state, courseId: string) {
@@ -43,7 +40,6 @@ export const Student = defineActor("Student", {
43
40
  },
44
41
  });
45
42
 
46
- // 3. A user-visible command that emits the event.
47
43
  export const enrolStudent = defineAction({
48
44
  name: "enrollments.enrol-student",
49
45
  schema: z.object({ studentId: z.string(), courseId: z.string() }),
@@ -51,54 +47,87 @@ export const enrolStudent = defineAction({
51
47
  handler: async (input, { use }) => {
52
48
  const student = await use(Student, input.studentId);
53
49
  student.enrol(input.courseId);
54
- return StudentWasEnrolled({
55
- studentId: input.studentId,
56
- courseId: input.courseId,
57
- });
50
+ return StudentWasEnrolled(input);
58
51
  },
59
52
  });
60
53
 
61
- // 4. A module bundles the bounded context.
62
- export const enrollmentsModule = defineModule("enrollments", {
63
- events: [StudentWasEnrolled],
64
- actors: [Student],
54
+ export const enrollments = defineModule("enrollments", {
55
+ events: [StudentWasEnrolled],
56
+ actors: [Student],
65
57
  actions: [enrolStudent.public()],
66
58
  });
67
59
 
68
- // 5. createApp wires the modules into a runnable app.
69
- export const app = createApp({ modules: [enrollmentsModule] });
60
+ const app = createApp({ modules: [enrollments] });
61
+
62
+ // Subscribe to lifecycle + dispatch events through the same bus.
63
+ app.bus.on(AppBooted, ({ appName }) => console.log("booted:", appName));
64
+ app.bus.on(ActionCompleted, ({ action }) => console.log("ran:", action.name));
65
+
70
66
  await app.start();
71
67
  await app.runtime.dispatch(enrolStudent, { studentId: "avi", courseId: "heb-1" });
72
68
  ```
73
69
 
74
- ## API surface
75
-
76
- | Primitive | Purpose |
77
- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
78
- | `defineAction` | User-visible command — validated input, emits events |
79
- | `defineEvent` | Past-tense fact (re-exported from `@nwire/messages`) |
80
- | `defineHandler` | Operation primitivetransport-agnostic |
81
- | `defineActor` | Aggregate with state, methods, optional state machine |
82
- | `defineSchema` | Data shape + lifecycle states + storage hints |
83
- | `defineProjection` | Read-model fold over events |
84
- | `defineQuery` | Projection-backed read function |
85
- | `defineWorkflow` | Reaction + saga unified — stateful or stateless |
86
- | `defineModule` | Bundle of actors + actions + events + projections + queries |
87
- | `defineApp` | App declaration (multi-wire instantiation) |
88
- | `createApp` | App runtime boots modules, owns the bus |
89
- | `definePlugin` | Cross-cutting: provide bindings, hook lifecycle, intercept dispatch |
90
- | `defineResource` | Public response shape (field allowlist + OpenAPI schema) |
91
- | `defineError` | Typed throwable with status code |
92
- | `defineMiddleware` | Reusable handler middleware step |
93
- | `defineCron`, `defineInbox`, `defineOutbox`, `defineExternalCall`, `defineInboundWebhook` | Orchestrator primitives |
94
- | `runCli(app, argv)` | Argv dispatcher operator CLI without HTTP |
95
-
96
- Forge also re-exports `MessageEnvelope`, `seedEnvelope`, `deriveEnvelope`
97
- from `@nwire/envelope` and the `Logger` contract from `@nwire/logger`.
98
-
99
- ## When to use forge
100
-
101
- When you want the full framework DX in one import. If you only need typed
102
- handlers without the actor/event machinery, pull `@nwire/handler` instead;
103
- if you only need lifecycle + plugins, pull `@nwire/app`. Forge is the
104
- default for app code; the smaller packages are the standalone path.
70
+ ## Surface
71
+
72
+ ### Domain primitives
73
+
74
+ | Export | Role |
75
+ | --------------------- | ------------------------------------------------------------- |
76
+ | `defineAction` | User-visible commandvalidated input, emits events |
77
+ | `defineEvent` | Past-tense fact (re-exported from `@nwire/messages`) |
78
+ | `defineHandler` | Operation primitive transport-agnostic |
79
+ | `defineActor` | Aggregate with state, methods, optional state machine |
80
+ | `defineSchema` | Data shape + lifecycle states + storage hints |
81
+ | `defineProjection` | Read-model fold over events |
82
+ | `defineQuery` | Projection-backed read function |
83
+ | `defineWorkflow` | Reaction + saga unified — stateless or stateful |
84
+ | `defineModule` | Bundle of actors + actions + events + projections + queries |
85
+ | `defineApp` | App declaration (multi-wire instantiation) |
86
+ | `createApp` | App runtime boots modules, owns the bus and runtime |
87
+ | `definePlugin` | Forge-richer plugin: middleware + actor hooks + before/after |
88
+ | `defineResource` | Public response shape (field allowlist + OpenAPI schema) |
89
+ | `defineError` | Typed throwable with status code |
90
+ | `defineMiddleware` / `defineHook` / `pipe` | Reusable resolver chain pieces |
91
+ | `defineCron` / `defineInbox` / `defineOutbox` / `defineExternalCall` / `defineInboundWebhook` | Orchestrator primitives |
92
+ | `runCli(app, argv)` | Argv dispatcher — operator CLI without HTTP |
93
+
94
+ ### Framework events
95
+
96
+ Forge re-exports the app-lifecycle events from `@nwire/app`
97
+ (`AppRegistering` / `AppBooting` / `AppBooted` / `AppReady` /
98
+ `AppShuttingDown` / `AppShutdown`, `PluginRegistered` …, `WireMounting` …)
99
+ and adds its own forge-local events:
100
+
101
+ | Event | Mode | When |
102
+ | --------------------- | ------------- | --------------------------------------------------- |
103
+ | `ActionDispatching` | series-bail | Before handler runs. Return `false` to short-circuit. |
104
+ | `ActionCompleted` | parallel | After handler returns successfully. |
105
+ | `ActionFailed` | parallel | After handler throws. |
106
+ | `EventRecording` | series-bail | Before an event is appended to the store. |
107
+ | `EventRecorded` | parallel | After append succeeds. |
108
+ | `builtInFrameworkEvents` | — | Catalog of every built-in (lifecycle + forge-local).|
109
+
110
+ ### Re-exports
111
+
112
+ - `MessageEnvelope`, `seedEnvelope`, `deriveEnvelope` from `@nwire/envelope`
113
+ - `Logger` contract + `NoopLogger` / `ConsoleLogger` from `@nwire/logger`
114
+ - `DeadLetterSink` + `InMemoryDeadLetterSink` from `@nwire/dead-letter`
115
+
116
+ ## Picking the right entry point
117
+
118
+ | You want… | Import from |
119
+ | ------------------------------------------ | ------------------ |
120
+ | Full framework DX in one import | `@nwire/forge` |
121
+ | Just operations (handlers / middleware) | `@nwire/handler` |
122
+ | Just lifecycle + plugins | `@nwire/app` |
123
+ | Just events + envelope | `@nwire/messages` |
124
+
125
+ ## Related
126
+
127
+ - `@nwire/endpoint` — wraps the runtime in a process (graceful shutdown, probes).
128
+ - `@nwire/http` — HTTP transport over the runtime.
129
+ - `@nwire/hooks` — the dispatch substrate that powers `runtime.use(...)` and every framework event.
130
+
131
+ ## Status
132
+
133
+ v0.x — public surface is stable; `createApp` will extract to `@nwire/app` in a follow-up phase but imports won't change (re-exports preserved).
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Per-action `action.before:<name>` and `action.after:<name>` hooks —
3
+ * proves the named-hook surface that plugin `before()`/`after()` sugar
4
+ * registers chain steps on, AND that the dispatcher honors veto + observes
5
+ * after-success.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=action-hooks.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-hooks.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/action-hooks.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Per-action `action.before:<name>` and `action.after:<name>` hooks —
3
+ * proves the named-hook surface that plugin `before()`/`after()` sugar
4
+ * registers chain steps on, AND that the dispatcher honors veto + observes
5
+ * after-success.
6
+ */
7
+ import { describe, it, expect } from "vitest";
8
+ import { z } from "zod";
9
+ import { listHooks } from "@nwire/hooks";
10
+ import { createApp, defineAction, defineHandler, defineModule, definePlugin } from "../foundation.js";
11
+ const Ping = defineAction({
12
+ name: "test/action-hooks-ping",
13
+ schema: z.object({ n: z.number() }),
14
+ });
15
+ const pingHandler = defineHandler(Ping, async (input) => undefined);
16
+ const mod = defineModule("test-action-hooks", {
17
+ actions: [Ping],
18
+ handlers: [pingHandler],
19
+ });
20
+ describe("per-action hooks", () => {
21
+ it("registers action.before:<name> + action.after:<name> on handler register", async () => {
22
+ const app = createApp({ appName: "action-hooks-test", modules: [mod] });
23
+ await app.start();
24
+ const names = listHooks().map((h) => h.name);
25
+ expect(names).toContain("action.before:test/action-hooks-ping");
26
+ expect(names).toContain("action.after:test/action-hooks-ping");
27
+ await app.stop();
28
+ });
29
+ it("plugin.before chain step that returns false vetoes the dispatch", async () => {
30
+ let handlerRan = false;
31
+ let beforeRan = false;
32
+ let afterRan = false;
33
+ const ping2 = defineHandler(defineAction({ name: "test/veto-ping", schema: z.object({}) }), async () => {
34
+ handlerRan = true;
35
+ return undefined;
36
+ });
37
+ const m = defineModule("test-veto", { actions: [ping2.action], handlers: [ping2] });
38
+ const vetoer = definePlugin("vetoer", ({ before, after }) => {
39
+ before("test/veto-ping", () => {
40
+ beforeRan = true;
41
+ return false;
42
+ });
43
+ after("test/veto-ping", () => {
44
+ afterRan = true;
45
+ });
46
+ });
47
+ const app = createApp({ appName: "veto-test", modules: [m], plugins: [vetoer] });
48
+ await app.start();
49
+ await app.runtime.dispatch(ping2.action, {});
50
+ expect(beforeRan).toBe(true);
51
+ expect(handlerRan).toBe(false);
52
+ expect(afterRan).toBe(false);
53
+ await app.stop();
54
+ });
55
+ it("plugin.after observes the result + durationMs of a successful dispatch", async () => {
56
+ let captured = null;
57
+ const ping3 = defineHandler(defineAction({ name: "test/observe-ping", schema: z.object({}) }), async () => undefined);
58
+ const m = defineModule("test-observe", { actions: [ping3.action], handlers: [ping3] });
59
+ const observer = definePlugin("observer", ({ after }) => {
60
+ after("test/observe-ping", ({ result, durationMs }) => {
61
+ captured = { result, durationMs };
62
+ });
63
+ });
64
+ const app = createApp({ appName: "observe-test", modules: [m], plugins: [observer] });
65
+ await app.start();
66
+ await app.runtime.dispatch(ping3.action, {});
67
+ expect(captured).not.toBeNull();
68
+ expect(typeof captured.durationMs).toBe("number");
69
+ await app.stop();
70
+ });
71
+ it("multiple plugins.before steps stack as named chain steps on the same hook", async () => {
72
+ const callOrder = [];
73
+ const ping4 = defineHandler(defineAction({ name: "test/stack-ping", schema: z.object({}) }), async () => {
74
+ callOrder.push("handler");
75
+ return undefined;
76
+ });
77
+ const m = defineModule("test-stack", { actions: [ping4.action], handlers: [ping4] });
78
+ const pluginA = definePlugin("a", ({ before }) => {
79
+ before("test/stack-ping", () => {
80
+ callOrder.push("a.before");
81
+ });
82
+ });
83
+ const pluginB = definePlugin("b", ({ before }) => {
84
+ before("test/stack-ping", () => {
85
+ callOrder.push("b.before");
86
+ });
87
+ });
88
+ const app = createApp({ appName: "stack-test", modules: [m], plugins: [pluginA, pluginB] });
89
+ await app.start();
90
+ await app.runtime.dispatch(ping4.action, {});
91
+ expect(callOrder).toEqual(["a.before", "b.before", "handler"]);
92
+ await app.stop();
93
+ });
94
+ });
95
+ //# sourceMappingURL=action-hooks.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-hooks.test.js","sourceRoot":"","sources":["../../src/__tests__/action-hooks.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Per-actor `actor.transition:<name>` and per-workflow `workflow.fire:<name>`
3
+ * hooks (A7). Proves both:
4
+ * - hooks appear in listHooks() right after registerActor/Workflow
5
+ * - chain steps observe transitions / fires during real dispatch
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=actor-workflow-hooks.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actor-workflow-hooks.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/actor-workflow-hooks.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Per-actor `actor.transition:<name>` and per-workflow `workflow.fire:<name>`
3
+ * hooks (A7). Proves both:
4
+ * - hooks appear in listHooks() right after registerActor/Workflow
5
+ * - chain steps observe transitions / fires during real dispatch
6
+ */
7
+ import { describe, it, expect } from "vitest";
8
+ import { z } from "zod";
9
+ import { defineEvent } from "@nwire/messages";
10
+ import { listHooks } from "@nwire/hooks";
11
+ import { createApp, defineAction, defineActor, defineModule, defineWorkflow, eventFactory, } from "../foundation.js";
12
+ // ─── Domain ────────────────────────────────────────────────────────
13
+ const OrderState = z.object({ orderId: z.string(), total: z.number() });
14
+ const Placed = defineEvent({
15
+ name: "orders.placed",
16
+ schema: z.object({ orderId: z.string(), total: z.number() }),
17
+ });
18
+ const Confirmed = defineEvent({
19
+ name: "orders.confirmed",
20
+ schema: z.object({ orderId: z.string() }),
21
+ });
22
+ const PlacedEvent = eventFactory(Placed);
23
+ const ConfirmedEvent = eventFactory(Confirmed);
24
+ const Order = defineActor("order", {
25
+ schema: OrderState,
26
+ key: "orderId",
27
+ initial: "draft",
28
+ states: {
29
+ draft: { on: { [Placed.name]: { target: "placed", assign: (_, e) => ({ ...e }) } } },
30
+ placed: { on: { [Confirmed.name]: { target: "confirmed" } } },
31
+ confirmed: {},
32
+ },
33
+ });
34
+ const placeOrder = defineAction({
35
+ name: "orders.place",
36
+ schema: z.object({ orderId: z.string(), total: z.number() }),
37
+ handler: async (input) => PlacedEvent(input),
38
+ });
39
+ const confirmOrder = defineAction({
40
+ name: "orders.confirm",
41
+ schema: z.object({ orderId: z.string() }),
42
+ handler: async (input) => ConfirmedEvent({ orderId: input.orderId }),
43
+ });
44
+ let workflowFiredCount = 0;
45
+ const notifyOnPlace = defineWorkflow("notify-on-place", ({ on }) => {
46
+ on(Placed, async () => {
47
+ workflowFiredCount++;
48
+ });
49
+ });
50
+ const mod = defineModule("orders", {
51
+ actors: [Order],
52
+ actions: [placeOrder, confirmOrder],
53
+ events: [Placed, Confirmed],
54
+ workflows: [notifyOnPlace],
55
+ });
56
+ // ─── Tests ─────────────────────────────────────────────────────────
57
+ describe("per-actor + per-workflow hooks", () => {
58
+ it("registerActor + registerWorkflow create named hooks visible in listHooks", async () => {
59
+ const app = createApp({ appName: "actor-workflow-hooks-list", modules: [mod] });
60
+ await app.start();
61
+ const names = listHooks().map((h) => h.name);
62
+ expect(names).toContain("actor.transition:order");
63
+ expect(names).toContain("workflow.fire:notify-on-place");
64
+ await app.stop();
65
+ });
66
+ it("actor.transition hook observes state changes during real dispatch", async () => {
67
+ const transitions = [];
68
+ const app = createApp({ appName: "actor-transition-test", modules: [mod] });
69
+ await app.start();
70
+ app.runtime.ensureActorTransitionHook("order").use(async (hctx, next) => {
71
+ transitions.push({ from: hctx.fromState, to: hctx.toState });
72
+ await next();
73
+ }, { name: "observer" });
74
+ await app.runtime.dispatch(placeOrder, { orderId: "o1", total: 100 });
75
+ expect(transitions).toEqual([{ from: "draft", to: "placed" }]);
76
+ await app.runtime.dispatch(confirmOrder, { orderId: "o1" });
77
+ expect(transitions).toEqual([
78
+ { from: "draft", to: "placed" },
79
+ { from: "placed", to: "confirmed" },
80
+ ]);
81
+ await app.stop();
82
+ });
83
+ it("workflow.fire hook observes saga invocations", async () => {
84
+ const fires = [];
85
+ workflowFiredCount = 0;
86
+ const app = createApp({ appName: "workflow-fire-test", modules: [mod] });
87
+ await app.start();
88
+ app.runtime.ensureWorkflowFireHook("notify-on-place").use(async (hctx, next) => {
89
+ fires.push({
90
+ workflow: hctx.workflow.name,
91
+ event: hctx.event.eventName,
92
+ correlationKey: hctx.correlationKey,
93
+ });
94
+ await next();
95
+ }, { name: "observer" });
96
+ await app.runtime.dispatch(placeOrder, { orderId: "o2", total: 50 });
97
+ expect(fires).toHaveLength(1);
98
+ expect(fires[0].workflow).toBe("notify-on-place");
99
+ expect(fires[0].event).toBe("orders.placed");
100
+ expect(workflowFiredCount).toBe(1);
101
+ await app.stop();
102
+ });
103
+ });
104
+ //# sourceMappingURL=actor-workflow-hooks.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actor-workflow-hooks.test.js","sourceRoot":"","sources":["../../src/__tests__/actor-workflow-hooks.test.ts"],"names":[],"mappings":"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"}
@@ -71,8 +71,10 @@ describe("framework events → telemetry → dev logger", () => {
71
71
  // Multiple lifecycle lines should be present.
72
72
  const lifecycleLines = lines.filter((l) => l.includes("nwire:"));
73
73
  expect(lifecycleLines.length).toBeGreaterThan(5);
74
- // Plugin-booted line should include the plugin name (`trace`).
75
- const booted = lifecycleLines.find((l) => l.includes("plugin.booted"));
74
+ // Plugin-booted line for the `trace` plugin specifically. Modules now
75
+ // also fire PluginBooted with `kind:"module"` first, so we need to find
76
+ // the booted line that names the `trace` plugin — not just the first.
77
+ const booted = lifecycleLines.find((l) => l.includes("plugin.booted") && l.includes("trace"));
76
78
  expect(booted).toBeTruthy();
77
79
  expect(booted).toContain("trace");
78
80
  });
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle-logging.test.js","sourceRoot":"","sources":["../../src/__tests__/lifecycle-logging.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lifecycle-logging.test.js","sourceRoot":"","sources":["../../src/__tests__/lifecycle-logging.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Plugin + module lifecycle stress test.
3
+ *
4
+ * Covers the failure modes that aren't exercised by `plugin.test.ts` /
5
+ * `plugin-closure.test.ts` / `lifecycle-logging.test.ts`:
6
+ *
7
+ * 1. Cross-plugin DI — plugin B reads plugin A's binding in its boot.
8
+ * 2. Slow boot timing — PluginBooted carries a real `durationMs`.
9
+ * 3. Boot failure recovery — A boots, B throws, stop() still cleans A.
10
+ * 4. Shutdown isolation — first plugin's shutdown throws but second still runs;
11
+ * the error surfaces from app.stop().
12
+ * 5. Ordering at scale — 10 plugins boot in registration order, shutdown reverse.
13
+ * 6. Module + plugin mixed — PluginRegistered fires with `kind:"module"` for
14
+ * modules first (topo order) then `kind:"plugin"` for plugins.
15
+ *
16
+ * Style follows `lifecycle-logging.test.ts` — real `createApp`, real
17
+ * `app.start()/stop()`, observe via the runtime's framework event bus
18
+ * (`runtime.frameworkEvents.onFire(...)`) and per-event subscriptions.
19
+ */
20
+ export {};
21
+ //# sourceMappingURL=plugin-stress.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-stress.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/plugin-stress.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG"}