@nwire/forge 0.7.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 (259) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -0
  3. package/dist/__tests__/actor-methods.test.d.ts +9 -0
  4. package/dist/__tests__/actor-methods.test.d.ts.map +1 -0
  5. package/dist/__tests__/actor-methods.test.js +210 -0
  6. package/dist/__tests__/actor-methods.test.js.map +1 -0
  7. package/dist/__tests__/actor-schema-bound.test.d.ts +6 -0
  8. package/dist/__tests__/actor-schema-bound.test.d.ts.map +1 -0
  9. package/dist/__tests__/actor-schema-bound.test.js +112 -0
  10. package/dist/__tests__/actor-schema-bound.test.js.map +1 -0
  11. package/dist/__tests__/app-capabilities.test.d.ts +19 -0
  12. package/dist/__tests__/app-capabilities.test.d.ts.map +1 -0
  13. package/dist/__tests__/app-capabilities.test.js +57 -0
  14. package/dist/__tests__/app-capabilities.test.js.map +1 -0
  15. package/dist/__tests__/cli-runner.test.d.ts +6 -0
  16. package/dist/__tests__/cli-runner.test.d.ts.map +1 -0
  17. package/dist/__tests__/cli-runner.test.js +158 -0
  18. package/dist/__tests__/cli-runner.test.js.map +1 -0
  19. package/dist/__tests__/create-app.test.d.ts +18 -0
  20. package/dist/__tests__/create-app.test.d.ts.map +1 -0
  21. package/dist/__tests__/create-app.test.js +189 -0
  22. package/dist/__tests__/create-app.test.js.map +1 -0
  23. package/dist/__tests__/cross-service-bus.test.d.ts +8 -0
  24. package/dist/__tests__/cross-service-bus.test.d.ts.map +1 -0
  25. package/dist/__tests__/cross-service-bus.test.js +139 -0
  26. package/dist/__tests__/cross-service-bus.test.js.map +1 -0
  27. package/dist/__tests__/define-schema.test.d.ts +5 -0
  28. package/dist/__tests__/define-schema.test.d.ts.map +1 -0
  29. package/dist/__tests__/define-schema.test.js +83 -0
  30. package/dist/__tests__/define-schema.test.js.map +1 -0
  31. package/dist/__tests__/dev-logger.test.d.ts +9 -0
  32. package/dist/__tests__/dev-logger.test.d.ts.map +1 -0
  33. package/dist/__tests__/dev-logger.test.js +126 -0
  34. package/dist/__tests__/dev-logger.test.js.map +1 -0
  35. package/dist/__tests__/external-call.test.d.ts +14 -0
  36. package/dist/__tests__/external-call.test.d.ts.map +1 -0
  37. package/dist/__tests__/external-call.test.js +99 -0
  38. package/dist/__tests__/external-call.test.js.map +1 -0
  39. package/dist/__tests__/framework-events.test.d.ts +13 -0
  40. package/dist/__tests__/framework-events.test.d.ts.map +1 -0
  41. package/dist/__tests__/framework-events.test.js +204 -0
  42. package/dist/__tests__/framework-events.test.js.map +1 -0
  43. package/dist/__tests__/inline-handler.test.d.ts +8 -0
  44. package/dist/__tests__/inline-handler.test.d.ts.map +1 -0
  45. package/dist/__tests__/inline-handler.test.js +101 -0
  46. package/dist/__tests__/inline-handler.test.js.map +1 -0
  47. package/dist/__tests__/lifecycle-logging.test.d.ts +12 -0
  48. package/dist/__tests__/lifecycle-logging.test.d.ts.map +1 -0
  49. package/dist/__tests__/lifecycle-logging.test.js +112 -0
  50. package/dist/__tests__/lifecycle-logging.test.js.map +1 -0
  51. package/dist/__tests__/middleware.test.d.ts +7 -0
  52. package/dist/__tests__/middleware.test.d.ts.map +1 -0
  53. package/dist/__tests__/middleware.test.js +109 -0
  54. package/dist/__tests__/middleware.test.js.map +1 -0
  55. package/dist/__tests__/module-needs.test.d.ts +10 -0
  56. package/dist/__tests__/module-needs.test.d.ts.map +1 -0
  57. package/dist/__tests__/module-needs.test.js +77 -0
  58. package/dist/__tests__/module-needs.test.js.map +1 -0
  59. package/dist/__tests__/module-topo-sort.test.d.ts +15 -0
  60. package/dist/__tests__/module-topo-sort.test.d.ts.map +1 -0
  61. package/dist/__tests__/module-topo-sort.test.js +105 -0
  62. package/dist/__tests__/module-topo-sort.test.js.map +1 -0
  63. package/dist/__tests__/multi-tenancy.test.d.ts +10 -0
  64. package/dist/__tests__/multi-tenancy.test.d.ts.map +1 -0
  65. package/dist/__tests__/multi-tenancy.test.js +122 -0
  66. package/dist/__tests__/multi-tenancy.test.js.map +1 -0
  67. package/dist/__tests__/needs-topology.test.d.ts +11 -0
  68. package/dist/__tests__/needs-topology.test.d.ts.map +1 -0
  69. package/dist/__tests__/needs-topology.test.js +82 -0
  70. package/dist/__tests__/needs-topology.test.js.map +1 -0
  71. package/dist/__tests__/plugin-closure.test.d.ts +15 -0
  72. package/dist/__tests__/plugin-closure.test.d.ts.map +1 -0
  73. package/dist/__tests__/plugin-closure.test.js +140 -0
  74. package/dist/__tests__/plugin-closure.test.js.map +1 -0
  75. package/dist/__tests__/plugin.test.d.ts +10 -0
  76. package/dist/__tests__/plugin.test.d.ts.map +1 -0
  77. package/dist/__tests__/plugin.test.js +225 -0
  78. package/dist/__tests__/plugin.test.js.map +1 -0
  79. package/dist/__tests__/primitives.test.d.ts +9 -0
  80. package/dist/__tests__/primitives.test.d.ts.map +1 -0
  81. package/dist/__tests__/primitives.test.js +434 -0
  82. package/dist/__tests__/primitives.test.js.map +1 -0
  83. package/dist/__tests__/production-readiness.test.d.ts +22 -0
  84. package/dist/__tests__/production-readiness.test.d.ts.map +1 -0
  85. package/dist/__tests__/production-readiness.test.js +196 -0
  86. package/dist/__tests__/production-readiness.test.js.map +1 -0
  87. package/dist/__tests__/provider.test.d.ts +6 -0
  88. package/dist/__tests__/provider.test.d.ts.map +1 -0
  89. package/dist/__tests__/provider.test.js +122 -0
  90. package/dist/__tests__/provider.test.js.map +1 -0
  91. package/dist/__tests__/public-marker.test.d.ts +7 -0
  92. package/dist/__tests__/public-marker.test.d.ts.map +1 -0
  93. package/dist/__tests__/public-marker.test.js +54 -0
  94. package/dist/__tests__/public-marker.test.js.map +1 -0
  95. package/dist/__tests__/retry-dlq.test.d.ts +6 -0
  96. package/dist/__tests__/retry-dlq.test.d.ts.map +1 -0
  97. package/dist/__tests__/retry-dlq.test.js +68 -0
  98. package/dist/__tests__/retry-dlq.test.js.map +1 -0
  99. package/dist/__tests__/validate.test.d.ts +5 -0
  100. package/dist/__tests__/validate.test.d.ts.map +1 -0
  101. package/dist/__tests__/validate.test.js +53 -0
  102. package/dist/__tests__/validate.test.js.map +1 -0
  103. package/dist/__tests__/workflow-saga.test.d.ts +7 -0
  104. package/dist/__tests__/workflow-saga.test.d.ts.map +1 -0
  105. package/dist/__tests__/workflow-saga.test.js +239 -0
  106. package/dist/__tests__/workflow-saga.test.js.map +1 -0
  107. package/dist/actor-store.d.ts +83 -0
  108. package/dist/actor-store.d.ts.map +1 -0
  109. package/dist/actor-store.js +85 -0
  110. package/dist/actor-store.js.map +1 -0
  111. package/dist/cli-runner.d.ts +46 -0
  112. package/dist/cli-runner.d.ts.map +1 -0
  113. package/dist/cli-runner.js +164 -0
  114. package/dist/cli-runner.js.map +1 -0
  115. package/dist/create-app.d.ts +131 -0
  116. package/dist/create-app.d.ts.map +1 -0
  117. package/dist/create-app.js +593 -0
  118. package/dist/create-app.js.map +1 -0
  119. package/dist/define-action.d.ts +148 -0
  120. package/dist/define-action.d.ts.map +1 -0
  121. package/dist/define-action.js +52 -0
  122. package/dist/define-action.js.map +1 -0
  123. package/dist/define-actor.d.ts +302 -0
  124. package/dist/define-actor.d.ts.map +1 -0
  125. package/dist/define-actor.js +294 -0
  126. package/dist/define-actor.js.map +1 -0
  127. package/dist/define-app.d.ts +104 -0
  128. package/dist/define-app.d.ts.map +1 -0
  129. package/dist/define-app.js +49 -0
  130. package/dist/define-app.js.map +1 -0
  131. package/dist/define-cron.d.ts +50 -0
  132. package/dist/define-cron.d.ts.map +1 -0
  133. package/dist/define-cron.js +34 -0
  134. package/dist/define-cron.js.map +1 -0
  135. package/dist/define-error.d.ts +10 -0
  136. package/dist/define-error.d.ts.map +1 -0
  137. package/dist/define-error.js +10 -0
  138. package/dist/define-error.js.map +1 -0
  139. package/dist/define-external-call.d.ts +85 -0
  140. package/dist/define-external-call.d.ts.map +1 -0
  141. package/dist/define-external-call.js +38 -0
  142. package/dist/define-external-call.js.map +1 -0
  143. package/dist/define-handler.d.ts +98 -0
  144. package/dist/define-handler.d.ts.map +1 -0
  145. package/dist/define-handler.js +29 -0
  146. package/dist/define-handler.js.map +1 -0
  147. package/dist/define-inbound-webhook.d.ts +82 -0
  148. package/dist/define-inbound-webhook.d.ts.map +1 -0
  149. package/dist/define-inbound-webhook.js +42 -0
  150. package/dist/define-inbound-webhook.js.map +1 -0
  151. package/dist/define-inbox.d.ts +40 -0
  152. package/dist/define-inbox.d.ts.map +1 -0
  153. package/dist/define-inbox.js +31 -0
  154. package/dist/define-inbox.js.map +1 -0
  155. package/dist/define-initializer.d.ts +54 -0
  156. package/dist/define-initializer.d.ts.map +1 -0
  157. package/dist/define-initializer.js +38 -0
  158. package/dist/define-initializer.js.map +1 -0
  159. package/dist/define-middleware.d.ts +8 -0
  160. package/dist/define-middleware.d.ts.map +1 -0
  161. package/dist/define-middleware.js +8 -0
  162. package/dist/define-middleware.js.map +1 -0
  163. package/dist/define-model.d.ts +10 -0
  164. package/dist/define-model.d.ts.map +1 -0
  165. package/dist/define-model.js +13 -0
  166. package/dist/define-model.js.map +1 -0
  167. package/dist/define-module.d.ts +157 -0
  168. package/dist/define-module.d.ts.map +1 -0
  169. package/dist/define-module.js +60 -0
  170. package/dist/define-module.js.map +1 -0
  171. package/dist/define-outbox.d.ts +47 -0
  172. package/dist/define-outbox.d.ts.map +1 -0
  173. package/dist/define-outbox.js +36 -0
  174. package/dist/define-outbox.js.map +1 -0
  175. package/dist/define-plugin.d.ts +171 -0
  176. package/dist/define-plugin.d.ts.map +1 -0
  177. package/dist/define-plugin.js +134 -0
  178. package/dist/define-plugin.js.map +1 -0
  179. package/dist/define-projection.d.ts +56 -0
  180. package/dist/define-projection.d.ts.map +1 -0
  181. package/dist/define-projection.js +44 -0
  182. package/dist/define-projection.js.map +1 -0
  183. package/dist/define-provider.d.ts +49 -0
  184. package/dist/define-provider.d.ts.map +1 -0
  185. package/dist/define-provider.js +45 -0
  186. package/dist/define-provider.js.map +1 -0
  187. package/dist/define-query.d.ts +50 -0
  188. package/dist/define-query.d.ts.map +1 -0
  189. package/dist/define-query.js +33 -0
  190. package/dist/define-query.js.map +1 -0
  191. package/dist/define-resolver.d.ts +111 -0
  192. package/dist/define-resolver.d.ts.map +1 -0
  193. package/dist/define-resolver.js +146 -0
  194. package/dist/define-resolver.js.map +1 -0
  195. package/dist/define-schema.d.ts +88 -0
  196. package/dist/define-schema.d.ts.map +1 -0
  197. package/dist/define-schema.js +72 -0
  198. package/dist/define-schema.js.map +1 -0
  199. package/dist/define-workflow.d.ts +193 -0
  200. package/dist/define-workflow.d.ts.map +1 -0
  201. package/dist/define-workflow.js +345 -0
  202. package/dist/define-workflow.js.map +1 -0
  203. package/dist/dev-logger.d.ts +41 -0
  204. package/dist/dev-logger.d.ts.map +1 -0
  205. package/dist/dev-logger.js +135 -0
  206. package/dist/dev-logger.js.map +1 -0
  207. package/dist/event-message.d.ts +37 -0
  208. package/dist/event-message.d.ts.map +1 -0
  209. package/dist/event-message.js +51 -0
  210. package/dist/event-message.js.map +1 -0
  211. package/dist/foundation.d.ts +14 -0
  212. package/dist/foundation.d.ts.map +1 -0
  213. package/dist/foundation.js +14 -0
  214. package/dist/foundation.js.map +1 -0
  215. package/dist/framework-event-bus.d.ts +13 -0
  216. package/dist/framework-event-bus.d.ts.map +1 -0
  217. package/dist/framework-event-bus.js +13 -0
  218. package/dist/framework-event-bus.js.map +1 -0
  219. package/dist/framework-events.d.ts +121 -0
  220. package/dist/framework-events.d.ts.map +1 -0
  221. package/dist/framework-events.js +67 -0
  222. package/dist/framework-events.js.map +1 -0
  223. package/dist/index.d.ts +53 -0
  224. package/dist/index.d.ts.map +1 -0
  225. package/dist/index.js +61 -0
  226. package/dist/index.js.map +1 -0
  227. package/dist/module-surface.d.ts +47 -0
  228. package/dist/module-surface.d.ts.map +1 -0
  229. package/dist/module-surface.js +65 -0
  230. package/dist/module-surface.js.map +1 -0
  231. package/dist/projection-store.d.ts +26 -0
  232. package/dist/projection-store.d.ts.map +1 -0
  233. package/dist/projection-store.js +28 -0
  234. package/dist/projection-store.js.map +1 -0
  235. package/dist/public-marker.d.ts +35 -0
  236. package/dist/public-marker.d.ts.map +1 -0
  237. package/dist/public-marker.js +45 -0
  238. package/dist/public-marker.js.map +1 -0
  239. package/dist/response.d.ts +8 -0
  240. package/dist/response.d.ts.map +1 -0
  241. package/dist/response.js +8 -0
  242. package/dist/response.js.map +1 -0
  243. package/dist/runtime.d.ts +497 -0
  244. package/dist/runtime.d.ts.map +1 -0
  245. package/dist/runtime.js +1083 -0
  246. package/dist/runtime.js.map +1 -0
  247. package/dist/validate.d.ts +33 -0
  248. package/dist/validate.d.ts.map +1 -0
  249. package/dist/validate.js +48 -0
  250. package/dist/validate.js.map +1 -0
  251. package/dist/when.d.ts +101 -0
  252. package/dist/when.d.ts.map +1 -0
  253. package/dist/when.js +57 -0
  254. package/dist/when.js.map +1 -0
  255. package/dist/workflow-timer-store.d.ts +78 -0
  256. package/dist/workflow-timer-store.d.ts.map +1 -0
  257. package/dist/workflow-timer-store.js +56 -0
  258. package/dist/workflow-timer-store.js.map +1 -0
  259. package/package.json +60 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alex Gefter / 200apps Ltd.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # @nwire/forge
2
+
3
+ > Flavor sugar + domain primitives — the aggregation product that composes the framework into one surface.
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
10
+
11
+ ```bash
12
+ pnpm add @nwire/forge
13
+ ```
14
+
15
+ ## Quick start
16
+
17
+ ```ts
18
+ import { z } from "zod";
19
+ import { defineAction, defineActor, defineEvent, defineModule, createApp } from "@nwire/forge";
20
+
21
+ const StudentWasEnrolled = defineEvent("StudentWasEnrolled", {
22
+ schema: z.object({ studentId: z.string(), courseId: z.string() }),
23
+ }).public();
24
+
25
+ const Student = defineActor("Student", {
26
+ initial: () => ({ enrolments: [] as string[] }),
27
+ methods: {
28
+ enrol(state, courseId: string) {
29
+ return { ...state, enrolments: [...state.enrolments, courseId] };
30
+ },
31
+ },
32
+ });
33
+
34
+ const enrolStudent = defineAction("enrolStudent", {
35
+ input: z.object({ studentId: z.string(), courseId: z.string() }),
36
+ emits: [StudentWasEnrolled],
37
+ handler: async ({ input, use, emit }) => {
38
+ const student = await use(Student, input.studentId);
39
+ student.enrol(input.courseId);
40
+ await emit(StudentWasEnrolled(input));
41
+ },
42
+ }).public();
43
+
44
+ export const enrolments = defineModule("enrolments", {
45
+ actors: [Student],
46
+ actions: [enrolStudent],
47
+ events: [StudentWasEnrolled],
48
+ });
49
+
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
66
+
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:
68
+
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
73
+
74
+ ## See also
75
+
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)
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Actor methods + `ctx.use(Actor, id)` — pure invariant-enforcers + event
3
+ * minters bound to the loaded state. Methods take state, return events or
4
+ * read values, throw on invariant violation. `ctx.use` loads the actor from
5
+ * the store and returns a view with state, stateName, key, and pre-bound
6
+ * methods. The view is a snapshot — the loaded state is frozen for that view.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=actor-methods.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actor-methods.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/actor-methods.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Actor methods + `ctx.use(Actor, id)` — pure invariant-enforcers + event
3
+ * minters bound to the loaded state. Methods take state, return events or
4
+ * read values, throw on invariant violation. `ctx.use` loads the actor from
5
+ * the store and returns a view with state, stateName, key, and pre-bound
6
+ * methods. The view is a snapshot — the loaded state is frozen for that view.
7
+ */
8
+ import { describe, it, expect } from "vitest";
9
+ import { z } from "zod";
10
+ import { defineEvent } from "@nwire/messages";
11
+ import { defineAction, defineActor, defineModule, createApp, eventFactory, } from "../foundation.js";
12
+ const SubmissionSchema = z.object({
13
+ studentId: z.string(),
14
+ answer: z.string(),
15
+ flags: z.number(),
16
+ });
17
+ const SubmittedEventDef = defineEvent({
18
+ name: "sub.submitted",
19
+ schema: z.object({
20
+ submissionId: z.string(),
21
+ studentId: z.string(),
22
+ answer: z.string(),
23
+ submittedAt: z.string(),
24
+ }),
25
+ });
26
+ const Submitted = eventFactory(SubmittedEventDef);
27
+ const FlaggedEventDef = defineEvent({
28
+ name: "sub.flagged",
29
+ schema: z.object({
30
+ submissionId: z.string(),
31
+ reason: z.string(),
32
+ flaggedAt: z.string(),
33
+ }),
34
+ });
35
+ const Flagged = eventFactory(FlaggedEventDef);
36
+ const GradedEventDef = defineEvent({
37
+ name: "sub.graded",
38
+ schema: z.object({
39
+ submissionId: z.string(),
40
+ verdict: z.enum(["correct", "incorrect"]),
41
+ gradedAt: z.string(),
42
+ }),
43
+ });
44
+ const Graded = eventFactory(GradedEventDef);
45
+ const Submission = defineActor("submission", {
46
+ schema: SubmissionSchema,
47
+ key: "submissionId",
48
+ initial: "pending",
49
+ states: {
50
+ pending: {
51
+ on: {
52
+ [SubmittedEventDef.name]: {
53
+ target: "pending",
54
+ assign: (_, event) => {
55
+ const e = event;
56
+ return { studentId: e.studentId, answer: e.answer, flags: 0 };
57
+ },
58
+ },
59
+ [FlaggedEventDef.name]: {
60
+ target: "flagged",
61
+ assign: (state) => ({ flags: (state.flags ?? 0) + 1 }),
62
+ },
63
+ [GradedEventDef.name]: { target: "graded" },
64
+ },
65
+ },
66
+ flagged: {
67
+ on: {
68
+ [GradedEventDef.name]: { target: "graded" },
69
+ },
70
+ },
71
+ graded: { final: true },
72
+ },
73
+ methods: {
74
+ flagForReview(state, reason) {
75
+ if (reason.length < 3) {
76
+ throw new Error("reason too short");
77
+ }
78
+ return Flagged({
79
+ submissionId: "placeholder", // handler injects the real id
80
+ reason,
81
+ flaggedAt: new Date().toISOString(),
82
+ });
83
+ },
84
+ isGradable(state) {
85
+ return state.flags === 0;
86
+ },
87
+ flagCount(state) {
88
+ return state.flags;
89
+ },
90
+ },
91
+ });
92
+ const submitAnswer = defineAction({
93
+ name: "sub.submit-answer",
94
+ schema: z.object({ submissionId: z.string(), studentId: z.string(), answer: z.string() }),
95
+ handler: async (input) => Submitted({
96
+ submissionId: input.submissionId,
97
+ studentId: input.studentId,
98
+ answer: input.answer,
99
+ submittedAt: new Date().toISOString(),
100
+ }),
101
+ });
102
+ const flagForReview = defineAction({
103
+ name: "sub.flag-for-review",
104
+ schema: z.object({ submissionId: z.string(), reason: z.string() }),
105
+ handler: async (input, ctx) => {
106
+ const submission = await ctx.use(Submission, input.submissionId);
107
+ // methods return an event — handler returns it for the runtime to apply.
108
+ const event = submission.flagForReview(input.reason);
109
+ // Inject the real submissionId (the method had a placeholder).
110
+ return {
111
+ ...event,
112
+ payload: { ...event.payload, submissionId: input.submissionId },
113
+ };
114
+ },
115
+ });
116
+ const checkGradable = defineAction({
117
+ name: "sub.check-gradable",
118
+ schema: z.object({ submissionId: z.string() }),
119
+ handler: async (input, ctx) => {
120
+ const submission = await ctx.use(Submission, input.submissionId);
121
+ if (!submission.isGradable()) {
122
+ throw new Error(`not gradable; ${submission.flagCount()} flags`);
123
+ }
124
+ return undefined;
125
+ },
126
+ });
127
+ describe("actor methods + ctx.use", () => {
128
+ it("ctx.use loads the actor and exposes state + stateName + key", async () => {
129
+ const app = createApp({
130
+ modules: [
131
+ defineModule("m", {
132
+ actors: [Submission],
133
+ actions: [submitAnswer, checkGradable],
134
+ events: [SubmittedEventDef, FlaggedEventDef, GradedEventDef],
135
+ }),
136
+ ],
137
+ });
138
+ await app.runtime.dispatch(submitAnswer, {
139
+ submissionId: "s1",
140
+ studentId: "avi",
141
+ answer: "4",
142
+ });
143
+ // checkGradable handler reads state + invokes methods; no throw = gradable.
144
+ await app.runtime.dispatch(checkGradable, { submissionId: "s1" });
145
+ });
146
+ it("a method returning an event flows through the handler into the runtime", async () => {
147
+ const app = createApp({
148
+ modules: [
149
+ defineModule("m", {
150
+ actors: [Submission],
151
+ actions: [submitAnswer, flagForReview],
152
+ events: [SubmittedEventDef, FlaggedEventDef, GradedEventDef],
153
+ }),
154
+ ],
155
+ });
156
+ await app.runtime.dispatch(submitAnswer, {
157
+ submissionId: "s2",
158
+ studentId: "avi",
159
+ answer: "4",
160
+ });
161
+ await app.runtime.dispatch(flagForReview, {
162
+ submissionId: "s2",
163
+ reason: "contains profanity",
164
+ });
165
+ const stored = await app.runtime.getActorStore().load("submission", "s2", "");
166
+ expect(stored?.state).toBe("flagged");
167
+ expect((stored?.data).flags).toBe(1);
168
+ });
169
+ it("a method that throws an invariant error bubbles up from the handler", async () => {
170
+ const app = createApp({
171
+ modules: [
172
+ defineModule("m", {
173
+ actors: [Submission],
174
+ actions: [submitAnswer, flagForReview],
175
+ events: [SubmittedEventDef, FlaggedEventDef, GradedEventDef],
176
+ }),
177
+ ],
178
+ });
179
+ await app.runtime.dispatch(submitAnswer, {
180
+ submissionId: "s3",
181
+ studentId: "avi",
182
+ answer: "4",
183
+ });
184
+ await expect(app.runtime.dispatch(flagForReview, { submissionId: "s3", reason: "ok" })).rejects.toThrow(/reason too short/);
185
+ });
186
+ it("ctx.use returns a virgin view when the instance has never received an event", async () => {
187
+ // Phase 42.1 + 42.2 canonicalized the "virgin instance" pattern so that
188
+ // `create` methods can bootstrap a brand-new aggregate. ctx.use does
189
+ // NOT throw on a missing instance — it returns the initial state and
190
+ // lets the handler decide whether that's an error.
191
+ const app = createApp({
192
+ modules: [
193
+ defineModule("m", {
194
+ actors: [Submission],
195
+ actions: [checkGradable],
196
+ events: [SubmittedEventDef],
197
+ }),
198
+ ],
199
+ });
200
+ await expect(app.runtime.dispatch(checkGradable, { submissionId: "never-existed" })).rejects.toThrow(/not gradable/);
201
+ });
202
+ it("ctx.use throws a helpful error when the actor TYPE is not registered", async () => {
203
+ // Actor type missing from the module manifest → boot-time framework
204
+ // problem, not a runtime data problem. Distinct from the virgin-
205
+ // instance case above.
206
+ const app = createApp({ modules: [defineModule("m", { actions: [checkGradable] })] });
207
+ await expect(app.runtime.dispatch(checkGradable, { submissionId: "x" })).rejects.toThrow(/not registered/);
208
+ });
209
+ });
210
+ //# sourceMappingURL=actor-methods.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actor-methods.test.js","sourceRoot":"","sources":["../../src/__tests__/actor-methods.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * defineActor — schema-bound form. The schema provides key/initial/final;
3
+ * the actor provides transitions per state.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=actor-schema-bound.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actor-schema-bound.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/actor-schema-bound.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * defineActor — schema-bound form. The schema provides key/initial/final;
3
+ * the actor provides transitions per state.
4
+ */
5
+ import { describe, it, expect } from "vitest";
6
+ import { z } from "zod";
7
+ import { defineEvent } from "@nwire/messages";
8
+ import { defineActor } from "../define-actor.js";
9
+ import { defineSchema } from "../define-schema.js";
10
+ const AnswerWasSubmitted = defineEvent({
11
+ name: "submissions.answer-was-submitted",
12
+ schema: z.object({ submissionId: z.string(), answer: z.string() }),
13
+ });
14
+ const AnswerWasFlagged = defineEvent({
15
+ name: "submissions.answer-was-flagged",
16
+ schema: z.object({ submissionId: z.string(), confidence: z.number() }),
17
+ });
18
+ const SubmissionWasManuallyGraded = defineEvent({
19
+ name: "submissions.was-manually-graded",
20
+ schema: z.object({ submissionId: z.string(), verdict: z.string() }),
21
+ });
22
+ const SubmissionData = defineSchema({
23
+ name: "submission",
24
+ key: "submissionId",
25
+ fields: {
26
+ submissionId: z.string(),
27
+ answer: z.string().optional(),
28
+ confidence: z.number().optional(),
29
+ verdict: z.string().optional(),
30
+ },
31
+ states: {
32
+ submitted: { initial: true },
33
+ "under-review": {},
34
+ graded: { final: true },
35
+ },
36
+ });
37
+ describe("defineActor (schema-bound)", () => {
38
+ it("derives name, key, initial, and final states from the schema", () => {
39
+ const Submission = defineActor({
40
+ schema: SubmissionData,
41
+ states: {
42
+ submitted: {
43
+ on: {
44
+ [AnswerWasSubmitted.name]: {
45
+ assign: (_s, e) => ({ answer: e.answer }),
46
+ },
47
+ [AnswerWasFlagged.name]: {
48
+ target: "under-review",
49
+ assign: (_s, e) => ({ confidence: e.confidence }),
50
+ },
51
+ },
52
+ },
53
+ "under-review": {
54
+ on: {
55
+ [SubmissionWasManuallyGraded.name]: {
56
+ target: "graded",
57
+ assign: (_s, e) => ({ verdict: e.verdict }),
58
+ },
59
+ },
60
+ },
61
+ },
62
+ });
63
+ expect(Submission.name).toBe("submission");
64
+ expect(Submission.key).toBe("submissionId");
65
+ expect(Submission.initial).toBe("submitted");
66
+ expect(Submission.states.graded?.final).toBe(true);
67
+ expect(Submission.eventIndex.size).toBe(3);
68
+ });
69
+ it("allows a custom name to override the schema's", () => {
70
+ const Renamed = defineActor({
71
+ name: "my-submission",
72
+ schema: SubmissionData,
73
+ });
74
+ expect(Renamed.name).toBe("my-submission");
75
+ });
76
+ it("rejects transitions for states not in the schema", () => {
77
+ expect(() => defineActor({
78
+ schema: SubmissionData,
79
+ states: {
80
+ unknown: { on: { [AnswerWasSubmitted.name]: {} } },
81
+ },
82
+ })).toThrow(/state "unknown" is not declared in schema/);
83
+ });
84
+ it("rejects on: reactions on final states", () => {
85
+ expect(() => defineActor({
86
+ schema: SubmissionData,
87
+ states: {
88
+ graded: { on: { [AnswerWasSubmitted.name]: {} } },
89
+ },
90
+ })).toThrow(/is final in schema/);
91
+ });
92
+ it("typed methods are still callable from the actor instance view", () => {
93
+ const Submission = defineActor({
94
+ schema: SubmissionData,
95
+ methods: {
96
+ isGraded: (state) => state.verdict !== undefined,
97
+ },
98
+ });
99
+ expect(Submission.methods?.isGraded).toBeTypeOf("function");
100
+ });
101
+ it("classic positional form still works", () => {
102
+ const Legacy = defineActor("legacy", {
103
+ schema: z.object({ id: z.string() }),
104
+ key: "id",
105
+ initial: "open",
106
+ states: { open: {}, closed: { final: true } },
107
+ });
108
+ expect(Legacy.name).toBe("legacy");
109
+ expect(Legacy.initial).toBe("open");
110
+ });
111
+ });
112
+ //# sourceMappingURL=actor-schema-bound.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actor-schema-bound.test.js","sourceRoot":"","sources":["../../src/__tests__/actor-schema-bound.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `createApp` registers app capabilities (`execute`, `send`, `useProjection`)
3
+ * on the container so handlers in any transport — http, queue, cli —
4
+ * can resolve them as plain functions:
5
+ *
6
+ * const execute = ctx.resolve<ExecuteFn>("execute");
7
+ * const result = await execute(myAction, input);
8
+ *
9
+ * Each capability seeds a fresh envelope. Use cases:
10
+ * - HTTP handler dispatching an action from an external request
11
+ * - Queue worker processing a job that triggers an action
12
+ * - CLI command invoking app behavior
13
+ *
14
+ * Inside a handler/workflow with an existing envelope, the in-flight
15
+ * ctx.request / ctx.send / ctx.query still inherit the parent envelope
16
+ * — those are unaffected.
17
+ */
18
+ export {};
19
+ //# sourceMappingURL=app-capabilities.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-capabilities.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/app-capabilities.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * `createApp` registers app capabilities (`execute`, `send`, `useProjection`)
3
+ * on the container so handlers in any transport — http, queue, cli —
4
+ * can resolve them as plain functions:
5
+ *
6
+ * const execute = ctx.resolve<ExecuteFn>("execute");
7
+ * const result = await execute(myAction, input);
8
+ *
9
+ * Each capability seeds a fresh envelope. Use cases:
10
+ * - HTTP handler dispatching an action from an external request
11
+ * - Queue worker processing a job that triggers an action
12
+ * - CLI command invoking app behavior
13
+ *
14
+ * Inside a handler/workflow with an existing envelope, the in-flight
15
+ * ctx.request / ctx.send / ctx.query still inherit the parent envelope
16
+ * — those are unaffected.
17
+ */
18
+ import { describe, it, expect } from "vitest";
19
+ import { z } from "zod";
20
+ import { defineAction, defineModule, createApp } from "../foundation.js";
21
+ describe("createApp app capabilities on container", () => {
22
+ it("execute resolves and dispatches an action", async () => {
23
+ let sum = 0;
24
+ const sumAction = defineAction({
25
+ name: "sum",
26
+ schema: z.object({ a: z.number(), b: z.number() }),
27
+ handler: async (input) => {
28
+ sum = input.a + input.b;
29
+ return undefined;
30
+ },
31
+ });
32
+ const app = createApp({ modules: [defineModule("m", { actions: [sumAction] })] });
33
+ await app.start();
34
+ const execute = app.runtime.getContainer().resolve("execute");
35
+ await execute(sumAction, { a: 2, b: 3 });
36
+ expect(sum).toBe(5);
37
+ await app.stop();
38
+ });
39
+ it("send dispatches fire-and-forget", async () => {
40
+ let seen;
41
+ const recordAction = defineAction({
42
+ name: "record",
43
+ schema: z.object({ tag: z.string() }),
44
+ handler: async (input) => {
45
+ seen = input;
46
+ return undefined;
47
+ },
48
+ });
49
+ const app = createApp({ modules: [defineModule("m", { actions: [recordAction] })] });
50
+ await app.start();
51
+ const send = app.runtime.getContainer().resolve("send");
52
+ await send(recordAction, { tag: "hello" });
53
+ expect(seen).toEqual({ tag: "hello" });
54
+ await app.stop();
55
+ });
56
+ });
57
+ //# sourceMappingURL=app-capabilities.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-capabilities.test.js","sourceRoot":"","sources":["../../src/__tests__/app-capabilities.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAOtE,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACvD,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,MAAM,SAAS,GAAG,YAAY,CAAC;YAC7B,IAAI,EAAE,KAAK;YACX,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;YAClD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;gBACvB,GAAG,GAAG,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;gBACxB,OAAO,SAAS,CAAC;YACnB,CAAC;SACF,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAClF,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAElB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,OAAO,CAAY,SAAS,CAAC,CAAC;QACzE,MAAM,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACzC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAEpB,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,IAAI,IAAa,CAAC;QAClB,MAAM,YAAY,GAAG,YAAY,CAAC;YAChC,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;YACrC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;gBACvB,IAAI,GAAG,KAAK,CAAC;gBACb,OAAO,SAAS,CAAC;YACnB,CAAC;SACF,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACrF,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAElB,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,OAAO,CAAY,MAAM,CAAC,CAAC;QACnE,MAAM,IAAI,CAAC,YAAY,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAEvC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * CLI runner — contract test. Verifies argv parsing → action/query dispatch
3
+ * → stdout/stderr capture, with no actual process spawning.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=cli-runner.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-runner.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/cli-runner.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}