@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
@@ -1,3 +1,2 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
2
- import { t as init } from "../../init-CpLkjU18.mjs";
3
- export { init };
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
+ export { t as init } from "../../init-BPzK5Lnr.mjs";
@@ -6,6 +6,5 @@
6
6
  * Shows all registered resources and their configuration.
7
7
  * Requires an entry file that exports defineResource() results.
8
8
  */
9
- declare function introspect(args: string[]): Promise<void>;
10
- //#endregion
11
- export { introspect };
9
+ export declare function introspect(args: string[]): Promise<void>;
10
+ //#endregion
@@ -1,5 +1,5 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
2
- import { t as loadResourcesFromEntry } from "../../loadResourcesFromEntry-ixtfL3J2.mjs";
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
+ import { t as loadResourcesFromEntry } from "../../loadResourcesFromEntry-MP8xEppu.mjs";
3
3
  //#region src/cli/commands/introspect.ts
4
4
  function describePermission(value) {
5
5
  if (!value) return "none";
@@ -1,8 +1,8 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
2
  import { describe } from "./commands/describe.mjs";
3
3
  import { exportDocs } from "./commands/docs.mjs";
4
4
  import { doctor } from "./commands/doctor.mjs";
5
- import { t as generate } from "../generate-BLRf2m3y.mjs";
6
- import { t as init } from "../init-CpLkjU18.mjs";
5
+ import { t as generate } from "../generate-BXKo2Gc8.mjs";
6
+ import { t as init } from "../init-BPzK5Lnr.mjs";
7
7
  import { introspect } from "./commands/introspect.mjs";
8
8
  export { describe, doctor, exportDocs, generate, init, introspect };
@@ -1,4 +1,4 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
2
  //#region src/constants.ts
3
3
  /**
4
4
  * Arc Framework Constants — Single Source of Truth
@@ -50,6 +50,8 @@ const DEFAULT_ID_FIELD = "_id";
50
50
  const DEFAULT_TENANT_FIELD = "organizationId";
51
51
  /** Default HTTP method for update routes */
52
52
  const DEFAULT_UPDATE_METHOD = "PATCH";
53
+ /** Default version field under `concurrency: {}` (optimistic concurrency) */
54
+ const DEFAULT_VERSION_FIELD = "__v";
53
55
  /** System-managed fields that cannot be set via request body */
54
56
  const SYSTEM_FIELDS = Object.freeze([
55
57
  "_id",
@@ -88,4 +90,4 @@ const RESERVED_QUERY_PARAMS = Object.freeze(/* @__PURE__ */ new Set([
88
90
  "_policyFilters"
89
91
  ]));
90
92
  //#endregion
91
- export { DEFAULT_SORT as a, HOOK_OPERATIONS as c, MAX_REGEX_LENGTH as d, MAX_SEARCH_LENGTH as f, SYSTEM_FIELDS as h, DEFAULT_MAX_LIMIT as i, HOOK_PHASES as l, RESERVED_QUERY_PARAMS as m, DEFAULT_ID_FIELD as n, DEFAULT_TENANT_FIELD as o, MUTATION_OPERATIONS as p, DEFAULT_LIMIT as r, DEFAULT_UPDATE_METHOD as s, CRUD_OPERATIONS as t, MAX_FILTER_DEPTH as u };
93
+ export { DEFAULT_SORT as a, DEFAULT_VERSION_FIELD as c, MAX_FILTER_DEPTH as d, MAX_REGEX_LENGTH as f, SYSTEM_FIELDS as g, RESERVED_QUERY_PARAMS as h, DEFAULT_MAX_LIMIT as i, HOOK_OPERATIONS as l, MUTATION_OPERATIONS as m, DEFAULT_ID_FIELD as n, DEFAULT_TENANT_FIELD as o, MAX_SEARCH_LENGTH as p, DEFAULT_LIMIT as r, DEFAULT_UPDATE_METHOD as s, CRUD_OPERATIONS as t, HOOK_PHASES as u };
@@ -52,7 +52,7 @@ interface RequestStore {
52
52
  * - `run(store, fn)` — run a function with a specific store (used by Arc internals)
53
53
  * - `getStore()` — alias for get() (matches Node.js API naming)
54
54
  */
55
- declare const requestContext: {
55
+ export declare const requestContext: {
56
56
  /**
57
57
  * Get the current request context.
58
58
  * Returns undefined if called outside a request lifecycle.
@@ -90,22 +90,19 @@ declare const requestContext: {
90
90
  * await outbox.store(event, { headers: traceHeaders });
91
91
  * ```
92
92
  */
93
- declare function getTraceHeaders(): Record<string, string> | undefined;
93
+ export declare function getTraceHeaders(): Record<string, string> | undefined;
94
94
  //#endregion
95
95
  //#region src/context/requestScopedCache.d.ts
96
96
  /**
97
- * The cache for the CURRENT unit of work — a request, an event dispatch or a
98
- * job run (see `runWorkScope`) — or `undefined` outside one.
99
- *
100
- * Lazily created on first use, so a scope that never touches a cached
101
- * repository allocates nothing.
97
+ * The cache for the CURRENT unit of work (see `runWorkScope`), or `undefined`
98
+ * outside one. Lazily created on first use.
102
99
  */
103
- declare function requestScopedCache(): CacheAdapter | undefined;
100
+ export declare function requestScopedCache(): CacheAdapter | undefined;
104
101
  /**
105
102
  * Whether the current scope has allocated a cache yet. Diagnostics and
106
103
  * tests only — never branch application behaviour on this.
107
104
  */
108
- declare function hasRequestScopedCache(): boolean;
105
+ export declare function hasRequestScopedCache(): boolean;
109
106
  //#endregion
110
107
  //#region src/context/transactionContext.d.ts
111
108
  /** DB session/transaction handle. Typed as unknown — arc is DB-agnostic. */
@@ -116,7 +113,7 @@ type DbSession = unknown;
116
113
  * - `run(session, fn)` — install an active DB session for the duration of `fn`
117
114
  * - `get()` — read the current session (undefined if outside a transaction scope)
118
115
  */
119
- declare const transactionContext: {
116
+ export declare const transactionContext: {
120
117
  /**
121
118
  * Run `fn` with `session` as the active DB transaction context.
122
119
  * Any call to `get()` within `fn`'s async call stack returns `session`.
@@ -139,17 +136,17 @@ interface WorkSeed {
139
136
  readonly organizationId?: string;
140
137
  }
141
138
  /** Enter a scope for `fn`, or run it inside the active one. */
142
- declare function runWorkScope<T>(seed: WorkSeed, fn: () => T): T;
139
+ export declare function runWorkScope<T>(seed: WorkSeed, fn: () => T): T;
143
140
  /**
144
141
  * A per-scope memo slot: created once on first use, the same instance after.
145
142
  * `undefined` outside a scope.
146
143
  */
147
- declare function scopedValue<T>(slot: symbol, create: () => T): T | undefined;
144
+ export declare function scopedValue<T>(slot: symbol, create: () => T): T | undefined;
148
145
  /**
149
146
  * The scope an event dispatch runs in. The correlation id is the scope id so a
150
147
  * child event published from a handler chains to the same correlation; the
151
148
  * tenant rides `meta`, never the payload.
152
149
  */
153
- declare function workSeedFromEvent(event: DomainEvent): WorkSeed;
150
+ export declare function workSeedFromEvent(event: DomainEvent): WorkSeed;
154
151
  //#endregion
155
- export { type DbSession, type RequestStore, type WorkKind, type WorkSeed, getTraceHeaders, hasRequestScopedCache, requestContext, requestScopedCache, runWorkScope, scopedValue, transactionContext, workSeedFromEvent };
152
+ export type { DbSession, RequestStore, WorkKind, WorkSeed };
@@ -1,34 +1,23 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
2
- import { t as transactionContext } from "../transactionContext-CPbdlnVw.mjs";
3
- import { n as requestContext, t as getTraceHeaders } from "../requestContext-cDkAUr-P.mjs";
4
- import { n as scopedValue, r as workSeedFromEvent, t as runWorkScope } from "../workScope-CxKqoIFn.mjs";
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
+ import { t as transactionContext } from "../transactionContext-orvnGu4F.mjs";
3
+ import { n as requestContext, t as getTraceHeaders } from "../requestContext-C10UeFe5.mjs";
4
+ import { n as evictToSize, r as touch } from "../boundedMap-DWiKW7lP.mjs";
5
+ import { n as scopedValue, r as workSeedFromEvent, t as runWorkScope } from "../workScope-n9a7d_lZ.mjs";
5
6
  //#region src/context/requestScopedCache.ts
6
7
  /** The memo slot the per-scope store hangs off. */
7
8
  const SLOT = Symbol.for("arc.requestScopedCache");
8
- /**
9
- * Entry cap for one scope's cache. A request touching this many distinct keys
10
- * is already pathological; a JOB RUN reaching it is ordinary, and that is the
11
- * case this exists for (see the eviction note below).
12
- */
9
+ /** Entry cap for one scope's cache — sized for long job runs, not requests. */
13
10
  const MAX_ENTRIES = 1e4;
14
11
  /**
15
12
  * A `Map`-backed `CacheAdapter` with NO TTL and LRU eviction above
16
13
  * {@link MAX_ENTRIES}.
17
14
  *
18
- * TTL is accepted and ignored because repo-core stamps freshness INTO the
19
- * envelope and re-checks on read — honouring it here too would put two clocks
20
- * on one question.
15
+ * TTL is ignored: repo-core stamps freshness INTO the envelope and re-checks
16
+ * on read, so honouring it here would put two clocks on one question.
21
17
  *
22
- * Eviction is newer than the rest of this file and the reason is worth
23
- * keeping. Unbounded was correct while a scope meant an HTTP REQUEST: the
24
- * store is unreachable once that async context ends, so it was garbage in
25
- * milliseconds and bounded by what one request touched, and an LRU would have
26
- * guarded a lifetime that could not occur. 2.40 extended scopes to job runs
27
- * and event dispatches — and `schedulesPlugin` wraps the WHOLE handler in one
28
- * scope, so a nightly job sweeping a million rows holds a single cache for the
29
- * duration. That is now a lifetime that occurs, and the old premise no longer
30
- * holds. Evicting is always safe here: this is a cache, so the worst a miss
31
- * costs is the re-read it was avoiding.
18
+ * The cap matters because `schedulesPlugin` wraps a WHOLE job handler in one
19
+ * scope, so a long sweep holds a single cache throughout. Evicting is always
20
+ * safe — a miss costs only the re-read it was avoiding.
32
21
  */
33
22
  function createRequestCacheAdapter() {
34
23
  const map = /* @__PURE__ */ new Map();
@@ -36,25 +25,19 @@ function createRequestCacheAdapter() {
36
25
  async get(key) {
37
26
  if (!map.has(key)) return void 0;
38
27
  const value = map.get(key);
39
- map.delete(key);
40
- map.set(key, value);
28
+ touch(map, key, value);
41
29
  return value;
42
30
  },
43
31
  async set(key, value, _ttlSeconds) {
44
- map.delete(key);
45
- map.set(key, value);
46
- if (map.size > MAX_ENTRIES) {
47
- const oldest = map.keys().next();
48
- if (!oldest.done) map.delete(oldest.value);
49
- }
32
+ touch(map, key, value);
33
+ evictToSize(map, MAX_ENTRIES);
50
34
  },
51
35
  async delete(key) {
52
36
  map.delete(key);
53
37
  },
54
38
  /**
55
- * Ignores the pattern and wipes the whole store. Over-invalidating within
56
- * one request costs at most a re-read; pattern matching is complexity a
57
- * store that dies in milliseconds does not earn.
39
+ * Ignores the pattern and wipes the whole store — over-invalidating a
40
+ * short-lived store costs at most a re-read.
58
41
  */
59
42
  async clear(_pattern) {
60
43
  map.clear();
@@ -62,11 +45,8 @@ function createRequestCacheAdapter() {
62
45
  };
63
46
  }
64
47
  /**
65
- * The cache for the CURRENT unit of work — a request, an event dispatch or a
66
- * job run (see `runWorkScope`) — or `undefined` outside one.
67
- *
68
- * Lazily created on first use, so a scope that never touches a cached
69
- * repository allocates nothing.
48
+ * The cache for the CURRENT unit of work (see `runWorkScope`), or `undefined`
49
+ * outside one. Lazily created on first use.
70
50
  */
71
51
  function requestScopedCache() {
72
52
  return scopedValue(SLOT, createRequestCacheAdapter);
@@ -1,4 +1,4 @@
1
1
 
2
- import { $t as AccessControlConfig, B as defineResource, Bt as BaseController, Cn as ControllerConstructionOptions, En as BodySanitizerConfig, Gt as SlugExt, Ht as SoftDeleteMixin, Jt as BulkMixin, Kt as SlugMixin, Qt as AccessControl, Sn as ControllerConfigurableOptions, Tn as BodySanitizer, Ut as TreeExt, V as ResourceDefinition, Vt as SoftDeleteExt, Wt as TreeMixin, Xt as QueryResolver, Yt as BaseCrudController, Zt as QueryResolverConfig, ct as AggMeasureShorthand, dt as AggregationDateRangeRequirement, ft as AggregationIndexHint, gt as AggregationsMap, ht as AggregationRateLimit, lt as AggregationCacheConfig, mt as AggregationMaterializedResult, pt as AggregationMaterializedContext, qt as BulkExt, st as AggMeasureInput, ut as AggregationConfig, wn as ListResult, xn as BaseControllerOptions } from "../index-DHbyPo5j.mjs";
3
- import { A as CRUD_OPERATIONS, B as HookOperation, C as SeamedResourceConfig, D as createCrudRouter, E as defineAction, F as DEFAULT_SORT, G as MUTATION_OPERATIONS, H as MAX_FILTER_DEPTH, I as DEFAULT_TENANT_FIELD, J as SYSTEM_FIELDS, K as MutationOperation, L as DEFAULT_UPDATE_METHOD, M as DEFAULT_ID_FIELD, N as DEFAULT_LIMIT, O as createPermissionMiddleware, P as DEFAULT_MAX_LIMIT, R as HOOK_OPERATIONS, S as ResourceSeams, T as DefineActionConfig, U as MAX_REGEX_LENGTH, V as HookPhase, W as MAX_SEARCH_LENGTH, _ as getEntityId, a as formatValidationErrors, b as defineResourceVariants, c as nativePolicyFilter, d as createCrudHandlers, f as createFastifyHandler, g as sendControllerResponse, h as getControllerScope, i as assertValidConfig, j as CrudOperation, k as defineAggregation, l as collectReadBlockedFields, m as getControllerContext, n as ValidateOptions, o as validateResourceConfig, p as createRequestContext, q as RESERVED_QUERY_PARAMS, r as ValidationResult, s as NativePolicyFilter, t as ConfigError, u as isFieldReadable, v as getEntityIdField, w as mergeResourceConfig, x as AdapterLike, y as getEntityQuery, z as HOOK_PHASES } from "../index-D4u76eQW.mjs";
4
- export { AccessControl, type AccessControlConfig, type AdapterLike, type AggMeasureInput, type AggMeasureShorthand, type AggregationCacheConfig, type AggregationConfig, type AggregationDateRangeRequirement, type AggregationIndexHint, type AggregationMaterializedContext, type AggregationMaterializedResult, type AggregationRateLimit, type AggregationsMap, BaseController, type BaseControllerOptions, BaseCrudController, BodySanitizer, type BodySanitizerConfig, type BulkExt, BulkMixin, CRUD_OPERATIONS, type ConfigError, type ControllerConfigurableOptions, type ControllerConstructionOptions, CrudOperation, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, type DefineActionConfig, HOOK_OPERATIONS, HOOK_PHASES, HookOperation, HookPhase, type ListResult, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, MutationOperation, type NativePolicyFilter, QueryResolver, type QueryResolverConfig, RESERVED_QUERY_PARAMS, ResourceDefinition, type ResourceSeams, SYSTEM_FIELDS, type SeamedResourceConfig, type SlugExt, SlugMixin, type SoftDeleteExt, SoftDeleteMixin, type TreeExt, TreeMixin, type ValidateOptions, type ValidationResult, assertValidConfig, collectReadBlockedFields, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineAction, defineAggregation, defineResource, defineResourceVariants, formatValidationErrors, getControllerContext, getControllerScope, getEntityId, getEntityIdField, getEntityQuery, isFieldReadable, mergeResourceConfig, nativePolicyFilter, sendControllerResponse, validateResourceConfig };
2
+ import { $t as AccessControl, An as MixinConstructor, Bt as TreeMixin, Dn as ControllerConfigurableOptions, En as BaseControllerOptions, F as ResourceDefinition, Gt as BaseCrudController, Ht as SlugMixin, It as BaseController, Jt as ActionTargetCheck, Kt as QueryResolver, Lt as SoftDeleteExt, Mn as BodySanitizerConfig, On as ControllerConstructionOptions, P as defineResource, Qt as getEntityQuery, Rt as SoftDeleteMixin, Ut as BulkExt, Vt as SlugExt, Wt as BulkMixin, Xt as getEntityId, Yt as getActionTarget, Zt as getEntityIdField, at as AggregationCacheConfig, ct as AggregationIndexHint, dt as AggregationRateLimit, en as AccessControlConfig, ft as AggregationsMap, it as AggMeasureShorthand, jn as BodySanitizer, kn as ListResult, lt as AggregationMaterializedContext, nn as FetchDenialReason, ot as AggregationConfig, qt as QueryResolverConfig, rn as FetchResult, rt as AggMeasureInput, st as AggregationDateRangeRequirement, tn as AccessControlRepository, ut as AggregationMaterializedResult, zt as TreeExt } from "../index-WH7xgvxS.mjs";
3
+ import { A as CrudOperation, B as HookOperation, C as mergeResourceConfig, D as createPermissionMiddleware, E as createCrudRouter, F as DEFAULT_TENANT_FIELD, G as MUTATION_OPERATIONS, H as MAX_FILTER_DEPTH, I as DEFAULT_UPDATE_METHOD, J as SYSTEM_FIELDS, K as MutationOperation, L as DEFAULT_VERSION_FIELD, M as DEFAULT_LIMIT, N as DEFAULT_MAX_LIMIT, O as defineAggregation, P as DEFAULT_SORT, R as HOOK_OPERATIONS, S as SeamedResourceConfig, T as defineAction, U as MAX_REGEX_LENGTH, V as HookPhase, W as MAX_SEARCH_LENGTH, _ as VariantsMap, a as formatValidationErrors, b as AdapterLike, c as nativePolicyFilter, d as createFastifyHandler, f as createRequestContext, g as VariantOverride, h as sendControllerResponse, i as assertValidConfig, j as DEFAULT_ID_FIELD, k as CRUD_OPERATIONS, l as collectReadBlockedFields, m as getControllerScope, n as ValidateOptions, o as validateResourceConfig, p as getControllerContext, q as RESERVED_QUERY_PARAMS, r as ValidationResult, s as NativePolicyFilter, t as ConfigError, u as isFieldReadable, v as VariantsResult, w as DefineActionConfig, x as ResourceSeams, y as defineResourceVariants, z as HOOK_PHASES } from "../index-Beg3aNnK.mjs";
4
+ export { AccessControl, type AccessControlConfig, type AccessControlRepository, type ActionTargetCheck, type AdapterLike, type AggMeasureInput, type AggMeasureShorthand, type AggregationCacheConfig, type AggregationConfig, type AggregationDateRangeRequirement, type AggregationIndexHint, type AggregationMaterializedContext, type AggregationMaterializedResult, type AggregationRateLimit, type AggregationsMap, BaseController, type BaseControllerOptions, BaseCrudController, BodySanitizer, type BodySanitizerConfig, type BulkExt, BulkMixin, CRUD_OPERATIONS, type ConfigError, type ControllerConfigurableOptions, type ControllerConstructionOptions, CrudOperation, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, DEFAULT_VERSION_FIELD, type DefineActionConfig, type FetchDenialReason, type FetchResult, HOOK_OPERATIONS, HOOK_PHASES, HookOperation, HookPhase, type ListResult, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, type MixinConstructor, MutationOperation, type NativePolicyFilter, QueryResolver, type QueryResolverConfig, RESERVED_QUERY_PARAMS, ResourceDefinition, type ResourceSeams, SYSTEM_FIELDS, type SeamedResourceConfig, type SlugExt, SlugMixin, type SoftDeleteExt, SoftDeleteMixin, type TreeExt, TreeMixin, type ValidateOptions, type ValidationResult, type VariantOverride, type VariantsMap, type VariantsResult, assertValidConfig, collectReadBlockedFields, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineAction, defineAggregation, defineResource, defineResourceVariants, formatValidationErrors, getActionTarget, getControllerContext, getControllerScope, getEntityId, getEntityIdField, getEntityQuery, isFieldReadable, mergeResourceConfig, nativePolicyFilter, sendControllerResponse, validateResourceConfig };
@@ -1,8 +1,8 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
2
- import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "../constants-D5Ubn1fe.mjs";
3
- import { a as BulkMixin, c as collectReadBlockedFields, f as BodySanitizer, h as nativePolicyFilter, i as SlugMixin, l as isFieldReadable, m as AccessControl, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, s as QueryResolver, t as BaseController } from "../BaseController-CYEwjyjN.mjs";
4
- import { t as defineAggregation } from "../defineAggregation-D_eJjm5A.mjs";
5
- import { a as createCrudHandlers, c as getControllerContext, l as getControllerScope, o as createFastifyHandler, s as createRequestContext, u as sendControllerResponse } from "../actionPermissions-BoPGQ5-4.mjs";
6
- import { a as ResourceDefinition, i as validateResourceConfig, n as assertValidConfig, o as createCrudRouter, r as formatValidationErrors, s as createPermissionMiddleware, t as defineResource } from "../defineResource-DxkMTjRn.mjs";
7
- import { a as mergeResourceConfig, i as defineResourceVariants, n as getEntityIdField, o as defineAction, r as getEntityQuery, t as getEntityId } from "../core-5lazhva9.mjs";
8
- export { AccessControl, BaseController, BaseCrudController, BodySanitizer, BulkMixin, CRUD_OPERATIONS, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, HOOK_OPERATIONS, HOOK_PHASES, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, QueryResolver, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugMixin, SoftDeleteMixin, TreeMixin, assertValidConfig, collectReadBlockedFields, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineAction, defineAggregation, defineResource, defineResourceVariants, formatValidationErrors, getControllerContext, getControllerScope, getEntityId, getEntityIdField, getEntityQuery, isFieldReadable, mergeResourceConfig, nativePolicyFilter, sendControllerResponse, validateResourceConfig };
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
+ import { a as DEFAULT_SORT, c as DEFAULT_VERSION_FIELD, d as MAX_FILTER_DEPTH, f as MAX_REGEX_LENGTH, g as SYSTEM_FIELDS, h as RESERVED_QUERY_PARAMS, i as DEFAULT_MAX_LIMIT, l as HOOK_OPERATIONS, m as MUTATION_OPERATIONS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MAX_SEARCH_LENGTH, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as HOOK_PHASES } from "../constants-B2QHb6u6.mjs";
3
+ import { S as nativePolicyFilter, b as BodySanitizer, c as BaseController, d as SlugMixin, f as BulkMixin, g as isFieldReadable, h as collectReadBlockedFields, l as TreeMixin, m as QueryResolver, o as createCrudRouter, p as BaseCrudController, s as createPermissionMiddleware, u as SoftDeleteMixin, x as AccessControl } from "../plugin-DALd9dcF.mjs";
4
+ import { t as defineAggregation } from "../defineAggregation--3xguLkk.mjs";
5
+ import { C as sendControllerResponse, S as getControllerScope, b as createRequestContext, x as getControllerContext, y as createFastifyHandler } from "../actionPermissions-5N04zBL4.mjs";
6
+ import { a as defineResourceVariants, i as getEntityQuery, n as getEntityId, o as mergeResourceConfig, r as getEntityIdField, s as defineAction, t as getActionTarget } from "../core-COcqo0Cp.mjs";
7
+ import { a as ResourceDefinition, i as validateResourceConfig, n as assertValidConfig, r as formatValidationErrors, t as defineResource } from "../defineResource-gUp9ug66.mjs";
8
+ export { AccessControl, BaseController, BaseCrudController, BodySanitizer, BulkMixin, CRUD_OPERATIONS, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, DEFAULT_VERSION_FIELD, HOOK_OPERATIONS, HOOK_PHASES, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, QueryResolver, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugMixin, SoftDeleteMixin, TreeMixin, assertValidConfig, collectReadBlockedFields, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineAction, defineAggregation, defineResource, defineResourceVariants, formatValidationErrors, getActionTarget, getControllerContext, getControllerScope, getEntityId, getEntityIdField, getEntityQuery, isFieldReadable, mergeResourceConfig, nativePolicyFilter, sendControllerResponse, validateResourceConfig };
@@ -1,6 +1,6 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
2
- import "./constants-D5Ubn1fe.mjs";
3
- import { t as defineResource } from "./defineResource-DxkMTjRn.mjs";
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
+ import "./constants-B2QHb6u6.mjs";
3
+ import { t as defineResource } from "./defineResource-gUp9ug66.mjs";
4
4
  //#region src/core/defineAction.ts
5
5
  /**
6
6
  * Build an `ActionDefinition` with a typed handler. The literal schema
@@ -19,7 +19,8 @@ function defineAction(config) {
19
19
  schema: config.schema,
20
20
  description: config.description,
21
21
  id: config.id,
22
- mcp: config.mcp
22
+ mcp: config.mcp,
23
+ ...config.idempotency ? { idempotency: config.idempotency } : {}
23
24
  };
24
25
  }
25
26
  //#endregion
@@ -172,5 +173,14 @@ function getEntityQuery(req) {
172
173
  if (id === void 0) return {};
173
174
  return { [getEntityIdField(req)]: id };
174
175
  }
176
+ /**
177
+ * The row the action-target fence loaded for this request, so the handler need not read it
178
+ * again. `undefined` when no fence read happened (untenanted resource, `scope: 'handler'`,
179
+ * id-less action) — load it yourself then. It is a snapshot taken after the idempotency lock
180
+ * and before the handler: a guarded write must still carry its precondition in the filter.
181
+ */
182
+ function getActionTarget(req) {
183
+ return req.arc?.actionTarget;
184
+ }
175
185
  //#endregion
176
- export { mergeResourceConfig as a, defineResourceVariants as i, getEntityIdField as n, defineAction as o, getEntityQuery as r, getEntityId as t };
186
+ export { defineResourceVariants as a, getEntityQuery as i, getEntityId as n, mergeResourceConfig as o, getEntityIdField as r, defineAction as s, getActionTarget as t };
@@ -1,16 +1,34 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
2
- import { t as __exportAll } from "./rolldown-runtime-eysyzFAF.mjs";
3
- import "./constants-D5Ubn1fe.mjs";
4
- import { f as createError } from "./errors-BH7YU_9O.mjs";
5
- import { i as resolvePipelineSteps, n as buildActionPipelineHandler, u as sendControllerResponse } from "./actionPermissions-BoPGQ5-4.mjs";
6
- import { a as selectPluginMw, c as buildRouteHooks, f as buildAuthMiddlewareForPermissions, i as resolveRouterPluginMw, n as buildRateLimitConfig, o as buildActionPermissionMw, p as buildArcDecorator, r as buildRouteConfig, t as tryRegisterRoute, u as routeHookOptions } from "./registerRoute-Bsnk6NiZ.mjs";
7
- import { n as schemaIRToJsonSchemaBranch, t as normalizeSchemaIR } from "./schemaIR-CTvPDoPB.mjs";
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
+ import { r as __exportAll } from "./rolldown-runtime-MYrLNGnq.mjs";
3
+ import "./constants-B2QHb6u6.mjs";
4
+ import { f as createError, i as NotFoundError, u as ValidationError } from "./errors-CW4anJBy.mjs";
5
+ import { C as sendControllerResponse, _ as buildArcDecorator, a as resolveRouterPluginMw, f as buildRouteHooks, g as buildAuthMiddlewareForPermissions, i as buildRouteConfig, l as resolvePipelineSteps, m as routeHookOptions, n as tryRegisterRoute, o as selectPluginMw, r as buildRateLimitConfig, s as buildActionPipelineHandler, u as buildActionPermissionMw } from "./actionPermissions-5N04zBL4.mjs";
6
+ import { n as schemaIRToJsonSchemaBranch, t as normalizeSchemaIR } from "./schemaIR-BA0Hb21Y.mjs";
8
7
  //#region src/core/createActionRouter.ts
9
8
  var createActionRouter_exports = /* @__PURE__ */ __exportAll({
10
9
  buildActionBodySchema: () => buildActionBodySchema,
11
10
  createActionRouter: () => createActionRouter
12
11
  });
13
12
  /**
13
+ * Record a successful action. The actor and organization come from the request's
14
+ * validated scope (`auditContext`); a failed write is logged, never turned into a 500
15
+ * after the action has already happened.
16
+ */
17
+ async function auditAction(req, resource, id, action) {
18
+ const audit = req.server.audit;
19
+ if (!audit?.custom || audit._noop === true) return;
20
+ try {
21
+ await audit.custom(resource, id, action, { ...req.auditMetadata ?? {} }, req.auditContext);
22
+ } catch (err) {
23
+ req.log.error({
24
+ err,
25
+ resource,
26
+ id,
27
+ action
28
+ }, "[arc] action audit write failed");
29
+ }
30
+ }
31
+ /**
14
32
  * Register the unified action endpoint: `POST /:id/action`.
15
33
  *
16
34
  * Shares every lifecycle primitive with the CRUD router — the preHandler
@@ -19,7 +37,8 @@ var createActionRouter_exports = /* @__PURE__ */ __exportAll({
19
37
  * (keyed by `body.action` at request time).
20
38
  */
21
39
  function createActionRouter(fastify, config) {
22
- const { tag, resourceName = tag ?? "action", actions, actionPermissions = {}, actionSchemas = {}, globalAuth, onError, fields: fieldPermissions, schemaOptions, idField = "_id", permissions: resourcePermissions, routeGuards = [], pipeline, rateLimit, idLessActionNames = [], extensions } = config;
40
+ const { tag, resourceName = tag ?? "action", actions, actionPermissions = {}, actionSchemas = {}, globalAuth, onError, fields: fieldPermissions, schemaOptions, idField = "_id", permissions: resourcePermissions, routeGuards = [], tenantMiddlewares = [], pipeline, rateLimit, idLessActionNames = [], extensions, isTargetVisible, loadTarget, handlerScopedActionNames = [], idempotentActionNames = [], handlerDedupOwners = {}, auditActions = false } = config;
41
+ const handlerScoped = new Set(handlerScopedActionNames);
23
42
  const allActionNames = Object.keys(actions);
24
43
  if (allActionNames.length === 0) {
25
44
  fastify.log.warn("[createActionRouter] No actions defined, skipping route creation");
@@ -82,23 +101,26 @@ function createActionRouter(fastify, config) {
82
101
  } },
83
102
  required: ["id"]
84
103
  };
104
+ const actionDispatchCheck = async (req, _reply) => {
105
+ if (!req.validationError) return;
106
+ const body = req.body;
107
+ const submitted = typeof body?.action === "string" ? body.action : void 0;
108
+ if (submitted && subsetSet.has(submitted)) return;
109
+ const wrongMount = submitted && allActionNames.includes(submitted) ? submitted : void 0;
110
+ const otherMount = hasId ? "/action" : "/:id/action";
111
+ const message = wrongMount ? `Action '${wrongMount}' on '${resourceName}' is mounted at 'POST ${otherMount}', not 'POST ${urlPath}'` : submitted ? `Unknown action '${submitted}' on '${resourceName}'. Valid at 'POST ${urlPath}': ${actionSubset.join(", ")}` : `Missing 'action' field on '${resourceName}'. Valid at 'POST ${urlPath}': ${actionSubset.join(", ")}`;
112
+ throw createError(400, message, {
113
+ code: "arc.invalid_action",
114
+ validActions: actionSubset,
115
+ mount: urlPath,
116
+ ...submitted ? { submitted } : {},
117
+ ...wrongMount ? { mountedAt: otherMount } : {}
118
+ });
119
+ };
85
120
  const actionValidationFormatter = async (req, _reply) => {
86
121
  const validationError = req.validationError;
87
122
  if (!validationError) return;
88
- const body = req.body;
89
- const submitted = typeof body?.action === "string" ? body.action : void 0;
90
- if (!submitted || !subsetSet.has(submitted)) {
91
- const wrongMount = submitted && allActionNames.includes(submitted) ? submitted : void 0;
92
- const otherMount = hasId ? "/action" : "/:id/action";
93
- const message = wrongMount ? `Action '${wrongMount}' on '${resourceName}' is mounted at 'POST ${otherMount}', not 'POST ${urlPath}'` : submitted ? `Unknown action '${submitted}' on '${resourceName}'. Valid at 'POST ${urlPath}': ${actionSubset.join(", ")}` : `Missing 'action' field on '${resourceName}'. Valid at 'POST ${urlPath}': ${actionSubset.join(", ")}`;
94
- throw createError(400, message, {
95
- code: "arc.invalid_action",
96
- validActions: actionSubset,
97
- mount: urlPath,
98
- ...submitted ? { submitted } : {},
99
- ...wrongMount ? { mountedAt: otherMount } : {}
100
- });
101
- }
123
+ const submitted = req.body.action;
102
124
  const branchPath = `/oneOf/${actionSubset.indexOf(submitted)}/`;
103
125
  const ajvErrors = validationError.validation ?? [];
104
126
  const scoped = ajvErrors.filter((e) => e.keyword !== "oneOf" && (e.schemaPath?.includes(branchPath) || !e.schemaPath?.includes("/oneOf/")));
@@ -111,24 +133,30 @@ function createActionRouter(fastify, config) {
111
133
  scopedError.meta = { action: submitted };
112
134
  throw scopedError;
113
135
  };
136
+ const requiredActions = actionSubset.filter((name) => idempotentActionNames.includes(name));
137
+ const handlerDedup = Object.fromEntries(requiredActions.flatMap((name) => {
138
+ const owner = handlerDedupOwners[name];
139
+ return owner === void 0 ? [] : [[name, owner]];
140
+ }));
114
141
  const hooks = buildRouteHooks({
115
142
  arcDecorator,
116
143
  authMw,
144
+ prePermission: actionDispatchCheck,
117
145
  permissionMw,
146
+ validationFormatter: actionValidationFormatter,
118
147
  pluginMw: selectPluginMw("POST", pluginMw),
119
- routeGuards
148
+ routeGuards,
149
+ customMws: tenantMiddlewares
120
150
  });
121
- const preHandler = [actionValidationFormatter, ...hooks.preHandler];
122
151
  tryRegisterRoute(fastify, {
123
152
  method: "POST",
124
153
  url: urlPath,
125
154
  schema: routeSchema,
126
- attachValidation: true,
127
- ...routeHookOptions({
128
- onRequest: hooks.onRequest,
129
- preHandler
130
- }),
131
- ...buildRouteConfig(rateLimitConfig, extensions),
155
+ ...routeHookOptions(hooks),
156
+ ...buildRouteConfig(rateLimitConfig, extensions, void 0, requiredActions.length > 0 ? {
157
+ requiredActions,
158
+ ...Object.keys(handlerDedup).length > 0 ? { handlerDedup } : {}
159
+ } : void 0),
132
160
  handler: async (req, reply) => {
133
161
  const { action, ...data } = req.body;
134
162
  const id = hasId ? req.params.id : "";
@@ -141,8 +169,20 @@ function createActionRouter(fastify, config) {
141
169
  }
142
170
  const handler = wrappedHandlers.get(action);
143
171
  if (!handler) throw createError(400, `Invalid action '${action}'. Valid actions: ${actionSubset.join(", ")}`, { validActions: actionSubset });
172
+ if (hasId && (loadTarget || isTargetVisible) && !handlerScoped.has(action)) {
173
+ const target = loadTarget ? await loadTarget(id, req) : { visible: await isTargetVisible(id, req) };
174
+ if (!target.visible) throw new NotFoundError(resourceName);
175
+ if (target.doc !== void 0) {
176
+ const reqWithExtras = req;
177
+ reqWithExtras.arc = {
178
+ ...reqWithExtras.arc ?? {},
179
+ actionTarget: target.doc
180
+ };
181
+ }
182
+ }
144
183
  try {
145
184
  const response = await handler(id, data, req);
185
+ if (auditActions && (response.status ?? 200) < 400) await auditAction(req, resourceName, id, action);
146
186
  sendControllerResponse(reply, response, req);
147
187
  return reply;
148
188
  } catch (error) {
@@ -150,6 +190,8 @@ function createActionRouter(fastify, config) {
150
190
  const { statusCode, error: errorMsg, code } = onError(error, action, id);
151
191
  throw createError(statusCode, errorMsg, code ? { code } : void 0);
152
192
  }
193
+ const validation = zodIssues(error);
194
+ if (validation) throw new ValidationError(`Invalid '${action}' payload`, validation);
153
195
  const err = error;
154
196
  const statusCode = err.statusCode || err.status || 500;
155
197
  const errorCode = err.code || "ACTION_FAILED";
@@ -190,7 +232,7 @@ function createActionRouter(fastify, config) {
190
232
  * `action: { const }` and carrying its own `required`.
191
233
  *
192
234
  * EVERY BRANCH LISTS THE FULL PROPERTY UNION — the non-obvious part. AJV's
193
- * `removeAdditional: 'all'` (Fastify's default) strips a field during a
235
+ * `removeAdditional` (Fastify's default strips) strips a field during a
194
236
  * branch's evaluation when that branch's `properties` omits it, EVEN IF
195
237
  * another branch would have allowed it. The strip mutates the body before
196
238
  * `oneOf` finishes discriminating, so the winning branch receives a body that
@@ -199,11 +241,10 @@ function createActionRouter(fastify, config) {
199
241
  * every branch makes each walk see every field as its own, so nothing is
200
242
  * stripped; `required` stays per-action, so dispatch still gates correctly.
201
243
  *
202
- * Per-branch `additionalProperties: false` survives but cannot reject
203
- * sibling-action fields under host `removeAdditional: 'all'` — those strip at
204
- * top level instead. That is the host's opt-in; arc's job is only to stop
205
- * losing an action's OWN declared fields. Under arc's `createApp`
206
- * (`removeAdditional: false`) strict rejection works normally.
244
+ * Arc compiles this route with its own validator (`removeAdditional: false`, see
245
+ * `./routeValidator.ts`), whatever the host's AJV says — so per-branch
246
+ * `additionalProperties: false` rejects unknown fields on every host. The full
247
+ * property union stays because a host-supplied `validatorCompiler` may still strip.
207
248
  *
208
249
  * Pinned by `tests/core/action-discriminator-strip.test.ts` and
209
250
  * `action-strict-schema-parity.test.ts`. Exported so OpenAPI and MCP tool
@@ -211,6 +252,7 @@ function createActionRouter(fastify, config) {
211
252
  */
212
253
  function buildActionBodySchema(actionEnum, actionSchemas = {}) {
213
254
  const unionProperties = {};
255
+ const conflicting = /* @__PURE__ */ new Set();
214
256
  const irs = [];
215
257
  for (const actionName of actionEnum) {
216
258
  const ir = normalizeSchemaIR(actionSchemas[actionName]);
@@ -218,13 +260,19 @@ function buildActionBodySchema(actionEnum, actionSchemas = {}) {
218
260
  name: actionName,
219
261
  ir
220
262
  });
221
- for (const [key, val] of Object.entries(ir.properties)) unionProperties[key] = val;
263
+ for (const [key, val] of Object.entries(ir.properties)) {
264
+ const prior = unionProperties[key];
265
+ if (prior !== void 0 && JSON.stringify(prior) !== JSON.stringify(val)) conflicting.add(key);
266
+ unionProperties[key] = val;
267
+ }
222
268
  }
269
+ const topLevelProperties = { ...unionProperties };
270
+ for (const key of conflicting) topLevelProperties[key] = {};
223
271
  const branches = [];
224
272
  for (const { name, ir } of irs) branches.push(schemaIRToJsonSchemaBranch({
225
273
  ...ir,
226
274
  properties: {
227
- ...unionProperties,
275
+ ...topLevelProperties,
228
276
  ...ir.properties
229
277
  }
230
278
  }, {
@@ -242,7 +290,7 @@ function buildActionBodySchema(actionEnum, actionSchemas = {}) {
242
290
  type: "string",
243
291
  enum: [...actionEnum]
244
292
  },
245
- ...unionProperties
293
+ ...topLevelProperties
246
294
  },
247
295
  oneOf: branches
248
296
  };
@@ -261,5 +309,15 @@ function buildActionDescription(actions, actionPermissions) {
261
309
  }
262
310
  return lines.join("\n");
263
311
  }
312
+ /** A ZodError's issues as `{ field, message }`, or `undefined` for any other error. */
313
+ function zodIssues(error) {
314
+ if (!(error instanceof Error) || error.name !== "ZodError" || !("issues" in error)) return void 0;
315
+ const issues = error.issues;
316
+ if (!Array.isArray(issues)) return void 0;
317
+ return issues.map((issue) => ({
318
+ field: Array.isArray(issue.path) ? issue.path.map(String).join(".") || "(payload)" : "(payload)",
319
+ message: typeof issue.message === "string" ? issue.message : "invalid"
320
+ }));
321
+ }
264
322
  //#endregion
265
323
  export { createActionRouter_exports as n, buildActionBodySchema as t };
@@ -1,10 +1,10 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
2
- import { n as evaluateAndApplyPermission } from "./authorizationDecision-DawKGoXb.mjs";
3
- import { f as createError } from "./errors-BH7YU_9O.mjs";
4
- import { u as getRequestScope } from "./types-CgenB1gv.mjs";
5
- import { a as selectPluginMw, c as buildRouteHooks, d as buildAuthMiddleware, i as resolveRouterPluginMw, n as buildRateLimitConfig, p as buildArcDecorator, u as routeHookOptions } from "./registerRoute-Bsnk6NiZ.mjs";
6
- import { n as validateAggregations } from "./validate-DrYWnOzI.mjs";
7
- import { t as buildAggregationHandler } from "./buildHandler-CvxKOc0m.mjs";
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
+ import { f as createError } from "./errors-CW4anJBy.mjs";
3
+ import { u as getRequestScope } from "./types-fvO6Ovzx.mjs";
4
+ import { _ as buildArcDecorator, a as resolveRouterPluginMw, f as buildRouteHooks, h as buildAuthMiddleware, m as routeHookOptions, n as tryRegisterRoute, o as selectPluginMw, r as buildRateLimitConfig } from "./actionPermissions-5N04zBL4.mjs";
5
+ import { n as evaluateAndApplyPermission } from "./authorizationDecision-wX3SA9w_.mjs";
6
+ import { n as validateAggregations } from "./validate-CWp-lsrm.mjs";
7
+ import { t as buildAggregationHandler } from "./buildHandler-Bswu_vNb.mjs";
8
8
  //#region src/core/aggregation/createAggregationRouter.ts
9
9
  /**
10
10
  * Register one Fastify route per aggregation. No-op when the map is
@@ -68,7 +68,7 @@ function registerOne(fastify, normalized, ctx) {
68
68
  summary: config.summary ?? `Aggregation: ${name}`,
69
69
  description: config.description ?? "Portable aggregation generated by arc. Filters from query string compose with the declaration's base filter + tenant scope."
70
70
  };
71
- fastify.route({
71
+ tryRegisterRoute(fastify, {
72
72
  method: "GET",
73
73
  url: `/aggregations/${name}`,
74
74
  schema: routeSchema,
@@ -86,6 +86,9 @@ function registerOne(fastify, normalized, ctx) {
86
86
  throw createError(500, `Aggregation "${name}" failed: ${message}`);
87
87
  }
88
88
  }
89
+ }, {
90
+ resourceName: tag ?? name,
91
+ op: `aggregation:${name}`
89
92
  });
90
93
  }
91
94
  /**