@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
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `defineModel` — re-exported from `@nwire/handler` as `defineResource`.
3
+ *
4
+ * The canonical name for the interface/response shape primitive moved
5
+ * to `defineResource` in `@nwire/handler` as part of the v1.0 sealed-
6
+ * architecture extraction. Forge re-exports under both names so existing
7
+ * call sites compile unchanged.
8
+ */
9
+ export { defineModel, isModelDefinition,
10
+ // New canonical names also exposed for forge consumers that want
11
+ // to track the spec vocabulary.
12
+ defineResource, isResourceDefinition, } from "@nwire/handler";
13
+ //# sourceMappingURL=define-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-model.js","sourceRoot":"","sources":["../src/define-model.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,WAAW,EACX,iBAAiB;AACjB,iEAAiE;AACjE,gCAAgC;AAChC,cAAc,EACd,oBAAoB,GAKrB,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * `defineModule` — a bounded context as an explicit table of contents.
3
+ *
4
+ * export default defineModule('submissions', {
5
+ * actions: [submitAnswer, flagForReview, gradeSubmission, autoGrade],
6
+ * actors: [Submission],
7
+ * projections: [SubmissionsByStudent],
8
+ * queries: [submissionsByStudent, submissionById],
9
+ * events: [AnswerSubmittedEvent, AnswerFlaggedForReviewEvent, ...],
10
+ * handlers: [submitAnswerHandler, flagForReviewHandler, ...],
11
+ * workflows: [autoGradeWorkflow, notifyOnFlaggedWorkflow]
12
+ * })
13
+ *
14
+ * Modules own DOMAIN, not transport — route bindings live in the app layer
15
+ * (transport interface builders) where they belong. Auto-discovery (file
16
+ * globs, directory walks) is rejected: new team members read one file to
17
+ * find every surface in the module. The module is what `createApp` registers
18
+ * with the runtime.
19
+ */
20
+ import type { ActionDefinition } from "./define-action.js";
21
+ import type { ActorDefinition } from "./define-actor.js";
22
+ import type { HandlerDefinition } from "./define-handler.js";
23
+ import type { ProjectionDefinition } from "./define-projection.js";
24
+ import type { QueryDefinition } from "./define-query.js";
25
+ import type { WorkflowDefinition } from "./define-workflow.js";
26
+ import type { EventDefinition } from "@nwire/messages";
27
+ import type { ExternalCallDefinition } from "./define-external-call.js";
28
+ import type { InboundWebhookDefinition } from "./define-inbound-webhook.js";
29
+ import type { OutboxDefinition } from "./define-outbox.js";
30
+ import type { InboxDefinition } from "./define-inbox.js";
31
+ import type { CronDefinition } from "./define-cron.js";
32
+ import type { NwireInterface } from "@nwire/interface";
33
+ /**
34
+ * Cross-module dependencies declared by this module.
35
+ *
36
+ * The existing `events` and `actions` arrays on a manifest serve as the
37
+ * module's implicit **provides** (what it owns + emits). `needs` declares
38
+ * the inverse — what this module consumes from other modules.
39
+ *
40
+ * defineModule('mastery', {
41
+ * events: [MasteryContributionRecordedEvent], // this module's provides
42
+ * workflows: [updateOnGradedReaction], // listens to ...
43
+ * needs: {
44
+ * events: [SubmissionAutoGradedEvent, SubmissionManuallyGradedEvent]
45
+ * }
46
+ * })
47
+ *
48
+ * `createApp` validates the resulting dep graph at startup:
49
+ * - every needed event must be in some OTHER module's `events` array,
50
+ * - the producing event must be `visibility: 'public'` (the default),
51
+ * - every needed action must be in some other module's `actions`,
52
+ * - a module may not `need` what it itself provides (self-reference).
53
+ *
54
+ * Violations throw with a message that names the offending module + ref.
55
+ * This catches typos and refactor breakage at boot, before the first
56
+ * real dispatch, and makes the cross-module graph explicit for readers.
57
+ */
58
+ export interface ModuleNeeds {
59
+ /**
60
+ * Events this module subscribes to that are provided by another module in
61
+ * the SAME app/service. Validated in-process at createApp.
62
+ */
63
+ readonly events?: readonly EventDefinition[];
64
+ /**
65
+ * Actions this module dispatches that are provided by another module in
66
+ * the SAME app/service. Validated in-process at createApp.
67
+ */
68
+ readonly actions?: readonly ActionDefinition[];
69
+ /**
70
+ * Events this module subscribes to that originate in OTHER services (a
71
+ * different `defineApp(...)` running in a different process). These flow
72
+ * over the configured `EventBus` (`@nwire/bus`). createApp:
73
+ * - rejects an externalEvent that ALSO appears in this app's provides
74
+ * (you don't reach across the bus for your own publishes),
75
+ * - auto-subscribes the bus to each external event name at boot,
76
+ * - routes received bus messages to `runtime.applyExternalEvent`.
77
+ *
78
+ * If the app has no bus configured but a module declares externalEvents,
79
+ * createApp throws — the dep is unsatisfiable.
80
+ */
81
+ readonly externalEvents?: readonly EventDefinition[];
82
+ }
83
+ /** A journey step a bounded context owns — Studio renders these as the
84
+ * spine of its persona view. `id` ties back to action.journeyStep. */
85
+ export interface JourneyStep {
86
+ readonly id: string;
87
+ readonly label: string;
88
+ readonly description?: string;
89
+ }
90
+ export interface ModuleManifest {
91
+ readonly actions?: readonly ActionDefinition[];
92
+ readonly actors?: readonly ActorDefinition<any>[];
93
+ readonly handlers?: readonly HandlerDefinition<any>[];
94
+ readonly projections?: readonly ProjectionDefinition<any>[];
95
+ readonly queries?: readonly QueryDefinition<any, any, any>[];
96
+ readonly events?: readonly EventDefinition[];
97
+ /**
98
+ * Optional split of `events` into domain (BC-internal) + integration
99
+ * (public bus contract). If both are provided, `events` is computed as
100
+ * the union. If only `events` is provided, scope is inferred from
101
+ * each event's `scope` / `visibility`.
102
+ */
103
+ readonly domainEvents?: readonly EventDefinition[];
104
+ readonly integrationEvents?: readonly EventDefinition[];
105
+ /**
106
+ * Workflows — the unified primitive for event-driven side effects
107
+ * (reactions, translators, sagas). One declaration, three sophistication
108
+ * levels; the runtime picks fast-path dispatch vs full saga semantics
109
+ * based on what each workflow declares.
110
+ */
111
+ readonly workflows?: readonly WorkflowDefinition[];
112
+ readonly needs?: ModuleNeeds;
113
+ readonly externalCalls?: readonly ExternalCallDefinition<any, any>[];
114
+ readonly inboundWebhooks?: readonly InboundWebhookDefinition<any>[];
115
+ readonly outboxes?: readonly OutboxDefinition[];
116
+ readonly inboxes?: readonly InboxDefinition[];
117
+ readonly crons?: readonly CronDefinition[];
118
+ /**
119
+ * Wires the module owns — transport interfaces (http / queue / mcp / …)
120
+ * declared inside the module's own `__wires__/` folder. The fractal
121
+ * "module ≅ small project" layout means a module can ship its own
122
+ * transports for embedded / standalone runs; the parent app composes
123
+ * them onto its endpoint at boot.
124
+ *
125
+ * Wires here are values produced by `http()` / `queue()` / `mcp()` /
126
+ * etc. — they extend `InterfaceBuilder` and are servable by
127
+ * `@nwire/endpoint`. The framework treats them as opaque at the module
128
+ * layer; transports own the semantics.
129
+ */
130
+ readonly wires?: readonly NwireInterface[];
131
+ /** Studio-aware: free-form description. */
132
+ readonly description?: string;
133
+ /** Studio-aware: owning team/people identifiers. */
134
+ readonly owners?: readonly string[];
135
+ /** Studio-aware: declared journey steps this BC owns. */
136
+ readonly journey?: readonly JourneyStep[];
137
+ }
138
+ /**
139
+ * Public surface of a module — the names of every item this module
140
+ * exposed via `.public()` in its manifest. `createApp` validates cross-
141
+ * module needs against these sets; runtime cross-module dispatch is
142
+ * permitted only for names that appear here.
143
+ */
144
+ export interface ModulePublicSurface {
145
+ readonly actions: ReadonlySet<string>;
146
+ readonly events: ReadonlySet<string>;
147
+ readonly queries: ReadonlySet<string>;
148
+ readonly workflows: ReadonlySet<string>;
149
+ }
150
+ export interface ModuleDefinition {
151
+ readonly $kind: "module";
152
+ readonly name: string;
153
+ readonly manifest: ModuleManifest;
154
+ readonly publicSurface: ModulePublicSurface;
155
+ }
156
+ export declare function defineModule(name: string, manifest: ModuleManifest): ModuleDefinition;
157
+ //# sourceMappingURL=define-module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-module.d.ts","sourceRoot":"","sources":["../src/define-module.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * `defineModule` — a bounded context as an explicit table of contents.
3
+ *
4
+ * export default defineModule('submissions', {
5
+ * actions: [submitAnswer, flagForReview, gradeSubmission, autoGrade],
6
+ * actors: [Submission],
7
+ * projections: [SubmissionsByStudent],
8
+ * queries: [submissionsByStudent, submissionById],
9
+ * events: [AnswerSubmittedEvent, AnswerFlaggedForReviewEvent, ...],
10
+ * handlers: [submitAnswerHandler, flagForReviewHandler, ...],
11
+ * workflows: [autoGradeWorkflow, notifyOnFlaggedWorkflow]
12
+ * })
13
+ *
14
+ * Modules own DOMAIN, not transport — route bindings live in the app layer
15
+ * (transport interface builders) where they belong. Auto-discovery (file
16
+ * globs, directory walks) is rejected: new team members read one file to
17
+ * find every surface in the module. The module is what `createApp` registers
18
+ * with the runtime.
19
+ */
20
+ function namesOf(items) {
21
+ const out = new Set();
22
+ for (const it of items ?? []) {
23
+ if (it.$public === true)
24
+ out.add(it.name);
25
+ }
26
+ return out;
27
+ }
28
+ export function defineModule(name, manifest) {
29
+ // If the user split events into domainEvents + integrationEvents, auto-merge
30
+ // into `events` so downstream registries find them. If the user provided
31
+ // their own `events` too, prefer the explicit value.
32
+ const split = [...(manifest.domainEvents ?? []), ...(manifest.integrationEvents ?? [])];
33
+ const events = manifest.events ?? (split.length > 0 ? split : undefined);
34
+ // The public surface is whatever was tagged `.public()` in this manifest.
35
+ // Until the example codebase fully migrates, events with the older
36
+ // `visibility: "public"` flag are also treated as part of the surface so
37
+ // pre-existing modules keep working.
38
+ const publicSurface = {
39
+ actions: namesOf(manifest.actions),
40
+ queries: namesOf(manifest.queries),
41
+ workflows: namesOf(manifest.workflows),
42
+ events: (() => {
43
+ const s = namesOf(events);
44
+ for (const e of events ?? []) {
45
+ if (e.$public === true)
46
+ s.add(e.name);
47
+ else if (e.visibility === "public")
48
+ s.add(e.name);
49
+ }
50
+ return s;
51
+ })(),
52
+ };
53
+ return {
54
+ $kind: "module",
55
+ name,
56
+ manifest: { ...manifest, events },
57
+ publicSurface,
58
+ };
59
+ }
60
+ //# sourceMappingURL=define-module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-module.js","sourceRoot":"","sources":["../src/define-module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAuJH,SAAS,OAAO,CACd,KAA+B;IAE/B,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,EAAE,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;QAC7B,IAAI,EAAE,CAAC,OAAO,KAAK,IAAI;YAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,QAAwB;IACjE,6EAA6E;IAC7E,yEAAyE;IACzE,qDAAqD;IACrD,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,CAAC;IACxF,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEzE,0EAA0E;IAC1E,mEAAmE;IACnE,yEAAyE;IACzE,qCAAqC;IACrC,MAAM,aAAa,GAAwB;QACzC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;QAClC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;QAClC,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;QACtC,MAAM,EAAE,CAAC,GAAG,EAAE;YACZ,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;YAC1B,KAAK,MAAM,CAAC,IAAI,MAAM,IAAI,EAAE,EAAE,CAAC;gBAC7B,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI;oBAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;qBACjC,IAAK,CAA6B,CAAC,UAAU,KAAK,QAAQ;oBAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACjF,CAAC;YACD,OAAO,CAAC,CAAC;QACX,CAAC,CAAC,EAAE;KACL,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,QAAQ;QACf,IAAI;QACJ,QAAQ,EAAE,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE;QACjC,aAAa;KACd,CAAC;AACJ,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * `defineOutbox` — declarative transactional outbox.
3
+ *
4
+ * export const ordersOutbox = defineOutbox({
5
+ * name: "orders",
6
+ * publishes: [OrderPlacedEvent, OrderShippedEvent],
7
+ * flushIntervalMs: 200,
8
+ * maxBatch: 100,
9
+ * });
10
+ *
11
+ * An outbox is a durable queue local to the service: events are written
12
+ * to it inside the same transaction as the business state change. A
13
+ * separate flusher reads the outbox and publishes events to the
14
+ * cross-service bus. Guarantees at-least-once delivery — readers handle
15
+ * dedup via inbox (`defineInbox`).
16
+ *
17
+ * The framework treats outboxes as first-class so Studio can render them
18
+ * as boundary stickies and surface depth + flush latency + failed-flush
19
+ * counts as drift signals.
20
+ *
21
+ * Runtime: a registered `OutboxStore` adapter holds pending entries; a
22
+ * flusher (`@nwire/outbox-poller` or BullMQ-backed) drains it. The
23
+ * runtime emits `outbox.flushed` telemetry on each batch.
24
+ */
25
+ import type { EventDefinition } from "@nwire/messages";
26
+ export interface OutboxMeta {
27
+ readonly name: string;
28
+ readonly description?: string;
29
+ /** Events this outbox is allowed to publish — Studio uses this to draw arrows. */
30
+ readonly publishes: readonly EventDefinition[];
31
+ /** Flush interval in milliseconds. Default 1000. */
32
+ readonly flushIntervalMs?: number;
33
+ /** Max batch size per flush. Default 100. */
34
+ readonly maxBatch?: number;
35
+ readonly tags?: readonly string[];
36
+ }
37
+ export interface OutboxDefinition {
38
+ readonly $kind: "outbox";
39
+ readonly name: string;
40
+ readonly description?: string;
41
+ readonly publishes: readonly EventDefinition[];
42
+ readonly flushIntervalMs: number;
43
+ readonly maxBatch: number;
44
+ readonly tags?: readonly string[];
45
+ }
46
+ export declare function defineOutbox(meta: OutboxMeta): OutboxDefinition;
47
+ //# sourceMappingURL=define-outbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-outbox.d.ts","sourceRoot":"","sources":["../src/define-outbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,kFAAkF;IAClF,QAAQ,CAAC,SAAS,EAAE,SAAS,eAAe,EAAE,CAAC;IAC/C,oDAAoD;IACpD,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,SAAS,eAAe,EAAE,CAAC;IAC/C,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,gBAAgB,CAU/D"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * `defineOutbox` — declarative transactional outbox.
3
+ *
4
+ * export const ordersOutbox = defineOutbox({
5
+ * name: "orders",
6
+ * publishes: [OrderPlacedEvent, OrderShippedEvent],
7
+ * flushIntervalMs: 200,
8
+ * maxBatch: 100,
9
+ * });
10
+ *
11
+ * An outbox is a durable queue local to the service: events are written
12
+ * to it inside the same transaction as the business state change. A
13
+ * separate flusher reads the outbox and publishes events to the
14
+ * cross-service bus. Guarantees at-least-once delivery — readers handle
15
+ * dedup via inbox (`defineInbox`).
16
+ *
17
+ * The framework treats outboxes as first-class so Studio can render them
18
+ * as boundary stickies and surface depth + flush latency + failed-flush
19
+ * counts as drift signals.
20
+ *
21
+ * Runtime: a registered `OutboxStore` adapter holds pending entries; a
22
+ * flusher (`@nwire/outbox-poller` or BullMQ-backed) drains it. The
23
+ * runtime emits `outbox.flushed` telemetry on each batch.
24
+ */
25
+ export function defineOutbox(meta) {
26
+ return {
27
+ $kind: "outbox",
28
+ name: meta.name,
29
+ description: meta.description,
30
+ publishes: meta.publishes,
31
+ flushIntervalMs: meta.flushIntervalMs ?? 1000,
32
+ maxBatch: meta.maxBatch ?? 100,
33
+ tags: meta.tags,
34
+ };
35
+ }
36
+ //# sourceMappingURL=define-outbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-outbox.js","sourceRoot":"","sources":["../src/define-outbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA0BH,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,OAAO;QACL,KAAK,EAAE,QAAQ;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,eAAe,EAAE,IAAI,CAAC,eAAe,IAAI,IAAI;QAC7C,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,GAAG;QAC9B,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * `definePlugin` — first-class extension primitive.
3
+ *
4
+ * Plugins extend the FRAMEWORK; modules provide DOMAIN. The distinction is
5
+ * load-bearing — module code is "what the system does"; plugin code is
6
+ * "what cuts across the system."
7
+ *
8
+ * Plugin examples (cross-cutting):
9
+ * - Tracing: open a span around every dispatch (middleware).
10
+ * - Audit log: persist {action, user, input, result} per dispatch.
11
+ * - Authz: enforce per-action policy before dispatch.
12
+ * - Rate-limiting: throttle dispatches by user / tenant / action.
13
+ * - Observability: register Prometheus metrics, expose /metrics.
14
+ *
15
+ * Two authoring forms — pick whichever is clearer:
16
+ *
17
+ * 1. Closure form (recommended for most plugins):
18
+ *
19
+ * definePlugin("audit", ({ bind, on, after, middleware, boot }) => {
20
+ * const log = bind("auditLog", () => new AuditLog())
21
+ * after("post.publish", async ({ result }) => log.write(result))
22
+ * middleware(async (next, action, input, ctx) => {
23
+ * log.start(ctx.envelope.messageId, action.name)
24
+ * try { return await next() }
25
+ * finally { log.finish(ctx.envelope.messageId) }
26
+ * })
27
+ * boot(async () => log.connect())
28
+ * })
29
+ *
30
+ * 2. Object form (kept for back-compat and explicit-lifecycle cases):
31
+ *
32
+ * definePlugin("audit", {
33
+ * register: (container) => container.register("auditLog", ...),
34
+ * boot: async (container) => { ... },
35
+ * shutdown: async (container) => { ... },
36
+ * middleware: [ ... ],
37
+ * })
38
+ *
39
+ * The closure form's `on`/`before`/`after` subscribe to framework events
40
+ * (see `framework-events.ts`) so plugins can react to lifecycle and
41
+ * dispatch events the same way they'd react to a domain event — there is
42
+ * no separate "hooks" system.
43
+ *
44
+ * Plugins are listed in `createApp({ plugins: [...] })`. Sequencing:
45
+ * start: plugin register / setup (sync) → providers boot → plugin boot
46
+ * stop: shutdown plugins in reverse → shutdown providers in reverse
47
+ */
48
+ import type { Container } from "@nwire/container";
49
+ import type { DispatchMiddleware, Runtime } from "./runtime.js";
50
+ import type { EventMessage } from "./event-message.js";
51
+ import type { ActorDefinition } from "./define-actor.js";
52
+ import type { MessageEnvelope } from "@nwire/envelope";
53
+ import type { FrameworkEventDefinition } from "./framework-events.js";
54
+ import type { FrameworkEventHandler } from "./framework-event-bus.js";
55
+ /** Hook fired by the runtime after an actor transitions to a new state. */
56
+ export type ActorTransitionHook = (actor: ActorDefinition, key: string, fromState: string, toState: string, event: EventMessage, envelope: MessageEnvelope) => Promise<void> | void;
57
+ export interface PluginActorHooks {
58
+ readonly afterTransition?: ActorTransitionHook;
59
+ }
60
+ /**
61
+ * The builder passed to a closure-form plugin. Every method mutates the
62
+ * world (container, runtime) immediately — there's no separate "apply"
63
+ * step. Returning values from `bind` gives ergonomic access to the just-
64
+ * registered binding (handy when the plugin's own subscriptions need it).
65
+ */
66
+ export interface PluginContext {
67
+ readonly container: Container;
68
+ readonly runtime: Runtime;
69
+ readonly config: Record<string, any>;
70
+ /**
71
+ * Register a singleton on the container. The factory runs once, lazily,
72
+ * the first time something resolves the name. Returns the binding name
73
+ * so callers can immediately resolve if needed.
74
+ */
75
+ bind<T>(name: string, factory: () => T): string;
76
+ /** Resolve a previously-bound value (provider or other plugin's bind). */
77
+ resolve<T>(name: string): T;
78
+ /**
79
+ * Subscribe to ANY event — framework or domain. For framework events the
80
+ * payload type is the event's `__payload` marker. For domain events use
81
+ * `runtime.frameworkEvents` directly or rely on the workflow primitive.
82
+ */
83
+ on<TPayload>(event: FrameworkEventDefinition<TPayload>, handler: FrameworkEventHandler<TPayload>, priority?: number): void;
84
+ /**
85
+ * Sugar over `on(ActionDispatching, ...)` scoped to one action. Return
86
+ * `false` to veto the dispatch (interceptable). Throw to fail.
87
+ *
88
+ * before("post.publish", async ({ ctx }) => {
89
+ * if (!ctx.envelope.user) return false // reject anonymous
90
+ * })
91
+ */
92
+ before(actionName: string, handler: (payload: {
93
+ readonly action: import("./define-action.js").ActionDefinition;
94
+ readonly input: unknown;
95
+ readonly ctx: import("./define-handler.js").HandlerContext;
96
+ }) => Promise<void | boolean> | void | boolean): void;
97
+ /**
98
+ * Sugar over `on(ActionCompleted, ...)` scoped to one action. Observable;
99
+ * runs in parallel with other subscribers. Throws are logged, not fatal.
100
+ */
101
+ after(actionName: string, handler: (payload: {
102
+ readonly action: import("./define-action.js").ActionDefinition;
103
+ readonly input: unknown;
104
+ readonly result: unknown;
105
+ readonly durationMs: number;
106
+ }) => Promise<void> | void): void;
107
+ /** Add a dispatch middleware. Onion-style; first call is outermost. */
108
+ middleware(mw: DispatchMiddleware): void;
109
+ /** Hook actor transitions (every actor, every state change, every event). */
110
+ actorHook(hook: ActorTransitionHook): void;
111
+ /** Register an async boot callback — runs after all providers booted. */
112
+ boot(fn: () => Promise<void> | void): void;
113
+ /** Register an async shutdown callback — runs in REVERSE registration order. */
114
+ shutdown(fn: () => Promise<void> | void): void;
115
+ }
116
+ /** The closure form's setup signature. */
117
+ export type PluginSetup = (ctx: PluginContext) => void | Promise<void>;
118
+ export interface PluginDefinition {
119
+ readonly $kind: "plugin";
120
+ readonly name: string;
121
+ /**
122
+ * Synchronous container registration — runs before any provider boot.
123
+ * Use for value bindings the plugin will need later.
124
+ */
125
+ readonly register?: (container: Container) => void;
126
+ /**
127
+ * Closure-form setup. The framework runs this during plugin-register
128
+ * with `{ container, runtime, config }` and the builder helpers. Only
129
+ * set by the closure form; object-form plugins leave it undefined.
130
+ */
131
+ readonly setup?: PluginSetup;
132
+ /**
133
+ * Async startup. Runs AFTER providers have booted, BEFORE modules begin
134
+ * receiving traffic. Use for any I/O the plugin needs (connect to OTEL
135
+ * collector, prefetch policy, warm cache).
136
+ */
137
+ readonly boot?: (container: Container) => Promise<void> | void;
138
+ /** Async teardown. Runs in reverse plugin order on app.stop(). */
139
+ readonly shutdown?: (container: Container) => Promise<void> | void;
140
+ /** Dispatch middlewares the plugin contributes. Runs onion-style. */
141
+ readonly middleware?: readonly DispatchMiddleware[];
142
+ /** Actor lifecycle hooks the plugin contributes. */
143
+ readonly actorHooks?: PluginActorHooks;
144
+ }
145
+ export interface PluginOptions {
146
+ readonly register?: (container: Container) => void;
147
+ readonly boot?: (container: Container) => Promise<void> | void;
148
+ readonly shutdown?: (container: Container) => Promise<void> | void;
149
+ readonly middleware?: readonly DispatchMiddleware[];
150
+ readonly actorHooks?: PluginActorHooks;
151
+ }
152
+ /**
153
+ * Two callable shapes:
154
+ *
155
+ * definePlugin("name", (ctx) => { ... }) // closure form
156
+ * definePlugin("name", { register, boot, ... }) // object form
157
+ */
158
+ export declare function definePlugin(name: string, setup: PluginSetup): PluginDefinition;
159
+ export declare function definePlugin(name: string, options: PluginOptions): PluginDefinition;
160
+ /**
161
+ * Build a PluginContext bound to a specific container + runtime + config,
162
+ * collecting boot/shutdown callbacks the closure registers. Used by
163
+ * createApp's plugin-register loop. Returns the bound API + the lists of
164
+ * boot/shutdown functions for createApp to wire into its lifecycle.
165
+ */
166
+ export declare function buildPluginContext(container: Container, runtime: Runtime, config: Record<string, any>): {
167
+ readonly api: PluginContext;
168
+ readonly boots: Array<() => Promise<void> | void>;
169
+ readonly shutdowns: Array<() => Promise<void> | void>;
170
+ };
171
+ //# sourceMappingURL=define-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-plugin.d.ts","sourceRoot":"","sources":["../src/define-plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * `definePlugin` — first-class extension primitive.
3
+ *
4
+ * Plugins extend the FRAMEWORK; modules provide DOMAIN. The distinction is
5
+ * load-bearing — module code is "what the system does"; plugin code is
6
+ * "what cuts across the system."
7
+ *
8
+ * Plugin examples (cross-cutting):
9
+ * - Tracing: open a span around every dispatch (middleware).
10
+ * - Audit log: persist {action, user, input, result} per dispatch.
11
+ * - Authz: enforce per-action policy before dispatch.
12
+ * - Rate-limiting: throttle dispatches by user / tenant / action.
13
+ * - Observability: register Prometheus metrics, expose /metrics.
14
+ *
15
+ * Two authoring forms — pick whichever is clearer:
16
+ *
17
+ * 1. Closure form (recommended for most plugins):
18
+ *
19
+ * definePlugin("audit", ({ bind, on, after, middleware, boot }) => {
20
+ * const log = bind("auditLog", () => new AuditLog())
21
+ * after("post.publish", async ({ result }) => log.write(result))
22
+ * middleware(async (next, action, input, ctx) => {
23
+ * log.start(ctx.envelope.messageId, action.name)
24
+ * try { return await next() }
25
+ * finally { log.finish(ctx.envelope.messageId) }
26
+ * })
27
+ * boot(async () => log.connect())
28
+ * })
29
+ *
30
+ * 2. Object form (kept for back-compat and explicit-lifecycle cases):
31
+ *
32
+ * definePlugin("audit", {
33
+ * register: (container) => container.register("auditLog", ...),
34
+ * boot: async (container) => { ... },
35
+ * shutdown: async (container) => { ... },
36
+ * middleware: [ ... ],
37
+ * })
38
+ *
39
+ * The closure form's `on`/`before`/`after` subscribe to framework events
40
+ * (see `framework-events.ts`) so plugins can react to lifecycle and
41
+ * dispatch events the same way they'd react to a domain event — there is
42
+ * no separate "hooks" system.
43
+ *
44
+ * Plugins are listed in `createApp({ plugins: [...] })`. Sequencing:
45
+ * start: plugin register / setup (sync) → providers boot → plugin boot
46
+ * stop: shutdown plugins in reverse → shutdown providers in reverse
47
+ */
48
+ import { ActionDispatching as ActionDispatchingEvent, ActionCompleted as ActionCompletedEvent, } from "./framework-events.js";
49
+ export function definePlugin(name, setupOrOptions) {
50
+ if (typeof setupOrOptions === "function") {
51
+ return {
52
+ $kind: "plugin",
53
+ name,
54
+ setup: setupOrOptions,
55
+ };
56
+ }
57
+ const opts = setupOrOptions;
58
+ return {
59
+ $kind: "plugin",
60
+ name,
61
+ register: opts.register,
62
+ boot: opts.boot,
63
+ shutdown: opts.shutdown,
64
+ middleware: opts.middleware,
65
+ actorHooks: opts.actorHooks,
66
+ };
67
+ }
68
+ /**
69
+ * Build a PluginContext bound to a specific container + runtime + config,
70
+ * collecting boot/shutdown callbacks the closure registers. Used by
71
+ * createApp's plugin-register loop. Returns the bound API + the lists of
72
+ * boot/shutdown functions for createApp to wire into its lifecycle.
73
+ */
74
+ export function buildPluginContext(container, runtime,
75
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
76
+ config) {
77
+ const boots = [];
78
+ const shutdowns = [];
79
+ const api = {
80
+ container,
81
+ runtime,
82
+ config,
83
+ bind(bindingName, factory) {
84
+ let cached;
85
+ let computed = false;
86
+ container.register(bindingName, () => {
87
+ if (!computed) {
88
+ cached = factory();
89
+ computed = true;
90
+ }
91
+ return cached;
92
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
93
+ });
94
+ return bindingName;
95
+ },
96
+ resolve(bindingName) {
97
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
98
+ return container.resolve(bindingName);
99
+ },
100
+ on(event, handler, priority) {
101
+ runtime.onFramework(event, handler, priority);
102
+ },
103
+ before(actionName, handler) {
104
+ runtime.onFramework(ActionDispatchingEvent, async (payload) => {
105
+ if (payload.action.name !== actionName)
106
+ return;
107
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
108
+ return (await handler(payload));
109
+ });
110
+ },
111
+ after(actionName, handler) {
112
+ runtime.onFramework(ActionCompletedEvent, async (payload) => {
113
+ if (payload.action.name !== actionName)
114
+ return;
115
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
116
+ await handler(payload);
117
+ });
118
+ },
119
+ middleware(mw) {
120
+ runtime.use(mw);
121
+ },
122
+ actorHook(hook) {
123
+ runtime.registerActorTransitionHook(hook);
124
+ },
125
+ boot(fn) {
126
+ boots.push(fn);
127
+ },
128
+ shutdown(fn) {
129
+ shutdowns.push(fn);
130
+ },
131
+ };
132
+ return { api, boots, shutdowns };
133
+ }
134
+ //# sourceMappingURL=define-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-plugin.js","sourceRoot":"","sources":["../src/define-plugin.ts"],"names":[],"mappings":"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"}