@classytic/arc 2.20.0 → 2.21.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.
- package/dist/{BaseController-D-MHZ27_.mjs → BaseController-BnLYgE9A.mjs} +2 -2
- package/dist/{EventTransport-IEn7Tn-Q.d.mts → EventTransport-QmY7A258.d.mts} +0 -1
- package/dist/{QueryCache-TRfXau3W.d.mts → QueryCache-Z1B38koh.d.mts} +0 -1
- package/dist/{actionPermissions-C9RMiIpc.mjs → actionPermissions-ze70xXJi.mjs} +1 -1
- package/dist/audit/index.d.mts +9 -5
- package/dist/auth/audit.d.mts +7 -4
- package/dist/auth/audit.mjs +5 -0
- package/dist/auth/index.d.mts +7 -14
- package/dist/auth/index.mjs +1 -1
- package/dist/auth/redis-session.d.mts +1 -2
- package/dist/cache/index.d.mts +2 -3
- package/dist/cli/commands/describe.d.mts +1 -2
- package/dist/cli/commands/docs.mjs +1 -1
- package/dist/cli/commands/init.mjs +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/context/index.d.mts +2 -2
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +4 -4
- package/dist/{core-CWhyGkiM.mjs → core-DZ6Xe1jR.mjs} +65 -10
- package/dist/{createActionRouter-HlQso0jO.mjs → createActionRouter-BWMDW-dL.mjs} +2 -2
- package/dist/{createAggregationRouter-5LzPzgw1.mjs → createAggregationRouter-l5mNdYrZ.mjs} +1 -1
- package/dist/{createApp-D6uwzCKu.mjs → createApp-Bi61XxqU.mjs} +149 -137
- package/dist/discovery/index.d.mts +0 -1
- package/dist/docs/index.d.mts +1 -2
- package/dist/docs/index.mjs +1 -1
- package/dist/{elevation-xGUBq6p_.d.mts → elevation-C9s5hFP_.d.mts} +0 -1
- package/dist/encryption/index.d.mts +2 -144
- package/dist/{errorHandler-BtUUDPEa.d.mts → errorHandler-B0e-bq-O.d.mts} +0 -1
- package/dist/{errors-DOHkjQlD.d.mts → errors-DHcHVAgk.d.mts} +0 -1
- package/dist/{eventPlugin-DbBFd3x_.d.mts → eventPlugin-A6EbthXR.d.mts} +10 -6
- package/dist/events/index.d.mts +9 -6
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis.d.mts +1 -2
- package/dist/factory/index.d.mts +4 -4
- package/dist/factory/index.mjs +2 -2
- package/dist/{fastify-augmentation-CCQJEDgh.d.mts → fastify-augmentation-DafigGQp.d.mts} +2 -3
- package/dist/{fields-C7ahdGYf.d.mts → fields-BGqrAa_u.d.mts} +1 -2
- package/dist/hooks/index.d.mts +1 -1
- package/dist/idempotency/index.d.mts +4 -3
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/{index-DUa8WHz3.d.mts → index-B5N-NaHs.d.mts} +88 -7
- package/dist/{index-CdFkIMEd.d.mts → index-B5PoNbfu.d.mts} +36 -7
- package/dist/{index-_--GyzcO.d.mts → index-Dtrj6XZk.d.mts} +62 -28
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +6 -6
- package/dist/{init-YH_nslQR.mjs → init-0YhHkXGk.mjs} +154 -137
- package/dist/integrations/event-gateway.d.mts +2 -3
- package/dist/integrations/index.d.mts +2 -2
- package/dist/integrations/jobs.d.mts +0 -1
- package/dist/integrations/mcp/index.d.mts +6 -7
- package/dist/integrations/mcp/index.mjs +1 -1
- package/dist/integrations/mcp/testing.d.mts +1 -2
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/integrations/streamline.d.mts +2 -2
- package/dist/integrations/webhooks.d.mts +0 -1
- package/dist/integrations/websocket-pushref-redis.d.mts +1 -2
- package/dist/integrations/websocket-redis.d.mts +1 -2
- package/dist/integrations/websocket.d.mts +2 -2
- package/dist/{loadResources-B8UmpITt.mjs → loadResources-DpU8pfjV.mjs} +4 -3
- package/dist/{mcpPlugin-CuW6L_uD.mjs → mcpPlugin-B9XjjNVG.mjs} +3 -3
- package/dist/middleware/index.d.mts +1 -2
- package/dist/{module-JYH9V0I8.d.mts → module-WeuU5jfd.d.mts} +46 -1
- package/dist/{openapi-Dq6RbEGK.mjs → openapi-Kyod_di6.mjs} +2 -2
- package/dist/permissions/index.d.mts +3 -3
- package/dist/permissions/index.mjs +2 -2
- package/dist/{permissions-CgbOLJZG.mjs → permissions-BJMuKMl7.mjs} +33 -1
- package/dist/pipeline/index.d.mts +1 -2
- package/dist/plugins/index.d.mts +79 -7
- package/dist/plugins/index.mjs +88 -1
- package/dist/plugins/response-cache.d.mts +5 -3
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/presets/filesUpload.d.mts +4 -5
- package/dist/presets/filesUpload.mjs +1 -1
- package/dist/presets/index.d.mts +1 -2
- package/dist/presets/index.mjs +1 -1
- package/dist/presets/multiTenant.d.mts +1 -2
- package/dist/presets/search.d.mts +2 -3
- package/dist/presets/search.mjs +1 -1
- package/dist/{presets-DWsYQdbV.mjs → presets-gw0ciIUD.mjs} +1 -1
- package/dist/{pushref-registry-DnCqL3aa.d.mts → pushref-registry-BbcnpNTm.d.mts} +4 -2
- package/dist/{queryCachePlugin-xzFyKAjT.d.mts → queryCachePlugin-CfYWq-Ak.d.mts} +1 -2
- package/dist/{redis-C3W0qbz8.d.mts → redis-UDtLaNj6.d.mts} +0 -1
- package/dist/{redis-stream-DsP1vqZB.d.mts → redis-stream-iVR2l7aS.d.mts} +1 -2
- package/dist/{registerRoute-DGSREwPw.mjs → registerRoute-oGAl0oA8.mjs} +1 -1
- package/dist/registry/index.d.mts +2 -2
- package/dist/schemas/index.d.mts +0 -1
- package/dist/scim/index.d.mts +0 -1
- package/dist/scope/index.d.mts +2 -3
- package/dist/{sessionManager-BXG-HGwG.d.mts → sessionManager-BHOM3N_0.d.mts} +10 -6
- package/dist/{storage-Co_PQpeQ.d.mts → storage-DLUZ04kK.d.mts} +8 -4
- package/dist/testing/index.d.mts +2 -3
- package/dist/testing/index.mjs +5 -2
- package/dist/testing/storageContract.d.mts +1 -2
- package/dist/{tracing-D8jlGXP7.d.mts → tracing-CsGKQJGg.d.mts} +0 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/types/storage.d.mts +1 -1
- package/dist/types-Cc91nXuA.d.mts +132 -0
- package/dist/{types-LNebCoJx.d.mts → types-DH0GupI7.d.mts} +8 -4
- package/dist/{types-C9b2HR5W.d.mts → types-DRj-Ut4n.d.mts} +1 -2
- package/dist/{types-BHMKlMBU.d.mts → types-DpxoNX5v.d.mts} +61 -21
- package/dist/utils/index.d.mts +182 -128
- package/dist/utils/index.mjs +2 -2
- package/dist/{utils-ChjYQpjn.mjs → utils-CO8a3B_1.mjs} +70 -26
- package/dist/{versioning-D_eBCfNr.d.mts → versioning-DQ4mCvg0.d.mts} +1 -2
- package/dist/{websocket-MlYlrYq0.d.mts → websocket-uuWqM6UY.d.mts} +5 -4
- package/package.json +7 -7
- package/skills/arc-module-publishing/SKILL.md +242 -0
- package/skills/arc-module-publishing/references/authoring-modules.md +272 -0
- package/skills/arc-module-publishing/references/package-manifest.md +155 -0
- package/skills/arc-module-publishing/references/publishing-workflow.md +182 -0
|
@@ -17,7 +17,7 @@ function createAdapterTemplate(config) {
|
|
|
17
17
|
|
|
18
18
|
import { createMongooseAdapter } from '@classytic/mongokit/adapter';
|
|
19
19
|
import { buildCrudSchemasFromModel } from '@classytic/mongokit';
|
|
20
|
-
${ts ? "import type { Model } from 'mongoose';\nimport type { Repository } from '@classytic/mongokit';" : ""}
|
|
20
|
+
${ts ? "import type { DataAdapter } from '@classytic/repo-core/adapter';\nimport type { Model } from 'mongoose';\nimport type { Repository } from '@classytic/mongokit';" : ""}
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Create a MongoKit-powered adapter for a resource.
|
|
@@ -30,7 +30,10 @@ ${ts ? "import type { Model } from 'mongoose';\nimport type { Repository } from
|
|
|
30
30
|
export function createAdapter${ts ? "<TDoc = unknown>" : ""}(
|
|
31
31
|
model${ts ? ": Model<TDoc>" : ""},
|
|
32
32
|
repository${ts ? ": Repository<TDoc>" : ""}
|
|
33
|
-
) {
|
|
33
|
+
)${ts ? ": DataAdapter<TDoc>" : ""} {
|
|
34
|
+
// Explicit return type keeps the declaration portable — under pnpm's
|
|
35
|
+
// non-hoisted layout the inferred type references mongokit's internal
|
|
36
|
+
// paths and tsc fails with TS2742/TS2883.
|
|
34
37
|
return createMongooseAdapter({
|
|
35
38
|
model,
|
|
36
39
|
repository,
|
|
@@ -484,20 +487,13 @@ ${[
|
|
|
484
487
|
].filter(Boolean).join("\n")}
|
|
485
488
|
import config from '#config/index.js';
|
|
486
489
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
export function getAuth()${ts ? ": ReturnType<typeof betterAuth>" : ""} {
|
|
495
|
-
if (process.env.NODE_ENV === 'production' && !process.env.BETTER_AUTH_SECRET) {
|
|
496
|
-
throw new Error('BETTER_AUTH_SECRET is required in production (min 32 chars)');
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
if (!_auth) {
|
|
500
|
-
_auth = betterAuth({
|
|
490
|
+
// Factory keeps the CONCRETE betterAuth({...}) instantiation as the source
|
|
491
|
+
// of truth for the instance type — annotating with the wide
|
|
492
|
+
// \`Auth<BetterAuthOptions>\` (aka \`ReturnType<typeof betterAuth>\`) does not
|
|
493
|
+
// typecheck because Better Auth's \`Auth<T>\` is generic over the exact
|
|
494
|
+
// options object.
|
|
495
|
+
function createAuth() {
|
|
496
|
+
return betterAuth({
|
|
501
497
|
secret: config.betterAuth.secret,
|
|
502
498
|
baseURL: process.env.BETTER_AUTH_URL || \`http://localhost:\${config.server.port}\`,
|
|
503
499
|
basePath: '/api/auth',
|
|
@@ -545,6 +541,26 @@ ${orgPluginUsage}
|
|
|
545
541
|
enabled: process.env.NODE_ENV === 'production',
|
|
546
542
|
},
|
|
547
543
|
});
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
let _auth${ts ? ": ReturnType<typeof createAuth> | null" : ""} = null;
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Get the Better Auth instance (lazy singleton)
|
|
550
|
+
*
|
|
551
|
+
* Must be called AFTER database connection is established.
|
|
552
|
+
*/
|
|
553
|
+
export function getAuth()${ts ? ": ReturnType<typeof createAuth>" : ""} {
|
|
554
|
+
if (process.env.NODE_ENV === 'production' && !process.env.BETTER_AUTH_SECRET) {
|
|
555
|
+
throw new Error('BETTER_AUTH_SECRET is required in production (min 32 chars)');
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Narrow through a local — assigning the module-level \`_auth\` directly
|
|
559
|
+
// would lose the non-null narrowing across the calls below.
|
|
560
|
+
let auth = _auth;
|
|
561
|
+
if (!auth) {
|
|
562
|
+
auth = createAuth();
|
|
563
|
+
_auth = auth;
|
|
548
564
|
${useStubs ? `
|
|
549
565
|
// Register stub Mongoose models for Better Auth's collections so
|
|
550
566
|
// \`.populate('user')\` / \`ref: 'organization'\` resolve against BA-owned
|
|
@@ -552,7 +568,7 @@ ${useStubs ? `
|
|
|
552
568
|
registerBetterAuthStubs(mongoose, {${stubPluginsList ? ` plugins: [${stubPluginsList}]` : ""}${stubExtras} });
|
|
553
569
|
` : ""} }
|
|
554
570
|
|
|
555
|
-
return
|
|
571
|
+
return auth;
|
|
556
572
|
}
|
|
557
573
|
|
|
558
574
|
export default getAuth;
|
|
@@ -692,6 +708,9 @@ export async function getUserProfile(request${ts ? ": FastifyRequest" : ""}, rep
|
|
|
692
708
|
try {
|
|
693
709
|
const requestUser = (request${ts ? " as unknown as { user?: { _id?: string; id?: string } }" : ""}).user;
|
|
694
710
|
const userId = requestUser?._id || requestUser?.id;
|
|
711
|
+
if (!userId) {
|
|
712
|
+
return reply.code(401).send({ error: 'Authentication required', code: 'arc.unauthorized' });
|
|
713
|
+
}
|
|
695
714
|
const user = await userRepository.getById(userId);
|
|
696
715
|
|
|
697
716
|
if (!user) {
|
|
@@ -712,6 +731,9 @@ export async function updateUserProfile(request${ts ? ": FastifyRequest" : ""},
|
|
|
712
731
|
try {
|
|
713
732
|
const requestUser = (request${ts ? " as unknown as { user?: { _id?: string; id?: string } }" : ""}).user;
|
|
714
733
|
const userId = requestUser?._id || requestUser?.id;
|
|
734
|
+
if (!userId) {
|
|
735
|
+
return reply.code(401).send({ error: 'Authentication required', code: 'arc.unauthorized' });
|
|
736
|
+
}
|
|
715
737
|
const updates${ts ? ": Record<string, unknown>" : ""} = { ...request.body${ts ? " as Record<string, unknown>" : ""} };
|
|
716
738
|
|
|
717
739
|
// Prevent updating protected fields — auth-managed only
|
|
@@ -840,20 +862,29 @@ function authTestTemplate(config) {
|
|
|
840
862
|
*/
|
|
841
863
|
|
|
842
864
|
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
843
|
-
${config.adapter === "mongokit" ? "import mongoose from 'mongoose';\n" : ""}import { createAppInstance } from '../src/app.js';
|
|
865
|
+
${config.adapter === "mongokit" ? "import mongoose from 'mongoose';\nimport { MongoMemoryServer } from 'mongodb-memory-server';\n" : ""}import { createAppInstance } from '../src/app.js';
|
|
844
866
|
${ts ? "import type { FastifyInstance } from 'fastify';\n" : ""}
|
|
867
|
+
// Resources mount under the app's resourcePrefix (see src/app.${ts ? "ts" : "js"}).
|
|
868
|
+
const API = '/api';
|
|
869
|
+
|
|
845
870
|
describe('Auth', () => {
|
|
846
871
|
let app${ts ? ": FastifyInstance" : ""};
|
|
847
|
-
const testUser = {
|
|
872
|
+
${config.adapter === "mongokit" ? ` let mongo${ts ? ": MongoMemoryServer | undefined" : ""};\n` : ""} const testUser = {
|
|
848
873
|
name: 'Test User',
|
|
849
874
|
email: 'test@example.com',
|
|
850
875
|
password: 'password123',
|
|
851
876
|
};
|
|
852
877
|
|
|
853
878
|
beforeAll(async () => {
|
|
854
|
-
${config.adapter === "mongokit" ? `
|
|
855
|
-
|
|
856
|
-
|
|
879
|
+
${config.adapter === "mongokit" ? ` // In-memory MongoDB — no local mongod required. Set MONGODB_URI to use
|
|
880
|
+
// a real instance instead (e.g. a CI service container).
|
|
881
|
+
let uri = process.env.MONGODB_URI;
|
|
882
|
+
if (!uri) {
|
|
883
|
+
mongo = await MongoMemoryServer.create();
|
|
884
|
+
uri = mongo.getUri();
|
|
885
|
+
}
|
|
886
|
+
await mongoose.connect(uri);
|
|
887
|
+
// Clean up test data (matters when MONGODB_URI points at a shared DB)
|
|
857
888
|
await mongoose.connection.collection('users').deleteMany({ email: testUser.email });
|
|
858
889
|
` : ""}
|
|
859
890
|
app = await createAppInstance();
|
|
@@ -862,27 +893,29 @@ ${config.adapter === "mongokit" ? ` const testDbUri = process.env.MONGODB_URI
|
|
|
862
893
|
|
|
863
894
|
afterAll(async () => {
|
|
864
895
|
${config.adapter === "mongokit" ? ` await mongoose.connection.collection('users').deleteMany({ email: testUser.email });
|
|
896
|
+
await app.close();
|
|
865
897
|
await mongoose.connection.close();
|
|
866
|
-
|
|
867
|
-
|
|
898
|
+
await mongo?.stop();
|
|
899
|
+
` : ` await app.close();
|
|
900
|
+
`} });
|
|
868
901
|
|
|
869
902
|
describe('POST /auth/register', () => {
|
|
870
903
|
it('should register a new user', async () => {
|
|
871
904
|
const response = await app.inject({
|
|
872
905
|
method: 'POST',
|
|
873
|
-
url:
|
|
906
|
+
url: \`\${API}/auth/register\`,
|
|
874
907
|
payload: testUser,
|
|
875
908
|
});
|
|
876
909
|
|
|
877
910
|
expect(response.statusCode).toBe(201);
|
|
878
911
|
const body = JSON.parse(response.body);
|
|
879
|
-
expect(body.
|
|
912
|
+
expect(body.message).toBeDefined();
|
|
880
913
|
});
|
|
881
914
|
|
|
882
915
|
it('should reject duplicate email', async () => {
|
|
883
916
|
const response = await app.inject({
|
|
884
917
|
method: 'POST',
|
|
885
|
-
url:
|
|
918
|
+
url: \`\${API}/auth/register\`,
|
|
886
919
|
payload: testUser,
|
|
887
920
|
});
|
|
888
921
|
|
|
@@ -894,13 +927,13 @@ ${config.adapter === "mongokit" ? ` await mongoose.connection.collection('use
|
|
|
894
927
|
it('should login with valid credentials', async () => {
|
|
895
928
|
const response = await app.inject({
|
|
896
929
|
method: 'POST',
|
|
897
|
-
url:
|
|
930
|
+
url: \`\${API}/auth/login\`,
|
|
898
931
|
payload: { email: testUser.email, password: testUser.password },
|
|
899
932
|
});
|
|
900
933
|
|
|
901
934
|
expect(response.statusCode).toBe(200);
|
|
902
935
|
const body = JSON.parse(response.body);
|
|
903
|
-
expect(body.
|
|
936
|
+
expect(body.user).toBeDefined();
|
|
904
937
|
expect(body.accessToken).toBeDefined();
|
|
905
938
|
expect(body.refreshToken).toBeDefined();
|
|
906
939
|
});
|
|
@@ -908,7 +941,7 @@ ${config.adapter === "mongokit" ? ` await mongoose.connection.collection('use
|
|
|
908
941
|
it('should reject invalid credentials', async () => {
|
|
909
942
|
const response = await app.inject({
|
|
910
943
|
method: 'POST',
|
|
911
|
-
url:
|
|
944
|
+
url: \`\${API}/auth/login\`,
|
|
912
945
|
payload: { email: testUser.email, password: 'wrongpassword' },
|
|
913
946
|
});
|
|
914
947
|
|
|
@@ -920,7 +953,7 @@ ${config.adapter === "mongokit" ? ` await mongoose.connection.collection('use
|
|
|
920
953
|
it('should require authentication', async () => {
|
|
921
954
|
const response = await app.inject({
|
|
922
955
|
method: 'GET',
|
|
923
|
-
url:
|
|
956
|
+
url: \`\${API}/users/me\`,
|
|
924
957
|
});
|
|
925
958
|
|
|
926
959
|
expect(response.statusCode).toBe(401);
|
|
@@ -955,8 +988,8 @@ ${config.adapter === "mongokit" ? ` await mongoose.connection.collection('use
|
|
|
955
988
|
const SCAFFOLD_DEP_VERSIONS = {
|
|
956
989
|
core: {
|
|
957
990
|
"@classytic/arc": "^2.20.0",
|
|
958
|
-
"@classytic/primitives": "^0.
|
|
959
|
-
"@classytic/repo-core": "^0.
|
|
991
|
+
"@classytic/primitives": "^0.11.0",
|
|
992
|
+
"@classytic/repo-core": "^0.8.0",
|
|
960
993
|
"@fastify/cors": "^11.2.0",
|
|
961
994
|
"@fastify/helmet": "^13.0.2",
|
|
962
995
|
"@fastify/rate-limit": "^10.3.0",
|
|
@@ -976,7 +1009,7 @@ const SCAFFOLD_DEP_VERSIONS = {
|
|
|
976
1009
|
},
|
|
977
1010
|
authBetterAuthApiKey: { "@better-auth/api-key": "^1.6.11" },
|
|
978
1011
|
adapterMongokit: {
|
|
979
|
-
"@classytic/mongokit": "^3.
|
|
1012
|
+
"@classytic/mongokit": "^3.21.0",
|
|
980
1013
|
mongoose: "^9.6.2"
|
|
981
1014
|
},
|
|
982
1015
|
devCommon: {
|
|
@@ -988,7 +1021,7 @@ const SCAFFOLD_DEP_VERSIONS = {
|
|
|
988
1021
|
devTypescript: {
|
|
989
1022
|
"@types/node": "^22.10.0",
|
|
990
1023
|
tsx: "^4.22.3",
|
|
991
|
-
typescript: "^
|
|
1024
|
+
typescript: "^7.0.2"
|
|
992
1025
|
},
|
|
993
1026
|
typesJwt: { "@types/bcryptjs": "^3.0.0" }
|
|
994
1027
|
};
|
|
@@ -1061,6 +1094,7 @@ function resolveScaffoldDependencies(config) {
|
|
|
1061
1094
|
const devDependencies = { ...SCAFFOLD_DEP_VERSIONS.devCommon };
|
|
1062
1095
|
if (config.auth === "better-auth") {
|
|
1063
1096
|
Object.assign(dependencies, SCAFFOLD_DEP_VERSIONS.authBetterAuth);
|
|
1097
|
+
devDependencies["@fastify/jwt"] = SCAFFOLD_DEP_VERSIONS.authJwt["@fastify/jwt"];
|
|
1064
1098
|
if (config.apiKey) Object.assign(dependencies, SCAFFOLD_DEP_VERSIONS.authBetterAuthApiKey);
|
|
1065
1099
|
} else {
|
|
1066
1100
|
Object.assign(dependencies, SCAFFOLD_DEP_VERSIONS.authJwt);
|
|
@@ -1159,6 +1193,7 @@ function tsconfigTemplate() {
|
|
|
1159
1193
|
declarationMap: true,
|
|
1160
1194
|
sourceMap: true,
|
|
1161
1195
|
resolveJsonModule: true,
|
|
1196
|
+
types: ["node"],
|
|
1162
1197
|
paths: {
|
|
1163
1198
|
"#shared/*": ["./src/shared/*"],
|
|
1164
1199
|
"#resources/*": ["./src/resources/*"],
|
|
@@ -2053,7 +2088,13 @@ import { describe, it, beforeAll, afterAll } from 'vitest';
|
|
|
2053
2088
|
import { createTestApp, expectArc } from '@classytic/arc/testing';
|
|
2054
2089
|
import type { TestAppContext${ts ? ", TestAuthProvider" : ""} } from '@classytic/arc/testing';
|
|
2055
2090
|
import exampleResource from '../src/resources/example/example.resource.js';
|
|
2056
|
-
|
|
2091
|
+
${config.tenant === "multi" ? `
|
|
2092
|
+
// Valid ObjectId hex — the example model types organizationId and createdBy
|
|
2093
|
+
// as ObjectId (createdBy is auto-stamped from the caller's user id).
|
|
2094
|
+
const TEST_ORG_ID = '64f000000000000000000001';
|
|
2095
|
+
const MANAGER_ID = '64f0000000000000000000a1';
|
|
2096
|
+
const STAFF_ID = '64f0000000000000000000a2';
|
|
2097
|
+
` : ""}
|
|
2057
2098
|
describe('Example Resource', () => {
|
|
2058
2099
|
let ctx${ts ? ": TestAppContext" : ""};
|
|
2059
2100
|
// Narrowed once below — \`authMode: 'jwt'\` guarantees a provider, but
|
|
@@ -2068,17 +2109,70 @@ ${config.adapter === "mongokit" ? " connectMongoose: true,\n" : ""} });
|
|
|
2068
2109
|
|
|
2069
2110
|
if (!ctx.auth) throw new Error('Test auth provider was not configured');
|
|
2070
2111
|
auth = ctx.auth;
|
|
2071
|
-
|
|
2112
|
+
${config.tenant === "multi" ? `
|
|
2113
|
+
// Arc's JWT auth builds a MEMBER scope straight from token claims —
|
|
2114
|
+
// \`organizationId\` + \`orgRoles\` land on \`request.scope\`. The org-staff
|
|
2115
|
+
// permission set reads those org roles; the tenant preset filters and
|
|
2116
|
+
// stamps rows by the org id.
|
|
2117
|
+
auth.register('manager', {
|
|
2118
|
+
user: { id: MANAGER_ID, role: 'user', organizationId: TEST_ORG_ID, orgRoles: ['manager'] },
|
|
2119
|
+
orgId: TEST_ORG_ID,
|
|
2120
|
+
});
|
|
2121
|
+
auth.register('staff', {
|
|
2122
|
+
user: { id: STAFF_ID, role: 'user', organizationId: TEST_ORG_ID, orgRoles: ['staff'] },
|
|
2123
|
+
orgId: TEST_ORG_ID,
|
|
2124
|
+
});
|
|
2125
|
+
` : `
|
|
2072
2126
|
// Arc's permission engine reads singular user.role — string,
|
|
2073
2127
|
// comma-separated string, or array all normalise via getUserRoles().
|
|
2128
|
+
// The id must be ObjectId-shaped: the example model's createdBy is an
|
|
2129
|
+
// ObjectId, auto-stamped from the caller's user id.
|
|
2074
2130
|
auth.register('admin', {
|
|
2075
|
-
user: { id: '
|
|
2076
|
-
orgId: 'org-1',
|
|
2131
|
+
user: { id: '64f0000000000000000000ad', role: 'admin' },
|
|
2077
2132
|
});
|
|
2078
|
-
});
|
|
2133
|
+
`} });
|
|
2079
2134
|
|
|
2080
2135
|
afterAll(() => ctx.close());
|
|
2136
|
+
${config.tenant === "multi" ? `
|
|
2137
|
+
describe('GET /examples', () => {
|
|
2138
|
+
it('should reject unauthenticated listing (org-staff gated)', async () => {
|
|
2139
|
+
const res = await ctx.app.inject({ method: 'GET', url: '/examples' });
|
|
2140
|
+
expectArc(res).unauthorized();
|
|
2141
|
+
});
|
|
2081
2142
|
|
|
2143
|
+
it('should list for an org member (rows scoped to their org)', async () => {
|
|
2144
|
+
const res = await ctx.app.inject({
|
|
2145
|
+
method: 'GET',
|
|
2146
|
+
url: '/examples',
|
|
2147
|
+
headers: auth.as('staff').headers,
|
|
2148
|
+
});
|
|
2149
|
+
expectArc(res).ok().paginated();
|
|
2150
|
+
});
|
|
2151
|
+
});
|
|
2152
|
+
|
|
2153
|
+
describe('POST /examples', () => {
|
|
2154
|
+
it('should require authentication', async () => {
|
|
2155
|
+
const res = await ctx.app.inject({
|
|
2156
|
+
method: 'POST',
|
|
2157
|
+
url: '/examples',
|
|
2158
|
+
payload: { name: 'Test Example' },
|
|
2159
|
+
});
|
|
2160
|
+
expectArc(res).unauthorized();
|
|
2161
|
+
});
|
|
2162
|
+
|
|
2163
|
+
it('should create for an org manager — organizationId stamped server-side', async () => {
|
|
2164
|
+
const res = await ctx.app.inject({
|
|
2165
|
+
method: 'POST',
|
|
2166
|
+
url: '/examples',
|
|
2167
|
+
headers: auth.as('manager').headers,
|
|
2168
|
+
// No organizationId in the body — the tenant preset injects it from
|
|
2169
|
+
// the caller's scope (the field is systemManaged in the schema).
|
|
2170
|
+
payload: { name: 'Test Example' },
|
|
2171
|
+
});
|
|
2172
|
+
expectArc(res).ok(201);
|
|
2173
|
+
});
|
|
2174
|
+
});
|
|
2175
|
+
` : `
|
|
2082
2176
|
describe('GET /examples', () => {
|
|
2083
2177
|
it('should return a list of examples (public)', async () => {
|
|
2084
2178
|
const res = await ctx.app.inject({ method: 'GET', url: '/examples' });
|
|
@@ -2103,9 +2197,10 @@ ${config.adapter === "mongokit" ? " connectMongoose: true,\n" : ""} });
|
|
|
2103
2197
|
headers: auth.as('admin').headers,
|
|
2104
2198
|
payload: { name: 'Test Example' },
|
|
2105
2199
|
});
|
|
2106
|
-
expectArc(res).ok();
|
|
2200
|
+
expectArc(res).ok(201);
|
|
2107
2201
|
});
|
|
2108
2202
|
});
|
|
2203
|
+
`}
|
|
2109
2204
|
|
|
2110
2205
|
// Add more tests as needed:
|
|
2111
2206
|
// - GET /examples/:id (expectArc(res).ok().hasData({ name: '...' }))
|
|
@@ -2495,113 +2590,35 @@ function flexibleMultiTenantPresetTemplate(config) {
|
|
|
2495
2590
|
return `/**
|
|
2496
2591
|
* Flexible Multi-Tenant Preset
|
|
2497
2592
|
*
|
|
2498
|
-
*
|
|
2593
|
+
* Thin wrapper around arc's built-in 'multiTenantPreset' with public reads:
|
|
2594
|
+
*
|
|
2595
|
+
* - list/get WITHOUT org context → allowed through unfiltered (public data)
|
|
2596
|
+
* - org context present → rows filtered + stamped to the caller's org
|
|
2597
|
+
* - elevated (platform admin) → unfiltered, cross-tenant
|
|
2598
|
+
* - create/update fail closed without org context, and update overwrites any
|
|
2599
|
+
* client-supplied tenant field (no cross-tenant document hops)
|
|
2499
2600
|
*
|
|
2500
|
-
*
|
|
2501
|
-
*
|
|
2502
|
-
*
|
|
2503
|
-
*
|
|
2601
|
+
* The built-in preset also registers 'systemManaged' field rules for the
|
|
2602
|
+
* tenant field, so generated request schemas never demand it in the body —
|
|
2603
|
+
* the server stamps it from the caller's scope instead. Don't hand-roll
|
|
2604
|
+
* tenant middleware: without those field rules Fastify's validation rejects
|
|
2605
|
+
* creates before injection can run.
|
|
2504
2606
|
*
|
|
2505
|
-
*
|
|
2607
|
+
* Want members-only reads? Drop 'allowPublic' below, or use
|
|
2608
|
+
* 'multiTenantPreset({ tenantField })' directly on the resource.
|
|
2506
2609
|
*/
|
|
2507
2610
|
${ts ? `
|
|
2508
|
-
import {
|
|
2509
|
-
import type { RequestScope } from '@classytic/arc/scope';
|
|
2611
|
+
import { multiTenantPreset } from '@classytic/arc/presets/tenant';
|
|
2510
2612
|
|
|
2511
2613
|
interface FlexibleMultiTenantOptions {
|
|
2512
2614
|
tenantField?: string;
|
|
2513
2615
|
}
|
|
2514
|
-
|
|
2515
|
-
interface PresetMiddlewares {
|
|
2516
|
-
list: ((request: any, reply: any) => Promise<void>)[];
|
|
2517
|
-
get: ((request: any, reply: any) => Promise<void>)[];
|
|
2518
|
-
create: ((request: any, reply: any) => Promise<void>)[];
|
|
2519
|
-
update: ((request: any, reply: any) => Promise<void>)[];
|
|
2520
|
-
delete: ((request: any, reply: any) => Promise<void>)[];
|
|
2521
|
-
}
|
|
2522
|
-
|
|
2523
|
-
interface Preset {
|
|
2524
|
-
[key: string]: unknown;
|
|
2525
|
-
name: string;
|
|
2526
|
-
middlewares: PresetMiddlewares;
|
|
2527
|
-
}
|
|
2528
2616
|
` : `
|
|
2529
|
-
const {
|
|
2617
|
+
const { multiTenantPreset } = require('@classytic/arc/presets/tenant');
|
|
2530
2618
|
`}
|
|
2531
|
-
|
|
2532
|
-
* Create flexible tenant filter middleware.
|
|
2533
|
-
* Only filters when org context is present.
|
|
2534
|
-
*/
|
|
2535
|
-
function createFlexibleTenantFilter(tenantField${ts ? ": string" : ""}) {
|
|
2536
|
-
return async (request${ts ? ": any" : ""}, reply${ts ? ": any" : ""}) => {
|
|
2537
|
-
const scope${ts ? ": RequestScope" : ""} = request.scope ?? { kind: 'public' };
|
|
2538
|
-
|
|
2539
|
-
// Elevated scope — platform admin sees all, no filter
|
|
2540
|
-
if (isElevated(scope)) {
|
|
2541
|
-
request.log?.debug?.({ msg: 'Elevated scope — no tenant filter' });
|
|
2542
|
-
return;
|
|
2543
|
-
}
|
|
2544
|
-
|
|
2545
|
-
// Member scope — filter by org
|
|
2546
|
-
if (isMember(scope)) {
|
|
2547
|
-
request.query = request.query ?? {};
|
|
2548
|
-
request.query._policyFilters = {
|
|
2549
|
-
...(request.query._policyFilters ?? {}),
|
|
2550
|
-
[tenantField]: scope.organizationId,
|
|
2551
|
-
};
|
|
2552
|
-
request.log?.debug?.({ msg: 'Tenant filter applied', orgId: scope.organizationId, tenantField });
|
|
2553
|
-
return;
|
|
2554
|
-
}
|
|
2555
|
-
|
|
2556
|
-
// Public / authenticated — no org context, show all data (public routes)
|
|
2557
|
-
request.log?.debug?.({ msg: 'No org context — showing all data' });
|
|
2558
|
-
};
|
|
2559
|
-
}
|
|
2560
|
-
|
|
2561
|
-
/**
|
|
2562
|
-
* Create tenant injection middleware.
|
|
2563
|
-
* Injects tenant ID into request body on create.
|
|
2564
|
-
*/
|
|
2565
|
-
function createTenantInjection(tenantField${ts ? ": string" : ""}) {
|
|
2566
|
-
return async (request${ts ? ": any" : ""}, reply${ts ? ": any" : ""}) => {
|
|
2567
|
-
const scope${ts ? ": RequestScope" : ""} = request.scope ?? { kind: 'public' };
|
|
2568
|
-
const orgId = getOrgId(scope);
|
|
2569
|
-
|
|
2570
|
-
// Fail-closed: Require orgId for create operations
|
|
2571
|
-
if (!orgId) {
|
|
2572
|
-
return reply.code(403).send({
|
|
2573
|
-
error: 'Organization context required to create resources',
|
|
2574
|
-
code: 'arc.org_required',
|
|
2575
|
-
});
|
|
2576
|
-
}
|
|
2577
|
-
|
|
2578
|
-
if (request.body) {
|
|
2579
|
-
request.body[tenantField] = orgId;
|
|
2580
|
-
}
|
|
2581
|
-
};
|
|
2582
|
-
}
|
|
2583
|
-
|
|
2584
|
-
/**
|
|
2585
|
-
* Flexible Multi-Tenant Preset
|
|
2586
|
-
*
|
|
2587
|
-
* @param options.tenantField - Field name in database (default: 'organizationId')
|
|
2588
|
-
*/
|
|
2589
|
-
export function flexibleMultiTenantPreset(options${ts ? ": FlexibleMultiTenantOptions = {}" : " = {}"})${ts ? ": Preset" : ""} {
|
|
2619
|
+
export function flexibleMultiTenantPreset(options${ts ? ": FlexibleMultiTenantOptions = {}" : " = {}"}) {
|
|
2590
2620
|
const { tenantField = 'organizationId' } = options;
|
|
2591
|
-
|
|
2592
|
-
const tenantFilter = createFlexibleTenantFilter(tenantField);
|
|
2593
|
-
const tenantInjection = createTenantInjection(tenantField);
|
|
2594
|
-
|
|
2595
|
-
return {
|
|
2596
|
-
name: 'flexibleMultiTenant',
|
|
2597
|
-
middlewares: {
|
|
2598
|
-
list: [tenantFilter],
|
|
2599
|
-
get: [tenantFilter],
|
|
2600
|
-
create: [tenantInjection],
|
|
2601
|
-
update: [tenantFilter],
|
|
2602
|
-
delete: [tenantFilter],
|
|
2603
|
-
},
|
|
2604
|
-
};
|
|
2621
|
+
return multiTenantPreset({ tenantField, allowPublic: ['list', 'get'] });
|
|
2605
2622
|
}
|
|
2606
2623
|
|
|
2607
2624
|
export default flexibleMultiTenantPreset;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { n as DomainEvent } from "../EventTransport-
|
|
2
|
-
import { c as WebSocketClient, l as WebSocketMessage } from "../websocket-
|
|
1
|
+
import { n as DomainEvent } from "../EventTransport-QmY7A258.mjs";
|
|
2
|
+
import { c as WebSocketClient, l as WebSocketMessage } from "../websocket-uuWqM6UY.mjs";
|
|
3
3
|
import { FastifyPluginAsync, FastifyRequest } from "fastify";
|
|
4
|
-
|
|
5
4
|
//#region src/integrations/event-gateway.d.ts
|
|
6
5
|
interface EventGatewayOptions {
|
|
7
6
|
/** Require auth for all real-time connections (default: true) */
|
|
@@ -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-uuWqM6UY.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-DRj-Ut4n.mjs";
|
|
5
5
|
import { StreamlinePluginOptions, WorkflowLike, WorkflowRunLike } from "./streamline.mjs";
|
|
6
6
|
import { WebhookDeliveryRecord, WebhookManager, WebhookPluginOptions, WebhookStore, WebhookSubscription } from "./webhooks.mjs";
|
|
7
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,11 +1,10 @@
|
|
|
1
|
-
import { V as ResourceDefinition, bt as IControllerResponse, xt as IRequestContext } 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 IControllerResponse, xt as IRequestContext } from "../../index-Dtrj6XZk.mjs";
|
|
2
|
+
import { i as RequestScope } from "../../types-DH0GupI7.mjs";
|
|
3
|
+
import { c as PermissionCheck } from "../../fields-BGqrAa_u.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-DRj-Ut4n.mjs";
|
|
5
5
|
import { ErrorContract } from "@classytic/repo-core/errors";
|
|
6
6
|
import { FastifyPluginAsync } from "fastify";
|
|
7
7
|
import { z } from "zod";
|
|
8
|
-
|
|
9
8
|
//#region src/integrations/mcp/aiSdkBridge.d.ts
|
|
10
9
|
/** Minimal AI SDK tool shape we need to invoke. */
|
|
11
10
|
interface AiSdkExecutable {
|
|
@@ -170,7 +169,7 @@ interface DefinePromptConfig<TArgs extends Record<string, z.ZodTypeAny>> {
|
|
|
170
169
|
title?: string;
|
|
171
170
|
/** Flat Zod shape for prompt arguments */
|
|
172
171
|
args?: TArgs;
|
|
173
|
-
handler: (args: { [K in keyof TArgs]: z.infer<TArgs[K]
|
|
172
|
+
handler: (args: { [K in keyof TArgs]: z.infer<TArgs[K]>; }) => PromptResult;
|
|
174
173
|
}
|
|
175
174
|
/**
|
|
176
175
|
* Define a type-safe MCP prompt.
|
|
@@ -197,7 +196,7 @@ interface DefineToolConfig<TInput extends Record<string, z.ZodTypeAny>, TSession
|
|
|
197
196
|
/** Flat Zod shape for structured output */
|
|
198
197
|
output?: Record<string, z.ZodTypeAny>;
|
|
199
198
|
annotations?: ToolAnnotations;
|
|
200
|
-
handler: (input: { [K in keyof TInput]: z.infer<TInput[K]
|
|
199
|
+
handler: (input: { [K in keyof TInput]: z.infer<TInput[K]>; }, ctx: ToolContext<TSession>) => Promise<CallToolResult>;
|
|
201
200
|
}
|
|
202
201
|
/**
|
|
203
202
|
* Define a type-safe MCP tool.
|
|
@@ -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-B9XjjNVG.mjs";
|
|
2
2
|
//#region src/integrations/mcp/defineTool.ts
|
|
3
3
|
/**
|
|
4
4
|
* Define a type-safe MCP tool.
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { c as McpAuthResult, l as McpPluginOptions } from "../../types-
|
|
2
|
-
|
|
1
|
+
import { c as McpAuthResult, l as McpPluginOptions } from "../../types-DRj-Ut4n.mjs";
|
|
3
2
|
//#region src/integrations/mcp/testing.d.ts
|
|
4
3
|
interface TestMcpClientOptions {
|
|
5
4
|
/** MCP plugin options (resources, overrides, etc.) — same as mcpPlugin config */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { m as createMcpServer, r as resourceToTools, t as filterResourcesForMcp } from "../../mcpPlugin-
|
|
1
|
+
import { m as createMcpServer, r as resourceToTools, t as filterResourcesForMcp } from "../../mcpPlugin-B9XjjNVG.mjs";
|
|
2
2
|
//#region src/integrations/mcp/testing.ts
|
|
3
3
|
/**
|
|
4
4
|
* @classytic/arc/mcp/testing — MCP Test Utilities
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { FastifyPluginAsync, FastifyRequest } from "fastify";
|
|
2
|
-
|
|
3
2
|
//#region src/integrations/streamline.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Start options — matches @classytic/streamline v2.3+ `StartOptions`.
|
|
@@ -53,7 +52,8 @@ interface WorkflowLike {
|
|
|
53
52
|
eventBus: {
|
|
54
53
|
on(event: string, listener: (...args: unknown[]) => void): void;
|
|
55
54
|
off(event: string, listener: (...args: unknown[]) => void): void;
|
|
56
|
-
};
|
|
55
|
+
};
|
|
56
|
+
/** Repository — used by the list-runs endpoint to query workflow_runs. */
|
|
57
57
|
repository?: {
|
|
58
58
|
getAll(params: Record<string, unknown>, options?: Record<string, unknown>): Promise<unknown>;
|
|
59
59
|
/**
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { c as SerializedEntry, i as Principal, n as FencedWriteOutcome, s as PushRefStore, t as EnvelopeSnapshot } from "../pushref-registry-
|
|
2
|
-
|
|
1
|
+
import { c as SerializedEntry, i as Principal, n as FencedWriteOutcome, s as PushRefStore, t as EnvelopeSnapshot } from "../pushref-registry-BbcnpNTm.mjs";
|
|
3
2
|
//#region src/integrations/websocket-pushref-redis.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Minimal `ioredis` shape — typed structurally so this file doesn't
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { f as WebSocketAdapter } from "../websocket-
|
|
2
|
-
|
|
1
|
+
import { f as WebSocketAdapter } from "../websocket-uuWqM6UY.mjs";
|
|
3
2
|
//#region src/integrations/websocket-redis.d.ts
|
|
4
3
|
interface RedisLike {
|
|
5
4
|
publish(channel: string, message: string): Promise<number>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as GeoRoomOptions, c as WebSocketClient, d as LocalWebSocketAdapter, f as WebSocketAdapter, i as GeoRoom, l as WebSocketMessage, n as GeoPoint, o as RoomManager, r as GeoPublishOpts, s as AuthResult, t as websocketPlugin, u as WebSocketPluginOptions } from "../websocket-
|
|
2
|
-
import { a as PushRefRegistry, c as SerializedEntry, i as Principal, o as PushRefRegistryOptions, r as MemoryPushRefStore, s as PushRefStore } from "../pushref-registry-
|
|
1
|
+
import { a as GeoRoomOptions, c as WebSocketClient, d as LocalWebSocketAdapter, f as WebSocketAdapter, i as GeoRoom, l as WebSocketMessage, n as GeoPoint, o as RoomManager, r as GeoPublishOpts, s as AuthResult, t as websocketPlugin, u as WebSocketPluginOptions } from "../websocket-uuWqM6UY.mjs";
|
|
2
|
+
import { a as PushRefRegistry, c as SerializedEntry, i as Principal, o as PushRefRegistryOptions, r as MemoryPushRefStore, s as PushRefStore } from "../pushref-registry-BbcnpNTm.mjs";
|
|
3
3
|
export { type AuthResult, type GeoPoint, type GeoPublishOpts, GeoRoom, type GeoRoomOptions, LocalWebSocketAdapter, MemoryPushRefStore, type Principal, PushRefRegistry, type PushRefRegistryOptions, type PushRefStore, RoomManager, type SerializedEntry, type WebSocketAdapter, type WebSocketClient, type WebSocketMessage, type WebSocketPluginOptions, websocketPlugin };
|
|
@@ -59,10 +59,11 @@ var loadResources_exports = /* @__PURE__ */ __exportAll({ loadResources: () => l
|
|
|
59
59
|
* ```
|
|
60
60
|
*/
|
|
61
61
|
async function loadResources(dir, options = {}) {
|
|
62
|
-
const { suffix = ".resource", recursive = true, exclude, include } = options;
|
|
62
|
+
const { suffix = ".resource", recursive = true, exclude, include, filter } = options;
|
|
63
63
|
const absDir = resolve(dir.startsWith("file://") ? dirname(fileURLToPath(dir)) : dir);
|
|
64
|
-
const
|
|
65
|
-
|
|
64
|
+
const discovered = await collectFiles(absDir, new RegExp(`${escapeRegex(suffix)}\\.(ts|js|mts|mjs)$`), recursive);
|
|
65
|
+
discovered.sort();
|
|
66
|
+
const files = filter ? discovered.filter((f) => filter(f)) : discovered;
|
|
66
67
|
const includeSet = include ? new Set(include) : null;
|
|
67
68
|
const excludeSet = exclude ? new Set(exclude) : null;
|
|
68
69
|
const skipped = [];
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { p as isArcError, t as ArcError } from "./errors-DkO8Nk6-.mjs";
|
|
2
2
|
import { c as getOrgId, g as getUserId } from "./types-bHblZ9YN.mjs";
|
|
3
|
-
import { t as BaseController } from "./BaseController-
|
|
4
|
-
import {
|
|
3
|
+
import { t as BaseController } from "./BaseController-BnLYgE9A.mjs";
|
|
4
|
+
import { P as normalizePermissionResult } from "./permissions-BJMuKMl7.mjs";
|
|
5
5
|
import { t as executePipeline } from "./pipe-BOLmGIxa.mjs";
|
|
6
|
-
import { i as resolvePipelineSteps, t as resolveActionPermission } from "./actionPermissions-
|
|
6
|
+
import { i as resolvePipelineSteps, t as resolveActionPermission } from "./actionPermissions-ze70xXJi.mjs";
|
|
7
7
|
import { n as validateAggregations } from "./validate-C2mGgSXg.mjs";
|
|
8
8
|
import { n as executeAggregation } from "./buildHandler-D_2ULWxZ.mjs";
|
|
9
9
|
import { t as pluralize } from "./pluralize-BhrgwZb9.mjs";
|