@classytic/arc 2.18.4 → 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.
- package/dist/{BaseController-B-uXzf6I.mjs → BaseController-Dy6EQHjM.mjs} +7 -7
- package/dist/{QueryCache-Dsyv2mLS.d.mts → QueryCache-TRfXau3W.d.mts} +1 -1
- package/dist/{ResourceRegistry-CWmOggxS.mjs → ResourceRegistry-5fKZwhK_.mjs} +1 -1
- package/dist/{pipeline-D4sqiokR.mjs → actionPermissions-h7DYDNMg.mjs} +28 -5
- package/dist/audit/index.d.mts +1 -1
- package/dist/auth/index.d.mts +4 -4
- package/dist/auth/index.mjs +252 -5
- package/dist/auth/redis-session.d.mts +1 -1
- package/dist/betterAuthOpenApi-CV1lxpRX.mjs +2 -0
- package/dist/{buildHandler-Cvrc2p7r.mjs → buildHandler-B0qvAguf.mjs} +1 -1
- package/dist/cache/index.d.mts +3 -3
- package/dist/cache/index.mjs +3 -3
- package/dist/{caching-C0DdKiYB.mjs → caching-_NJeDd1_.mjs} +1 -1
- package/dist/cli/commands/describe.d.mts +1 -1
- package/dist/cli/commands/describe.mjs +2 -2
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/generate.d.mts +2 -2
- package/dist/cli/commands/generate.mjs +1 -1
- package/dist/cli/commands/init.d.mts +2 -2
- package/dist/cli/commands/init.mjs +1 -1
- package/dist/cli/commands/introspect.mjs +1 -1
- package/dist/cli/index.d.mts +2 -2
- package/dist/cli/index.mjs +2 -2
- package/dist/context/index.mjs +1 -1
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +4 -4
- package/dist/{core-C88uIwd3.mjs → core-ZnQBa5rh.mjs} +55 -56
- package/dist/{createActionRouter-DGCCp-kP.mjs → createActionRouter-CagItpxI.mjs} +6 -7
- package/dist/{createAggregationRouter-Ca77b8iK.mjs → createAggregationRouter-DVKroXhC.mjs} +4 -4
- package/dist/{createApp-J1iPXY9p.mjs → createApp--703hQE1.mjs} +14 -14
- package/dist/docs/index.d.mts +2 -2
- package/dist/docs/index.mjs +2 -2
- package/dist/{elevation-BzhyVWfn.mjs → elevation-COpYKt2h.mjs} +2 -2
- package/dist/{errorHandler-Bua97SEt.mjs → errorHandler-Dxf6P_kV.mjs} +2 -2
- package/dist/{eventPlugin-Bw4bUDEO.mjs → eventPlugin-DJG2D7sy.mjs} +106 -5
- package/dist/{eventPlugin-C1W1CRbf.d.mts → eventPlugin-DbBFd3x_.d.mts} +1 -1
- package/dist/events/index.d.mts +3 -3
- package/dist/events/index.mjs +189 -5
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis.d.mts +1 -1
- package/dist/factory/index.d.mts +1 -1
- package/dist/factory/index.mjs +3 -3
- package/dist/{fastify-augmentation-BdCl_eNo.d.mts → fastify-augmentation-Cxb0ROIw.d.mts} +2 -2
- package/dist/{fields-CKLrhyOb.d.mts → fields-C7ahdGYf.d.mts} +1 -1
- package/dist/{generate-BaxDdmJ8.mjs → generate-Brans3fW.mjs} +1 -1
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.mjs +1 -1
- package/dist/idempotency/index.d.mts +2 -2
- package/dist/idempotency/index.mjs +1 -1
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/{index-QYma8mdC.d.mts → index-CHNQIhcb.d.mts} +5 -6
- package/dist/{index-vcWUGkwf.d.mts → index-CRKiiP5o.d.mts} +3 -3
- package/dist/{index-Cvo1u9n6.d.mts → index-Dh0_RSTd.d.mts} +3 -3
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +7 -7
- package/dist/{init-DSsdRfk9.mjs → init-Bqpt1Hxf.mjs} +274 -130
- package/dist/integrations/event-gateway.d.mts +2 -2
- package/dist/integrations/event-gateway.mjs +1 -1
- package/dist/integrations/index.d.mts +3 -3
- package/dist/integrations/mcp/index.d.mts +4 -4
- package/dist/integrations/mcp/index.mjs +1 -1
- package/dist/integrations/mcp/testing.d.mts +1 -1
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/integrations/streamline.mjs +7 -3
- package/dist/integrations/websocket-pushref-redis.d.mts +1 -1
- package/dist/integrations/websocket-redis.d.mts +1 -1
- package/dist/integrations/websocket.d.mts +3 -3
- package/dist/{loadResources-CwXt9MCh.mjs → loadResources-B8UmpITt.mjs} +1 -1
- package/dist/{loadResourcesFromEntry-XHNeUWpu.mjs → loadResourcesFromEntry-BTlFEx05.mjs} +1 -1
- package/dist/{mcpPlugin-CzKdt3B8.mjs → mcpPlugin-D1wuRD2c.mjs} +10 -11
- package/dist/{memory-TdTHCS9-.mjs → memory-CLXA2VeJ.mjs} +1 -1
- package/dist/{metrics-Da2EUPi9.mjs → metrics-fdxI5mn_.mjs} +1 -1
- package/dist/middleware/index.d.mts +1 -1
- package/dist/middleware/index.mjs +2 -2
- package/dist/{openapi-ButnRyOM.mjs → openapi-xVJibapr.mjs} +5 -5
- package/dist/permissions/index.d.mts +3 -3
- package/dist/permissions/index.mjs +2 -2
- package/dist/{permissions-3uzwkbQt.mjs → permissions-BPB1xqGf.mjs} +4 -4
- package/dist/{pipe-9Tl-OAus.mjs → pipe-BOLmGIxa.mjs} +1 -1
- package/dist/pipeline/index.d.mts +1 -1
- package/dist/pipeline/index.mjs +1 -1
- package/dist/plugins/index.d.mts +6 -7
- package/dist/plugins/index.mjs +12 -12
- package/dist/plugins/response-cache.mjs +1 -1
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/presets/filesUpload.d.mts +4 -4
- package/dist/presets/filesUpload.mjs +4 -4
- package/dist/presets/index.d.mts +1 -1
- package/dist/presets/index.mjs +1 -1
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/presets/multiTenant.mjs +2 -2
- package/dist/presets/search.d.mts +2 -2
- package/dist/presets/search.mjs +1 -1
- package/dist/{presets-CF79RHEo.mjs → presets-BtyFwTO4.mjs} +2 -2
- package/dist/{queryCachePlugin-CnAeFqju.mjs → queryCachePlugin-emHb0CuX.mjs} +4 -4
- package/dist/{queryCachePlugin-Bd2tYgh5.d.mts → queryCachePlugin-xzFyKAjT.d.mts} +2 -2
- package/dist/{redis-3hqH_Qk_.d.mts → redis-C3W0qbz8.d.mts} +1 -1
- package/dist/{redis-stream-BtEUtjxZ.d.mts → redis-stream-DsP1vqZB.d.mts} +1 -1
- package/dist/{rateLimit-yKvxWAky.mjs → registerRoute-CPmdkZGu.mjs} +109 -2
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +2 -2
- package/dist/{registry-Br15xdGM.mjs → registry-Bm9LjWKs.mjs} +1 -1
- package/dist/{replyHelpers-DXHVxrrj.mjs → replyHelpers-67tRawQZ.mjs} +1 -1
- package/dist/{schemaIR-CE6USIRi.mjs → schemaIR-D1MJwqmp.mjs} +1 -1
- package/dist/schemas/index.d.mts +64 -65
- package/dist/scope/index.d.mts +2 -2
- package/dist/scope/index.mjs +3 -3
- package/dist/{sse-BrY1W6U8.mjs → sse-CfUjwjDk.mjs} +7 -4
- package/dist/streaming-BQcW6_Kq.mjs +162 -0
- package/dist/testing/index.d.mts +7 -7
- package/dist/testing/index.mjs +3 -3
- package/dist/testing/storageContract.d.mts +1 -1
- package/dist/types/index.d.mts +5 -5
- package/dist/types/storage.d.mts +1 -1
- package/dist/{types-WVlAVp8T.d.mts → types-CmkknLzI.d.mts} +10 -10
- package/dist/{types-BWBcb88c.d.mts → types-D60PFwfG.d.mts} +1 -1
- package/dist/{types-Bi0r0vjG.mjs → types-bHblZ9YN.mjs} +1 -1
- package/dist/utils/index.d.mts +42 -4
- package/dist/utils/index.mjs +6 -5
- package/dist/{utils-xAQeDyU_.mjs → utils-C6QQ9-hd.mjs} +1415 -1524
- package/dist/{validate-0__MuUsK.mjs → validate-CRcaWzp2.mjs} +1 -1
- package/dist/{versioning-BSEDGXKC.d.mts → versioning-D_eBCfNr.d.mts} +8 -1
- package/dist/{versioning-C0K8KQLx.mjs → versioning-Dk-71iIz.mjs} +1 -1
- package/dist/{websocket-BFBT5rH-.d.mts → websocket-MlYlrYq0.d.mts} +1 -1
- package/package.json +36 -30
- package/dist/EventTransport-7LPXLEUX.mjs +0 -103
- package/dist/actionPermissions-CX9QIMTd.mjs +0 -24
- package/dist/betterAuthOpenApi-DAAhMZff.mjs +0 -251
- package/dist/defineEvent-DC981g-o.mjs +0 -188
- package/dist/registerRoute-BEYn0ylk.mjs +0 -108
- /package/dist/{EventTransport-CaaXM5Y1.d.mts → EventTransport-IEn7Tn-Q.d.mts} +0 -0
- /package/dist/{HookSystem-BfCpWbwM.mjs → HookSystem-C1vB_Gc9.mjs} +0 -0
- /package/dist/{constants-TrJVIJl0.mjs → constants-gaEeMlz-.mjs} +0 -0
- /package/dist/{elevation-DW90z5bT.d.mts → elevation-xGUBq6p_.d.mts} +0 -0
- /package/dist/{errorHandler-_Lp2k9M3.d.mts → errorHandler-BtUUDPEa.d.mts} +0 -0
- /package/dist/{errors-DZOemeGa.d.mts → errors-DOHkjQlD.d.mts} +0 -0
- /package/dist/{errors-j4aJm1Wg.mjs → errors-DkO8Nk6-.mjs} +0 -0
- /package/dist/{externalPaths-DLle0R07.d.mts → externalPaths-BE6wFpYv.d.mts} +0 -0
- /package/dist/{generate-Dmk8cfvX.d.mts → generate-BnsL9GBm.d.mts} +0 -0
- /package/dist/{init-BS4Daqnv.d.mts → init-BPEu8cs-.d.mts} +0 -0
- /package/dist/{interface-DL7LlWS5.d.mts → interface-C1_WLTMK.d.mts} +0 -0
- /package/dist/{interface-CsrGR8LF.d.mts → interface-Uk8ONJv7.d.mts} +0 -0
- /package/dist/{keys-B3yyBEyH.mjs → keys-Cd316u_y.mjs} +0 -0
- /package/dist/{multipartBody-709YcXi1.mjs → multipartBody-CHEQSZ6G.mjs} +0 -0
- /package/dist/{pluralize-BxdUl2P4.mjs → pluralize-DccFV9R7.mjs} +0 -0
- /package/dist/{preloadResources-B-j-iqo-.mjs → preloadResources-CHw3_oA_.mjs} +0 -0
- /package/dist/{pushref-registry-Dqclzjy7.d.mts → pushref-registry-DnCqL3aa.d.mts} +0 -0
- /package/dist/{requestContext-DDLS3NVU.mjs → requestContext-BZKOr13H.mjs} +0 -0
- /package/dist/{chunk-BpYLSNr0.mjs → rolldown-runtime-8H4AJuhK.mjs} +0 -0
- /package/dist/{schemaConverter-DatAaVNj.mjs → schemaConverter-U0MnO9vd.mjs} +0 -0
- /package/dist/{sessionManager-CyHpYXoB.d.mts → sessionManager-BXG-HGwG.d.mts} +0 -0
- /package/dist/{storage-C5q8fuEt.d.mts → storage-Co_PQpeQ.d.mts} +0 -0
- /package/dist/{store-helpers-DjSYI2uP.mjs → store-helpers-DY6xq4sM.mjs} +0 -0
- /package/dist/{tracing-Bnb1-YVd.d.mts → tracing-D8jlGXP7.d.mts} +0 -0
- /package/dist/{typeGuards-CcFZXgU7.mjs → typeGuards-C9KXUly6.mjs} +0 -0
- /package/dist/{types-BJwJN2Pg.d.mts → types-LNebCoJx.d.mts} +0 -0
- /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
|
|
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
|
-
|
|
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()
|
|
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.
|
|
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.
|
|
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
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
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
|
|
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
|
-
};${
|
|
1535
|
+
};${isMongo ? `
|
|
1398
1536
|
database: {
|
|
1399
1537
|
uri: string;
|
|
1400
|
-
};` : ""}${
|
|
1538
|
+
};` : ""}${isMulti ? `
|
|
1401
1539
|
org: {
|
|
1402
1540
|
header: string;
|
|
1403
1541
|
};` : ""}
|
|
1404
1542
|
}
|
|
1405
|
-
|
|
1406
|
-
|
|
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:
|
|
1555
|
+
secret: env.BETTER_AUTH_SECRET,
|
|
1409
1556
|
},
|
|
1410
1557
|
|
|
1411
1558
|
frontend: {
|
|
1412
|
-
url:
|
|
1559
|
+
url: env.FRONTEND_URL,
|
|
1413
1560
|
},` : `
|
|
1414
1561
|
jwt: {
|
|
1415
|
-
secret:
|
|
1416
|
-
expiresIn:
|
|
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
|
-
${
|
|
1573
|
+
${isMongo ? `
|
|
1447
1574
|
database: {
|
|
1448
|
-
uri:
|
|
1575
|
+
uri: env.MONGODB_URI,
|
|
1449
1576
|
},
|
|
1450
|
-
` : ""}${
|
|
1577
|
+
` : ""}${isMulti ? `
|
|
1451
1578
|
org: {
|
|
1452
|
-
header:
|
|
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
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
-
${
|
|
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,
|
|
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 ?
|
|
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-
|
|
2
|
-
import { c as WebSocketClient, l as WebSocketMessage } from "../websocket-
|
|
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-
|
|
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-
|
|
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-
|
|
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 {
|
|
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-
|
|
2
|
-
import { i as RequestScope } from "../../types-
|
|
3
|
-
import { c as PermissionCheck } from "../../fields-
|
|
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-
|
|
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-
|
|
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.
|