@classytic/arc 2.30.0 → 2.32.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 (242) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +7 -0
  3. package/TRADEMARK.md +22 -0
  4. package/dist/{BaseController-B5DwufbB.mjs → BaseController-Dk34dxhI.mjs} +21 -19
  5. package/dist/{EventTransport-QmY7A258.d.mts → EventTransport-2uVV34WU.d.mts} +1 -0
  6. package/dist/{EventTransport-C6YA8xY9.mjs → EventTransport-BV10D0oG.mjs} +1 -0
  7. package/dist/{HookSystem-WkIougo6.mjs → HookSystem-vimw5D7Z.mjs} +2 -1
  8. package/dist/{QueryCache-DOMT_iq7.d.mts → QueryCache-DFA-QrU9.d.mts} +2 -1
  9. package/dist/{ResourceRegistry-y9Hnypus.mjs → ResourceRegistry-BVr7PgA0.mjs} +18 -15
  10. package/dist/{actionPermissions-CAphcmUG.mjs → actionPermissions-Dti7ebyv.mjs} +1 -0
  11. package/dist/audit/index.d.mts +3 -2
  12. package/dist/audit/index.mjs +2 -1
  13. package/dist/auth/audit.d.mts +1 -0
  14. package/dist/auth/audit.mjs +1 -0
  15. package/dist/auth/index.d.mts +5 -4
  16. package/dist/auth/index.mjs +11 -9
  17. package/dist/auth/redis-session.d.mts +2 -1
  18. package/dist/auth/redis-session.mjs +1 -0
  19. package/dist/{applyPermissionResult-Cf6zUCvb.mjs → authorizationDecision-__T3EJDA.mjs} +19 -10
  20. package/dist/{buildHandler-BYS3Vkfz.mjs → buildHandler-Dn7rzUJo.mjs} +6 -4
  21. package/dist/cache/index.d.mts +4 -3
  22. package/dist/cache/index.mjs +4 -3
  23. package/dist/{caching-_NJeDd1_.mjs → caching-DFJqHyFs.mjs} +2 -1
  24. package/dist/cleanup/index.d.mts +39 -16
  25. package/dist/cleanup/index.mjs +50 -38
  26. package/dist/cli/commands/describe.d.mts +2 -1
  27. package/dist/cli/commands/describe.mjs +4 -5
  28. package/dist/cli/commands/docs.d.mts +1 -0
  29. package/dist/cli/commands/docs.mjs +3 -2
  30. package/dist/cli/commands/doctor.d.mts +1 -0
  31. package/dist/cli/commands/doctor.mjs +1 -0
  32. package/dist/cli/commands/generate.d.mts +2 -1
  33. package/dist/cli/commands/generate.mjs +2 -1
  34. package/dist/cli/commands/init.d.mts +2 -1
  35. package/dist/cli/commands/init.mjs +2 -1
  36. package/dist/cli/commands/introspect.d.mts +1 -0
  37. package/dist/cli/commands/introspect.mjs +2 -1
  38. package/dist/cli/index.d.mts +3 -2
  39. package/dist/cli/index.mjs +3 -2
  40. package/dist/{constants-DNre0wRg.mjs → constants-J99LGTJI.mjs} +1 -0
  41. package/dist/context/index.d.mts +1 -0
  42. package/dist/context/index.mjs +3 -2
  43. package/dist/core/index.d.mts +3 -2
  44. package/dist/core/index.mjs +7 -6
  45. package/dist/{core-poalJLvp.mjs → core-BwwmNSp7.mjs} +3 -2
  46. package/dist/{createActionRouter-BxuywVRB.mjs → createActionRouter-DkJZWo0m.mjs} +14 -10
  47. package/dist/{createAggregationRouter-BiY-lGdY.mjs → createAggregationRouter-B1exOVD8.mjs} +10 -7
  48. package/dist/{createApp-CXrKFciH.mjs → createApp-Bv0m-Q6_.mjs} +625 -229
  49. package/dist/{defineAggregation-ufWjUwml.mjs → defineAggregation-gX4No1gt.mjs} +1 -0
  50. package/dist/{defineResource-CxWqDCAy.mjs → defineResource-XFPPUu2c.mjs} +84 -50
  51. package/dist/discovery/index.d.mts +1 -0
  52. package/dist/discovery/index.mjs +1 -0
  53. package/dist/docs/index.d.mts +3 -2
  54. package/dist/docs/index.mjs +3 -2
  55. package/dist/{elevation-C9s5hFP_.d.mts → elevation-BXCfVcNG.d.mts} +1 -0
  56. package/dist/{elevation-CIz1GjGm.mjs → elevation-DNXXxgjl.mjs} +4 -3
  57. package/dist/encryption/index.d.mts +2 -1
  58. package/dist/encryption/index.mjs +5 -3
  59. package/dist/{errorHandler-Bq2OeEQL.mjs → errorHandler-B2AZUJUj.mjs} +3 -2
  60. package/dist/{errorHandler-C6yv4ZTW.d.mts → errorHandler-CpYUJmPA.d.mts} +1 -0
  61. package/dist/{errors-DHcHVAgk.d.mts → errors-BGdVwP25.d.mts} +1 -0
  62. package/dist/{errors-DkO8Nk6-.mjs → errors-Bh1KK5ps.mjs} +1 -0
  63. package/dist/{eventPlugin-D2NNR4py.mjs → eventPlugin-Dk_TyXeE.mjs} +8 -6
  64. package/dist/{eventPlugin-Bg3cP2_u.d.mts → eventPlugin-GF5nnBIq.d.mts} +2 -1
  65. package/dist/events/index.d.mts +112 -44
  66. package/dist/events/index.mjs +177 -141
  67. package/dist/events/transports/redis-stream-entry.d.mts +2 -1
  68. package/dist/events/transports/redis-stream-entry.mjs +14 -9
  69. package/dist/events/transports/redis.d.mts +2 -1
  70. package/dist/events/transports/redis.mjs +1 -0
  71. package/dist/{externalPaths-BE6wFpYv.d.mts → externalPaths-CmGOxOtD.d.mts} +1 -0
  72. package/dist/factory/index.d.mts +9 -5
  73. package/dist/factory/index.mjs +131 -7
  74. package/dist/fastify-augmentation-BppG5bMT.d.mts +179 -0
  75. package/dist/{fields-CQ_7KQWw.mjs → fields-DEi65pGj.mjs} +6 -10
  76. package/dist/{fields-D3lhgzhD.d.mts → fields-I_EeRWND.d.mts} +1 -0
  77. package/dist/{generate-D0wZupBg.mjs → generate-CRSG0jTv.mjs} +2 -1
  78. package/dist/{generate-BnsL9GBm.d.mts → generate-DCGuEbqI.d.mts} +1 -0
  79. package/dist/{headers-BvlQSDMB.mjs → headers-BXjQYbeC.mjs} +2 -1
  80. package/dist/{health-CB_m4S32.mjs → health-5XnTa2uo.mjs} +1 -0
  81. package/dist/hooks/index.d.mts +2 -1
  82. package/dist/hooks/index.mjs +2 -1
  83. package/dist/idempotency/index.d.mts +3 -2
  84. package/dist/idempotency/index.mjs +8 -5
  85. package/dist/idempotency/redis.d.mts +2 -1
  86. package/dist/idempotency/redis.mjs +1 -0
  87. package/dist/{index-CG4yqMDB.d.mts → index-C-481Zf2.d.mts} +74 -18
  88. package/dist/{index-Q5gzEIWY.d.mts → index-CpzxqePp.d.mts} +107 -32
  89. package/dist/{index-Cx7bro4R.d.mts → index-DXlHwvuE.d.mts} +5 -4
  90. package/dist/index-ZWhLTp_s.d.mts +290 -0
  91. package/dist/{index-Ch16aAah.d.mts → index-zq6VrjaB.d.mts} +122 -15
  92. package/dist/index.d.mts +9 -8
  93. package/dist/index.mjs +11 -10
  94. package/dist/{init-tlRSt667.mjs → init-BbfP8aky.mjs} +25 -27
  95. package/dist/{init-BPEu8cs-.d.mts → init-Cscs4lab.d.mts} +1 -0
  96. package/dist/integrations/event-gateway.d.mts +3 -2
  97. package/dist/integrations/event-gateway.mjs +2 -1
  98. package/dist/integrations/index.d.mts +4 -3
  99. package/dist/integrations/index.mjs +1 -0
  100. package/dist/integrations/jobs/index.d.mts +2 -1
  101. package/dist/integrations/jobs/index.mjs +109 -33
  102. package/dist/integrations/mcp/index.d.mts +6 -6
  103. package/dist/integrations/mcp/index.mjs +2 -1
  104. package/dist/integrations/mcp/testing.d.mts +3 -2
  105. package/dist/integrations/mcp/testing.mjs +2 -2
  106. package/dist/integrations/streamline.d.mts +1 -0
  107. package/dist/integrations/streamline.mjs +3 -2
  108. package/dist/integrations/webhooks.d.mts +1 -0
  109. package/dist/integrations/webhooks.mjs +1 -0
  110. package/dist/integrations/websocket-pushref-redis.d.mts +2 -1
  111. package/dist/integrations/websocket-pushref-redis.mjs +1 -0
  112. package/dist/integrations/websocket-redis.d.mts +2 -1
  113. package/dist/integrations/websocket-redis.mjs +1 -0
  114. package/dist/integrations/websocket.d.mts +3 -2
  115. package/dist/integrations/websocket.mjs +38 -34
  116. package/dist/{interface-BGZCzOGL.d.mts → interface-BOk3YnTz.d.mts} +1 -0
  117. package/dist/{interface-n5hpKg1d.mjs → interface-BP4IJCBO.mjs} +1 -0
  118. package/dist/{interface-Uk8ONJv7.d.mts → interface-DEWNOMza.d.mts} +1 -0
  119. package/dist/{jsonBody-BlzAoGCe.mjs → jsonBody-DDSR2HFl.mjs} +2 -1
  120. package/dist/{keys-Cd316u_y.mjs → keys-B-HBTGXl.mjs} +1 -0
  121. package/dist/{loadResources-DpU8pfjV.mjs → loadResources-DisEAmkm.mjs} +4 -2
  122. package/dist/{loadResourcesFromEntry-kvGT6EcO.mjs → loadResourcesFromEntry-D1MJp13f.mjs} +2 -1
  123. package/dist/logger/index.d.mts +1 -0
  124. package/dist/logger/index.mjs +1 -0
  125. package/dist/{mcpPlugin-nRzm5g2s.mjs → mcpPlugin-CpfVpKHE.mjs} +38 -38
  126. package/dist/{memory-CmnzXE5Z.mjs → memory-DsuWnj4T.mjs} +5 -4
  127. package/dist/{metrics-fdxI5mn_.mjs → metrics-DdQL8syd.mjs} +2 -1
  128. package/dist/middleware/index.d.mts +2 -1
  129. package/dist/middleware/index.mjs +3 -2
  130. package/dist/migrations/index.d.mts +1 -0
  131. package/dist/migrations/index.mjs +3 -2
  132. package/dist/module-Br81am6m.mjs +78 -0
  133. package/dist/{multipartBody-D0eBvkeq.mjs → multipartBody-BnkBLN7v.mjs} +3 -2
  134. package/dist/{openapi-B8Vkbxbn.mjs → openapi-DIRzvxC0.mjs} +6 -5
  135. package/dist/outbox-admin/index.d.mts +85 -0
  136. package/dist/outbox-admin/index.mjs +115 -0
  137. package/dist/permissions/index.d.mts +5 -4
  138. package/dist/permissions/index.mjs +6 -5
  139. package/dist/{permissions-Bfu_8y1U.mjs → permissions-Dl_m0NCe.mjs} +308 -42
  140. package/dist/{pipe-BOLmGIxa.mjs → pipe-ELHCP3zj.mjs} +3 -4
  141. package/dist/pipeline/index.d.mts +2 -1
  142. package/dist/pipeline/index.mjs +2 -1
  143. package/dist/{pipeline-BJnpkY9i.mjs → pipeline-CPA-jx0M.mjs} +17 -14
  144. package/dist/plugins/index.d.mts +8 -7
  145. package/dist/plugins/index.mjs +16 -15
  146. package/dist/plugins/response-cache.d.mts +1 -0
  147. package/dist/plugins/response-cache.mjs +2 -1
  148. package/dist/plugins/tracing-entry.d.mts +2 -1
  149. package/dist/plugins/tracing-entry.mjs +2 -1
  150. package/dist/{pluralize-BhrgwZb9.mjs → pluralize-C2ZkKbsn.mjs} +1 -0
  151. package/dist/{preloadResources-DSY5HGpS.mjs → preloadResources-CDs87fTw.mjs} +1 -0
  152. package/dist/{preloadResources-DCfa2egz.d.mts → preloadResources-T1hmlTEZ.d.mts} +117 -12
  153. package/dist/presets/filesUpload.d.mts +6 -5
  154. package/dist/presets/filesUpload.mjs +10 -12
  155. package/dist/presets/index.d.mts +3 -2
  156. package/dist/presets/index.mjs +2 -1
  157. package/dist/presets/multiTenant.d.mts +2 -1
  158. package/dist/presets/multiTenant.mjs +3 -2
  159. package/dist/presets/search.d.mts +3 -2
  160. package/dist/presets/search.mjs +2 -1
  161. package/dist/{presets-CJOEXLuk.mjs → presets-Dntd_pUO.mjs} +6 -4
  162. package/dist/{projection-UBDgfMwu.mjs → projection-CjHhM5W1.mjs} +2 -1
  163. package/dist/{pushref-registry-BbcnpNTm.d.mts → pushref-registry-Dov9l4qE.d.mts} +1 -0
  164. package/dist/{queryCachePlugin-br4otiqF.d.mts → queryCachePlugin-BzqxconG.d.mts} +3 -2
  165. package/dist/{queryCachePlugin-DSGuSVLW.mjs → queryCachePlugin-Dhps-Ldt.mjs} +6 -5
  166. package/dist/{rateLimit-DrED-C4v.mjs → rateLimit-C7mmAGs3.mjs} +7 -3
  167. package/dist/{rateLimitKey-BoWRH3e7.mjs → rateLimitKey-CccEFBfk.mjs} +1 -0
  168. package/dist/{realtime-B9nmIY5V.mjs → realtime-DVvVZZFz.mjs} +20 -9
  169. package/dist/{redis-UDtLaNj6.d.mts → redis-CduhKsJi.d.mts} +2 -1
  170. package/dist/{redis-stream-uIaauNpZ.d.mts → redis-stream-qN6A-RFv.d.mts} +2 -1
  171. package/dist/{registerRoute-JkxIEBJq.mjs → registerRoute-B_QrjYZS.mjs} +10 -7
  172. package/dist/registry/index.d.mts +3 -2
  173. package/dist/registry/index.mjs +3 -2
  174. package/dist/{registry-BYXUUg21.mjs → registry-DqUmzA9W.mjs} +2 -1
  175. package/dist/{renewingLease-3cuQH7h8.mjs → renewingLease-BpP9wwj7.mjs} +1 -0
  176. package/dist/{replyHelpers-67tRawQZ.mjs → replyHelpers-DS-P0b32.mjs} +2 -1
  177. package/dist/{repositoryFilter-Dz8k3S4P.mjs → repositoryFilter-DotlxG3L.mjs} +1 -0
  178. package/dist/{requestContext-MrlJwECf.mjs → requestContext-B6vQF-sy.mjs} +1 -0
  179. package/dist/{rolldown-runtime-8H4AJuhK.mjs → rolldown-runtime-BhflRrBs.mjs} +1 -0
  180. package/dist/{schedules-CjOd2MG9.mjs → schedules-C2Q3uv2d.mjs} +3 -2
  181. package/dist/{schemaConverter-DJvodiHj.mjs → schemaConverter-Crjvczi_.mjs} +70 -17
  182. package/dist/{schemaIR-Ca7ySNPx.mjs → schemaIR-CnyKK_1j.mjs} +2 -1
  183. package/dist/schemas/index.d.mts +1 -0
  184. package/dist/schemas/index.mjs +1 -0
  185. package/dist/scim/index.d.mts +1 -0
  186. package/dist/scim/index.mjs +2 -1
  187. package/dist/scope/index.d.mts +3 -2
  188. package/dist/scope/index.mjs +5 -4
  189. package/dist/{scope-DfaPntpo.mjs → scope-afz_Ieek.mjs} +4 -3
  190. package/dist/{sessionManager-BHOM3N_0.d.mts → sessionManager-qimlKV0P.d.mts} +1 -0
  191. package/dist/{simpleEqualityMatcher-Cg05HPsn.mjs → simpleEqualityMatcher-C4KiMWUa.mjs} +1 -0
  192. package/dist/{sse-BQ1w0dfl.mjs → sse-B9P4Y-UI.mjs} +7 -5
  193. package/dist/{sseStream-BQ7Qaynp.mjs → sseStream-B3zb_d1h.mjs} +2 -1
  194. package/dist/{storage-DLUZ04kK.d.mts → storage-Cx9Sz3Ou.d.mts} +1 -0
  195. package/dist/{store-helpers-DY6xq4sM.mjs → store-helpers-DmEMHlPQ.mjs} +1 -0
  196. package/dist/{streaming-BQcW6_Kq.mjs → streaming-DPZdQmDz.mjs} +1 -0
  197. package/dist/{subscribe-helpers-DfzsivM6.mjs → subscribe-helpers-sp5xTDVA.mjs} +2 -1
  198. package/dist/sync/changelog.d.mts +1 -0
  199. package/dist/sync/changelog.mjs +1 -0
  200. package/dist/testing/cleanupStoreContract.d.mts +2 -1
  201. package/dist/testing/cleanupStoreContract.mjs +10 -5
  202. package/dist/testing/index.d.mts +166 -12
  203. package/dist/testing/index.mjs +315 -43
  204. package/dist/testing/outboxStoreContract.d.mts +12 -2
  205. package/dist/testing/outboxStoreContract.mjs +110 -20
  206. package/dist/testing/storageContract.d.mts +2 -1
  207. package/dist/testing/storageContract.mjs +11 -5
  208. package/dist/{tracing-CsGKQJGg.d.mts → tracing-Dro5eH6j.d.mts} +1 -0
  209. package/dist/{transactionContext-PNdoyLLm.mjs → transactionContext-BvLKvOIL.mjs} +1 -0
  210. package/dist/{typeGuards-C9KXUly6.mjs → typeGuards-B_5-hKjJ.mjs} +1 -0
  211. package/dist/types/index.d.mts +6 -5
  212. package/dist/types/index.mjs +1 -0
  213. package/dist/types/storage.d.mts +2 -1
  214. package/dist/types/storage.mjs +1 -0
  215. package/dist/{types-ChvvVNP8.d.mts → types-B7XeLEgK.d.mts} +34 -2
  216. package/dist/{types-Cc91nXuA.d.mts → types-ByHn9rEO.d.mts} +1 -0
  217. package/dist/{types-C_ZZRcD6.d.mts → types-C4QE8qnm.d.mts} +1 -0
  218. package/dist/{types-D_n8L6VY.d.mts → types-CT5vu6M0.d.mts} +132 -17
  219. package/dist/{types-DjC-KUCz.d.mts → types-ChuShpCP.d.mts} +1 -0
  220. package/dist/{types-Bmmn-fO0.d.mts → types-CwcUQ610.d.mts} +2 -6
  221. package/dist/{types-CSyCxl2V.mjs → types-DXYX7dIR.mjs} +4 -3
  222. package/dist/usage/index.d.mts +3 -2
  223. package/dist/usage/index.mjs +0 -0
  224. package/dist/{userHelpers-Cg_y3fBz.mjs → userHelpers-BNsOXzOd.mjs} +1 -0
  225. package/dist/utils/index.d.mts +16 -7
  226. package/dist/utils/index.mjs +10 -9
  227. package/dist/{utils-taUVD4p3.mjs → utils-BtOha_Sp.mjs} +3 -2
  228. package/dist/{validate-Bk44F2yT.mjs → validate-PMCPR9El.mjs} +2 -1
  229. package/dist/{versioning-gKWyryT3.mjs → versioning-CKv2jz_U.mjs} +4 -3
  230. package/dist/{versioning-DXgY5BUm.d.mts → versioning-D_rhHfZm.d.mts} +5 -2
  231. package/dist/{websocket-_Pd0CgR0.d.mts → websocket-BOXVggMf.d.mts} +2 -1
  232. package/package.json +557 -539
  233. package/skills/arc/SKILL.md +22 -8
  234. package/skills/arc/references/api-reference.md +4 -0
  235. package/skills/arc/references/auth.md +3 -0
  236. package/skills/arc/references/integrations.md +33 -0
  237. package/skills/arc/references/mcp.md +6 -7
  238. package/skills/arc/references/production.md +24 -25
  239. package/skills/arc-code-review/references/anti-patterns.md +3 -3
  240. package/dist/fastify-augmentation-0WhPnUH7.d.mts +0 -76
  241. package/dist/index-CCzVR-N3.d.mts +0 -107
  242. package/dist/module-_-M7C5ES.mjs +0 -29
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
1
2
  //#region src/core/aggregation/defineAggregation.ts
2
3
  /**
3
4
  * Declare a single resource aggregation. Exported configs flow into
@@ -1,21 +1,22 @@
1
- import { s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS } from "./constants-DNre0wRg.mjs";
1
+ /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
2
+ import { s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS } from "./constants-J99LGTJI.mjs";
2
3
  import { arcLog } from "./logger/index.mjs";
3
- import { r as ForbiddenError } from "./errors-DkO8Nk6-.mjs";
4
- import { n as getUserRoles } from "./userHelpers-Cg_y3fBz.mjs";
5
- import { b as isElevated, n as PUBLIC_SCOPE, x as isMember } from "./types-CSyCxl2V.mjs";
6
- import { d as DEFAULT_FIELD_WRITE_DENIAL_POLICY, t as BaseController } from "./BaseController-B5DwufbB.mjs";
7
- import { a as buildRouteHooks, c as buildAuthMiddleware, i as selectPluginMw, n as buildRouteConfig, o as resolveRoutePreHandlers, r as resolveRouterPluginMw, s as routeHookOptions, t as buildRateLimitConfig, u as buildArcDecorator } from "./rateLimit-DrED-C4v.mjs";
8
- import { i as resolveEffectiveRoles, n as applyFieldWritePermissions } from "./fields-CQ_7KQWw.mjs";
9
- import { r as buildCrudPermissionMw, t as tryRegisterRoute } from "./registerRoute-JkxIEBJq.mjs";
10
- import { c as getDefaultCrudSchemas } from "./utils-taUVD4p3.mjs";
11
- import { n as convertRouteSchema, r as ensureSchemaConverter, t as convertOpenApiSchemas } from "./schemaConverter-DJvodiHj.mjs";
12
- import { i as pipeUIMessageStreamToReply, r as isReadableStream } from "./streaming-BQcW6_Kq.mjs";
13
- import { t as hasEvents } from "./typeGuards-C9KXUly6.mjs";
14
- import { a as createFastifyHandler, i as createCrudHandlers, n as buildPipelineHandler, o as createRequestContext, r as resolvePipelineSteps } from "./pipeline-BJnpkY9i.mjs";
15
- import { I as requireAuth } from "./permissions-Bfu_8y1U.mjs";
16
- import { r as getAvailablePresets, t as applyPresets } from "./presets-CJOEXLuk.mjs";
17
- import { t as pluralize } from "./pluralize-BhrgwZb9.mjs";
18
- import { t as resolveActionPermission } from "./actionPermissions-CAphcmUG.mjs";
4
+ import { r as ForbiddenError } from "./errors-Bh1KK5ps.mjs";
5
+ import { n as getUserRoles } from "./userHelpers-BNsOXzOd.mjs";
6
+ import { b as isElevated, n as PUBLIC_SCOPE, x as isMember } from "./types-DXYX7dIR.mjs";
7
+ import { d as DEFAULT_FIELD_WRITE_DENIAL_POLICY, t as BaseController } from "./BaseController-Dk34dxhI.mjs";
8
+ import { a as buildRouteHooks, c as buildAuthMiddleware, i as selectPluginMw, n as buildRouteConfig, o as resolveRoutePreHandlers, r as resolveRouterPluginMw, s as routeHookOptions, t as buildRateLimitConfig, u as buildArcDecorator } from "./rateLimit-C7mmAGs3.mjs";
9
+ import { i as resolveEffectiveRoles, n as applyFieldWritePermissions } from "./fields-DEi65pGj.mjs";
10
+ import { r as buildCrudPermissionMw, t as tryRegisterRoute } from "./registerRoute-B_QrjYZS.mjs";
11
+ import { c as getDefaultCrudSchemas } from "./utils-BtOha_Sp.mjs";
12
+ import { n as convertRouteSchema, r as ensureSchemaConverter, t as convertOpenApiSchemas } from "./schemaConverter-Crjvczi_.mjs";
13
+ import { i as pipeUIMessageStreamToReply, r as isReadableStream } from "./streaming-DPZdQmDz.mjs";
14
+ import { t as hasEvents } from "./typeGuards-B_5-hKjJ.mjs";
15
+ import { a as createFastifyHandler, i as createCrudHandlers, n as buildPipelineHandler, o as createRequestContext, r as resolvePipelineSteps } from "./pipeline-CPA-jx0M.mjs";
16
+ import { B as requireAuth } from "./permissions-Dl_m0NCe.mjs";
17
+ import { r as getAvailablePresets, t as applyPresets } from "./presets-Dntd_pUO.mjs";
18
+ import { t as pluralize } from "./pluralize-C2ZkKbsn.mjs";
19
+ import { t as resolveActionPermission } from "./actionPermissions-Dti7ebyv.mjs";
19
20
  //#region src/core/middlewares/fieldWrite.ts
20
21
  /**
21
22
  * Build a preHandler that enforces field-write permissions on the request body.
@@ -41,7 +42,10 @@ function buildFieldWritePreHandler(fieldPermissions, policy = DEFAULT_FIELD_WRIT
41
42
  if (!body || typeof body !== "object" || Array.isArray(body)) return;
42
43
  const scope = request.scope ?? PUBLIC_SCOPE;
43
44
  if (isElevated(scope)) return;
44
- const { body: filtered, deniedFields } = applyFieldWritePermissions(body, fieldPermissions, resolveEffectiveRoles(getUserRoles(request.user), isMember(scope) ? scope.orgRoles : []));
45
+ const globalRoles = getUserRoles(request.user);
46
+ const orgRoles = isMember(scope) ? scope.orgRoles : [];
47
+ const effectiveRoles = resolveEffectiveRoles(globalRoles, orgRoles);
48
+ const { body: filtered, deniedFields } = applyFieldWritePermissions(body, fieldPermissions, effectiveRoles);
45
49
  if (deniedFields.length > 0 && policy === "reject") throw new ForbiddenError(`Not permitted to write field${deniedFields.length === 1 ? "" : "s"}: ${deniedFields.join(", ")}`);
46
50
  request.body = filtered;
47
51
  };
@@ -58,25 +62,30 @@ function methodCarriesBody(method) {
58
62
  //#region src/core/createCrudRouter.ts
59
63
  /**
60
64
  * Mount custom routes (from presets or user-defined `routes`) on Fastify.
61
- * `wrapHandler` is derived inline from `!route.raw`.
65
+ * `wrapHandler` is derived inline from whether `rawHandler` was set.
62
66
  */
63
67
  function createCustomRoutes(fastify, routes, controller, options) {
64
68
  const { tag, resourceName, arcDecorator, rateLimitConfig, pluginMw, pipeline, routeGuards, tenantScopeMw, fieldPermissions, onFieldWriteDenied, extensions } = options;
65
69
  for (const route of routes) {
70
+ if ("raw" in route) throw new Error(`Route ${route.method} ${route.path}: \`raw\` was removed in arc 2.31 — the FIELD now carries the intent. Move the function to \`rawHandler\` (Fastify-native \`(request, reply)\`) or leave it in \`handler\` (arc pipeline, \`(ctx)\`), and delete the flag. If this route comes from a dependency, that package needs a release built against arc >=2.31.`);
66
71
  const routeWithRefs = route;
67
- const hasHandler = route.handler !== void 0;
72
+ const hasHandler = route.handler !== void 0 || route.rawHandler !== void 0;
68
73
  const hasControllerMethod = typeof routeWithRefs.controllerMethod === "function";
69
74
  if (hasHandler && hasControllerMethod) throw new Error(`Route ${route.method} ${route.path}: pass either \`handler\` or \`controllerMethod\`, not both. Prefer \`controllerMethod: (c: MyController) => c.method\` for typed handler refs (TS catches typos).`);
70
- if (!hasHandler && !hasControllerMethod) throw new Error(`Route ${route.method} ${route.path}: must declare either \`handler\` (string / function) or \`controllerMethod: (c) => c.method\` (typed function-ref form).`);
75
+ if (!hasHandler && !hasControllerMethod) throw new Error(`Route ${route.method} ${route.path}: must declare one of \`handler\` (arc pipeline), \`rawHandler\` (Fastify-native), or \`controllerMethod: (c) => c.method\` (typed function-ref form).`);
71
76
  let resolvedHandler;
72
77
  if (hasControllerMethod) {
73
78
  if (!controller) throw new Error(`Route ${route.method} ${route.path}: \`controllerMethod\` requires a controller. Provide one via \`defineResource({ controller, … })\`, or use \`defineResource\` with an \`adapter\` so arc auto-creates a BaseController.`);
74
79
  const referenced = routeWithRefs.controllerMethod?.(controller);
75
80
  if (typeof referenced !== "function") throw new Error(`Route ${route.method} ${route.path}: \`controllerMethod\` did not return a function. Return the method itself: \`controllerMethod: (c) => c.myMethod\`.`);
76
81
  resolvedHandler = referenced.bind(controller);
77
- } else resolvedHandler = route.handler;
82
+ } else {
83
+ if (route.rawHandler && route.handler) throw new Error(`Route ${route.method} ${route.path}: set either \`handler\` (arc pipeline) or \`rawHandler\` (Fastify-native), not both.`);
84
+ resolvedHandler = route.rawHandler ?? route.handler;
85
+ }
78
86
  const opName = route.operation ?? (typeof resolvedHandler === "string" ? resolvedHandler : `${route.method.toLowerCase()}${route.path.replace(/[/:]/g, "_")}`);
79
- const wrapHandler = !route.raw;
87
+ const isRaw = route.rawHandler !== void 0;
88
+ const wrapHandler = !isRaw;
80
89
  let handler;
81
90
  if (typeof resolvedHandler === "string") {
82
91
  if (!controller) throw new Error(`Route ${route.method} ${route.path}: string handler '${resolvedHandler}' requires a controller. Either provide a controller or use a function handler instead.`);
@@ -104,12 +113,13 @@ function createCustomRoutes(fastify, routes, controller, options) {
104
113
  if (!tenantScopeMw || tenantScopeMw.length === 0) throw new Error(`Route ${route.method} ${route.path}: \`tenantScope: true\` requires a multi-tenant preset. Add \`multiTenantPreset()\` (or \`flexibleMultiTenantPreset()\`) to the resource's \`presets\`, or remove the \`tenantScope\` flag from this route.`);
105
114
  customPreHandlers.unshift(...tenantScopeMw);
106
115
  }
107
- if (route.raw !== true && route.fieldWrite !== false && methodCarriesBody(route.method)) {
116
+ if (!isRaw && route.fieldWrite !== false && methodCarriesBody(route.method)) {
108
117
  const fieldWriteMw = buildFieldWritePreHandler(fieldPermissions, onFieldWriteDenied);
109
118
  if (fieldWriteMw) customPreHandlers.push(fieldWriteMw);
110
119
  }
120
+ const preAuthHandlers = route.preAuth ?? [];
111
121
  const hooks = buildRouteHooks({
112
- preAuth: route.preAuth ?? [],
122
+ preAuth: preAuthHandlers,
113
123
  arcDecorator,
114
124
  authMw: buildAuthMiddleware(fastify, route.permissions),
115
125
  permissionMw: buildCrudPermissionMw(route.permissions, resourceName, opName),
@@ -123,18 +133,18 @@ function createCustomRoutes(fastify, routes, controller, options) {
123
133
  url: route.path,
124
134
  schema,
125
135
  ...routeHookOptions(hooks),
126
- handler: isStream ? async (request, reply) => {
136
+ handler: isStream ? async function streamRoute(request, reply) {
127
137
  reply.raw.setHeader("Content-Type", "text/event-stream");
128
138
  reply.raw.setHeader("Cache-Control", "no-cache");
129
139
  reply.raw.setHeader("Connection", "keep-alive");
130
- const result = await handler(request, reply);
140
+ const result = await handler.call(this, request, reply);
131
141
  if (isReadableStream(result)) {
132
142
  await pipeUIMessageStreamToReply(reply, result);
133
143
  return reply;
134
144
  }
135
145
  return result;
136
146
  } : handler,
137
- ...buildRouteConfig(route.rateLimit !== void 0 ? buildRateLimitConfig(route.rateLimit) : rateLimitConfig, extensions)
147
+ ...buildRouteConfig(route.rateLimit !== void 0 ? buildRateLimitConfig(route.rateLimit) : rateLimitConfig, extensions, route.cors)
138
148
  }, {
139
149
  resourceName,
140
150
  op: opName
@@ -281,7 +291,8 @@ function buildCrudHandlers(ctrl, pipeline, resourceName) {
281
291
  for (const op of CRUD_OPERATIONS) {
282
292
  const steps = resolvePipelineSteps(pipeline, op);
283
293
  if (steps.length === 0) continue;
284
- wrapped[op] = buildPipelineHandler(ctrl[op].bind(ctrl), steps, op, resourceName);
294
+ const method = ctrl[op].bind(ctrl);
295
+ wrapped[op] = buildPipelineHandler(method, steps, op, resourceName);
285
296
  }
286
297
  return wrapped;
287
298
  }
@@ -640,8 +651,7 @@ function expandHistory(config) {
640
651
  method: "GET",
641
652
  path: "/:id/history",
642
653
  summary: `Change history for a ${resourceName} record (audit-backed timeline)`,
643
- raw: true,
644
- handler: async (request, reply) => {
654
+ rawHandler: async (request, reply) => {
645
655
  const audit = request.server.audit;
646
656
  if (!audit?.query || audit._noop === true) return reply.code(503).send({
647
657
  code: "history.audit_unavailable",
@@ -1221,11 +1231,13 @@ function buildResourcePlugin(resource) {
1221
1231
  handler: hook.handler,
1222
1232
  priority: hook.priority
1223
1233
  });
1224
- if (isFirstMount && resource.cache?.invalidateOn) if (fastify.registerCacheInvalidationRule) for (const [pattern, tags] of Object.entries(resource.cache.invalidateOn)) fastify.registerCacheInvalidationRule({
1225
- pattern,
1226
- tags
1227
- });
1228
- else fastify.log?.warn?.(`[Arc] Resource '${resource.name}' declares \`cache.invalidateOn\` but \`queryCachePlugin\` is not registered. Cache-invalidation rules are silently ignored. Either register the plugin (\`await fastify.register(queryCachePlugin, ...)\`) or remove the \`cache.invalidateOn\` config to clean up the resource definition.`);
1234
+ if (isFirstMount && resource.cache?.invalidateOn) {
1235
+ if (fastify.registerCacheInvalidationRule) for (const [pattern, tags] of Object.entries(resource.cache.invalidateOn)) fastify.registerCacheInvalidationRule({
1236
+ pattern,
1237
+ tags
1238
+ });
1239
+ else fastify.log?.warn?.(`[Arc] Resource '${resource.name}' declares \`cache.invalidateOn\` but \`queryCachePlugin\` is not registered. Cache-invalidation rules are silently ignored. Either register the plugin (\`await fastify.register(queryCachePlugin, ...)\`) or remove the \`cache.invalidateOn\` config to clean up the resource definition.`);
1240
+ }
1229
1241
  if (isFirstMount && resource.audit) {
1230
1242
  if (!(fastify.hasDecorator("audit") && typeof fastify.audit?.create === "function" && fastify.audit?._noop !== true)) fastify.log?.warn?.(`[Arc] Resource '${resource.name}' declares \`audit: ${JSON.stringify(resource.audit)}\` but \`auditPlugin\` is not registered (or is registered with a noop logger). Audit events for this resource will NOT be recorded. Either register \`auditPlugin\` (\`await fastify.register(auditPlugin, { store: ... })\`) or remove the \`audit\` flag from the resource definition.`);
1231
1243
  }
@@ -1266,7 +1278,7 @@ function buildResourcePlugin(resource) {
1266
1278
  extensions: resource.extensions
1267
1279
  });
1268
1280
  if (resource.actions && Object.keys(resource.actions).length > 0) {
1269
- const { createActionRouter } = await import("./createActionRouter-BxuywVRB.mjs").then((n) => n.n);
1281
+ const { createActionRouter } = await import("./createActionRouter-DkJZWo0m.mjs").then((n) => n.n);
1270
1282
  createActionRouter(typedInstance, {
1271
1283
  ...normalizeActionsToRouterConfig(resource.actions, resource.actionPermissions, resource.tag, resource.permissions, resource.name, typedInstance.log),
1272
1284
  resourceName: resource.name,
@@ -1281,7 +1293,7 @@ function buildResourcePlugin(resource) {
1281
1293
  });
1282
1294
  }
1283
1295
  if (resource.aggregations && Object.keys(resource.aggregations).length > 0) {
1284
- const [{ createAggregationRouter }, { adapterSupportsAggregate, ArcAggregationConfigError }] = await Promise.all([import("./createAggregationRouter-BiY-lGdY.mjs"), import("./validate-Bk44F2yT.mjs").then((n) => n.r)]);
1296
+ const [{ createAggregationRouter }, { adapterSupportsAggregate, ArcAggregationConfigError }] = await Promise.all([import("./createAggregationRouter-B1exOVD8.mjs"), import("./validate-PMCPR9El.mjs").then((n) => n.r)]);
1285
1297
  const repoForAgg = resource.controller?.repository ?? resource.repository;
1286
1298
  if (!adapterSupportsAggregate(repoForAgg)) {
1287
1299
  const undispatchable = Object.entries(resource.aggregations).filter(([, cfg]) => !cfg.materialized).map(([name]) => name);
@@ -1481,10 +1493,12 @@ var ResourceDefinition = class {
1481
1493
  _validateControllerMethods() {
1482
1494
  const errors = [];
1483
1495
  const enabledCrudRoutes = CRUD_OPERATIONS.filter((route) => !this.disabledRoutes.includes(route));
1484
- if (!this.disableDefaultRoutes && enabledCrudRoutes.length > 0) if (!this.controller) errors.push("Controller is required when CRUD routes are enabled");
1485
- else {
1486
- const ctrl = this.controller;
1487
- for (const method of enabledCrudRoutes) if (typeof ctrl[method] !== "function") errors.push(`CRUD method '${method}' not found on controller`);
1496
+ if (!this.disableDefaultRoutes && enabledCrudRoutes.length > 0) {
1497
+ if (!this.controller) errors.push("Controller is required when CRUD routes are enabled");
1498
+ else {
1499
+ const ctrl = this.controller;
1500
+ for (const method of enabledCrudRoutes) if (typeof ctrl[method] !== "function") errors.push(`CRUD method '${method}' not found on controller`);
1501
+ }
1488
1502
  }
1489
1503
  for (const route of this.routes) {
1490
1504
  if (typeof route.handler !== "string") continue;
@@ -1537,7 +1551,7 @@ var ResourceDefinition = class {
1537
1551
  summary: r.summary,
1538
1552
  description: r.description,
1539
1553
  permissions: r.permissions,
1540
- raw: r.raw,
1554
+ raw: r.rawHandler !== void 0,
1541
1555
  schema: r.schema
1542
1556
  })),
1543
1557
  routes: [],
@@ -1815,17 +1829,22 @@ function validateResourceConfig(config, options = {}) {
1815
1829
  }
1816
1830
  function validateRouteHandlers(controller, routes, errors) {
1817
1831
  const ctrl = controller;
1818
- for (const route of routes) if (typeof route.handler === "string") {
1819
- if (typeof ctrl[route.handler] !== "function") errors.push({
1832
+ for (const route of routes) {
1833
+ const named = typeof route.handler === "string" ? route.handler : route.rawHandler;
1834
+ if (typeof named !== "string") continue;
1835
+ if (typeof ctrl[named] !== "function") errors.push({
1820
1836
  field: `routes[${route.method} ${route.path}]`,
1821
- message: `Handler "${route.handler}" not found on controller`,
1822
- suggestion: `Add method "${route.handler}" to controller or use a function handler`
1837
+ message: `Handler "${named}" not found on controller`,
1838
+ suggestion: `Add method "${named}" to controller or use a function handler`
1823
1839
  });
1824
1840
  }
1825
1841
  }
1826
1842
  function validatePermissionKeys(config, options, _errors, warnings) {
1827
1843
  const validKeys = /* @__PURE__ */ new Set([...CRUD_OPERATIONS, ...options.additionalPermissionKeys ?? []]);
1828
- for (const route of config.routes ?? []) if (typeof route.handler === "string") validKeys.add(route.handler);
1844
+ for (const route of config.routes ?? []) {
1845
+ if (typeof route.handler === "string") validKeys.add(route.handler);
1846
+ if (typeof route.rawHandler === "string") validKeys.add(route.rawHandler);
1847
+ }
1829
1848
  for (const preset of config.presets ?? []) {
1830
1849
  const presetName = typeof preset === "string" ? preset : preset.name;
1831
1850
  if (presetName === "softDelete") {
@@ -1966,11 +1985,26 @@ function validateRoutes(routes, errors) {
1966
1985
  suggestion: `Change to "/${route.path}"`
1967
1986
  });
1968
1987
  const routeWithRefs = route;
1969
- if (!route.handler && typeof routeWithRefs.controllerMethod !== "function") errors.push({
1988
+ if (!route.handler && !route.rawHandler && typeof routeWithRefs.controllerMethod !== "function") errors.push({
1970
1989
  field: `routes[${i}].handler`,
1971
- message: "Route must declare either `handler` (string / function) or `controllerMethod`",
1990
+ message: "Route must declare one of `handler` (arc pipeline), `rawHandler` (Fastify-native), or `controllerMethod`",
1972
1991
  suggestion: "Prefer `controllerMethod: (c: MyController) => c.method` for typed handler refs."
1973
1992
  });
1993
+ if (route.handler && route.rawHandler) errors.push({
1994
+ field: `routes[${i}].rawHandler`,
1995
+ message: "Route declares BOTH `handler` and `rawHandler`",
1996
+ suggestion: "Use `handler` for the arc pipeline (receives IRequestContext) or `rawHandler` for a Fastify-native handler (receives request, reply) — not both."
1997
+ });
1998
+ if ("raw" in route) errors.push({
1999
+ field: `routes[${i}].raw`,
2000
+ message: "`raw` was removed in arc 2.31 — the field now carries the intent",
2001
+ suggestion: "Move the function to `rawHandler` (Fastify-native) or leave it in `handler` (arc pipeline), and delete the flag. If the route comes from a dependency, that package needs a release built against arc >=2.31."
2002
+ });
2003
+ if (route.streamResponse === true && route.rawHandler === void 0) errors.push({
2004
+ field: `routes[${i}].streamResponse`,
2005
+ message: "`streamResponse: true` requires `rawHandler`",
2006
+ suggestion: "Streaming routes are invoked with `(request, reply)` and own the socket — declare the function as `rawHandler` (not `handler` or `controllerMethod`)."
2007
+ });
1974
2008
  const routeKey = `${route.method} ${route.path}`;
1975
2009
  if (seenRoutes.has(routeKey)) errors.push({
1976
2010
  field: `routes[${i}]`,
@@ -1,3 +1,4 @@
1
+
1
2
  import { FastifyPluginAsync } from "fastify";
2
3
  //#region src/discovery/index.d.ts
3
4
  /** A discovered resource — must have toPlugin() method */
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
1
2
  import { readdir } from "node:fs/promises";
2
3
  import { extname, join, resolve } from "node:path";
3
4
  import { pathToFileURL } from "node:url";
@@ -1,5 +1,6 @@
1
- import { p as RegistryEntry } from "../index-Q5gzEIWY.mjs";
2
- import { t as ExternalOpenApiPaths } from "../externalPaths-BE6wFpYv.mjs";
1
+
2
+ import { p as RegistryEntry } from "../index-CpzxqePp.mjs";
3
+ import { t as ExternalOpenApiPaths } from "../externalPaths-CmGOxOtD.mjs";
3
4
  import { FastifyPluginAsync } from "fastify";
4
5
  //#region src/docs/openapi/types.d.ts
5
6
  /**
@@ -1,5 +1,6 @@
1
- import { n as getUserRoles } from "../userHelpers-Cg_y3fBz.mjs";
2
- import { n as openApiPlugin, r as openapi_default, t as buildOpenApiSpec } from "../openapi-B8Vkbxbn.mjs";
1
+ /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
2
+ import { n as getUserRoles } from "../userHelpers-BNsOXzOd.mjs";
3
+ import { n as openApiPlugin, r as openapi_default, t as buildOpenApiSpec } from "../openapi-DIRzvxC0.mjs";
3
4
  import fp from "fastify-plugin";
4
5
  //#region src/docs/scalar.ts
5
6
  const scalarPlugin = async (fastify, opts = {}) => {
@@ -1,3 +1,4 @@
1
+
1
2
  import { FastifyPluginAsync, FastifyRequest } from "fastify";
2
3
  //#region src/scope/elevation.d.ts
3
4
  interface ElevationOptions {
@@ -1,7 +1,8 @@
1
- import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
1
+ /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
2
+ import { t as __exportAll } from "./rolldown-runtime-BhflRrBs.mjs";
2
3
  import { arcLog } from "./logger/index.mjs";
3
- import { n as requireSingleHeaderValue } from "./headers-BvlQSDMB.mjs";
4
- import { n as getUserRoles } from "./userHelpers-Cg_y3fBz.mjs";
4
+ import { n as requireSingleHeaderValue } from "./headers-BXjQYbeC.mjs";
5
+ import { n as getUserRoles } from "./userHelpers-BNsOXzOd.mjs";
5
6
  import fp from "fastify-plugin";
6
7
  //#region src/scope/elevation.ts
7
8
  var elevation_exports = /* @__PURE__ */ __exportAll({
@@ -1,4 +1,5 @@
1
- import { a as JweAlg, c as KeyMaterial, i as EncryptionOptions, l as KeyProvider, n as EncryptionDirective, o as JweEnc, r as EncryptionMode, s as KeyContext, t as ActiveKey } from "../types-Cc91nXuA.mjs";
1
+
2
+ import { a as JweAlg, c as KeyMaterial, i as EncryptionOptions, l as KeyProvider, n as EncryptionDirective, o as JweEnc, r as EncryptionMode, s as KeyContext, t as ActiveKey } from "../types-ByHn9rEO.mjs";
2
3
  import { FastifyPluginAsync } from "fastify";
3
4
  //#region src/encryption/encryptionPlugin.d.ts
4
5
  declare const encryptionPlugin: FastifyPluginAsync<EncryptionOptions>;
@@ -1,5 +1,6 @@
1
- import { t as ArcError } from "../errors-DkO8Nk6-.mjs";
2
- import { t as parseJsonBody } from "../jsonBody-BlzAoGCe.mjs";
1
+ /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
2
+ import { t as ArcError } from "../errors-Bh1KK5ps.mjs";
3
+ import { t as parseJsonBody } from "../jsonBody-DDSR2HFl.mjs";
3
4
  import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
4
5
  import fp from "fastify-plugin";
5
6
  //#region src/encryption/fieldCipher.ts
@@ -70,7 +71,8 @@ function parseFieldEnvelope(token) {
70
71
  }
71
72
  /** Decrypt a parsed `arc.v1` envelope with the resolved key. Throws on tamper. */
72
73
  function decryptField(envelope, key) {
73
- const decipher = createDecipheriv("aes-256-gcm", toKeyBuffer(key), envelope.iv);
74
+ const secret = toKeyBuffer(key);
75
+ const decipher = createDecipheriv("aes-256-gcm", secret, envelope.iv);
74
76
  decipher.setAuthTag(envelope.tag);
75
77
  return Buffer.concat([decipher.update(envelope.ciphertext), decipher.final()]).toString("utf8");
76
78
  }
@@ -1,5 +1,6 @@
1
- import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
2
- import { m as statusToArcCode, p as isArcError } from "./errors-DkO8Nk6-.mjs";
1
+ /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
2
+ import { t as __exportAll } from "./rolldown-runtime-BhflRrBs.mjs";
3
+ import { m as statusToArcCode, p as isArcError } from "./errors-Bh1KK5ps.mjs";
3
4
  import { isHttpError, toErrorContract } from "@classytic/repo-core/errors";
4
5
  import fp from "fastify-plugin";
5
6
  //#region src/plugins/errorHandler.ts
@@ -1,3 +1,4 @@
1
+
1
2
  import { ErrorDetail } from "@classytic/repo-core/errors";
2
3
  import { FastifyInstance, FastifyRequest } from "fastify";
3
4
  //#region src/plugins/errorHandler.d.ts
@@ -1,3 +1,4 @@
1
+
1
2
  import { HttpError } from "@classytic/repo-core/errors";
2
3
  //#region src/utils/errors.d.ts
3
4
  interface ErrorOptions {
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
1
2
  //#region src/utils/errors.ts
2
3
  /**
3
4
  * Base Arc Error. Implements the canonical `HttpError` contract — `status`
@@ -1,8 +1,9 @@
1
- import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
1
+ /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
2
+ import { t as __exportAll } from "./rolldown-runtime-BhflRrBs.mjs";
2
3
  import { arcLog } from "./logger/index.mjs";
3
- import { d as createDomainError } from "./errors-DkO8Nk6-.mjs";
4
- import { n as requestContext } from "./requestContext-MrlJwECf.mjs";
5
- import { n as createEvent, t as MemoryEventTransport } from "./EventTransport-C6YA8xY9.mjs";
4
+ import { d as createDomainError } from "./errors-Bh1KK5ps.mjs";
5
+ import { n as requestContext } from "./requestContext-B6vQF-sy.mjs";
6
+ import { n as createEvent, t as MemoryEventTransport } from "./EventTransport-BV10D0oG.mjs";
6
7
  import fp from "fastify-plugin";
7
8
  //#region src/events/retry.ts
8
9
  /**
@@ -138,10 +139,11 @@ const eventPlugin = async (fastify, opts = {}) => {
138
139
  if (type.startsWith("$") && type !== "$deadLetter") throw new Error(`[Arc Events] Event type '${type}' uses reserved '$' prefix`);
139
140
  if (type.length > 256) throw new Error("[Arc Events] Event type exceeds 256 characters");
140
141
  const store = requestContext.get();
141
- const event = createEvent(type, payload, {
142
+ const enrichedMeta = {
142
143
  ...store?.requestId && !meta?.correlationId ? { correlationId: store.requestId } : {},
143
144
  ...meta
144
- });
145
+ };
146
+ const event = createEvent(type, payload, enrichedMeta);
145
147
  if (warnOnDuplicate && event.meta.correlationId) {
146
148
  const now = Date.now();
147
149
  evictExpiredPublishes(now);
@@ -1,4 +1,5 @@
1
- import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "./EventTransport-QmY7A258.mjs";
1
+
2
+ import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "./EventTransport-2uVV34WU.mjs";
2
3
  import { FastifyPluginAsync } from "fastify";
3
4
  //#region src/events/defineEvent.d.ts
4
5
  interface EventSchema {
@@ -1,8 +1,12 @@
1
- import { a as EventTransport, i as EventLogger, n as DomainEvent, o as MemoryEventTransport, r as EventHandler, s as MemoryEventTransportOptions, t as DeadLetteredEvent } from "../EventTransport-QmY7A258.mjs";
2
- import { a as withRetry, c as EventDefinitionOutput, d as EventSchema, f as ValidationResult, i as createDeadLetterPublisher, l as EventRegistry, m as defineEvent, n as eventPlugin, o as CustomValidator, p as createEventRegistry, r as RetryOptions, s as EventDefinitionInput, t as EventPluginOptions, u as EventRegistryOptions } from "../eventPlugin-Bg3cP2_u.mjs";
1
+
2
+ import { a as EventTransport, i as EventLogger, n as DomainEvent, o as MemoryEventTransport, r as EventHandler, s as MemoryEventTransportOptions, t as DeadLetteredEvent } from "../EventTransport-2uVV34WU.mjs";
3
+ import { t as ArcModule } from "../types-CT5vu6M0.mjs";
4
+ import { a as withRetry, c as EventDefinitionOutput, d as EventSchema, f as ValidationResult, i as createDeadLetterPublisher, l as EventRegistry, m as defineEvent, n as eventPlugin, o as CustomValidator, p as createEventRegistry, r as RetryOptions, s as EventDefinitionInput, t as EventPluginOptions, u as EventRegistryOptions } from "../eventPlugin-GF5nnBIq.mjs";
3
5
  import { RedisEventTransportOptions, RedisLike } from "./transports/redis.mjs";
4
- import { r as RedisStreamTransportOptions, t as RedisStreamLike } from "../redis-stream-uIaauNpZ.mjs";
5
- import { OutboxAcknowledgeOptions, OutboxClaimOptions, OutboxErrorInfo, OutboxFailOptions, OutboxFailurePolicy, OutboxStore, OutboxWriteOptions } from "@classytic/primitives/outbox";
6
+ import { r as RedisStreamTransportOptions, t as RedisStreamLike } from "../redis-stream-qN6A-RFv.mjs";
7
+ import { FastifyInstance } from "fastify";
8
+ import { MemoryOutboxStore } from "@classytic/primitives/memory-outbox";
9
+ import { OutboxFailurePolicy, OutboxStore, OutboxWriteOptions } from "@classytic/primitives/outbox";
6
10
  import { RepositoryLike } from "@classytic/repo-core/adapter";
7
11
  //#region src/events/eventTypes.d.ts
8
12
  /**
@@ -55,44 +59,6 @@ declare const CACHE_EVENTS: Readonly<{
55
59
  /** Type for cache event names */
56
60
  type CacheEvent = (typeof CACHE_EVENTS)[keyof typeof CACHE_EVENTS];
57
61
  //#endregion
58
- //#region src/events/memory-outbox.d.ts
59
- interface MemoryEntry {
60
- event: DomainEvent;
61
- status: "pending" | "delivered" | "dead_letter";
62
- attempts: number;
63
- visibleAt: number;
64
- leaseOwner: string | null;
65
- leaseExpiresAt: number;
66
- deliveredAt: number | null;
67
- firstFailedAt: number | null;
68
- lastFailedAt: number | null;
69
- lastError: OutboxErrorInfo | null;
70
- dedupeKey?: string;
71
- }
72
- declare class MemoryOutboxStore implements OutboxStore {
73
- private readonly entries;
74
- private readonly seenDedupeKeys;
75
- /**
76
- * Drop every entry (including delivered / failed / dead-lettered rows) and
77
- * the dedupe-key memory.
78
- *
79
- * For tests only — it is the in-memory analogue of truncating the table, and
80
- * exists so a suite can isolate cases against ONE store instance (the
81
- * `reset` hook of `runOutboxStoreContract`). Not part of `OutboxStore`; a
82
- * production store must never expose this.
83
- */
84
- clear(): void;
85
- save(event: DomainEvent, options?: OutboxWriteOptions): Promise<void>;
86
- getPending(limit: number): Promise<DomainEvent[]>;
87
- claimPending(options?: OutboxClaimOptions): Promise<DomainEvent[]>;
88
- acknowledge(eventId: string, options?: OutboxAcknowledgeOptions): Promise<void>;
89
- fail(eventId: string, error: OutboxErrorInfo, options?: OutboxFailOptions): Promise<void>;
90
- getDeadLettered(limit: number): Promise<DeadLetteredEvent[]>;
91
- purge(olderThanMs: number): Promise<number>;
92
- /** Test helper: inspect entry by id */
93
- _getEntry(eventId: string): Readonly<MemoryEntry> | undefined;
94
- }
95
- //#endregion
96
62
  //#region src/events/outbox/backoff.d.ts
97
63
  /**
98
64
  * Exponential backoff for outbox failure policies — pure date math shared
@@ -404,6 +370,97 @@ declare class EventOutbox {
404
370
  purge(olderThanMs?: number): Promise<number>;
405
371
  }
406
372
  //#endregion
373
+ //#region src/events/outbox-module.d.ts
374
+ interface OutboxModuleOptions {
375
+ /**
376
+ * The durable store. Supply it directly, or as a factory when it needs the booted app
377
+ * (a mongoose connection decorated by an earlier plugin, for instance).
378
+ */
379
+ store: OutboxStore | ((fastify: FastifyInstance) => OutboxStore);
380
+ /**
381
+ * Where relayed events are published. Omit to use `fastify.events` — the ordinary case; pass
382
+ * one only when the outbox must publish somewhere other than the app's own transport.
383
+ */
384
+ transport?: EventTransport | ((fastify: FastifyInstance) => EventTransport);
385
+ /** Module name, and therefore the `dependsOn` key. Default `'outbox'`. */
386
+ name?: string;
387
+ /** Relay interval in ms. Default 5000. */
388
+ relayEveryMs?: number;
389
+ /**
390
+ * Rows per relay tick. Left to the store's own default when omitted — a batch size is a
391
+ * throughput tuning decision, not something this module should invent.
392
+ */
393
+ batchSize?: number;
394
+ /** Lease duration for a claimed batch, in ms. */
395
+ leaseMs?: number;
396
+ /**
397
+ * Consumer id recorded on the lease. Default `'arc-outbox-relay'`.
398
+ *
399
+ * Give each relaying process a DISTINCT id when several run: the lease is what stops two
400
+ * relays publishing the same event, and it can only do that if they are distinguishable.
401
+ */
402
+ consumerId?: string;
403
+ /**
404
+ * Called for every non-fatal relay problem — publish failures, ownership mismatches,
405
+ * acknowledge failures.
406
+ *
407
+ * **Wire this.** Silence here is the failure mode that matters: the relay keeps ticking, rows
408
+ * keep failing, and the only symptom is revenue that never posted.
409
+ */
410
+ onError?: OutboxRelayErrorHandler;
411
+ /**
412
+ * Retry / dead-letter policy for a failed publish — `({ attempts }) => { retryAt } |
413
+ * { deadLetter: true }`.
414
+ *
415
+ * Omitting it takes `EventOutbox`'s default. Exposed because a real host had one and losing it
416
+ * on adoption would be a silent downgrade: without a policy a permanently-failing row either
417
+ * retries forever or dead-letters on the first blip, and both are wrong for money. A typical
418
+ * shape is exponential backoff up to N attempts, then dead-letter.
419
+ */
420
+ failurePolicy?: OutboxFailurePolicy;
421
+ /**
422
+ * Run one relay pass at boot. Default `true` — a process that restarts with a backlog should
423
+ * drain it immediately rather than waiting a full interval, because that backlog is precisely
424
+ * the events the previous process failed to publish.
425
+ */
426
+ runOnStart?: boolean;
427
+ }
428
+ /** What the module exports at `fastify.arc.modules.<name>`. */
429
+ interface OutboxModuleExports {
430
+ /** The store, for consumers that write events transactionally. */
431
+ store: OutboxStore;
432
+ /** The relay, for a host that wants to drain on demand (tests, admin actions). */
433
+ relay: EventOutbox;
434
+ }
435
+ /**
436
+ * Compose the outbox as a module.
437
+ *
438
+ * ```ts
439
+ * // host
440
+ * const model = createOutboxModel(connection, { visibleAtField: 'nextVisibleAt' });
441
+ * createApp({ modules: [
442
+ * createOutboxModule({
443
+ * store: repositoryAsOutboxStore(new Repository(model), { visibleAtField: 'nextVisibleAt' }),
444
+ * onError: (err, ctx) => app.log.error({ err, ...ctx }, 'outbox relay'),
445
+ * }),
446
+ * …
447
+ * ]});
448
+ *
449
+ * // consumer module
450
+ * defineModule({
451
+ * name: 'order',
452
+ * dependsOn: ['outbox'],
453
+ * bootstrap: (f) => createOrder({
454
+ * outbox: getModuleExports<OutboxModuleExports>(f, 'outbox').store,
455
+ * }),
456
+ * });
457
+ * ```
458
+ *
459
+ * `dependsOn` is doing real work there: it both orders the bootstraps and makes a missing outbox a
460
+ * boot error naming the module that needed it.
461
+ */
462
+ declare function createOutboxModule(options: OutboxModuleOptions): ArcModule<OutboxModuleExports>;
463
+ //#endregion
407
464
  //#region src/events/repository-outbox-adapter.d.ts
408
465
  interface RepositoryOutboxStoreOptions {
409
466
  /**
@@ -421,7 +478,18 @@ interface RepositoryOutboxStoreOptions {
421
478
  */
422
479
  readonly visibleAtField?: string;
423
480
  }
424
- declare function repositoryAsOutboxStore(repository: RepositoryLike, options?: RepositoryOutboxStoreOptions): OutboxStore;
481
+ /**
482
+ * What this adapter GUARANTEES, as opposed to what `OutboxStore` permits.
483
+ *
484
+ * Most of the contract is optional so a minimal or non-relational store can implement
485
+ * the floor and no more. This adapter implements all of it, and saying so in the type
486
+ * is not cosmetic: with a plain `OutboxStore` return every caller of `getDeadLettered`,
487
+ * `requeue` or `countByStatus` has to write `store.requeue?.(id)`, and the `?.` silently
488
+ * evaluates to `undefined` if the method ever disappears — an operator's replay that
489
+ * quietly does nothing and reports success.
490
+ */
491
+ type RepositoryOutboxStore = OutboxStore & Required<Pick<OutboxStore, "fail" | "getDeadLettered" | "purge" | "requeue" | "countByStatus" | "oldestPendingAgeMs">>;
492
+ declare function repositoryAsOutboxStore(repository: RepositoryLike, options?: RepositoryOutboxStoreOptions): RepositoryOutboxStore;
425
493
  //#endregion
426
494
  //#region src/events/subscribe-helpers.d.ts
427
495
  /**
@@ -582,4 +650,4 @@ interface FastifyEventBus {
582
650
  };
583
651
  }
584
652
  //#endregion
585
- export { ARC_LIFECYCLE_EVENTS, type ArcLifecycleEvent, CACHE_EVENTS, CRUD_EVENT_SUFFIXES, type CacheEvent, type CrudEventSuffix, type CustomValidator, type EventDefinitionInput, type EventDefinitionOutput, EventOutbox, type EventOutboxOptions, type EventPluginOptions, type EventRegistry, type EventRegistryOptions, type EventSchema, type ExponentialBackoffOptions, MemoryEventTransport, type MemoryEventTransportOptions, MemoryOutboxStore, type OutboxRelayErrorHandler, type OutboxRelayErrorKind, type PayloadOf, type RedisEventTransportOptions, type RedisLike, type RedisStreamLike, type RedisStreamTransportOptions, type RelayResult, type RepositoryOutboxStoreOptions, type RetryOptions, type ValidationResult, type WrapWithBoundaryOptions, type WrapWithSchemaOptions, createDeadLetterPublisher, createEventRegistry, crudEventType, defineEvent, eventPlugin, exponentialBackoff, repositoryAsOutboxStore, subscribeWithBoundary, subscribeWithSchema, withRetry, wrapWithBoundary, wrapWithSchema };
653
+ export { ARC_LIFECYCLE_EVENTS, type ArcLifecycleEvent, CACHE_EVENTS, CRUD_EVENT_SUFFIXES, type CacheEvent, type CrudEventSuffix, type CustomValidator, type EventDefinitionInput, type EventDefinitionOutput, EventOutbox, type EventOutboxOptions, type EventPluginOptions, type EventRegistry, type EventRegistryOptions, type EventSchema, type ExponentialBackoffOptions, MemoryEventTransport, type MemoryEventTransportOptions, MemoryOutboxStore, type OutboxModuleExports, type OutboxModuleOptions, type OutboxRelayErrorHandler, type OutboxRelayErrorKind, type PayloadOf, type RedisEventTransportOptions, type RedisLike, type RedisStreamLike, type RedisStreamTransportOptions, type RelayResult, type RepositoryOutboxStore, type RepositoryOutboxStoreOptions, type RetryOptions, type ValidationResult, type WrapWithBoundaryOptions, type WrapWithSchemaOptions, createDeadLetterPublisher, createEventRegistry, createOutboxModule, crudEventType, defineEvent, eventPlugin, exponentialBackoff, repositoryAsOutboxStore, subscribeWithBoundary, subscribeWithSchema, withRetry, wrapWithBoundary, wrapWithSchema };