@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,5 +1,6 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
2
- import { t as __exportAll } from "./rolldown-runtime-eysyzFAF.mjs";
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
+ import { r as __exportAll } from "./rolldown-runtime-MYrLNGnq.mjs";
3
+ import { n as evictToSize } from "./boundedMap-DWiKW7lP.mjs";
3
4
  //#region src/cache/memory.ts
4
5
  var memory_exports = /* @__PURE__ */ __exportAll({ MemoryCacheStore: () => MemoryCacheStore });
5
6
  /**
@@ -24,13 +25,13 @@ var MemoryCacheStore = class {
24
25
  _misses = 0;
25
26
  _evictions = 0;
26
27
  constructor(options = {}) {
27
- this.defaultTtlSeconds = options.defaultTtlSeconds ?? 60;
28
- this.maxEntries = clamp(options.maxEntries ?? 1e3, 1, 1e5);
29
- this.maxEntryBytes = clamp(options.maxEntryBytes ?? 262144, 1024, 10485760);
30
- this.maxMemoryBytes = options.maxMemoryBytes ?? 52428800;
31
- this.evictionWatermark = clamp(options.evictionWatermark ?? .9, .5, 1);
28
+ this.defaultTtlSeconds = finite("defaultTtlSeconds", options.defaultTtlSeconds ?? 60);
29
+ this.maxEntries = clamp("maxEntries", options.maxEntries ?? 1e3, 1, 1e5);
30
+ this.maxEntryBytes = clamp("maxEntryBytes", options.maxEntryBytes ?? 262144, 1024, 10485760);
31
+ this.maxMemoryBytes = clamp("maxMemoryBytes", options.maxMemoryBytes ?? 52428800, 0, Number.MAX_SAFE_INTEGER);
32
+ this.evictionWatermark = clamp("evictionWatermark", options.evictionWatermark ?? .9, .5, 1);
32
33
  this.logger = options.logger ?? console;
33
- const cleanupIntervalMs = clamp(options.cleanupIntervalMs ?? 3e4, 1e3, 6e5);
34
+ const cleanupIntervalMs = clamp("cleanupIntervalMs", options.cleanupIntervalMs ?? 3e4, 1e3, 6e5);
34
35
  this.cleanupTimer = setInterval(() => this.cleanupExpired(), cleanupIntervalMs);
35
36
  if (this.cleanupTimer.unref) this.cleanupTimer.unref();
36
37
  }
@@ -54,11 +55,12 @@ var MemoryCacheStore = class {
54
55
  const effectiveTtlSeconds = ttlSeconds ?? this.defaultTtlSeconds;
55
56
  if (!Number.isFinite(effectiveTtlSeconds) || effectiveTtlSeconds <= 0) return;
56
57
  const ttlMs = effectiveTtlSeconds * 1e3;
57
- const size = this.estimateSize(value);
58
- if (size > this.maxEntryBytes) {
59
- this.logger.warn(`[MemoryCacheStore] Skipping oversized entry for key '${key}' (${size} bytes > ${this.maxEntryBytes} bytes)`);
58
+ const valueBytes = this.estimateSize(value);
59
+ if (valueBytes > this.maxEntryBytes) {
60
+ this.logger.warn(`[MemoryCacheStore] Skipping oversized entry for key '${key}' (${valueBytes} bytes > ${this.maxEntryBytes} bytes)`);
60
61
  return;
61
62
  }
63
+ const size = valueBytes + keyBytes(key);
62
64
  const existing = this.cache.get(key);
63
65
  if (existing) {
64
66
  this.currentBytes -= existing.size;
@@ -70,8 +72,7 @@ var MemoryCacheStore = class {
70
72
  expiresAt: Date.now() + ttlMs
71
73
  });
72
74
  this.currentBytes += size;
73
- this.evictToLimit();
74
- if (this.maxMemoryBytes > 0) this.evictToMemoryLimit();
75
+ this.enforceLimits();
75
76
  }
76
77
  async delete(key) {
77
78
  const entry = this.cache.get(key);
@@ -96,14 +97,14 @@ var MemoryCacheStore = class {
96
97
  const effectiveTtlSeconds = ttlSeconds ?? this.defaultTtlSeconds;
97
98
  if (entry) this.currentBytes -= entry.size;
98
99
  this.cache.delete(key);
99
- const size = 8;
100
+ const size = 8 + keyBytes(key);
100
101
  this.cache.set(key, {
101
102
  value: next,
102
103
  size,
103
104
  expiresAt: live ? entry.expiresAt : now + Math.max(1, effectiveTtlSeconds) * 1e3
104
105
  });
105
106
  this.currentBytes += size;
106
- this.evictToLimit();
107
+ this.enforceLimits();
107
108
  return next;
108
109
  }
109
110
  async clear(pattern) {
@@ -133,26 +134,19 @@ var MemoryCacheStore = class {
133
134
  this.cache.delete(key);
134
135
  this.currentBytes -= entry.size;
135
136
  }
136
- evictToLimit() {
137
- while (this.cache.size > this.maxEntries) {
138
- const oldestKey = this.cache.keys().next().value;
139
- if (!oldestKey) break;
140
- const entry = this.cache.get(oldestKey);
141
- if (!entry) break;
142
- this.removeEntry(oldestKey, entry);
143
- this._evictions++;
144
- }
145
- }
146
- evictToMemoryLimit() {
137
+ /** Every write path ends here, so no path can skip a limit. */
138
+ enforceLimits() {
139
+ this._evictions += evictToSize(this.cache, this.maxEntries, (_key, entry) => {
140
+ this.currentBytes -= entry.size;
141
+ });
142
+ if (this.maxMemoryBytes <= 0 || this.currentBytes <= this.maxMemoryBytes) return;
147
143
  const target = this.maxMemoryBytes * this.evictionWatermark;
148
- while (this.currentBytes > this.maxMemoryBytes && this.cache.size > 0) {
149
- const oldestKey = this.cache.keys().next().value;
150
- if (!oldestKey) break;
151
- const entry = this.cache.get(oldestKey);
152
- if (!entry) break;
144
+ while (this.currentBytes > target) {
145
+ const oldest = this.cache.entries().next();
146
+ if (oldest.done) break;
147
+ const [oldestKey, entry] = oldest.value;
153
148
  this.removeEntry(oldestKey, entry);
154
149
  this._evictions++;
155
- if (this.currentBytes <= target) break;
156
150
  }
157
151
  }
158
152
  cleanupExpired() {
@@ -169,8 +163,16 @@ var MemoryCacheStore = class {
169
163
  }
170
164
  }
171
165
  };
172
- function clamp(value, min, max) {
173
- return Math.min(max, Math.max(min, value));
166
+ /** A non-finite option is a configuration bug — `Math.max(min, NaN)` is NaN, which silently disabled the cap. */
167
+ function finite(name, value) {
168
+ if (!Number.isFinite(value)) throw new Error(`[arc] MemoryCacheStore ${name} must be a finite number, got ${String(value)}.`);
169
+ return value;
170
+ }
171
+ function clamp(name, value, min, max) {
172
+ return Math.min(max, Math.max(min, finite(name, value)));
173
+ }
174
+ function keyBytes(key) {
175
+ return Buffer.byteLength(key, "utf8");
174
176
  }
175
177
  /**
176
178
  * Translate a glob pattern (`prefix:*`, `*:tag:v`) into a regex. Only `*`
@@ -1,5 +1,6 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
2
- import { t as __exportAll } from "./rolldown-runtime-eysyzFAF.mjs";
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
+ import { r as __exportAll } from "./rolldown-runtime-MYrLNGnq.mjs";
3
+ import { a as MetricHistogram, i as DURATION_BUCKETS_SECONDS, o as MetricSeries, s as renderMetricSample } from "./health-CrqUp3sz.mjs";
3
4
  import fp from "fastify-plugin";
4
5
  //#region src/plugins/metrics.ts
5
6
  var metrics_exports = /* @__PURE__ */ __exportAll({
@@ -7,99 +8,64 @@ var metrics_exports = /* @__PURE__ */ __exportAll({
7
8
  metricsPlugin: () => metricsPlugin
8
9
  });
9
10
  var Counter = class {
10
- data = /* @__PURE__ */ new Map();
11
+ series;
12
+ constructor(maxSeries) {
13
+ this.series = new MetricSeries(maxSeries);
14
+ }
11
15
  inc(labels, value = 1) {
12
- const key = labelKey(labels);
13
- const existing = this.data.get(key);
14
- if (existing) existing.value += value;
15
- else this.data.set(key, {
16
- labels: { ...labels },
17
- value
18
- });
16
+ this.series.get(labels, () => ({ value: 0 })).value += value;
19
17
  }
20
18
  values() {
21
- return [...this.data.values()];
22
- }
23
- reset() {
24
- this.data.clear();
25
- }
26
- };
27
- var Histogram = class {
28
- data = /* @__PURE__ */ new Map();
29
- observe(labels, value) {
30
- const key = labelKey(labels);
31
- const existing = this.data.get(key);
32
- if (existing) {
33
- existing.sum += value;
34
- existing.count += 1;
35
- } else this.data.set(key, {
19
+ return this.series.entries().map(({ labels, value }) => ({
36
20
  labels: { ...labels },
37
- sum: value,
38
- count: 1
39
- });
40
- }
41
- values() {
42
- return [...this.data.values()].flatMap(({ labels, sum, count }) => [{
43
- labels: {
44
- ...labels,
45
- le: "sum"
46
- },
47
- value: sum
48
- }, {
49
- labels: {
50
- ...labels,
51
- le: "count"
52
- },
53
- value: count
54
- }]);
21
+ value: value.value
22
+ }));
55
23
  }
56
24
  reset() {
57
- this.data.clear();
25
+ this.series.reset();
58
26
  }
59
27
  };
60
28
  var Gauge = class {
61
- data = /* @__PURE__ */ new Map();
29
+ series;
30
+ constructor(maxSeries) {
31
+ this.series = new MetricSeries(maxSeries);
32
+ }
62
33
  set(labels, value) {
63
- const key = labelKey(labels);
64
- this.data.set(key, {
65
- labels: { ...labels },
66
- value
67
- });
34
+ this.series.get(labels, () => ({ value: 0 })).value = value;
68
35
  }
69
36
  values() {
70
- return [...this.data.values()];
37
+ return this.series.entries().map(({ labels, value }) => ({
38
+ labels: { ...labels },
39
+ value: value.value
40
+ }));
71
41
  }
72
42
  reset() {
73
- this.data.clear();
43
+ this.series.reset();
74
44
  }
75
45
  };
76
- function labelKey(labels) {
77
- return Object.entries(labels).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}=${v}`).join(",");
78
- }
79
46
  function toPrometheusText(metrics) {
80
47
  const lines = [];
81
48
  for (const m of metrics) {
82
49
  lines.push(`# HELP ${m.name} ${m.help}`);
83
50
  lines.push(`# TYPE ${m.name} ${m.type}`);
84
- for (const v of m.values) {
85
- const labelStr = Object.entries(v.labels).map(([k, val]) => `${k}="${val}"`).join(",");
86
- lines.push(`${m.name}{${labelStr}} ${v.value}`);
87
- }
51
+ for (const v of m.values) lines.push(renderMetricSample(m.name, v));
88
52
  }
89
53
  return `${lines.join("\n")}\n`;
90
54
  }
91
55
  const metricsPlugin = async (fastify, opts = {}) => {
92
56
  const path = opts.path ?? "/_metrics";
93
57
  const prefix = opts.prefix ?? "arc";
94
- const httpRequestsTotal = new Counter();
95
- const crudOpsTotal = new Counter();
96
- const cacheHitsTotal = new Counter();
97
- const cacheMissesTotal = new Counter();
98
- const eventsPublishedTotal = new Counter();
99
- const eventsConsumedTotal = new Counter();
100
- const httpDuration = new Histogram();
101
- const crudDuration = new Histogram();
102
- const circuitBreakerState = new Gauge();
58
+ const maxSeries = opts.maxSeries ?? 1e3;
59
+ if (!/^[a-zA-Z_:][a-zA-Z0-9_:]*$/.test(prefix)) throw new Error("metrics.prefix must be a valid Prometheus metric prefix");
60
+ const httpRequestsTotal = new Counter(maxSeries);
61
+ const crudOpsTotal = new Counter(maxSeries);
62
+ const cacheHitsTotal = new Counter(maxSeries);
63
+ const cacheMissesTotal = new Counter(maxSeries);
64
+ const eventsPublishedTotal = new Counter(maxSeries);
65
+ const eventsConsumedTotal = new Counter(maxSeries);
66
+ const httpDuration = new MetricHistogram(DURATION_BUCKETS_SECONDS, maxSeries);
67
+ const crudDuration = new MetricHistogram(DURATION_BUCKETS_SECONDS, maxSeries);
68
+ const circuitBreakerState = new Gauge(maxSeries);
103
69
  const collector = {
104
70
  collect() {
105
71
  const metrics = [
@@ -196,17 +162,18 @@ const metricsPlugin = async (fastify, opts = {}) => {
196
162
  eventsConsumedTotal.inc({ event_type: eventType });
197
163
  },
198
164
  recordCircuitBreakerState(service, state) {
199
- const stateValue = state === "open" ? 1 : state === "half-open" ? 2 : 0;
165
+ const normalized = state.toLowerCase().replaceAll("_", "-");
166
+ const stateValue = normalized === "open" ? 1 : normalized === "half-open" ? 2 : 0;
200
167
  circuitBreakerState.set({ service }, stateValue);
201
168
  }
202
169
  };
203
170
  fastify.decorate("metrics", collector);
204
171
  fastify.addHook("onResponse", async (request, reply) => {
205
- if (request.url === path) return;
172
+ if (request.routeOptions.url === path) return;
206
173
  const duration = reply.elapsedTime / 1e3;
207
174
  const labels = {
208
175
  method: request.method,
209
- route: request.routeOptions?.url ?? request.url,
176
+ route: request.routeOptions.url ?? "__unmatched__",
210
177
  status: String(reply.statusCode)
211
178
  };
212
179
  httpRequestsTotal.inc(labels);
@@ -222,4 +189,4 @@ var metrics_default = fp(metricsPlugin, {
222
189
  fastify: "5.x"
223
190
  });
224
191
  //#endregion
225
- export { metrics_default as n, metrics_exports as r, metricsPlugin as t };
192
+ export { metrics_exports as n, metrics_default as t };
@@ -1,5 +1,5 @@
1
1
 
2
- import { I as MiddlewareHandler, L as RequestWithExtras, Q as MiddlewareConfig } from "../index-DHbyPo5j.mjs";
2
+ import { A as RequestWithExtras, J as MiddlewareConfig, k as MiddlewareHandler } from "../index-WH7xgvxS.mjs";
3
3
  import { RouteHandlerMethod } from "fastify";
4
4
  //#region src/middleware/middleware.d.ts
5
5
  interface NamedMiddleware {
@@ -23,12 +23,12 @@ interface MiddlewareOptions {
23
23
  /**
24
24
  * Create a named middleware with priority and conditions.
25
25
  */
26
- declare function middleware(name: string, options: MiddlewareOptions): NamedMiddleware;
26
+ export declare function middleware(name: string, options: MiddlewareOptions): NamedMiddleware;
27
27
  /**
28
28
  * Sort named middlewares by priority (ascending — lower runs first).
29
29
  * Returns a MiddlewareConfig map keyed by operation, ready to pass to `defineResource()`.
30
30
  */
31
- declare function sortMiddlewares(middlewares: NamedMiddleware[]): MiddlewareConfig;
31
+ export declare function sortMiddlewares(middlewares: NamedMiddleware[]): MiddlewareConfig;
32
32
  //#endregion
33
33
  //#region src/middleware/multipartBody.d.ts
34
34
  /** Parsed file from multipart form-data */
@@ -120,6 +120,6 @@ interface MultipartBodyOptions {
120
120
  * routes with strict rate limits — buffering video through the app tier is
121
121
  * the wrong architecture regardless of limits.
122
122
  */
123
- declare function multipartBody(options?: MultipartBodyOptions): RouteHandlerMethod;
123
+ export declare function multipartBody(options?: MultipartBodyOptions): RouteHandlerMethod;
124
124
  //#endregion
125
- export { type MultipartBodyOptions, type NamedMiddleware, type ParsedFile, middleware, multipartBody, sortMiddlewares };
125
+ export type { MiddlewareOptions, MultipartBodyOptions, NamedMiddleware, ParsedFile };
@@ -1,6 +1,6 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
2
- import { t as CRUD_OPERATIONS } from "../constants-D5Ubn1fe.mjs";
3
- import { t as multipartBody } from "../multipartBody-DtRWM6_U.mjs";
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
+ import { t as CRUD_OPERATIONS } from "../constants-B2QHb6u6.mjs";
3
+ import { t as multipartBody } from "../multipartBody-Cc7eZ9cq.mjs";
4
4
  //#region src/middleware/middleware.ts
5
5
  /**
6
6
  * Named Middleware — Priority-based, conditional middleware execution.
@@ -1,7 +1,7 @@
1
1
 
2
2
  import { LockAdapter } from "@classytic/repo-core/lock";
3
3
  //#region src/migrations/index.d.ts
4
- interface Migration {
4
+ export interface Migration {
5
5
  /** Migration version (sequential number) */
6
6
  version: number;
7
7
  /** Resource name this migration applies to */
@@ -22,7 +22,7 @@ interface Migration {
22
22
  */
23
23
  validate?: (db: unknown) => Promise<boolean>;
24
24
  }
25
- interface MigrationRecord {
25
+ export interface MigrationRecord {
26
26
  version: number;
27
27
  resource: string;
28
28
  description?: string;
@@ -43,7 +43,7 @@ interface MigrationRecord {
43
43
  * - PrismaMigrationStore (uses a `_migrations` table)
44
44
  * - or any custom store
45
45
  */
46
- interface MigrationStore {
46
+ export interface MigrationStore {
47
47
  /** Get all applied migration records, sorted by appliedAt ascending */
48
48
  getApplied(): Promise<MigrationRecord[]>;
49
49
  /**
@@ -60,7 +60,7 @@ interface MigrationStore {
60
60
  /**
61
61
  * Minimal logger interface — matches Fastify's logger, pino, console, etc.
62
62
  */
63
- interface MigrationLogger {
63
+ export interface MigrationLogger {
64
64
  info(msg: string): void;
65
65
  error(msg: string): void;
66
66
  }
@@ -93,7 +93,7 @@ interface MongoCollectionLike {
93
93
  interface MongoDbLike {
94
94
  collection(name: string): MongoCollectionLike;
95
95
  }
96
- declare class MongoMigrationStore implements MigrationStore {
96
+ export declare class MongoMigrationStore implements MigrationStore {
97
97
  private readonly collectionName;
98
98
  private readonly db;
99
99
  constructor(db: MongoDbLike, opts?: {
@@ -105,7 +105,7 @@ declare class MongoMigrationStore implements MigrationStore {
105
105
  }): Promise<void>;
106
106
  remove(migration: Migration): Promise<void>;
107
107
  }
108
- interface MigrationRunnerOptions {
108
+ export interface MigrationRunnerOptions {
109
109
  /** Migration store (required — use MongoMigrationStore or implement your own) */
110
110
  store: MigrationStore;
111
111
  /** Logger (defaults to process.stdout/stderr) */
@@ -144,11 +144,11 @@ interface MigrationRunnerOptions {
144
144
  * `up`/`down` source. Stable for a given build; a transpile-target change
145
145
  * can legitimately shift it (hence `checksumMismatch: 'warn'` default).
146
146
  */
147
- declare function computeMigrationChecksum(migration: Migration): string;
147
+ export declare function computeMigrationChecksum(migration: Migration): string;
148
148
  /**
149
149
  * Define a migration
150
150
  */
151
- declare function defineMigration(migration: Migration): Migration;
151
+ export declare function defineMigration(migration: Migration): Migration;
152
152
  /**
153
153
  * Migration Runner
154
154
  *
@@ -171,7 +171,7 @@ declare function defineMigration(migration: Migration): Migration;
171
171
  * await runner.up(migrations);
172
172
  * ```
173
173
  */
174
- declare class MigrationRunner {
174
+ export declare class MigrationRunner {
175
175
  private readonly db;
176
176
  private readonly store;
177
177
  private readonly log;
@@ -243,7 +243,7 @@ declare class MigrationRunner {
243
243
  /**
244
244
  * Schema version definition for resources
245
245
  */
246
- interface SchemaVersion {
246
+ export interface SchemaVersion {
247
247
  version: number;
248
248
  migrations: Migration[];
249
249
  }
@@ -258,11 +258,11 @@ interface SchemaVersion {
258
258
  * // ... rest of resource definition
259
259
  * });
260
260
  */
261
- declare function withSchemaVersion(version: number, migrations: Migration[]): SchemaVersion;
261
+ export declare function withSchemaVersion(version: number, migrations: Migration[]): SchemaVersion;
262
262
  /**
263
263
  * Global migration registry
264
264
  */
265
- declare class MigrationRegistry {
265
+ export declare class MigrationRegistry {
266
266
  private migrations;
267
267
  /**
268
268
  * Register a migration
@@ -290,4 +290,4 @@ declare class MigrationRegistry {
290
290
  clear(): void;
291
291
  }
292
292
  //#endregion
293
- export { Migration, MigrationLogger, MigrationRecord, MigrationRegistry, MigrationRunner, MigrationRunnerOptions, MigrationStore, MongoMigrationStore, SchemaVersion, computeMigrationChecksum, defineMigration, withSchemaVersion };
293
+ export {};
@@ -1,5 +1,5 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
2
- import { t as startRenewingLease } from "../renewingLease-yF8BdW4b.mjs";
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
+ import { t as startRenewingLease } from "../renewingLease-BFJxGPuh.mjs";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  //#region src/migrations/index.ts
5
5
  /**
@@ -1,18 +1,18 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
2
2
  //#region src/factory/module/index.ts
3
3
  /**
4
4
  * Identity helper for authoring a typed module — mirrors `defineResource`.
5
5
  * Gives inference + a single obvious construction site; does no work.
6
6
  *
7
- * `TExports` is inferred from the `bootstrap` return value, so a module
8
- * author gets a typed public export for free:
7
+ * Everything is inferred: the export from `bootstrap`'s return, the port types from
8
+ * `requires` (declare `requires` BEFORE the phases that read `ports`):
9
9
  *
10
10
  * ```ts
11
- * export const accountingModule = (deps: Deps) =>
12
- * defineModule({
13
- * name: "accounting",
14
- * bootstrap: async () => createAccountingEngine(deps), // TExports inferred
15
- * });
11
+ * defineModule({
12
+ * name: "accounting",
13
+ * requires: { ports: ["outbox"], optionalPorts: ["calendar"] },
14
+ * bootstrap: (f, { ports }) => createAccountingEngine(ports.outbox, ports.calendar),
15
+ * });
16
16
  * ```
17
17
  */
18
18
  function defineModule(module) {