@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
@@ -1,1366 +0,0 @@
1
- import { ClientSession, Model, Document, Types } from 'mongoose';
2
- import { FastifyPluginAsync, FastifyRequest, FastifyReply, RouteHandlerMethod, FastifyInstance } from 'fastify';
3
- import { U as UserBase, P as PermissionCheck } from './types-B99TBmFV.js';
4
-
5
- /**
6
- * Repository Interface - Database-Agnostic CRUD Operations
7
- *
8
- * This is the standard interface that all repositories must implement.
9
- * MongoKit Repository already implements this interface.
10
- *
11
- * @example
12
- * ```typescript
13
- * import type { CrudRepository } from '@classytic/arc';
14
- *
15
- * // Your repository automatically satisfies this interface
16
- * const userRepo: CrudRepository<UserDocument> = new Repository(UserModel);
17
- * ```
18
- */
19
-
20
- /**
21
- * Query options for read operations
22
- */
23
- interface QueryOptions {
24
- /** MongoDB session for transactions */
25
- session?: ClientSession;
26
- /** Field selection - include or exclude fields */
27
- select?: string | string[] | Record<string, 0 | 1>;
28
- /** Relations to populate - string, array, or Mongoose populate options */
29
- populate?: string | string[] | Record<string, unknown>;
30
- /** Return plain JS objects instead of Mongoose documents */
31
- lean?: boolean;
32
- /** Allow additional adapter-specific options */
33
- [key: string]: unknown;
34
- }
35
- /**
36
- * Pagination parameters for list operations
37
- */
38
- interface PaginationParams<TDoc = unknown> {
39
- /** Filter criteria */
40
- filters?: Partial<TDoc> & Record<string, unknown>;
41
- /** Sort specification - string ("-createdAt") or object ({ createdAt: -1 }) */
42
- sort?: string | Record<string, 1 | -1>;
43
- /** Page number (1-indexed) */
44
- page?: number;
45
- /** Items per page */
46
- limit?: number;
47
- /** Allow additional options (select, populate, etc.) */
48
- [key: string]: unknown;
49
- }
50
- /**
51
- * Paginated result from list operations
52
- */
53
- interface PaginatedResult<TDoc> {
54
- /** Documents for current page */
55
- docs: TDoc[];
56
- /** Current page number */
57
- page: number;
58
- /** Items per page */
59
- limit: number;
60
- /** Total document count */
61
- total: number;
62
- /** Total page count */
63
- pages: number;
64
- /** Has next page */
65
- hasNext: boolean;
66
- /** Has previous page */
67
- hasPrev: boolean;
68
- }
69
- /**
70
- * Standard CRUD Repository Interface
71
- *
72
- * Defines the contract for data access operations.
73
- * All database adapters (MongoKit, Prisma, etc.) implement this interface.
74
- *
75
- * @typeParam TDoc - The document/entity type
76
- */
77
- interface CrudRepository<TDoc> {
78
- /**
79
- * Get paginated list of documents
80
- */
81
- getAll(params?: PaginationParams<TDoc>, options?: QueryOptions): Promise<PaginatedResult<TDoc>>;
82
- /**
83
- * Get single document by ID
84
- */
85
- getById(id: string, options?: QueryOptions): Promise<TDoc | null>;
86
- /**
87
- * Create new document
88
- */
89
- create(data: Partial<TDoc>, options?: {
90
- session?: ClientSession;
91
- [key: string]: unknown;
92
- }): Promise<TDoc>;
93
- /**
94
- * Update document by ID
95
- */
96
- update(id: string, data: Partial<TDoc>, options?: QueryOptions): Promise<TDoc | null>;
97
- /**
98
- * Delete document by ID
99
- */
100
- delete(id: string, options?: {
101
- session?: ClientSession;
102
- [key: string]: unknown;
103
- }): Promise<{
104
- success: boolean;
105
- message: string;
106
- }>;
107
- }
108
- /**
109
- * Extract document type from a repository
110
- *
111
- * @example
112
- * ```typescript
113
- * type UserDoc = InferDoc<typeof userRepository>;
114
- * // UserDoc is now the document type of userRepository
115
- * ```
116
- */
117
- type InferDoc<R> = R extends CrudRepository<infer T> ? T : never;
118
-
119
- /**
120
- * Define a resource with database adapter
121
- *
122
- * This is the MAIN entry point for creating Arc resources.
123
- * The adapter provides both repository and schema metadata.
124
- */
125
- declare function defineResource<TDoc = AnyRecord>(config: ResourceConfig<TDoc>): ResourceDefinition<TDoc>;
126
- interface ResolvedResourceConfig<TDoc = AnyRecord> extends ResourceConfig<TDoc> {
127
- _appliedPresets?: string[];
128
- _controllerOptions?: {
129
- slugField?: string;
130
- parentField?: string;
131
- [key: string]: unknown;
132
- };
133
- }
134
- declare class ResourceDefinition<TDoc = AnyRecord> {
135
- readonly name: string;
136
- readonly displayName: string;
137
- readonly tag: string;
138
- readonly prefix: string;
139
- readonly adapter?: DataAdapter<TDoc>;
140
- readonly controller?: IController<TDoc>;
141
- readonly schemaOptions: RouteSchemaOptions;
142
- readonly customSchemas: CrudSchemas;
143
- readonly permissions: ResourcePermissions;
144
- readonly additionalRoutes: AdditionalRoute[];
145
- readonly middlewares: MiddlewareConfig;
146
- readonly disableDefaultRoutes: boolean;
147
- readonly disabledRoutes: CrudRouteKey[];
148
- readonly organizationScoped: boolean;
149
- readonly events: Record<string, EventDefinition>;
150
- readonly _appliedPresets: string[];
151
- constructor(config: ResolvedResourceConfig<TDoc>);
152
- /** Get repository from adapter (if available) */
153
- get repository(): RepositoryLike | CrudRepository<TDoc> | undefined;
154
- /** Get model from adapter (if available) */
155
- get model(): Model<Document> | unknown | undefined;
156
- _validateControllerMethods(): void;
157
- toPlugin(): FastifyPluginAsync;
158
- /**
159
- * Get event definitions for registry
160
- */
161
- getEvents(): Array<{
162
- name: string;
163
- module: string;
164
- schema?: AnyRecord;
165
- description?: string;
166
- }>;
167
- /**
168
- * Get resource metadata
169
- */
170
- getMetadata(): ResourceMetadata;
171
- }
172
-
173
- /**
174
- * Resource Registry
175
- *
176
- * Singleton that tracks all registered resources for introspection.
177
- */
178
-
179
- interface RegisterOptions {
180
- module?: string;
181
- /** Pre-generated OpenAPI schemas */
182
- openApiSchemas?: OpenApiSchemas;
183
- }
184
- declare class ResourceRegistry {
185
- private _resources;
186
- private _frozen;
187
- constructor();
188
- /**
189
- * Register a resource
190
- */
191
- register(resource: ResourceDefinition<unknown>, options?: RegisterOptions): this;
192
- /**
193
- * Get resource by name
194
- */
195
- get(name: string): RegistryEntry | undefined;
196
- /**
197
- * Get all resources
198
- */
199
- getAll(): RegistryEntry[];
200
- /**
201
- * Get resources by module
202
- */
203
- getByModule(moduleName: string): RegistryEntry[];
204
- /**
205
- * Get resources by preset
206
- */
207
- getByPreset(presetName: string): RegistryEntry[];
208
- /**
209
- * Check if resource exists
210
- */
211
- has(name: string): boolean;
212
- /**
213
- * Get registry statistics
214
- */
215
- getStats(): RegistryStats;
216
- /**
217
- * Get full introspection data
218
- */
219
- getIntrospection(): IntrospectionData;
220
- /**
221
- * Freeze registry (prevent further registrations)
222
- */
223
- freeze(): void;
224
- /**
225
- * Check if frozen
226
- */
227
- isFrozen(): boolean;
228
- /**
229
- * Unfreeze registry (for testing)
230
- */
231
- _unfreeze(): void;
232
- /**
233
- * Clear all resources (for testing)
234
- */
235
- _clear(): void;
236
- /**
237
- * Group by key
238
- */
239
- private _groupBy;
240
- }
241
- declare const resourceRegistry: ResourceRegistry;
242
-
243
- /**
244
- * Hook System
245
- *
246
- * Lifecycle hooks for resource operations.
247
- * Allows intercepting and modifying data at various points.
248
- */
249
-
250
- type HookPhase = 'before' | 'after';
251
- type HookOperation = 'create' | 'update' | 'delete' | 'read' | 'list';
252
- interface HookContext<T = AnyRecord> {
253
- resource: string;
254
- operation: HookOperation;
255
- phase: HookPhase;
256
- data?: T;
257
- result?: T | T[];
258
- user?: UserBase;
259
- context?: RequestContext;
260
- meta?: AnyRecord;
261
- }
262
- type HookHandler<T = AnyRecord> = (ctx: HookContext<T>) => void | Promise<void> | T | Promise<T>;
263
- interface HookRegistration {
264
- resource: string;
265
- operation: HookOperation;
266
- phase: HookPhase;
267
- handler: HookHandler;
268
- priority: number;
269
- }
270
- interface HookSystemOptions {
271
- /** Custom logger for error reporting. Defaults to console.error */
272
- logger?: {
273
- error: (message: string, ...args: unknown[]) => void;
274
- };
275
- }
276
- declare class HookSystem {
277
- private hooks;
278
- private logger;
279
- constructor(options?: HookSystemOptions);
280
- /**
281
- * Generate hook key
282
- */
283
- private getKey;
284
- /**
285
- * Register a hook
286
- * Supports both object parameter and positional arguments
287
- */
288
- register<T = AnyRecord>(resourceOrOptions: string | {
289
- resource: string;
290
- operation: HookOperation;
291
- phase: HookPhase;
292
- handler: HookHandler<T>;
293
- priority?: number;
294
- }, operation?: HookOperation, phase?: HookPhase, handler?: HookHandler<T>, priority?: number): () => void;
295
- /**
296
- * Register before hook
297
- */
298
- before<T = AnyRecord>(resource: string, operation: HookOperation, handler: HookHandler<T>, priority?: number): () => void;
299
- /**
300
- * Register after hook
301
- */
302
- after<T = AnyRecord>(resource: string, operation: HookOperation, handler: HookHandler<T>, priority?: number): () => void;
303
- /**
304
- * Execute hooks for a given context
305
- */
306
- execute<T = AnyRecord>(ctx: HookContext<T>): Promise<T | undefined>;
307
- /**
308
- * Execute before hooks
309
- */
310
- executeBefore<T = AnyRecord>(resource: string, operation: HookOperation, data: T, options?: {
311
- user?: UserBase;
312
- context?: RequestContext;
313
- meta?: AnyRecord;
314
- }): Promise<T>;
315
- /**
316
- * Execute after hooks
317
- * Errors in after hooks are logged but don't fail the request
318
- */
319
- executeAfter<T = AnyRecord>(resource: string, operation: HookOperation, result: T | T[], options?: {
320
- user?: UserBase;
321
- context?: RequestContext;
322
- meta?: AnyRecord;
323
- }): Promise<void>;
324
- /**
325
- * Get all registered hooks
326
- */
327
- getAll(): HookRegistration[];
328
- /**
329
- * Get hooks for a specific resource
330
- */
331
- getForResource(resource: string): HookRegistration[];
332
- /**
333
- * Clear all hooks
334
- */
335
- clear(): void;
336
- /**
337
- * Clear hooks for a specific resource
338
- */
339
- clearResource(resource: string): void;
340
- }
341
- /**
342
- * Create a new isolated HookSystem instance
343
- *
344
- * Use this for:
345
- * - Test isolation (parallel test suites)
346
- * - Multiple app instances with independent hooks
347
- *
348
- * @example
349
- * const hooks = createHookSystem();
350
- * await app.register(arcCorePlugin, { hookSystem: hooks });
351
- *
352
- * @example With custom logger
353
- * const hooks = createHookSystem({ logger: fastify.log });
354
- */
355
- declare function createHookSystem(options?: HookSystemOptions): HookSystem;
356
- declare const hookSystem: HookSystem;
357
- /**
358
- * Register a before create hook
359
- */
360
- declare function beforeCreate<T = AnyRecord>(resource: string, handler: HookHandler<T>, priority?: number): () => void;
361
- /**
362
- * Register an after create hook
363
- */
364
- declare function afterCreate<T = AnyRecord>(resource: string, handler: HookHandler<T>, priority?: number): () => void;
365
- /**
366
- * Register a before update hook
367
- */
368
- declare function beforeUpdate<T = AnyRecord>(resource: string, handler: HookHandler<T>, priority?: number): () => void;
369
- /**
370
- * Register an after update hook
371
- */
372
- declare function afterUpdate<T = AnyRecord>(resource: string, handler: HookHandler<T>, priority?: number): () => void;
373
- /**
374
- * Register a before delete hook
375
- */
376
- declare function beforeDelete<T = AnyRecord>(resource: string, handler: HookHandler<T>, priority?: number): () => void;
377
- /**
378
- * Register an after delete hook
379
- */
380
- declare function afterDelete<T = AnyRecord>(resource: string, handler: HookHandler<T>, priority?: number): () => void;
381
-
382
- /**
383
- * Handler Types - Controller and Route Handler Definitions
384
- *
385
- * Two handler patterns supported:
386
- * 1. ControllerHandler - Arc's standard pattern (receives context object)
387
- * 2. FastifyHandler - Fastify native pattern (receives request, reply)
388
- *
389
- * Use `wrapHandler: true` for ControllerHandler, `wrapHandler: false` for FastifyHandler.
390
- */
391
-
392
- /**
393
- * Request context passed to controller handlers
394
- */
395
- interface IRequestContext {
396
- /** Route parameters (e.g., { id: '123' }) */
397
- params: Record<string, string>;
398
- /** Query string parameters */
399
- query: Record<string, unknown>;
400
- /** Request body */
401
- body: unknown;
402
- /** Authenticated user or null */
403
- user: UserBase | null;
404
- /** Request headers */
405
- headers: Record<string, string | undefined>;
406
- /** Organization ID (for multi-tenant apps) */
407
- organizationId?: string;
408
- /** Additional metadata and custom fields */
409
- metadata?: Record<string, unknown>;
410
- }
411
- /**
412
- * Standard response from controller handlers
413
- */
414
- interface IControllerResponse<T = unknown> {
415
- /** Operation success status */
416
- success: boolean;
417
- /** Response data */
418
- data?: T;
419
- /** Error message (when success is false) */
420
- error?: string;
421
- /** HTTP status code (default: 200 for success, 400 for error) */
422
- status?: number;
423
- /** Additional metadata */
424
- meta?: Record<string, unknown>;
425
- /** Error details (for debugging) */
426
- details?: Record<string, unknown>;
427
- }
428
- /**
429
- * Controller handler - Arc's standard pattern
430
- *
431
- * Receives a request context object, returns IControllerResponse.
432
- * Use with `wrapHandler: true` in additionalRoutes.
433
- *
434
- * @example
435
- * ```typescript
436
- * const createProduct: ControllerHandler<Product> = async (req) => {
437
- * const product = await productRepo.create(req.body);
438
- * return { success: true, data: product, status: 201 };
439
- * };
440
- *
441
- * additionalRoutes: [{
442
- * method: 'POST',
443
- * path: '/products',
444
- * handler: createProduct,
445
- * permissions: requireAuth(),
446
- * wrapHandler: true, // Arc wraps this into Fastify handler
447
- * }]
448
- * ```
449
- */
450
- type ControllerHandler<T = unknown> = (req: IRequestContext) => Promise<IControllerResponse<T>>;
451
- /**
452
- * Fastify native handler
453
- *
454
- * Standard Fastify request/reply pattern.
455
- * Use with `wrapHandler: false` in additionalRoutes.
456
- *
457
- * @example
458
- * ```typescript
459
- * const downloadFile: FastifyHandler = async (request, reply) => {
460
- * const file = await getFile(request.params.id);
461
- * reply.header('Content-Type', file.mimeType);
462
- * return reply.send(file.buffer);
463
- * };
464
- *
465
- * additionalRoutes: [{
466
- * method: 'GET',
467
- * path: '/files/:id/download',
468
- * handler: downloadFile,
469
- * permissions: requireAuth(),
470
- * wrapHandler: false, // Use as-is, no wrapping
471
- * }]
472
- * ```
473
- */
474
- type FastifyHandler = (request: FastifyRequest, reply: FastifyReply) => Promise<void> | void;
475
- /**
476
- * Union type for route handlers
477
- */
478
- type RouteHandler = ControllerHandler | FastifyHandler;
479
- /**
480
- * Controller interface for CRUD operations (strict)
481
- */
482
- interface IController<TDoc = unknown> {
483
- list(req: IRequestContext): Promise<IControllerResponse<{
484
- docs: TDoc[];
485
- total: number;
486
- }>>;
487
- get(req: IRequestContext): Promise<IControllerResponse<TDoc>>;
488
- create(req: IRequestContext): Promise<IControllerResponse<TDoc>>;
489
- update(req: IRequestContext): Promise<IControllerResponse<TDoc>>;
490
- delete(req: IRequestContext): Promise<IControllerResponse<{
491
- message: string;
492
- }>>;
493
- }
494
- /**
495
- * Flexible controller interface - accepts controllers with any handler style
496
- * Use this when your controller uses Fastify native handlers
497
- */
498
- interface ControllerLike {
499
- list?: unknown;
500
- get?: unknown;
501
- create?: unknown;
502
- update?: unknown;
503
- delete?: unknown;
504
- [key: string]: unknown;
505
- }
506
-
507
- type AnyRecord = Record<string, unknown>;
508
- type ObjectId = Types.ObjectId | string;
509
- /**
510
- * Flexible user type that accepts any object with id/ID properties.
511
- * Use this instead of `any` when dealing with user objects.
512
- * Re-exports UserBase from permissions module for convenience.
513
- * The actual user structure is defined by your app's auth system.
514
- */
515
- type UserLike = UserBase & {
516
- /** User email (optional) */
517
- email?: string;
518
- };
519
- /**
520
- * Extract user ID from a user object (supports both id and _id)
521
- */
522
- declare function getUserId(user: UserLike | null | undefined): string | undefined;
523
-
524
- type CrudController<TDoc> = IController<TDoc>;
525
- interface ApiResponse<T = unknown> {
526
- success: boolean;
527
- data?: T;
528
- error?: string;
529
- message?: string;
530
- meta?: Record<string, unknown>;
531
- }
532
- interface UserOrganization {
533
- userId: string;
534
- organizationId: string;
535
- [key: string]: unknown;
536
- }
537
- interface JWTPayload {
538
- sub: string;
539
- [key: string]: unknown;
540
- }
541
- interface RequestContext {
542
- operation?: string;
543
- user?: unknown;
544
- organizationId?: string;
545
- filters?: Record<string, unknown>;
546
- [key: string]: unknown;
547
- }
548
- /**
549
- * Controller-level query options - parsed from request query string
550
- * Includes pagination, filtering, and context data
551
- */
552
- interface ControllerQueryOptions {
553
- page?: number;
554
- limit?: number;
555
- sort?: string | Record<string, 1 | -1>;
556
- /** Simple populate (comma-separated string or array) */
557
- populate?: string | string[] | Record<string, unknown>;
558
- /**
559
- * Advanced populate options (Mongoose-compatible)
560
- * When set, takes precedence over simple `populate`
561
- */
562
- populateOptions?: PopulateOption[];
563
- select?: string | string[] | Record<string, 0 | 1>;
564
- filters?: Record<string, unknown>;
565
- search?: string;
566
- lean?: boolean;
567
- after?: string;
568
- user?: unknown;
569
- organizationId?: string;
570
- context?: Record<string, unknown>;
571
- /** Allow additional options */
572
- [key: string]: unknown;
573
- }
574
- /**
575
- * Mongoose-compatible populate option for advanced field selection
576
- * Used when you need to select specific fields from populated documents
577
- *
578
- * @example
579
- * ```typescript
580
- * // URL: ?populate[author][select]=name,email
581
- * // Generates: { path: 'author', select: 'name email' }
582
- * ```
583
- */
584
- interface PopulateOption {
585
- /** Field path to populate */
586
- path: string;
587
- /** Fields to select (space-separated) */
588
- select?: string;
589
- /** Filter conditions for populated documents */
590
- match?: Record<string, unknown>;
591
- /** Query options (limit, sort, skip) */
592
- options?: {
593
- limit?: number;
594
- sort?: Record<string, 1 | -1>;
595
- skip?: number;
596
- };
597
- /** Nested populate configuration */
598
- populate?: PopulateOption;
599
- }
600
- /**
601
- * Parsed query result from QueryParser
602
- * Includes pagination, sorting, filtering, etc.
603
- *
604
- * The index signature allows custom query parsers (like MongoKit's QueryParser)
605
- * to add additional fields without breaking Arc's type system.
606
- */
607
- interface ParsedQuery {
608
- filters?: Record<string, unknown>;
609
- limit?: number;
610
- sort?: string | Record<string, 1 | -1>;
611
- /** Simple populate (comma-separated string or array) */
612
- populate?: string | string[] | Record<string, unknown>;
613
- /**
614
- * Advanced populate options (Mongoose-compatible)
615
- * When set, takes precedence over simple `populate`
616
- * @example [{ path: 'author', select: 'name email' }]
617
- */
618
- populateOptions?: PopulateOption[];
619
- search?: string;
620
- page?: number;
621
- after?: string;
622
- select?: string | string[] | Record<string, 0 | 1>;
623
- /** Allow additional fields from custom query parsers */
624
- [key: string]: unknown;
625
- }
626
- /**
627
- * Query Parser Interface
628
- * Implement this to create custom query parsers
629
- *
630
- * @example MongoKit QueryParser
631
- * ```typescript
632
- * import { QueryParser } from '@classytic/mongokit';
633
- * const queryParser = new QueryParser();
634
- * ```
635
- */
636
- interface QueryParserInterface {
637
- parse(query: Record<string, unknown> | null | undefined): ParsedQuery;
638
- /**
639
- * Optional: Export OpenAPI schema for query parameters
640
- * Use this to document query parameters in OpenAPI/Swagger
641
- */
642
- getQuerySchema?(): {
643
- type: 'object';
644
- properties: Record<string, unknown>;
645
- required?: string[];
646
- };
647
- }
648
- interface FastifyRequestExtras {
649
- user?: unknown;
650
- organizationId?: string;
651
- }
652
- interface RequestWithExtras extends Omit<FastifyRequest, 'user'> {
653
- /**
654
- * Arc metadata - set by createCrudRouter
655
- * Contains resource configuration and schema options
656
- */
657
- arc?: {
658
- resourceName?: string;
659
- schemaOptions?: RouteSchemaOptions;
660
- permissions?: ResourcePermissions;
661
- };
662
- user?: unknown;
663
- organizationId?: string;
664
- context?: Record<string, unknown>;
665
- _policyFilters?: Record<string, unknown>;
666
- fieldMask?: string[];
667
- _ownershipCheck?: Record<string, unknown>;
668
- }
669
- type FastifyWithAuth = FastifyInstance & {
670
- authenticate: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
671
- };
672
- /**
673
- * Arc core decorator interface
674
- * Added by arcCorePlugin to provide instance-scoped hooks and registry
675
- */
676
- interface ArcDecorator {
677
- /** Instance-scoped hook system */
678
- hooks: HookSystem;
679
- /** Instance-scoped resource registry */
680
- registry: ResourceRegistry;
681
- /** Whether event emission is enabled */
682
- emitEvents: boolean;
683
- }
684
- /**
685
- * Events decorator interface
686
- * Added by eventPlugin to provide event pub/sub
687
- */
688
- interface EventsDecorator {
689
- /** Publish an event */
690
- publish: <T>(type: string, payload: T, meta?: Partial<{
691
- id: string;
692
- timestamp: Date;
693
- }>) => Promise<void>;
694
- /** Subscribe to events */
695
- subscribe: (pattern: string, handler: (event: unknown) => void | Promise<void>) => Promise<() => void>;
696
- /** Get transport name */
697
- transportName: string;
698
- }
699
- /**
700
- * Fastify instance with Arc decorators
701
- * Arc adds these decorators via plugins/presets
702
- */
703
- type FastifyWithDecorators = FastifyInstance & {
704
- arc?: ArcDecorator;
705
- events?: EventsDecorator;
706
- authenticate?: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
707
- organizationScoped?: (options?: {
708
- required?: boolean;
709
- }) => RouteHandlerMethod;
710
- [key: string]: unknown;
711
- };
712
- interface OwnershipCheck {
713
- field: string;
714
- userField?: string;
715
- }
716
-
717
- interface ResourceConfig<TDoc = AnyRecord> {
718
- name: string;
719
- displayName?: string;
720
- tag?: string;
721
- prefix?: string;
722
- adapter?: DataAdapter<TDoc>;
723
- /** Controller instance - accepts any object with CRUD methods */
724
- controller?: IController<TDoc> | ControllerLike | Record<string, any> | object;
725
- queryParser?: unknown;
726
- permissions?: ResourcePermissions;
727
- schemaOptions?: RouteSchemaOptions;
728
- openApiSchemas?: OpenApiSchemas;
729
- customSchemas?: Partial<CrudSchemas>;
730
- presets?: Array<string | PresetResult | {
731
- name: string;
732
- [key: string]: unknown;
733
- }>;
734
- hooks?: ResourceHooks;
735
- middlewares?: MiddlewareConfig;
736
- additionalRoutes?: AdditionalRoute[];
737
- disableCrud?: boolean;
738
- disableDefaultRoutes?: boolean;
739
- disabledRoutes?: CrudRouteKey[];
740
- organizationScoped?: boolean;
741
- module?: string;
742
- events?: Record<string, EventDefinition>;
743
- skipValidation?: boolean;
744
- skipRegistry?: boolean;
745
- _appliedPresets?: string[];
746
- }
747
- /**
748
- * Resource-level permissions
749
- * ONLY PermissionCheck functions allowed - no string arrays
750
- */
751
- interface ResourcePermissions {
752
- list?: PermissionCheck;
753
- get?: PermissionCheck;
754
- create?: PermissionCheck;
755
- update?: PermissionCheck;
756
- delete?: PermissionCheck;
757
- }
758
- interface ResourceHooks {
759
- beforeCreate?: (data: AnyRecord) => Promise<AnyRecord> | AnyRecord;
760
- afterCreate?: (doc: AnyRecord) => Promise<void> | void;
761
- beforeUpdate?: (id: string, data: AnyRecord) => Promise<AnyRecord> | AnyRecord;
762
- afterUpdate?: (doc: AnyRecord) => Promise<void> | void;
763
- beforeDelete?: (id: string) => Promise<void> | void;
764
- afterDelete?: (id: string) => Promise<void> | void;
765
- }
766
- /**
767
- * Additional route definition for custom endpoints
768
- */
769
- interface AdditionalRoute {
770
- /** HTTP method */
771
- method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
772
- /** Route path (relative to resource prefix) */
773
- path: string;
774
- /**
775
- * Handler - string (controller method name) or function
776
- * Function can be Fastify handler or any (request, reply) => Promise<any>
777
- */
778
- handler: string | RouteHandlerMethod | ((request: any, reply: any) => any);
779
- /** Permission check - REQUIRED */
780
- permissions: PermissionCheck;
781
- /**
782
- * Handler type - REQUIRED, no auto-detection
783
- * true = ControllerHandler (receives context object)
784
- * false = FastifyHandler (receives request, reply)
785
- */
786
- wrapHandler: boolean;
787
- /** OpenAPI summary */
788
- summary?: string;
789
- /** OpenAPI description */
790
- description?: string;
791
- /** OpenAPI tags */
792
- tags?: string[];
793
- /**
794
- * Custom route-level middleware
795
- * Can be an array of handlers or a function that receives fastify and returns handlers
796
- * @example
797
- * // Direct array
798
- * preHandler: [myMiddleware]
799
- * // Function that receives fastify (for accessing decorators)
800
- * preHandler: (fastify) => [fastify.customerContext({ required: true })]
801
- */
802
- preHandler?: RouteHandlerMethod[] | ((fastify: any) => RouteHandlerMethod[]);
803
- /** Fastify route schema */
804
- schema?: Record<string, unknown>;
805
- }
806
- interface RouteSchemaOptions {
807
- hiddenFields?: string[];
808
- readonlyFields?: string[];
809
- requiredFields?: string[];
810
- optionalFields?: string[];
811
- excludeFields?: string[];
812
- fieldRules?: Record<string, {
813
- systemManaged?: boolean;
814
- [key: string]: unknown;
815
- }>;
816
- query?: Record<string, unknown>;
817
- }
818
- interface FieldRule {
819
- field: string;
820
- required?: boolean;
821
- readonly?: boolean;
822
- hidden?: boolean;
823
- }
824
- /**
825
- * CRUD Route Schemas (Fastify Native Format)
826
- *
827
- * @example
828
- * {
829
- * list: {
830
- * querystring: { type: 'object', properties: { page: { type: 'number' } } },
831
- * response: { 200: { type: 'object', properties: { docs: { type: 'array' } } } }
832
- * },
833
- * create: {
834
- * body: { type: 'object', properties: { name: { type: 'string' } } },
835
- * response: { 201: { type: 'object' } }
836
- * }
837
- * }
838
- */
839
- interface CrudSchemas {
840
- /** GET / - List all resources */
841
- list?: {
842
- querystring?: Record<string, unknown>;
843
- response?: Record<number, unknown>;
844
- [key: string]: unknown;
845
- };
846
- /** GET /:id - Get single resource */
847
- get?: {
848
- params?: Record<string, unknown>;
849
- response?: Record<number, unknown>;
850
- [key: string]: unknown;
851
- };
852
- /** POST / - Create resource */
853
- create?: {
854
- body?: Record<string, unknown>;
855
- response?: Record<number, unknown>;
856
- [key: string]: unknown;
857
- };
858
- /** PATCH /:id - Update resource */
859
- update?: {
860
- params?: Record<string, unknown>;
861
- body?: Record<string, unknown>;
862
- response?: Record<number, unknown>;
863
- [key: string]: unknown;
864
- };
865
- /** DELETE /:id - Delete resource */
866
- delete?: {
867
- params?: Record<string, unknown>;
868
- response?: Record<number, unknown>;
869
- [key: string]: unknown;
870
- };
871
- [key: string]: unknown;
872
- }
873
- interface OpenApiSchemas {
874
- entity?: unknown;
875
- createBody?: unknown;
876
- updateBody?: unknown;
877
- params?: unknown;
878
- listQuery?: unknown;
879
- /**
880
- * Explicit response schema for OpenAPI documentation.
881
- * If provided, this will be used as-is for the response schema.
882
- * If not provided, response schema is auto-generated from createBody.
883
- *
884
- * Note: This is for OpenAPI docs only - does NOT affect Fastify serialization.
885
- *
886
- * @example
887
- * response: {
888
- * type: 'object',
889
- * properties: {
890
- * _id: { type: 'string' },
891
- * name: { type: 'string' },
892
- * email: { type: 'string' },
893
- * // Exclude password, include virtuals
894
- * fullName: { type: 'string' },
895
- * }
896
- * }
897
- */
898
- response?: unknown;
899
- [key: string]: unknown;
900
- }
901
- /** Handler for middleware functions */
902
- type MiddlewareHandler = (request: RequestWithExtras, reply: FastifyReply) => Promise<unknown>;
903
- type CrudRouteKey = 'list' | 'get' | 'create' | 'update' | 'delete';
904
- interface MiddlewareConfig {
905
- list?: MiddlewareHandler[];
906
- get?: MiddlewareHandler[];
907
- create?: MiddlewareHandler[];
908
- update?: MiddlewareHandler[];
909
- delete?: MiddlewareHandler[];
910
- [key: string]: MiddlewareHandler[] | undefined;
911
- }
912
- /**
913
- * JWT utilities provided to authenticator
914
- * Arc provides these helpers, app uses them as needed
915
- */
916
- interface JwtContext {
917
- /** Verify a JWT token and return decoded payload */
918
- verify: <T = Record<string, unknown>>(token: string) => T;
919
- /** Sign a payload and return JWT token */
920
- sign: (payload: Record<string, unknown>, options?: {
921
- expiresIn?: string;
922
- }) => string;
923
- /** Decode without verification (for inspection) */
924
- decode: <T = Record<string, unknown>>(token: string) => T | null;
925
- }
926
- /**
927
- * Context passed to app's authenticator function
928
- */
929
- interface AuthenticatorContext {
930
- /** JWT utilities (available if jwt.secret provided) */
931
- jwt: JwtContext | null;
932
- /** Fastify instance for advanced use cases */
933
- fastify: FastifyInstance;
934
- }
935
- /**
936
- * App-provided authenticator function
937
- *
938
- * Arc calls this for every non-public route.
939
- * App has FULL control over authentication logic.
940
- *
941
- * @example
942
- * ```typescript
943
- * // Simple JWT auth
944
- * authenticate: async (request, { jwt }) => {
945
- * const token = request.headers.authorization?.split(' ')[1];
946
- * if (!token || !jwt) return null;
947
- * const decoded = jwt.verify(token);
948
- * return userRepo.findById(decoded.id);
949
- * }
950
- *
951
- * // Multi-strategy (JWT + API Key)
952
- * authenticate: async (request, { jwt }) => {
953
- * const apiKey = request.headers['x-api-key'];
954
- * if (apiKey) {
955
- * const result = await apiKeyService.verify(apiKey);
956
- * if (result) return { _id: result.userId, isApiKey: true };
957
- * }
958
- * const token = request.headers.authorization?.split(' ')[1];
959
- * if (token && jwt) {
960
- * const decoded = jwt.verify(token);
961
- * return userRepo.findById(decoded.id);
962
- * }
963
- * return null;
964
- * }
965
- * ```
966
- */
967
- type Authenticator = (request: FastifyRequest, context: AuthenticatorContext) => Promise<any | null> | any | null;
968
- /**
969
- * Token pair returned by issueTokens helper
970
- */
971
- interface TokenPair {
972
- /** Access token (JWT) */
973
- accessToken: string;
974
- /** Refresh token (JWT with longer expiry) */
975
- refreshToken?: string;
976
- /** Access token expiry in seconds */
977
- expiresIn: number;
978
- /** Refresh token expiry in seconds */
979
- refreshExpiresIn?: number;
980
- /** Token type (always 'Bearer') */
981
- tokenType: 'Bearer';
982
- }
983
- /**
984
- * Auth helpers available on fastify.auth
985
- *
986
- * @example
987
- * ```typescript
988
- * // In login handler
989
- * const user = await userRepo.findByEmail(email);
990
- * if (!user || !await bcrypt.compare(password, user.password)) {
991
- * return reply.code(401).send({ error: 'Invalid credentials' });
992
- * }
993
- *
994
- * const tokens = fastify.auth.issueTokens({
995
- * id: user._id,
996
- * email: user.email,
997
- * roles: user.roles,
998
- * });
999
- *
1000
- * return { success: true, ...tokens, user };
1001
- * ```
1002
- */
1003
- interface AuthHelpers {
1004
- /** JWT utilities (if configured) */
1005
- jwt: JwtContext | null;
1006
- /**
1007
- * Issue access + refresh tokens for a user
1008
- * App calls this after validating credentials
1009
- */
1010
- issueTokens: (payload: Record<string, unknown>, options?: {
1011
- expiresIn?: string;
1012
- refreshExpiresIn?: string;
1013
- }) => TokenPair;
1014
- /**
1015
- * Verify a refresh token and return decoded payload
1016
- */
1017
- verifyRefreshToken: <T = Record<string, unknown>>(token: string) => T;
1018
- }
1019
- interface ServiceContext {
1020
- user?: unknown;
1021
- organizationId?: string;
1022
- requestId?: string;
1023
- select?: string[] | Record<string, 0 | 1>;
1024
- populate?: string | string[];
1025
- lean?: boolean;
1026
- }
1027
- interface PresetHook {
1028
- operation: 'create' | 'update' | 'delete' | 'read' | 'list';
1029
- phase: 'before' | 'after';
1030
- handler: (ctx: any) => void | Promise<void> | AnyRecord | Promise<AnyRecord>;
1031
- priority?: number;
1032
- }
1033
- interface PresetResult {
1034
- name: string;
1035
- additionalRoutes?: AdditionalRoute[] | ((permissions: ResourcePermissions) => AdditionalRoute[]);
1036
- middlewares?: MiddlewareConfig;
1037
- schemaOptions?: RouteSchemaOptions;
1038
- controllerOptions?: Record<string, unknown>;
1039
- hooks?: PresetHook[];
1040
- }
1041
- type PresetFunction = (config: ResourceConfig) => PresetResult;
1042
- interface GracefulShutdownOptions {
1043
- timeout?: number;
1044
- onShutdown?: () => Promise<void> | void;
1045
- signals?: NodeJS.Signals[];
1046
- logEvents?: boolean;
1047
- }
1048
- interface RequestIdOptions {
1049
- headerName?: string;
1050
- generator?: () => string;
1051
- }
1052
- interface HealthOptions {
1053
- path?: string;
1054
- check?: () => Promise<any>;
1055
- }
1056
- interface HealthCheck {
1057
- healthy: boolean;
1058
- timestamp: string;
1059
- [key: string]: unknown;
1060
- }
1061
- /**
1062
- * Auth Plugin Options - Clean, Minimal Configuration
1063
- *
1064
- * Arc provides JWT infrastructure and calls your authenticator.
1065
- * You control ALL authentication logic.
1066
- *
1067
- * @example
1068
- * ```typescript
1069
- * // Minimal: just JWT (uses default jwtVerify)
1070
- * auth: {
1071
- * jwt: { secret: process.env.JWT_SECRET },
1072
- * }
1073
- *
1074
- * // With custom authenticator (recommended)
1075
- * auth: {
1076
- * jwt: { secret: process.env.JWT_SECRET },
1077
- * authenticate: async (request, { jwt }) => {
1078
- * const token = request.headers.authorization?.split(' ')[1];
1079
- * if (!token) return null;
1080
- * const decoded = jwt.verify(token);
1081
- * return userRepo.findById(decoded.id);
1082
- * },
1083
- * }
1084
- *
1085
- * // Multi-strategy (JWT + API Key)
1086
- * auth: {
1087
- * jwt: { secret: process.env.JWT_SECRET },
1088
- * authenticate: async (request, { jwt }) => {
1089
- * // Try API key first (faster)
1090
- * const apiKey = request.headers['x-api-key'];
1091
- * if (apiKey) {
1092
- * const result = await apiKeyService.verify(apiKey);
1093
- * if (result) return { _id: result.userId, isApiKey: true };
1094
- * }
1095
- * // Try JWT
1096
- * const token = request.headers.authorization?.split(' ')[1];
1097
- * if (token) {
1098
- * const decoded = jwt.verify(token);
1099
- * return userRepo.findById(decoded.id);
1100
- * }
1101
- * return null;
1102
- * },
1103
- * onFailure: (request, reply) => {
1104
- * reply.code(401).send({
1105
- * success: false,
1106
- * error: 'Authentication required',
1107
- * message: 'Use Bearer token or X-API-Key header',
1108
- * });
1109
- * },
1110
- * }
1111
- * ```
1112
- */
1113
- interface AuthPluginOptions {
1114
- /**
1115
- * JWT configuration (optional but recommended)
1116
- * If provided, jwt utilities are available in authenticator context
1117
- */
1118
- jwt?: {
1119
- /** JWT secret (required for JWT features) */
1120
- secret: string;
1121
- /** Access token expiry (default: '15m') */
1122
- expiresIn?: string;
1123
- /** Refresh token secret (defaults to main secret) */
1124
- refreshSecret?: string;
1125
- /** Refresh token expiry (default: '7d') */
1126
- refreshExpiresIn?: string;
1127
- /** Additional @fastify/jwt sign options */
1128
- sign?: Record<string, unknown>;
1129
- /** Additional @fastify/jwt verify options */
1130
- verify?: Record<string, unknown>;
1131
- };
1132
- /**
1133
- * Custom authenticator function (recommended)
1134
- *
1135
- * Arc calls this for non-public routes.
1136
- * Return user object to authenticate, null/undefined to reject.
1137
- *
1138
- * If not provided and jwt.secret is set, uses default jwtVerify.
1139
- */
1140
- authenticate?: Authenticator;
1141
- /**
1142
- * Custom auth failure handler
1143
- * Customize the 401 response when authentication fails
1144
- */
1145
- onFailure?: (request: FastifyRequest, reply: FastifyReply, error?: Error) => void | Promise<void>;
1146
- /**
1147
- * Property name to store user on request (default: 'user')
1148
- */
1149
- userProperty?: string;
1150
- }
1151
- interface OrgScopeOptions {
1152
- enabled?: boolean;
1153
- header?: string;
1154
- headerName?: string;
1155
- queryParam?: string;
1156
- bypassRoles?: string[];
1157
- userOrgsPath?: string;
1158
- validateMembership?: (user: unknown, orgId: string) => Promise<boolean> | boolean;
1159
- }
1160
- interface IntrospectionPluginOptions {
1161
- path?: string;
1162
- prefix?: string;
1163
- enabled?: boolean;
1164
- authRoles?: string[];
1165
- }
1166
- interface CrudRouterOptions {
1167
- /** Route prefix */
1168
- prefix?: string;
1169
- /** Permission checks for CRUD operations */
1170
- permissions?: ResourcePermissions;
1171
- /** OpenAPI tag for grouping routes */
1172
- tag?: string;
1173
- /** JSON schemas for CRUD operations */
1174
- schemas?: Partial<CrudSchemas>;
1175
- /** Middlewares for each CRUD operation */
1176
- middlewares?: MiddlewareConfig;
1177
- /** Additional custom routes (from presets or user-defined) */
1178
- additionalRoutes?: AdditionalRoute[];
1179
- /** Disable all default CRUD routes */
1180
- disableDefaultRoutes?: boolean;
1181
- /** Disable specific CRUD routes */
1182
- disabledRoutes?: CrudRouteKey[];
1183
- /** Enable organization-scoped filtering */
1184
- organizationScoped?: boolean;
1185
- /** Resource name for lifecycle hooks */
1186
- resourceName?: string;
1187
- /** Schema generation options */
1188
- schemaOptions?: RouteSchemaOptions;
1189
- }
1190
- interface ResourceMetadata {
1191
- name: string;
1192
- displayName?: string;
1193
- tag?: string;
1194
- prefix: string;
1195
- module?: string;
1196
- permissions?: ResourcePermissions;
1197
- presets: string[];
1198
- additionalRoutes?: AdditionalRoute[];
1199
- routes: Array<{
1200
- method: string;
1201
- path: string;
1202
- handler?: string;
1203
- operation?: string;
1204
- summary?: string;
1205
- }>;
1206
- events?: string[];
1207
- }
1208
- interface RegistryEntry extends ResourceMetadata {
1209
- plugin: unknown;
1210
- adapter?: {
1211
- type: string;
1212
- name: string;
1213
- } | null;
1214
- events?: string[];
1215
- disableDefaultRoutes?: boolean;
1216
- openApiSchemas?: OpenApiSchemas;
1217
- registeredAt?: string;
1218
- }
1219
- interface RegistryStats {
1220
- total?: number;
1221
- totalResources: number;
1222
- byTag?: Record<string, number>;
1223
- byModule?: Record<string, number>;
1224
- presetUsage?: Record<string, number>;
1225
- totalRoutes?: number;
1226
- totalEvents?: number;
1227
- }
1228
- interface IntrospectionData {
1229
- resources: ResourceMetadata[];
1230
- stats: RegistryStats;
1231
- generatedAt?: string;
1232
- }
1233
- interface EventDefinition {
1234
- name: string;
1235
- handler: (data: unknown) => Promise<void> | void;
1236
- schema?: Record<string, unknown>;
1237
- description?: string;
1238
- }
1239
- interface ConfigError {
1240
- field: string;
1241
- message: string;
1242
- code?: string;
1243
- }
1244
- interface ValidationResult$1 {
1245
- valid: boolean;
1246
- errors: ConfigError[];
1247
- }
1248
- interface ValidateOptions {
1249
- strict?: boolean;
1250
- }
1251
-
1252
- /**
1253
- * Infer document type from DataAdapter or ResourceConfig
1254
- */
1255
- type InferDocType<T> = T extends DataAdapter<infer D> ? D : T extends ResourceConfig<infer D> ? D : never;
1256
- type InferResourceDoc<T> = T extends ResourceConfig<infer D> ? D : never;
1257
- type TypedResourceConfig<TDoc> = ResourceConfig<TDoc>;
1258
- type TypedController<TDoc> = IController<TDoc>;
1259
- type TypedRepository<TDoc> = CrudRepository<TDoc>;
1260
- interface BaseControllerOptions {
1261
- /** Query parser instance */
1262
- queryParser: QueryParserInterface;
1263
- /** Schema generation options */
1264
- schemaOptions?: RouteSchemaOptions;
1265
- /** Maximum items per page */
1266
- maxLimit?: number;
1267
- /** Default items per page */
1268
- defaultLimit?: number;
1269
- /** Default sort field */
1270
- defaultSort?: string;
1271
- /** Resource name for hooks */
1272
- resourceName?: string;
1273
- /** Disable event emission */
1274
- disableEvents?: boolean;
1275
- }
1276
-
1277
- /**
1278
- * Data Adapter Interface - Database Abstraction Layer
1279
- *
1280
- * Core abstraction that allows Arc to work with any database.
1281
- * This is the ONLY contract between Arc and data persistence.
1282
- */
1283
-
1284
- /**
1285
- * Minimal repository interface for flexible adapter compatibility
1286
- * Accepts any object with CRUD method names
1287
- */
1288
- interface RepositoryLike {
1289
- getAll: unknown;
1290
- getById: unknown;
1291
- create: unknown;
1292
- update: unknown;
1293
- delete: unknown;
1294
- [key: string]: unknown;
1295
- }
1296
- interface DataAdapter<TDoc = unknown> {
1297
- /**
1298
- * Repository implementing CRUD operations
1299
- * Accepts CrudRepository, MongoKit Repository, or any compatible object
1300
- */
1301
- repository: CrudRepository<TDoc> | RepositoryLike;
1302
- /** Adapter identifier for introspection */
1303
- readonly type: 'mongoose' | 'prisma' | 'drizzle' | 'typeorm' | 'custom';
1304
- /** Human-readable name */
1305
- readonly name: string;
1306
- /**
1307
- * Generate OpenAPI schemas for CRUD operations
1308
- *
1309
- * This method allows each adapter to generate schemas specific to its ORM/database.
1310
- * For example, Mongoose adapter can use mongokit to generate schemas from Mongoose models.
1311
- *
1312
- * @param options - Schema generation options (field rules, populate settings, etc.)
1313
- * @returns OpenAPI schemas for CRUD operations or null if not supported
1314
- */
1315
- generateSchemas?(options?: RouteSchemaOptions): OpenApiSchemas | null;
1316
- /** Extract schema metadata for OpenAPI/introspection */
1317
- getSchemaMetadata?(): SchemaMetadata | null;
1318
- /** Validate data against schema before persistence */
1319
- validate?(data: unknown): Promise<ValidationResult> | ValidationResult;
1320
- /** Health check for database connection */
1321
- healthCheck?(): Promise<boolean>;
1322
- /** Close/cleanup resources */
1323
- close?(): Promise<void>;
1324
- }
1325
- interface SchemaMetadata {
1326
- name: string;
1327
- fields: Record<string, FieldMetadata>;
1328
- indexes?: Array<{
1329
- fields: string[];
1330
- unique?: boolean;
1331
- sparse?: boolean;
1332
- }>;
1333
- relations?: Record<string, RelationMetadata>;
1334
- }
1335
- interface FieldMetadata {
1336
- type: 'string' | 'number' | 'boolean' | 'date' | 'object' | 'array' | 'objectId' | 'enum';
1337
- required?: boolean;
1338
- unique?: boolean;
1339
- default?: unknown;
1340
- enum?: Array<string | number>;
1341
- min?: number;
1342
- max?: number;
1343
- minLength?: number;
1344
- maxLength?: number;
1345
- pattern?: string;
1346
- description?: string;
1347
- ref?: string;
1348
- array?: boolean;
1349
- }
1350
- interface RelationMetadata {
1351
- type: 'one-to-one' | 'one-to-many' | 'many-to-many';
1352
- target: string;
1353
- foreignKey?: string;
1354
- through?: string;
1355
- }
1356
- interface ValidationResult {
1357
- valid: boolean;
1358
- errors?: Array<{
1359
- field: string;
1360
- message: string;
1361
- code?: string;
1362
- }>;
1363
- }
1364
- type AdapterFactory<TDoc> = (config: unknown) => DataAdapter<TDoc>;
1365
-
1366
- export { type InferDocType as $, type AnyRecord as A, type CrudController as B, type ControllerQueryOptions as C, type DataAdapter as D, type FieldRule as E, type FieldMetadata as F, type CrudSchemas as G, HookSystem as H, type IController as I, type JWTPayload as J, type AdditionalRoute as K, type PresetFunction as L, type MiddlewareConfig as M, type EventDefinition as N, type OwnershipCheck as O, type PaginatedResult as P, type QueryParserInterface as Q, type RouteSchemaOptions as R, type ServiceContext as S, type ResourceMetadata as T, type UserOrganization as U, type ValidationResult as V, type RegistryEntry as W, type RegistryStats as X, type IntrospectionData as Y, type OrgScopeOptions as Z, type CrudRouterOptions as _, type IRequestContext as a, type InferResourceDoc as a0, type TypedResourceConfig as a1, type TypedController as a2, type TypedRepository as a3, type ConfigError as a4, type ValidationResult$1 as a5, type ValidateOptions as a6, type HealthCheck as a7, type HealthOptions as a8, type GracefulShutdownOptions as a9, createHookSystem as aA, beforeCreate as aB, afterCreate as aC, beforeUpdate as aD, afterUpdate as aE, beforeDelete as aF, afterDelete as aG, type HookPhase as aH, type HookOperation as aI, type HookRegistration as aJ, type HookSystemOptions as aK, type RequestIdOptions as aa, hookSystem as ab, type HookContext as ac, type HookHandler as ad, type ParsedQuery as ae, type OpenApiSchemas as af, type AdapterFactory as ag, type ObjectId as ah, type UserLike as ai, getUserId as aj, type PopulateOption as ak, type ArcDecorator as al, type EventsDecorator as am, type ResourcePermissions as an, type ResourceHooks as ao, type MiddlewareHandler as ap, type JwtContext as aq, type AuthenticatorContext as ar, type Authenticator as as, type TokenPair as at, type PresetHook as au, type BaseControllerOptions as av, type PaginationParams as aw, type InferDoc as ax, type ControllerHandler as ay, type FastifyHandler as az, type RequestContext as b, type IControllerResponse as c, type RequestWithExtras as d, type CrudRouteKey as e, type PresetResult as f, type AuthHelpers as g, type AuthPluginOptions as h, type IntrospectionPluginOptions as i, ResourceRegistry as j, type RegisterOptions as k, type ResourceConfig as l, type SchemaMetadata as m, type RelationMetadata as n, type RepositoryLike as o, defineResource as p, ResourceDefinition as q, resourceRegistry as r, type ApiResponse as s, type ControllerLike as t, type FastifyRequestExtras as u, type FastifyWithAuth as v, type FastifyWithDecorators as w, type QueryOptions as x, type CrudRepository as y, type RouteHandler as z };