@classytic/arc 2.30.0 → 2.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +7 -0
  3. package/TRADEMARK.md +22 -0
  4. package/dist/{BaseController-B5DwufbB.mjs → BaseController-Dk34dxhI.mjs} +21 -19
  5. package/dist/{EventTransport-QmY7A258.d.mts → EventTransport-2uVV34WU.d.mts} +1 -0
  6. package/dist/{EventTransport-C6YA8xY9.mjs → EventTransport-BV10D0oG.mjs} +1 -0
  7. package/dist/{HookSystem-WkIougo6.mjs → HookSystem-vimw5D7Z.mjs} +2 -1
  8. package/dist/{QueryCache-DOMT_iq7.d.mts → QueryCache-DFA-QrU9.d.mts} +2 -1
  9. package/dist/{ResourceRegistry-y9Hnypus.mjs → ResourceRegistry-BVr7PgA0.mjs} +18 -15
  10. package/dist/{actionPermissions-CAphcmUG.mjs → actionPermissions-Dti7ebyv.mjs} +1 -0
  11. package/dist/audit/index.d.mts +3 -2
  12. package/dist/audit/index.mjs +2 -1
  13. package/dist/auth/audit.d.mts +1 -0
  14. package/dist/auth/audit.mjs +1 -0
  15. package/dist/auth/index.d.mts +5 -4
  16. package/dist/auth/index.mjs +11 -9
  17. package/dist/auth/redis-session.d.mts +2 -1
  18. package/dist/auth/redis-session.mjs +1 -0
  19. package/dist/{applyPermissionResult-Cf6zUCvb.mjs → authorizationDecision-__T3EJDA.mjs} +19 -10
  20. package/dist/{buildHandler-BYS3Vkfz.mjs → buildHandler-Dn7rzUJo.mjs} +6 -4
  21. package/dist/cache/index.d.mts +4 -3
  22. package/dist/cache/index.mjs +4 -3
  23. package/dist/{caching-_NJeDd1_.mjs → caching-DFJqHyFs.mjs} +2 -1
  24. package/dist/cleanup/index.d.mts +39 -16
  25. package/dist/cleanup/index.mjs +50 -38
  26. package/dist/cli/commands/describe.d.mts +2 -1
  27. package/dist/cli/commands/describe.mjs +4 -5
  28. package/dist/cli/commands/docs.d.mts +1 -0
  29. package/dist/cli/commands/docs.mjs +3 -2
  30. package/dist/cli/commands/doctor.d.mts +1 -0
  31. package/dist/cli/commands/doctor.mjs +1 -0
  32. package/dist/cli/commands/generate.d.mts +2 -1
  33. package/dist/cli/commands/generate.mjs +2 -1
  34. package/dist/cli/commands/init.d.mts +2 -1
  35. package/dist/cli/commands/init.mjs +2 -1
  36. package/dist/cli/commands/introspect.d.mts +1 -0
  37. package/dist/cli/commands/introspect.mjs +2 -1
  38. package/dist/cli/index.d.mts +3 -2
  39. package/dist/cli/index.mjs +3 -2
  40. package/dist/{constants-DNre0wRg.mjs → constants-J99LGTJI.mjs} +1 -0
  41. package/dist/context/index.d.mts +1 -0
  42. package/dist/context/index.mjs +3 -2
  43. package/dist/core/index.d.mts +3 -2
  44. package/dist/core/index.mjs +7 -6
  45. package/dist/{core-poalJLvp.mjs → core-BwwmNSp7.mjs} +3 -2
  46. package/dist/{createActionRouter-BxuywVRB.mjs → createActionRouter-DkJZWo0m.mjs} +14 -10
  47. package/dist/{createAggregationRouter-BiY-lGdY.mjs → createAggregationRouter-B1exOVD8.mjs} +10 -7
  48. package/dist/{createApp-CXrKFciH.mjs → createApp-Bv0m-Q6_.mjs} +625 -229
  49. package/dist/{defineAggregation-ufWjUwml.mjs → defineAggregation-gX4No1gt.mjs} +1 -0
  50. package/dist/{defineResource-CxWqDCAy.mjs → defineResource-XFPPUu2c.mjs} +84 -50
  51. package/dist/discovery/index.d.mts +1 -0
  52. package/dist/discovery/index.mjs +1 -0
  53. package/dist/docs/index.d.mts +3 -2
  54. package/dist/docs/index.mjs +3 -2
  55. package/dist/{elevation-C9s5hFP_.d.mts → elevation-BXCfVcNG.d.mts} +1 -0
  56. package/dist/{elevation-CIz1GjGm.mjs → elevation-DNXXxgjl.mjs} +4 -3
  57. package/dist/encryption/index.d.mts +2 -1
  58. package/dist/encryption/index.mjs +5 -3
  59. package/dist/{errorHandler-Bq2OeEQL.mjs → errorHandler-B2AZUJUj.mjs} +3 -2
  60. package/dist/{errorHandler-C6yv4ZTW.d.mts → errorHandler-CpYUJmPA.d.mts} +1 -0
  61. package/dist/{errors-DHcHVAgk.d.mts → errors-BGdVwP25.d.mts} +1 -0
  62. package/dist/{errors-DkO8Nk6-.mjs → errors-Bh1KK5ps.mjs} +1 -0
  63. package/dist/{eventPlugin-D2NNR4py.mjs → eventPlugin-Dk_TyXeE.mjs} +8 -6
  64. package/dist/{eventPlugin-Bg3cP2_u.d.mts → eventPlugin-GF5nnBIq.d.mts} +2 -1
  65. package/dist/events/index.d.mts +112 -44
  66. package/dist/events/index.mjs +177 -141
  67. package/dist/events/transports/redis-stream-entry.d.mts +2 -1
  68. package/dist/events/transports/redis-stream-entry.mjs +14 -9
  69. package/dist/events/transports/redis.d.mts +2 -1
  70. package/dist/events/transports/redis.mjs +1 -0
  71. package/dist/{externalPaths-BE6wFpYv.d.mts → externalPaths-CmGOxOtD.d.mts} +1 -0
  72. package/dist/factory/index.d.mts +9 -5
  73. package/dist/factory/index.mjs +131 -7
  74. package/dist/fastify-augmentation-BppG5bMT.d.mts +179 -0
  75. package/dist/{fields-CQ_7KQWw.mjs → fields-DEi65pGj.mjs} +6 -10
  76. package/dist/{fields-D3lhgzhD.d.mts → fields-I_EeRWND.d.mts} +1 -0
  77. package/dist/{generate-D0wZupBg.mjs → generate-CRSG0jTv.mjs} +2 -1
  78. package/dist/{generate-BnsL9GBm.d.mts → generate-DCGuEbqI.d.mts} +1 -0
  79. package/dist/{headers-BvlQSDMB.mjs → headers-BXjQYbeC.mjs} +2 -1
  80. package/dist/{health-CB_m4S32.mjs → health-5XnTa2uo.mjs} +1 -0
  81. package/dist/hooks/index.d.mts +2 -1
  82. package/dist/hooks/index.mjs +2 -1
  83. package/dist/idempotency/index.d.mts +3 -2
  84. package/dist/idempotency/index.mjs +8 -5
  85. package/dist/idempotency/redis.d.mts +2 -1
  86. package/dist/idempotency/redis.mjs +1 -0
  87. package/dist/{index-CG4yqMDB.d.mts → index-C-481Zf2.d.mts} +74 -18
  88. package/dist/{index-Q5gzEIWY.d.mts → index-CpzxqePp.d.mts} +107 -32
  89. package/dist/{index-Cx7bro4R.d.mts → index-DXlHwvuE.d.mts} +5 -4
  90. package/dist/index-ZWhLTp_s.d.mts +290 -0
  91. package/dist/{index-Ch16aAah.d.mts → index-zq6VrjaB.d.mts} +122 -15
  92. package/dist/index.d.mts +9 -8
  93. package/dist/index.mjs +11 -10
  94. package/dist/{init-tlRSt667.mjs → init-BbfP8aky.mjs} +25 -27
  95. package/dist/{init-BPEu8cs-.d.mts → init-Cscs4lab.d.mts} +1 -0
  96. package/dist/integrations/event-gateway.d.mts +3 -2
  97. package/dist/integrations/event-gateway.mjs +2 -1
  98. package/dist/integrations/index.d.mts +4 -3
  99. package/dist/integrations/index.mjs +1 -0
  100. package/dist/integrations/jobs/index.d.mts +2 -1
  101. package/dist/integrations/jobs/index.mjs +109 -33
  102. package/dist/integrations/mcp/index.d.mts +6 -6
  103. package/dist/integrations/mcp/index.mjs +2 -1
  104. package/dist/integrations/mcp/testing.d.mts +3 -2
  105. package/dist/integrations/mcp/testing.mjs +2 -2
  106. package/dist/integrations/streamline.d.mts +1 -0
  107. package/dist/integrations/streamline.mjs +3 -2
  108. package/dist/integrations/webhooks.d.mts +1 -0
  109. package/dist/integrations/webhooks.mjs +1 -0
  110. package/dist/integrations/websocket-pushref-redis.d.mts +2 -1
  111. package/dist/integrations/websocket-pushref-redis.mjs +1 -0
  112. package/dist/integrations/websocket-redis.d.mts +2 -1
  113. package/dist/integrations/websocket-redis.mjs +1 -0
  114. package/dist/integrations/websocket.d.mts +3 -2
  115. package/dist/integrations/websocket.mjs +38 -34
  116. package/dist/{interface-BGZCzOGL.d.mts → interface-BOk3YnTz.d.mts} +1 -0
  117. package/dist/{interface-n5hpKg1d.mjs → interface-BP4IJCBO.mjs} +1 -0
  118. package/dist/{interface-Uk8ONJv7.d.mts → interface-DEWNOMza.d.mts} +1 -0
  119. package/dist/{jsonBody-BlzAoGCe.mjs → jsonBody-DDSR2HFl.mjs} +2 -1
  120. package/dist/{keys-Cd316u_y.mjs → keys-B-HBTGXl.mjs} +1 -0
  121. package/dist/{loadResources-DpU8pfjV.mjs → loadResources-DisEAmkm.mjs} +4 -2
  122. package/dist/{loadResourcesFromEntry-kvGT6EcO.mjs → loadResourcesFromEntry-D1MJp13f.mjs} +2 -1
  123. package/dist/logger/index.d.mts +1 -0
  124. package/dist/logger/index.mjs +1 -0
  125. package/dist/{mcpPlugin-nRzm5g2s.mjs → mcpPlugin-CpfVpKHE.mjs} +38 -38
  126. package/dist/{memory-CmnzXE5Z.mjs → memory-DsuWnj4T.mjs} +5 -4
  127. package/dist/{metrics-fdxI5mn_.mjs → metrics-DdQL8syd.mjs} +2 -1
  128. package/dist/middleware/index.d.mts +2 -1
  129. package/dist/middleware/index.mjs +3 -2
  130. package/dist/migrations/index.d.mts +1 -0
  131. package/dist/migrations/index.mjs +3 -2
  132. package/dist/module-Br81am6m.mjs +78 -0
  133. package/dist/{multipartBody-D0eBvkeq.mjs → multipartBody-BnkBLN7v.mjs} +3 -2
  134. package/dist/{openapi-B8Vkbxbn.mjs → openapi-DIRzvxC0.mjs} +6 -5
  135. package/dist/outbox-admin/index.d.mts +85 -0
  136. package/dist/outbox-admin/index.mjs +115 -0
  137. package/dist/permissions/index.d.mts +5 -4
  138. package/dist/permissions/index.mjs +6 -5
  139. package/dist/{permissions-Bfu_8y1U.mjs → permissions-Dl_m0NCe.mjs} +308 -42
  140. package/dist/{pipe-BOLmGIxa.mjs → pipe-ELHCP3zj.mjs} +3 -4
  141. package/dist/pipeline/index.d.mts +2 -1
  142. package/dist/pipeline/index.mjs +2 -1
  143. package/dist/{pipeline-BJnpkY9i.mjs → pipeline-CPA-jx0M.mjs} +17 -14
  144. package/dist/plugins/index.d.mts +8 -7
  145. package/dist/plugins/index.mjs +16 -15
  146. package/dist/plugins/response-cache.d.mts +1 -0
  147. package/dist/plugins/response-cache.mjs +2 -1
  148. package/dist/plugins/tracing-entry.d.mts +2 -1
  149. package/dist/plugins/tracing-entry.mjs +2 -1
  150. package/dist/{pluralize-BhrgwZb9.mjs → pluralize-C2ZkKbsn.mjs} +1 -0
  151. package/dist/{preloadResources-DSY5HGpS.mjs → preloadResources-CDs87fTw.mjs} +1 -0
  152. package/dist/{preloadResources-DCfa2egz.d.mts → preloadResources-T1hmlTEZ.d.mts} +117 -12
  153. package/dist/presets/filesUpload.d.mts +6 -5
  154. package/dist/presets/filesUpload.mjs +10 -12
  155. package/dist/presets/index.d.mts +3 -2
  156. package/dist/presets/index.mjs +2 -1
  157. package/dist/presets/multiTenant.d.mts +2 -1
  158. package/dist/presets/multiTenant.mjs +3 -2
  159. package/dist/presets/search.d.mts +3 -2
  160. package/dist/presets/search.mjs +2 -1
  161. package/dist/{presets-CJOEXLuk.mjs → presets-Dntd_pUO.mjs} +6 -4
  162. package/dist/{projection-UBDgfMwu.mjs → projection-CjHhM5W1.mjs} +2 -1
  163. package/dist/{pushref-registry-BbcnpNTm.d.mts → pushref-registry-Dov9l4qE.d.mts} +1 -0
  164. package/dist/{queryCachePlugin-br4otiqF.d.mts → queryCachePlugin-BzqxconG.d.mts} +3 -2
  165. package/dist/{queryCachePlugin-DSGuSVLW.mjs → queryCachePlugin-Dhps-Ldt.mjs} +6 -5
  166. package/dist/{rateLimit-DrED-C4v.mjs → rateLimit-C7mmAGs3.mjs} +7 -3
  167. package/dist/{rateLimitKey-BoWRH3e7.mjs → rateLimitKey-CccEFBfk.mjs} +1 -0
  168. package/dist/{realtime-B9nmIY5V.mjs → realtime-DVvVZZFz.mjs} +20 -9
  169. package/dist/{redis-UDtLaNj6.d.mts → redis-CduhKsJi.d.mts} +2 -1
  170. package/dist/{redis-stream-uIaauNpZ.d.mts → redis-stream-qN6A-RFv.d.mts} +2 -1
  171. package/dist/{registerRoute-JkxIEBJq.mjs → registerRoute-B_QrjYZS.mjs} +10 -7
  172. package/dist/registry/index.d.mts +3 -2
  173. package/dist/registry/index.mjs +3 -2
  174. package/dist/{registry-BYXUUg21.mjs → registry-DqUmzA9W.mjs} +2 -1
  175. package/dist/{renewingLease-3cuQH7h8.mjs → renewingLease-BpP9wwj7.mjs} +1 -0
  176. package/dist/{replyHelpers-67tRawQZ.mjs → replyHelpers-DS-P0b32.mjs} +2 -1
  177. package/dist/{repositoryFilter-Dz8k3S4P.mjs → repositoryFilter-DotlxG3L.mjs} +1 -0
  178. package/dist/{requestContext-MrlJwECf.mjs → requestContext-B6vQF-sy.mjs} +1 -0
  179. package/dist/{rolldown-runtime-8H4AJuhK.mjs → rolldown-runtime-BhflRrBs.mjs} +1 -0
  180. package/dist/{schedules-CjOd2MG9.mjs → schedules-C2Q3uv2d.mjs} +3 -2
  181. package/dist/{schemaConverter-DJvodiHj.mjs → schemaConverter-Crjvczi_.mjs} +70 -17
  182. package/dist/{schemaIR-Ca7ySNPx.mjs → schemaIR-CnyKK_1j.mjs} +2 -1
  183. package/dist/schemas/index.d.mts +1 -0
  184. package/dist/schemas/index.mjs +1 -0
  185. package/dist/scim/index.d.mts +1 -0
  186. package/dist/scim/index.mjs +2 -1
  187. package/dist/scope/index.d.mts +3 -2
  188. package/dist/scope/index.mjs +5 -4
  189. package/dist/{scope-DfaPntpo.mjs → scope-afz_Ieek.mjs} +4 -3
  190. package/dist/{sessionManager-BHOM3N_0.d.mts → sessionManager-qimlKV0P.d.mts} +1 -0
  191. package/dist/{simpleEqualityMatcher-Cg05HPsn.mjs → simpleEqualityMatcher-C4KiMWUa.mjs} +1 -0
  192. package/dist/{sse-BQ1w0dfl.mjs → sse-B9P4Y-UI.mjs} +7 -5
  193. package/dist/{sseStream-BQ7Qaynp.mjs → sseStream-B3zb_d1h.mjs} +2 -1
  194. package/dist/{storage-DLUZ04kK.d.mts → storage-Cx9Sz3Ou.d.mts} +1 -0
  195. package/dist/{store-helpers-DY6xq4sM.mjs → store-helpers-DmEMHlPQ.mjs} +1 -0
  196. package/dist/{streaming-BQcW6_Kq.mjs → streaming-DPZdQmDz.mjs} +1 -0
  197. package/dist/{subscribe-helpers-DfzsivM6.mjs → subscribe-helpers-sp5xTDVA.mjs} +2 -1
  198. package/dist/sync/changelog.d.mts +1 -0
  199. package/dist/sync/changelog.mjs +1 -0
  200. package/dist/testing/cleanupStoreContract.d.mts +2 -1
  201. package/dist/testing/cleanupStoreContract.mjs +10 -5
  202. package/dist/testing/index.d.mts +166 -12
  203. package/dist/testing/index.mjs +315 -43
  204. package/dist/testing/outboxStoreContract.d.mts +12 -2
  205. package/dist/testing/outboxStoreContract.mjs +110 -20
  206. package/dist/testing/storageContract.d.mts +2 -1
  207. package/dist/testing/storageContract.mjs +11 -5
  208. package/dist/{tracing-CsGKQJGg.d.mts → tracing-Dro5eH6j.d.mts} +1 -0
  209. package/dist/{transactionContext-PNdoyLLm.mjs → transactionContext-BvLKvOIL.mjs} +1 -0
  210. package/dist/{typeGuards-C9KXUly6.mjs → typeGuards-B_5-hKjJ.mjs} +1 -0
  211. package/dist/types/index.d.mts +6 -5
  212. package/dist/types/index.mjs +1 -0
  213. package/dist/types/storage.d.mts +2 -1
  214. package/dist/types/storage.mjs +1 -0
  215. package/dist/{types-ChvvVNP8.d.mts → types-B7XeLEgK.d.mts} +34 -2
  216. package/dist/{types-Cc91nXuA.d.mts → types-ByHn9rEO.d.mts} +1 -0
  217. package/dist/{types-C_ZZRcD6.d.mts → types-C4QE8qnm.d.mts} +1 -0
  218. package/dist/{types-D_n8L6VY.d.mts → types-CT5vu6M0.d.mts} +132 -17
  219. package/dist/{types-DjC-KUCz.d.mts → types-ChuShpCP.d.mts} +1 -0
  220. package/dist/{types-Bmmn-fO0.d.mts → types-CwcUQ610.d.mts} +2 -6
  221. package/dist/{types-CSyCxl2V.mjs → types-DXYX7dIR.mjs} +4 -3
  222. package/dist/usage/index.d.mts +3 -2
  223. package/dist/usage/index.mjs +0 -0
  224. package/dist/{userHelpers-Cg_y3fBz.mjs → userHelpers-BNsOXzOd.mjs} +1 -0
  225. package/dist/utils/index.d.mts +16 -7
  226. package/dist/utils/index.mjs +10 -9
  227. package/dist/{utils-taUVD4p3.mjs → utils-BtOha_Sp.mjs} +3 -2
  228. package/dist/{validate-Bk44F2yT.mjs → validate-PMCPR9El.mjs} +2 -1
  229. package/dist/{versioning-gKWyryT3.mjs → versioning-CKv2jz_U.mjs} +4 -3
  230. package/dist/{versioning-DXgY5BUm.d.mts → versioning-D_rhHfZm.d.mts} +5 -2
  231. package/dist/{websocket-_Pd0CgR0.d.mts → websocket-BOXVggMf.d.mts} +2 -1
  232. package/package.json +557 -539
  233. package/skills/arc/SKILL.md +22 -8
  234. package/skills/arc/references/api-reference.md +4 -0
  235. package/skills/arc/references/auth.md +3 -0
  236. package/skills/arc/references/integrations.md +33 -0
  237. package/skills/arc/references/mcp.md +6 -7
  238. package/skills/arc/references/production.md +24 -25
  239. package/skills/arc-code-review/references/anti-patterns.md +3 -3
  240. package/dist/fastify-augmentation-0WhPnUH7.d.mts +0 -76
  241. package/dist/index-CCzVR-N3.d.mts +0 -107
  242. package/dist/module-_-M7C5ES.mjs +0 -29
@@ -1,10 +1,11 @@
1
- import { a as QueryCacheConfig } from "./QueryCache-DOMT_iq7.mjs";
2
- import { P as ArcHeaders, i as RequestScope } from "./types-DjC-KUCz.mjs";
3
- import { a as UserBase, l as AnyRecord, r as PermissionCheck } from "./types-ChvvVNP8.mjs";
4
- import "./elevation-C9s5hFP_.mjs";
5
- import { n as FieldPermissionMap } from "./fields-D3lhgzhD.mjs";
6
- import { n as EncryptionDirective } from "./types-Cc91nXuA.mjs";
7
- import { n as DomainEvent } from "./EventTransport-QmY7A258.mjs";
1
+
2
+ import { a as QueryCacheConfig } from "./QueryCache-DFA-QrU9.mjs";
3
+ import { P as ArcHeaders, i as RequestScope } from "./types-ChuShpCP.mjs";
4
+ import { a as UserBase, l as AnyRecord, r as PermissionCheck } from "./types-B7XeLEgK.mjs";
5
+ import "./elevation-BXCfVcNG.mjs";
6
+ import { n as FieldPermissionMap } from "./fields-I_EeRWND.mjs";
7
+ import { n as EncryptionDirective } from "./types-ByHn9rEO.mjs";
8
+ import { n as DomainEvent } from "./EventTransport-2uVV34WU.mjs";
8
9
  import { Filter } from "@classytic/repo-core/filter";
9
10
  import { KeysetPaginationResult, OffsetPaginationResult } from "@classytic/repo-core/pagination";
10
11
  import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest, RouteHandlerMethod, RouteHandlerMethod as RouteHandlerMethod$1 } from "fastify";
@@ -1238,11 +1239,27 @@ interface AuthPluginOptions {
1238
1239
  strictTokenType?: boolean;
1239
1240
  }
1240
1241
  //#endregion
1242
+ //#region src/core/middlewares/rateLimit.d.ts
1243
+ /**
1244
+ * Per-route CORS override, read by `@fastify/cors` off `routeOptions.config.cors`.
1245
+ *
1246
+ * The app-wide policy cannot serve both an API and public assets: an API wants
1247
+ * `credentials: true` with a pinned origin list, while a public asset wants
1248
+ * `origin: "*"` — and `*` with credentials is forbidden by the CORS spec (arc
1249
+ * throws at boot on that combination). Per-route is the granularity that
1250
+ * resolves it. `false` disables CORS for the route entirely.
1251
+ *
1252
+ * Arc does not interpret the value; `@fastify/cors` owns the semantics. Typed
1253
+ * loosely on purpose so a host is never blocked by arc lagging the plugin's
1254
+ * option surface.
1255
+ */
1256
+ type RouteCorsConfig = Record<string, unknown> | false;
1257
+ //#endregion
1241
1258
  //#region src/types/handlers.d.ts
1242
1259
  /**
1243
1260
  * Minimal server accessor — exposes safe, read-only server decorators.
1244
1261
  * Allows controller handlers to publish events, log, and audit
1245
- * without switching to `raw: true`.
1262
+ * without switching to `rawHandler`.
1246
1263
  */
1247
1264
  interface ServerAccessor {
1248
1265
  /** Event bus — publish domain events from any handler */
@@ -1396,7 +1413,7 @@ interface IRequestContext<TBody = unknown, TParams extends Record<string, string
1396
1413
  metadata?: TMetadata;
1397
1414
  /**
1398
1415
  * Fastify server accessor — publish events, log, and audit
1399
- * from any handler without switching to `raw: true`.
1416
+ * from any handler without switching to `rawHandler`.
1400
1417
  *
1401
1418
  * @example
1402
1419
  * ```typescript
@@ -1431,7 +1448,7 @@ interface IControllerResponse<T = unknown> {
1431
1448
  * Controller handler — Arc's standard pattern.
1432
1449
  *
1433
1450
  * Receives a request context object, returns IControllerResponse.
1434
- * Use with `raw: false` in routes.
1451
+ * Use with `handler` in routes.
1435
1452
  *
1436
1453
  * **Generic parameters:**
1437
1454
  * - `TResponse` — shape of `IControllerResponse.data` (default: `unknown`)
@@ -1468,7 +1485,6 @@ interface IControllerResponse<T = unknown> {
1468
1485
  * path: '/products',
1469
1486
  * handler: createProduct,
1470
1487
  * permissions: requireAuth(),
1471
- * raw: false, // Arc wraps this into Fastify handler
1472
1488
  * }]
1473
1489
  * ```
1474
1490
  */
@@ -1477,7 +1493,7 @@ type ControllerHandler<TResponse = unknown, TBody = unknown, TParams extends Rec
1477
1493
  * Fastify native handler
1478
1494
  *
1479
1495
  * Standard Fastify request/reply pattern.
1480
- * Use with `raw: true` in routes.
1496
+ * Use with `rawHandler` in routes.
1481
1497
  *
1482
1498
  * @example
1483
1499
  * ```typescript
@@ -1490,12 +1506,31 @@ type ControllerHandler<TResponse = unknown, TBody = unknown, TParams extends Rec
1490
1506
  * routes: [{
1491
1507
  * method: 'GET',
1492
1508
  * path: '/files/:id/download',
1493
- * handler: downloadFile,
1509
+ * rawHandler: downloadFile,
1494
1510
  * permissions: requireAuth(),
1495
- * raw: true, // Use as-is, no wrapping
1496
1511
  * }]
1497
1512
  * ```
1498
1513
  */
1514
+ type RawRouteHandler = {
1515
+ /**
1516
+ * Fastify-native route handler — the type behind `RouteDefinition.rawHandler`.
1517
+ *
1518
+ * Declared with METHOD syntax and read back through an indexed access, which
1519
+ * buys two properties a plain arrow alias can't have at once:
1520
+ *
1521
+ * - **Bivariant parameters.** `strictFunctionTypes` exempts method
1522
+ * declarations, so a handler annotated `FastifyRequest<{ Body: CreateBody }>`
1523
+ * assigns without a cast. Fastify's own `RouteHandlerMethod` is an arrow
1524
+ * alias, so it rejects those — hosts used to write `as any`.
1525
+ * - **One call signature.** TypeScript contextually types parameters only
1526
+ * when a single constituent is callable, so inline
1527
+ * `rawHandler: async (request, reply) => …` infers instead of reporting
1528
+ * TS7006.
1529
+ *
1530
+ * The runtime always passes the real `(request, reply)` pair.
1531
+ */
1532
+ handler(this: FastifyInstance, request: FastifyRequest, reply: FastifyReply): unknown;
1533
+ }["handler"];
1499
1534
  type FastifyHandler<RouteGeneric extends Record<string, unknown> = Record<string, unknown>> = (request: FastifyRequest<RouteGeneric>, reply: FastifyReply) => Promise<unknown> | unknown;
1500
1535
  /**
1501
1536
  * Union type for route handlers
@@ -1574,7 +1609,7 @@ interface RouteMcpConfig {
1574
1609
  *
1575
1610
  * - `handler: 'string'` → controller method → full Arc pipeline + MCP tool
1576
1611
  * - `handler: function` → inline handler → full Arc pipeline + MCP tool
1577
- * - `raw: true` → raw Fastify handler → no pipeline, no MCP by default
1612
+ * - `rawHandler` → raw Fastify handler → no pipeline, no MCP by default
1578
1613
  */
1579
1614
  interface RouteDefinition {
1580
1615
  readonly method: RouteMethod;
@@ -1583,14 +1618,14 @@ interface RouteDefinition {
1583
1618
  /**
1584
1619
  * Route handler.
1585
1620
  * - String: controller method name (Arc pipeline) — runtime lookup, no TS coverage on typos.
1586
- * - Function without `raw: true`: receives IRequestContext, returns IControllerResponse (Arc pipeline)
1587
- * - Function with `raw: true`: raw Fastify handler `(request, reply)`
1621
+ * - Function: receives IRequestContext, returns IControllerResponse (Arc pipeline)
1622
+ * - For a raw Fastify handler `(request, reply)`, use {@link rawHandler}
1588
1623
  *
1589
1624
  * Prefer `controllerMethod` (2.16) over the string form when you want the
1590
1625
  * compiler to catch typos. `handler` stays optional when `controllerMethod`
1591
1626
  * is set — exactly one of the two must be declared.
1592
1627
  */
1593
- readonly handler?: string | ControllerHandler | RouteHandlerMethod | ((request: never, reply: never) => unknown);
1628
+ readonly handler?: string | ControllerHandler;
1594
1629
  /**
1595
1630
  * Typed function-reference handler (2.16). Receives the live controller
1596
1631
  * instance and returns the method to invoke — TypeScript catches typos
@@ -1602,11 +1637,15 @@ interface RouteDefinition {
1602
1637
  * handlers go through), so there's no per-request lookup overhead.
1603
1638
  * The returned method is bound to the controller before dispatch.
1604
1639
  *
1640
+ * PIPELINE-ONLY: the referenced method is invoked as a `ControllerHandler`
1641
+ * (one `IRequestContext`), because the router derives "is this raw?" from
1642
+ * {@link rawHandler} alone and this field is mutually exclusive with it.
1643
+ * There is no flag that could make a `controllerMethod` route raw. For a
1644
+ * Fastify-native controller method, put its NAME in `rawHandler` — the
1645
+ * lookup is the same, and the field states the calling convention.
1646
+ *
1605
1647
  * Mutually exclusive with `handler` — passing both throws at boot
1606
- * with a clear "pick one" message. The runtime contract on what the
1607
- * returned function accepts mirrors the `handler` rules: a plain
1608
- * `ControllerHandler` for pipeline routes, a raw Fastify handler when
1609
- * the route is `raw: true`.
1648
+ * with a clear "pick one" message.
1610
1649
  *
1611
1650
  * Typed loosely (`(controller: unknown) => …`) at the type-system
1612
1651
  * boundary because `RouteDefinition` is not generic over the
@@ -1630,14 +1669,33 @@ interface RouteDefinition {
1630
1669
  * });
1631
1670
  * ```
1632
1671
  */
1633
- readonly controllerMethod?: (controller: unknown) => ControllerHandler | RouteHandlerMethod;
1672
+ readonly controllerMethod?: (controller: unknown) => ControllerHandler;
1634
1673
  /** Permission check — REQUIRED */
1635
1674
  readonly permissions: PermissionCheck;
1636
1675
  /**
1637
- * Raw mode — bypasses Arc pipeline. Handler receives raw Fastify
1638
- * request/reply. Default: false.
1639
- */
1640
- readonly raw?: boolean;
1676
+ * Fastify-native handler — receives `(request, reply)` and owns the response.
1677
+ * Bypasses arc's pipeline entirely: no `IControllerResponse` shaping, no
1678
+ * field-write sanitization.
1679
+ *
1680
+ * Mutually exclusive with {@link handler}. The FIELD carries the intent, so
1681
+ * there is no flag to forget: the previous `raw: boolean` let a Fastify-shaped
1682
+ * function sit in `handler` without it (silently run through the pipeline) or
1683
+ * a pipeline handler sit there with it (silently unwrapped), and neither
1684
+ * mismatch was a type error.
1685
+ *
1686
+ * Splitting the two also restores inference. One field carrying both shapes
1687
+ * meant a union of several function types, which has no single contextual
1688
+ * signature — so an inline `handler: async (req) => …` reported TS7006 and
1689
+ * every author annotated `req` by hand. Fastify types its own
1690
+ * `RouteOptions.handler` as ONE function type for exactly this reason; see
1691
+ * {@link RawRouteHandler} for why arc declares its own rather than reusing
1692
+ * `RouteHandlerMethod` directly.
1693
+ *
1694
+ * Accepts a controller-method NAME as well, same as {@link handler} — the
1695
+ * lookup is identical and only the calling convention differs, so a
1696
+ * Fastify-native controller method stays reachable by name.
1697
+ */
1698
+ readonly rawHandler?: string | RawRouteHandler;
1641
1699
  /** Logical operation name (pipeline keys, MCP tool naming). */
1642
1700
  readonly operation?: string;
1643
1701
  /** OpenAPI summary */
@@ -1669,7 +1727,8 @@ interface RouteDefinition {
1669
1727
  */
1670
1728
  readonly tenantScope?: boolean;
1671
1729
  /**
1672
- * SSE streaming mode. Two handler shapes work:
1730
+ * SSE streaming mode. Requires {@link rawHandler} — the handler is invoked
1731
+ * with `(request, reply)` and owns the response. Two shapes work:
1673
1732
  *
1674
1733
  * - Write to `reply.raw` directly (NDJSON, custom SSE — historical contract).
1675
1734
  * - Return a Web `ReadableStream` (Vercel AI SDK's `result.toUIMessageStream()`,
@@ -1700,7 +1759,7 @@ interface RouteDefinition {
1700
1759
  * `onFieldWriteDenied: 'reject' | 'strip'` setting governs how denials
1701
1760
  * are surfaced.
1702
1761
  *
1703
- * `raw: true` routes ALWAYS bypass this — they've opted out of the
1762
+ * `rawHandler` routes ALWAYS bypass this — they've opted out of the
1704
1763
  * pipeline entirely.
1705
1764
  */
1706
1765
  readonly fieldWrite?: boolean;
@@ -1723,6 +1782,22 @@ interface RouteDefinition {
1723
1782
  * it to a dedicated `routes:` entry, or rely on the resource-level limit.
1724
1783
  */
1725
1784
  readonly rateLimit?: RateLimitConfig | false;
1785
+ /**
1786
+ * Per-route CORS override, forwarded to `@fastify/cors` as
1787
+ * `routeOptions.config.cors`. `undefined` inherits the app policy; `false`
1788
+ * disables CORS for this route; an object replaces the app policy for it.
1789
+ *
1790
+ * Needed because one app-wide policy cannot serve both an API and a public
1791
+ * asset: an API wants `credentials: true` with a pinned origin list, a public
1792
+ * asset wants `origin: "*"`, and `*` + credentials is forbidden by the spec
1793
+ * (arc throws at boot on that pair).
1794
+ *
1795
+ * ```ts
1796
+ * { method: "GET", path: "/manifest.json", permissions: allowPublic(),
1797
+ * cors: { origin: "*", credentials: false }, handler }
1798
+ * ```
1799
+ */
1800
+ readonly cors?: RouteCorsConfig;
1726
1801
  /**
1727
1802
  * Fastify route schema. Each slot (`body`, `querystring`, `params`,
1728
1803
  * `headers`, `response[status]`) accepts a plain JSON Schema object
@@ -2829,7 +2904,7 @@ interface ResourceConfig<TDoc = AnyRecord> {
2829
2904
  * object, primitive) is supported via auto-envelope (2.17+) but the
2830
2905
  * explicit envelope is the canonical contract — declared `fields:`
2831
2906
  * permissions, custom `status`, `meta`, and `headers` only work when
2832
- * you return the envelope. Set `raw: true` on a route to opt out of
2907
+ * you return the envelope. Declare a route's function via `rawHandler` to opt out of
2833
2908
  * arc's pipeline entirely (custom streaming, SSE, manual `reply.send()`).
2834
2909
  *
2835
2910
  * **Path collisions with auto-CRUD are detected at `defineResource()` time.**
@@ -2844,7 +2919,7 @@ interface ResourceConfig<TDoc = AnyRecord> {
2844
2919
  * ```typescript
2845
2920
  * routes: [
2846
2921
  * { method: 'GET', path: '/stats', handler: 'getStats', permissions: auth() },
2847
- * { method: 'POST', path: '/webhook', handler: webhookFn, raw: true, permissions: auth() },
2922
+ * { method: 'POST', path: '/webhook', rawHandler: webhookFn, permissions: auth() },
2848
2923
  * ]
2849
2924
  * ```
2850
2925
  *
@@ -4220,4 +4295,4 @@ interface ValidateOptions {
4220
4295
  strict?: boolean;
4221
4296
  }
4222
4297
  //#endregion
4223
- export { OpenApiSchemas as $, SlugExt as $t, RequestIdOptions as A, ControllerConfigurableOptions as An, RouteDefinition as At, defineResource as B, RouteHandler as Bt, RequestContext as C, defineHook as Cn, PipelineStep as Ct, HealthCheck as D, ArcListResult as Dn, ActionEntry as Dt, GracefulShutdownOptions as E, ArcGetResult as En, ActionDefinition as Et, FastifyWithDecorators as F, ControllerLike as Ft, OnTenantDeleteConfig as G, AuthenticatorContext as Gt, CrudController as H, AuthHelpers as Ht, MiddlewareHandler as I, FastifyHandler as It, PresetHook as J, BaseController as Jt, ResolvedTenantPurge as K, JwtContext as Kt, RequestWithExtras as L, IController as Lt, EventsDecorator as M, ListResult as Mn, RouteMethod as Mt, FastifyRequestExtras as N, BodySanitizer as Nn, RateLimitConfig as Nt, HealthOptions as O, ArcUpdateResult as On, ActionHandlerFn as Ot, FastifyWithAuth as P, BodySanitizerConfig as Pn, ControllerHandler as Pt, MiddlewareConfig as Q, TreeMixin as Qt, RegisterOptions as R, IControllerResponse as Rt, QueryParserInterface as S, createHookSystem as Sn, PipelineContext as St, CrudRouterOptions as T, ArcDeleteResult as Tn, ResourceCacheConfig as Tt, ResourceConfig as U, AuthPluginOptions as Ut, ResourceDefinition as V, ServerAccessor as Vt, ResourcePermissions as W, Authenticator as Wt, CrudRouteKey as X, SoftDeleteMixin as Xt, PresetResult as Y, SoftDeleteExt as Yt, CrudSchemas as Z, TreeExt as Zt, ControllerQueryOptions as _, afterDelete as _n, Guard as _t, InferAdapterDoc as a, QueryResolverConfig as an, ResourceExtensions as at, ParsedQuery as b, beforeDelete as bn, OperationFilter as bt, TypedController as c, DefineHookOptions as cn, AggMeasureShorthand as ct, PaginationResult as d, HookOperation as dn, AggregationDateRangeRequirement as dt, SlugMixin as en, RouteSchemaOptions as et, IntrospectionData as f, HookPhase as fn, AggregationIndexHint as ft, ArcInternalMetadata as g, afterCreate as gn, AggregationsMap as gt, ResourceMetadata as h, HookSystemOptions as hn, AggregationRateLimit as ht, ValidationResult as i, QueryResolver as in, ResourceHooks as it, ArcDecorator as j, ControllerConstructionOptions as jn, RouteMcpConfig as jt, IntrospectionPluginOptions as k, BaseControllerOptions as kn, ActionsMap as kt, TypedRepository as l, HookContext as ln, AggregationCacheConfig as lt, RegistryStats as m, HookSystem as mn, AggregationMaterializedResult as mt, ConfigError as n, BulkMixin as nn, FieldRule$1 as nt, InferDocType as o, AccessControl as on, EventDefinition as ot, RegistryEntry as p, HookRegistration as pn, AggregationMaterializedContext as pt, PresetFunction as q, TokenPair as qt, ValidateOptions as r, BaseCrudController as rn, ResourceHookContext as rt, InferResourceDoc as s, AccessControlConfig as sn, AggMeasureInput as st, RouteHandlerMethod$1 as t, BulkExt as tn, ArcFieldRule as tt, TypedResourceConfig as u, HookHandler as un, AggregationConfig as ut, LookupOption as v, afterUpdate as vn, Interceptor as vt, ServiceContext as w, ArcCreateResult as wn, Transform as wt, PopulateOption as x, beforeUpdate as xn, PipelineConfig as xt, OwnershipCheck as y, beforeCreate as yn, NextFunction as yt, ResourceRegistry as z, IRequestContext as zt };
4298
+ export { OpenApiSchemas as $, TreeMixin as $t, RequestIdOptions as A, BaseControllerOptions as An, RouteDefinition as At, defineResource as B, RawRouteHandler as Bt, RequestContext as C, createHookSystem as Cn, PipelineStep as Ct, HealthCheck as D, ArcGetResult as Dn, ActionEntry as Dt, GracefulShutdownOptions as E, ArcDeleteResult as En, ActionDefinition as Et, FastifyWithDecorators as F, BodySanitizerConfig as Fn, ControllerLike as Ft, OnTenantDeleteConfig as G, Authenticator as Gt, CrudController as H, ServerAccessor as Ht, MiddlewareHandler as I, FastifyHandler as It, PresetHook as J, TokenPair as Jt, ResolvedTenantPurge as K, AuthenticatorContext as Kt, RequestWithExtras as L, IController as Lt, EventsDecorator as M, ControllerConstructionOptions as Mn, RouteMethod as Mt, FastifyRequestExtras as N, ListResult as Nn, RateLimitConfig as Nt, HealthOptions as O, ArcListResult as On, ActionHandlerFn as Ot, FastifyWithAuth as P, BodySanitizer as Pn, ControllerHandler as Pt, MiddlewareConfig as Q, TreeExt as Qt, RegisterOptions as R, IControllerResponse as Rt, QueryParserInterface as S, beforeUpdate as Sn, PipelineContext as St, CrudRouterOptions as T, ArcCreateResult as Tn, ResourceCacheConfig as Tt, ResourceConfig as U, AuthHelpers as Ut, ResourceDefinition as V, RouteHandler as Vt, ResourcePermissions as W, AuthPluginOptions as Wt, CrudRouteKey as X, SoftDeleteExt as Xt, PresetResult as Y, BaseController as Yt, CrudSchemas as Z, SoftDeleteMixin as Zt, ControllerQueryOptions as _, afterCreate as _n, Guard as _t, InferAdapterDoc as a, QueryResolver as an, ResourceExtensions as at, ParsedQuery as b, beforeCreate as bn, OperationFilter as bt, TypedController as c, AccessControlConfig as cn, AggMeasureShorthand as ct, PaginationResult as d, HookHandler as dn, AggregationDateRangeRequirement as dt, SlugExt as en, RouteSchemaOptions as et, IntrospectionData as f, HookOperation as fn, AggregationIndexHint as ft, ArcInternalMetadata as g, HookSystemOptions as gn, AggregationsMap as gt, ResourceMetadata as h, HookSystem as hn, AggregationRateLimit as ht, ValidationResult as i, BaseCrudController as in, ResourceHooks as it, ArcDecorator as j, ControllerConfigurableOptions as jn, RouteMcpConfig as jt, IntrospectionPluginOptions as k, ArcUpdateResult as kn, ActionsMap as kt, TypedRepository as l, DefineHookOptions as ln, AggregationCacheConfig as lt, RegistryStats as m, HookRegistration as mn, AggregationMaterializedResult as mt, ConfigError as n, BulkExt as nn, FieldRule$1 as nt, InferDocType as o, QueryResolverConfig as on, EventDefinition as ot, RegistryEntry as p, HookPhase as pn, AggregationMaterializedContext as pt, PresetFunction as q, JwtContext as qt, ValidateOptions as r, BulkMixin as rn, ResourceHookContext as rt, InferResourceDoc as s, AccessControl as sn, AggMeasureInput as st, RouteHandlerMethod$1 as t, SlugMixin as tn, ArcFieldRule as tt, TypedResourceConfig as u, HookContext as un, AggregationConfig as ut, LookupOption as v, afterDelete as vn, Interceptor as vt, ServiceContext as w, defineHook as wn, Transform as wt, PopulateOption as x, beforeDelete as xn, PipelineConfig as xt, OwnershipCheck as y, afterUpdate as yn, NextFunction as yt, ResourceRegistry as z, IRequestContext as zt };
@@ -1,7 +1,8 @@
1
- import { C as RequestContext, Et as ActionDefinition, F as FastifyWithDecorators, H as CrudController, L as RequestWithExtras, Lt as IController, Rt as IControllerResponse, T as CrudRouterOptions, U as ResourceConfig, V as ResourceDefinition, et as RouteSchemaOptions, jt as RouteMcpConfig, tt as ArcFieldRule, ut as AggregationConfig, zt as IRequestContext } from "./index-Q5gzEIWY.mjs";
2
- import { i as RequestScope } from "./types-DjC-KUCz.mjs";
3
- import { l as AnyRecord, r as PermissionCheck } from "./types-ChvvVNP8.mjs";
4
- import "./fastify-augmentation-0WhPnUH7.mjs";
1
+
2
+ import { C as RequestContext, Et as ActionDefinition, F as FastifyWithDecorators, H as CrudController, L as RequestWithExtras, Lt as IController, Rt as IControllerResponse, T as CrudRouterOptions, U as ResourceConfig, V as ResourceDefinition, et as RouteSchemaOptions, jt as RouteMcpConfig, tt as ArcFieldRule, ut as AggregationConfig, zt as IRequestContext } from "./index-CpzxqePp.mjs";
3
+ import { i as RequestScope } from "./types-ChuShpCP.mjs";
4
+ import { l as AnyRecord, r as PermissionCheck } from "./types-B7XeLEgK.mjs";
5
+ import "./fastify-augmentation-BppG5bMT.mjs";
5
6
  import { FastifyReply, FastifyRequest, RouteHandlerMethod } from "fastify";
6
7
  import { z } from "zod";
7
8
  import { DataAdapter } from "@classytic/repo-core/adapter";
@@ -0,0 +1,290 @@
1
+
2
+ import { _ as HealthCheck, a as ModuleContribution, f as ScheduleDefinition, n as ArcModuleInput, r as ArcModuleRegistry, s as ModuleSetupContext, t as ArcModule } from "./types-CT5vu6M0.mjs";
3
+ import { FastifyInstance } from "fastify";
4
+ //#region src/factory/module/contributions.d.ts
5
+ /**
6
+ * Collect every module's `healthChecks` in the caller's order. Fails at boot
7
+ * on a duplicate check `name` across modules, naming BOTH owning modules.
8
+ * The host's app-level checks are appended AFTER this (modules-first,
9
+ * host-last) by the caller.
10
+ */
11
+ declare function collectModuleHealthChecks(modules: readonly ArcModule[]): HealthCheck[];
12
+ /**
13
+ * Collect every module's `workflows`. Resolves factory contributions (so a
14
+ * factory can close over a container the caller has already decorated on
15
+ * `fastify`) and flattens to a single opaque array. Arc core deliberately
16
+ * does NOT validate or interpret the values — the streamline integration
17
+ * owns name/shape checks and registration. Called by the integration at init
18
+ * time, not by arc's boot pipeline (workflows depend on the integration's
19
+ * container).
20
+ */
21
+ declare function collectModuleWorkflows(fastify: FastifyInstance, modules: readonly ArcModule[]): Promise<unknown[]>;
22
+ /**
23
+ * Collect every module's `scheduledJobs`. Resolves factory contributions
24
+ * (after bootstraps) and fails at boot on a duplicate job `name` across
25
+ * modules. The caller passes the returned definitions to the canonical
26
+ * schedules plugin; factories must therefore be resolved only once.
27
+ */
28
+ declare function collectModuleScheduledJobs(fastify: FastifyInstance, modules: readonly ArcModule[],
29
+ /**
30
+ * Optional sink for per-module counts, filled as each arm resolves.
31
+ *
32
+ * Exists so `arc.moduleDescriptors` can report real numbers without
33
+ * resolving the factories a SECOND time — a contribution factory closes over
34
+ * booted engines and may register or allocate, so running it twice is not a
35
+ * free read. One resolution feeds both activation and introspection.
36
+ */
37
+ countsByModule?: Map<string, number>): Promise<ScheduleDefinition[]>;
38
+ //#endregion
39
+ //#region src/factory/module/extend.d.ts
40
+ /**
41
+ * What a caller may add. Every mergeable arm of `ArcModule`, plus `bootstrap`
42
+ * in wrapper form only.
43
+ *
44
+ * `name` is absent on purpose: renaming a module mid-composition breaks the
45
+ * `dependsOn` graph and the registry key its consumers read, and it is the one
46
+ * "extension" that is never additive.
47
+ */
48
+ interface ModuleExtension<TExports = unknown> {
49
+ dependsOn?: readonly string[];
50
+ owns?: readonly string[] | "provided";
51
+ resources?: ArcModule<TExports>["resources"];
52
+ eventHandlers?: ArcModule<TExports>["eventHandlers"];
53
+ scheduledJobs?: ArcModule<TExports>["scheduledJobs"];
54
+ workflows?: ArcModule<TExports>["workflows"];
55
+ healthChecks?: ArcModule<TExports>["healthChecks"];
56
+ errorMappers?: ArcModule<TExports>["errorMappers"];
57
+ plugins?: ArcModule<TExports>["plugins"];
58
+ afterResources?: ArcModule<TExports>["afterResources"];
59
+ onClose?: ArcModule<TExports>["onClose"];
60
+ /**
61
+ * WRAP the module's bootstrap — it is never replaced.
62
+ *
63
+ * Bootstrap returns the module's exports, so two of them cannot be
64
+ * concatenated: one value has to win, and a host silently winning is the gym
65
+ * failure (`{ ...mod, bootstrap }` overwrote the factory's own, so the engine
66
+ * the module published was never created). The wrapper form makes the
67
+ * relationship explicit — call `inner` and decorate its result, or
68
+ * deliberately do not.
69
+ *
70
+ * `inner` is `undefined` when the module has no bootstrap of its own.
71
+ */
72
+ bootstrap?: (inner: ((f: FastifyInstance, c: ModuleSetupContext) => TExports | Promise<TExports>) | undefined) => (f: FastifyInstance, c: ModuleSetupContext) => TExports | Promise<TExports>;
73
+ }
74
+ /**
75
+ * Merge a host's additions onto a module. Nothing the module declared is lost.
76
+ *
77
+ * ```ts
78
+ * return extendModule(createOrderModule({ … }), {
79
+ * eventHandlers: () => hostHandlers(), // appended after the module's
80
+ * dependsOn: ["outbox"], // unioned
81
+ * bootstrap: (inner) => async (f, c) => { // wraps, never replaces
82
+ * const exports = await inner?.(f, c);
83
+ * return decorate(exports);
84
+ * },
85
+ * });
86
+ * ```
87
+ */
88
+ declare function extendModule<TExports = unknown>(mod: ArcModule<TExports>, extension: ModuleExtension<TExports>): ArcModule<TExports>;
89
+ //#endregion
90
+ //#region src/factory/module/lifecycle.d.ts
91
+ /**
92
+ * Subscribe every module's `eventHandlers` in dependency order (pass the
93
+ * `orderModules`-sorted list). Returns the ordered list of unsubscribe
94
+ * functions so the caller can tear them down at shutdown BEFORE module
95
+ * `onClose` (while module deps are still alive). Fails at boot on:
96
+ * - a duplicate NAMED handler across modules (attributing both owners);
97
+ * - a module declaring handlers while the event subsystem is unavailable.
98
+ * Resolves factory contributions (after bootstraps) so a handler can close over
99
+ * booted engines rather than a global getter.
100
+ */
101
+ declare function subscribeModuleEventHandlers(fastify: FastifyInstance, modules: readonly ArcModule[],
102
+ /**
103
+ * Optional sink for per-module handler counts, filled as each arm resolves.
104
+ * Lets `arc.moduleDescriptors` report real numbers without resolving the
105
+ * factories a SECOND time — see the note on `collectModuleScheduledJobs`.
106
+ */
107
+ countsByModule?: Map<string, number>): Promise<Array<() => void | Promise<void>>>;
108
+ //#endregion
109
+ //#region src/factory/module/order.d.ts
110
+ /**
111
+ * Order modules for composition by their `dependsOn` edges — a STABLE
112
+ * topological sort. Called once at the start of the bootstrap phase; every
113
+ * subsequent phase (bootstrap, resources, afterResources, and reverse-order
114
+ * onClose) iterates the returned list, so a module's declared dependencies are
115
+ * always composed before it.
116
+ *
117
+ * "Stable" = modules with no edge between them keep their original list order,
118
+ * so declaring `dependsOn` on one module never silently reorders an unrelated
119
+ * one. Backward compatible: a `modules` array with NO `dependsOn` anywhere is
120
+ * returned unchanged.
121
+ *
122
+ * Fail-fast — throws (never reorders past a broken contract) on:
123
+ * - duplicate module names (the name is the graph key)
124
+ * - a `dependsOn` name not present in the composed set
125
+ * - a self-reference (`dependsOn` includes the module's own name)
126
+ * - a dependency cycle (reports the concrete `a → b → … → a` path)
127
+ */
128
+ declare function orderModules(modules: readonly ArcModule[]): ArcModule[];
129
+ //#endregion
130
+ //#region src/factory/module/resolve.d.ts
131
+ /**
132
+ * Resolve any module-input form to a concrete `ArcModule`. A thunk is invoked
133
+ * (this is where a dynamic `import()` fires); a promise (or plain module) is
134
+ * awaited. Called once per module at the start of the bootstrap phase.
135
+ */
136
+ declare function resolveModule(input: ArcModuleInput): Promise<ArcModule>;
137
+ /** Resolve a `ModuleContribution` to a concrete array (array passthrough or factory call). */
138
+ declare function resolveContribution<T>(contribution: ModuleContribution<T> | undefined, fastify: FastifyInstance): Promise<readonly T[]>;
139
+ //#endregion
140
+ //#region src/factory/module/state.d.ts
141
+ type ModuleState = "resolved" | "bootstrapping" | "ready" | "closing" | "closed" | "failed";
142
+ /**
143
+ * Is `name` in the composed module graph? TRUE for resource-only modules and
144
+ * modules that exported nothing — the question `hasModuleExports()` cannot
145
+ * answer. FALSE before registerResources runs (no graph yet) and for
146
+ * uncomposed names.
147
+ */
148
+ declare function hasModule(fastify: FastifyInstance, name: string): boolean;
149
+ /**
150
+ * The module's current lifecycle state, or `undefined` when the module is not
151
+ * composed (or no graph has been composed on this instance). See the state
152
+ * machine in the file header.
153
+ */
154
+ declare function getModuleState(fastify: FastifyInstance, name: string): ModuleState | undefined;
155
+ //#endregion
156
+ //#region src/factory/module/index.d.ts
157
+ /**
158
+ * Identity helper for authoring a typed module — mirrors `defineResource`.
159
+ * Gives inference + a single obvious construction site; does no work.
160
+ *
161
+ * `TExports` is inferred from the `bootstrap` return value, so a module
162
+ * author gets a typed public export for free:
163
+ *
164
+ * ```ts
165
+ * export const accountingModule = (deps: Deps) =>
166
+ * defineModule({
167
+ * name: "accounting",
168
+ * bootstrap: async () => createAccountingEngine(deps), // TExports inferred
169
+ * });
170
+ * ```
171
+ */
172
+ declare function defineModule<TExports = unknown>(module: ArcModule<TExports>): ArcModule<TExports>;
173
+ /**
174
+ * Typed accessor for a module's public export (its `bootstrap` return value),
175
+ * recorded at `fastify.arc.modules[name]`.
176
+ *
177
+ * Throwing, in line with the fail-fast contract (and `requireOrgId`-style
178
+ * accessors): a missing entry means the module either isn't composed, is
179
+ * composed AFTER the caller (list order = init order), or returned nothing —
180
+ * all wiring bugs that must surface at boot, not as `undefined` downstream.
181
+ *
182
+ * The type parameter is an assertion, not a proof. Two ways to type it:
183
+ * - augment `ArcModuleRegistry` once — then the name alone infers the type:
184
+ * `getModuleExports(f, "accounting")` → `AccountingEngine`.
185
+ * - or pass it inline: `getModuleExports<AccountingEngine>(f, "accounting")`.
186
+ *
187
+ * Siblings, for the two shapes this one is wrong for:
188
+ * - `getOptionalModuleExports` — the module is genuinely OPTIONAL.
189
+ * - `lazyModuleExports` / `lazyRequiredModuleExports` — the read happens at
190
+ * composition time, where boot order decides the answer.
191
+ */
192
+ declare function getModuleExports<K extends keyof ArcModuleRegistry>(fastify: FastifyInstance, name: K): ArcModuleRegistry[K];
193
+ declare function getModuleExports<TExports = unknown>(fastify: FastifyInstance, name: string): TExports;
194
+ /**
195
+ * Non-throwing sibling of `getModuleExports`: `undefined` when the module is
196
+ * not composed (or has not bootstrapped yet).
197
+ *
198
+ * Exists because OPTIONAL sibling modules are a first-class composition shape —
199
+ * a deployment that turns `inventory` off still sells services, so its POS
200
+ * module must ask "is inventory here?" rather than fail-fast. Hosts were
201
+ * spelling that question as
202
+ *
203
+ * ```ts
204
+ * (fastify as unknown as { arc?: { modules?: Record<string, unknown> } })
205
+ * .arc?.modules?.inventory;
206
+ * ```
207
+ *
208
+ * — a double cast that (a) defeats `ArcModuleRegistry` inference, (b) silently
209
+ * survives a typo in the module name, and (c) is impossible to grep for. Use
210
+ * `getModuleExports` when the dependency is REQUIRED (boot must fail), this
211
+ * when it is genuinely optional.
212
+ *
213
+ * Prefer `lazyModuleExports` whenever the read happens at COMPOSITION time —
214
+ * see its doc for why a value read once can latch `undefined` forever.
215
+ */
216
+ declare function getOptionalModuleExports<K extends keyof ArcModuleRegistry>(fastify: FastifyInstance, name: K): ArcModuleRegistry[K] | undefined;
217
+ declare function getOptionalModuleExports<TExports = unknown>(fastify: FastifyInstance, name: string): TExports | undefined;
218
+ /**
219
+ * Is a module's public export recorded yet? The predicate form of
220
+ * `getOptionalModuleExports`, for readiness gates (`ready: () => ...`) that
221
+ * should not have to reason about falsy-but-present exports.
222
+ */
223
+ declare function hasModuleExports(fastify: FastifyInstance, name: string): boolean;
224
+ /**
225
+ * A DEFERRED reader of a sibling module's export: returns a getter that reads
226
+ * the registry at CALL time, not now.
227
+ *
228
+ * ── Why this exists (the bug it removes) ─────────────────────────────────────
229
+ *
230
+ * Module composition runs bootstraps in dependency/list order, but a lot of
231
+ * wiring is *registered* earlier than it *runs*: an `eventHandlers` factory, a
232
+ * bridge accessor handed to another module, a hook added during bootstrap and
233
+ * fired per request. Such a factory can execute BEFORE the sibling it needs has
234
+ * bootstrapped — so a sibling engine captured into a local at that moment is
235
+ * `undefined`, and stays `undefined` for the life of the process even though the
236
+ * sibling came up milliseconds later.
237
+ *
238
+ * That failure is SILENT by construction: the consumer sees a null bridge and
239
+ * treats it as "this deployment has no inventory / no revenue engine", which is
240
+ * a legitimate configuration. Real cost in this codebase: orders were created
241
+ * and never payment-confirmed (no entitlement, no card, no door) and nothing
242
+ * errored anywhere.
243
+ *
244
+ * The getter therefore:
245
+ * - re-reads while the module is ABSENT, so boot order cannot matter;
246
+ * - memoizes the FIRST resolved value, so the steady-state read is a closure
247
+ * variable rather than a registry lookup per request;
248
+ * - never memoizes absence — that is precisely the latch this replaces.
249
+ *
250
+ * ```ts
251
+ * const inventory = lazyModuleExports<FlowEngine>(fastify, "inventory");
252
+ * return {
253
+ * flowBridge: () => (inventory() ? createFlowEngineBridge({ getFlowEngine: () => inventory()! }) : null),
254
+ * ready: () => inventory() !== undefined,
255
+ * };
256
+ * ```
257
+ */
258
+ declare function lazyModuleExports<K extends keyof ArcModuleRegistry>(fastify: FastifyInstance, name: K): () => ArcModuleRegistry[K] | undefined;
259
+ declare function lazyModuleExports<TExports = unknown>(fastify: FastifyInstance, name: string): () => TExports | undefined;
260
+ /**
261
+ * Required counterpart of `lazyModuleExports`: defers the read, then throws
262
+ * `getModuleExports`' error if the module is still absent at first use.
263
+ *
264
+ * The pair matters because "required" and "readable now" are different
265
+ * questions. A hook registered at bootstrap that needs the `order` engine at
266
+ * REQUEST time is a hard dependency, but reading it eagerly turns a correct
267
+ * composition into a boot crash purely because of list order. Deferring keeps
268
+ * the fail-fast guarantee and moves it to the first moment the answer is
269
+ * actually needed.
270
+ *
271
+ * Deferred does NOT mean unvalidated: a lazily-required module is still a
272
+ * HARD dependency, so PRESENCE is checked eagerly. When the composed module
273
+ * graph is known (any `createApp`/`registerResources` boot — the normal
274
+ * case), a name that is not in the graph throws HERE, at composition time,
275
+ * instead of surviving startup and failing on the first request or event.
276
+ * Only the EXPORT read (does bootstrap's return value exist yet?) is
277
+ * deferred to first call.
278
+ *
279
+ * Convention for hard sibling access: also declare the target in the
280
+ * consumer's `dependsOn`. That orders composition (the sibling's bootstrap
281
+ * runs first), while this accessor merely defers the read — the two are
282
+ * complementary, not alternatives:
283
+ * - hard dependency, read during bootstrap → `dependsOn` + `getModuleExports`
284
+ * - hard dependency, read at request/event time → `dependsOn` + this
285
+ * - optional integration → `lazyModuleExports` (no `dependsOn` needed)
286
+ */
287
+ declare function lazyRequiredModuleExports<K extends keyof ArcModuleRegistry>(fastify: FastifyInstance, name: K): () => ArcModuleRegistry[K];
288
+ declare function lazyRequiredModuleExports<TExports = unknown>(fastify: FastifyInstance, name: string): () => TExports;
289
+ //#endregion
290
+ export { collectModuleScheduledJobs as _, lazyModuleExports as a, getModuleState as c, resolveModule as d, orderModules as f, collectModuleHealthChecks as g, extendModule as h, hasModuleExports as i, hasModule as l, ModuleExtension as m, getModuleExports as n, lazyRequiredModuleExports as o, subscribeModuleEventHandlers as p, getOptionalModuleExports as r, ModuleState as s, defineModule as t, resolveContribution as u, collectModuleWorkflows as v };