@classytic/arc 2.41.1 → 2.44.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 (248) hide show
  1. package/dist/{EventTransport-CbUKDzZZ.d.mts → EventTransport-CiicKz2Z.d.mts} +1 -1
  2. package/dist/{EventTransport-DSqD_Xsg.mjs → EventTransport-DZWDsaPa.mjs} +22 -17
  3. package/dist/{HookSystem-CMF94SEA.mjs → HookSystem-yjEgn7Cm.mjs} +2 -2
  4. package/dist/{QueryCache-DFA-QrU9.d.mts → QueryCache--5uAuYPW.d.mts} +7 -3
  5. package/dist/{ResourceRegistry-MGpXoxHZ.mjs → ResourceRegistry-DJxHUpE4.mjs} +44 -13
  6. package/dist/acquire-BozJ-9yt.mjs +35 -0
  7. package/dist/actionPermissions-5N04zBL4.mjs +772 -0
  8. package/dist/audit/index.d.mts +46 -8
  9. package/dist/audit/index.mjs +48 -26
  10. package/dist/auth/audit.d.mts +8 -8
  11. package/dist/auth/audit.mjs +1 -1
  12. package/dist/auth/index.d.mts +46 -16
  13. package/dist/auth/index.mjs +134 -156
  14. package/dist/auth/redis-session.d.mts +4 -5
  15. package/dist/auth/redis-session.mjs +1 -1
  16. package/dist/{authorizationDecision-DawKGoXb.mjs → authorizationDecision-wX3SA9w_.mjs} +7 -102
  17. package/dist/{base-CxrV1LmG.d.mts → base-CZyixEQR.d.mts} +27 -5
  18. package/dist/boundedMap-DWiKW7lP.mjs +57 -0
  19. package/dist/{buildHandler-CvxKOc0m.mjs → buildHandler-Bswu_vNb.mjs} +4 -4
  20. package/dist/cache/index.d.mts +31 -43
  21. package/dist/cache/index.mjs +4 -4
  22. package/dist/{caching-DbCBxlgw.mjs → caching-Drp68DIS.mjs} +3 -3
  23. package/dist/claimed-DYvQoZLv.mjs +8 -0
  24. package/dist/cleanup/index.d.mts +18 -22
  25. package/dist/cleanup/index.mjs +27 -73
  26. package/dist/cli/commands/describe.d.mts +7 -5
  27. package/dist/cli/commands/describe.mjs +7 -4
  28. package/dist/cli/commands/docs.d.mts +2 -3
  29. package/dist/cli/commands/docs.mjs +3 -3
  30. package/dist/cli/commands/doctor.d.mts +2 -3
  31. package/dist/cli/commands/doctor.mjs +1 -1
  32. package/dist/cli/commands/generate.mjs +2 -3
  33. package/dist/cli/commands/init.mjs +2 -3
  34. package/dist/cli/commands/introspect.d.mts +2 -3
  35. package/dist/cli/commands/introspect.mjs +2 -2
  36. package/dist/cli/index.mjs +3 -3
  37. package/dist/{constants-D5Ubn1fe.mjs → constants-B2QHb6u6.mjs} +4 -2
  38. package/dist/context/index.d.mts +11 -14
  39. package/dist/context/index.mjs +18 -38
  40. package/dist/core/index.d.mts +3 -3
  41. package/dist/core/index.mjs +8 -8
  42. package/dist/{core-5lazhva9.mjs → core-COcqo0Cp.mjs} +15 -5
  43. package/dist/{createActionRouter-DNqoaK81.mjs → createActionRouter-zG13rpPJ.mjs} +97 -39
  44. package/dist/{createAggregationRouter-BcbQJf10.mjs → createAggregationRouter-CWRz96Vr.mjs} +11 -8
  45. package/dist/{preloadResources-f3boenVZ.mjs → createApp-BGLYtErt.mjs} +305 -394
  46. package/dist/{createMcpServer-CbDWkZ1T.d.mts → createMcpServer-DSztofa9.d.mts} +1 -1
  47. package/dist/{defineAggregation-D_eJjm5A.mjs → defineAggregation--3xguLkk.mjs} +1 -1
  48. package/dist/{defineResource-DxkMTjRn.mjs → defineResource-gUp9ug66.mjs} +118 -1024
  49. package/dist/discovery/index.d.mts +6 -7
  50. package/dist/discovery/index.mjs +1 -1
  51. package/dist/docs/index.d.mts +11 -5
  52. package/dist/docs/index.mjs +4 -4
  53. package/dist/{elevation-CkvG0LG2.mjs → elevation-BG4gnMsJ.mjs} +41 -12
  54. package/dist/{elevation-BXCfVcNG.d.mts → elevation-BW2J3tNj.d.mts} +1 -2
  55. package/dist/encryption/index.d.mts +5 -5
  56. package/dist/encryption/index.mjs +3 -3
  57. package/dist/{errorHandler-D1GHKGlV.mjs → errorHandler-COHw3N1b.mjs} +26 -5
  58. package/dist/{errors-BH7YU_9O.mjs → errors-CW4anJBy.mjs} +58 -23
  59. package/dist/{errors-BGdVwP25.d.mts → errors-JYc9vwqE.d.mts} +9 -0
  60. package/dist/{eventPlugin-B52abJ8W.d.mts → eventPlugin-BtmA4-3P.d.mts} +65 -9
  61. package/dist/{eventPlugin-zZY-unhr.mjs → eventPlugin-BweHAVws.mjs} +82 -21
  62. package/dist/{subscribe-helpers-DatDkcuG.mjs → eventTypes-N4-omQFR.mjs} +151 -17
  63. package/dist/events/index.d.mts +43 -18
  64. package/dist/events/index.mjs +49 -53
  65. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  66. package/dist/events/transports/redis-stream-entry.mjs +139 -157
  67. package/dist/events/transports/redis.d.mts +5 -6
  68. package/dist/events/transports/redis.mjs +2 -2
  69. package/dist/factory/index.d.mts +42 -27
  70. package/dist/factory/index.mjs +213 -32
  71. package/dist/{fastify-augmentation-Cq2nHVaW.d.mts → fastify-augmentation-DRlCIWE9.d.mts} +11 -25
  72. package/dist/{fields-BHrkoF5y.mjs → fields-A5crhsJb.mjs} +1 -1
  73. package/dist/{fields-I_EeRWND.d.mts → fields-BBSpf8pS.d.mts} +1 -1
  74. package/dist/filter-merge-DGM-GQ1J.mjs +99 -0
  75. package/dist/{generate-BLRf2m3y.mjs → generate-BXKo2Gc8.mjs} +2 -2
  76. package/dist/{headers-BIXWKrzQ.mjs → headers-DKZQKL-Z.mjs} +2 -2
  77. package/dist/health-BYAwA6YS.mjs +22 -0
  78. package/dist/{health-ZRHeDHXH.mjs → health-CrqUp3sz.mjs} +115 -55
  79. package/dist/hooks/index.d.mts +2 -2
  80. package/dist/hooks/index.mjs +2 -3
  81. package/dist/idempotency/index.d.mts +36 -10
  82. package/dist/idempotency/index.mjs +230 -111
  83. package/dist/idempotency/redis.d.mts +1 -1
  84. package/dist/idempotency/redis.mjs +77 -12
  85. package/dist/{index-D4u76eQW.d.mts → index-Beg3aNnK.d.mts} +23 -101
  86. package/dist/{preloadResources-CjS2OfpU.d.mts → index-BkV55WlV.d.mts} +37 -38
  87. package/dist/{index-BHdZD8zK.d.mts → index-Bxriq3so.d.mts} +84 -21
  88. package/dist/index-CUJvoyw3.d.mts +510 -0
  89. package/dist/{index-CbJiYrfv.d.mts → index-Chgz3d0i.d.mts} +1 -1
  90. package/dist/{index-DHbyPo5j.d.mts → index-WH7xgvxS.d.mts} +304 -254
  91. package/dist/index.d.mts +9 -9
  92. package/dist/index.mjs +11 -11
  93. package/dist/{init-CpLkjU18.mjs → init-BPzK5Lnr.mjs} +1 -1
  94. package/dist/integrations/event-gateway.d.mts +11 -7
  95. package/dist/integrations/event-gateway.mjs +4 -4
  96. package/dist/integrations/index.d.mts +3 -3
  97. package/dist/integrations/index.mjs +1 -1
  98. package/dist/integrations/jobs/index.d.mts +1 -1
  99. package/dist/integrations/jobs/index.mjs +18 -5
  100. package/dist/integrations/mcp/index.d.mts +102 -89
  101. package/dist/integrations/mcp/index.mjs +19 -4
  102. package/dist/integrations/mcp/testing.d.mts +8 -9
  103. package/dist/integrations/mcp/testing.mjs +2 -2
  104. package/dist/integrations/streamline.d.mts +85 -144
  105. package/dist/integrations/streamline.mjs +131 -55
  106. package/dist/integrations/webhooks.d.mts +83 -143
  107. package/dist/integrations/webhooks.mjs +36 -80
  108. package/dist/integrations/websocket-pushref-redis.d.mts +5 -6
  109. package/dist/integrations/websocket-pushref-redis.mjs +1 -1
  110. package/dist/integrations/websocket-redis.d.mts +5 -6
  111. package/dist/integrations/websocket-redis.mjs +1 -1
  112. package/dist/integrations/websocket.d.mts +3 -3
  113. package/dist/integrations/websocket.mjs +2 -2
  114. package/dist/{interface-DEWNOMza.d.mts → interface-JJzwH4Ro.d.mts} +34 -2
  115. package/dist/{jsonBody-ELR9lfeU.mjs → jsonBody-YIq-vGLv.mjs} +2 -2
  116. package/dist/{keys-cpZCtcIE.mjs → keys-CpoiZ8hU.mjs} +7 -18
  117. package/dist/{loadResources-BPfWiI5s.mjs → loadResources-6jO52-RR.mjs} +3 -3
  118. package/dist/{loadResourcesFromEntry-ixtfL3J2.mjs → loadResourcesFromEntry-MP8xEppu.mjs} +2 -2
  119. package/dist/logger/index.d.mts +9 -17
  120. package/dist/logger/index.mjs +2 -153
  121. package/dist/logger-D4V1zGLI.mjs +160 -0
  122. package/dist/{mcpPlugin-BX5PujI0.mjs → mcpPlugin-srPc7ItN.mjs} +446 -170
  123. package/dist/{memory-Iotz0cCx.mjs → memory-CTa5pOCW.mjs} +36 -34
  124. package/dist/{metrics-NMsmpRmY.mjs → metrics-DsZrvnpB.mjs} +39 -72
  125. package/dist/middleware/index.d.mts +5 -5
  126. package/dist/middleware/index.mjs +3 -3
  127. package/dist/migrations/index.d.mts +13 -13
  128. package/dist/migrations/index.mjs +2 -2
  129. package/dist/{module-DpLJG2_N.mjs → module--L0iBIZz.mjs} +8 -8
  130. package/dist/mongodb-memory-server-CHhYSq5y.mjs +35539 -0
  131. package/dist/mongoose-CYJCLyi-.mjs +67451 -0
  132. package/dist/multiTenant-CAtYlW6H.d.mts +104 -0
  133. package/dist/{multipartBody-DtRWM6_U.mjs → multipartBody-Cc7eZ9cq.mjs} +46 -7
  134. package/dist/node-D8UZv_8c.mjs +41236 -0
  135. package/dist/{openapi-CmFf3yq_.mjs → openapi-CMegfsm8.mjs} +48 -10
  136. package/dist/outbox-admin/index.d.mts +5 -5
  137. package/dist/outbox-admin/index.mjs +6 -18
  138. package/dist/{outbox-module-D2z5WkDY.mjs → outbox-module-Ryk270jd.mjs} +203 -33
  139. package/dist/{outbox-module-BHdUnuuK.d.mts → outbox-module-gZCHoE4H.d.mts} +79 -6
  140. package/dist/permissions/index.d.mts +5 -4
  141. package/dist/permissions/index.mjs +8 -6
  142. package/dist/{permissions-D8TBH44E.mjs → permissions-C5ijIz5Q.mjs} +149 -33
  143. package/dist/{pipe-FMWNheSO.mjs → pipe-D81zMtWs.mjs} +2 -2
  144. package/dist/pipeline/index.d.mts +7 -7
  145. package/dist/pipeline/index.mjs +2 -2
  146. package/dist/plan-CJGMKoui.mjs +565 -0
  147. package/dist/{BaseController-CYEwjyjN.mjs → plugin-DALd9dcF.mjs} +1269 -346
  148. package/dist/plugins/index.d.mts +17 -14
  149. package/dist/plugins/index.mjs +44 -22
  150. package/dist/plugins/response-cache.d.mts +5 -6
  151. package/dist/plugins/response-cache.mjs +8 -14
  152. package/dist/plugins/tracing-entry.mjs +2 -2
  153. package/dist/{pluralize-CXWZIzTv.mjs → pluralize-COUNYo3d.mjs} +1 -1
  154. package/dist/presets/filesUpload.d.mts +8 -8
  155. package/dist/presets/filesUpload.mjs +5 -5
  156. package/dist/presets/index.d.mts +35 -40
  157. package/dist/presets/index.mjs +4 -4
  158. package/dist/presets/multiTenant.d.mts +2 -107
  159. package/dist/presets/multiTenant.mjs +22 -162
  160. package/dist/presets/search.d.mts +9 -10
  161. package/dist/presets/search.mjs +2 -2
  162. package/dist/{presets-ZJSPgmT2.mjs → presets-CONf2Qem.mjs} +99 -107
  163. package/dist/{projection-BzIgzoKZ.mjs → projection-wFoLqdss.mjs} +2 -2
  164. package/dist/{pushref-registry-Dov9l4qE.d.mts → pushref-registry-UxCkoA4C.d.mts} +1 -1
  165. package/dist/{queryCachePlugin-DZHPOm9p.mjs → queryCachePlugin-BATECpyh.mjs} +12 -14
  166. package/dist/{queryCachePlugin-BzqxconG.d.mts → queryCachePlugin-C2lZjTxk.d.mts} +1 -1
  167. package/dist/{rateLimitKey-BvOvcBDi.mjs → rateLimitKey-DVEZ_UpV.mjs} +1 -1
  168. package/dist/{realtime-8tIQWZz4.mjs → realtime-xyubMKSB.mjs} +25 -21
  169. package/dist/{redis-Bzi1y3F9.d.mts → redis-BDgv9Glw.d.mts} +17 -24
  170. package/dist/redis-stream-BMk-bpQS.d.mts +219 -0
  171. package/dist/redisShapes-CQksY67q.d.mts +55 -0
  172. package/dist/registry/index.d.mts +15 -10
  173. package/dist/registry/index.mjs +4 -4
  174. package/dist/{registry-DNkgGQcK.mjs → registry-Bdzg-hdm.mjs} +13 -10
  175. package/dist/{renewingLease-yF8BdW4b.mjs → renewingLease-BFJxGPuh.mjs} +1 -1
  176. package/dist/{replyHelpers-CNdvMfM4.mjs → replyHelpers-Bnc6lJyy.mjs} +2 -2
  177. package/dist/{requestContext-cDkAUr-P.mjs → requestContext-C10UeFe5.mjs} +1 -1
  178. package/dist/requirement-Bu50QALH.mjs +35 -0
  179. package/dist/requirement-CbiLdQ1n.d.mts +22 -0
  180. package/dist/resourceRateLimit-Wf6d6FL9.d.mts +30 -0
  181. package/dist/resourceRateLimit-urWPJxrt.mjs +180 -0
  182. package/dist/rolldown-runtime-MYrLNGnq.mjs +45 -0
  183. package/dist/routeValidator-DHtpzrzk.mjs +70 -0
  184. package/dist/{runtimeCapabilities-CkhS6jn6.mjs → runtimeCapabilities-DIMKMV2G.mjs} +1 -1
  185. package/dist/{schedules-j6uXXAeJ.mjs → schedules-CKTs5ys8.mjs} +46 -37
  186. package/dist/{schemaConverter-BVA7cFRG.mjs → schemaConverter-BVjkQ5DD.mjs} +2 -2
  187. package/dist/{schemaIR-CTvPDoPB.mjs → schemaIR-BA0Hb21Y.mjs} +2 -2
  188. package/dist/schemas/index.d.mts +20 -10
  189. package/dist/schemas/index.mjs +8 -3
  190. package/dist/scim/index.d.mts +13 -13
  191. package/dist/scim/index.mjs +2 -2
  192. package/dist/scope/index.d.mts +4 -4
  193. package/dist/scope/index.mjs +6 -6
  194. package/dist/{scope-BUi1xV1I.mjs → scope-DINaj7Ax.mjs} +4 -4
  195. package/dist/shutdown-LpLMH8T1.mjs +59 -0
  196. package/dist/{simpleEqualityMatcher-C9bzq2gO.mjs → simpleEqualityMatcher-DbwIM1f1.mjs} +1 -1
  197. package/dist/{sse-BeqVKQKu.mjs → sse-BzJFPX_1.mjs} +11 -15
  198. package/dist/{sseStream-Ppzo-WUH.mjs → sseStream-DQChzGTs.mjs} +2 -2
  199. package/dist/{store-helpers-dW71XVWL.mjs → store-helpers-Coj9RhOZ.mjs} +1 -1
  200. package/dist/{streaming-IcRFjWQU.mjs → streaming-JzB5CAga.mjs} +1 -1
  201. package/dist/subscriberIdentity-DeyppIif.mjs +28 -0
  202. package/dist/tenancy-DxV8OuX2.mjs +43 -0
  203. package/dist/tenantPreparation-CBvvAcAj.mjs +67 -0
  204. package/dist/testing/cleanupStoreContract.d.mts +4 -5
  205. package/dist/testing/cleanupStoreContract.mjs +1 -1
  206. package/dist/testing/index.d.mts +215 -197
  207. package/dist/testing/index.mjs +289 -214
  208. package/dist/testing/outboxStoreContract.d.mts +4 -5
  209. package/dist/testing/outboxStoreContract.mjs +137 -2
  210. package/dist/testing/requiredPorts.d.mts +16 -0
  211. package/dist/testing/requiredPorts.mjs +65 -0
  212. package/dist/testing/storageContract.d.mts +4 -5
  213. package/dist/testing/storageContract.mjs +1 -1
  214. package/dist/timing-CntavTlR.mjs +46 -0
  215. package/dist/{transactionContext-CPbdlnVw.mjs → transactionContext-orvnGu4F.mjs} +1 -1
  216. package/dist/{typeGuards-BLjPgVBm.mjs → typeGuards-kEaP_WmO.mjs} +1 -1
  217. package/dist/types/index.d.mts +4 -4
  218. package/dist/types/index.mjs +1 -1
  219. package/dist/types/storage.mjs +1 -1
  220. package/dist/{types-DfVDvkdP.d.mts → types-BJ-2XqVF.d.mts} +189 -204
  221. package/dist/{types-CWQn9-IC.d.mts → types-D3Ixsh00.d.mts} +22 -9
  222. package/dist/{types-CgenB1gv.mjs → types-fvO6Ovzx.mjs} +4 -4
  223. package/dist/usage/index.d.mts +5 -6
  224. package/dist/usage/index.mjs +5 -5
  225. package/dist/{userHelpers-ChRvkuSZ.mjs → userHelpers-C76zD5pa.mjs} +1 -1
  226. package/dist/utils/index.d.mts +125 -264
  227. package/dist/utils/index.mjs +13 -12
  228. package/dist/{utils-CxcctrAh.mjs → utils-BpkVZ8rB.mjs} +315 -404
  229. package/dist/{validate-DrYWnOzI.mjs → validate-CWp-lsrm.mjs} +6 -14
  230. package/dist/{versioning-D6JIK8Tk.d.mts → versioning-Bsb51gGT.d.mts} +28 -13
  231. package/dist/{versioning-DKkT4hNJ.mjs → versioning-CHhL9P3o.mjs} +4 -4
  232. package/dist/{websocket-BOXVggMf.d.mts → websocket-Cs4awVyD.d.mts} +1 -1
  233. package/dist/{workScope-CxKqoIFn.mjs → workScope-n9a7d_lZ.mjs} +2 -2
  234. package/package.json +57 -59
  235. package/skills/arc/SKILL.md +13 -4
  236. package/skills/arc/references/auth.md +8 -5
  237. package/skills/arc/references/integrations.md +1 -1
  238. package/skills/arc/references/mcp.md +8 -6
  239. package/skills/arc/references/multi-tenancy.md +19 -14
  240. package/skills/arc/references/production.md +27 -10
  241. package/dist/actionPermissions-BoPGQ5-4.mjs +0 -350
  242. package/dist/index-CFfLKMH4.d.mts +0 -290
  243. package/dist/interface-YzIbF7Ii.mjs +0 -17
  244. package/dist/redis-stream-BPKscsTB.d.mts +0 -260
  245. package/dist/registerRoute-Bsnk6NiZ.mjs +0 -364
  246. package/dist/rolldown-runtime-eysyzFAF.mjs +0 -15
  247. package/dist/sync/changelog.d.mts +0 -3
  248. package/dist/sync/changelog.mjs +0 -3
@@ -88,7 +88,7 @@ interface MemoryEventTransportOptions {
88
88
  */
89
89
  declare class MemoryEventTransport implements EventTransport {
90
90
  readonly name = "memory";
91
- private handlers;
91
+ private router;
92
92
  private logger;
93
93
  private onHandlerError;
94
94
  private handlerDispatch;
@@ -1,6 +1,6 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
2
- import { r as workSeedFromEvent, t as runWorkScope } from "./workScope-CxKqoIFn.mjs";
3
- import { createEvent, matchEventPattern } from "@classytic/primitives/events";
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
+ import { r as workSeedFromEvent, t as runWorkScope } from "./workScope-n9a7d_lZ.mjs";
3
+ import { createEvent, createEventRouter } from "@classytic/primitives/events";
4
4
  //#region src/events/EventTransport.ts
5
5
  /**
6
6
  * Internal arc events module — concrete in-memory transport.
@@ -77,7 +77,7 @@ function resolveEventTransport(fastify) {
77
77
  */
78
78
  var MemoryEventTransport = class {
79
79
  name = "memory";
80
- handlers = /* @__PURE__ */ new Map();
80
+ router = createEventRouter();
81
81
  logger;
82
82
  onHandlerError;
83
83
  handlerDispatch;
@@ -103,9 +103,8 @@ var MemoryEventTransport = class {
103
103
  return runWorkScope(workSeedFromEvent(event), () => this.dispatch(event));
104
104
  }
105
105
  async dispatch(event) {
106
- const allHandlers = /* @__PURE__ */ new Set();
107
- for (const [pattern, handlers] of this.handlers) if (matchEventPattern(pattern, event.type)) for (const h of handlers) allHandlers.add(h);
108
- if (allHandlers.size === 0 && this.onUnroutedEvent) try {
106
+ const allHandlers = this.router.route(event.type);
107
+ if (allHandlers.length === 0 && this.onUnroutedEvent) try {
109
108
  this.onUnroutedEvent(event);
110
109
  } catch (err) {
111
110
  try {
@@ -132,7 +131,7 @@ var MemoryEventTransport = class {
132
131
  * written not to reject, and `allSettled` means the next person to add a
133
132
  * timeout or a metric to it cannot silently break that.
134
133
  */
135
- const pending = [...allHandlers];
134
+ const pending = allHandlers;
136
135
  if (this.handlerConcurrency >= pending.length) await Promise.allSettled(pending.map(run));
137
136
  else {
138
137
  let next = 0;
@@ -154,7 +153,7 @@ var MemoryEventTransport = class {
154
153
  * finds nothing. A broker-backed transport has no such ambiguity — publish
155
154
  * means "durably handed off" and redelivery is the consumer group's job.
156
155
  */
157
- if (failures.length > 0 && this.onHandlerError === "throw") throw new AggregateError(failures, `[EventTransport] ${failures.length} handler(s) failed for ${event.type}`);
156
+ if (failures.length > 0 && this.onHandlerError === "throw") throw new AggregateError(failures, `[EventTransport] ${failures.length} handler(s) failed for ${event.type}: ${describeFailures(failures)}`);
158
157
  }
159
158
  /**
160
159
  * Reference `publishMany` implementation — delegates to `publish()` in order.
@@ -175,19 +174,25 @@ var MemoryEventTransport = class {
175
174
  return results;
176
175
  }
177
176
  async subscribe(pattern, handler) {
178
- if (!this.handlers.has(pattern)) this.handlers.set(pattern, /* @__PURE__ */ new Set());
179
- this.handlers.get(pattern)?.add(handler);
177
+ this.router.add(pattern, handler);
180
178
  return () => {
181
- const set = this.handlers.get(pattern);
182
- if (set) {
183
- set.delete(handler);
184
- if (set.size === 0) this.handlers.delete(pattern);
185
- }
179
+ this.router.remove(pattern, handler);
186
180
  };
187
181
  }
188
182
  async close() {
189
- this.handlers.clear();
183
+ this.router.clear();
190
184
  }
191
185
  };
186
+ /** Per-cause and total caps, so a dead-lettered row's `lastError` stays readable and bounded. */
187
+ const CAUSE_MESSAGE_MAX = 300;
188
+ const FAILURES_MESSAGE_MAX = 1500;
189
+ /** Every cause's message, `; `-joined and truncated — the aggregate names what failed. */
190
+ function describeFailures(failures) {
191
+ const joined = failures.map((err) => {
192
+ const message = err instanceof Error ? err.message : String(err);
193
+ return message.length > CAUSE_MESSAGE_MAX ? `${message.slice(0, CAUSE_MESSAGE_MAX)}…` : message;
194
+ }).join("; ");
195
+ return joined.length > FAILURES_MESSAGE_MAX ? `${joined.slice(0, FAILURES_MESSAGE_MAX)}… (${failures.length} causes)` : joined;
196
+ }
192
197
  //#endregion
193
198
  export { resolveEventTransport as i, MemoryEventTransport as n, createEvent as r, ARC_EVENT_TRANSPORT as t };
@@ -1,5 +1,5 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
2
- import { t as buildRequestScopeProjection } from "./projection-BzIgzoKZ.mjs";
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
+ import { t as buildRequestScopeProjection } from "./projection-wFoLqdss.mjs";
3
3
  //#region src/hooks/HookSystem.ts
4
4
  /**
5
5
  * Hook System
@@ -27,10 +27,14 @@ interface QueryCacheConfig {
27
27
  jitter?: number;
28
28
  }
29
29
  type CacheStatus = "fresh" | "stale" | "miss";
30
- interface CacheResult<T> {
30
+ /** A miss carries no data — narrow on `status` before reading `data`. */
31
+ type CacheResult<T> = {
32
+ status: "miss";
33
+ data: undefined;
34
+ } | {
35
+ status: "fresh" | "stale";
31
36
  data: T;
32
- status: CacheStatus;
33
- }
37
+ };
34
38
  declare class QueryCache {
35
39
  private readonly store;
36
40
  constructor(store: CacheStore);
@@ -1,5 +1,5 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
2
- import "./constants-D5Ubn1fe.mjs";
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
+ import "./constants-B2QHb6u6.mjs";
3
3
  //#region src/registry/ResourceRegistry.ts
4
4
  /**
5
5
  * Resource Registry
@@ -17,13 +17,29 @@ var ResourceRegistry = class {
17
17
  * runtime-only handle is still reachable.
18
18
  */
19
19
  _adapters;
20
+ /** The mounted definitions, in registration order — see `getDefinitions`. */
21
+ _definitions;
20
22
  _frozen;
21
23
  constructor() {
22
24
  this._resources = /* @__PURE__ */ new Map();
23
25
  this._adapters = /* @__PURE__ */ new Map();
26
+ this._definitions = /* @__PURE__ */ new Map();
24
27
  this._frozen = false;
25
28
  }
26
29
  /**
30
+ * The live `ResourceDefinition`s that mounted, in registration order — what a host hands to
31
+ * `mcpPlugin({ resources })` or a docs generator instead of re-collecting them. A resource
32
+ * declaring `skipRegistry` (incl. `customRoutesOnly`) opted out and is absent. Fresh array per call.
33
+ * One composed module's share: `getModuleResources(fastify, name)` from `@classytic/arc/factory`.
34
+ */
35
+ getDefinitions() {
36
+ return [...this._definitions.values()];
37
+ }
38
+ /** The live definition registered under `name`, or `undefined`. */
39
+ getDefinition(name) {
40
+ return this._definitions.get(name);
41
+ }
42
+ /**
27
43
  * Get the live `DataAdapter` for a registered resource — the handle whose
28
44
  * `.repository` cascade / cleanup helpers actually call. Returns `undefined`
29
45
  * when the resource is unknown OR was registered without an adapter
@@ -33,12 +49,22 @@ var ResourceRegistry = class {
33
49
  getAdapter(name) {
34
50
  return this._adapters.get(name);
35
51
  }
52
+ /** Set only by an explicit `strictResources: false`: a duplicate name keeps the FIRST entry. */
53
+ _tolerateDuplicates = false;
54
+ /** Accept a duplicate resource name (the host opted out of `strictResources`; it was warned). */
55
+ tolerateDuplicateNames() {
56
+ this._tolerateDuplicates = true;
57
+ }
36
58
  /**
37
- * Register a resource
59
+ * Register a resource. A duplicate name throws — a resource missing from the registry still
60
+ * serves traffic but vanishes from introspection, the permission matrix and MCP.
38
61
  */
39
62
  register(resource, options = {}) {
40
63
  if (this._frozen) throw new Error(`Registry frozen. Cannot register '${resource.name}' after startup.`);
41
- if (this._resources.has(resource.name)) throw new Error(`Resource '${resource.name}' already registered.`);
64
+ if (this._resources.has(resource.name)) {
65
+ if (this._tolerateDuplicates) return this;
66
+ throw new Error(`Resource '${resource.name}' already registered.`);
67
+ }
42
68
  const entry = {
43
69
  name: resource.name,
44
70
  displayName: resource.displayName,
@@ -62,12 +88,21 @@ var ResourceRegistry = class {
62
88
  permissions: r.permissions,
63
89
  capability: r.capability,
64
90
  raw: r.rawHandler !== void 0,
65
- schema: r.schema
91
+ schema: r.schema,
92
+ ...(r.config?.idempotency)?.required === true ? { idempotency: {
93
+ required: true,
94
+ ...(r.config?.idempotency)?.dedup === "handler" ? {
95
+ dedup: "handler",
96
+ owner: String((r.config?.idempotency)?.owner)
97
+ } : {}
98
+ } } : {}
66
99
  })),
67
100
  events: Object.keys(resource.events ?? {}),
68
101
  registeredAt: (/* @__PURE__ */ new Date()).toISOString(),
69
102
  disableDefaultRoutes: resource.disableDefaultRoutes,
70
103
  tenantField: resource.tenantField,
104
+ idField: resource.idField,
105
+ versionField: resource.versionField,
71
106
  resolvedTenantPurge: resource.resolvedTenantPurge,
72
107
  updateMethod: resource.updateMethod,
73
108
  disabledRoutes: resource.disabledRoutes ? [...resource.disabledRoutes] : void 0,
@@ -76,6 +111,7 @@ var ResourceRegistry = class {
76
111
  fields: resource.fields && Object.keys(resource.fields).length > 0 ? resource.fields : void 0,
77
112
  pipelineSteps: extractPipelineSteps(resource.pipe),
78
113
  rateLimit: resource.rateLimit,
114
+ idempotency: resource.idempotency,
79
115
  audit: resource.audit,
80
116
  actionPermissions: resource.actionPermissions,
81
117
  actions: resource.actions ? Object.entries(resource.actions).map(([name, entry]) => {
@@ -86,6 +122,7 @@ var ResourceRegistry = class {
86
122
  schema: entry.schema,
87
123
  permissions: entry.permissions,
88
124
  mcp: entry.mcp,
125
+ idempotency: entry.idempotency,
89
126
  id: entry.id
90
127
  };
91
128
  }) : void 0,
@@ -108,6 +145,7 @@ var ResourceRegistry = class {
108
145
  };
109
146
  this._resources.set(resource.name, entry);
110
147
  if (resource.adapter) this._adapters.set(resource.name, resource.adapter);
148
+ this._definitions.set(resource.name, resource);
111
149
  return this;
112
150
  }
113
151
  /**
@@ -303,16 +341,9 @@ var ResourceRegistry = class {
303
341
  reset() {
304
342
  this._resources.clear();
305
343
  this._adapters.clear();
344
+ this._definitions.clear();
306
345
  this._frozen = false;
307
346
  }
308
- /** @internal Alias for unfreeze() */
309
- _unfreeze() {
310
- this.unfreeze();
311
- }
312
- /** @internal Alias for reset() */
313
- _clear() {
314
- this.reset();
315
- }
316
347
  /**
317
348
  * Group by key
318
349
  */
@@ -0,0 +1,35 @@
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
+ //#region src/idempotency/acquire.ts
3
+ async function acquireIdempotencyKey(store, key, requestId, lockTtlMs) {
4
+ if (typeof store.acquire === "function") return store.acquire(key, requestId, lockTtlMs);
5
+ return acquireBySteps(store, key, requestId, lockTtlMs);
6
+ }
7
+ /** `get` → `tryLock` → `get`, for stores without an atomic `acquire`. */
8
+ async function acquireBySteps(store, key, requestId, lockTtlMs) {
9
+ const cached = await store.get(key);
10
+ if (cached) return {
11
+ status: "completed",
12
+ result: cached
13
+ };
14
+ if (!await store.tryLock(key, requestId, lockTtlMs)) return { status: "locked" };
15
+ let completed;
16
+ try {
17
+ completed = await store.get(key);
18
+ } catch (err) {
19
+ await store.unlock(key, requestId);
20
+ throw err;
21
+ }
22
+ if (!completed) return { status: "acquired" };
23
+ await store.unlock(key, requestId);
24
+ return {
25
+ status: "completed",
26
+ result: completed
27
+ };
28
+ }
29
+ /** Release a held lock — skipped after a completion that already released it. */
30
+ async function releaseIdempotencyLock(store, key, requestId, completed) {
31
+ if (completed && store.completionReleasesLock === true) return;
32
+ await store.unlock(key, requestId);
33
+ }
34
+ //#endregion
35
+ export { acquireIdempotencyKey as n, releaseIdempotencyLock as r, acquireBySteps as t };