@classytic/arc 2.11.4 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/README.md +16 -12
  2. package/dist/{BaseController-swXruJ2_.mjs → BaseController-DX_T-bDB.mjs} +388 -423
  3. package/dist/EventTransport-CT_52aWU.d.mts +34 -0
  4. package/dist/EventTransport-DLWoUMHy.mjs +103 -0
  5. package/dist/{ResourceRegistry-DkAeAuTX.mjs → ResourceRegistry-CTERg_2x.mjs} +139 -66
  6. package/dist/audit/index.d.mts +2 -2
  7. package/dist/audit/index.mjs +1 -1
  8. package/dist/auth/audit.d.mts +199 -0
  9. package/dist/auth/audit.mjs +288 -0
  10. package/dist/auth/index.d.mts +3 -3
  11. package/dist/auth/index.mjs +117 -191
  12. package/dist/{betterAuthOpenApi-DwxtK3uG.mjs → betterAuthOpenApi--M_i87dQ.mjs} +1 -1
  13. package/dist/buildHandler-olo-gt94.mjs +610 -0
  14. package/dist/cache/index.mjs +3 -3
  15. package/dist/cli/commands/describe.d.mts +89 -13
  16. package/dist/cli/commands/describe.mjs +56 -2
  17. package/dist/cli/commands/docs.mjs +2 -2
  18. package/dist/cli/commands/generate.mjs +147 -48
  19. package/dist/cli/commands/init.d.mts +13 -0
  20. package/dist/cli/commands/init.mjs +130 -87
  21. package/dist/cli/commands/introspect.mjs +8 -1
  22. package/dist/context/index.mjs +1 -1
  23. package/dist/core/index.d.mts +3 -3
  24. package/dist/core/index.mjs +5 -5
  25. package/dist/core-DECn6zaU.mjs +1399 -0
  26. package/dist/{createActionRouter-CIKOcNA7.mjs → createActionRouter-CBxLLbn3.mjs} +7 -20
  27. package/dist/createAggregationRouter-CRIBv4sC.mjs +114 -0
  28. package/dist/{createApp-C9bRrqlX.mjs → createApp-XX2-N0Yd.mjs} +28 -22
  29. package/dist/{defineEvent-D1Ky9M1D.mjs → defineEvent-D5h7EvAx.mjs} +1 -1
  30. package/dist/docs/index.d.mts +24 -11
  31. package/dist/docs/index.mjs +2 -2
  32. package/dist/{elevation-DOFoxoDs.mjs → elevation-DgoeTyfX.mjs} +1 -1
  33. package/dist/errorHandler-Bk-AGhkU.mjs +174 -0
  34. package/dist/errorHandler-DFr45ZG4.d.mts +45 -0
  35. package/dist/errors-j4aJm1Wg.mjs +184 -0
  36. package/dist/{eventPlugin-Cts2-Tfj.mjs → eventPlugin-CaKTYkYM.mjs} +28 -4
  37. package/dist/{eventPlugin-DDJoNEPL.d.mts → eventPlugin-qXpqTebY.d.mts} +24 -1
  38. package/dist/events/index.d.mts +6 -6
  39. package/dist/events/index.mjs +11 -35
  40. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  41. package/dist/events/transports/redis.d.mts +1 -1
  42. package/dist/factory/index.d.mts +2 -2
  43. package/dist/factory/index.mjs +2 -2
  44. package/dist/{fields-BRjxOAFp.d.mts → fields-COhcH3fk.d.mts} +23 -2
  45. package/dist/hooks/index.d.mts +1 -1
  46. package/dist/hooks/index.mjs +1 -1
  47. package/dist/idempotency/index.d.mts +1 -1
  48. package/dist/idempotency/index.mjs +1 -20
  49. package/dist/idempotency/redis.mjs +1 -1
  50. package/dist/{index-rHjXmJar.d.mts → index-BTqLEvhu.d.mts} +163 -3
  51. package/dist/{index-CXXRbnf8.d.mts → index-BtW7qYwa.d.mts} +660 -326
  52. package/dist/{index-m8mOOlFW.d.mts → index-Ds61mrJE.d.mts} +50 -4
  53. package/dist/{index-D9t1KNaB.d.mts → index-Dz5IKsrE.d.mts} +360 -219
  54. package/dist/index.d.mts +6 -7
  55. package/dist/index.mjs +9 -10
  56. package/dist/integrations/event-gateway.d.mts +1 -1
  57. package/dist/integrations/event-gateway.mjs +1 -1
  58. package/dist/integrations/index.d.mts +1 -1
  59. package/dist/integrations/mcp/index.d.mts +2 -2
  60. package/dist/integrations/mcp/index.mjs +1 -1
  61. package/dist/integrations/mcp/testing.d.mts +1 -1
  62. package/dist/integrations/mcp/testing.mjs +1 -1
  63. package/dist/integrations/streamline.d.mts +60 -11
  64. package/dist/integrations/streamline.mjs +75 -85
  65. package/dist/integrations/websocket.mjs +2 -8
  66. package/dist/middleware/index.d.mts +1 -1
  67. package/dist/middleware/index.mjs +2 -2
  68. package/dist/migrations/index.d.mts +23 -3
  69. package/dist/migrations/index.mjs +0 -7
  70. package/dist/{multipartBody-CvTR1Un6.mjs → multipartBody-BOvVSVCD.mjs} +11 -8
  71. package/dist/openapi-noXno2CV.mjs +968 -0
  72. package/dist/org/index.d.mts +2 -2
  73. package/dist/org/index.mjs +1 -1
  74. package/dist/permissions/index.d.mts +3 -3
  75. package/dist/permissions/index.mjs +3 -3
  76. package/dist/{permissions-gd_aUWrR.mjs → permissions-ohQyv50e.mjs} +404 -176
  77. package/dist/{pipe-DVoIheVC.mjs → pipe-Zr0KXjQe.mjs} +1 -1
  78. package/dist/pipeline/index.d.mts +1 -1
  79. package/dist/pipeline/index.mjs +1 -1
  80. package/dist/plugins/index.d.mts +16 -31
  81. package/dist/plugins/index.mjs +33 -13
  82. package/dist/plugins/response-cache.mjs +1 -1
  83. package/dist/plugins/tracing-entry.mjs +1 -1
  84. package/dist/presets/filesUpload.d.mts +4 -4
  85. package/dist/presets/filesUpload.mjs +6 -9
  86. package/dist/presets/index.d.mts +1 -1
  87. package/dist/presets/index.mjs +1 -1
  88. package/dist/presets/multiTenant.d.mts +1 -1
  89. package/dist/presets/multiTenant.mjs +2 -2
  90. package/dist/presets/search.d.mts +2 -2
  91. package/dist/presets/search.mjs +6 -8
  92. package/dist/{presets-Z7P5w4gF.mjs → presets-BbkjdPeH.mjs} +6 -28
  93. package/dist/{queryCachePlugin-Bq6bO6vc.mjs → queryCachePlugin-m1XsgAIJ.mjs} +3 -3
  94. package/dist/{redis-stream-xTGxB2bm.d.mts → redis-stream-D6HzR1Z_.d.mts} +1 -1
  95. package/dist/registry/index.d.mts +1 -1
  96. package/dist/registry/index.mjs +2 -2
  97. package/dist/{replyHelpers-ByllIXXV.mjs → replyHelpers-CK-FNO8E.mjs} +3 -21
  98. package/dist/{resourceToTools-CxNmI6xF.mjs → resourceToTools-DLL32us3.mjs} +224 -71
  99. package/dist/{routerShared-BqLRb5l7.mjs → routerShared-DrOa-26E.mjs} +41 -36
  100. package/dist/{schemaIR-Dy2p4MxS.mjs → schemaIR-lYhC2gE5.mjs} +1 -1
  101. package/dist/schemas/index.d.mts +100 -30
  102. package/dist/schemas/index.mjs +86 -29
  103. package/dist/scim/index.d.mts +264 -0
  104. package/dist/scim/index.mjs +963 -0
  105. package/dist/scope/index.d.mts +3 -3
  106. package/dist/scope/index.mjs +4 -4
  107. package/dist/{sse-V7aXc3bW.mjs → sse-Bz-5ZeTt.mjs} +1 -1
  108. package/dist/{store-helpers-Cp4uKC1U.mjs → store-helpers-BkIN9-vu.mjs} +1 -1
  109. package/dist/testing/index.d.mts +2 -8
  110. package/dist/testing/index.mjs +16 -24
  111. package/dist/types/index.d.mts +4 -4
  112. package/dist/{types-D7KpfiL1.d.mts → types-BvqwCCSx.d.mts} +73 -25
  113. package/dist/{types-DDyTPc6y.d.mts → types-CTYvcwHe.d.mts} +195 -1
  114. package/dist/{types-AOD8fxIw.mjs → types-C_s5moIu.mjs} +117 -1
  115. package/dist/{types-BQ9TJQNy.d.mts → types-DQHFc8PM.d.mts} +1 -1
  116. package/dist/utils/index.d.mts +2 -2
  117. package/dist/utils/index.mjs +5 -5
  118. package/dist/{utils-CcYTj09l.mjs → utils-_h9B3c57.mjs} +1269 -1334
  119. package/dist/{versioning-DsglKfM_.d.mts → versioning-DTTvc80y.d.mts} +1 -1
  120. package/package.json +24 -34
  121. package/skills/arc/SKILL.md +147 -51
  122. package/skills/arc/references/agent-auth.md +238 -0
  123. package/skills/arc/references/api-reference.md +187 -0
  124. package/skills/arc/references/auth.md +354 -7
  125. package/skills/arc/references/enterprise-auth.md +94 -0
  126. package/skills/arc/references/events.md +8 -6
  127. package/skills/arc/references/mcp.md +2 -2
  128. package/skills/arc/references/multi-tenancy.md +11 -2
  129. package/skills/arc/references/production.md +10 -9
  130. package/skills/arc/references/scim.md +247 -0
  131. package/skills/arc/references/testing.md +1 -1
  132. package/skills/arc-code-review/SKILL.md +141 -0
  133. package/skills/arc-code-review/references/anti-patterns.md +911 -0
  134. package/skills/arc-code-review/references/arc-cheatsheet.md +380 -0
  135. package/skills/arc-code-review/references/migration-recipes.md +700 -0
  136. package/skills/arc-code-review/references/mongokit-migration.md +386 -0
  137. package/skills/arc-code-review/references/scaffolding.md +230 -0
  138. package/skills/arc-code-review/references/severity.md +127 -0
  139. package/dist/EventTransport-BFQjw9pB.mjs +0 -133
  140. package/dist/EventTransport-CYNUXdCJ.d.mts +0 -293
  141. package/dist/adapters/index.d.mts +0 -3
  142. package/dist/adapters/index.mjs +0 -2
  143. package/dist/adapters-DUUiiimH.mjs +0 -964
  144. package/dist/auth/mongoose.d.mts +0 -191
  145. package/dist/auth/mongoose.mjs +0 -73
  146. package/dist/core-CbcQRIch.mjs +0 -1054
  147. package/dist/errorHandler-BQm8ZxTK.mjs +0 -173
  148. package/dist/errorHandler-DEWmGWPz.d.mts +0 -114
  149. package/dist/errors-D5c-5BJL.mjs +0 -232
  150. package/dist/index-Rg8axYPz.d.mts +0 -370
  151. package/dist/openapi-D7G1V7ex.mjs +0 -557
  152. /package/dist/{HookSystem-CGsMd6oK.mjs → HookSystem-Iiebom92.mjs} +0 -0
  153. /package/dist/{actionPermissions-sUUKDhtP.mjs → actionPermissions-CyUkQu6O.mjs} +0 -0
  154. /package/dist/{caching-CheW3m-S.mjs → caching-SM8gghN6.mjs} +0 -0
  155. /package/dist/{constants-BhY1OHoH.mjs → constants-Cxde4rpC.mjs} +0 -0
  156. /package/dist/{elevation-BQQXZ_VR.d.mts → elevation-BXOWoGCF.d.mts} +0 -0
  157. /package/dist/{keys-CARyUjiR.mjs → keys-CGcCbNyu.mjs} +0 -0
  158. /package/dist/{loadResources-CPpkyKfM.mjs → loadResources-DBMQg_Aj.mjs} +0 -0
  159. /package/dist/{memory-DikHSvWa.mjs → memory-UBydS5ku.mjs} +0 -0
  160. /package/dist/{metrics-Csh4nsvv.mjs → metrics-Qnvwc-LQ.mjs} +0 -0
  161. /package/dist/{pluralize-CWP6MB39.mjs → pluralize-DQgqgifU.mjs} +0 -0
  162. /package/dist/{registry-D63ee7fl.mjs → registry-I-ogLgL9.mjs} +0 -0
  163. /package/dist/{requestContext-C5XeK3VA.mjs → requestContext-SSaaTgW8.mjs} +0 -0
  164. /package/dist/{schemaConverter-B0oKLuqI.mjs → schemaConverter-De34B1ZG.mjs} +0 -0
  165. /package/dist/{typeGuards-CcFZXgU7.mjs → typeGuards-BzkXkvVv.mjs} +0 -0
  166. /package/dist/{types-DV9WDfeg.mjs → types-D57iXYb8.mjs} +0 -0
  167. /package/dist/{versioning-CGPjkqAg.mjs → versioning-BUrT5aP4.mjs} +0 -0
@@ -28,6 +28,10 @@ async function init(options = {}) {
28
28
  console.log(`\nCreating project: ${config.name}`);
29
29
  console.log(` Adapter: ${config.adapter === "mongokit" ? "MongoKit (MongoDB)" : "Custom / Drizzle-ready"}`);
30
30
  console.log(` Auth: ${config.auth === "better-auth" ? "Better Auth (recommended)" : "Arc JWT"}`);
31
+ if (config.auth === "better-auth") {
32
+ console.log(` Session: ${config.session === "cookie" ? "Cookie" : config.session === "bearer" ? "Bearer token" : "Cookie + Bearer"}`);
33
+ if (config.apiKey) console.log(` API keys: enabled (@better-auth/api-key)`);
34
+ }
31
35
  console.log(` Tenant: ${config.tenant === "multi" ? "Multi-tenant" : "Single-tenant"}`);
32
36
  console.log(` Language: ${config.typescript ? "TypeScript" : "JavaScript"}`);
33
37
  console.log(` Target: ${config.edge ? "Edge/Serverless" : "Node.js Server"}\n`);
@@ -102,36 +106,39 @@ function existsSync$1(filePath) {
102
106
  */
103
107
  const SCAFFOLD_DEP_VERSIONS = {
104
108
  core: {
105
- "@classytic/arc": "^2.11.3",
106
- "@fastify/cors": "^11.0.0",
107
- "@fastify/helmet": "^13.0.0",
108
- "@fastify/rate-limit": "^10.0.0",
109
- "@fastify/sensible": "^6.0.0",
110
- "@fastify/under-pressure": "^9.0.0",
111
- dotenv: "^17.0.0",
112
- fastify: "^5.8.0"
109
+ "@classytic/arc": "^2.13.0",
110
+ "@classytic/primitives": "^0.3.0",
111
+ "@classytic/repo-core": "^0.4.0",
112
+ "@fastify/cors": "^11.2.0",
113
+ "@fastify/helmet": "^13.0.2",
114
+ "@fastify/rate-limit": "^10.3.0",
115
+ "@fastify/sensible": "^6.0.4",
116
+ "@fastify/under-pressure": "^9.0.3",
117
+ dotenv: "^17.4.2",
118
+ fastify: "^5.8.5"
113
119
  },
114
120
  authJwt: {
115
121
  "@fastify/jwt": "^10.0.0",
116
122
  bcryptjs: "^3.0.0"
117
123
  },
118
124
  authBetterAuth: {
119
- "better-auth": "^1.6.0",
120
- mongodb: "^6.10.0"
125
+ "better-auth": "^1.6.9",
126
+ mongodb: "^7.1.0"
121
127
  },
128
+ authBetterAuthApiKey: { "@better-auth/api-key": "^1.6.9" },
122
129
  adapterMongokit: {
123
- "@classytic/mongokit": "^3.11.0",
124
- "@classytic/repo-core": "^0.2.0",
125
- mongoose: "^9.4.1"
130
+ "@classytic/mongokit": "^3.13.0",
131
+ mongoose: "^9.6.1"
126
132
  },
127
133
  devCommon: {
134
+ "mongodb-memory-server": "^11.1.0",
128
135
  "pino-pretty": "^13.0.0",
129
- vitest: "^4.0.0"
136
+ vitest: "^4.1.5"
130
137
  },
131
138
  devTypescript: {
132
- "@types/node": "^22.0.0",
139
+ "@types/node": "^22.10.0",
133
140
  tsx: "^4.21.0",
134
- typescript: "^5.6.0"
141
+ typescript: "^5.7.2"
135
142
  },
136
143
  typesJwt: { "@types/bcryptjs": "^3.0.0" }
137
144
  };
@@ -144,8 +151,10 @@ const SCAFFOLD_DEP_VERSIONS = {
144
151
  function resolveScaffoldDependencies(config) {
145
152
  const dependencies = { ...SCAFFOLD_DEP_VERSIONS.core };
146
153
  const devDependencies = { ...SCAFFOLD_DEP_VERSIONS.devCommon };
147
- if (config.auth === "better-auth") Object.assign(dependencies, SCAFFOLD_DEP_VERSIONS.authBetterAuth);
148
- else {
154
+ if (config.auth === "better-auth") {
155
+ Object.assign(dependencies, SCAFFOLD_DEP_VERSIONS.authBetterAuth);
156
+ if (config.apiKey) Object.assign(dependencies, SCAFFOLD_DEP_VERSIONS.authBetterAuthApiKey);
157
+ } else {
149
158
  Object.assign(dependencies, SCAFFOLD_DEP_VERSIONS.authJwt);
150
159
  if (config.typescript) Object.assign(devDependencies, SCAFFOLD_DEP_VERSIONS.typesJwt);
151
160
  }
@@ -220,6 +229,15 @@ async function gatherConfig(options) {
220
229
  if (!options.adapter && !nonInteractive) adapter = await question("Database adapter [1=MongoKit (recommended), 2=Custom / Drizzle-ready]: ") === "2" ? "custom" : "mongokit";
221
230
  let auth = options.auth || "better-auth";
222
231
  if (!options.auth && !nonInteractive) auth = await question("Auth strategy [1=Better Auth (recommended), 2=Arc JWT]: ") === "2" ? "jwt" : "better-auth";
232
+ let session = options.session ?? "cookie";
233
+ let apiKey = options.apiKey ?? false;
234
+ if (auth === "better-auth" && !nonInteractive) {
235
+ if (options.session === void 0) {
236
+ const sessionChoice = await question("Session strategy [1=Cookie (web app, default), 2=Bearer token (mobile/SPA), 3=Both]: ");
237
+ session = sessionChoice === "2" ? "bearer" : sessionChoice === "3" ? "both" : "cookie";
238
+ }
239
+ if (options.apiKey === void 0) apiKey = (await question("Enable API key plugin (machine-to-machine auth via @better-auth/api-key)? [y/N]: ")).toLowerCase() === "y";
240
+ }
223
241
  let tenant = options.tenant || "single";
224
242
  if (!options.tenant && !nonInteractive) tenant = await question("Tenant mode [1=Single-tenant, 2=Multi-tenant]: ") === "2" ? "multi" : "single";
225
243
  let typescript = options.typescript ?? true;
@@ -237,7 +255,7 @@ async function gatherConfig(options) {
237
255
  console.log("");
238
256
  if ((await question("Continue with MongoKit? [y/N]: ")).toLowerCase() !== "y") {
239
257
  adapter = "custom";
240
- console.log(" Switched to custom adapter. Wire sqlitekit/Drizzle here; Prisma remains experimental.");
258
+ console.log(" Switched to custom adapter. Wire sqlitekit/Drizzle, prismakit, or any RepositoryLike-conforming repo.");
241
259
  }
242
260
  }
243
261
  return {
@@ -245,6 +263,8 @@ async function gatherConfig(options) {
245
263
  adapter,
246
264
  auth,
247
265
  tenant,
266
+ apiKey,
267
+ session,
248
268
  typescript,
249
269
  edge
250
270
  };
@@ -621,7 +641,7 @@ Short forms also supported: \`.env.prod\`, \`.env.dev\`, \`.env.test\`
621
641
 
622
642
  API documentation is available via Scalar UI:
623
643
 
624
- - **Interactive UI**: [http://localhost:8040/docs](http://localhost:8040/docs)
644
+ - **Interactive UI**: [http://localhost:8040/docs](http://localhost:8040/data)
625
645
  - **OpenAPI Spec**: [http://localhost:8040/_docs/openapi.json](http://localhost:8040/_docs/openapi.json)
626
646
 
627
647
  ## API Endpoints
@@ -742,7 +762,10 @@ function appTemplate(config) {
742
762
  const betterAuthImport = config.auth === "better-auth" ? `import { createBetterAuthAdapter } from '@classytic/arc/auth';
743
763
  import { getAuth } from './auth.js';
744
764
  ` : "";
745
- const authConfig = config.auth === "better-auth" ? config.tenant === "multi" ? `auth: { type: 'betterAuth', betterAuth: createBetterAuthAdapter({ auth: getAuth(), orgContext: true }) },` : `auth: { type: 'betterAuth', betterAuth: createBetterAuthAdapter({ auth: getAuth() }) },` : `auth: {
765
+ const authConfig = config.auth === "better-auth" ? `auth: {
766
+ type: 'betterAuth',
767
+ betterAuth: createBetterAuthAdapter({ auth: getAuth(), orgContext: true }),
768
+ },` : `auth: {
746
769
  type: 'jwt',
747
770
  jwt: { secret: config.jwt.secret },
748
771
  },`;
@@ -772,10 +795,13 @@ import { resources, registerResources } from '#resources/index.js';
772
795
  * @returns Configured Fastify instance ready to use
773
796
  */
774
797
  export async function createAppInstance()${ts ? ": Promise<FastifyInstance>" : ""} {
775
- // Create Arc app with resources and base configuration
798
+ // Create Arc app with resources and base configuration. \`resourcePrefix\`
799
+ // mounts every resource under \`/api\`, matching the \`apiPrefix\` the
800
+ // OpenAPI plugin advertises — keeps docs and routes in agreement.
776
801
  const app = await createApp({
777
802
  preset: config.env === 'production' ? (${config.edge ? "'edge'" : "'production'"}) : 'development',
778
803
  resources,
804
+ resourcePrefix: '/api',
779
805
  ${authConfig}
780
806
  cors: {
781
807
  origin: config.cors.origins,
@@ -1016,7 +1042,8 @@ function sharedIndexTemplate(_config) {
1016
1042
  export { createAdapter } from './adapter.js';
1017
1043
 
1018
1044
  // Core Arc exports
1019
- export { createMongooseAdapter, defineResource } from '@classytic/arc';
1045
+ export { defineResource } from '@classytic/arc';
1046
+ export { createMongooseAdapter } from '@classytic/mongokit/adapter';
1020
1047
 
1021
1048
  // Permission helpers (core + application-level)
1022
1049
  export * from './permissions.js';
@@ -1034,14 +1061,17 @@ function createAdapterTemplate(config) {
1034
1061
  * The repository handles query parsing via MongoKit's built-in QueryParser.
1035
1062
  */
1036
1063
 
1037
- import { createMongooseAdapter } from '@classytic/arc';
1064
+ import { createMongooseAdapter } from '@classytic/mongokit/adapter';
1065
+ import { buildCrudSchemasFromModel } from '@classytic/mongokit';
1038
1066
  ${ts ? "import type { Model } from 'mongoose';\nimport type { Repository } from '@classytic/mongokit';" : ""}
1039
1067
 
1040
1068
  /**
1041
- * Create a MongoKit-powered adapter for a resource
1069
+ * Create a MongoKit-powered adapter for a resource.
1042
1070
  *
1043
1071
  * Note: Query parsing is handled by MongoKit's Repository class.
1044
- * Just pass the model and repository - Arc handles the rest.
1072
+ * \`buildCrudSchemasFromModel\` is the canonical OpenAPI schema generator
1073
+ * for arc + Mongoose (arc 2.12+ no longer ships a built-in fallback —
1074
+ * passing it explicitly is required for OpenAPI auto-generation).
1045
1075
  */
1046
1076
  export function createAdapter${ts ? "<TDoc = any>" : ""}(
1047
1077
  model${ts ? ": Model<TDoc>" : ""},
@@ -1050,6 +1080,7 @@ export function createAdapter${ts ? "<TDoc = any>" : ""}(
1050
1080
  return createMongooseAdapter({
1051
1081
  model,
1052
1082
  repository,
1083
+ schemaGenerator: buildCrudSchemasFromModel,
1053
1084
  });
1054
1085
  }
1055
1086
  `;
@@ -1059,21 +1090,21 @@ function customAdapterTemplate(config) {
1059
1090
  return `/**
1060
1091
  * Custom Adapter Factory
1061
1092
  *
1062
- * Use this for sqlitekit/Drizzle, Prisma experiments, or any repository
1063
- * that satisfies Arc's RepositoryLike contract.
1093
+ * Use this for the bring-your-own-repository path any object that
1094
+ * satisfies the \`RepositoryLike\` contract from
1095
+ * \`@classytic/repo-core/adapter\` plugs in here. Each classytic kit
1096
+ * also ships its own \`/adapter\` subpath; if one of those fits, import
1097
+ * its factory directly instead.
1064
1098
  */
1065
1099
 
1066
- ${ts ? "import type { DataAdapter, RepositoryLike } from '@classytic/arc/adapters';" : ""}
1100
+ ${ts ? "import type { DataAdapter, RepositoryLike } from '@classytic/repo-core/adapter';" : ""}
1067
1101
 
1068
1102
  /**
1069
1103
  * Create a custom adapter for a resource.
1070
1104
  *
1071
- * Recommended SQL path:
1072
- * - sqlitekit repository + Arc's createDrizzleAdapter for Drizzle tables
1073
- *
1074
- * Experimental path:
1075
- * - Prisma can be wired with createPrismaAdapter, but keep it opt-in until
1076
- * your app has integration coverage.
1105
+ * Pass any object satisfying \`RepositoryLike<TDoc>\` (a 5-method floor:
1106
+ * \`getAll\` / \`getById\` / \`create\` / \`update\` / \`delete\`, plus any
1107
+ * optional \`StandardRepo\` methods you implement).
1077
1108
  */
1078
1109
  export function createAdapter${ts ? "<TDoc = unknown>" : ""}(
1079
1110
  _source${ts ? ": unknown" : ""},
@@ -1286,9 +1317,8 @@ function createTenantInjection(tenantField${ts ? ": string" : ""}) {
1286
1317
  // Fail-closed: Require orgId for create operations
1287
1318
  if (!orgId) {
1288
1319
  return reply.code(403).send({
1289
- success: false,
1290
- error: 'Forbidden',
1291
- message: 'Organization context required to create resources',
1320
+ error: 'Organization context required to create resources',
1321
+ code: 'arc.org_required',
1292
1322
  });
1293
1323
  }
1294
1324
 
@@ -2319,39 +2349,58 @@ export default authResource;
2319
2349
  }
2320
2350
  function betterAuthSetupTemplate(config) {
2321
2351
  const ts = config.typescript;
2322
- const mongoImport = config.adapter === "mongokit" ? `import mongoose from 'mongoose';
2323
- import { mongodbAdapter } from 'better-auth/adapters/mongodb';` : "";
2324
- const dbAdapter = config.adapter === "mongokit" ? config.typescript ? `database: mongodbAdapter(mongoose.connection.getClient().db() as any),` : `database: mongodbAdapter(mongoose.connection.getClient().db()),` : `// Configure your database adapter here
2352
+ const useMongo = config.adapter === "mongokit";
2353
+ const useStubs = useMongo;
2354
+ const useOrg = config.tenant === "multi";
2355
+ const useBearer = config.session === "bearer" || config.session === "both";
2356
+ const useApiKey = config.apiKey;
2357
+ const mongoImport = useMongo ? `import mongoose from 'mongoose';
2358
+ import { mongodbAdapter } from '@better-auth/mongo-adapter';` : "";
2359
+ const stubsImport = useStubs ? `import { registerBetterAuthStubs } from '@classytic/mongokit/better-auth';` : "";
2360
+ const pluginImports = [
2361
+ useOrg ? `import { organization } from 'better-auth/plugins';` : "",
2362
+ useBearer ? `import { bearer } from 'better-auth/plugins';` : "",
2363
+ useApiKey ? `import { apiKey } from '@better-auth/api-key';` : ""
2364
+ ].filter(Boolean).join("\n");
2365
+ const dbAdapter = useMongo ? config.typescript ? `database: mongodbAdapter(mongoose.connection.getClient().db() as any),` : `database: mongodbAdapter(mongoose.connection.getClient().db()),` : `// Configure your database adapter here
2325
2366
  // See: https://www.better-auth.com/docs/concepts/database`;
2326
- const orgPlugin = config.tenant === "multi" ? `
2327
- import { organization } from 'better-auth/plugins/organization';
2328
- import { bearer } from 'better-auth/plugins/bearer';` : "";
2329
- const orgPluginUsage = config.tenant === "multi" ? `
2330
- plugins: [
2331
- bearer(),
2332
- organization({
2367
+ const pluginEntries = [
2368
+ useBearer ? ` bearer(),` : "",
2369
+ useApiKey ? ` apiKey({
2370
+ enableMetadata: true,
2371
+ rateLimit: { enabled: true, timeWindow: 1000 * 60 * 60 * 24, maxRequests: 10 },
2372
+ }),` : "",
2373
+ useOrg ? ` organization({
2333
2374
  allowUserToCreateOrganization: true,
2334
2375
  creatorRole: 'owner',
2335
- teams: {
2336
- enabled: true,
2337
- },
2338
- }),
2376
+ teams: { enabled: true },
2377
+ }),` : ""
2378
+ ].filter(Boolean);
2379
+ const orgPluginUsage = pluginEntries.length > 0 ? `
2380
+ plugins: [
2381
+ ${pluginEntries.join("\n")}
2339
2382
  ],` : "";
2383
+ const stubPluginsList = [useOrg ? `'organization'` : ""].filter(Boolean).join(", ");
2384
+ const stubExtras = useApiKey ? `, extraCollections: ['apikey']` : "";
2340
2385
  return `/**
2341
2386
  * Better Auth Configuration
2342
2387
  * Generated by Arc CLI
2343
2388
  *
2344
- * Authentication is handled entirely by Better Auth.
2345
- * Routes are registered automatically at /api/auth/*
2389
+ * Better Auth owns auth flows + writes its own tables. Arc reads them as
2390
+ * resources via \`@classytic/mongokit/better-auth\`'s overlay (full pagination,
2391
+ * queryparser, OpenAPI, audit) without re-implementing CRUD.
2346
2392
  *
2347
- * Better Auth manages these collections:
2348
- * - user, session, account${config.tenant === "multi" ? ", organization, member, invitation, team, teamMember" : ""}
2393
+ * BA-managed tables: user, session, account, verification${useOrg ? ", organization, member, invitation, team, teamMember" : ""}${useApiKey ? ", apikey" : ""}
2349
2394
  *
2350
2395
  * @see https://www.better-auth.com/docs
2351
2396
  */
2352
2397
 
2353
2398
  import { betterAuth } from 'better-auth';
2354
- ${mongoImport}${orgPlugin}
2399
+ ${[
2400
+ mongoImport,
2401
+ pluginImports,
2402
+ stubsImport
2403
+ ].filter(Boolean).join("\n")}
2355
2404
  import config from '#config/index.js';
2356
2405
 
2357
2406
  let _auth${ts ? ": ReturnType<typeof betterAuth> | null" : ""} = null;
@@ -2415,16 +2464,11 @@ ${orgPluginUsage}
2415
2464
  enabled: process.env.NODE_ENV === 'production',
2416
2465
  },
2417
2466
  });
2418
- ${config.adapter === "mongokit" ? `
2419
- // Register stub Mongoose models for Better Auth collections.
2420
- // BA uses the raw MongoDB driver, so no Mongoose models exist by default.
2421
- // These stubs (strict: false) enable populate() on refs like 'user', 'organization', etc.
2422
- const baCollections = ['user', 'organization', 'member', 'invitation', 'session', 'account'];
2423
- for (const name of baCollections) {
2424
- if (!mongoose.models[name]) {
2425
- mongoose.model(name, new mongoose.Schema({}, { strict: false, collection: name }));
2426
- }
2427
- }
2467
+ ${useStubs ? `
2468
+ // Register stub Mongoose models for Better Auth's collections so
2469
+ // \`.populate('user')\` / \`ref: 'organization'\` resolve against BA-owned
2470
+ // documents app-wide. Idempotent, strict:false, plugin-aware.
2471
+ registerBetterAuthStubs(mongoose, {${stubPluginsList ? ` plugins: [${stubPluginsList}]` : ""}${stubExtras} });
2428
2472
  ` : ""} }
2429
2473
 
2430
2474
  return _auth;
@@ -2459,16 +2503,16 @@ export async function register(request${ts ? ": FastifyRequest" : ""}, reply${ts
2459
2503
 
2460
2504
  // Check if email exists
2461
2505
  if (await userRepository.emailExists(email)) {
2462
- return reply.code(400).send({ success: false, message: 'Email already registered' });
2506
+ return reply.code(400).send({ error: 'Email already registered', code: 'arc.email_exists' });
2463
2507
  }
2464
2508
 
2465
2509
  // Create user
2466
2510
  await userRepository.create({ name, email, password, role: 'user' });
2467
2511
 
2468
- return reply.code(201).send({ success: true, message: 'User registered successfully' });
2512
+ return reply.code(201).send({ message: 'User registered successfully' });
2469
2513
  } catch (error) {
2470
2514
  request.log.error({ err: error }, 'Register error');
2471
- return reply.code(500).send({ success: false, message: 'Registration failed' });
2515
+ return reply.code(500).send({ error: 'Registration failed', code: 'arc.internal' });
2472
2516
  }
2473
2517
  }
2474
2518
 
@@ -2481,19 +2525,18 @@ export async function login(request${ts ? ": FastifyRequest" : ""}, reply${ts ?
2481
2525
 
2482
2526
  const user = await userRepository.findByEmail(email);
2483
2527
  if (!user || !(await user.matchPassword(password))) {
2484
- return reply.code(401).send({ success: false, message: 'Invalid credentials' });
2528
+ return reply.code(401).send({ error: 'Invalid credentials', code: 'arc.unauthorized' });
2485
2529
  }
2486
2530
 
2487
2531
  const tokens = request.server.auth.issueTokens({ id: user._id.toString(), role: user.role });
2488
2532
 
2489
2533
  return reply.send({
2490
- success: true,
2491
2534
  user: { id: user._id, name: user.name, email: user.email, role: user.role },
2492
2535
  ...tokens,
2493
2536
  });
2494
2537
  } catch (error) {
2495
2538
  request.log.error({ err: error }, 'Login error');
2496
- return reply.code(500).send({ success: false, message: 'Login failed' });
2539
+ return reply.code(500).send({ error: 'Login failed', code: 'arc.internal' });
2497
2540
  }
2498
2541
  }
2499
2542
 
@@ -2504,15 +2547,15 @@ export async function refreshToken(request${ts ? ": FastifyRequest" : ""}, reply
2504
2547
  try {
2505
2548
  const { token } = request.body${ts ? " as any" : ""};
2506
2549
  if (!token) {
2507
- return reply.code(401).send({ success: false, message: 'Refresh token required' });
2550
+ return reply.code(401).send({ error: 'Refresh token required', code: 'arc.unauthorized' });
2508
2551
  }
2509
2552
 
2510
2553
  const decoded = request.server.auth.verifyRefreshToken(token)${ts ? " as { id: string }" : ""};
2511
2554
  const tokens = request.server.auth.issueTokens({ id: decoded.id });
2512
2555
 
2513
- return reply.send({ success: true, ...tokens });
2556
+ return reply.send(tokens);
2514
2557
  } catch {
2515
- return reply.code(401).send({ success: false, message: 'Invalid refresh token' });
2558
+ return reply.code(401).send({ error: 'Invalid refresh token', code: 'arc.unauthorized' });
2516
2559
  }
2517
2560
  }
2518
2561
 
@@ -2533,11 +2576,11 @@ export async function forgotPassword(request${ts ? ": FastifyRequest" : ""}, rep
2533
2576
  request.log.info(\`Password reset requested for \${email}\`);
2534
2577
  }
2535
2578
 
2536
- // Always return success to prevent email enumeration
2537
- return reply.send({ success: true, message: 'If email exists, reset link sent' });
2579
+ // Always 200 to prevent email enumeration
2580
+ return reply.send({ message: 'If email exists, reset link sent' });
2538
2581
  } catch (error) {
2539
2582
  request.log.error({ err: error }, 'Forgot password error');
2540
- return reply.code(500).send({ success: false, message: 'Failed to process request' });
2583
+ return reply.code(500).send({ error: 'Failed to process request', code: 'arc.internal' });
2541
2584
  }
2542
2585
  }
2543
2586
 
@@ -2550,14 +2593,14 @@ export async function resetPassword(request${ts ? ": FastifyRequest" : ""}, repl
2550
2593
  const user = await userRepository.findByResetToken(token);
2551
2594
 
2552
2595
  if (!user) {
2553
- return reply.code(400).send({ success: false, message: 'Invalid or expired token' });
2596
+ return reply.code(400).send({ error: 'Invalid or expired token', code: 'arc.bad_request' });
2554
2597
  }
2555
2598
 
2556
2599
  await userRepository.updatePassword(user._id, newPassword);
2557
- return reply.send({ success: true, message: 'Password has been reset' });
2600
+ return reply.send({ message: 'Password has been reset' });
2558
2601
  } catch (error) {
2559
2602
  request.log.error({ err: error }, 'Reset password error');
2560
- return reply.code(500).send({ success: false, message: 'Failed to reset password' });
2603
+ return reply.code(500).send({ error: 'Failed to reset password', code: 'arc.internal' });
2561
2604
  }
2562
2605
  }
2563
2606
 
@@ -2570,13 +2613,13 @@ export async function getUserProfile(request${ts ? ": FastifyRequest" : ""}, rep
2570
2613
  const user = await userRepository.getById(userId);
2571
2614
 
2572
2615
  if (!user) {
2573
- return reply.code(404).send({ success: false, message: 'User not found' });
2616
+ return reply.code(404).send({ error: 'User not found', code: 'arc.not_found' });
2574
2617
  }
2575
2618
 
2576
- return reply.send({ success: true, data: user });
2619
+ return reply.send(user);
2577
2620
  } catch (error) {
2578
2621
  request.log.error({ err: error }, 'Get profile error');
2579
- return reply.code(500).send({ success: false, message: 'Failed to get profile' });
2622
+ return reply.code(500).send({ error: 'Failed to get profile', code: 'arc.internal' });
2580
2623
  }
2581
2624
  }
2582
2625
 
@@ -2594,10 +2637,10 @@ export async function updateUserProfile(request${ts ? ": FastifyRequest" : ""},
2594
2637
  delete updates.organizations;
2595
2638
 
2596
2639
  const user = await userRepository.Model.findByIdAndUpdate(userId, updates, { new: true });
2597
- return reply.send({ success: true, data: user });
2640
+ return reply.send(user);
2598
2641
  } catch (error) {
2599
2642
  request.log.error({ err: error }, 'Update profile error');
2600
- return reply.code(500).send({ success: false, message: 'Failed to update profile' });
2643
+ return reply.code(500).send({ error: 'Failed to update profile', code: 'arc.internal' });
2601
2644
  }
2602
2645
  }
2603
2646
  `;
@@ -1,4 +1,4 @@
1
- import { t as ResourceRegistry } from "../../ResourceRegistry-DkAeAuTX.mjs";
1
+ import { t as ResourceRegistry } from "../../ResourceRegistry-CTERg_2x.mjs";
2
2
  import { resolve } from "node:path";
3
3
  import { pathToFileURL } from "node:url";
4
4
  //#region src/cli/commands/introspect.ts
@@ -57,6 +57,11 @@ async function introspect(args) {
57
57
  }
58
58
  if (resource.presets && resource.presets.length > 0) console.log(` Presets: ${resource.presets.join(", ")}`);
59
59
  if (resource.customRoutes && resource.customRoutes.length > 0) console.log(` Additional Routes: ${resource.customRoutes.length}`);
60
+ if (resource.actions && resource.actions.length > 0) {
61
+ const fallback = resource.actionPermissions ? ` (fallback: ${describePermission(resource.actionPermissions)})` : "";
62
+ console.log(` Actions: ${resource.actions.map((a) => a.name).join(", ")}${fallback}`);
63
+ }
64
+ if (resource.aggregations && resource.aggregations.length > 0) console.log(` Aggregations: ${resource.aggregations.map((a) => a.name).join(", ")}`);
60
65
  console.log("");
61
66
  });
62
67
  const stats = registry.getStats();
@@ -64,6 +69,8 @@ async function introspect(args) {
64
69
  console.log(` Total Resources: ${stats.totalResources}`);
65
70
  console.log(` With Presets: ${resources.filter((r) => r.presets?.length > 0).length}`);
66
71
  console.log(` With Custom Routes: ${resources.filter((r) => r.customRoutes && r.customRoutes.length > 0).length}`);
72
+ console.log(` With Actions: ${resources.filter((r) => r.actions && r.actions.length > 0).length}`);
73
+ console.log(` With Aggregations: ${resources.filter((r) => r.aggregations && r.aggregations.length > 0).length}`);
67
74
  } catch (error) {
68
75
  if (error instanceof Error) throw error;
69
76
  throw new Error(String(error));
@@ -1,2 +1,2 @@
1
- import { t as requestContext } from "../requestContext-C5XeK3VA.mjs";
1
+ import { t as requestContext } from "../requestContext-SSaaTgW8.mjs";
2
2
  export { requestContext };
@@ -1,3 +1,3 @@
1
- import { B as ResourceDefinition, Gt as TreeMixin, Ht as SoftDeleteExt, Jt as BulkExt, Kt as SlugExt, Ut as SoftDeleteMixin, V as defineResource, Vt as BaseController, Wt as TreeExt, Yt as BulkMixin, an as QueryResolverConfig, cn as AccessControl, in as QueryResolver, ln as AccessControlConfig, nn as BaseCrudController, on as BodySanitizer, qt as SlugMixin, rn as ListResult, sn as BodySanitizerConfig, tn as BaseControllerOptions } from "../index-CXXRbnf8.mjs";
2
- import { C as MAX_REGEX_LENGTH, D as RESERVED_QUERY_PARAMS, E as MutationOperation, O as SYSTEM_FIELDS, S as MAX_FILTER_DEPTH, T as MUTATION_OPERATIONS, _ as DEFAULT_UPDATE_METHOD, a as getControllerScope, b as HookOperation, c as createCrudRouter, d as CrudOperation, f as DEFAULT_ID_FIELD, g as DEFAULT_TENANT_FIELD, h as DEFAULT_SORT, i as getControllerContext, l as createPermissionMiddleware, m as DEFAULT_MAX_LIMIT, n as createFastifyHandler, o as sendControllerResponse, p as DEFAULT_LIMIT, r as createRequestContext, s as defineResourceVariants, t as createCrudHandlers, u as CRUD_OPERATIONS, v as HOOK_OPERATIONS, w as MAX_SEARCH_LENGTH, x as HookPhase, y as HOOK_PHASES } from "../index-m8mOOlFW.mjs";
3
- export { AccessControl, AccessControlConfig, BaseController, BaseControllerOptions, BaseCrudController, BodySanitizer, BodySanitizerConfig, BulkExt, BulkMixin, CRUD_OPERATIONS, CrudOperation, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, HOOK_OPERATIONS, HOOK_PHASES, HookOperation, HookPhase, ListResult, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, MutationOperation, QueryResolver, QueryResolverConfig, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugExt, SlugMixin, SoftDeleteExt, SoftDeleteMixin, TreeExt, TreeMixin, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineResource, defineResourceVariants, getControllerContext, getControllerScope, sendControllerResponse };
1
+ import { $t as SoftDeleteMixin, B as defineResource, Ct as AggregationConfig, Dt as AggregationMaterializedResult, Et as AggregationMaterializedContext, Ot as AggregationRateLimit, Qt as SoftDeleteExt, St as AggregationCacheConfig, Tt as AggregationIndexHint, V as ResourceDefinition, Zt as BaseController, _n as BodySanitizerConfig, an as BulkMixin, bt as AggMeasureInput, cn as QueryResolver, en as TreeExt, gn as BodySanitizer, hn as ListResult, in as BulkExt, kt as AggregationsMap, ln as QueryResolverConfig, nn as SlugExt, on as BaseControllerOptions, rn as SlugMixin, sn as BaseCrudController, tn as TreeMixin, vn as AccessControl, wt as AggregationDateRangeRequirement, xt as AggMeasureShorthand, yn as AccessControlConfig } from "../index-BtW7qYwa.mjs";
2
+ import { C as MAX_FILTER_DEPTH, D as MutationOperation, E as MUTATION_OPERATIONS, O as RESERVED_QUERY_PARAMS, S as HookPhase, T as MAX_SEARCH_LENGTH, _ as DEFAULT_TENANT_FIELD, a as getControllerScope, b as HOOK_PHASES, c as createCrudRouter, d as CRUD_OPERATIONS, f as CrudOperation, g as DEFAULT_SORT, h as DEFAULT_MAX_LIMIT, i as getControllerContext, k as SYSTEM_FIELDS, l as createPermissionMiddleware, m as DEFAULT_LIMIT, n as createFastifyHandler, o as sendControllerResponse, p as DEFAULT_ID_FIELD, r as createRequestContext, s as defineResourceVariants, t as createCrudHandlers, u as defineAggregation, v as DEFAULT_UPDATE_METHOD, w as MAX_REGEX_LENGTH, x as HookOperation, y as HOOK_OPERATIONS } from "../index-Ds61mrJE.mjs";
3
+ export { AccessControl, AccessControlConfig, AggMeasureInput, AggMeasureShorthand, AggregationCacheConfig, AggregationConfig, AggregationDateRangeRequirement, AggregationIndexHint, AggregationMaterializedContext, AggregationMaterializedResult, AggregationRateLimit, AggregationsMap, BaseController, BaseControllerOptions, BaseCrudController, BodySanitizer, BodySanitizerConfig, BulkExt, BulkMixin, CRUD_OPERATIONS, CrudOperation, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, HOOK_OPERATIONS, HOOK_PHASES, HookOperation, HookPhase, ListResult, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, MutationOperation, QueryResolver, QueryResolverConfig, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugExt, SlugMixin, SoftDeleteExt, SoftDeleteMixin, TreeExt, TreeMixin, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineAggregation, defineResource, defineResourceVariants, getControllerContext, getControllerScope, sendControllerResponse };
@@ -1,5 +1,5 @@
1
- import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "../constants-BhY1OHoH.mjs";
2
- import { a as BulkMixin, c as BodySanitizer, i as SlugMixin, l as AccessControl, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, s as QueryResolver, t as BaseController } from "../BaseController-swXruJ2_.mjs";
3
- import { _ as getControllerContext, g as createRequestContext, h as createFastifyHandler, m as createCrudHandlers, v as getControllerScope, y as sendControllerResponse } from "../routerShared-BqLRb5l7.mjs";
4
- import { a as createPermissionMiddleware, i as createCrudRouter, n as ResourceDefinition, r as defineResource, t as defineResourceVariants } from "../core-CbcQRIch.mjs";
5
- export { AccessControl, BaseController, BaseCrudController, BodySanitizer, BulkMixin, CRUD_OPERATIONS, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, HOOK_OPERATIONS, HOOK_PHASES, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, QueryResolver, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugMixin, SoftDeleteMixin, TreeMixin, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineResource, defineResourceVariants, getControllerContext, getControllerScope, sendControllerResponse };
1
+ import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "../constants-Cxde4rpC.mjs";
2
+ import { a as BulkMixin, c as BodySanitizer, i as SlugMixin, l as AccessControl, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, s as QueryResolver, t as BaseController } from "../BaseController-DX_T-bDB.mjs";
3
+ import { _ as getControllerContext, g as createRequestContext, h as createFastifyHandler, m as createCrudHandlers, v as getControllerScope, y as sendControllerResponse } from "../routerShared-DrOa-26E.mjs";
4
+ import { a as createPermissionMiddleware, i as createCrudRouter, n as defineResource, o as defineAggregation, r as ResourceDefinition, t as defineResourceVariants } from "../core-DECn6zaU.mjs";
5
+ export { AccessControl, BaseController, BaseCrudController, BodySanitizer, BulkMixin, CRUD_OPERATIONS, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, HOOK_OPERATIONS, HOOK_PHASES, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, QueryResolver, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugMixin, SoftDeleteMixin, TreeMixin, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineAggregation, defineResource, defineResourceVariants, getControllerContext, getControllerScope, sendControllerResponse };