@classytic/arc 2.18.3 → 2.18.5

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 (158) hide show
  1. package/dist/{BaseController-B-uXzf6I.mjs → BaseController-Dy6EQHjM.mjs} +7 -7
  2. package/dist/{QueryCache-Dsyv2mLS.d.mts → QueryCache-TRfXau3W.d.mts} +1 -1
  3. package/dist/{ResourceRegistry-CWmOggxS.mjs → ResourceRegistry-5fKZwhK_.mjs} +1 -1
  4. package/dist/{pipeline-D4sqiokR.mjs → actionPermissions-h7DYDNMg.mjs} +28 -5
  5. package/dist/audit/index.d.mts +1 -1
  6. package/dist/auth/index.d.mts +4 -4
  7. package/dist/auth/index.mjs +252 -5
  8. package/dist/auth/redis-session.d.mts +1 -1
  9. package/dist/betterAuthOpenApi-CV1lxpRX.mjs +2 -0
  10. package/dist/{buildHandler-Cvrc2p7r.mjs → buildHandler-B0qvAguf.mjs} +1 -1
  11. package/dist/cache/index.d.mts +3 -3
  12. package/dist/cache/index.mjs +3 -3
  13. package/dist/{caching-C0DdKiYB.mjs → caching-_NJeDd1_.mjs} +1 -1
  14. package/dist/cli/commands/describe.d.mts +1 -1
  15. package/dist/cli/commands/describe.mjs +2 -2
  16. package/dist/cli/commands/docs.mjs +2 -2
  17. package/dist/cli/commands/generate.d.mts +2 -2
  18. package/dist/cli/commands/generate.mjs +1 -1
  19. package/dist/cli/commands/init.d.mts +2 -2
  20. package/dist/cli/commands/init.mjs +1 -1
  21. package/dist/cli/commands/introspect.mjs +1 -1
  22. package/dist/cli/index.d.mts +2 -2
  23. package/dist/cli/index.mjs +2 -2
  24. package/dist/context/index.mjs +1 -1
  25. package/dist/core/index.d.mts +3 -3
  26. package/dist/core/index.mjs +4 -4
  27. package/dist/{core-C88uIwd3.mjs → core-ZnQBa5rh.mjs} +55 -56
  28. package/dist/{createActionRouter-DGCCp-kP.mjs → createActionRouter-CagItpxI.mjs} +6 -7
  29. package/dist/{createAggregationRouter-Ca77b8iK.mjs → createAggregationRouter-DVKroXhC.mjs} +4 -4
  30. package/dist/{createApp-DLuUGVZQ.mjs → createApp--703hQE1.mjs} +14 -14
  31. package/dist/docs/index.d.mts +2 -2
  32. package/dist/docs/index.mjs +2 -2
  33. package/dist/{elevation-BzhyVWfn.mjs → elevation-COpYKt2h.mjs} +2 -2
  34. package/dist/{errorHandler-Bua97SEt.mjs → errorHandler-Dxf6P_kV.mjs} +2 -2
  35. package/dist/{eventPlugin-Bw4bUDEO.mjs → eventPlugin-DJG2D7sy.mjs} +106 -5
  36. package/dist/{eventPlugin-C1W1CRbf.d.mts → eventPlugin-DbBFd3x_.d.mts} +1 -1
  37. package/dist/events/index.d.mts +3 -3
  38. package/dist/events/index.mjs +189 -5
  39. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  40. package/dist/events/transports/redis.d.mts +1 -1
  41. package/dist/factory/index.d.mts +1 -1
  42. package/dist/factory/index.mjs +3 -3
  43. package/dist/{fastify-augmentation-BdCl_eNo.d.mts → fastify-augmentation-Cxb0ROIw.d.mts} +2 -2
  44. package/dist/{fields-CKLrhyOb.d.mts → fields-C7ahdGYf.d.mts} +1 -1
  45. package/dist/{generate-BaxDdmJ8.mjs → generate-Brans3fW.mjs} +1 -1
  46. package/dist/hooks/index.d.mts +1 -1
  47. package/dist/hooks/index.mjs +1 -1
  48. package/dist/idempotency/index.d.mts +2 -2
  49. package/dist/idempotency/index.mjs +1 -1
  50. package/dist/idempotency/redis.d.mts +1 -1
  51. package/dist/{index-QYma8mdC.d.mts → index-CHNQIhcb.d.mts} +5 -6
  52. package/dist/{index-vcWUGkwf.d.mts → index-CRKiiP5o.d.mts} +3 -3
  53. package/dist/{index-Cvo1u9n6.d.mts → index-Dh0_RSTd.d.mts} +3 -3
  54. package/dist/index.d.mts +5 -5
  55. package/dist/index.mjs +7 -7
  56. package/dist/{init-DSsdRfk9.mjs → init-Bqpt1Hxf.mjs} +274 -130
  57. package/dist/integrations/event-gateway.d.mts +2 -2
  58. package/dist/integrations/event-gateway.mjs +1 -1
  59. package/dist/integrations/index.d.mts +3 -3
  60. package/dist/integrations/mcp/index.d.mts +4 -4
  61. package/dist/integrations/mcp/index.mjs +1 -1
  62. package/dist/integrations/mcp/testing.d.mts +1 -1
  63. package/dist/integrations/mcp/testing.mjs +1 -1
  64. package/dist/integrations/streamline.mjs +7 -3
  65. package/dist/integrations/websocket-pushref-redis.d.mts +1 -1
  66. package/dist/integrations/websocket-redis.d.mts +1 -1
  67. package/dist/integrations/websocket.d.mts +3 -3
  68. package/dist/{loadResources-CwXt9MCh.mjs → loadResources-B8UmpITt.mjs} +1 -1
  69. package/dist/{loadResourcesFromEntry-XHNeUWpu.mjs → loadResourcesFromEntry-BTlFEx05.mjs} +1 -1
  70. package/dist/{mcpPlugin-CzKdt3B8.mjs → mcpPlugin-D1wuRD2c.mjs} +10 -11
  71. package/dist/{memory-TdTHCS9-.mjs → memory-CLXA2VeJ.mjs} +1 -1
  72. package/dist/{metrics-Da2EUPi9.mjs → metrics-fdxI5mn_.mjs} +1 -1
  73. package/dist/middleware/index.d.mts +1 -1
  74. package/dist/middleware/index.mjs +2 -2
  75. package/dist/{openapi-ButnRyOM.mjs → openapi-xVJibapr.mjs} +5 -5
  76. package/dist/permissions/index.d.mts +3 -3
  77. package/dist/permissions/index.mjs +2 -2
  78. package/dist/{permissions-3uzwkbQt.mjs → permissions-BPB1xqGf.mjs} +4 -4
  79. package/dist/{pipe-9Tl-OAus.mjs → pipe-BOLmGIxa.mjs} +1 -1
  80. package/dist/pipeline/index.d.mts +1 -1
  81. package/dist/pipeline/index.mjs +1 -1
  82. package/dist/plugins/index.d.mts +6 -7
  83. package/dist/plugins/index.mjs +12 -12
  84. package/dist/plugins/response-cache.mjs +1 -1
  85. package/dist/plugins/tracing-entry.d.mts +1 -1
  86. package/dist/plugins/tracing-entry.mjs +1 -1
  87. package/dist/presets/filesUpload.d.mts +4 -4
  88. package/dist/presets/filesUpload.mjs +4 -4
  89. package/dist/presets/index.d.mts +1 -1
  90. package/dist/presets/index.mjs +1 -1
  91. package/dist/presets/multiTenant.d.mts +1 -1
  92. package/dist/presets/multiTenant.mjs +2 -2
  93. package/dist/presets/search.d.mts +2 -2
  94. package/dist/presets/search.mjs +1 -1
  95. package/dist/{presets-CF79RHEo.mjs → presets-BtyFwTO4.mjs} +2 -2
  96. package/dist/{queryCachePlugin-CnAeFqju.mjs → queryCachePlugin-emHb0CuX.mjs} +4 -4
  97. package/dist/{queryCachePlugin-Bd2tYgh5.d.mts → queryCachePlugin-xzFyKAjT.d.mts} +2 -2
  98. package/dist/{redis-3hqH_Qk_.d.mts → redis-C3W0qbz8.d.mts} +1 -1
  99. package/dist/{redis-stream-BtEUtjxZ.d.mts → redis-stream-DsP1vqZB.d.mts} +1 -1
  100. package/dist/{rateLimit-yKvxWAky.mjs → registerRoute-CPmdkZGu.mjs} +109 -2
  101. package/dist/registry/index.d.mts +1 -1
  102. package/dist/registry/index.mjs +2 -2
  103. package/dist/{registry-Br15xdGM.mjs → registry-Bm9LjWKs.mjs} +1 -1
  104. package/dist/{replyHelpers-DXHVxrrj.mjs → replyHelpers-67tRawQZ.mjs} +1 -1
  105. package/dist/{schemaIR-CE6USIRi.mjs → schemaIR-D1MJwqmp.mjs} +1 -1
  106. package/dist/schemas/index.d.mts +64 -65
  107. package/dist/scope/index.d.mts +2 -2
  108. package/dist/scope/index.mjs +3 -3
  109. package/dist/{sse-Xq8UtuQx.mjs → sse-CfUjwjDk.mjs} +18 -6
  110. package/dist/streaming-BQcW6_Kq.mjs +162 -0
  111. package/dist/testing/index.d.mts +7 -7
  112. package/dist/testing/index.mjs +3 -3
  113. package/dist/testing/storageContract.d.mts +1 -1
  114. package/dist/types/index.d.mts +5 -5
  115. package/dist/types/storage.d.mts +1 -1
  116. package/dist/{types-WVlAVp8T.d.mts → types-CmkknLzI.d.mts} +10 -10
  117. package/dist/{types-BWBcb88c.d.mts → types-D60PFwfG.d.mts} +1 -1
  118. package/dist/{types-Bi0r0vjG.mjs → types-bHblZ9YN.mjs} +1 -1
  119. package/dist/utils/index.d.mts +42 -4
  120. package/dist/utils/index.mjs +6 -5
  121. package/dist/{utils-xAQeDyU_.mjs → utils-C6QQ9-hd.mjs} +1415 -1524
  122. package/dist/{validate-0__MuUsK.mjs → validate-CRcaWzp2.mjs} +1 -1
  123. package/dist/{versioning-BSEDGXKC.d.mts → versioning-D_eBCfNr.d.mts} +8 -1
  124. package/dist/{versioning-C0K8KQLx.mjs → versioning-Dk-71iIz.mjs} +1 -1
  125. package/dist/{websocket-BFBT5rH-.d.mts → websocket-MlYlrYq0.d.mts} +1 -1
  126. package/package.json +36 -30
  127. package/dist/EventTransport-7LPXLEUX.mjs +0 -103
  128. package/dist/actionPermissions-CX9QIMTd.mjs +0 -24
  129. package/dist/betterAuthOpenApi-DAAhMZff.mjs +0 -251
  130. package/dist/defineEvent-DC981g-o.mjs +0 -188
  131. package/dist/registerRoute-BEYn0ylk.mjs +0 -108
  132. /package/dist/{EventTransport-CaaXM5Y1.d.mts → EventTransport-IEn7Tn-Q.d.mts} +0 -0
  133. /package/dist/{HookSystem-BfCpWbwM.mjs → HookSystem-C1vB_Gc9.mjs} +0 -0
  134. /package/dist/{constants-TrJVIJl0.mjs → constants-gaEeMlz-.mjs} +0 -0
  135. /package/dist/{elevation-DW90z5bT.d.mts → elevation-xGUBq6p_.d.mts} +0 -0
  136. /package/dist/{errorHandler-_Lp2k9M3.d.mts → errorHandler-BtUUDPEa.d.mts} +0 -0
  137. /package/dist/{errors-DZOemeGa.d.mts → errors-DOHkjQlD.d.mts} +0 -0
  138. /package/dist/{errors-j4aJm1Wg.mjs → errors-DkO8Nk6-.mjs} +0 -0
  139. /package/dist/{externalPaths-DLle0R07.d.mts → externalPaths-BE6wFpYv.d.mts} +0 -0
  140. /package/dist/{generate-Dmk8cfvX.d.mts → generate-BnsL9GBm.d.mts} +0 -0
  141. /package/dist/{init-BS4Daqnv.d.mts → init-BPEu8cs-.d.mts} +0 -0
  142. /package/dist/{interface-DL7LlWS5.d.mts → interface-C1_WLTMK.d.mts} +0 -0
  143. /package/dist/{interface-CsrGR8LF.d.mts → interface-Uk8ONJv7.d.mts} +0 -0
  144. /package/dist/{keys-B3yyBEyH.mjs → keys-Cd316u_y.mjs} +0 -0
  145. /package/dist/{multipartBody-709YcXi1.mjs → multipartBody-CHEQSZ6G.mjs} +0 -0
  146. /package/dist/{pluralize-BxdUl2P4.mjs → pluralize-DccFV9R7.mjs} +0 -0
  147. /package/dist/{preloadResources-B-j-iqo-.mjs → preloadResources-CHw3_oA_.mjs} +0 -0
  148. /package/dist/{pushref-registry-Dqclzjy7.d.mts → pushref-registry-DnCqL3aa.d.mts} +0 -0
  149. /package/dist/{requestContext-DDLS3NVU.mjs → requestContext-BZKOr13H.mjs} +0 -0
  150. /package/dist/{chunk-BpYLSNr0.mjs → rolldown-runtime-8H4AJuhK.mjs} +0 -0
  151. /package/dist/{schemaConverter-DatAaVNj.mjs → schemaConverter-U0MnO9vd.mjs} +0 -0
  152. /package/dist/{sessionManager-CyHpYXoB.d.mts → sessionManager-BXG-HGwG.d.mts} +0 -0
  153. /package/dist/{storage-C5q8fuEt.d.mts → storage-Co_PQpeQ.d.mts} +0 -0
  154. /package/dist/{store-helpers-DjSYI2uP.mjs → store-helpers-DY6xq4sM.mjs} +0 -0
  155. /package/dist/{tracing-Bnb1-YVd.d.mts → tracing-D8jlGXP7.d.mts} +0 -0
  156. /package/dist/{typeGuards-CcFZXgU7.mjs → typeGuards-C9KXUly6.mjs} +0 -0
  157. /package/dist/{types-BJwJN2Pg.d.mts → types-LNebCoJx.d.mts} +0 -0
  158. /package/dist/{types-D57iXYb8.mjs → types-XTApa8b6.mjs} +0 -0
@@ -178,13 +178,14 @@ import { getAuth } from './auth.js';
178
178
  */
179
179
 
180
180
  ${typeImport}import config from '#config/index.js';
181
- import { createApp, loadResources } from '@classytic/arc/factory';
182
- ${betterAuthImport}
181
+ import { createApp } from '@classytic/arc/factory';
182
+ ${config.adapter === "mongokit" ? "import mongoose from 'mongoose';\n" : ""}${betterAuthImport}
183
183
  // App-specific plugins
184
184
  import { registerPlugins } from '#plugins/index.js';
185
185
 
186
- // Resource registry
187
- import { resources, registerResources } from '#resources/index.js';
186
+ // Resource registry — createApp({ resources }) mounts each one under the
187
+ // resourcePrefix below; no manual registration loop needed.
188
+ import { resources } from '#resources/index.js';
188
189
 
189
190
  /**
190
191
  * Create a fully configured app instance
@@ -209,7 +210,20 @@ export async function createAppInstance()${ts ? ": Promise<FastifyInstance>" : "
209
210
  trustProxy: true,
210
211
  arcPlugins: {
211
212
  metrics: config.env === 'production', // Prometheus /_metrics endpoint
212
- },
213
+ ${config.adapter === "mongokit" ? ` // Readiness probe (/_health/ready) reports DOWN until Mongo connects —
214
+ // K8s / load balancers hold traffic until the app can actually serve.
215
+ health: {
216
+ checks: [
217
+ { name: 'mongodb', check: () => mongoose.connection.readyState === 1 },
218
+ ],
219
+ },
220
+ ` : ""} },${config.adapter === "mongokit" ? `
221
+ // Drain the DB connection on shutdown. Arc's gracefulShutdown (on by
222
+ // default) calls app.close() on SIGTERM/SIGINT, which runs this hook —
223
+ // no manual signal handlers needed.
224
+ onClose: async () => {
225
+ await mongoose.disconnect();
226
+ },` : ""}
213
227
  });
214
228
 
215
229
  // Register app-specific plugins (explicit dependency injection)
@@ -274,7 +288,7 @@ for (const file of candidates) {
274
288
  if (existsSync(file)) {
275
289
  // override: false means earlier files take priority (first loaded wins)
276
290
  dotenv.config({ path: file, override: false });
277
- loaded.push(file.split(/[\\\\/]/).pop()${ts ? "!" : ""});
291
+ loaded.push(file.split(/[\\\\/]/).pop() ?? file);
278
292
  }
279
293
  }
280
294
 
@@ -917,7 +931,7 @@ ${config.adapter === "mongokit" ? ` await mongoose.connection.collection('use
917
931
  //#region src/cli/commands/init/dependency-plan.ts
918
932
  const SCAFFOLD_DEP_VERSIONS = {
919
933
  core: {
920
- "@classytic/arc": "^2.18.3",
934
+ "@classytic/arc": "^2.18.5",
921
935
  "@classytic/primitives": "^0.6.0",
922
936
  "@classytic/repo-core": "^0.6.0",
923
937
  "@fastify/cors": "^11.2.0",
@@ -926,7 +940,8 @@ const SCAFFOLD_DEP_VERSIONS = {
926
940
  "@fastify/sensible": "^6.0.4",
927
941
  "@fastify/under-pressure": "^9.0.3",
928
942
  dotenv: "^17.4.2",
929
- fastify: "^5.8.5"
943
+ fastify: "^5.8.5",
944
+ zod: "^4.3.6"
930
945
  },
931
946
  authJwt: {
932
947
  "@fastify/jwt": "^10.1.0",
@@ -938,10 +953,11 @@ const SCAFFOLD_DEP_VERSIONS = {
938
953
  },
939
954
  authBetterAuthApiKey: { "@better-auth/api-key": "^1.6.11" },
940
955
  adapterMongokit: {
941
- "@classytic/mongokit": "^3.16.0",
956
+ "@classytic/mongokit": "^3.16.1",
942
957
  mongoose: "^9.6.2"
943
958
  },
944
959
  devCommon: {
960
+ "@biomejs/biome": "^2.4.15",
945
961
  "mongodb-memory-server": "^11.1.0",
946
962
  "pino-pretty": "^13.1.3",
947
963
  vitest: "^4.1.7"
@@ -992,49 +1008,45 @@ function sortByKey(record) {
992
1008
  */
993
1009
  function packageJsonTemplate(config) {
994
1010
  const { dependencies, devDependencies } = resolveScaffoldDependencies(config);
995
- const scripts = config.typescript ? config.edge ? {
996
- dev: "tsx watch src/index.ts",
997
- build: "tsc",
998
- start: "node dist/index.js",
999
- deploy: "wrangler deploy",
1000
- "deploy:dev": "wrangler dev",
1001
- test: "vitest run",
1002
- "test:watch": "vitest"
1003
- } : {
1004
- dev: "tsx watch src/index.ts",
1005
- build: "tsc",
1006
- start: "node dist/index.js",
1007
- test: "vitest run",
1008
- "test:watch": "vitest"
1009
- } : config.edge ? {
1010
- dev: "node --watch src/index.js",
1011
- start: "node src/index.js",
1012
- deploy: "wrangler deploy",
1013
- "deploy:dev": "wrangler dev",
1014
- test: "vitest run",
1015
- "test:watch": "vitest"
1016
- } : {
1017
- dev: "node --watch src/index.js",
1018
- start: "node src/index.js",
1011
+ const qualityScripts = {
1012
+ lint: "biome check src/",
1013
+ format: "biome check --write src/",
1014
+ ...config.typescript ? { typecheck: "tsc --noEmit" } : {},
1019
1015
  test: "vitest run",
1020
1016
  "test:watch": "vitest"
1021
1017
  };
1018
+ const scripts = {
1019
+ ...config.typescript ? config.edge ? {
1020
+ dev: "tsx watch src/index.ts",
1021
+ build: "tsc",
1022
+ start: "node dist/index.js",
1023
+ deploy: "wrangler deploy",
1024
+ "deploy:dev": "wrangler dev"
1025
+ } : {
1026
+ dev: "tsx watch src/index.ts",
1027
+ build: "tsc",
1028
+ start: "node dist/index.js"
1029
+ } : config.edge ? {
1030
+ dev: "node --watch src/index.js",
1031
+ start: "node src/index.js",
1032
+ deploy: "wrangler deploy",
1033
+ "deploy:dev": "wrangler dev"
1034
+ } : {
1035
+ dev: "node --watch src/index.js",
1036
+ start: "node src/index.js"
1037
+ },
1038
+ ...qualityScripts
1039
+ };
1022
1040
  const imports = config.typescript ? {
1023
1041
  "#config/*": "./dist/config/*",
1024
1042
  "#shared/*": "./dist/shared/*",
1025
1043
  "#resources/*": "./dist/resources/*",
1026
- "#plugins/*": "./dist/plugins/*",
1027
- "#services/*": "./dist/services/*",
1028
- "#lib/*": "./dist/lib/*",
1029
- "#utils/*": "./dist/utils/*"
1044
+ "#plugins/*": "./dist/plugins/*"
1030
1045
  } : {
1031
1046
  "#config/*": "./src/config/*",
1032
1047
  "#shared/*": "./src/shared/*",
1033
1048
  "#resources/*": "./src/resources/*",
1034
- "#plugins/*": "./src/plugins/*",
1035
- "#services/*": "./src/services/*",
1036
- "#lib/*": "./src/lib/*",
1037
- "#utils/*": "./src/utils/*"
1049
+ "#plugins/*": "./src/plugins/*"
1038
1050
  };
1039
1051
  return JSON.stringify({
1040
1052
  name: config.name,
@@ -1079,7 +1091,7 @@ function tsconfigTemplate() {
1079
1091
  function vitestConfigTemplate(config) {
1080
1092
  const srcDir = config.typescript ? "./src" : "./src";
1081
1093
  return `import { defineConfig } from 'vitest/config';
1082
- import { resolve } from 'path';
1094
+ import { resolve } from 'node:path';
1083
1095
 
1084
1096
  export default defineConfig({
1085
1097
  test: {
@@ -1104,6 +1116,7 @@ node_modules/
1104
1116
  # Build
1105
1117
  dist/
1106
1118
  *.js.map
1119
+ *.tsbuildinfo
1107
1120
 
1108
1121
  # Environment (local overrides — never commit secrets)
1109
1122
  .env.local
@@ -1129,6 +1142,68 @@ npm-debug.log*
1129
1142
  coverage/
1130
1143
  `;
1131
1144
  }
1145
+ /**
1146
+ * Biome config — formatter + linter in one. Mirrors arc's own defaults
1147
+ * (2-space indent, double quotes, organize-imports on) so generated code
1148
+ * and the framework share a house style. `npm run lint` / `npm run format`.
1149
+ */
1150
+ function biomeTemplate() {
1151
+ return `${JSON.stringify({
1152
+ $schema: "https://biomejs.dev/schemas/2.4.15/schema.json",
1153
+ vcs: {
1154
+ enabled: true,
1155
+ clientKind: "git",
1156
+ useIgnoreFile: true
1157
+ },
1158
+ files: { ignoreUnknown: true },
1159
+ formatter: {
1160
+ enabled: true,
1161
+ indentStyle: "space",
1162
+ indentWidth: 2,
1163
+ lineWidth: 100
1164
+ },
1165
+ assist: { actions: { source: { organizeImports: "on" } } },
1166
+ linter: {
1167
+ enabled: true,
1168
+ rules: { recommended: true }
1169
+ },
1170
+ javascript: { formatter: {
1171
+ quoteStyle: "double",
1172
+ semicolons: "always"
1173
+ } }
1174
+ }, null, 2)}\n`;
1175
+ }
1176
+ /**
1177
+ * GitHub Actions CI — install, typecheck, lint, test on push + PR.
1178
+ * The quality gate every team re-adds by hand; ship it wired.
1179
+ */
1180
+ function ciWorkflowTemplate(config) {
1181
+ return `name: CI
1182
+
1183
+ on:
1184
+ push:
1185
+ branches: [main]
1186
+ pull_request:
1187
+
1188
+ jobs:
1189
+ build:
1190
+ runs-on: ubuntu-latest
1191
+ steps:
1192
+ - uses: actions/checkout@v4
1193
+ - uses: actions/setup-node@v4
1194
+ with:
1195
+ node-version: 22
1196
+ cache: npm
1197
+ - name: Install
1198
+ run: npm ci
1199
+ ${config.typescript ? ` - name: Typecheck
1200
+ run: npm run typecheck
1201
+ ` : ""} - name: Lint
1202
+ run: npm run lint
1203
+ - name: Test
1204
+ run: npm test
1205
+ `;
1206
+ }
1132
1207
  function envExampleTemplate(config) {
1133
1208
  let content = `# Environment Files (Next.js-style priority):
1134
1209
  # .env.local → machine-specific overrides (gitignored)
@@ -1368,7 +1443,80 @@ docker-compose up -d
1368
1443
  }
1369
1444
  function configTemplate(config) {
1370
1445
  const ts = config.typescript;
1371
- const authTypeBlock = config.auth === "better-auth" ? `
1446
+ const isBetterAuth = config.auth === "better-auth";
1447
+ const isMongo = config.adapter === "mongokit";
1448
+ const isMulti = config.tenant === "multi";
1449
+ const authSchemaFields = isBetterAuth ? ` BETTER_AUTH_SECRET: z
1450
+ .string()
1451
+ .min(32, 'BETTER_AUTH_SECRET must be at least 32 characters')
1452
+ .default('dev-secret-change-in-production-min-32-chars'),
1453
+ FRONTEND_URL: z.string().url().default('http://localhost:3000'),` : ` JWT_SECRET: z
1454
+ .string()
1455
+ .min(32, 'JWT_SECRET must be at least 32 characters')
1456
+ .default('dev-secret-change-in-production-min-32'),
1457
+ JWT_EXPIRES_IN: z.string().default('7d'),`;
1458
+ const dbSchemaField = isMongo ? `\n MONGODB_URI: z.string().min(1).default('mongodb://localhost:27017/${config.name}'),` : "";
1459
+ const orgSchemaField = isMulti ? `\n ORG_HEADER: z.string().default('x-organization-id'),` : "";
1460
+ const secretVar = isBetterAuth ? "BETTER_AUTH_SECRET" : "JWT_SECRET";
1461
+ const prodGuard = ` .superRefine((env, ctx) => {
1462
+ if (env.NODE_ENV === 'production' && env.${secretVar}.startsWith('dev-secret')) {
1463
+ ctx.addIssue({
1464
+ code: 'custom',
1465
+ path: ['${secretVar}'],
1466
+ message:
1467
+ 'Set a strong ${secretVar} in production — the bundled dev default is not allowed.',
1468
+ });
1469
+ }
1470
+ })`;
1471
+ return `/**
1472
+ * Application Configuration
1473
+ *
1474
+ * Environment variables are validated with Zod at startup. A missing or
1475
+ * malformed var fails fast here with a clear message — instead of surfacing
1476
+ * as a confusing runtime error on the first request. ENV files are loaded
1477
+ * by config/env.${ts ? "ts" : "js"} (imported first in the entry points).
1478
+ */
1479
+
1480
+ import { z } from 'zod';
1481
+
1482
+ // Normalize NODE_ENV to the three canonical values the rest of the app
1483
+ // reasons about (matches the env loader's prod/dev/test aliasing).
1484
+ const NodeEnv = z.preprocess((v) => {
1485
+ const s = String(v ?? '').toLowerCase();
1486
+ if (s === 'prod' || s === 'production') return 'production';
1487
+ if (s === 'test' || s === 'qa') return 'test';
1488
+ return 'development';
1489
+ }, z.enum(['development', 'production', 'test']));
1490
+
1491
+ const EnvSchema = z
1492
+ .object({
1493
+ NODE_ENV: NodeEnv,
1494
+ PORT: z.coerce.number().int().positive().default(8040),
1495
+ HOST: z.string().min(1).default('0.0.0.0'),
1496
+ CORS_ORIGINS: z.string().default('http://localhost:3000'),
1497
+ ${authSchemaFields}${dbSchemaField}${orgSchemaField}
1498
+ })
1499
+ ${prodGuard};
1500
+
1501
+ const parsed = EnvSchema.safeParse(process.env);
1502
+ if (!parsed.success) {
1503
+ const lines = parsed.error.issues
1504
+ .map((i) => \` - \${i.path.join('.') || '(root)'}: \${i.message}\`)
1505
+ .join('\\n');
1506
+ console.error(\`Invalid environment configuration:\\n\${lines}\`);
1507
+ process.exit(1);
1508
+ }
1509
+
1510
+ const env = parsed.data;
1511
+ ${ts ? `
1512
+ export interface AppConfig {
1513
+ env: 'development' | 'production' | 'test';
1514
+ isDev: boolean;
1515
+ isProd: boolean;
1516
+ server: {
1517
+ port: number;
1518
+ host: string;
1519
+ };${isBetterAuth ? `
1372
1520
  betterAuth: {
1373
1521
  secret: string;
1374
1522
  };
@@ -1378,78 +1526,57 @@ function configTemplate(config) {
1378
1526
  jwt: {
1379
1527
  secret: string;
1380
1528
  expiresIn: string;
1381
- };`;
1382
- let typeDefinition = "";
1383
- if (ts) typeDefinition = `
1384
- export interface AppConfig {
1385
- env: string;
1386
- isDev: boolean;
1387
- isProd: boolean;
1388
- server: {
1389
- port: number;
1390
- host: string;
1391
- };${authTypeBlock}
1529
+ };`}
1392
1530
  cors: {
1393
1531
  origins: string[] | boolean; // true = allow all ('*')
1394
1532
  methods: string[];
1395
1533
  allowedHeaders: string[];
1396
1534
  credentials: boolean;
1397
- };${config.adapter === "mongokit" ? `
1535
+ };${isMongo ? `
1398
1536
  database: {
1399
1537
  uri: string;
1400
- };` : ""}${config.tenant === "multi" ? `
1538
+ };` : ""}${isMulti ? `
1401
1539
  org: {
1402
1540
  header: string;
1403
1541
  };` : ""}
1404
1542
  }
1405
- `;
1406
- const authConfigBlock = config.auth === "better-auth" ? `
1543
+ ` : ""}
1544
+ const config${ts ? ": AppConfig" : ""} = {
1545
+ env: env.NODE_ENV,
1546
+ isDev: env.NODE_ENV !== 'production',
1547
+ isProd: env.NODE_ENV === 'production',
1548
+
1549
+ server: {
1550
+ port: env.PORT,
1551
+ host: env.HOST,
1552
+ },
1553
+ ${isBetterAuth ? `
1407
1554
  betterAuth: {
1408
- secret: process.env.BETTER_AUTH_SECRET || 'dev-secret-change-in-production-min-32-chars',
1555
+ secret: env.BETTER_AUTH_SECRET,
1409
1556
  },
1410
1557
 
1411
1558
  frontend: {
1412
- url: process.env.FRONTEND_URL || 'http://localhost:3000',
1559
+ url: env.FRONTEND_URL,
1413
1560
  },` : `
1414
1561
  jwt: {
1415
- secret: process.env.JWT_SECRET || 'dev-secret-change-in-production-min-32',
1416
- expiresIn: process.env.JWT_EXPIRES_IN || '7d',
1417
- },`;
1418
- return `/**
1419
- * Application Configuration
1420
- *
1421
- * All config is loaded from environment variables.
1422
- * ENV file is loaded by config/env.ts (imported first in entry points).
1423
- */
1424
- ${typeDefinition}
1425
- const config${ts ? ": AppConfig" : ""} = {
1426
- env: process.env.NODE_ENV || 'development',
1427
- isDev: (process.env.NODE_ENV || 'development') !== 'production',
1428
- isProd: process.env.NODE_ENV === 'production',
1429
-
1430
- server: {
1431
- port: parseInt(process.env.PORT || '8040', 10),
1432
- host: process.env.HOST || '0.0.0.0',
1433
- },
1434
- ${authConfigBlock}
1562
+ secret: env.JWT_SECRET,
1563
+ expiresIn: env.JWT_EXPIRES_IN,
1564
+ },`}
1435
1565
 
1436
1566
  cors: {
1437
1567
  // '*' = allow all origins (true), otherwise comma-separated list
1438
- origins:
1439
- process.env.CORS_ORIGINS === '*'
1440
- ? true
1441
- : (process.env.CORS_ORIGINS || 'http://localhost:3000').split(','),
1568
+ origins: env.CORS_ORIGINS === '*' ? true : env.CORS_ORIGINS.split(','),
1442
1569
  methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
1443
1570
  allowedHeaders: ['Content-Type', 'Authorization', 'x-organization-id', 'x-request-id'],
1444
1571
  credentials: true,
1445
1572
  },
1446
- ${config.adapter === "mongokit" ? `
1573
+ ${isMongo ? `
1447
1574
  database: {
1448
- uri: process.env.MONGODB_URI || 'mongodb://localhost:27017/${config.name}',
1575
+ uri: env.MONGODB_URI,
1449
1576
  },
1450
- ` : ""}${config.tenant === "multi" ? `
1577
+ ` : ""}${isMulti ? `
1451
1578
  org: {
1452
- header: process.env.ORG_HEADER || 'x-organization-id',
1579
+ header: env.ORG_HEADER,
1453
1580
  },
1454
1581
  ` : ""}};
1455
1582
 
@@ -1842,11 +1969,14 @@ function exampleTestTemplate(config) {
1842
1969
 
1843
1970
  import { describe, it, beforeAll, afterAll } from 'vitest';
1844
1971
  import { createTestApp, expectArc } from '@classytic/arc/testing';
1845
- import type { TestAppContext } from '@classytic/arc/testing';
1846
- import { exampleResource } from '../src/resources/example/example.js';
1972
+ import type { TestAppContext${ts ? ", TestAuthProvider" : ""} } from '@classytic/arc/testing';
1973
+ import exampleResource from '../src/resources/example/example.resource.js';
1847
1974
 
1848
1975
  describe('Example Resource', () => {
1849
1976
  let ctx${ts ? ": TestAppContext" : ""};
1977
+ // Narrowed once below — \`authMode: 'jwt'\` guarantees a provider, but
1978
+ // ctx.auth is typed optional, so bind it instead of asserting at every use.
1979
+ let auth${ts ? ": TestAuthProvider" : ""};
1850
1980
 
1851
1981
  beforeAll(async () => {
1852
1982
  ctx = await createTestApp({
@@ -1854,9 +1984,12 @@ describe('Example Resource', () => {
1854
1984
  authMode: 'jwt',
1855
1985
  ${config.adapter === "mongokit" ? " connectMongoose: true,\n" : ""} });
1856
1986
 
1987
+ if (!ctx.auth) throw new Error('Test auth provider was not configured');
1988
+ auth = ctx.auth;
1989
+
1857
1990
  // Arc's permission engine reads singular user.role — string,
1858
1991
  // comma-separated string, or array all normalise via getUserRoles().
1859
- ctx.auth${ts ? "!" : ""}.register('admin', {
1992
+ auth.register('admin', {
1860
1993
  user: { id: '1', role: 'admin' },
1861
1994
  orgId: 'org-1',
1862
1995
  });
@@ -1885,7 +2018,7 @@ ${config.adapter === "mongokit" ? " connectMongoose: true,\n" : ""} });
1885
2018
  const res = await ctx.app.inject({
1886
2019
  method: 'POST',
1887
2020
  url: '/examples',
1888
- headers: ctx.auth${ts ? "!" : ""}.as('admin').headers,
2021
+ headers: auth.as('admin').headers,
1889
2022
  payload: { name: 'Test Example' },
1890
2023
  });
1891
2024
  expectArc(res).ok();
@@ -2396,22 +2529,25 @@ export default flexibleMultiTenantPreset;
2396
2529
  //#region src/cli/commands/init/templates/resources.ts
2397
2530
  function resourcesIndexTemplate(config) {
2398
2531
  const ts = config.typescript;
2399
- const typeImport = ts ? "import type { FastifyInstance } from 'fastify';\n" : "";
2400
- const appType = ts ? ": FastifyInstance" : "";
2401
- return `/**
2402
- * Resources Registry
2403
- *
2404
- * Central registry for all API resources.
2405
- * All resources are mounted under /api prefix via Fastify scoping.
2406
- */
2407
-
2408
- ${typeImport}${config.auth === "jwt" ? `
2532
+ const authImports = config.auth === "jwt" ? `
2409
2533
  // Auth resources (register, login, /users/me)
2410
2534
  import { authResource, userProfileResource } from './auth/auth.resource.js';
2411
2535
  ` : `
2412
2536
  // Auth is handled by Better Auth — routes at /api/auth/*
2413
2537
  // No manual auth resource needed.
2414
- `}
2538
+ `;
2539
+ const authResources = config.auth === "jwt" ? ` authResource,
2540
+ userProfileResource,
2541
+ ` : ` `;
2542
+ return `/**
2543
+ * Resources Registry
2544
+ *
2545
+ * Central array of every API resource. Passed to \`createApp({ resources })\`
2546
+ * in app.${ts ? "ts" : "js"}, which mounts each one under the configured
2547
+ * resourcePrefix (/api) — add a resource by importing it and listing it here.
2548
+ */
2549
+
2550
+ ${authImports}
2415
2551
  // App resources
2416
2552
  import exampleResource from './example/example.resource.js';
2417
2553
 
@@ -2422,23 +2558,8 @@ import exampleResource from './example/example.resource.js';
2422
2558
  * All registered resources
2423
2559
  */
2424
2560
  export const resources = [
2425
- ${config.auth === "jwt" ? ` authResource,
2426
- userProfileResource,
2427
- ` : ` `}exampleResource,
2561
+ ${authResources}exampleResource,
2428
2562
  ]${ts ? " as const" : ""};
2429
-
2430
- /**
2431
- * Register all resources with the app under a common prefix.
2432
- * Fastify scoping ensures all routes are mounted at /api/*.
2433
- * The apiPrefix option in openApiPlugin keeps OpenAPI docs in sync.
2434
- */
2435
- export async function registerResources(app${appType}, prefix = '/api')${ts ? ": Promise<void>" : ""} {
2436
- await app.register(async (scope) => {
2437
- for (const resource of resources) {
2438
- await scope.register(resource.toPlugin());
2439
- }
2440
- }, { prefix });
2441
- }
2442
2563
  `;
2443
2564
  }
2444
2565
  function sharedIndexTemplate(_config) {
@@ -2524,18 +2645,13 @@ userSchema.methods.removeOrganization = function(organizationId${ts ? ": Types.O
2524
2645
  userSchema.index({ 'organizations.organizationId': 1 });
2525
2646
  ` : "";
2526
2647
  const userType = ts ? `
2527
- const PLATFORM_ROLES = ['user', 'admin', 'superadmin'] as const;
2528
- type PlatformRole = typeof PLATFORM_ROLES[number];
2529
-
2530
- /**
2531
- * Comma-separated list of platform roles (Better Auth admin-plugin convention).
2532
- * Single role: 'admin'. Multiple: 'admin,trainer'. Arc's permission engine
2533
- * normalises both forms via getUserRoles() — see @classytic/arc/scope.
2534
- */
2535
2648
  type User = {
2536
2649
  name: string;
2537
2650
  email: string;
2538
2651
  password: string;
2652
+ // Platform role(s), Better Auth admin-plugin convention: a single role
2653
+ // ('admin') or a comma-separated list ('admin,trainer'). Arc's permission
2654
+ // engine normalises both forms via getUserRoles() — see @classytic/arc/scope.
2539
2655
  role: string;${config.tenant === "multi" ? `
2540
2656
  organizations: UserOrganization[];` : ""}
2541
2657
  resetPasswordToken?: string;
@@ -2551,7 +2667,7 @@ type UserMethods = {
2551
2667
  };
2552
2668
 
2553
2669
  export type UserDocument = HydratedDocument<User, UserMethods>;
2554
- export type UserModel = Model<User, {}, UserMethods>;
2670
+ export type UserModel = Model<User, Record<string, never>, UserMethods>;
2555
2671
  ` : "";
2556
2672
  return `/**
2557
2673
  * User Model
@@ -2559,7 +2675,7 @@ export type UserModel = Model<User, {}, UserMethods>;
2559
2675
  */
2560
2676
 
2561
2677
  import bcrypt from 'bcryptjs';
2562
- import mongoose${ts ? ", { type HydratedDocument, type Model, type Types }" : ""} from 'mongoose';
2678
+ import mongoose${ts ? `, { type HydratedDocument, type Model${config.tenant === "multi" ? ", type Types" : ""} }` : ""} from 'mongoose';
2563
2679
  ${orgRoles}
2564
2680
  const { Schema } = mongoose;
2565
2681
  ${orgInterface}${userType}
@@ -2774,7 +2890,9 @@ async function createProjectStructure(projectPath, config) {
2774
2890
  ".gitignore": gitignoreTemplate(),
2775
2891
  ".env.example": envExampleTemplate(config),
2776
2892
  ".env.dev": envDevTemplate(config),
2777
- "README.md": readmeTemplate(config)
2893
+ "README.md": readmeTemplate(config),
2894
+ "biome.json": biomeTemplate(),
2895
+ ".github/workflows/ci.yml": ciWorkflowTemplate(config)
2778
2896
  };
2779
2897
  if (config.typescript) files["tsconfig.json"] = tsconfigTemplate();
2780
2898
  files["vitest.config.ts"] = vitestConfigTemplate(config);
@@ -3016,6 +3134,31 @@ async function installDependencies(projectPath, _config, pm) {
3016
3134
  console.log(`\nDependencies installed successfully.`);
3017
3135
  }
3018
3136
  /**
3137
+ * Normalize the freshly-scaffolded tree to Biome's house style so the
3138
+ * shipped `npm run lint` (= `biome check`) is green on first run and the
3139
+ * generated code matches the framework's formatting.
3140
+ *
3141
+ * Best-effort: runs the project-local Biome (installed as a devDep) via the
3142
+ * package manager's exec. Swallows failure — a formatting hiccup must never
3143
+ * fail `init`. Only call this when dependencies were installed (otherwise
3144
+ * there is no Biome binary to invoke).
3145
+ */
3146
+ async function formatProject(projectPath, pm) {
3147
+ console.log(` Formatting project...`);
3148
+ try {
3149
+ await runCommand(`${getExecPrefix(pm)} biome check --write --no-errors-on-unmatched .`, projectPath);
3150
+ } catch {}
3151
+ }
3152
+ /** Package-manager `exec` prefix for running a project-local binary. */
3153
+ function getExecPrefix(pm) {
3154
+ switch (pm) {
3155
+ case "pnpm": return "pnpm exec";
3156
+ case "yarn": return "yarn";
3157
+ case "bun": return "bunx";
3158
+ default: return "npx";
3159
+ }
3160
+ }
3161
+ /**
3019
3162
  * Get the plain `install` command for a package manager. Reads the declared
3020
3163
  * dependencies from the project's `package.json`.
3021
3164
  */
@@ -3091,6 +3234,7 @@ async function init(options = {}) {
3091
3234
  if (!options.skipInstall) {
3092
3235
  console.log("\n📥 Installing dependencies...\n");
3093
3236
  await installDependencies(projectPath, config, packageManager);
3237
+ await formatProject(projectPath, packageManager);
3094
3238
  }
3095
3239
  printSuccessMessage(config, options.skipInstall);
3096
3240
  }
@@ -1,5 +1,5 @@
1
- import { n as DomainEvent } from "../EventTransport-CaaXM5Y1.mjs";
2
- import { c as WebSocketClient, l as WebSocketMessage } from "../websocket-BFBT5rH-.mjs";
1
+ import { n as DomainEvent } from "../EventTransport-IEn7Tn-Q.mjs";
2
+ import { c as WebSocketClient, l as WebSocketMessage } from "../websocket-MlYlrYq0.mjs";
3
3
  import { FastifyPluginAsync, FastifyRequest } from "fastify";
4
4
 
5
5
  //#region src/integrations/event-gateway.d.ts
@@ -4,7 +4,7 @@ const eventGatewayPluginImpl = async (fastify, opts = {}) => {
4
4
  const { auth = true, orgScoped = false, roomPolicy, maxMessageBytes, maxSubscriptionsPerClient, authenticate } = opts;
5
5
  if (auth && !authenticate && !fastify.hasDecorator("authenticate")) throw new Error("[arc-event-gateway] auth is true but fastify.authenticate is not registered. Register an auth plugin first, provide a custom authenticate function, or set auth: false.");
6
6
  if (opts.sse !== false) {
7
- const { default: ssePlugin } = await import("../sse-Xq8UtuQx.mjs").then((n) => n.r);
7
+ const { default: ssePlugin } = await import("../sse-CfUjwjDk.mjs").then((n) => n.r);
8
8
  await fastify.register(ssePlugin, {
9
9
  path: opts.sse?.path ?? "/events/stream",
10
10
  requireAuth: auth,
@@ -1,7 +1,7 @@
1
- import { c as WebSocketClient, l as WebSocketMessage, u as WebSocketPluginOptions } from "../websocket-BFBT5rH-.mjs";
1
+ import { c as WebSocketClient, l as WebSocketMessage, u as WebSocketPluginOptions } from "../websocket-MlYlrYq0.mjs";
2
2
  import { EventGatewayOptions } from "./event-gateway.mjs";
3
3
  import { JobDefinition, JobDispatchOptions, JobDispatcher, JobMeta, JobsPluginOptions, QueueStats } from "./jobs.mjs";
4
- import { c as McpAuthResult, d as PromptDefinition, g as ToolDefinition, h as ToolContext, l as McpPluginOptions, m as ToolAnnotations, n as CallToolResult, o as CrudOperation, r as CreateMcpServerConfig, t as BetterAuthHandler, u as McpResourceConfig } from "../types-BWBcb88c.mjs";
4
+ import { c as McpAuthResult, d as PromptDefinition, g as ToolDefinition, h as ToolContext, l as McpPluginOptions, m as ToolAnnotations, n as CallToolResult, o as CrudOperation, r as CreateMcpServerConfig, t as BetterAuthHandler, u as McpResourceConfig } from "../types-D60PFwfG.mjs";
5
5
  import { StreamlinePluginOptions, WorkflowLike, WorkflowRunLike } from "./streamline.mjs";
6
6
  import { WebhookDeliveryRecord, WebhookManager, WebhookPluginOptions, WebhookStore, WebhookSubscription } from "./webhooks.mjs";
7
- export { type BetterAuthHandler, type CallToolResult, type CreateMcpServerConfig, type CrudOperation, type EventGatewayOptions, type JobDefinition, type JobDispatchOptions, type JobDispatcher, type JobMeta, type JobsPluginOptions, type McpAuthResult, type McpPluginOptions, type McpResourceConfig, type PromptDefinition, type QueueStats, type StreamlinePluginOptions, type ToolAnnotations, type ToolContext, type ToolDefinition, type WebSocketClient, type WebSocketMessage, type WebSocketPluginOptions, type WebhookDeliveryRecord, type WebhookManager, type WebhookPluginOptions, type WebhookStore, type WebhookSubscription, type WorkflowLike, type WorkflowRunLike };
7
+ export type { BetterAuthHandler, CallToolResult, CreateMcpServerConfig, CrudOperation, EventGatewayOptions, JobDefinition, JobDispatchOptions, JobDispatcher, JobMeta, JobsPluginOptions, McpAuthResult, McpPluginOptions, McpResourceConfig, PromptDefinition, QueueStats, StreamlinePluginOptions, ToolAnnotations, ToolContext, ToolDefinition, WebSocketClient, WebSocketMessage, WebSocketPluginOptions, WebhookDeliveryRecord, WebhookManager, WebhookPluginOptions, WebhookStore, WebhookSubscription, WorkflowLike, WorkflowRunLike };
@@ -1,7 +1,7 @@
1
- import { V as ResourceDefinition, bt as IRequestContext, yt as IControllerResponse } from "../../index-QYma8mdC.mjs";
2
- import { i as RequestScope } from "../../types-BJwJN2Pg.mjs";
3
- import { c as PermissionCheck } from "../../fields-CKLrhyOb.mjs";
4
- import { a as CrudDescriptionOverride, c as McpAuthResult, d as PromptDefinition, f as PromptResult, g as ToolDefinition, h as ToolContext, i as CrudDescriptionMeta, l as McpPluginOptions, m as ToolAnnotations, n as CallToolResult, o as CrudOperation, p as SessionEntry, r as CreateMcpServerConfig, s as McpAuthResolver, t as BetterAuthHandler, u as McpResourceConfig } from "../../types-BWBcb88c.mjs";
1
+ import { V as ResourceDefinition, bt as IRequestContext, yt as IControllerResponse } from "../../index-CHNQIhcb.mjs";
2
+ import { i as RequestScope } from "../../types-LNebCoJx.mjs";
3
+ import { c as PermissionCheck } from "../../fields-C7ahdGYf.mjs";
4
+ import { a as CrudDescriptionOverride, c as McpAuthResult, d as PromptDefinition, f as PromptResult, g as ToolDefinition, h as ToolContext, i as CrudDescriptionMeta, l as McpPluginOptions, m as ToolAnnotations, n as CallToolResult, o as CrudOperation, p as SessionEntry, r as CreateMcpServerConfig, s as McpAuthResolver, t as BetterAuthHandler, u as McpResourceConfig } from "../../types-D60PFwfG.mjs";
5
5
  import { ErrorContract } from "@classytic/repo-core/errors";
6
6
  import { FastifyPluginAsync } from "fastify";
7
7
  import { z } from "zod";
@@ -1,4 +1,4 @@
1
- import { a as defaultCrudDescription, c as mcpHandlerAdapter, d as toCallToolResult, f as toCallToolSuccess, h as resolveToolCollisions, i as fieldRulesToZod, l as permissionDeniedResult, m as createMcpServer, n as mcpPlugin, o as resolveCrudDescription, p as buildRequestContext, r as resourceToTools, s as invokeController, t as filterResourcesForMcp, u as toCallToolError } from "../../mcpPlugin-CzKdt3B8.mjs";
1
+ import { a as defaultCrudDescription, c as mcpHandlerAdapter, d as toCallToolResult, f as toCallToolSuccess, h as resolveToolCollisions, i as fieldRulesToZod, l as permissionDeniedResult, m as createMcpServer, n as mcpPlugin, o as resolveCrudDescription, p as buildRequestContext, r as resourceToTools, s as invokeController, t as filterResourcesForMcp, u as toCallToolError } from "../../mcpPlugin-D1wuRD2c.mjs";
2
2
  //#region src/integrations/mcp/defineTool.ts
3
3
  /**
4
4
  * Define a type-safe MCP tool.