@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,294 @@
1
+ /**
2
+ * `defineActor` — the primitive for entities that carry state, transitions,
3
+ * and timers. The actor is data + state machine in one declaration.
4
+ *
5
+ * export const Submission = defineActor('submission', {
6
+ * schema: SubmissionSchema,
7
+ * key: 'submissionId',
8
+ * initial: 'submitted',
9
+ * states: {
10
+ * submitted: {
11
+ * on: {
12
+ * [AnswerFlaggedEvent.name]: {
13
+ * target: 'under-review',
14
+ * assign: (ctx, event) => ({ confidence: event.confidence })
15
+ * },
16
+ * [AnswerAutoGradedEvent.name]: {
17
+ * target: 'graded',
18
+ * assign: (ctx, event) => ({
19
+ * verdict: event.verdict,
20
+ * confidence: event.confidence,
21
+ * gradedAt: event.gradedAt
22
+ * })
23
+ * }
24
+ * }
25
+ * },
26
+ * 'under-review': {
27
+ * on: {
28
+ * [SubmissionManuallyGradedEvent.name]: {
29
+ * target: 'graded',
30
+ * assign: (ctx, event) => ({ verdict: event.verdict })
31
+ * }
32
+ * },
33
+ * after: {
34
+ * '3d': sendReviewReminder
35
+ * }
36
+ * },
37
+ * graded: { final: true }
38
+ * }
39
+ * })
40
+ *
41
+ * See:
42
+ * - `__docs__/framework/foundation-v3-spec.md` — design rationale
43
+ * - `ADR-006-actors-vs-reactions.md` — when to use defineActor vs `when`
44
+ * - `ADR-007-declarative-state-via-assign.md` — why `assign` returns partials
45
+ */
46
+ import { isSchemaDefinition } from "./define-schema.js";
47
+ export function defineActor(
48
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
49
+ ...args) {
50
+ // Three signatures:
51
+ // (name: string, options: ActorOptions) → classic
52
+ // (options: ActorOptionsBound) → schema-bound object form
53
+ // (schema: SchemaDefinition, body: (ctx) => methods, options?: {...}) → closure form
54
+ const [first, second, third] = args;
55
+ // Closure form: first arg is a SchemaDefinition, second is a function.
56
+ if (isSchemaDefinition(first) && typeof second === "function") {
57
+ return defineActorClosure(first,
58
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
+ second, (third ?? {}));
60
+ }
61
+ // Schema-bound object form: first arg is an options object with a schema field.
62
+ if (typeof first === "object" &&
63
+ first !== null &&
64
+ isSchemaDefinition(first.schema)) {
65
+ return defineActorBound(first);
66
+ }
67
+ // Classic form.
68
+ if (typeof first !== "string" || !second) {
69
+ throw new Error("defineActor: signatures are (name, options) | (boundOptions) | (schema, closure, options?).");
70
+ }
71
+ return defineActorClassic(first, second);
72
+ }
73
+ /**
74
+ * Closure-form implementation.
75
+ *
76
+ * Define-time pass: run the body with a recording context. We capture:
77
+ * - each `when(Event, fn)` call → one transition per state (initially
78
+ * applied to all non-final states; per-state scoping is also supported).
79
+ * - the methods object returned (or via `methods(obj)`).
80
+ *
81
+ * Runtime pass (per `use()` call): the binder re-invokes the body with the
82
+ * live state + id, returning the bound methods. `recordThat` calls push to
83
+ * an array that `loadActorView` exposes; the runtime publishes them after
84
+ * the method returns.
85
+ */
86
+ function defineActorClosure(schema, body, options) {
87
+ const name = options.name ?? schema.name;
88
+ const schemaStates = schema.states;
89
+ // Build state refs once — same identity across all closure invocations.
90
+ const stateRefs = {};
91
+ for (const stateName of Object.keys(schemaStates)) {
92
+ stateRefs[stateName] = Object.freeze({ $kind: "state-ref", name: stateName });
93
+ // Provide camelCase alias for kebab-case state names: "under-review" → underReview
94
+ const camel = stateName.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
95
+ if (camel !== stateName)
96
+ stateRefs[camel] = stateRefs[stateName];
97
+ }
98
+ const captured = [];
99
+ const defineTimeCtx = {
100
+ data: new Proxy({}, {
101
+ get: () => undefined,
102
+ has: () => false,
103
+ }),
104
+ id: "",
105
+ validate: () => { },
106
+ recordThat: () => { },
107
+ states: stateRefs,
108
+ when: (event, fn) => {
109
+ captured.push({
110
+ eventName: event.name,
111
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
112
+ fn: fn,
113
+ });
114
+ },
115
+ methods: (obj) => obj,
116
+ };
117
+ const defineTimeReturn = body(defineTimeCtx) ?? {};
118
+ const methodNames = Object.keys(defineTimeReturn);
119
+ // ── BUILD ACTOR STATE MACHINE ────────────────────────────────────
120
+ // Each captured `when(Event, fn)` becomes a reaction entry in every
121
+ // non-final state. The reaction's `assign` runs the fn against a buffer;
122
+ // its `target` is set if the fn returned a state ref.
123
+ const mergedStates = {};
124
+ for (const [stateName, stateSpec] of Object.entries(schemaStates)) {
125
+ if (stateSpec.final) {
126
+ mergedStates[stateName] = { final: true };
127
+ continue;
128
+ }
129
+ const onEntries = {};
130
+ for (const { eventName, fn } of captured) {
131
+ // If multiple `when()` for the same event, only the last wins per
132
+ // state. (Closure-form de-duplication semantics; document this.)
133
+ let target;
134
+ let delta = {};
135
+ onEntries[eventName] = {
136
+ assign: (_currentState, event) => {
137
+ target = undefined;
138
+ delta = {};
139
+ const transCtx = {
140
+ assign: (d) => {
141
+ delta = { ...delta, ...d };
142
+ },
143
+ };
144
+ const result = fn(event, transCtx);
145
+ if (result &&
146
+ typeof result === "object" &&
147
+ "$kind" in result &&
148
+ result.$kind === "state-ref") {
149
+ target = result.name;
150
+ }
151
+ return delta;
152
+ },
153
+ get target() {
154
+ return target;
155
+ },
156
+ };
157
+ }
158
+ mergedStates[stateName] = { on: onEntries };
159
+ }
160
+ // ── PER-USE BINDER — re-invoke body with live state + id ─────────
161
+ const closureBinder = (state, id) => {
162
+ const recorded = [];
163
+ const liveCtx = {
164
+ data: state,
165
+ id,
166
+ validate: (input, predicates, stateArg) => {
167
+ const failures = [];
168
+ for (const pred of predicates) {
169
+ const r = pred(input, stateArg ?? state);
170
+ if (r !== true)
171
+ failures.push(typeof r === "string" ? r : "invariant failed");
172
+ }
173
+ if (failures.length > 0) {
174
+ const err = new Error(`Invariant failed: ${failures.join("; ")}`);
175
+ err.failures = failures;
176
+ err.name = "InvariantError";
177
+ throw err;
178
+ }
179
+ },
180
+ recordThat: (event) => {
181
+ recorded.push(event);
182
+ },
183
+ states: stateRefs,
184
+ when: () => { }, // no-op at runtime
185
+ methods: (obj) => obj,
186
+ };
187
+ const methodsObj = (body(liveCtx) ?? {});
188
+ return { methods: methodsObj, recorded };
189
+ };
190
+ // Runtime schema = partial of the schema's zodSchema, like schema-bound form.
191
+ const runtimeSchema = schema.zodSchema.partial();
192
+ return {
193
+ $kind: "actor",
194
+ name,
195
+ schema: runtimeSchema,
196
+ key: schema.key,
197
+ initial: schema.initial,
198
+ states: mergedStates,
199
+ // No object-form methods — runtime detects closureBinder and uses it.
200
+ methods: undefined,
201
+ stuckThresholds: options.stuckThresholds,
202
+ slas: options.slas,
203
+ eventIndex: buildEventIndex(mergedStates),
204
+ closureBinder,
205
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
206
+ };
207
+ }
208
+ function defineActorClassic(name, options) {
209
+ if (!options.states[options.initial]) {
210
+ throw new Error(`defineActor("${name}"): initial state "${options.initial}" is not declared in states.`);
211
+ }
212
+ for (const [stateName, stateConfig] of Object.entries(options.states)) {
213
+ if (stateConfig.on && stateConfig.final) {
214
+ throw new Error(`defineActor("${name}"): final state "${stateName}" must not declare event reactions (final states are absorbing).`);
215
+ }
216
+ }
217
+ return {
218
+ $kind: "actor",
219
+ name,
220
+ schema: options.schema,
221
+ key: options.key,
222
+ initial: options.initial,
223
+ states: options.states,
224
+ methods: options.methods,
225
+ stuckThresholds: options.stuckThresholds,
226
+ slas: options.slas,
227
+ eventIndex: buildEventIndex(options.states),
228
+ };
229
+ }
230
+ function defineActorBound(options) {
231
+ const name = options.name ?? options.schema.name;
232
+ const schemaStates = options.schema.states;
233
+ const transitions = options.states ?? {};
234
+ // Every state we declare transitions for must exist in the schema.
235
+ for (const stateName of Object.keys(transitions)) {
236
+ if (!(stateName in schemaStates)) {
237
+ throw new Error(`defineActor("${name}"): state "${stateName}" is not declared in schema "${options.schema.name}".states.`);
238
+ }
239
+ if (schemaStates[stateName]?.final && transitions[stateName]?.on) {
240
+ throw new Error(`defineActor("${name}"): state "${stateName}" is final in schema "${options.schema.name}" and cannot declare \`on:\` reactions.`);
241
+ }
242
+ }
243
+ // Build the merged states map: every schema state appears, with the actor's
244
+ // transitions overlaid + `final: true` propagated from the schema.
245
+ const mergedStates = {};
246
+ for (const [stateName, stateSpec] of Object.entries(schemaStates)) {
247
+ const t = transitions[stateName];
248
+ mergedStates[stateName] = {
249
+ ...(t ?? {}),
250
+ ...(stateSpec.final ? { final: true } : {}),
251
+ };
252
+ }
253
+ // Actor instances accumulate state across events — every field is
254
+ // present-or-pending. `.partial()` keeps each field's *type* validation
255
+ // (a string field still rejects a number) but lets the object be empty
256
+ // mid-lifecycle, matching how the classic positional form is used.
257
+ // The static type stays z.ZodObject<TFields> (what callers see); the
258
+ // runtime parser is the partial.
259
+ const runtimeSchema = options.schema.zodSchema.partial();
260
+ return {
261
+ $kind: "actor",
262
+ name,
263
+ schema: runtimeSchema,
264
+ key: options.schema.key,
265
+ initial: options.schema.initial,
266
+ states: mergedStates,
267
+ methods: options.methods,
268
+ stuckThresholds: options.stuckThresholds,
269
+ slas: options.slas,
270
+ eventIndex: buildEventIndex(mergedStates),
271
+ };
272
+ }
273
+ function buildEventIndex(states) {
274
+ const eventIndex = new Map();
275
+ for (const [stateName, stateConfig] of Object.entries(states)) {
276
+ if (!stateConfig.on)
277
+ continue;
278
+ for (const [eventName, reaction] of Object.entries(stateConfig.on)) {
279
+ const list = eventIndex.get(eventName) ?? [];
280
+ list.push({ state: stateName, reaction });
281
+ eventIndex.set(eventName, list);
282
+ }
283
+ }
284
+ return eventIndex;
285
+ }
286
+ /**
287
+ * Helper: turn an `EventDefinition` reference into a string suitable for the
288
+ * `on` map key. Equivalent to `Event.name` but reads as `eventKey(Event)` at
289
+ * call sites where the import is shorter.
290
+ */
291
+ export function eventKey(event) {
292
+ return event.name;
293
+ }
294
+ //# sourceMappingURL=define-actor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-actor.js","sourceRoot":"","sources":["../src/define-actor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * `defineApp` — declares a named, configured application.
3
+ *
4
+ * An app is a cohesive system: a set of modules that share an identity, a
5
+ * routing namespace, an event bus, and a deployment shape. Multiple apps can
6
+ * coexist in one repo (e.g. `learnflow` + `reporting` + `admin`) and one
7
+ * process can host one or many.
8
+ *
9
+ * export const learnflowApp = defineApp('learnflow', {
10
+ * modules: [submissionsModule, enrollmentsModule, masteryModule, lessonsModule],
11
+ * description: 'Adaptive learning loop for AMIT students and teachers.'
12
+ * })
13
+ *
14
+ * // wires/web/web.ts
15
+ * await httpInterface({ port: 3000 })
16
+ * .wire(learnflowApp)
17
+ * .run();
18
+ *
19
+ * The difference between `defineApp` and `createApp`:
20
+ * - `defineApp` is a **declaration** — pure data, no runtime side effects.
21
+ * Multiple wires can instantiate the same `defineApp` declaration with
22
+ * different runtime options (in-memory in dev, Mongo in prod).
23
+ * - `createApp` is the **instantiation** — produces a runtime ready to
24
+ * dispatch. Called by wires (or by `defineApp.create(...)`).
25
+ */
26
+ import type { CreateAppOptions, App } from "./create-app.js";
27
+ import type { ModuleDefinition } from "./define-module.js";
28
+ /**
29
+ * Tenant partitioning model the app commits to. Studio uses this to surface
30
+ * the right "tenant" picker per app and to score multi-tenant isolation.
31
+ * - `'single'` — one tenant per process (the app itself is the boundary)
32
+ * - `'per-org'` — every request carries an org id (e.g. an AMIT school)
33
+ * - `'per-account'` — every request carries an end-user account id
34
+ * - `'per-workspace'` — multi-tenant per workspace inside an org
35
+ */
36
+ export type TenantModel = "single" | "per-org" | "per-account" | "per-workspace";
37
+ /**
38
+ * An endpoint is one named transport binding (http on this port + middleware,
39
+ * queue on this transport, cron on this scheduler, …) declared on the app.
40
+ *
41
+ * Endpoint values are produced by `http(name, opts)`, `queue(name, opts)`,
42
+ * `cron(name, opts)` from `@nwire/http`. The framework keeps them opaque
43
+ * here (tagged values) so the forge package doesn't depend on HTTP.
44
+ */
45
+ export interface EndpointDefinition {
46
+ readonly $kind: "endpoint";
47
+ readonly kind: "http" | "queue" | "cron" | "cli";
48
+ readonly name: string;
49
+ readonly options: any;
50
+ }
51
+ export interface DefineAppOptions {
52
+ readonly modules: readonly ModuleDefinition[];
53
+ /** Human-readable; surfaces in logs, swagger title, OTEL service.name. */
54
+ readonly description?: string;
55
+ /**
56
+ * Default runtime options applied when `create(...)` is called without
57
+ * overrides. Wires can override any of these.
58
+ */
59
+ readonly defaults?: Omit<CreateAppOptions, "modules">;
60
+ /** Studio-aware: declared tenant model. Default `'single'`. */
61
+ readonly tenantModel?: TenantModel;
62
+ /**
63
+ * Studio-aware: the field name in payloads that carries the tenant id,
64
+ * e.g. `'schoolId'` for AMIT, `'workspaceId'` for sparkil.
65
+ */
66
+ readonly tenantKey?: string;
67
+ /**
68
+ * Endpoints — named transport bindings. `runApp(app)` boots all of them;
69
+ * `runApp(app, { endpoints: ["http"] })` boots a subset (container split).
70
+ */
71
+ readonly endpoints?: readonly EndpointDefinition[];
72
+ /**
73
+ * Transport adapters that attach to a transport interface when the wire
74
+ * boots. Each adapter is an opaque value with an `attach(host, app)` call.
75
+ * Forge holds it as `unknown` so it doesn't take a hard dep on a particular
76
+ * transport; the transport runner invokes attach.
77
+ */
78
+ readonly transports?: readonly any[];
79
+ /**
80
+ * App-level config — exposed to every plugin closure via
81
+ * `PluginContext.config`. Typically loaded from env at boot.
82
+ */
83
+ readonly config?: Record<string, any>;
84
+ }
85
+ export interface AppDefinition {
86
+ readonly $kind: "app-definition";
87
+ readonly name: string;
88
+ readonly description?: string;
89
+ readonly modules: readonly ModuleDefinition[];
90
+ readonly defaults: Omit<CreateAppOptions, "modules">;
91
+ readonly tenantModel?: TenantModel;
92
+ readonly tenantKey?: string;
93
+ readonly endpoints: readonly EndpointDefinition[];
94
+ readonly transports: readonly any[];
95
+ readonly config: Record<string, any>;
96
+ /**
97
+ * Instantiate this app's runtime. Pass overrides for stores, logger,
98
+ * DLQ, timer scheduler. Wires typically read from `config.*` and pass
99
+ * the result here.
100
+ */
101
+ create(options?: Omit<CreateAppOptions, "modules">): App;
102
+ }
103
+ export declare function defineApp(name: string, options: DefineAppOptions): AppDefinition;
104
+ //# sourceMappingURL=define-app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-app.d.ts","sourceRoot":"","sources":["../src/define-app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAE1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,GAAG,eAAe,CAAC;AAEjF;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC9C,0EAA0E;IAC1E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;IACtD,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IACnC;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACnD;;;;;OAKG;IAEH,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,GAAG,EAAE,CAAC;IACrC;;;OAGG;IAEH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;IACrD,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IACnC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAElD,QAAQ,CAAC,UAAU,EAAE,SAAS,GAAG,EAAE,CAAC;IAEpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACrC;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,GAAG,GAAG,CAAC;CAC1D;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,aAAa,CAqBhF"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * `defineApp` — declares a named, configured application.
3
+ *
4
+ * An app is a cohesive system: a set of modules that share an identity, a
5
+ * routing namespace, an event bus, and a deployment shape. Multiple apps can
6
+ * coexist in one repo (e.g. `learnflow` + `reporting` + `admin`) and one
7
+ * process can host one or many.
8
+ *
9
+ * export const learnflowApp = defineApp('learnflow', {
10
+ * modules: [submissionsModule, enrollmentsModule, masteryModule, lessonsModule],
11
+ * description: 'Adaptive learning loop for AMIT students and teachers.'
12
+ * })
13
+ *
14
+ * // wires/web/web.ts
15
+ * await httpInterface({ port: 3000 })
16
+ * .wire(learnflowApp)
17
+ * .run();
18
+ *
19
+ * The difference between `defineApp` and `createApp`:
20
+ * - `defineApp` is a **declaration** — pure data, no runtime side effects.
21
+ * Multiple wires can instantiate the same `defineApp` declaration with
22
+ * different runtime options (in-memory in dev, Mongo in prod).
23
+ * - `createApp` is the **instantiation** — produces a runtime ready to
24
+ * dispatch. Called by wires (or by `defineApp.create(...)`).
25
+ */
26
+ import { createApp } from "./create-app.js";
27
+ export function defineApp(name, options) {
28
+ return {
29
+ $kind: "app-definition",
30
+ name,
31
+ description: options.description,
32
+ modules: options.modules,
33
+ defaults: options.defaults ?? {},
34
+ tenantModel: options.tenantModel,
35
+ tenantKey: options.tenantKey,
36
+ endpoints: options.endpoints ?? [],
37
+ transports: options.transports ?? [],
38
+ config: options.config ?? {},
39
+ create(overrides = {}) {
40
+ return createApp({
41
+ ...options.defaults,
42
+ ...overrides,
43
+ modules: options.modules,
44
+ config: options.config,
45
+ });
46
+ },
47
+ };
48
+ }
49
+ //# sourceMappingURL=define-app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-app.js","sourceRoot":"","sources":["../src/define-app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAuFzC,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,OAAyB;IAC/D,OAAO;QACL,KAAK,EAAE,gBAAgB;QACvB,IAAI;QACJ,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE;QAChC,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE;QAClC,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,EAAE;QACpC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;QAC5B,MAAM,CAAC,SAAS,GAAG,EAAE;YACnB,OAAO,SAAS,CAAC;gBACf,GAAG,OAAO,CAAC,QAAQ;gBACnB,GAAG,SAAS;gBACZ,OAAO,EAAE,OAAO,CAAC,OAAsC;gBACvD,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * `defineCron` — declarative scheduled action.
3
+ *
4
+ * export const dailyBillingSummary = defineCron({
5
+ * name: "billing.daily-summary",
6
+ * schedule: "0 2 * * *", // every day at 02:00
7
+ * dispatches: generateBillingSummary,
8
+ * });
9
+ *
10
+ * The framework treats cron schedules as first-class so Studio can render
11
+ * them as a panel ("Scheduled today"), score on-time firing against
12
+ * declared schedule, and surface missed firings as drift signals.
13
+ *
14
+ * Runtime: a registered cron scheduler (`@nwire/cron`) walks declarations
15
+ * and dispatches the bound action at each fire time. The runtime emits
16
+ * `cron.fired` telemetry (with `lateByMs` from expected vs actual).
17
+ *
18
+ * `schedule` accepts standard 5-field cron (`'0 2 * * *'`) or an alias
19
+ * (`'@hourly'`, `'@daily'`, etc.). Interval shorthand (`'every 5m'`) is
20
+ * the scheduler adapter's concern, not enforced here.
21
+ */
22
+ import type { ActionDefinition } from "./define-action.js";
23
+ export interface CronMeta {
24
+ readonly name: string;
25
+ readonly description?: string;
26
+ /** Cron expression or alias. */
27
+ readonly schedule: string;
28
+ /** Action to dispatch when the schedule fires. */
29
+ readonly dispatches: ActionDefinition;
30
+ /**
31
+ * Optional pure builder for the action input. Default: dispatch with an
32
+ * empty object. Cron handlers often take `{ now: ISOString }`.
33
+ */
34
+ readonly buildInput?: () => unknown;
35
+ /** Optional timezone for the schedule. Default UTC. */
36
+ readonly timezone?: string;
37
+ readonly tags?: readonly string[];
38
+ }
39
+ export interface CronDefinition {
40
+ readonly $kind: "cron";
41
+ readonly name: string;
42
+ readonly description?: string;
43
+ readonly schedule: string;
44
+ readonly dispatches: ActionDefinition;
45
+ readonly buildInput?: () => unknown;
46
+ readonly timezone?: string;
47
+ readonly tags?: readonly string[];
48
+ }
49
+ export declare function defineCron(meta: CronMeta): CronDefinition;
50
+ //# sourceMappingURL=define-cron.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-cron.d.ts","sourceRoot":"","sources":["../src/define-cron.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,kDAAkD;IAClD,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;IACpC,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,CAWzD"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * `defineCron` — declarative scheduled action.
3
+ *
4
+ * export const dailyBillingSummary = defineCron({
5
+ * name: "billing.daily-summary",
6
+ * schedule: "0 2 * * *", // every day at 02:00
7
+ * dispatches: generateBillingSummary,
8
+ * });
9
+ *
10
+ * The framework treats cron schedules as first-class so Studio can render
11
+ * them as a panel ("Scheduled today"), score on-time firing against
12
+ * declared schedule, and surface missed firings as drift signals.
13
+ *
14
+ * Runtime: a registered cron scheduler (`@nwire/cron`) walks declarations
15
+ * and dispatches the bound action at each fire time. The runtime emits
16
+ * `cron.fired` telemetry (with `lateByMs` from expected vs actual).
17
+ *
18
+ * `schedule` accepts standard 5-field cron (`'0 2 * * *'`) or an alias
19
+ * (`'@hourly'`, `'@daily'`, etc.). Interval shorthand (`'every 5m'`) is
20
+ * the scheduler adapter's concern, not enforced here.
21
+ */
22
+ export function defineCron(meta) {
23
+ return {
24
+ $kind: "cron",
25
+ name: meta.name,
26
+ description: meta.description,
27
+ schedule: meta.schedule,
28
+ dispatches: meta.dispatches,
29
+ buildInput: meta.buildInput,
30
+ timezone: meta.timezone,
31
+ tags: meta.tags,
32
+ };
33
+ }
34
+ //# sourceMappingURL=define-cron.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-cron.js","sourceRoot":"","sources":["../src/define-cron.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAgCH,MAAM,UAAU,UAAU,CAAC,IAAc;IACvC,OAAO;QACL,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `defineError` — re-exported from `@nwire/handler`.
3
+ *
4
+ * The canonical implementation lives in `@nwire/handler` so transports
5
+ * and foreign hosts can import errors without dragging in forge. Forge
6
+ * re-exports the same names so consumers pulling from forge get one
7
+ * import line.
8
+ */
9
+ export { defineError, isNwireError, NwireError, Unauthorized, Forbidden, NotFound, Gone, BadRequest, Conflict, type ErrorDefinition, type ErrorMeta, } from "@nwire/handler";
10
+ //# sourceMappingURL=define-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-error.d.ts","sourceRoot":"","sources":["../src/define-error.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,WAAW,EACX,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,IAAI,EACJ,UAAU,EACV,QAAQ,EACR,KAAK,eAAe,EACpB,KAAK,SAAS,GACf,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `defineError` — re-exported from `@nwire/handler`.
3
+ *
4
+ * The canonical implementation lives in `@nwire/handler` so transports
5
+ * and foreign hosts can import errors without dragging in forge. Forge
6
+ * re-exports the same names so consumers pulling from forge get one
7
+ * import line.
8
+ */
9
+ export { defineError, isNwireError, NwireError, Unauthorized, Forbidden, NotFound, Gone, BadRequest, Conflict, } from "@nwire/handler";
10
+ //# sourceMappingURL=define-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-error.js","sourceRoot":"","sources":["../src/define-error.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,WAAW,EACX,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,IAAI,EACJ,UAAU,EACV,QAAQ,GAGT,MAAM,gBAAgB,CAAC"}