@nwire/forge 0.7.0 → 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 +104 -48
  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 +14 -11
package/README.md CHANGED
@@ -1,77 +1,133 @@
1
1
  # @nwire/forge
2
2
 
3
- > Flavor sugar + domain primitives — the aggregation product that composes the framework into one surface.
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
- The `define*` surface domain code uses every day: `defineAction` / `defineQuery` (handler sugar), `defineActor` / `defineProjection` / `defineWorkflow` / `defineListener` (domain machinery), `defineEvent`, `defineModule`, `defineApp`, `createApp`, plus the runtime and the InMemory store defaults. Forge doesn't invent primitives — it composes lower packages into the unified DX teams ship features on.
8
-
9
- ## 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.
10
8
 
11
9
  ```bash
12
- pnpm add @nwire/forge
10
+ pnpm add @nwire/forge zod
13
11
  ```
14
12
 
15
- ## Quick start
13
+ ## Quick example
16
14
 
17
15
  ```ts
18
16
  import { z } from "zod";
19
- import { defineAction, defineActor, defineEvent, defineModule, createApp } from "@nwire/forge";
20
-
21
- const StudentWasEnrolled = defineEvent("StudentWasEnrolled", {
17
+ import { defineEvent } from "@nwire/messages";
18
+ import {
19
+ defineAction,
20
+ defineActor,
21
+ defineModule,
22
+ createApp,
23
+ AppBooted,
24
+ ActionCompleted,
25
+ } from "@nwire/forge";
26
+
27
+ export const StudentWasEnrolled = defineEvent({
28
+ name: "enrollments.student-was-enrolled",
22
29
  schema: z.object({ studentId: z.string(), courseId: z.string() }),
23
- }).public();
30
+ });
24
31
 
25
- const Student = defineActor("Student", {
26
- initial: () => ({ enrolments: [] as string[] }),
32
+ export const Student = defineActor("Student", {
33
+ schema: z.object({ studentId: z.string(), enrolments: z.array(z.string()) }),
34
+ initial: (id: string) => ({ studentId: id, enrolments: [] }),
27
35
  methods: {
28
36
  enrol(state, courseId: string) {
37
+ if (state.enrolments.includes(courseId)) return state;
29
38
  return { ...state, enrolments: [...state.enrolments, courseId] };
30
39
  },
31
40
  },
32
41
  });
33
42
 
34
- const enrolStudent = defineAction("enrolStudent", {
35
- input: z.object({ studentId: z.string(), courseId: z.string() }),
43
+ export const enrolStudent = defineAction({
44
+ name: "enrollments.enrol-student",
45
+ schema: z.object({ studentId: z.string(), courseId: z.string() }),
36
46
  emits: [StudentWasEnrolled],
37
- handler: async ({ input, use, emit }) => {
47
+ handler: async (input, { use }) => {
38
48
  const student = await use(Student, input.studentId);
39
49
  student.enrol(input.courseId);
40
- await emit(StudentWasEnrolled(input));
50
+ return StudentWasEnrolled(input);
41
51
  },
42
- }).public();
43
-
44
- export const enrolments = defineModule("enrolments", {
45
- actors: [Student],
46
- actions: [enrolStudent],
47
- events: [StudentWasEnrolled],
48
52
  });
49
53
 
50
- export const app = createApp("learnflow", { modules: [enrolments] });
51
- ```
52
-
53
- ## API surface
54
-
55
- - Handler sugar: `defineAction`, `defineQuery`, `defineHandler`, `defineMiddleware`, `pipe`, response helpers.
56
- - Domain primitives: `defineActor`, `defineProjection`, `defineWorkflow`, `defineListener`, `defineCron`, `defineInbox`, `defineOutbox`, `defineExternalCall`, `defineInboundWebhook`.
57
- - Composition: `defineModule`, `defineApp`, `createApp`, `definePlugin`.
58
- - Models/errors: `defineResource`, `defineError`, `defineSchema`.
59
- - Runtime + InMemory store defaults; `MessageEnvelope` re-exported from `@nwire/envelope`.
60
-
61
- ## When to use
62
-
63
- The default surface for L3+ Nwire apps. Pull `@nwire/forge` directly when you want the full framework DX (actions, actors, projections, workflows, modules) without picking each lower package by hand.
64
-
65
- ## Used only within nwire-app
54
+ export const enrollments = defineModule("enrollments", {
55
+ events: [StudentWasEnrolled],
56
+ actors: [Student],
57
+ actions: [enrolStudent.public()],
58
+ });
66
59
 
67
- This package is part of the Nwire stack — it only makes sense inside a Nwire application built with `@nwire/app` + `@nwire/forge`. If you're looking for a standalone primitive, see:
60
+ const app = createApp({ modules: [enrollments] });
68
61
 
69
- - [`@nwire/handler`](../nwire-handler/README.md) the operation primitive (transport-agnostic)
70
- - [`@nwire/hooks`](../nwire-hooks/README.md) universal dispatch (chain + listeners)
71
- - [`@nwire/http`](../nwire-http/README.md) typed HTTP without forge
72
- - [`@nwire/endpoint`](../nwire-endpoint/README.md) — graceful shutdown for any host
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));
73
65
 
74
- ## See also
66
+ await app.start();
67
+ await app.runtime.dispatch(enrolStudent, { studentId: "avi", courseId: "heb-1" });
68
+ ```
75
69
 
76
- - [Architecture sketch §05 — Forge tier](../../architecture-sketch.html#packages)
77
- - Sibling packages: [@nwire/app](../nwire-app), [@nwire/http](../nwire-http), [@nwire/messages](../nwire-messages)
70
+ ## Surface
71
+
72
+ ### Domain primitives
73
+
74
+ | Export | Role |
75
+ | --------------------- | ------------------------------------------------------------- |
76
+ | `defineAction` | User-visible command — validated 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":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEnG,MAAM,IAAI,GAAG,YAAY,CAAC;IACxB,IAAI,EAAE,wBAAwB;IAC9B,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;CACpC,CAAC,CAAC;AACH,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC;AACpE,MAAM,GAAG,GAAG,YAAY,CAAC,mBAAmB,EAAE;IAC5C,OAAO,EAAE,CAAC,IAAI,CAAC;IACf,QAAQ,EAAE,CAAC,WAAW,CAAC;CACxB,CAAC,CAAC;AAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACxF,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxE,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAElB,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,sCAAsC,CAAC,CAAC;QAChE,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,qCAAqC,CAAC,CAAC;QAE/D,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,MAAM,KAAK,GAAG,aAAa,CACzB,YAAY,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAC9D,KAAK,IAAI,EAAE;YACT,UAAU,GAAG,IAAI,CAAC;YAClB,OAAO,SAAS,CAAC;QACnB,CAAC,CACF,CAAC;QACF,MAAM,CAAC,GAAG,YAAY,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAEpF,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;YAC1D,MAAM,CAAC,gBAAgB,EAAE,GAAG,EAAE;gBAC5B,SAAS,GAAG,IAAI,CAAC;gBACjB,OAAO,KAAK,CAAC;YACf,CAAC,CAAC,CAAC;YACH,KAAK,CAAC,gBAAgB,EAAE,GAAG,EAAE;gBAC3B,QAAQ,GAAG,IAAI,CAAC;YAClB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACjF,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAE7C,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE7B,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACtF,IAAI,QAAQ,GAAmD,IAAI,CAAC;QAEpE,MAAM,KAAK,GAAG,aAAa,CACzB,YAAY,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EACjE,KAAK,IAAI,EAAE,CAAC,SAAS,CACtB,CAAC;QACF,MAAM,CAAC,GAAG,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAEvF,MAAM,QAAQ,GAAG,YAAY,CAAC,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;YACtD,KAAK,CAAC,mBAAmB,EAAE,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE;gBACpD,QAAQ,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;YACpC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACtF,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAE7C,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,CAAC,OAAO,QAAS,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEnD,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;QACzF,MAAM,SAAS,GAAa,EAAE,CAAC;QAE/B,MAAM,KAAK,GAAG,aAAa,CACzB,YAAY,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAC/D,KAAK,IAAI,EAAE;YACT,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC1B,OAAO,SAAS,CAAC;QACnB,CAAC,CACF,CAAC;QACF,MAAM,CAAC,GAAG,YAAY,CAAC,YAAY,EAAE,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAErF,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;YAC/C,MAAM,CAAC,iBAAiB,EAAE,GAAG,EAAE;gBAC7B,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC7B,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;YAC/C,MAAM,CAAC,iBAAiB,EAAE,GAAG,EAAE;gBAC7B,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC7B,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5F,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAE7C,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;QAE/D,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -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"}