@classytic/arc 2.41.1 → 2.43.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 (230) hide show
  1. package/dist/{EventTransport-CbUKDzZZ.d.mts → EventTransport-CiicKz2Z.d.mts} +1 -1
  2. package/dist/{EventTransport-DSqD_Xsg.mjs → EventTransport-tzA7CAB4.mjs} +22 -17
  3. package/dist/{HookSystem-CMF94SEA.mjs → HookSystem-B6UaKRbF.mjs} +2 -2
  4. package/dist/{QueryCache-DFA-QrU9.d.mts → QueryCache--5uAuYPW.d.mts} +7 -3
  5. package/dist/{ResourceRegistry-MGpXoxHZ.mjs → ResourceRegistry-CuCARu2B.mjs} +44 -13
  6. package/dist/actionPermissions-BotX1YOa.mjs +776 -0
  7. package/dist/audit/index.d.mts +43 -5
  8. package/dist/audit/index.mjs +48 -26
  9. package/dist/auth/audit.mjs +1 -1
  10. package/dist/auth/index.d.mts +43 -13
  11. package/dist/auth/index.mjs +130 -155
  12. package/dist/auth/redis-session.mjs +1 -1
  13. package/dist/{authorizationDecision-DawKGoXb.mjs → authorizationDecision-DQYrkl5f.mjs} +7 -102
  14. package/dist/{base-CxrV1LmG.d.mts → base-CZyixEQR.d.mts} +27 -5
  15. package/dist/boundedMap-BULzfXYU.mjs +57 -0
  16. package/dist/{buildHandler-CvxKOc0m.mjs → buildHandler-CRQ8EcX5.mjs} +4 -4
  17. package/dist/cache/index.d.mts +22 -34
  18. package/dist/cache/index.mjs +4 -4
  19. package/dist/{caching-DbCBxlgw.mjs → caching-Cc2M1DwO.mjs} +3 -3
  20. package/dist/claimed-B10RTfkM.mjs +8 -0
  21. package/dist/cleanup/index.d.mts +6 -10
  22. package/dist/cleanup/index.mjs +27 -73
  23. package/dist/cli/commands/describe.d.mts +4 -2
  24. package/dist/cli/commands/describe.mjs +7 -4
  25. package/dist/cli/commands/docs.mjs +3 -3
  26. package/dist/cli/commands/doctor.mjs +1 -1
  27. package/dist/cli/commands/generate.mjs +2 -2
  28. package/dist/cli/commands/init.mjs +2 -2
  29. package/dist/cli/commands/introspect.mjs +2 -2
  30. package/dist/cli/index.mjs +3 -3
  31. package/dist/{constants-D5Ubn1fe.mjs → constants-Cu7Mx7_U.mjs} +4 -2
  32. package/dist/context/index.d.mts +2 -5
  33. package/dist/context/index.mjs +18 -38
  34. package/dist/core/index.d.mts +3 -3
  35. package/dist/core/index.mjs +8 -8
  36. package/dist/{core-5lazhva9.mjs → core-Cb0LjccA.mjs} +5 -4
  37. package/dist/{createActionRouter-DNqoaK81.mjs → createActionRouter-xjqonMRO.mjs} +87 -39
  38. package/dist/{createAggregationRouter-BcbQJf10.mjs → createAggregationRouter-zRYWw_5D.mjs} +11 -8
  39. package/dist/{preloadResources-f3boenVZ.mjs → createApp-D-953ZAq.mjs} +299 -390
  40. package/dist/{createMcpServer-CbDWkZ1T.d.mts → createMcpServer-C9cxS8zt.d.mts} +1 -1
  41. package/dist/{defineAggregation-D_eJjm5A.mjs → defineAggregation-Bm8RjMbq.mjs} +1 -1
  42. package/dist/{defineResource-DxkMTjRn.mjs → defineResource-DIC7JZGU.mjs} +118 -1024
  43. package/dist/discovery/index.mjs +1 -1
  44. package/dist/docs/index.d.mts +10 -4
  45. package/dist/docs/index.mjs +4 -4
  46. package/dist/{elevation-BXCfVcNG.d.mts → elevation-BW2J3tNj.d.mts} +1 -2
  47. package/dist/{elevation-CkvG0LG2.mjs → elevation-DG8SrLN-.mjs} +41 -12
  48. package/dist/encryption/index.mjs +3 -3
  49. package/dist/{errorHandler-D1GHKGlV.mjs → errorHandler-BnfDviL1.mjs} +26 -5
  50. package/dist/{errors-BH7YU_9O.mjs → errors-CtrywMHP.mjs} +58 -23
  51. package/dist/{errors-BGdVwP25.d.mts → errors-JYc9vwqE.d.mts} +9 -0
  52. package/dist/{eventPlugin-B52abJ8W.d.mts → eventPlugin-BtmA4-3P.d.mts} +65 -9
  53. package/dist/{eventPlugin-zZY-unhr.mjs → eventPlugin-Q6BhzHzs.mjs} +82 -21
  54. package/dist/{subscribe-helpers-DatDkcuG.mjs → eventTypes-Cdhm6ZlV.mjs} +151 -17
  55. package/dist/events/index.d.mts +33 -8
  56. package/dist/events/index.mjs +49 -53
  57. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  58. package/dist/events/transports/redis-stream-entry.mjs +139 -157
  59. package/dist/events/transports/redis.d.mts +1 -1
  60. package/dist/events/transports/redis.mjs +2 -2
  61. package/dist/factory/index.d.mts +32 -17
  62. package/dist/factory/index.mjs +213 -32
  63. package/dist/{fastify-augmentation-Cq2nHVaW.d.mts → fastify-augmentation-DhUJ-mvo.d.mts} +11 -25
  64. package/dist/{fields-I_EeRWND.d.mts → fields-BBSpf8pS.d.mts} +1 -1
  65. package/dist/{fields-BHrkoF5y.mjs → fields-ToPYpMqS.mjs} +1 -1
  66. package/dist/filter-merge-IpGywvym.mjs +99 -0
  67. package/dist/{generate-BLRf2m3y.mjs → generate-DRTkLlIl.mjs} +2 -2
  68. package/dist/{headers-BIXWKrzQ.mjs → headers-BbkIF6vA.mjs} +2 -2
  69. package/dist/health-D-Ft6JM6.mjs +22 -0
  70. package/dist/{health-ZRHeDHXH.mjs → health-DqbsG-_w.mjs} +115 -55
  71. package/dist/hooks/index.d.mts +2 -2
  72. package/dist/hooks/index.mjs +2 -2
  73. package/dist/idempotency/index.d.mts +31 -7
  74. package/dist/idempotency/index.mjs +155 -98
  75. package/dist/idempotency/redis.d.mts +1 -1
  76. package/dist/idempotency/redis.mjs +48 -11
  77. package/dist/{index-BHdZD8zK.d.mts → index-Bxriq3so.d.mts} +84 -21
  78. package/dist/{preloadResources-CjS2OfpU.d.mts → index-C8zVGYsk.d.mts} +37 -38
  79. package/dist/{index-D4u76eQW.d.mts → index-CRoPtISf.d.mts} +23 -73
  80. package/dist/{index-CbJiYrfv.d.mts → index-Chgz3d0i.d.mts} +1 -1
  81. package/dist/index-JdbZAIsm.d.mts +510 -0
  82. package/dist/{index-DHbyPo5j.d.mts → index-mqaqZNpe.d.mts} +253 -254
  83. package/dist/index.d.mts +8 -8
  84. package/dist/index.mjs +11 -11
  85. package/dist/{init-CpLkjU18.mjs → init-B_oUYDXI.mjs} +1 -1
  86. package/dist/integrations/event-gateway.d.mts +8 -3
  87. package/dist/integrations/event-gateway.mjs +4 -4
  88. package/dist/integrations/index.d.mts +3 -3
  89. package/dist/integrations/index.mjs +1 -1
  90. package/dist/integrations/jobs/index.d.mts +1 -1
  91. package/dist/integrations/jobs/index.mjs +18 -5
  92. package/dist/integrations/mcp/index.d.mts +72 -59
  93. package/dist/integrations/mcp/index.mjs +19 -4
  94. package/dist/integrations/mcp/testing.d.mts +2 -2
  95. package/dist/integrations/mcp/testing.mjs +2 -2
  96. package/dist/integrations/streamline.d.mts +78 -136
  97. package/dist/integrations/streamline.mjs +116 -54
  98. package/dist/integrations/webhooks.d.mts +60 -120
  99. package/dist/integrations/webhooks.mjs +36 -80
  100. package/dist/integrations/websocket-pushref-redis.d.mts +1 -1
  101. package/dist/integrations/websocket-pushref-redis.mjs +1 -1
  102. package/dist/integrations/websocket-redis.d.mts +1 -1
  103. package/dist/integrations/websocket-redis.mjs +1 -1
  104. package/dist/integrations/websocket.d.mts +3 -3
  105. package/dist/integrations/websocket.mjs +2 -2
  106. package/dist/{interface-DEWNOMza.d.mts → interface-C0395yUN.d.mts} +13 -1
  107. package/dist/{jsonBody-ELR9lfeU.mjs → jsonBody-B4YVGcql.mjs} +2 -2
  108. package/dist/{keys-cpZCtcIE.mjs → keys-B2KtgMLJ.mjs} +7 -18
  109. package/dist/{loadResources-BPfWiI5s.mjs → loadResources-Dn4lalw2.mjs} +3 -3
  110. package/dist/{loadResourcesFromEntry-ixtfL3J2.mjs → loadResourcesFromEntry-3sLYbuse.mjs} +2 -2
  111. package/dist/logger/index.d.mts +1 -8
  112. package/dist/logger/index.mjs +3 -153
  113. package/dist/logger-DXjfIqjV.mjs +160 -0
  114. package/dist/{mcpPlugin-BX5PujI0.mjs → mcpPlugin-C08HalN5.mjs} +433 -170
  115. package/dist/{memory-Iotz0cCx.mjs → memory-9Cp7611C.mjs} +36 -34
  116. package/dist/{metrics-NMsmpRmY.mjs → metrics-CWI11eRu.mjs} +39 -72
  117. package/dist/middleware/index.d.mts +2 -2
  118. package/dist/middleware/index.mjs +3 -3
  119. package/dist/migrations/index.mjs +2 -2
  120. package/dist/{module-DpLJG2_N.mjs → module-BSvOQC7E.mjs} +8 -8
  121. package/dist/multiTenant-cY0FkDiA.d.mts +104 -0
  122. package/dist/{multipartBody-DtRWM6_U.mjs → multipartBody-CXM2a-Dy.mjs} +46 -7
  123. package/dist/{openapi-CmFf3yq_.mjs → openapi-DT_G4VhY.mjs} +48 -10
  124. package/dist/outbox-admin/index.d.mts +3 -3
  125. package/dist/outbox-admin/index.mjs +6 -18
  126. package/dist/{outbox-module-D2z5WkDY.mjs → outbox-module-Bjgzl6tg.mjs} +203 -33
  127. package/dist/{outbox-module-BHdUnuuK.d.mts → outbox-module-gZCHoE4H.d.mts} +79 -6
  128. package/dist/permissions/index.d.mts +5 -4
  129. package/dist/permissions/index.mjs +8 -6
  130. package/dist/{permissions-D8TBH44E.mjs → permissions-Cm0uYHvd.mjs} +149 -33
  131. package/dist/{pipe-FMWNheSO.mjs → pipe-BqeGT6UO.mjs} +2 -2
  132. package/dist/pipeline/index.d.mts +2 -2
  133. package/dist/pipeline/index.mjs +2 -2
  134. package/dist/plan-FVR6LP59.mjs +565 -0
  135. package/dist/{BaseController-CYEwjyjN.mjs → plugin-BccET1tL.mjs} +1256 -345
  136. package/dist/plugins/index.d.mts +14 -11
  137. package/dist/plugins/index.mjs +44 -22
  138. package/dist/plugins/response-cache.mjs +8 -14
  139. package/dist/plugins/tracing-entry.mjs +2 -2
  140. package/dist/{pluralize-CXWZIzTv.mjs → pluralize-CVIOcgMF.mjs} +1 -1
  141. package/dist/presets/filesUpload.d.mts +2 -2
  142. package/dist/presets/filesUpload.mjs +5 -5
  143. package/dist/presets/index.d.mts +26 -31
  144. package/dist/presets/index.mjs +4 -4
  145. package/dist/presets/multiTenant.d.mts +2 -107
  146. package/dist/presets/multiTenant.mjs +22 -162
  147. package/dist/presets/search.d.mts +2 -2
  148. package/dist/presets/search.mjs +2 -2
  149. package/dist/{presets-ZJSPgmT2.mjs → presets-Cpvj6fGO.mjs} +99 -107
  150. package/dist/{projection-BzIgzoKZ.mjs → projection-Ce4aQhQk.mjs} +2 -2
  151. package/dist/{pushref-registry-Dov9l4qE.d.mts → pushref-registry-UxCkoA4C.d.mts} +1 -1
  152. package/dist/{queryCachePlugin-BzqxconG.d.mts → queryCachePlugin-C2lZjTxk.d.mts} +1 -1
  153. package/dist/{queryCachePlugin-DZHPOm9p.mjs → queryCachePlugin-CFWNH8aT.mjs} +12 -14
  154. package/dist/{rateLimitKey-BvOvcBDi.mjs → rateLimitKey-C4O-kPm0.mjs} +1 -1
  155. package/dist/{realtime-8tIQWZz4.mjs → realtime-DmPE9S54.mjs} +25 -21
  156. package/dist/redis-stream-BMk-bpQS.d.mts +219 -0
  157. package/dist/{redis-Bzi1y3F9.d.mts → redis-vLvtcGy_.d.mts} +13 -24
  158. package/dist/redisShapes-CQksY67q.d.mts +55 -0
  159. package/dist/registry/index.d.mts +9 -4
  160. package/dist/registry/index.mjs +4 -4
  161. package/dist/{registry-DNkgGQcK.mjs → registry-Bcz9G1bh.mjs} +10 -8
  162. package/dist/{renewingLease-yF8BdW4b.mjs → renewingLease-qODa7KJQ.mjs} +1 -1
  163. package/dist/{replyHelpers-CNdvMfM4.mjs → replyHelpers-CG_VtVgS.mjs} +2 -2
  164. package/dist/{requestContext-cDkAUr-P.mjs → requestContext-Dsu9P1bV.mjs} +1 -1
  165. package/dist/requirement-CbiLdQ1n.d.mts +22 -0
  166. package/dist/requirement-KDdoRcOP.mjs +35 -0
  167. package/dist/resourceRateLimit-Wf6d6FL9.d.mts +30 -0
  168. package/dist/resourceRateLimit-dSjVr1pk.mjs +180 -0
  169. package/dist/{rolldown-runtime-eysyzFAF.mjs → rolldown-runtime-D1w9Y1VJ.mjs} +1 -1
  170. package/dist/routeValidator-D36SW8qt.mjs +70 -0
  171. package/dist/{runtimeCapabilities-CkhS6jn6.mjs → runtimeCapabilities-0tccjRlj.mjs} +1 -1
  172. package/dist/{schedules-j6uXXAeJ.mjs → schedules-C-OpmHBq.mjs} +46 -37
  173. package/dist/{schemaConverter-BVA7cFRG.mjs → schemaConverter-BORek3O-.mjs} +2 -2
  174. package/dist/{schemaIR-CTvPDoPB.mjs → schemaIR-C7Vbp71I.mjs} +2 -2
  175. package/dist/schemas/index.d.mts +10 -0
  176. package/dist/schemas/index.mjs +8 -3
  177. package/dist/scim/index.mjs +2 -2
  178. package/dist/scope/index.d.mts +2 -2
  179. package/dist/scope/index.mjs +6 -6
  180. package/dist/{scope-BUi1xV1I.mjs → scope-DQthe88b.mjs} +4 -4
  181. package/dist/shutdown-MqA81z_P.mjs +59 -0
  182. package/dist/{simpleEqualityMatcher-C9bzq2gO.mjs → simpleEqualityMatcher-auW8QjXN.mjs} +1 -1
  183. package/dist/{sse-BeqVKQKu.mjs → sse-CYzQBVFe.mjs} +11 -15
  184. package/dist/{sseStream-Ppzo-WUH.mjs → sseStream-B5_Afiqn.mjs} +2 -2
  185. package/dist/{store-helpers-dW71XVWL.mjs → store-helpers-BOzk-CuX.mjs} +1 -1
  186. package/dist/{streaming-IcRFjWQU.mjs → streaming-DjTQhZrN.mjs} +1 -1
  187. package/dist/subscriberIdentity-CW39uA8G.mjs +28 -0
  188. package/dist/tenancy--ed9eH_z.mjs +43 -0
  189. package/dist/tenantPreparation-BKon6Yox.mjs +67 -0
  190. package/dist/testing/cleanupStoreContract.mjs +1 -1
  191. package/dist/testing/index.d.mts +193 -175
  192. package/dist/testing/index.mjs +286 -212
  193. package/dist/testing/outboxStoreContract.mjs +137 -2
  194. package/dist/testing/requiredPorts.d.mts +17 -0
  195. package/dist/testing/requiredPorts.mjs +65 -0
  196. package/dist/testing/storageContract.mjs +1 -1
  197. package/dist/timing-qczZ0YC-.mjs +46 -0
  198. package/dist/{transactionContext-CPbdlnVw.mjs → transactionContext-DjFkrNG6.mjs} +1 -1
  199. package/dist/{typeGuards-BLjPgVBm.mjs → typeGuards-CySF12G-.mjs} +1 -1
  200. package/dist/types/index.d.mts +4 -4
  201. package/dist/types/index.mjs +1 -1
  202. package/dist/types/storage.mjs +1 -1
  203. package/dist/{types-CWQn9-IC.d.mts → types-B4Aq4Sdj.d.mts} +22 -9
  204. package/dist/{types-DfVDvkdP.d.mts → types-BJ-2XqVF.d.mts} +189 -204
  205. package/dist/{types-CgenB1gv.mjs → types-Bk9NOgOC.mjs} +4 -4
  206. package/dist/usage/index.d.mts +2 -3
  207. package/dist/usage/index.mjs +5 -5
  208. package/dist/{userHelpers-ChRvkuSZ.mjs → userHelpers-aklawRaK.mjs} +1 -1
  209. package/dist/utils/index.d.mts +84 -223
  210. package/dist/utils/index.mjs +13 -12
  211. package/dist/{utils-CxcctrAh.mjs → utils-ec1oTo1n.mjs} +315 -404
  212. package/dist/{validate-DrYWnOzI.mjs → validate-9yzHC1e2.mjs} +6 -14
  213. package/dist/{versioning-D6JIK8Tk.d.mts → versioning-Bsb51gGT.d.mts} +28 -13
  214. package/dist/{versioning-DKkT4hNJ.mjs → versioning-fhhWHV74.mjs} +4 -4
  215. package/dist/{websocket-BOXVggMf.d.mts → websocket-Cs4awVyD.d.mts} +1 -1
  216. package/dist/{workScope-CxKqoIFn.mjs → workScope-zpPyge4t.mjs} +2 -2
  217. package/package.json +16 -12
  218. package/skills/arc/SKILL.md +13 -4
  219. package/skills/arc/references/auth.md +8 -5
  220. package/skills/arc/references/integrations.md +1 -1
  221. package/skills/arc/references/mcp.md +8 -6
  222. package/skills/arc/references/multi-tenancy.md +19 -14
  223. package/skills/arc/references/production.md +27 -10
  224. package/dist/actionPermissions-BoPGQ5-4.mjs +0 -350
  225. package/dist/index-CFfLKMH4.d.mts +0 -290
  226. package/dist/interface-YzIbF7Ii.mjs +0 -17
  227. package/dist/redis-stream-BPKscsTB.d.mts +0 -260
  228. package/dist/registerRoute-Bsnk6NiZ.mjs +0 -364
  229. package/dist/sync/changelog.d.mts +0 -3
  230. package/dist/sync/changelog.mjs +0 -3
@@ -1,260 +0,0 @@
1
-
2
- import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "./EventTransport-CbUKDzZZ.mjs";
3
- //#region src/events/transports/redis-stream.d.ts
4
- interface RedisStreamLike {
5
- xadd(key: string, id: string, ...fieldValues: string[]): Promise<string | null>;
6
- xreadgroup(command: "GROUP", group: string, consumer: string, ...args: unknown[]): Promise<Array<[string, Array<[string, string[] | null]>]> | null>;
7
- xack(key: string, group: string, ...ids: unknown[]): Promise<number>;
8
- xgroup(command: string, key: string, group: string, ...args: unknown[]): Promise<unknown>;
9
- xpending(key: string, group: string, ...args: unknown[]): Promise<unknown[]>;
10
- xclaim(key: string, group: string, consumer: string, minIdleTime: number, ...ids: unknown[]): Promise<unknown[]>;
11
- xlen(key: string): Promise<number>;
12
- /**
13
- * Read a range of entries by id. When present, the DLQ writer uses this
14
- * to fetch the original message payload so dead-lettered events are
15
- * **fully replayable** (a re-publish of `envelope.event` is sufficient).
16
- *
17
- * Optional to preserve back-compat with custom Redis wrappers that
18
- * satisfied the pre-2.11.3 shape. When missing, the DLQ envelope still
19
- * carries the **error reason + attempt accounting** (operator-grade
20
- * triage info survives), but `envelope.event.payload` is `null` and
21
- * `envelope.event.type` is `<unknown>` — replay is NOT possible without
22
- * upgrading the client. A one-shot warning fires per process so this
23
- * isn't silent.
24
- */
25
- xrange?(key: string, start: string, end: string): Promise<Array<[string, string[]]>>;
26
- /** Graceful close — flushes queued commands then closes. ioredis-style. */
27
- quit(): Promise<unknown>;
28
- /**
29
- * Force-disconnect — closes the socket immediately, abandoning any
30
- * pending command (including a live `XREADGROUP BLOCK`). Optional because
31
- * non-ioredis clients may not expose a force path; `close()` falls back
32
- * to `quit()` when this is missing, accepting a longer shutdown wait.
33
- */
34
- disconnect?(): void;
35
- }
36
- interface RedisStreamTransportOptions {
37
- /**
38
- * Redis stream key name.
39
- * @default 'arc:events'
40
- */
41
- stream?: string;
42
- /**
43
- * Consumer group name. Each group receives every event independently.
44
- * Multiple instances of the same service should share a group name.
45
- * @default 'default'
46
- */
47
- group?: string;
48
- /**
49
- * Consumer name within the group. Must be unique per instance.
50
- * @default 'consumer-<random>'
51
- */
52
- consumer?: string;
53
- /**
54
- * Block time in ms when waiting for new events.
55
- * @default 5000
56
- */
57
- blockTimeMs?: number;
58
- /**
59
- * Max events to read per batch.
60
- * @default 10
61
- */
62
- batchSize?: number;
63
- /**
64
- * Bounded concurrency for processing a batch's ENTRIES (default: 1 —
65
- * strict stream order, the safe default). With one slow handler,
66
- * throughput per consumer is ~`1 / total handler latency`; raising this
67
- * processes up to N entries of a batch concurrently.
68
- *
69
- * Trade-off: entries within a batch may complete OUT OF ORDER — only
70
- * raise it when handlers are order-independent (idempotent, keyed
71
- * upserts). Handlers on this transport should be short and I/O-bound
72
- * regardless; heavy work belongs in jobs. Matching handlers for a single
73
- * event always run sequentially.
74
- * @default 1
75
- */
76
- processingConcurrency?: number;
77
- /**
78
- * Max delivery attempts before moving to dead letter stream.
79
- * @default 5
80
- */
81
- maxRetries?: number;
82
- /**
83
- * Idle time in ms before pending entries are claimed by this consumer.
84
- * Handles crash recovery — if a consumer dies mid-processing, another
85
- * consumer will claim its pending entries after this timeout.
86
- * @default 30000
87
- */
88
- claimTimeoutMs?: number;
89
- /**
90
- * Dead letter stream name. Failed events are moved here after maxRetries.
91
- * Set to `false` to disable DLQ (failed events are acked and dropped).
92
- * @default 'arc:events:dlq'
93
- */
94
- deadLetterStream?: string | false;
95
- /**
96
- * Max stream length (approximate). Uses XADD MAXLEN ~ to trim old entries.
97
- * Set to 0 to disable trimming.
98
- * @default 10000
99
- */
100
- maxLen?: number;
101
- /**
102
- * Max event payload size in bytes. Publish rejects events exceeding this limit
103
- * to prevent Redis memory exhaustion from oversized payloads.
104
- * @default 1_000_000 (1 MB)
105
- */
106
- maxPayloadBytes?: number;
107
- /**
108
- * If `true`, `close()` does NOT call `redis.quit()` — useful when the host
109
- * manages the Redis connection lifecycle externally (shared client across
110
- * multiple transports / cache stores). Without this, every transport
111
- * `close()` would tear down a shared client and break siblings.
112
- *
113
- * Mirror of `RedisEventTransportOptions.externalLifecycle`.
114
- * @default false
115
- */
116
- externalLifecycle?: boolean;
117
- /**
118
- * Hard cap on how long `close()` waits for the in-flight `XREADGROUP BLOCK`
119
- * iteration to drain. Tests and serverless shutdowns would otherwise hang
120
- * up to `blockTimeMs` (default 5s) per close.
121
- *
122
- * Behaviour after timeout:
123
- * - `externalLifecycle: false` (default) — `redis.disconnect()` (or
124
- * `quit()` if the client lacks `disconnect`) breaks the BLOCK
125
- * immediately. Strict bounded close.
126
- * - `externalLifecycle: true` — arc CANNOT touch the host's connection,
127
- * so the poll loop is left to drain in the background when its
128
- * XREADGROUP returns. `close()` returns within `closeTimeoutMs` but
129
- * the loop's eventual completion is silently absorbed (no log spam,
130
- * no unhandled rejection). The contract here is "bounded return,
131
- * background drain" — set `blockTimeMs` low (e.g. 500ms) under
132
- * externalLifecycle to keep the drain window short.
133
- *
134
- * @default 1000
135
- */
136
- closeTimeoutMs?: number;
137
- /**
138
- * Logger for error messages (default: console).
139
- * Pass `fastify.log` to integrate with your application logger.
140
- */
141
- logger?: EventLogger;
142
- }
143
- declare class RedisStreamTransport implements EventTransport {
144
- readonly name = "redis-stream";
145
- private redis;
146
- private stream;
147
- private group;
148
- private consumer;
149
- private blockTimeMs;
150
- private batchSize;
151
- private processingConcurrency;
152
- private maxRetries;
153
- private claimTimeoutMs;
154
- private deadLetterStream;
155
- private maxLen;
156
- private maxPayloadBytes;
157
- private logger;
158
- /** Tracks the lifecycle policy — set in constructor, read in close(). */
159
- private externalLifecycle;
160
- private closeTimeoutMs;
161
- private handlers;
162
- private running;
163
- private pollPromise;
164
- /**
165
- * Monotonic counter bumped every time the poll loop should stop —
166
- * `unsubscribe` (last handler removed) and `close()` increment it. Each
167
- * `pollLoop` instance captures its generation at start and exits when
168
- * `this.generation` no longer matches. Prevents the
169
- * subscribe → unsubscribe → fast-resubscribe race where the old loop
170
- * would still be in `XREADGROUP BLOCK` while a new loop started, leading
171
- * to two concurrent poll loops on the same consumer name.
172
- */
173
- private generation;
174
- private groupCreated;
175
- /**
176
- * Last-seen failure context per message id, populated when an in-process
177
- * handler throws in {@link processEntry}. Consumed (and cleared) by
178
- * {@link moveToDlq} so the dead-letter envelope carries the actual error
179
- * message instead of opaque "reclaimed without context". Entries are
180
- * deleted on ack and on DLQ write; messages resolved by ANOTHER consumer
181
- * never drain locally, so the map is additionally hard-capped at
182
- * {@link MAX_FAILURE_CONTEXT_ENTRIES} with oldest-first eviction.
183
- */
184
- private failureContext;
185
- /** One-shot guard so the "client lacks xrange" warning fires once per process. */
186
- private xrangeWarningEmitted;
187
- constructor(redis: RedisStreamLike, options?: RedisStreamTransportOptions);
188
- publish(event: DomainEvent): Promise<void>;
189
- subscribe(pattern: string, handler: EventHandler): Promise<() => void>;
190
- /**
191
- * Stop polling and release transport state.
192
- *
193
- * **Two close contracts** — pick the one that matches your deployment:
194
- *
195
- * 1. **Default (`externalLifecycle: false`) — strict bounded close.**
196
- * `close()` waits up to `closeTimeoutMs` for the in-flight
197
- * `XREADGROUP BLOCK` to drain. On timeout it calls `redis.disconnect()`
198
- * (or `quit()` if the client lacks `disconnect`) to break the BLOCK
199
- * immediately, then awaits the loop's exit. After `close()` returns
200
- * the transport is fully closed and the connection is released.
201
- *
202
- * 2. **`externalLifecycle: true` — bounded RETURN, background drain.**
203
- * Arc must NOT touch a connection it doesn't own. `close()` returns
204
- * within `closeTimeoutMs`, but the poll loop is left to drain on its
205
- * own when its outstanding `XREADGROUP BLOCK` returns (up to
206
- * `blockTimeMs`). Arc silently absorbs the loop's eventual completion
207
- * so the host doesn't see unhandled rejections / log spam against a
208
- * transport it considers closed. The host's own `redis.quit()` /
209
- * process exit is what ultimately tears the connection down.
210
- *
211
- * Practical implication: under `externalLifecycle: true`, set
212
- * `blockTimeMs` low (e.g. 500ms) so the background drain window is
213
- * short. The transport is "closed enough" to stop dispatching to
214
- * handlers (handlers map is cleared and generation is bumped) but is
215
- * not "fully closed" in the connection-lifecycle sense until the host
216
- * closes the underlying client.
217
- *
218
- * In both modes the generation counter is bumped, so a follow-up
219
- * `subscribe()` spawns a fresh poll loop with a new generation — the
220
- * stale loop exits on its next iteration and never overlaps the new one.
221
- */
222
- close(): Promise<void>;
223
- private ensureGroup;
224
- private pollLoop;
225
- private readNewMessages;
226
- /**
227
- * Process a batch's entries with bounded concurrency
228
- * (`processingConcurrency`, default 1 = strict order). Worker-pool over a
229
- * shared index — at most N entries in flight, each entry's own handlers
230
- * still sequential inside `processEntry`.
231
- */
232
- private processEntries;
233
- private claimPending;
234
- private processEntry;
235
- /**
236
- * The canonical matcher from primitives — the SAME glob rules the memory
237
- * transport speaks. A private matcher here once accepted `prefix.*` but not
238
- * `prefix:*`, so an `order:*` subscription that worked in-process received
239
- * nothing after a move to the stream, with no error.
240
- */
241
- private getMatchingHandlers;
242
- private moveToDlq;
243
- /**
244
- * Reconstruct a `DeadLetteredEvent` for a message id. Reads the original
245
- * entry via `xrange` (when the client supports it) and merges in any
246
- * in-process failure context. Returns `null` only when BOTH sources are
247
- * missing — callers ack-and-drop rather than re-queuing a ghost.
248
- *
249
- * Graceful degradation paths:
250
- * - Client lacks `xrange` (older custom wrappers) → log once, build the
251
- * envelope from `failureContext` alone. Payload is absent but the
252
- * error reason + attempt accounting still survive.
253
- * - `xrange` throws (network blip, ACL) → same fallback.
254
- * - Source entry trimmed before DLQ write → same fallback.
255
- */
256
- private buildDlqEnvelope;
257
- private sleep;
258
- }
259
- //#endregion
260
- export { RedisStreamTransport as n, RedisStreamTransportOptions as r, RedisStreamLike as t };
@@ -1,364 +0,0 @@
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 { r as deriveHiddenFieldPermissions } from "./fields-BHrkoF5y.mjs";
6
- import { n as requestContext } from "./requestContext-cDkAUr-P.mjs";
7
- //#region src/core/middlewares/arcDecorator.ts
8
- /**
9
- * Build the `arcDecorator` preHandler for a resource.
10
- *
11
- * The decorator is a closure over frozen metadata — allocated once per
12
- * resource and shared across every request. Stamps `req.arc` with the
13
- * resource's field permissions, hooks, events bus, and schema options
14
- * so `sendControllerResponse`, `BaseController.run*`, and custom
15
- * middleware can read a consistent view.
16
- *
17
- * Also populates `requestContext.resourceName` for async-context access
18
- * in code paths that can't reach `req.arc` directly (e.g. detached logger
19
- * formatters).
20
- */
21
- function buildArcDecorator(meta) {
22
- const frozen = Object.freeze({
23
- ...meta,
24
- fields: deriveHiddenFieldPermissions(meta.schemaOptions, meta.fields)
25
- });
26
- return async (req, _reply) => {
27
- req.arc = frozen;
28
- const store = requestContext.get();
29
- if (store) store.resourceName = frozen.resourceName;
30
- };
31
- }
32
- //#endregion
33
- //#region src/core/middlewares/auth.ts
34
- /**
35
- * A permission requires authentication unless it carries the `_isPublic`
36
- * marker set by `allowPublic()`. Absence of a permission is treated as
37
- * public (no auth) — matches historical CRUD behaviour.
38
- */
39
- function requiresAuthentication(permission) {
40
- if (!permission) return false;
41
- return !permission._isPublic;
42
- }
43
- /**
44
- * Pick the right Fastify auth decorator for a single-permission route:
45
- * - protected route → `fastify.authenticate` (401 on missing token)
46
- * - public route → `fastify.optionalAuthenticate` (parses token if present)
47
- *
48
- * Public routes still get optional auth so downstream multi-tenant filters
49
- * can narrow queries when a Bearer token IS supplied.
50
- */
51
- function buildAuthMiddleware(fastify, permission) {
52
- if (requiresAuthentication(permission)) return fastify.authenticate ?? null;
53
- return fastify.optionalAuthenticate ?? null;
54
- }
55
- /**
56
- * Pick the right auth decorator for a multi-permission route (Action router).
57
- *
58
- * The input is the array of resolved per-action permissions — one slot per
59
- * action, in registration order, already flattened against `globalAuth`
60
- * fallback by the caller (`actionPermissions[name] ?? globalAuth`). A slot
61
- * may be `undefined` when the action has no per-action check AND no
62
- * `globalAuth` fallback — that is "public by omission" and must be honored
63
- * here the same way `buildActionPermissionMw` honors it (by skipping the
64
- * permission evaluation entirely). If we filtered undefineds out at this
65
- * layer, a mixed endpoint like `{ ping: undefined, promote: requireRoles(...) }`
66
- * would collapse to "all protected" and 401 the public `ping` action at the
67
- * auth layer before the permission prehandler could let it through.
68
- *
69
- * Rules:
70
- * - ALL public (explicit allowPublic OR omission) → `optionalAuthenticate`
71
- * - ALL protected → `authenticate` (fail-fast)
72
- * - MIXED → `optionalAuthenticate`
73
- * (parse token if present; per-action check fails-closed when user=null)
74
- *
75
- * The mixed case was previously handled by an in-handler
76
- * `fastify.authenticate()` call that bypassed the preHandler chain; this
77
- * helper moves that logic back into the preHandler stack so the request
78
- * lifecycle is consistent across router types.
79
- */
80
- function buildAuthMiddlewareForPermissions(fastify, permissions) {
81
- if (permissions.length === 0) return fastify.optionalAuthenticate ?? null;
82
- const hasProtected = permissions.some((p) => requiresAuthentication(p));
83
- const hasPublic = permissions.some((p) => p && p._isPublic === true) || permissions.some((p) => !p);
84
- if (hasProtected && !hasPublic) return fastify.authenticate ?? null;
85
- return fastify.optionalAuthenticate ?? null;
86
- }
87
- //#endregion
88
- //#region src/core/middlewares/chain.ts
89
- /**
90
- * Compose the route-level `onRequest` + `preHandler` arrays in the canonical
91
- * order. Every null/undefined entry is dropped. Keeps the three routers from
92
- * accidentally ordering the same ingredients differently (regression risk:
93
- * cache before auth → user-scoped cache keys leak across users; auth after
94
- * body parse → anonymous schema probing).
95
- *
96
- * onRequest constraints (Fastify lifecycle): `request.body` is undefined —
97
- * everything placed there must be header/cookie/param/query-driven. arc's
98
- * `authenticate` / `optionalAuthenticate` qualify by contract (Bearer
99
- * header, session cookie, api-key header); `preAuth` handlers exist
100
- * precisely to promote query tokens into headers (SSE `?token=`); the arc
101
- * decorator stamps static route metadata.
102
- */
103
- function buildRouteHooks(parts) {
104
- return {
105
- onRequest: [
106
- ...parts.preAuth ?? [],
107
- parts.arcDecorator,
108
- parts.authMw ?? null
109
- ].filter(Boolean),
110
- preHandler: [
111
- parts.permissionMw ?? null,
112
- parts.pluginMw ?? null,
113
- ...parts.routeGuards ?? [],
114
- ...parts.customMws ?? []
115
- ].filter(Boolean)
116
- };
117
- }
118
- /**
119
- * Spread helper — turns `RouteHookChains` into the two Fastify route-option
120
- * fields, omitting empty arrays so routes without middleware stay
121
- * option-free (Fastify skips absent hooks faster than empty arrays).
122
- */
123
- function routeHookOptions(hooks) {
124
- return {
125
- ...hooks.onRequest.length > 0 ? { onRequest: hooks.onRequest } : {},
126
- ...hooks.preHandler.length > 0 ? { preHandler: hooks.preHandler } : {}
127
- };
128
- }
129
- /**
130
- * `RouteDefinition.preHandler` accepts two shapes:
131
- *
132
- * 1. **Array form** — `RouteHandlerMethod[]`. Used directly.
133
- * 2. **Factory form** — `(fastify) => RouteHandlerMethod[]`. Called once at
134
- * route-registration time with the Fastify instance, so handlers can
135
- * capture decorators (`fastify.authenticate`, `fastify.events`, etc.)
136
- * that aren't on the request.
137
- *
138
- * The two forms are equally idiomatic, but the discrimination is by
139
- * `typeof preHandler === "function"`. Single-function shapes such as
140
- * `multipartBody({...})` (a `RouteHandlerMethod`) **structurally satisfy
141
- * the factory branch** at the call site, then fail with a cryptic
142
- * `Cannot read properties of undefined (reading 'content-type')` once the
143
- * handler runs with `fastify` in the request slot.
144
- *
145
- * This resolver:
146
- * 1. Distinguishes the two valid shapes.
147
- * 2. Validates the factory's RETURN — must be an array of functions.
148
- * 3. Throws an actionable error pointing at the route + the fix when
149
- * a single `RouteHandlerMethod` was passed instead of an array, OR
150
- * when a factory returned the wrong shape.
151
- *
152
- * The error message names the route (`{method} {path}`) and the
153
- * canonical fix (`preHandler: [yourHandler]`) so the failure mode is
154
- * obvious instead of debug-archaeology.
155
- *
156
- * @param preHandler The `route.preHandler` value (any of the valid shapes
157
- * plus the common bare-handler mistake).
158
- * @param fastify Passed to factory-form preHandlers.
159
- * @param routeId `"GET /todos/:id/attach"` (or similar) — used in the
160
- * error message so a multi-route file points at the
161
- * actual offender.
162
- */
163
- function resolveRoutePreHandlers(preHandler, fastify, routeId) {
164
- if (preHandler === void 0 || preHandler === null) return [];
165
- if (Array.isArray(preHandler)) return preHandler.filter((h) => typeof h === "function");
166
- if (typeof preHandler === "function") {
167
- let result;
168
- try {
169
- result = preHandler(fastify);
170
- } catch (err) {
171
- const msg = err instanceof Error ? err.message : String(err);
172
- throw new TypeError(`Route ${routeId}: preHandler factory threw during route registration: ${msg}.\nIf you intended to pass a single handler (e.g. \`multipartBody({...})\`), wrap it in an array: \`preHandler: [yourHandler]\`. The factory form is \`(fastify) => RouteHandlerMethod[]\` — it must return an array.`, { cause: err instanceof Error ? err : void 0 });
173
- }
174
- if (result && typeof result.then === "function") result.catch(() => void 0);
175
- if (!Array.isArray(result)) throw new TypeError(`Route ${routeId}: preHandler factory must return an array of handlers, got ${describeValue(result)}.\nCommon cause: passing a single \`RouteHandlerMethod\` (e.g. \`multipartBody({...})\`) where an array was expected. Wrap it: \`preHandler: [yourHandler]\`. The factory form \`(fastify) => RouteHandlerMethod[]\` is for cases that need the Fastify instance — e.g. \`(fastify) => [fastify.authenticate, myHandler]\`.`);
176
- return result.filter((h) => typeof h === "function");
177
- }
178
- throw new TypeError(`Route ${routeId}: preHandler must be an array of handlers OR a factory \`(fastify) => RouteHandlerMethod[]\`. Got ${describeValue(preHandler)}.`);
179
- }
180
- function describeValue(v) {
181
- if (v === null) return "null";
182
- if (v === void 0) return "undefined";
183
- if (typeof v === "function") return "a function (single handler — wrap in array)";
184
- if (Array.isArray(v)) return `an array of length ${v.length}`;
185
- return `${typeof v} (${JSON.stringify(v).slice(0, 80)})`;
186
- }
187
- //#endregion
188
- //#region src/core/middlewares/permissions.ts
189
- /**
190
- * Build a PermissionContext from a Fastify request. Extracted so the CRUD
191
- * permission middleware and the dynamic action-permission check use the same
192
- * field layout — divergence here silently broke policy filters for actions.
193
- */
194
- function buildPermissionContext(req, opts) {
195
- const reqWithExtras = req;
196
- const params = req.params;
197
- return {
198
- user: reqWithExtras.user ?? null,
199
- scope: getRequestScope(req),
200
- request: req,
201
- resource: opts.resource,
202
- action: opts.action,
203
- resourceId: opts.resourceId ?? params?.id,
204
- params,
205
- data: opts.data ?? req.body
206
- };
207
- }
208
- /**
209
- * Static per-route CRUD permission gate. The permission and action are known
210
- * at route-registration time, so the gate is a plain preHandler.
211
- *
212
- * Actions use the dynamic counterpart `buildActionPermissionMw` — their
213
- * permission is resolved from `body.action` at request time.
214
- */
215
- function buildCrudPermissionMw(permissionCheck, resourceName, action) {
216
- if (!permissionCheck) return null;
217
- return async (req, reply) => {
218
- const context = buildPermissionContext(req, {
219
- resource: resourceName,
220
- action
221
- });
222
- await evaluateAndApplyPermission(permissionCheck, context, req, reply);
223
- };
224
- }
225
- /**
226
- * Dynamic per-action permission gate for the action router.
227
- *
228
- * Resolves the permission from `body.action` at request time and runs
229
- * `evaluateAndApplyPermission` from the canonical `permissionMw` slot — so
230
- * `_policyFilters` and `request.scope` are installed BEFORE `pluginMw`
231
- * (idempotency) and `routeGuards` run. Previously this check lived inside
232
- * the main action handler, which meant idempotency recorded unauthorized
233
- * requests and route guards saw unfiltered scope — the very divergence
234
- * routerShared exists to prevent.
235
- *
236
- * Also acts as a defensive fallback for invalid action names — the
237
- * `oneOf` body schema normally rejects these at AJV validation, but
238
- * hosts that disable schema validation still get a 400 here.
239
- */
240
- function buildActionPermissionMw(actionEnum, actionPermissions, globalAuth, resourceName) {
241
- const enumSet = new Set(actionEnum);
242
- const validActions = [...actionEnum];
243
- return async (req, reply) => {
244
- const body = req.body ?? {};
245
- const action = body.action;
246
- if (!action || !enumSet.has(action)) throw createError(400, `Invalid action '${action ?? ""}'. Valid actions: ${validActions.join(", ")}`, { validActions });
247
- const permissionCheck = actionPermissions[action] ?? globalAuth;
248
- if (!permissionCheck) return;
249
- const { action: _discard, ...data } = body;
250
- const params = req.params;
251
- const context = buildPermissionContext(req, {
252
- resource: resourceName,
253
- action,
254
- resourceId: params?.id,
255
- data
256
- });
257
- await evaluateAndApplyPermission(permissionCheck, context, req, reply, { defaultDenialMessage: (user) => user ? `Permission denied for '${action}'` : "Authentication required" });
258
- };
259
- }
260
- //#endregion
261
- //#region src/core/middlewares/pluginMw.ts
262
- /**
263
- * Pick the request-lifecycle plugin middleware for an HTTP method:
264
- * - GET / HEAD → response cache (if present)
265
- * - POST / PUT / PATCH → idempotency (if present)
266
- * - DELETE → none
267
- *
268
- * Either field may be `null` if the corresponding plugin wasn't registered.
269
- */
270
- function selectPluginMw(method, mws) {
271
- const upper = method.toUpperCase();
272
- if (upper === "GET" || upper === "HEAD") return mws.cacheMw;
273
- if (upper === "POST" || upper === "PUT" || upper === "PATCH") return mws.idempotencyMw;
274
- return null;
275
- }
276
- /**
277
- * Resolve the default cache/idempotency middlewares for a resource.
278
- *
279
- * Skips response-cache when the resource has QueryCache active — QueryCache
280
- * handles caching at the controller level with SWR, so the HTTP-level
281
- * response-cache would double-cache.
282
- */
283
- function resolveRouterPluginMw(fastify, resourceHasQueryCache) {
284
- return {
285
- cacheMw: !resourceHasQueryCache && fastify.hasDecorator("responseCache") ? fastify.responseCache.middleware : null,
286
- idempotencyMw: fastify.hasDecorator("idempotency") ? fastify.idempotency.middleware : null
287
- };
288
- }
289
- //#endregion
290
- //#region src/core/middlewares/rateLimit.ts
291
- /**
292
- * Build the per-route Fastify `config` object shared by the CRUD, custom, and
293
- * action routers. Two independent concerns ride on `routeOptions.config`:
294
- * - `config.rateLimit` — read by `@fastify/rate-limit`.
295
- * - `config.cors` — read by `@fastify/cors` as a per-route override.
296
- * - `config.arcExtensions` — read by arc plugins (encryption, …) at request
297
- * time, sourced from `defineResource({ extensions })`.
298
- *
299
- * Returns `{}` (no `config` key) when neither is present, so routes without
300
- * either stay config-free and the spread is a genuine no-op. Both fields are
301
- * optional in the return type, so no cast is needed when only one is set.
302
- */
303
- function buildRouteConfig(rateLimitConfig, extensions, cors) {
304
- const hasCors = cors !== void 0;
305
- if (!rateLimitConfig && !extensions && !hasCors) return {};
306
- return { config: {
307
- ...rateLimitConfig ?? {},
308
- ...hasCors ? { cors } : {},
309
- ...extensions ? { arcExtensions: extensions } : {}
310
- } };
311
- }
312
- /**
313
- * Build the `config` object for Fastify route options so
314
- * @fastify/rate-limit picks up per-route overrides.
315
- *
316
- * - `undefined` → no override (inherits instance config)
317
- * - `false` → explicitly disable rate limiting
318
- * - `{ max, timeWindow }` → apply that limit
319
- */
320
- function buildRateLimitConfig(rateLimit) {
321
- if (rateLimit === void 0) return void 0;
322
- if (rateLimit === false) return { rateLimit: false };
323
- return { rateLimit: {
324
- max: rateLimit.max,
325
- timeWindow: rateLimit.timeWindow
326
- } };
327
- }
328
- //#endregion
329
- //#region src/core/middlewares/registerRoute.ts
330
- /**
331
- * Register a route with friendly handling of `FST_ERR_DUPLICATED_ROUTE`.
332
- *
333
- * Boot-time `validateRouteCrudCollisions()` catches custom-route → auto-CRUD
334
- * overlaps before Fastify ever runs, but a few cases still slip through to
335
- * Fastify itself: two presets contributing the same `routes` entry, hosts
336
- * mounting two resources at the same prefix, custom routes that share a
337
- * URL with another plugin. Fastify's default message ("Method 'GET'
338
- * already declared for route '/'") gives no hint at the resource-shaped
339
- * fix — `disabledRoutes: ['list']` — so wrap it with one.
340
- */
341
- function tryRegisterRoute(fastify, opts, context) {
342
- try {
343
- fastify.route(opts);
344
- } catch (err) {
345
- const fastifyErr = err;
346
- if (fastifyErr?.code !== "FST_ERR_DUPLICATED_ROUTE") throw err;
347
- const method = opts.method;
348
- const url = opts.url;
349
- const opHint = context.op ? ` (op: ${context.op})` : "";
350
- const fixHint = context.op && [
351
- "list",
352
- "get",
353
- "create",
354
- "update",
355
- "delete"
356
- ].includes(context.op) ? ` Suppress the auto-CRUD route with \`disabledRoutes: ['${context.op}']\`.` : " If a custom route in `routes:` collides with auto-CRUD, add `disabledRoutes: ['list' | 'get' | 'create' | 'update' | 'delete']` to `defineResource()` to suppress the matching auto-CRUD route.";
357
- const enhanced = /* @__PURE__ */ new Error(`[arc] Duplicate route ${method} ${url} on resource "${context.resourceName}"${opHint}.${fixHint} Original: ${fastifyErr.message ?? "FST_ERR_DUPLICATED_ROUTE"}`);
358
- enhanced.code = "FST_ERR_DUPLICATED_ROUTE";
359
- enhanced.cause = err;
360
- throw enhanced;
361
- }
362
- }
363
- //#endregion
364
- export { selectPluginMw as a, buildRouteHooks as c, buildAuthMiddleware as d, buildAuthMiddlewareForPermissions as f, resolveRouterPluginMw as i, resolveRoutePreHandlers as l, buildRateLimitConfig as n, buildActionPermissionMw as o, buildArcDecorator as p, buildRouteConfig as r, buildCrudPermissionMw as s, tryRegisterRoute as t, routeHookOptions as u };
@@ -1,3 +0,0 @@
1
-
2
- import { ChangeEntry, ChangeLogAppendOptions, ChangeLogStore, ChangeOp, ChangesPage, ChangesSinceOptions, CursorExpiredError, MemoryChangeLogStore, PushMutation, PushVerdict, PushVerdictStatus } from "@classytic/repo-core/sync";
3
- export { type ChangeEntry, type ChangeLogAppendOptions, type ChangeLogStore, type ChangeOp, type ChangesPage, type ChangesSinceOptions, CursorExpiredError, MemoryChangeLogStore, type PushMutation, type PushVerdict, type PushVerdictStatus };
@@ -1,3 +0,0 @@
1
- /*! @classytic/arc v2.41.1 | MIT | https://classytic.com */
2
- import { CursorExpiredError, MemoryChangeLogStore } from "@classytic/repo-core/sync";
3
- export { CursorExpiredError, MemoryChangeLogStore };