@classytic/arc 1.1.0 → 2.1.2

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 (322) hide show
  1. package/README.md +247 -794
  2. package/bin/arc.js +91 -52
  3. package/dist/EventTransport-BD2U0BTc.d.mts +100 -0
  4. package/dist/EventTransport-BD2U0BTc.d.mts.map +1 -0
  5. package/dist/HookSystem-BsGV-j2l.mjs +405 -0
  6. package/dist/HookSystem-BsGV-j2l.mjs.map +1 -0
  7. package/dist/ResourceRegistry-DsN4KJjV.mjs +250 -0
  8. package/dist/ResourceRegistry-DsN4KJjV.mjs.map +1 -0
  9. package/dist/adapters/index.d.mts +5 -0
  10. package/dist/adapters/index.mjs +3 -0
  11. package/dist/audit/index.d.mts +82 -0
  12. package/dist/audit/index.d.mts.map +1 -0
  13. package/dist/audit/index.mjs +276 -0
  14. package/dist/audit/index.mjs.map +1 -0
  15. package/dist/audit/mongodb.d.mts +5 -0
  16. package/dist/audit/mongodb.mjs +3 -0
  17. package/dist/audited-C3T5DTUx.mjs +141 -0
  18. package/dist/audited-C3T5DTUx.mjs.map +1 -0
  19. package/dist/auth/index.d.mts +189 -0
  20. package/dist/auth/index.d.mts.map +1 -0
  21. package/dist/auth/index.mjs +1102 -0
  22. package/dist/auth/index.mjs.map +1 -0
  23. package/dist/auth/redis-session.d.mts +44 -0
  24. package/dist/auth/redis-session.d.mts.map +1 -0
  25. package/dist/auth/redis-session.mjs +76 -0
  26. package/dist/auth/redis-session.mjs.map +1 -0
  27. package/dist/betterAuthOpenApi-BrHKeSAx.mjs +250 -0
  28. package/dist/betterAuthOpenApi-BrHKeSAx.mjs.map +1 -0
  29. package/dist/cache/index.d.mts +146 -0
  30. package/dist/cache/index.d.mts.map +1 -0
  31. package/dist/cache/index.mjs +92 -0
  32. package/dist/cache/index.mjs.map +1 -0
  33. package/dist/caching-Bl28lYsR.mjs +94 -0
  34. package/dist/caching-Bl28lYsR.mjs.map +1 -0
  35. package/dist/chunk-C7Uep-_p.mjs +20 -0
  36. package/dist/circuitBreaker-DeY4FCjs.mjs +1097 -0
  37. package/dist/circuitBreaker-DeY4FCjs.mjs.map +1 -0
  38. package/dist/cli/commands/describe.d.mts +19 -0
  39. package/dist/cli/commands/describe.d.mts.map +1 -0
  40. package/dist/cli/commands/describe.mjs +239 -0
  41. package/dist/cli/commands/describe.mjs.map +1 -0
  42. package/dist/cli/commands/docs.d.mts +14 -0
  43. package/dist/cli/commands/docs.d.mts.map +1 -0
  44. package/dist/cli/commands/docs.mjs +53 -0
  45. package/dist/cli/commands/docs.mjs.map +1 -0
  46. package/dist/cli/commands/{generate.d.ts → generate.d.mts} +3 -1
  47. package/dist/cli/commands/generate.d.mts.map +1 -0
  48. package/dist/cli/commands/generate.mjs +358 -0
  49. package/dist/cli/commands/generate.mjs.map +1 -0
  50. package/dist/cli/commands/{init.d.ts → init.d.mts} +12 -8
  51. package/dist/cli/commands/init.d.mts.map +1 -0
  52. package/dist/cli/commands/{init.js → init.mjs} +807 -616
  53. package/dist/cli/commands/init.mjs.map +1 -0
  54. package/dist/cli/commands/introspect.d.mts +11 -0
  55. package/dist/cli/commands/introspect.d.mts.map +1 -0
  56. package/dist/cli/commands/introspect.mjs +76 -0
  57. package/dist/cli/commands/introspect.mjs.map +1 -0
  58. package/dist/cli/index.d.mts +17 -0
  59. package/dist/cli/index.d.mts.map +1 -0
  60. package/dist/cli/index.mjs +157 -0
  61. package/dist/cli/index.mjs.map +1 -0
  62. package/dist/constants-DdXFXQtN.mjs +85 -0
  63. package/dist/constants-DdXFXQtN.mjs.map +1 -0
  64. package/dist/core/index.d.mts +5 -0
  65. package/dist/core/index.mjs +4 -0
  66. package/dist/createApp-CUgNqegw.mjs +560 -0
  67. package/dist/createApp-CUgNqegw.mjs.map +1 -0
  68. package/dist/defineResource-k0_BDn8v.mjs +2197 -0
  69. package/dist/defineResource-k0_BDn8v.mjs.map +1 -0
  70. package/dist/discovery/index.d.mts +47 -0
  71. package/dist/discovery/index.d.mts.map +1 -0
  72. package/dist/discovery/index.mjs +110 -0
  73. package/dist/discovery/index.mjs.map +1 -0
  74. package/dist/docs/index.d.mts +163 -0
  75. package/dist/docs/index.d.mts.map +1 -0
  76. package/dist/docs/index.mjs +73 -0
  77. package/dist/docs/index.mjs.map +1 -0
  78. package/dist/elevation-BRy3yFWT.mjs +113 -0
  79. package/dist/elevation-BRy3yFWT.mjs.map +1 -0
  80. package/dist/elevation-B_2dRLVP.d.mts +88 -0
  81. package/dist/elevation-B_2dRLVP.d.mts.map +1 -0
  82. package/dist/errorHandler-BbcgBmIH.d.mts +73 -0
  83. package/dist/errorHandler-BbcgBmIH.d.mts.map +1 -0
  84. package/dist/errorHandler-C1okiriz.mjs +109 -0
  85. package/dist/errorHandler-C1okiriz.mjs.map +1 -0
  86. package/dist/errors-B9bZok84.mjs +212 -0
  87. package/dist/errors-B9bZok84.mjs.map +1 -0
  88. package/dist/errors-ChKiFz62.d.mts +125 -0
  89. package/dist/errors-ChKiFz62.d.mts.map +1 -0
  90. package/dist/eventPlugin-CTrLH3mt.d.mts +125 -0
  91. package/dist/eventPlugin-CTrLH3mt.d.mts.map +1 -0
  92. package/dist/eventPlugin-DGR_B2on.mjs +230 -0
  93. package/dist/eventPlugin-DGR_B2on.mjs.map +1 -0
  94. package/dist/events/index.d.mts +54 -0
  95. package/dist/events/index.d.mts.map +1 -0
  96. package/dist/events/index.mjs +52 -0
  97. package/dist/events/index.mjs.map +1 -0
  98. package/dist/events/transports/redis-stream-entry.d.mts +2 -0
  99. package/dist/events/transports/redis-stream-entry.mjs +178 -0
  100. package/dist/events/transports/redis-stream-entry.mjs.map +1 -0
  101. package/dist/events/transports/redis.d.mts +77 -0
  102. package/dist/events/transports/redis.d.mts.map +1 -0
  103. package/dist/events/transports/redis.mjs +125 -0
  104. package/dist/events/transports/redis.mjs.map +1 -0
  105. package/dist/externalPaths-DlINfKbP.d.mts +51 -0
  106. package/dist/externalPaths-DlINfKbP.d.mts.map +1 -0
  107. package/dist/factory/index.d.mts +64 -0
  108. package/dist/factory/index.d.mts.map +1 -0
  109. package/dist/factory/index.mjs +3 -0
  110. package/dist/fastifyAdapter-BkrGrlFi.d.mts +217 -0
  111. package/dist/fastifyAdapter-BkrGrlFi.d.mts.map +1 -0
  112. package/dist/fields-DyaDVX4J.d.mts +110 -0
  113. package/dist/fields-DyaDVX4J.d.mts.map +1 -0
  114. package/dist/fields-iagOozy0.mjs +115 -0
  115. package/dist/fields-iagOozy0.mjs.map +1 -0
  116. package/dist/hooks/index.d.mts +4 -0
  117. package/dist/hooks/index.mjs +3 -0
  118. package/dist/idempotency/index.d.mts +97 -0
  119. package/dist/idempotency/index.d.mts.map +1 -0
  120. package/dist/idempotency/index.mjs +320 -0
  121. package/dist/idempotency/index.mjs.map +1 -0
  122. package/dist/idempotency/mongodb.d.mts +2 -0
  123. package/dist/idempotency/mongodb.mjs +115 -0
  124. package/dist/idempotency/mongodb.mjs.map +1 -0
  125. package/dist/idempotency/redis.d.mts +2 -0
  126. package/dist/idempotency/redis.mjs +104 -0
  127. package/dist/idempotency/redis.mjs.map +1 -0
  128. package/dist/index.d.mts +261 -0
  129. package/dist/index.d.mts.map +1 -0
  130. package/dist/index.mjs +105 -0
  131. package/dist/index.mjs.map +1 -0
  132. package/dist/integrations/event-gateway.d.mts +47 -0
  133. package/dist/integrations/event-gateway.d.mts.map +1 -0
  134. package/dist/integrations/event-gateway.mjs +44 -0
  135. package/dist/integrations/event-gateway.mjs.map +1 -0
  136. package/dist/integrations/index.d.mts +5 -0
  137. package/dist/integrations/index.mjs +1 -0
  138. package/dist/integrations/jobs.d.mts +104 -0
  139. package/dist/integrations/jobs.d.mts.map +1 -0
  140. package/dist/integrations/jobs.mjs +124 -0
  141. package/dist/integrations/jobs.mjs.map +1 -0
  142. package/dist/integrations/streamline.d.mts +61 -0
  143. package/dist/integrations/streamline.d.mts.map +1 -0
  144. package/dist/integrations/streamline.mjs +126 -0
  145. package/dist/integrations/streamline.mjs.map +1 -0
  146. package/dist/integrations/websocket.d.mts +83 -0
  147. package/dist/integrations/websocket.d.mts.map +1 -0
  148. package/dist/integrations/websocket.mjs +289 -0
  149. package/dist/integrations/websocket.mjs.map +1 -0
  150. package/dist/interface-B01JvPVc.d.mts +78 -0
  151. package/dist/interface-B01JvPVc.d.mts.map +1 -0
  152. package/dist/interface-CZe8IkMf.d.mts +55 -0
  153. package/dist/interface-CZe8IkMf.d.mts.map +1 -0
  154. package/dist/interface-Ch8HU9uM.d.mts +1098 -0
  155. package/dist/interface-Ch8HU9uM.d.mts.map +1 -0
  156. package/dist/introspectionPlugin-rFdO8ZUa.mjs +54 -0
  157. package/dist/introspectionPlugin-rFdO8ZUa.mjs.map +1 -0
  158. package/dist/keys-BqNejWup.mjs +43 -0
  159. package/dist/keys-BqNejWup.mjs.map +1 -0
  160. package/dist/logger-Df2O2WsW.mjs +79 -0
  161. package/dist/logger-Df2O2WsW.mjs.map +1 -0
  162. package/dist/memory-cQgelFOj.mjs +144 -0
  163. package/dist/memory-cQgelFOj.mjs.map +1 -0
  164. package/dist/migrations/index.d.mts +157 -0
  165. package/dist/migrations/index.d.mts.map +1 -0
  166. package/dist/migrations/index.mjs +261 -0
  167. package/dist/migrations/index.mjs.map +1 -0
  168. package/dist/mongodb-BfJVlUJH.mjs +94 -0
  169. package/dist/mongodb-BfJVlUJH.mjs.map +1 -0
  170. package/dist/mongodb-CGzRbfAK.d.mts +119 -0
  171. package/dist/mongodb-CGzRbfAK.d.mts.map +1 -0
  172. package/dist/mongodb-JN-9JA7K.d.mts +72 -0
  173. package/dist/mongodb-JN-9JA7K.d.mts.map +1 -0
  174. package/dist/openapi-G3Cw7XuM.mjs +524 -0
  175. package/dist/openapi-G3Cw7XuM.mjs.map +1 -0
  176. package/dist/org/index.d.mts +69 -0
  177. package/dist/org/index.d.mts.map +1 -0
  178. package/dist/org/index.mjs +514 -0
  179. package/dist/org/index.mjs.map +1 -0
  180. package/dist/org/types.d.mts +83 -0
  181. package/dist/org/types.d.mts.map +1 -0
  182. package/dist/org/types.mjs +1 -0
  183. package/dist/permissions/index.d.mts +279 -0
  184. package/dist/permissions/index.d.mts.map +1 -0
  185. package/dist/permissions/index.mjs +579 -0
  186. package/dist/permissions/index.mjs.map +1 -0
  187. package/dist/plugins/index.d.mts +173 -0
  188. package/dist/plugins/index.d.mts.map +1 -0
  189. package/dist/plugins/index.mjs +523 -0
  190. package/dist/plugins/index.mjs.map +1 -0
  191. package/dist/plugins/response-cache.d.mts +88 -0
  192. package/dist/plugins/response-cache.d.mts.map +1 -0
  193. package/dist/plugins/response-cache.mjs +284 -0
  194. package/dist/plugins/response-cache.mjs.map +1 -0
  195. package/dist/plugins/tracing-entry.d.mts +2 -0
  196. package/dist/plugins/tracing-entry.mjs +186 -0
  197. package/dist/plugins/tracing-entry.mjs.map +1 -0
  198. package/dist/pluralize-CEweyOEm.mjs +87 -0
  199. package/dist/pluralize-CEweyOEm.mjs.map +1 -0
  200. package/dist/policies/{index.d.ts → index.d.mts} +204 -169
  201. package/dist/policies/index.d.mts.map +1 -0
  202. package/dist/policies/index.mjs +322 -0
  203. package/dist/policies/index.mjs.map +1 -0
  204. package/dist/presets/{index.d.ts → index.d.mts} +63 -131
  205. package/dist/presets/index.d.mts.map +1 -0
  206. package/dist/presets/index.mjs +144 -0
  207. package/dist/presets/index.mjs.map +1 -0
  208. package/dist/presets/multiTenant.d.mts +25 -0
  209. package/dist/presets/multiTenant.d.mts.map +1 -0
  210. package/dist/presets/multiTenant.mjs +114 -0
  211. package/dist/presets/multiTenant.mjs.map +1 -0
  212. package/dist/presets-BITljm96.mjs +120 -0
  213. package/dist/presets-BITljm96.mjs.map +1 -0
  214. package/dist/presets-DzSMwlKj.d.mts +58 -0
  215. package/dist/presets-DzSMwlKj.d.mts.map +1 -0
  216. package/dist/prisma-DJbMt3yf.mjs +628 -0
  217. package/dist/prisma-DJbMt3yf.mjs.map +1 -0
  218. package/dist/prisma-Dg9GoVdj.d.mts +275 -0
  219. package/dist/prisma-Dg9GoVdj.d.mts.map +1 -0
  220. package/dist/queryCachePlugin-7THaI5mt.d.mts +72 -0
  221. package/dist/queryCachePlugin-7THaI5mt.d.mts.map +1 -0
  222. package/dist/queryCachePlugin-DMBnp2Q0.mjs +139 -0
  223. package/dist/queryCachePlugin-DMBnp2Q0.mjs.map +1 -0
  224. package/dist/redis-D-JAeLtm.d.mts +50 -0
  225. package/dist/redis-D-JAeLtm.d.mts.map +1 -0
  226. package/dist/redis-stream-Bdh_vUU8.d.mts +104 -0
  227. package/dist/redis-stream-Bdh_vUU8.d.mts.map +1 -0
  228. package/dist/registry/index.d.mts +12 -0
  229. package/dist/registry/index.d.mts.map +1 -0
  230. package/dist/registry/index.mjs +4 -0
  231. package/dist/requestContext-QQD6ROJc.mjs +56 -0
  232. package/dist/requestContext-QQD6ROJc.mjs.map +1 -0
  233. package/dist/schemaConverter-BwrmWroW.mjs +99 -0
  234. package/dist/schemaConverter-BwrmWroW.mjs.map +1 -0
  235. package/dist/schemas/index.d.mts +64 -0
  236. package/dist/schemas/index.d.mts.map +1 -0
  237. package/dist/schemas/index.mjs +83 -0
  238. package/dist/schemas/index.mjs.map +1 -0
  239. package/dist/scope/index.d.mts +22 -0
  240. package/dist/scope/index.d.mts.map +1 -0
  241. package/dist/scope/index.mjs +66 -0
  242. package/dist/scope/index.mjs.map +1 -0
  243. package/dist/sessionManager-jPKLbHE0.d.mts +187 -0
  244. package/dist/sessionManager-jPKLbHE0.d.mts.map +1 -0
  245. package/dist/sse-B3c3_yZp.mjs +124 -0
  246. package/dist/sse-B3c3_yZp.mjs.map +1 -0
  247. package/dist/testing/index.d.mts +908 -0
  248. package/dist/testing/index.d.mts.map +1 -0
  249. package/dist/testing/index.mjs +1977 -0
  250. package/dist/testing/index.mjs.map +1 -0
  251. package/dist/tracing-Cc7vVQPp.d.mts +71 -0
  252. package/dist/tracing-Cc7vVQPp.d.mts.map +1 -0
  253. package/dist/typeGuards-DhMNLuvU.mjs +10 -0
  254. package/dist/typeGuards-DhMNLuvU.mjs.map +1 -0
  255. package/dist/types/index.d.mts +947 -0
  256. package/dist/types/index.d.mts.map +1 -0
  257. package/dist/types/index.mjs +15 -0
  258. package/dist/types/index.mjs.map +1 -0
  259. package/dist/types-Beqn1Un7.mjs +39 -0
  260. package/dist/types-Beqn1Un7.mjs.map +1 -0
  261. package/dist/types-CIgB7UUl.d.mts +446 -0
  262. package/dist/types-CIgB7UUl.d.mts.map +1 -0
  263. package/dist/types-aYB4V7uN.d.mts +87 -0
  264. package/dist/types-aYB4V7uN.d.mts.map +1 -0
  265. package/dist/utils/index.d.mts +748 -0
  266. package/dist/utils/index.d.mts.map +1 -0
  267. package/dist/utils/index.mjs +6 -0
  268. package/package.json +194 -68
  269. package/dist/BaseController-DVAiHxEQ.d.ts +0 -233
  270. package/dist/adapters/index.d.ts +0 -237
  271. package/dist/adapters/index.js +0 -668
  272. package/dist/arcCorePlugin-CsShQdyP.d.ts +0 -273
  273. package/dist/audit/index.d.ts +0 -195
  274. package/dist/audit/index.js +0 -319
  275. package/dist/auth/index.d.ts +0 -47
  276. package/dist/auth/index.js +0 -174
  277. package/dist/cli/commands/docs.d.ts +0 -11
  278. package/dist/cli/commands/docs.js +0 -474
  279. package/dist/cli/commands/generate.js +0 -334
  280. package/dist/cli/commands/introspect.d.ts +0 -8
  281. package/dist/cli/commands/introspect.js +0 -338
  282. package/dist/cli/index.d.ts +0 -4
  283. package/dist/cli/index.js +0 -3269
  284. package/dist/core/index.d.ts +0 -220
  285. package/dist/core/index.js +0 -2786
  286. package/dist/createApp-Ce9wl8W9.d.ts +0 -77
  287. package/dist/docs/index.d.ts +0 -166
  288. package/dist/docs/index.js +0 -658
  289. package/dist/errors-8WIxGS_6.d.ts +0 -122
  290. package/dist/events/index.d.ts +0 -117
  291. package/dist/events/index.js +0 -89
  292. package/dist/factory/index.d.ts +0 -38
  293. package/dist/factory/index.js +0 -1652
  294. package/dist/hooks/index.d.ts +0 -4
  295. package/dist/hooks/index.js +0 -199
  296. package/dist/idempotency/index.d.ts +0 -323
  297. package/dist/idempotency/index.js +0 -500
  298. package/dist/index-B4t03KQ0.d.ts +0 -1366
  299. package/dist/index.d.ts +0 -135
  300. package/dist/index.js +0 -4756
  301. package/dist/migrations/index.d.ts +0 -185
  302. package/dist/migrations/index.js +0 -274
  303. package/dist/org/index.d.ts +0 -129
  304. package/dist/org/index.js +0 -220
  305. package/dist/permissions/index.d.ts +0 -144
  306. package/dist/permissions/index.js +0 -103
  307. package/dist/plugins/index.d.ts +0 -46
  308. package/dist/plugins/index.js +0 -1069
  309. package/dist/policies/index.js +0 -196
  310. package/dist/presets/index.js +0 -384
  311. package/dist/presets/multiTenant.d.ts +0 -39
  312. package/dist/presets/multiTenant.js +0 -112
  313. package/dist/registry/index.d.ts +0 -16
  314. package/dist/registry/index.js +0 -253
  315. package/dist/testing/index.d.ts +0 -618
  316. package/dist/testing/index.js +0 -48020
  317. package/dist/types/index.d.ts +0 -4
  318. package/dist/types/index.js +0 -8
  319. package/dist/types-B99TBmFV.d.ts +0 -76
  320. package/dist/types-BvckRbs2.d.ts +0 -143
  321. package/dist/utils/index.d.ts +0 -679
  322. package/dist/utils/index.js +0 -931
@@ -0,0 +1,173 @@
1
+ import "../elevation-B_2dRLVP.mjs";
2
+ import { K as HookSystem, w as ResourceRegistry } from "../interface-Ch8HU9uM.mjs";
3
+ import "../types-aYB4V7uN.mjs";
4
+ import { AdditionalRoute, AnyRecord, MiddlewareConfig, PresetHook, RouteSchemaOptions } from "../types/index.mjs";
5
+ import { t as ExternalOpenApiPaths } from "../externalPaths-DlINfKbP.mjs";
6
+ import { a as ssePlugin, c as _default$1, i as _default$5, l as cachingPlugin, n as errorHandlerPlugin, o as CachingOptions, r as SSEOptions, s as CachingRule, t as ErrorHandlerOptions } from "../errorHandler-BbcgBmIH.mjs";
7
+ import { t as TracingOptions } from "../tracing-Cc7vVQPp.mjs";
8
+ import { FastifyInstance, FastifyPluginAsync } from "fastify";
9
+
10
+ //#region src/plugins/requestId.d.ts
11
+ interface RequestIdOptions {
12
+ /** Header name to read/write request ID (default: 'x-request-id') */
13
+ header?: string;
14
+ /** Custom ID generator (default: crypto.randomUUID) */
15
+ generator?: () => string;
16
+ /** Whether to set response header (default: true) */
17
+ setResponseHeader?: boolean;
18
+ }
19
+ declare module 'fastify' {
20
+ interface FastifyRequest {
21
+ /** Unique request identifier for tracing */
22
+ requestId: string;
23
+ }
24
+ }
25
+ declare const requestIdPlugin: FastifyPluginAsync<RequestIdOptions>;
26
+ declare const _default$4: FastifyPluginAsync<RequestIdOptions>;
27
+ //#endregion
28
+ //#region src/plugins/health.d.ts
29
+ declare module 'fastify' {
30
+ interface FastifyRequest {
31
+ _startTime?: number;
32
+ }
33
+ }
34
+ interface HealthCheck {
35
+ /** Name of the dependency */
36
+ name: string;
37
+ /** Function that returns true if healthy, false otherwise */
38
+ check: () => Promise<boolean> | boolean;
39
+ /** Optional timeout in ms (default: 5000) */
40
+ timeout?: number;
41
+ /** Whether this check is critical for readiness (default: true) */
42
+ critical?: boolean;
43
+ }
44
+ interface HealthOptions {
45
+ /** Route prefix (default: '/_health') */
46
+ prefix?: string;
47
+ /** Health check dependencies */
48
+ checks?: HealthCheck[];
49
+ /** Enable metrics endpoint (default: false) */
50
+ metrics?: boolean;
51
+ /** Custom metrics collector function */
52
+ metricsCollector?: () => Promise<string> | string;
53
+ /** Version info to include in responses */
54
+ version?: string;
55
+ /** Collect HTTP request metrics (default: true if metrics enabled) */
56
+ collectHttpMetrics?: boolean;
57
+ }
58
+ declare const healthPlugin: FastifyPluginAsync<HealthOptions>;
59
+ declare const _default$3: FastifyPluginAsync<HealthOptions>;
60
+ //#endregion
61
+ //#region src/plugins/gracefulShutdown.d.ts
62
+ interface GracefulShutdownOptions {
63
+ /** Maximum time to wait for graceful shutdown in ms (default: 30000) */
64
+ timeout?: number;
65
+ /** Custom cleanup function called before exit */
66
+ onShutdown?: () => Promise<void> | void;
67
+ /** Signals to handle (default: ['SIGTERM', 'SIGINT']) */
68
+ signals?: NodeJS.Signals[];
69
+ /** Whether to log shutdown events (default: true) */
70
+ logEvents?: boolean;
71
+ /**
72
+ * Called when shutdown times out or encounters an error.
73
+ * Defaults to `process.exit(1)` — appropriate for production but dangerous in:
74
+ * - **Tests**: kills the test runner. Pass `() => {}` or `() => { throw … }`.
75
+ * - **Shared runtimes** (e.g., serverless): may kill unrelated handlers.
76
+ *
77
+ * @param reason - `'timeout'` if shutdown exceeded `timeout` ms,
78
+ * `'error'` if `onShutdown` or `fastify.close()` threw.
79
+ */
80
+ onForceExit?: (reason: 'timeout' | 'error') => void;
81
+ }
82
+ declare const gracefulShutdownPlugin: FastifyPluginAsync<GracefulShutdownOptions>;
83
+ declare module 'fastify' {
84
+ interface FastifyInstance {
85
+ /** Trigger graceful shutdown manually */
86
+ shutdown: () => Promise<void>;
87
+ }
88
+ }
89
+ declare const _default$2: FastifyPluginAsync<GracefulShutdownOptions>;
90
+ //#endregion
91
+ //#region src/plugins/createPlugin.d.ts
92
+ interface PluginResourceResult {
93
+ /** Additional routes to add to the resource */
94
+ additionalRoutes?: AdditionalRoute[];
95
+ /** Middlewares per operation */
96
+ middlewares?: MiddlewareConfig;
97
+ /** Hooks to register */
98
+ hooks?: PresetHook[];
99
+ /** Schema options to merge */
100
+ schemaOptions?: RouteSchemaOptions;
101
+ }
102
+ interface CreatePluginDefinition<TRootOpts extends AnyRecord = AnyRecord, TResourceOpts extends AnyRecord = AnyRecord> {
103
+ /**
104
+ * Global setup function. Called once when the plugin is registered on the Fastify instance.
105
+ * Use this for database connections, decorators, shared state, etc.
106
+ */
107
+ forRoot?: (fastify: FastifyInstance, opts: TRootOpts) => void | Promise<void>;
108
+ /**
109
+ * Per-resource configuration function. Called for each resource that uses this plugin.
110
+ * Returns hooks, routes, middlewares, etc. to merge into the resource config.
111
+ */
112
+ forResource?: (resourceConfig: AnyRecord, opts: TResourceOpts) => PluginResourceResult;
113
+ }
114
+ interface ArcPlugin<TRootOpts extends AnyRecord = AnyRecord, TResourceOpts extends AnyRecord = AnyRecord> {
115
+ /** Plugin name */
116
+ readonly name: string;
117
+ /**
118
+ * Register the plugin globally on a Fastify instance.
119
+ * Returns a Fastify plugin that can be passed to `app.register()`.
120
+ */
121
+ forRoot(opts?: TRootOpts): FastifyPluginAsync<TRootOpts>;
122
+ /**
123
+ * Apply per-resource configuration.
124
+ * Returns a partial resource config to spread into `defineResource()`.
125
+ */
126
+ forResource(opts?: TResourceOpts): PluginResourceResult;
127
+ }
128
+ /**
129
+ * Create a structured plugin with forRoot (global) and forResource (per-resource) support.
130
+ *
131
+ * @param name - Plugin name (used for Fastify registration and debugging)
132
+ * @param definition - Plugin setup functions
133
+ * @returns ArcPlugin with forRoot() and forResource() methods
134
+ */
135
+ declare function createPlugin<TRootOpts extends AnyRecord = AnyRecord, TResourceOpts extends AnyRecord = AnyRecord>(name: string, definition: CreatePluginDefinition<TRootOpts, TResourceOpts>): ArcPlugin<TRootOpts, TResourceOpts>;
136
+ //#endregion
137
+ //#region src/core/arcCorePlugin.d.ts
138
+ interface ArcCorePluginOptions {
139
+ /** Enable event emission for CRUD operations (requires eventPlugin) */
140
+ emitEvents?: boolean;
141
+ /** Hook system instance (for testing/custom setup) */
142
+ hookSystem?: HookSystem;
143
+ /** Resource registry instance (for testing/custom setup) */
144
+ registry?: ResourceRegistry;
145
+ }
146
+ interface PluginMeta {
147
+ name: string;
148
+ version?: string;
149
+ options?: Record<string, unknown>;
150
+ registeredAt: string;
151
+ }
152
+ interface ArcCore {
153
+ /** Instance-scoped hook system */
154
+ hooks: HookSystem;
155
+ /** Instance-scoped resource registry */
156
+ registry: ResourceRegistry;
157
+ /** Whether event emission is enabled */
158
+ emitEvents: boolean;
159
+ /** External OpenAPI paths contributed by auth adapters or third-party integrations */
160
+ externalOpenApiPaths: ExternalOpenApiPaths[];
161
+ /** Registered plugins for introspection */
162
+ plugins: Map<string, PluginMeta>;
163
+ }
164
+ declare module 'fastify' {
165
+ interface FastifyInstance {
166
+ arc: ArcCore;
167
+ }
168
+ }
169
+ declare const arcCorePlugin: FastifyPluginAsync<ArcCorePluginOptions>;
170
+ declare const _default: FastifyPluginAsync<ArcCorePluginOptions>;
171
+ //#endregion
172
+ export { type ArcCore, type ArcCorePluginOptions, type ArcPlugin, type CachingOptions, type CachingRule, type CreatePluginDefinition, type ErrorHandlerOptions, type GracefulShutdownOptions, type HealthCheck, type HealthOptions, type PluginMeta, type PluginResourceResult, type RequestIdOptions, type SSEOptions, type TracingOptions, _default as arcCorePlugin, arcCorePlugin as arcCorePluginFn, _default$1 as cachingPlugin, cachingPlugin as cachingPluginFn, createPlugin, errorHandlerPlugin, errorHandlerPlugin as errorHandlerPluginFn, _default$2 as gracefulShutdownPlugin, gracefulShutdownPlugin as gracefulShutdownPluginFn, _default$3 as healthPlugin, healthPlugin as healthPluginFn, _default$4 as requestIdPlugin, requestIdPlugin as requestIdPluginFn, _default$5 as ssePlugin, ssePlugin as ssePluginFn };
173
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/plugins/requestId.ts","../../src/plugins/health.ts","../../src/plugins/gracefulShutdown.ts","../../src/plugins/createPlugin.ts","../../src/core/arcCorePlugin.ts"],"mappings":";;;;;;;;;;UAuBiB,gBAAA;EAOhB;EALC,MAAA;EAQU;EANV,SAAA;EAQW;EANX,iBAAA;AAAA;AAAA;EAAA,UAIU,cAAA;IAM8C;IAJtD,SAAA;EAAA;AAAA;AAAA,cAIE,eAAA,EAAiB,kBAAA,CAAmB,gBAAA;AAAA,cAAgB,UAAA;;;;YCd9C,cAAA;IACR,UAAA;EAAA;AAAA;AAAA,UAIa,WAAA;EDiDhB;EC/CC,IAAA;EDOqB;ECLrB,KAAA,QAAa,OAAA;EDK2C;ECHxD,OAAA;;EAEA,QAAA;AAAA;AAAA,UAGe,aAAA;;EAEf,MAAA;EAtBiE;EAwBjE,MAAA,GAAS,WAAA;;EAET,OAAA;EArBY;EAuBZ,gBAAA,SAAyB,OAAA;EAnBV;EAqBf,OAAA;;EAEA,kBAAA;AAAA;AAAA,cA4BI,YAAA,EAAc,kBAAA,CAAmB,aAAA;AAAA,cAAa,UAAA;;;UCjDnC,uBAAA;EFOyC;EELxD,OAAA;;EAEA,UAAA,SAAmB,OAAA;;EAEnB,OAAA,GAAU,MAAA,CAAO,OAAA;;EAEjB,SAAA;EDnBiE;;;;;;AASnE;;;ECoBE,WAAA,IAAe,MAAA;AAAA;AAAA,cAGX,sBAAA,EAAwB,kBAAA,CAAmB,uBAAA;AAAA;EAAA,UAoGrC,eAAA;IDnHV;ICqHE,QAAA,QAAgB,OAAA;EAAA;AAAA;AAAA,cAAO,UAAA;;;UC7GV,oBAAA;;EAEf,gBAAA,GAAmB,eAAA;EFtBP;EEwBZ,WAAA,GAAc,gBAAA;EFpBC;EEsBf,KAAA,GAAQ,UAAA;;EAER,aAAA,GAAgB,kBAAA;AAAA;AAAA,UAGD,sBAAA,mBACG,SAAA,GAAY,SAAA,wBACR,SAAA,GAAY,SAAA;EFzBrB;;;;EE+Bb,OAAA,IAAW,OAAA,EAAS,eAAA,EAAiB,IAAA,EAAM,SAAA,YAAqB,OAAA;EFxBjD;;;;EE8Bf,WAAA,IAAe,cAAA,EAAgB,SAAA,EAAW,IAAA,EAAM,aAAA,KAAkB,oBAAA;AAAA;AAAA,UAGnD,SAAA,mBACG,SAAA,GAAY,SAAA,wBACR,SAAA,GAAY,SAAA;EF7BlC;EAAA,SEgCS,IAAA;EF9BgB;;;;EEoCzB,OAAA,CAAQ,IAAA,GAAO,SAAA,GAAY,kBAAA,CAAmB,SAAA;EFJ1C;;;;EEUJ,WAAA,CAAY,IAAA,GAAO,aAAA,GAAgB,oBAAA;AAAA;;;;;;;;iBAcrB,YAAA,mBACI,SAAA,GAAY,SAAA,wBACR,SAAA,GAAY,SAAA,CAAA,CAElC,IAAA,UACA,UAAA,EAAY,sBAAA,CAAuB,SAAA,EAAW,aAAA,IAC7C,SAAA,CAAU,SAAA,EAAW,aAAA;;;UC5EP,oBAAA;;EAEf,UAAA;EJEwD;EIAxD,UAAA,GAAa,UAAA;;EAEb,QAAA,GAAW,gBAAA;AAAA;AAAA,UAGI,UAAA;EACf,IAAA;EACA,OAAA;EACA,OAAA,GAAU,MAAA;EACV,YAAA;AAAA;AAAA,UAGe,OAAA;EH1BL;EG4BV,KAAA,EAAO,UAAA;EH3BK;EG6BZ,QAAA,EAAU,gBAAA;EHzBgB;EG2B1B,UAAA;EHvBoB;EGyBpB,oBAAA,EAAsB,oBAAA;EHzBtB;EG2BA,OAAA,EAAS,GAAA,SAAY,UAAA;AAAA;AAAA;EAAA,UAIX,eAAA;IACR,GAAA,EAAK,OAAA;EAAA;AAAA;AAAA,cAIH,aAAA,EAAe,kBAAA,CAAmB,oBAAA;AAAA,cAAoB,QAAA"}
@@ -0,0 +1,523 @@
1
+ import { p as MUTATION_OPERATIONS } from "../constants-DdXFXQtN.mjs";
2
+ import { r as getOrgId } from "../types-Beqn1Un7.mjs";
3
+ import { t as HookSystem } from "../HookSystem-BsGV-j2l.mjs";
4
+ import { t as hasEvents } from "../typeGuards-DhMNLuvU.mjs";
5
+ import { t as requestContext } from "../requestContext-QQD6ROJc.mjs";
6
+ import { t as ResourceRegistry } from "../ResourceRegistry-DsN4KJjV.mjs";
7
+ import { t as errorHandlerPlugin } from "../errorHandler-C1okiriz.mjs";
8
+ import { n as caching_default, t as cachingPlugin } from "../caching-Bl28lYsR.mjs";
9
+ import { n as sse_default, t as ssePlugin } from "../sse-B3c3_yZp.mjs";
10
+ import fp from "fastify-plugin";
11
+ import { randomUUID } from "crypto";
12
+
13
+ //#region src/plugins/requestId.ts
14
+ /**
15
+ * Request ID Plugin
16
+ *
17
+ * Propagates request IDs for distributed tracing.
18
+ * - Accepts incoming x-request-id header
19
+ * - Generates UUID if not provided
20
+ * - Attaches to request.id and response header
21
+ *
22
+ * @example
23
+ * import { requestIdPlugin } from '@classytic/arc';
24
+ *
25
+ * await fastify.register(requestIdPlugin);
26
+ *
27
+ * // In handlers, access via request.id
28
+ * fastify.get('/', async (request) => {
29
+ * console.log(request.id); // UUID
30
+ * });
31
+ */
32
+ const requestIdPlugin = async (fastify, opts = {}) => {
33
+ const { header = "x-request-id", generator = randomUUID, setResponseHeader = true } = opts;
34
+ if (!fastify.hasRequestDecorator("requestId")) fastify.decorateRequest("requestId", "");
35
+ fastify.addHook("onRequest", async (request) => {
36
+ const incomingId = request.headers[header];
37
+ const sanitized = typeof incomingId === "string" ? incomingId.trim() : "";
38
+ const requestId = sanitized.length > 0 && sanitized.length <= 128 && /^[\w.:-]+$/.test(sanitized) ? sanitized : generator();
39
+ request.id = requestId;
40
+ request.requestId = requestId;
41
+ });
42
+ if (setResponseHeader) fastify.addHook("onSend", async (request, reply) => {
43
+ reply.header(header, request.requestId);
44
+ });
45
+ fastify.log?.debug?.("Request ID plugin registered");
46
+ };
47
+ var requestId_default = fp(requestIdPlugin, {
48
+ name: "arc-request-id",
49
+ fastify: "5.x"
50
+ });
51
+
52
+ //#endregion
53
+ //#region src/plugins/health.ts
54
+ /**
55
+ * Health Check Plugin
56
+ *
57
+ * Kubernetes-ready health endpoints:
58
+ * - /health/live - Liveness probe (is the process alive?)
59
+ * - /health/ready - Readiness probe (can we serve traffic?)
60
+ * - /health/metrics - Prometheus metrics (optional)
61
+ *
62
+ * @example
63
+ * import { healthPlugin } from '@classytic/arc';
64
+ *
65
+ * await fastify.register(healthPlugin, {
66
+ * prefix: '/_health',
67
+ * checks: [
68
+ * { name: 'mongodb', check: async () => mongoose.connection.readyState === 1 },
69
+ * { name: 'redis', check: async () => redis.ping() === 'PONG' },
70
+ * ],
71
+ * });
72
+ */
73
+ function createHttpMetrics() {
74
+ return {
75
+ requestsTotal: {},
76
+ requestDurations: [],
77
+ _ringIndex: 0,
78
+ startTime: Date.now()
79
+ };
80
+ }
81
+ const healthPlugin = async (fastify, opts = {}) => {
82
+ const { prefix = "/_health", checks = [], metrics = false, metricsCollector, version, collectHttpMetrics = metrics } = opts;
83
+ const httpMetrics = createHttpMetrics();
84
+ fastify.get(`${prefix}/live`, { schema: {
85
+ tags: ["Health"],
86
+ summary: "Liveness probe",
87
+ description: "Returns 200 if the process is alive",
88
+ response: { 200: {
89
+ type: "object",
90
+ properties: {
91
+ status: {
92
+ type: "string",
93
+ enum: ["ok"]
94
+ },
95
+ timestamp: { type: "string" },
96
+ version: { type: "string" }
97
+ }
98
+ } }
99
+ } }, async () => {
100
+ return {
101
+ status: "ok",
102
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
103
+ ...version ? { version } : {}
104
+ };
105
+ });
106
+ fastify.get(`${prefix}/ready`, { schema: {
107
+ tags: ["Health"],
108
+ summary: "Readiness probe",
109
+ description: "Returns 200 if all dependencies are healthy",
110
+ response: {
111
+ 200: {
112
+ type: "object",
113
+ properties: {
114
+ status: {
115
+ type: "string",
116
+ enum: ["ready", "not_ready"]
117
+ },
118
+ timestamp: { type: "string" },
119
+ checks: {
120
+ type: "array",
121
+ items: {
122
+ type: "object",
123
+ properties: {
124
+ name: { type: "string" },
125
+ healthy: { type: "boolean" },
126
+ duration: { type: "number" },
127
+ error: { type: "string" }
128
+ }
129
+ }
130
+ }
131
+ }
132
+ },
133
+ 503: {
134
+ type: "object",
135
+ properties: {
136
+ status: {
137
+ type: "string",
138
+ enum: ["not_ready"]
139
+ },
140
+ timestamp: { type: "string" },
141
+ checks: { type: "array" }
142
+ }
143
+ }
144
+ }
145
+ } }, async (_, reply) => {
146
+ const results = await runChecks(checks);
147
+ const criticalFailed = results.some((r) => !r.healthy && (checks.find((c) => c.name === r.name)?.critical ?? true));
148
+ const response = {
149
+ status: criticalFailed ? "not_ready" : "ready",
150
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
151
+ checks: results
152
+ };
153
+ if (criticalFailed) reply.code(503);
154
+ return response;
155
+ });
156
+ if (metrics) fastify.get(`${prefix}/metrics`, async (_, reply) => {
157
+ reply.type("text/plain; charset=utf-8");
158
+ if (metricsCollector) return await metricsCollector();
159
+ const uptime = process.uptime();
160
+ const memory = process.memoryUsage();
161
+ const cpu = process.cpuUsage();
162
+ const lines = [
163
+ "# HELP process_uptime_seconds Process uptime in seconds",
164
+ "# TYPE process_uptime_seconds gauge",
165
+ `process_uptime_seconds ${uptime.toFixed(2)}`,
166
+ "",
167
+ "# HELP process_memory_heap_bytes Heap memory usage in bytes",
168
+ "# TYPE process_memory_heap_bytes gauge",
169
+ `process_memory_heap_bytes{type="used"} ${memory.heapUsed}`,
170
+ `process_memory_heap_bytes{type="total"} ${memory.heapTotal}`,
171
+ "",
172
+ "# HELP process_memory_rss_bytes RSS memory in bytes",
173
+ "# TYPE process_memory_rss_bytes gauge",
174
+ `process_memory_rss_bytes ${memory.rss}`,
175
+ "",
176
+ "# HELP process_memory_external_bytes External memory in bytes",
177
+ "# TYPE process_memory_external_bytes gauge",
178
+ `process_memory_external_bytes ${memory.external}`,
179
+ "",
180
+ "# HELP process_cpu_user_microseconds User CPU time in microseconds",
181
+ "# TYPE process_cpu_user_microseconds counter",
182
+ `process_cpu_user_microseconds ${cpu.user}`,
183
+ "",
184
+ "# HELP process_cpu_system_microseconds System CPU time in microseconds",
185
+ "# TYPE process_cpu_system_microseconds counter",
186
+ `process_cpu_system_microseconds ${cpu.system}`,
187
+ ""
188
+ ];
189
+ if (collectHttpMetrics && Object.keys(httpMetrics.requestsTotal).length > 0) {
190
+ lines.push("# HELP http_requests_total Total HTTP requests by status code", "# TYPE http_requests_total counter");
191
+ for (const [status, count] of Object.entries(httpMetrics.requestsTotal)) lines.push(`http_requests_total{status="${status}"} ${count}`);
192
+ lines.push("");
193
+ if (httpMetrics.requestDurations.length > 0) {
194
+ const sorted = [...httpMetrics.requestDurations].sort((a, b) => a - b);
195
+ const p50 = sorted[Math.floor(sorted.length * .5)] || 0;
196
+ const p95 = sorted[Math.floor(sorted.length * .95)] || 0;
197
+ const p99 = sorted[Math.floor(sorted.length * .99)] || 0;
198
+ const sum = sorted.reduce((a, b) => a + b, 0);
199
+ lines.push("# HELP http_request_duration_milliseconds HTTP request duration", "# TYPE http_request_duration_milliseconds summary", `http_request_duration_milliseconds{quantile="0.5"} ${p50.toFixed(2)}`, `http_request_duration_milliseconds{quantile="0.95"} ${p95.toFixed(2)}`, `http_request_duration_milliseconds{quantile="0.99"} ${p99.toFixed(2)}`, `http_request_duration_milliseconds_sum ${sum.toFixed(2)}`, `http_request_duration_milliseconds_count ${sorted.length}`, "");
200
+ }
201
+ }
202
+ return lines.join("\n");
203
+ });
204
+ if (collectHttpMetrics) {
205
+ fastify.addHook("onRequest", async (request) => {
206
+ request._startTime = Date.now();
207
+ });
208
+ fastify.addHook("onResponse", async (request, reply) => {
209
+ const duration = Date.now() - (request._startTime ?? Date.now());
210
+ const statusBucket = `${Math.floor(reply.statusCode / 100)}xx`;
211
+ httpMetrics.requestsTotal[statusBucket] = (httpMetrics.requestsTotal[statusBucket] || 0) + 1;
212
+ if (httpMetrics.requestDurations.length < 1e4) httpMetrics.requestDurations.push(duration);
213
+ else httpMetrics.requestDurations[httpMetrics._ringIndex % 1e4] = duration;
214
+ httpMetrics._ringIndex = httpMetrics._ringIndex + 1;
215
+ });
216
+ }
217
+ fastify.log?.debug?.(`Health plugin registered at ${prefix}`);
218
+ };
219
+ /**
220
+ * Run all health checks with timeout
221
+ */
222
+ async function runChecks(checks) {
223
+ const results = [];
224
+ for (const check of checks) {
225
+ const start = Date.now();
226
+ const timeout = check.timeout ?? 5e3;
227
+ let timer;
228
+ try {
229
+ const checkPromise = Promise.resolve(check.check());
230
+ const timeoutPromise = new Promise((_, reject) => {
231
+ timer = setTimeout(() => reject(/* @__PURE__ */ new Error("Health check timeout")), timeout);
232
+ });
233
+ const healthy = await Promise.race([checkPromise, timeoutPromise]);
234
+ results.push({
235
+ name: check.name,
236
+ healthy: Boolean(healthy),
237
+ duration: Date.now() - start
238
+ });
239
+ } catch (err) {
240
+ results.push({
241
+ name: check.name,
242
+ healthy: false,
243
+ duration: Date.now() - start,
244
+ error: err.message
245
+ });
246
+ } finally {
247
+ if (timer) clearTimeout(timer);
248
+ }
249
+ }
250
+ return results;
251
+ }
252
+ var health_default = fp(healthPlugin, {
253
+ name: "arc-health",
254
+ fastify: "5.x"
255
+ });
256
+
257
+ //#endregion
258
+ //#region src/plugins/gracefulShutdown.ts
259
+ /**
260
+ * Graceful Shutdown Plugin
261
+ *
262
+ * Handles SIGTERM and SIGINT signals for clean shutdown:
263
+ * - Stops accepting new connections
264
+ * - Waits for in-flight requests to complete
265
+ * - Closes database connections
266
+ * - Exits cleanly
267
+ *
268
+ * Essential for Kubernetes deployments.
269
+ *
270
+ * @example
271
+ * import { gracefulShutdownPlugin } from '@classytic/arc';
272
+ *
273
+ * // Production
274
+ * await fastify.register(gracefulShutdownPlugin, {
275
+ * timeout: 30000, // 30 seconds max
276
+ * onShutdown: async () => {
277
+ * await mongoose.disconnect();
278
+ * await redis.quit();
279
+ * },
280
+ * });
281
+ *
282
+ * // Tests — prevent process.exit from killing the runner
283
+ * await fastify.register(gracefulShutdownPlugin, {
284
+ * onForceExit: () => {},
285
+ * });
286
+ */
287
+ const gracefulShutdownPlugin = async (fastify, opts = {}) => {
288
+ const { timeout = 3e4, onShutdown, signals = ["SIGTERM", "SIGINT"], logEvents = true, onForceExit = () => process.exit(1) } = opts;
289
+ let isShuttingDown = false;
290
+ const signalHandlers = /* @__PURE__ */ new Map();
291
+ const shutdown = async (signal) => {
292
+ if (isShuttingDown) {
293
+ if (logEvents) fastify.log?.warn?.({ signal }, "Shutdown already in progress, ignoring signal");
294
+ return;
295
+ }
296
+ isShuttingDown = true;
297
+ if (logEvents) fastify.log?.info?.({
298
+ signal,
299
+ timeout
300
+ }, "Shutdown signal received, starting graceful shutdown");
301
+ const forceExitTimer = setTimeout(() => {
302
+ if (logEvents) fastify.log?.error?.("Graceful shutdown timeout exceeded, forcing exit");
303
+ onForceExit("timeout");
304
+ }, timeout);
305
+ forceExitTimer.unref();
306
+ try {
307
+ if (logEvents) fastify.log?.info?.("Closing server to new connections");
308
+ await fastify.close();
309
+ if (onShutdown) {
310
+ if (logEvents) fastify.log?.info?.("Running custom shutdown handler");
311
+ await onShutdown();
312
+ }
313
+ if (logEvents) fastify.log?.info?.("Graceful shutdown complete");
314
+ clearTimeout(forceExitTimer);
315
+ } catch (err) {
316
+ if (logEvents) fastify.log?.error?.({ error: err.message }, "Error during shutdown");
317
+ clearTimeout(forceExitTimer);
318
+ onForceExit("error");
319
+ }
320
+ };
321
+ for (const signal of signals) {
322
+ const handler = () => {
323
+ shutdown(signal);
324
+ };
325
+ signalHandlers.set(signal, handler);
326
+ process.on(signal, handler);
327
+ }
328
+ fastify.addHook("onClose", async () => {
329
+ for (const [signal, handler] of signalHandlers) process.removeListener(signal, handler);
330
+ signalHandlers.clear();
331
+ });
332
+ fastify.decorate("shutdown", async () => {
333
+ await shutdown("MANUAL");
334
+ });
335
+ if (logEvents) fastify.log?.debug?.({ signals }, "Graceful shutdown plugin registered");
336
+ };
337
+ var gracefulShutdown_default = fp(gracefulShutdownPlugin, {
338
+ name: "arc-graceful-shutdown",
339
+ fastify: "5.x"
340
+ });
341
+
342
+ //#endregion
343
+ //#region src/plugins/createPlugin.ts
344
+ /**
345
+ * createPlugin() — forRoot/forFeature Pattern
346
+ *
347
+ * Standard pattern for plugins that need both global setup and per-resource configuration.
348
+ * Inspired by NestJS forRoot/forFeature but simpler — plain functions, no decorators.
349
+ *
350
+ * @example
351
+ * ```typescript
352
+ * // Define a plugin with global + per-resource config
353
+ * const analytics = createPlugin('analytics', {
354
+ * forRoot: async (fastify, opts) => {
355
+ * // Global setup: connect to analytics service, add decorators
356
+ * const client = new AnalyticsClient(opts.apiKey);
357
+ * fastify.decorate('analytics', client);
358
+ * },
359
+ * forResource: (resourceConfig, opts) => {
360
+ * // Per-resource: return hooks, middleware, or routes
361
+ * return {
362
+ * hooks: [{
363
+ * operation: 'create', phase: 'after', priority: 100,
364
+ * handler: (ctx) => client.track('created', ctx.result),
365
+ * }],
366
+ * };
367
+ * },
368
+ * });
369
+ *
370
+ * // Usage — register globally once
371
+ * await app.register(analytics.forRoot({ apiKey: 'xxx' }));
372
+ *
373
+ * // Then apply per-resource
374
+ * const productResource = defineResource({
375
+ * name: 'product',
376
+ * adapter: productAdapter,
377
+ * ...analytics.forResource({ trackEvents: true }),
378
+ * });
379
+ * ```
380
+ */
381
+ /**
382
+ * Create a structured plugin with forRoot (global) and forResource (per-resource) support.
383
+ *
384
+ * @param name - Plugin name (used for Fastify registration and debugging)
385
+ * @param definition - Plugin setup functions
386
+ * @returns ArcPlugin with forRoot() and forResource() methods
387
+ */
388
+ function createPlugin(name, definition) {
389
+ return {
390
+ name,
391
+ forRoot(opts) {
392
+ const plugin = async (fastify, pluginOpts) => {
393
+ const mergedOpts = {
394
+ ...opts,
395
+ ...pluginOpts
396
+ };
397
+ if (definition.forRoot) await definition.forRoot(fastify, mergedOpts);
398
+ };
399
+ return fp(plugin, {
400
+ name: `arc-plugin-${name}`,
401
+ fastify: "5.x"
402
+ });
403
+ },
404
+ forResource(opts) {
405
+ if (!definition.forResource) return {};
406
+ return definition.forResource({}, opts ?? {});
407
+ }
408
+ };
409
+ }
410
+
411
+ //#endregion
412
+ //#region src/core/arcCorePlugin.ts
413
+ /**
414
+ * Arc Core Plugin
415
+ *
416
+ * Sets up instance-scoped Arc systems:
417
+ * - HookSystem: Lifecycle hooks per app instance
418
+ * - ResourceRegistry: Resource tracking per app instance
419
+ * - Event integration: Wires CRUD operations to fastify.events
420
+ *
421
+ * This solves the global singleton leak problem where multiple
422
+ * app instances (e.g., in tests) would share state.
423
+ *
424
+ * @example
425
+ * import { arcCorePlugin } from '@classytic/arc';
426
+ *
427
+ * const app = Fastify();
428
+ * await app.register(arcCorePlugin);
429
+ *
430
+ * // Now use instance-scoped hooks
431
+ * app.arc.hooks.before('product', 'create', async (ctx) => {
432
+ * ctx.data.slug = slugify(ctx.data.name);
433
+ * });
434
+ */
435
+ const arcCorePlugin = async (fastify, opts = {}) => {
436
+ const { emitEvents = true, hookSystem, registry } = opts;
437
+ const actualHookSystem = hookSystem ?? new HookSystem();
438
+ const actualRegistry = registry ?? new ResourceRegistry();
439
+ fastify.decorate("arc", {
440
+ hooks: actualHookSystem,
441
+ registry: actualRegistry,
442
+ emitEvents,
443
+ externalOpenApiPaths: [],
444
+ plugins: /* @__PURE__ */ new Map()
445
+ });
446
+ fastify.addHook("onRequest", (request, _reply, done) => {
447
+ const store = {
448
+ requestId: request.id,
449
+ startTime: performance.now()
450
+ };
451
+ requestContext.storage.run(store, done);
452
+ });
453
+ fastify.addHook("preHandler", (request, _reply, done) => {
454
+ const store = requestContext.get();
455
+ if (store) {
456
+ store.user = request.user ?? null;
457
+ store.organizationId = request.scope?.kind === "member" ? request.scope.organizationId : request.scope?.kind === "elevated" ? request.scope.organizationId : void 0;
458
+ }
459
+ done();
460
+ });
461
+ if (emitEvents) {
462
+ const eventOperations = MUTATION_OPERATIONS;
463
+ for (const operation of eventOperations) actualHookSystem.after("*", operation, async (ctx) => {
464
+ if (!hasEvents(fastify)) return;
465
+ const store = requestContext.get();
466
+ const eventType = `${ctx.resource}.${operation}d`;
467
+ const userId = ctx.user?.id ?? ctx.user?._id;
468
+ const organizationId = ctx.context?._scope ? getOrgId(ctx.context._scope) : void 0;
469
+ const payload = {
470
+ resource: ctx.resource,
471
+ operation: ctx.operation,
472
+ data: ctx.result,
473
+ userId,
474
+ organizationId,
475
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
476
+ };
477
+ try {
478
+ await fastify.events.publish(eventType, payload, {
479
+ correlationId: store?.requestId,
480
+ resource: ctx.resource,
481
+ resourceId: extractId(ctx.result),
482
+ userId: userId ? String(userId) : void 0,
483
+ organizationId
484
+ });
485
+ } catch (error) {
486
+ fastify.log?.warn?.({
487
+ eventType,
488
+ error
489
+ }, "Failed to emit event");
490
+ }
491
+ });
492
+ }
493
+ fastify.addHook("onReady", async () => {
494
+ if (!hasEvents(fastify)) return;
495
+ try {
496
+ await fastify.events.publish("arc.ready", {
497
+ resources: actualRegistry.getAll().length,
498
+ hooks: actualHookSystem.getAll().length,
499
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
500
+ });
501
+ } catch {}
502
+ });
503
+ fastify.addHook("onClose", async () => {
504
+ actualHookSystem.clear();
505
+ actualRegistry._clear();
506
+ });
507
+ fastify.log?.debug?.("Arc core plugin enabled (instance-scoped hooks & registry)");
508
+ };
509
+ /** Extract document ID from a result (handles Mongoose docs and plain objects) */
510
+ function extractId(doc) {
511
+ if (!doc || typeof doc !== "object") return void 0;
512
+ const d = doc;
513
+ const rawId = d._id ?? d.id;
514
+ return rawId ? String(rawId) : void 0;
515
+ }
516
+ var arcCorePlugin_default = fp(arcCorePlugin, {
517
+ name: "arc-core",
518
+ fastify: "5.x"
519
+ });
520
+
521
+ //#endregion
522
+ export { arcCorePlugin_default as arcCorePlugin, arcCorePlugin as arcCorePluginFn, caching_default as cachingPlugin, cachingPlugin as cachingPluginFn, createPlugin, errorHandlerPlugin, errorHandlerPlugin as errorHandlerPluginFn, gracefulShutdown_default as gracefulShutdownPlugin, gracefulShutdownPlugin as gracefulShutdownPluginFn, health_default as healthPlugin, healthPlugin as healthPluginFn, requestId_default as requestIdPlugin, requestIdPlugin as requestIdPluginFn, sse_default as ssePlugin, ssePlugin as ssePluginFn };
523
+ //# sourceMappingURL=index.mjs.map