@classytic/arc 2.15.4 → 2.16.1
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/README.md +1 -0
- package/bin/arc.js +12 -0
- package/dist/{BaseController-dx3m2J8V.mjs → BaseController-Vk8I7C0x.mjs} +61 -19
- package/dist/{HookSystem-Iiebom92.mjs → HookSystem-Cmf7-Etp.mjs} +8 -4
- package/dist/{QueryCache-D41bfdBB.d.mts → QueryCache-8YmAQ-zW.d.mts} +1 -1
- package/dist/{ResourceRegistry-CTERg_2x.mjs → ResourceRegistry-CzSzVK1m.mjs} +55 -9
- package/dist/audit/index.d.mts +1 -1
- package/dist/audit/index.mjs +4 -2
- package/dist/auth/index.d.mts +4 -4
- package/dist/auth/index.mjs +4 -4
- package/dist/auth/redis-session.d.mts +1 -1
- package/dist/{betterAuthOpenApi--M_i87dQ.mjs → betterAuthOpenApi-ClWxaceA.mjs} +10 -6
- package/dist/buildHandler-C_SkBNF3.mjs +302 -0
- package/dist/cache/index.d.mts +3 -3
- package/dist/cache/index.mjs +3 -3
- package/dist/{caching-SM8gghN6.mjs → caching-8MfrrUYU.mjs} +1 -1
- package/dist/cli/commands/describe.d.mts +35 -1
- package/dist/cli/commands/describe.mjs +52 -12
- package/dist/cli/commands/docs.d.mts +1 -4
- package/dist/cli/commands/docs.mjs +4 -16
- package/dist/cli/commands/generate.d.mts +2 -20
- package/dist/cli/commands/generate.mjs +1 -546
- package/dist/cli/commands/init.d.mts +2 -40
- package/dist/cli/commands/init.mjs +1 -3045
- package/dist/cli/commands/introspect.mjs +53 -64
- package/dist/cli/index.d.mts +2 -2
- package/dist/cli/index.mjs +2 -2
- package/dist/{constants-Cxde4rpC.mjs → constants-TrJVIJl0.mjs} +7 -0
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +5 -5
- package/dist/{core-CvmOqEms.mjs → core-wKeGXn38.mjs} +222 -44
- package/dist/createActionRouter-eiOFtnC3.mjs +288 -0
- package/dist/{createAggregationRouter-B0bPDf5b.mjs → createAggregationRouter-C4unhBnV.mjs} +3 -2
- package/dist/{createApp-PFegs47-.mjs → createApp-DdPBtmzp.mjs} +16 -14
- package/dist/{defineEvent-D5h7EvAx.mjs → defineEvent-NPKUJRt8.mjs} +1 -1
- package/dist/docs/index.d.mts +2 -2
- package/dist/docs/index.mjs +1 -1
- package/dist/{errorHandler-Bk-AGhkU.mjs → errorHandler-DNPzqaTT.mjs} +17 -14
- package/dist/errors-4ZloYFvm.d.mts +91 -0
- package/dist/{eventPlugin-CaKTYkYM.mjs → eventPlugin-CnJCUyM0.mjs} +1 -1
- package/dist/{eventPlugin-qXpqTebY.d.mts → eventPlugin-DjEx_J3j.d.mts} +1 -1
- package/dist/events/index.d.mts +3 -3
- package/dist/events/index.mjs +5 -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 +2 -2
- package/dist/factory/index.mjs +4 -3
- package/dist/fastify-augmentation-CJm0vh-l.d.mts +42 -0
- package/dist/{fields-COhcH3fk.d.mts → fields-DqZLp5d6.d.mts} +1 -1
- package/dist/generate-CcM24hoq.mjs +654 -0
- package/dist/generate-cRnsafMS.d.mts +38 -0
- 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-BTqLEvhu.d.mts → index-3L-adFJO.d.mts} +12 -12
- package/dist/{index-BstGxcc3.d.mts → index-CC_pgZjY.d.mts} +88 -17
- package/dist/{index-BswOSJCE.d.mts → index-DBDgy6Hw.d.mts} +430 -19
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +7 -8
- package/dist/init-D-vrTZ1G.d.mts +71 -0
- package/dist/init-DYzfniuX.mjs +3098 -0
- package/dist/integrations/event-gateway.d.mts +2 -2
- package/dist/integrations/event-gateway.mjs +1 -1
- package/dist/integrations/index.d.mts +2 -2
- package/dist/integrations/jobs.mjs +3 -3
- package/dist/integrations/mcp/index.d.mts +239 -7
- package/dist/integrations/mcp/index.mjs +2 -528
- package/dist/integrations/mcp/testing.d.mts +2 -2
- package/dist/integrations/mcp/testing.mjs +6 -10
- package/dist/integrations/streamline.mjs +26 -1
- package/dist/integrations/websocket-redis.d.mts +1 -1
- package/dist/integrations/websocket.d.mts +1 -1
- package/dist/integrations/websocket.mjs +1 -0
- package/dist/loadResourcesFromEntry-DCjYMgfC.mjs +51 -0
- package/dist/{resourceToTools-tFYUNmM0.mjs → mcpPlugin-Dbgz9_Rj.mjs} +1021 -318
- package/dist/{memory-UBydS5ku.mjs → memory-QOLe11D5.mjs} +2 -0
- package/dist/middleware/index.d.mts +1 -1
- package/dist/middleware/index.mjs +1 -1
- package/dist/{openapi-BHXhoX8O.mjs → openapi-BRnd3pT7.mjs} +82 -44
- package/dist/permissions/index.d.mts +2 -2
- package/dist/permissions/index.mjs +1 -1
- package/dist/{permissions-ohQyv50e.mjs → permissions-CTxMrreC.mjs} +2 -2
- package/dist/{pipe-Zr0KXjQe.mjs → pipe-DiCyvyPN.mjs} +1 -0
- package/dist/pipeline/index.d.mts +1 -1
- package/dist/pipeline/index.mjs +1 -1
- package/dist/plugins/index.d.mts +5 -59
- package/dist/plugins/index.mjs +10 -10
- package/dist/plugins/response-cache.mjs +5 -5
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/{pluralize-DQgqgifU.mjs → pluralize-B9M8xvy-.mjs} +2 -1
- package/dist/preloadResources-BOXzPhKU.mjs +45 -0
- package/dist/presets/filesUpload.d.mts +4 -4
- package/dist/presets/filesUpload.mjs +2 -2
- 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 +4 -3
- package/dist/presets/search.d.mts +2 -2
- package/dist/presets/search.mjs +1 -1
- package/dist/{presets-BbkjdPeH.mjs → presets-C9BE6WaZ.mjs} +2 -2
- package/dist/{queryCachePlugin-m1XsgAIJ.mjs → queryCachePlugin-B4XMSSe7.mjs} +2 -2
- package/dist/{queryCachePlugin-CqMdLI2-.d.mts → queryCachePlugin-Do4P_WBC.d.mts} +2 -2
- package/dist/{redis-DiMkdHEl.d.mts → redis-cpqVb85w.d.mts} +1 -1
- package/dist/{redis-stream-D6HzR1Z_.d.mts → redis-stream-BuiAS3aE.d.mts} +1 -1
- package/dist/registry/index.d.mts +341 -2
- package/dist/registry/index.mjs +3 -3
- package/dist/registry-BrlHkrRS.mjs +582 -0
- package/dist/{routerShared-DrOa-26E.mjs → routerShared-ClV4cCaa.mjs} +40 -16
- package/dist/scope/index.d.mts +3 -3
- package/dist/scope/index.mjs +3 -3
- package/dist/{sse-Bz-5ZeTt.mjs → sse-jh5OqFjR.mjs} +1 -1
- package/dist/testing/index.d.mts +2 -25
- package/dist/testing/index.mjs +17 -51
- 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-BQsjgQzS.d.mts → types-BD0BCdf6.d.mts} +106 -12
- package/dist/{types-C_s5moIu.mjs → types-Bi0r0vjG.mjs} +53 -1
- package/dist/{types-CTYvcwHe.d.mts → types-CfapW2t8.d.mts} +42 -1
- package/dist/{types-DrBaUwyV.d.mts → types-Dw--SyTq.d.mts} +57 -11
- package/dist/utils/index.d.mts +1287 -2
- package/dist/utils/index.mjs +1 -1
- package/dist/{utils-_h9B3c57.mjs → utils-DPXZnZUx.mjs} +158 -41
- package/dist/{buildHandler-CcFOpJLh.mjs → validate-DFIP2VrM.mjs} +73 -302
- package/dist/{versioning-hmkPcDlX.d.mts → versioning-5H4930tj.d.mts} +1 -1
- package/package.json +22 -29
- package/skills/arc/SKILL.md +300 -706
- package/skills/arc/references/auth.md +19 -7
- package/skills/arc-code-review/SKILL.md +1 -1
- package/skills/arc-code-review/references/arc-cheatsheet.md +100 -322
- package/dist/createActionRouter-S3MLVYot.mjs +0 -220
- package/dist/index-bRjYu21O.d.mts +0 -1320
- package/dist/org/index.d.mts +0 -66
- package/dist/org/index.mjs +0 -486
- package/dist/org/types.d.mts +0 -82
- package/dist/org/types.mjs +0 -1
- package/dist/registry-I-ogLgL9.mjs +0 -46
- /package/dist/{EventTransport-CT_52aWU.d.mts → EventTransport-B1GFiYUy.d.mts} +0 -0
- /package/dist/{EventTransport-DLWoUMHy.mjs → EventTransport-ClEDfiMS.mjs} +0 -0
- /package/dist/{actionPermissions-CyUkQu6O.mjs → actionPermissions-Bjmvn7Eb.mjs} +0 -0
- /package/dist/{elevation-DgoeTyfX.mjs → elevation-Dci0AYLT.mjs} +0 -0
- /package/dist/{elevation-BXOWoGCF.d.mts → elevation-DvwtjDwu.d.mts} +0 -0
- /package/dist/{errorHandler-DFr45ZG4.d.mts → errorHandler-DuqTqeqn.d.mts} +0 -0
- /package/dist/{externalPaths-BD5nw6St.d.mts → externalPaths-ClykOQqa.d.mts} +0 -0
- /package/dist/{interface-beEtJyWM.d.mts → interface-BVkZsvEe.d.mts} +0 -0
- /package/dist/{interface-DfLGcus7.d.mts → interface-DoE6UoC2.d.mts} +0 -0
- /package/dist/{keys-CGcCbNyu.mjs → keys-DopsCuyQ.mjs} +0 -0
- /package/dist/{loadResources-DBMQg_Aj.mjs → loadResources-fol6JuvW.mjs} +0 -0
- /package/dist/{metrics-Qnvwc-LQ.mjs → metrics-B-PU4-Yu.mjs} +0 -0
- /package/dist/{replyHelpers-CK-FNO8E.mjs → replyHelpers-boS5Rx26.mjs} +0 -0
- /package/dist/{schemaIR-lYhC2gE5.mjs → schemaIR-DAOvBWgT.mjs} +0 -0
- /package/dist/{sessionManager-C4Le_UB3.d.mts → sessionManager-DlmaHUAl.d.mts} +0 -0
- /package/dist/{storage-Dfzt4VTl.d.mts → storage-HcAgP5Ni.d.mts} +0 -0
- /package/dist/{store-helpers-BkIN9-vu.mjs → store-helpers-5JgaxieH.mjs} +0 -0
- /package/dist/{tracing-QJVprktp.d.mts → tracing-bRqqUxFO.d.mts} +0 -0
- /package/dist/{versioning-BUrT5aP4.mjs → versioning-CuIwUQZ2.mjs} +0 -0
- /package/dist/{websocket-ChC2rqe1.d.mts → websocket-BJ0w-3Dt.d.mts} +0 -0
package/dist/scope/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { C as isService, D as requireUserId, E as requireTeamId, S as isOrgInScope, T as requireOrgId, _ as getUserRoles, a as getDPoPJkt, b as isElevated, c as getOrgId, d as getScopeContext, f as getScopeContextMap, g as getUserId, h as getTenantFromRequest, i as getClientId, l as getOrgRoles, m as getTeamId, n as PUBLIC_SCOPE, o as getMandate, p as getServiceScopes, r as getAncestorOrgIds, s as getOrgContext, t as AUTHENTICATED_SCOPE, u as getRequestScope, v as hasOrgAccess, w as requireClientId, x as isMember, y as isAuthenticated } from "../types-Bi0r0vjG.mjs";
|
|
2
2
|
import { n as normalizeRoles } from "../types-D57iXYb8.mjs";
|
|
3
|
-
import { n as elevation_default, t as elevationPlugin } from "../elevation-
|
|
3
|
+
import { n as elevation_default, t as elevationPlugin } from "../elevation-Dci0AYLT.mjs";
|
|
4
4
|
//#region src/scope/rateLimitKey.ts
|
|
5
5
|
function createTenantKeyGenerator(opts) {
|
|
6
6
|
if (opts?.strategy) return opts.strategy;
|
|
@@ -76,4 +76,4 @@ function resolveOrgFromHeader(options) {
|
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
78
|
//#endregion
|
|
79
|
-
export { AUTHENTICATED_SCOPE, PUBLIC_SCOPE, createTenantKeyGenerator, elevation_default as elevationPlugin, elevationPlugin as elevationPluginFn, getAncestorOrgIds, getClientId, getDPoPJkt, getMandate, getOrgContext, getOrgId, getOrgRoles, getRequestScope, getScopeContext, getScopeContextMap, getServiceScopes, getTeamId, getUserId, getUserRoles, hasOrgAccess, isAuthenticated, isElevated, isMember, isOrgInScope, isService, requireClientId, requireOrgId, requireTeamId, requireUserId, resolveOrgFromHeader };
|
|
79
|
+
export { AUTHENTICATED_SCOPE, PUBLIC_SCOPE, createTenantKeyGenerator, elevation_default as elevationPlugin, elevationPlugin as elevationPluginFn, getAncestorOrgIds, getClientId, getDPoPJkt, getMandate, getOrgContext, getOrgId, getOrgRoles, getRequestScope, getScopeContext, getScopeContextMap, getServiceScopes, getTeamId, getTenantFromRequest, getUserId, getUserRoles, hasOrgAccess, isAuthenticated, isElevated, isMember, isOrgInScope, isService, requireClientId, requireOrgId, requireTeamId, requireUserId, resolveOrgFromHeader };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
|
|
2
2
|
import { arcLog } from "./logger/index.mjs";
|
|
3
|
-
import { c as getOrgId, n as PUBLIC_SCOPE } from "./types-
|
|
3
|
+
import { c as getOrgId, n as PUBLIC_SCOPE } from "./types-Bi0r0vjG.mjs";
|
|
4
4
|
import fp from "fastify-plugin";
|
|
5
5
|
//#region src/plugins/sse.ts
|
|
6
6
|
var sse_exports = /* @__PURE__ */ __exportAll({
|
package/dist/testing/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { d as
|
|
1
|
+
import { Kt as AnyRecord, V as ResourceDefinition } from "../index-DBDgy6Hw.mjs";
|
|
2
|
+
import { d as preloadResourcesAsync, r as CreateAppOptions, u as preloadResources } from "../types-Dw--SyTq.mjs";
|
|
3
3
|
import { StorageContractSetup, StorageContractSetupResult, runStorageContract } from "./storageContract.mjs";
|
|
4
4
|
import { FastifyInstance, FastifyServerOptions } from "fastify";
|
|
5
5
|
import { Mock } from "vitest";
|
|
@@ -464,29 +464,6 @@ declare function createTestTimer(): {
|
|
|
464
464
|
reset: () => void;
|
|
465
465
|
};
|
|
466
466
|
//#endregion
|
|
467
|
-
//#region src/testing/preloadResources.d.ts
|
|
468
|
-
/** Eager glob result: `{ '/path/to/file.ts': resourceModule }` */
|
|
469
|
-
type EagerGlobResult = Record<string, unknown>;
|
|
470
|
-
/** Lazy glob result: `{ '/path/to/file.ts': () => Promise<unknown> }` */
|
|
471
|
-
type LazyGlobResult = Record<string, () => Promise<unknown>>;
|
|
472
|
-
/**
|
|
473
|
-
* Normalize an eager `import.meta.glob` result into a `ResourceLike[]`.
|
|
474
|
-
*
|
|
475
|
-
* Accepts either:
|
|
476
|
-
* - `{ import: 'default' }` form: values are the resource directly
|
|
477
|
-
* - default form: values are the full module — picks first export with `toPlugin()`
|
|
478
|
-
*
|
|
479
|
-
* Throws if any module doesn't yield a valid `ResourceLike`.
|
|
480
|
-
*/
|
|
481
|
-
declare function preloadResources(globResult: EagerGlobResult): ResourceLike[];
|
|
482
|
-
/**
|
|
483
|
-
* Normalize a lazy `import.meta.glob` result into a `Promise<ResourceLike[]>`.
|
|
484
|
-
*
|
|
485
|
-
* Use this when resources depend on prior bootstrap (e.g., engine init) and
|
|
486
|
-
* cannot be evaluated at import time of the preload file.
|
|
487
|
-
*/
|
|
488
|
-
declare function preloadResourcesAsync(globResult: LazyGlobResult): Promise<ResourceLike[]>;
|
|
489
|
-
//#endregion
|
|
490
467
|
//#region src/testing/testApp.d.ts
|
|
491
468
|
type DbMode = "in-memory" | {
|
|
492
469
|
uri: string;
|
package/dist/testing/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { t as CRUD_OPERATIONS } from "../constants-
|
|
1
|
+
import { t as CRUD_OPERATIONS } from "../constants-TrJVIJl0.mjs";
|
|
2
|
+
import { n as preloadResourcesAsync, t as preloadResources } from "../preloadResources-BOXzPhKU.mjs";
|
|
2
3
|
import { runStorageContract } from "./storageContract.mjs";
|
|
3
4
|
import Fastify from "fastify";
|
|
4
5
|
import { afterAll, describe, expect, it, vi } from "vitest";
|
|
@@ -415,7 +416,10 @@ async function setupBetterAuthTestApp(input) {
|
|
|
415
416
|
user: u
|
|
416
417
|
};
|
|
417
418
|
}
|
|
418
|
-
const
|
|
419
|
+
const creator = creators[0];
|
|
420
|
+
if (!creator) throw new Error("[arc-testing] setupBetterAuthTestApp: no `isCreator: true` user supplied");
|
|
421
|
+
const creatorRec = signedUp[creator.key];
|
|
422
|
+
if (!creatorRec) throw new Error(`[arc-testing] setupBetterAuthTestApp: creator '${creator.key}' missing from signed-up roster`);
|
|
419
423
|
const orgRes = await helpers.createOrg(app, creatorRec.token, org);
|
|
420
424
|
if (orgRes.statusCode >= 400 || !orgRes.orgId) throw new Error(`[arc-testing] setupBetterAuthTestApp: createOrg failed. statusCode=${orgRes.statusCode}, orgId=${orgRes.orgId ? "ok" : "missing"}, body=${JSON.stringify(orgRes.body).slice(0, 300)}`);
|
|
421
425
|
const orgId = orgRes.orgId;
|
|
@@ -423,6 +427,7 @@ async function setupBetterAuthTestApp(input) {
|
|
|
423
427
|
if (u.isCreator === true) continue;
|
|
424
428
|
if (!addMember) continue;
|
|
425
429
|
const rec = signedUp[u.key];
|
|
430
|
+
if (!rec) continue;
|
|
426
431
|
const res = await addMember({
|
|
427
432
|
app,
|
|
428
433
|
creatorToken: creatorRec.token,
|
|
@@ -486,6 +491,7 @@ function createTestFixtures() {
|
|
|
486
491
|
async clear() {
|
|
487
492
|
for (let i = tracked.length - 1; i >= 0; i--) {
|
|
488
493
|
const entry = tracked[i];
|
|
494
|
+
if (!entry) continue;
|
|
489
495
|
if (entry.destroy) await entry.destroy(entry.record).catch(() => {});
|
|
490
496
|
}
|
|
491
497
|
tracked.length = 0;
|
|
@@ -541,7 +547,9 @@ var HttpTestHarness = class {
|
|
|
541
547
|
this.runValidation();
|
|
542
548
|
}
|
|
543
549
|
runCrud() {
|
|
544
|
-
const
|
|
550
|
+
const resource = this.resource;
|
|
551
|
+
const enabledRoutes = this.enabledRoutes;
|
|
552
|
+
const updateMethods = this.updateMethods;
|
|
545
553
|
let createdId = null;
|
|
546
554
|
describe(`${resource.displayName} HTTP CRUD`, () => {
|
|
547
555
|
afterAll(async () => {
|
|
@@ -663,7 +671,9 @@ var HttpTestHarness = class {
|
|
|
663
671
|
});
|
|
664
672
|
}
|
|
665
673
|
runPermissions() {
|
|
666
|
-
const
|
|
674
|
+
const resource = this.resource;
|
|
675
|
+
const enabledRoutes = this.enabledRoutes;
|
|
676
|
+
const updateMethods = this.updateMethods;
|
|
667
677
|
const protectedOps = {
|
|
668
678
|
list: opRequiresAuth(resource, "list"),
|
|
669
679
|
get: opRequiresAuth(resource, "get"),
|
|
@@ -737,8 +747,8 @@ var HttpTestHarness = class {
|
|
|
737
747
|
});
|
|
738
748
|
}
|
|
739
749
|
runValidation() {
|
|
740
|
-
const
|
|
741
|
-
if (!enabledRoutes.has("create")) return;
|
|
750
|
+
const resource = this.resource;
|
|
751
|
+
if (!this.enabledRoutes.has("create")) return;
|
|
742
752
|
describe(`${resource.displayName} HTTP Validation`, () => {
|
|
743
753
|
it("POST with invalid payload should be rejected", async () => {
|
|
744
754
|
const { app, fixtures } = this.getOptions();
|
|
@@ -961,50 +971,6 @@ function createTestTimer() {
|
|
|
961
971
|
};
|
|
962
972
|
}
|
|
963
973
|
//#endregion
|
|
964
|
-
//#region src/testing/preloadResources.ts
|
|
965
|
-
/**
|
|
966
|
-
* Normalize an eager `import.meta.glob` result into a `ResourceLike[]`.
|
|
967
|
-
*
|
|
968
|
-
* Accepts either:
|
|
969
|
-
* - `{ import: 'default' }` form: values are the resource directly
|
|
970
|
-
* - default form: values are the full module — picks first export with `toPlugin()`
|
|
971
|
-
*
|
|
972
|
-
* Throws if any module doesn't yield a valid `ResourceLike`.
|
|
973
|
-
*/
|
|
974
|
-
function preloadResources(globResult) {
|
|
975
|
-
const resources = [];
|
|
976
|
-
for (const [path, value] of Object.entries(globResult)) {
|
|
977
|
-
const resource = pickResource(value);
|
|
978
|
-
if (!resource) throw new Error(`preloadResources: ${path} does not export a valid resource.\n Expected: a default export OR a named export with toPlugin().`);
|
|
979
|
-
resources.push(resource);
|
|
980
|
-
}
|
|
981
|
-
return resources.sort((a, b) => (a.name ?? "").localeCompare(b.name ?? ""));
|
|
982
|
-
}
|
|
983
|
-
/**
|
|
984
|
-
* Normalize a lazy `import.meta.glob` result into a `Promise<ResourceLike[]>`.
|
|
985
|
-
*
|
|
986
|
-
* Use this when resources depend on prior bootstrap (e.g., engine init) and
|
|
987
|
-
* cannot be evaluated at import time of the preload file.
|
|
988
|
-
*/
|
|
989
|
-
async function preloadResourcesAsync(globResult) {
|
|
990
|
-
return (await Promise.all(Object.entries(globResult).map(async ([path, loader]) => {
|
|
991
|
-
const resource = pickResource(await loader());
|
|
992
|
-
if (!resource) throw new Error(`preloadResourcesAsync: ${path} does not export a valid resource.\n Expected: a default export OR a named export with toPlugin().`);
|
|
993
|
-
return resource;
|
|
994
|
-
}))).sort((a, b) => (a.name ?? "").localeCompare(b.name ?? ""));
|
|
995
|
-
}
|
|
996
|
-
function pickResource(value) {
|
|
997
|
-
if (!value || typeof value !== "object") return void 0;
|
|
998
|
-
if (typeof value.toPlugin === "function") return value;
|
|
999
|
-
const mod = value;
|
|
1000
|
-
const candidates = [
|
|
1001
|
-
mod.default,
|
|
1002
|
-
mod.resource,
|
|
1003
|
-
...Object.values(mod)
|
|
1004
|
-
];
|
|
1005
|
-
for (const c of candidates) if (c && typeof c === "object" && typeof c.toPlugin === "function") return c;
|
|
1006
|
-
}
|
|
1007
|
-
//#endregion
|
|
1008
974
|
//#region src/testing/testApp.ts
|
|
1009
975
|
/**
|
|
1010
976
|
* createTestApp — test app factory for arc
|
|
@@ -1070,7 +1036,7 @@ function pickDefaultAuth(authMode, callerAuth) {
|
|
|
1070
1036
|
};
|
|
1071
1037
|
}
|
|
1072
1038
|
async function createTestApp(options = {}) {
|
|
1073
|
-
const { createApp } = await import("../createApp-
|
|
1039
|
+
const { createApp } = await import("../createApp-DdPBtmzp.mjs").then((n) => n.r);
|
|
1074
1040
|
const { resources = [], db = "in-memory", connectMongoose = false, authMode = "jwt", defaultOrgId, plugins, auth: callerAuth, ...appOptions } = options;
|
|
1075
1041
|
let dbHandle;
|
|
1076
1042
|
let dbUri;
|
package/dist/types/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
import { i as RequestScope } from "../types-
|
|
3
|
-
import { c as PermissionCheck, d as UserBase, l as PermissionContext, u as PermissionResult } from "../fields-
|
|
4
|
-
import { n as ElevationOptions, t as ElevationEvent } from "../elevation-
|
|
5
|
-
export { ActionDefinition, ActionEntry, ActionHandlerFn, ActionsMap, AnyRecord, ApiResponse, ArcDecorator, ArcFieldRule, ArcInternalMetadata, ArcRequest, AuthHelpers, AuthPluginOptions, Authenticator, AuthenticatorContext, BaseControllerOptions, ConfigError, ControllerHandler, ControllerLike, ControllerQueryOptions, CrudController, CrudRouteKey, CrudRouterOptions, CrudSchemas, ElevationEvent, ElevationOptions, EventDefinition, EventsDecorator, FastifyHandler, FastifyRequestExtras, FastifyWithAuth, FastifyWithDecorators, FieldRule, GracefulShutdownOptions, HealthCheck, HealthOptions, IController, IControllerResponse, IRequestContext, InferAdapterDoc, InferDocType, InferResourceDoc, IntrospectionData, IntrospectionPluginOptions, JWTPayload, JwtContext, LookupOption, MiddlewareConfig, MiddlewareHandler, ObjectId, OpenApiSchemas, OwnershipCheck, PaginationResult, ParsedQuery, PermissionCheck, PermissionContext, PermissionResult, PopulateOption, PresetFunction, PresetHook, PresetResult, QueryParserInterface, RateLimitConfig, RegistryEntry, RegistryStats, RequestContext, RequestIdOptions, RequestScope, RequestWithExtras, ResourceCacheConfig, ResourceConfig, ResourceHookContext, ResourceHooks, ResourceMetadata, ResourcePermissions, RouteDefinition, RouteHandler, RouteHandlerMethod, RouteMcpConfig, RouteMethod, RouteSchemaOptions, ServiceContext, TokenPair, TypedController, TypedRepository, TypedResourceConfig, UserBase, UserLike, UserOrganization, ValidateOptions, ValidationResult };
|
|
1
|
+
import { $ as OnTenantDeleteConfig, A as RequestIdOptions, Bt as AuthHelpers, C as RequestContext, D as HealthCheck, E as GracefulShutdownOptions, F as FastifyWithDecorators, G as ActionsMap, Gt as TokenPair, H as ActionDefinition, Ht as Authenticator, I as MiddlewareHandler, J as CrudRouteKey, Jt as ArcRequest, K as ArcFieldRule, Kt as AnyRecord, L as RequestWithExtras, M as EventsDecorator, N as FastifyRequestExtras, O as HealthOptions, P as FastifyWithAuth, Q as MiddlewareConfig, Qt as UserOrganization, S as QueryParserInterface, T as CrudRouterOptions, U as ActionEntry, Ut as AuthenticatorContext, Vt as AuthPluginOptions, W as ActionHandlerFn, Wt as JwtContext, X as EventDefinition, Xt as ObjectId, Y as CrudSchemas, Yt as JWTPayload, Z as FieldRule, Zt as UserLike, _ as ControllerQueryOptions, _t as FastifyHandler, a as InferAdapterDoc, at as ResolvedTenantPurge, b as ParsedQuery, bt as IRequestContext, c as TypedController, cn as BaseControllerOptions, ct as ResourceHookContext, d as PaginationResult, dt as RouteDefinition, et as OpenApiSchemas, f as IntrospectionData, ft as RouteMcpConfig, g as ArcInternalMetadata, gt as ControllerLike, h as ResourceMetadata, ht as ControllerHandler, i as ValidationResult, it as RateLimitConfig, j as ArcDecorator, k as IntrospectionPluginOptions, l as TypedRepository, lt as ResourceHooks, m as RegistryStats, mt as RouteSchemaOptions, n as ConfigError, nt as PresetHook, o as InferDocType, ot as ResourceCacheConfig, p as RegistryEntry, pt as RouteMethod, q as CrudController, qt as ApiResponse, r as ValidateOptions, rt as PresetResult, s as InferResourceDoc, st as ResourceConfig, t as RouteHandlerMethod, tt as PresetFunction, u as TypedResourceConfig, ut as ResourcePermissions, v as LookupOption, vt as IController, w as ServiceContext, x as PopulateOption, xt as RouteHandler, y as OwnershipCheck, yt as IControllerResponse } from "../index-DBDgy6Hw.mjs";
|
|
2
|
+
import { i as RequestScope } from "../types-CfapW2t8.mjs";
|
|
3
|
+
import { c as PermissionCheck, d as UserBase, l as PermissionContext, u as PermissionResult } from "../fields-DqZLp5d6.mjs";
|
|
4
|
+
import { n as ElevationOptions, t as ElevationEvent } from "../elevation-DvwtjDwu.mjs";
|
|
5
|
+
export { ActionDefinition, ActionEntry, ActionHandlerFn, ActionsMap, AnyRecord, ApiResponse, ArcDecorator, ArcFieldRule, ArcInternalMetadata, ArcRequest, AuthHelpers, AuthPluginOptions, Authenticator, AuthenticatorContext, BaseControllerOptions, ConfigError, ControllerHandler, ControllerLike, ControllerQueryOptions, CrudController, CrudRouteKey, CrudRouterOptions, CrudSchemas, ElevationEvent, ElevationOptions, EventDefinition, EventsDecorator, FastifyHandler, FastifyRequestExtras, FastifyWithAuth, FastifyWithDecorators, FieldRule, GracefulShutdownOptions, HealthCheck, HealthOptions, IController, IControllerResponse, IRequestContext, InferAdapterDoc, InferDocType, InferResourceDoc, IntrospectionData, IntrospectionPluginOptions, JWTPayload, JwtContext, LookupOption, MiddlewareConfig, MiddlewareHandler, ObjectId, OnTenantDeleteConfig, OpenApiSchemas, OwnershipCheck, PaginationResult, ParsedQuery, PermissionCheck, PermissionContext, PermissionResult, PopulateOption, PresetFunction, PresetHook, PresetResult, QueryParserInterface, RateLimitConfig, RegistryEntry, RegistryStats, RequestContext, RequestIdOptions, RequestScope, RequestWithExtras, ResolvedTenantPurge, ResourceCacheConfig, ResourceConfig, ResourceHookContext, ResourceHooks, ResourceMetadata, ResourcePermissions, RouteDefinition, RouteHandler, RouteHandlerMethod, RouteMcpConfig, RouteMethod, RouteSchemaOptions, ServiceContext, TokenPair, TypedController, TypedRepository, TypedResourceConfig, UserBase, UserLike, UserOrganization, ValidateOptions, ValidationResult };
|
package/dist/types/storage.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-
|
|
1
|
+
import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-HcAgP5Ni.mjs";
|
|
2
2
|
export { Storage, StorageContext, StorageFile, StorageReadRange, StorageReadResult, StorageUploadInput };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { V as ResourceDefinition } from "./index-
|
|
1
|
+
import { V as ResourceDefinition } from "./index-DBDgy6Hw.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
|
|
4
4
|
//#region src/integrations/mcp/types.d.ts
|
|
@@ -13,10 +13,30 @@ interface ToolAnnotations {
|
|
|
13
13
|
/** Tool interacts with external systems beyond this server */
|
|
14
14
|
openWorldHint?: boolean;
|
|
15
15
|
}
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Context passed to tool handlers at invocation time.
|
|
18
|
+
*
|
|
19
|
+
* The `TSession` parameter widens `session` to a host-specific shape — pass
|
|
20
|
+
* an interface that extends `McpAuthResult` (or omits it entirely for fully
|
|
21
|
+
* custom auth resolvers) to drop the `as any` casts at call sites:
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* interface MySession extends McpAuthResult {
|
|
25
|
+
* userId: string; // required, not optional
|
|
26
|
+
* organizationId: string;
|
|
27
|
+
* tenantPlan: 'free' | 'pro';
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* defineTool<MySession>('upgrade', {
|
|
31
|
+
* handler: async (_input, ctx) => {
|
|
32
|
+
* ctx.session?.tenantPlan; // typed, no cast
|
|
33
|
+
* },
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
interface ToolContext<TSession = McpAuthResult> {
|
|
38
|
+
/** Session identity — `null` in no-auth mode */
|
|
39
|
+
session: TSession | null;
|
|
20
40
|
/** Log to MCP client (best-effort, non-blocking) */
|
|
21
41
|
log: (level: "info" | "warning" | "error" | "debug", message: string) => Promise<void>;
|
|
22
42
|
/** Raw MCP SDK extra context (for advanced use) */
|
|
@@ -59,8 +79,11 @@ interface CallToolResult {
|
|
|
59
79
|
*
|
|
60
80
|
* `inputSchema` is a flat Zod shape `{ name: z.string(), age: z.number() }` —
|
|
61
81
|
* the SDK wraps it in z.object() internally. Do NOT pass z.object() here.
|
|
82
|
+
*
|
|
83
|
+
* The `TSession` parameter lets hosts widen the session shape on the
|
|
84
|
+
* handler — same generic the `defineTool()` builder accepts.
|
|
62
85
|
*/
|
|
63
|
-
interface ToolDefinition {
|
|
86
|
+
interface ToolDefinition<TSession = McpAuthResult> {
|
|
64
87
|
name: string;
|
|
65
88
|
description: string;
|
|
66
89
|
title?: string;
|
|
@@ -69,7 +92,7 @@ interface ToolDefinition {
|
|
|
69
92
|
/** Flat Zod shape for structured output validation */
|
|
70
93
|
outputSchema?: Record<string, z.ZodTypeAny>;
|
|
71
94
|
annotations?: ToolAnnotations;
|
|
72
|
-
handler: (input: Record<string, unknown>, ctx: ToolContext) => Promise<CallToolResult>;
|
|
95
|
+
handler: (input: Record<string, unknown>, ctx: ToolContext<TSession>) => Promise<CallToolResult>;
|
|
73
96
|
}
|
|
74
97
|
/** Output of definePrompt() — plain data, not yet registered */
|
|
75
98
|
interface PromptDefinition {
|
|
@@ -93,12 +116,57 @@ interface PromptResult {
|
|
|
93
116
|
};
|
|
94
117
|
}>;
|
|
95
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Metadata threaded into a function-form description override so authors
|
|
121
|
+
* can produce a context-aware description without re-deriving filter /
|
|
122
|
+
* sort / operator lists from the resource definition by hand.
|
|
123
|
+
*
|
|
124
|
+
* Equivalent to the inputs `defaultCrudDescription()` consumes — the
|
|
125
|
+
* default description is also passed (`defaultDescription`) so authors
|
|
126
|
+
* can prepend or append to it without duplicating Arc's auto-derived
|
|
127
|
+
* filterable-fields blurb.
|
|
128
|
+
*/
|
|
129
|
+
interface CrudDescriptionMeta {
|
|
130
|
+
readonly operation: CrudOperation;
|
|
131
|
+
/** Resource display name (e.g. `Posts`) — Arc derives this from `defineResource`. */
|
|
132
|
+
readonly displayName: string;
|
|
133
|
+
readonly softDelete: boolean;
|
|
134
|
+
/** Pre-rendered default description Arc would have used. */
|
|
135
|
+
readonly defaultDescription: string;
|
|
136
|
+
readonly filterableFields?: readonly string[];
|
|
137
|
+
readonly allowedOperators?: readonly string[];
|
|
138
|
+
readonly sortableFields?: readonly string[];
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Override shape for a single CRUD tool description.
|
|
142
|
+
*
|
|
143
|
+
* - `string` — replace the default outright.
|
|
144
|
+
* - Function — receives the auto-rendered default plus the same metadata
|
|
145
|
+
* `defaultCrudDescription()` consumes, returns a final string. Use this
|
|
146
|
+
* to append context (`'Note: prefer isActive: true'`) without losing
|
|
147
|
+
* Arc's auto-derived filterable-fields blurb.
|
|
148
|
+
*/
|
|
149
|
+
type CrudDescriptionOverride = string | ((meta: CrudDescriptionMeta) => string);
|
|
96
150
|
/** Per-resource MCP configuration overrides */
|
|
97
151
|
interface McpResourceConfig {
|
|
98
152
|
/** Which CRUD operations to expose (default: all enabled on the resource) */
|
|
99
153
|
operations?: CrudOperation[];
|
|
100
|
-
/**
|
|
101
|
-
|
|
154
|
+
/**
|
|
155
|
+
* Override tool descriptions per operation.
|
|
156
|
+
*
|
|
157
|
+
* Each entry is either a plain replacement string OR a function
|
|
158
|
+
* `(meta) => string` that receives the auto-rendered default plus the
|
|
159
|
+
* filterable / sortable metadata Arc would have used. Use the function
|
|
160
|
+
* form to extend the default without losing the auto-derived blurb:
|
|
161
|
+
*
|
|
162
|
+
* ```ts
|
|
163
|
+
* descriptions: {
|
|
164
|
+
* list: ({ defaultDescription }) =>
|
|
165
|
+
* `${defaultDescription} Sort by createdAt desc for newest first.`,
|
|
166
|
+
* }
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
descriptions?: Partial<Record<CrudOperation, CrudDescriptionOverride>>;
|
|
102
170
|
/** Fields to hide from MCP tool schemas (beyond schemaOptions.hiddenFields) */
|
|
103
171
|
hideFields?: string[];
|
|
104
172
|
/** Per-operation tool name overrides: `{ get: 'get_job_by_id' }` */
|
|
@@ -168,9 +236,35 @@ interface McpPluginOptions {
|
|
|
168
236
|
serverVersion?: string;
|
|
169
237
|
/** Instructions for the LLM — guidance on tool usage, constraints */
|
|
170
238
|
instructions?: string;
|
|
171
|
-
/**
|
|
239
|
+
/**
|
|
240
|
+
* Resources to exclude by name (ignored if `expose`/`include` is set).
|
|
241
|
+
*
|
|
242
|
+
* Drift-prone for LLM-facing surfaces: a new `defineResource()` is exposed
|
|
243
|
+
* by default and you have to remember to add it here. Prefer `expose` when
|
|
244
|
+
* the principle of least authority matters.
|
|
245
|
+
*/
|
|
172
246
|
exclude?: string[];
|
|
173
|
-
/**
|
|
247
|
+
/**
|
|
248
|
+
* Default-deny allowlist — only resources whose names appear here are
|
|
249
|
+
* surfaced to MCP. New `defineResource()` calls are auto-denied (the
|
|
250
|
+
* inverse of `exclude`), matching the principle-of-least-authority that
|
|
251
|
+
* LLM-driven tool surfaces want.
|
|
252
|
+
*
|
|
253
|
+
* Mutually exclusive with `include` (a deprecated alias) — passing both
|
|
254
|
+
* throws at registration. Mutually exclusive with `exclude`: the deny
|
|
255
|
+
* default would render the exclude list redundant; passing both throws
|
|
256
|
+
* with a hint to drop `exclude`.
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```ts
|
|
260
|
+
* await app.register(mcpPlugin, { resources, expose: ['post'] });
|
|
261
|
+
* ```
|
|
262
|
+
*/
|
|
263
|
+
expose?: string[];
|
|
264
|
+
/**
|
|
265
|
+
* @deprecated Use `expose` — same default-deny semantics with a clearer
|
|
266
|
+
* verb. Kept for backwards compatibility with pre-2.15.5 hosts.
|
|
267
|
+
*/
|
|
174
268
|
include?: string[];
|
|
175
269
|
/** Tool name prefix: 'crm' → 'crm_list_products' */
|
|
176
270
|
toolNamePrefix?: string;
|
|
@@ -288,4 +382,4 @@ interface CreateMcpServerConfig {
|
|
|
288
382
|
/** CRUD operation type */
|
|
289
383
|
type CrudOperation = "list" | "get" | "create" | "update" | "delete";
|
|
290
384
|
//#endregion
|
|
291
|
-
export {
|
|
385
|
+
export { CrudDescriptionOverride as a, McpAuthResult as c, PromptDefinition as d, PromptResult as f, ToolDefinition as g, ToolContext as h, CrudDescriptionMeta as i, McpPluginOptions as l, ToolAnnotations as m, CallToolResult as n, CrudOperation as o, SessionEntry as p, CreateMcpServerConfig as r, McpAuthResolver as s, BetterAuthHandler as t, McpResourceConfig as u };
|
|
@@ -47,6 +47,58 @@ function getOrgId(scope) {
|
|
|
47
47
|
if (scope.kind === "elevated") return scope.organizationId;
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
|
+
* Resolve the tenant (organization) id from an incoming Fastify request,
|
|
51
|
+
* walking the canonical sources in order: `request.scope` → `x-organization-id`
|
|
52
|
+
* header. Returns `{ organizationId, source }` so callers can log or branch
|
|
53
|
+
* on which path won.
|
|
54
|
+
*
|
|
55
|
+
* Use in custom handlers that bypass arc's auto-CRUD path (worker routes,
|
|
56
|
+
* batch importers, cross-engine subscribers) and therefore don't get the
|
|
57
|
+
* tenant injected by `BaseCrudController`. Bridges arc's HTTP shape to
|
|
58
|
+
* the mongokit/kit-side tenant context (e.g. `createTenantContext().run`).
|
|
59
|
+
*
|
|
60
|
+
* Header fallback is intentional: matches `resolveOrgFromHeader` semantics
|
|
61
|
+
* for hosts that select an org via header instead of session/scope. Don't
|
|
62
|
+
* reach for this when `getOrgId(scope)` alone is enough — for standard
|
|
63
|
+
* authenticated routes the scope is already authoritative.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* import { getTenantFromRequest } from '@classytic/arc/scope';
|
|
68
|
+
* import { tenantContext } from './lib/mongokit.js';
|
|
69
|
+
*
|
|
70
|
+
* fastify.post('/statements/batch', async (req, reply) => {
|
|
71
|
+
* const { organizationId } = getTenantFromRequest(req);
|
|
72
|
+
* if (!organizationId) {
|
|
73
|
+
* return reply.code(400).send({ error: 'organizationId required' });
|
|
74
|
+
* }
|
|
75
|
+
* await tenantContext.run({ tenantId: organizationId }, async () => {
|
|
76
|
+
* await statementRepository.create(req.body);
|
|
77
|
+
* });
|
|
78
|
+
* });
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
function getTenantFromRequest(req, options = {}) {
|
|
82
|
+
if (req.scope) {
|
|
83
|
+
const id = getOrgId(req.scope);
|
|
84
|
+
if (id) return {
|
|
85
|
+
organizationId: id,
|
|
86
|
+
source: "scope"
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const headerName = (options.header ?? "x-organization-id").toLowerCase();
|
|
90
|
+
const raw = req.headers[headerName];
|
|
91
|
+
const headerValue = Array.isArray(raw) ? raw[0] : raw;
|
|
92
|
+
if (typeof headerValue === "string" && headerValue.length > 0) return {
|
|
93
|
+
organizationId: headerValue,
|
|
94
|
+
source: "header"
|
|
95
|
+
};
|
|
96
|
+
return {
|
|
97
|
+
organizationId: void 0,
|
|
98
|
+
source: "none"
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
50
102
|
* Get stable client identity from a service scope.
|
|
51
103
|
*
|
|
52
104
|
* Returns the `clientId` for machine-to-machine auth (API keys, service accounts),
|
|
@@ -342,4 +394,4 @@ const PUBLIC_SCOPE = Object.freeze({ kind: "public" });
|
|
|
342
394
|
/** Default authenticated scope — used when user is logged in but no org */
|
|
343
395
|
const AUTHENTICATED_SCOPE = Object.freeze({ kind: "authenticated" });
|
|
344
396
|
//#endregion
|
|
345
|
-
export {
|
|
397
|
+
export { isService as C, requireUserId as D, requireTeamId as E, isOrgInScope as S, requireOrgId as T, getUserRoles as _, getDPoPJkt as a, isElevated as b, getOrgId as c, getScopeContext as d, getScopeContextMap as f, getUserId as g, getTenantFromRequest as h, getClientId as i, getOrgRoles as l, getTeamId as m, PUBLIC_SCOPE as n, getMandate as o, getServiceScopes as p, getAncestorOrgIds as r, getOrgContext as s, AUTHENTICATED_SCOPE as t, getRequestScope as u, hasOrgAccess as v, requireClientId as w, isMember as x, isAuthenticated as y };
|
|
@@ -229,6 +229,47 @@ declare function hasOrgAccess(scope: RequestScope): boolean;
|
|
|
229
229
|
declare function isAuthenticated(scope: RequestScope): boolean;
|
|
230
230
|
/** Get organizationId from scope (member, service, or elevated — undefined otherwise) */
|
|
231
231
|
declare function getOrgId(scope: RequestScope): string | undefined;
|
|
232
|
+
/**
|
|
233
|
+
* Resolve the tenant (organization) id from an incoming Fastify request,
|
|
234
|
+
* walking the canonical sources in order: `request.scope` → `x-organization-id`
|
|
235
|
+
* header. Returns `{ organizationId, source }` so callers can log or branch
|
|
236
|
+
* on which path won.
|
|
237
|
+
*
|
|
238
|
+
* Use in custom handlers that bypass arc's auto-CRUD path (worker routes,
|
|
239
|
+
* batch importers, cross-engine subscribers) and therefore don't get the
|
|
240
|
+
* tenant injected by `BaseCrudController`. Bridges arc's HTTP shape to
|
|
241
|
+
* the mongokit/kit-side tenant context (e.g. `createTenantContext().run`).
|
|
242
|
+
*
|
|
243
|
+
* Header fallback is intentional: matches `resolveOrgFromHeader` semantics
|
|
244
|
+
* for hosts that select an org via header instead of session/scope. Don't
|
|
245
|
+
* reach for this when `getOrgId(scope)` alone is enough — for standard
|
|
246
|
+
* authenticated routes the scope is already authoritative.
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```typescript
|
|
250
|
+
* import { getTenantFromRequest } from '@classytic/arc/scope';
|
|
251
|
+
* import { tenantContext } from './lib/mongokit.js';
|
|
252
|
+
*
|
|
253
|
+
* fastify.post('/statements/batch', async (req, reply) => {
|
|
254
|
+
* const { organizationId } = getTenantFromRequest(req);
|
|
255
|
+
* if (!organizationId) {
|
|
256
|
+
* return reply.code(400).send({ error: 'organizationId required' });
|
|
257
|
+
* }
|
|
258
|
+
* await tenantContext.run({ tenantId: organizationId }, async () => {
|
|
259
|
+
* await statementRepository.create(req.body);
|
|
260
|
+
* });
|
|
261
|
+
* });
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
declare function getTenantFromRequest(req: {
|
|
265
|
+
scope?: RequestScope;
|
|
266
|
+
headers: Record<string, string | string[] | undefined>;
|
|
267
|
+
}, options?: {
|
|
268
|
+
header?: string;
|
|
269
|
+
}): {
|
|
270
|
+
organizationId: string | undefined;
|
|
271
|
+
source: "scope" | "header" | "none";
|
|
272
|
+
};
|
|
232
273
|
/**
|
|
233
274
|
* Get stable client identity from a service scope.
|
|
234
275
|
*
|
|
@@ -477,4 +518,4 @@ declare const PUBLIC_SCOPE: Readonly<RequestScope>;
|
|
|
477
518
|
/** Default authenticated scope — used when user is logged in but no org */
|
|
478
519
|
declare const AUTHENTICATED_SCOPE: Readonly<RequestScope>;
|
|
479
520
|
//#endregion
|
|
480
|
-
export {
|
|
521
|
+
export { isMember as C, requireOrgId as D, requireClientId as E, requireTeamId as O, isElevated as S, isService as T, getTenantFromRequest as _, getAncestorOrgIds as a, hasOrgAccess as b, getMandate as c, getOrgRoles as d, getRequestScope as f, getTeamId as g, getServiceScopes as h, RequestScope as i, requireUserId as k, getOrgContext as l, getScopeContextMap as m, Mandate as n, getClientId as o, getScopeContext as p, PUBLIC_SCOPE as r, getDPoPJkt as s, AUTHENTICATED_SCOPE as t, getOrgId as u, getUserId as v, isOrgInScope as w, isAuthenticated as x, getUserRoles as y };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { r as CacheStore } from "./interface-
|
|
2
|
-
import {
|
|
3
|
-
import { n as ElevationOptions } from "./elevation-
|
|
4
|
-
import { a as EventTransport } from "./EventTransport-
|
|
5
|
-
import { t as ExternalOpenApiPaths } from "./externalPaths-
|
|
6
|
-
import { r as QueryCachePluginOptions } from "./queryCachePlugin-
|
|
7
|
-
import { t as EventPluginOptions } from "./eventPlugin-
|
|
8
|
-
import { _ as HealthOptions, f as CachingOptions, l as SSEOptions, o as MetricsOptions, t as VersioningOptions } from "./versioning-
|
|
9
|
-
import { t as ErrorHandlerOptions } from "./errorHandler-
|
|
10
|
-
import { r as IdempotencyStore } from "./interface-
|
|
1
|
+
import { r as CacheStore } from "./interface-BVkZsvEe.mjs";
|
|
2
|
+
import { Ht as Authenticator } from "./index-DBDgy6Hw.mjs";
|
|
3
|
+
import { n as ElevationOptions } from "./elevation-DvwtjDwu.mjs";
|
|
4
|
+
import { a as EventTransport } from "./EventTransport-B1GFiYUy.mjs";
|
|
5
|
+
import { t as ExternalOpenApiPaths } from "./externalPaths-ClykOQqa.mjs";
|
|
6
|
+
import { r as QueryCachePluginOptions } from "./queryCachePlugin-Do4P_WBC.mjs";
|
|
7
|
+
import { t as EventPluginOptions } from "./eventPlugin-DjEx_J3j.mjs";
|
|
8
|
+
import { _ as HealthOptions, f as CachingOptions, l as SSEOptions, o as MetricsOptions, t as VersioningOptions } from "./versioning-5H4930tj.mjs";
|
|
9
|
+
import { t as ErrorHandlerOptions } from "./errorHandler-DuqTqeqn.mjs";
|
|
10
|
+
import { r as IdempotencyStore } from "./interface-DoE6UoC2.mjs";
|
|
11
11
|
import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest, FastifyServerOptions } from "fastify";
|
|
12
12
|
|
|
13
13
|
//#region src/factory/loadResources.d.ts
|
|
@@ -203,6 +203,29 @@ interface LoadResourcesOptions<TContext = unknown> {
|
|
|
203
203
|
*/
|
|
204
204
|
declare function loadResources<TContext = unknown>(dir: string, options?: LoadResourcesOptions<TContext>): Promise<ResourceLike[]>;
|
|
205
205
|
//#endregion
|
|
206
|
+
//#region src/testing/preloadResources.d.ts
|
|
207
|
+
/** Eager glob result: `{ '/path/to/file.ts': resourceModule }` */
|
|
208
|
+
type EagerGlobResult = Record<string, unknown>;
|
|
209
|
+
/** Lazy glob result: `{ '/path/to/file.ts': () => Promise<unknown> }` */
|
|
210
|
+
type LazyGlobResult = Record<string, () => Promise<unknown>>;
|
|
211
|
+
/**
|
|
212
|
+
* Normalize an eager `import.meta.glob` result into a `ResourceLike[]`.
|
|
213
|
+
*
|
|
214
|
+
* Accepts either:
|
|
215
|
+
* - `{ import: 'default' }` form: values are the resource directly
|
|
216
|
+
* - default form: values are the full module — picks first export with `toPlugin()`
|
|
217
|
+
*
|
|
218
|
+
* Throws if any module doesn't yield a valid `ResourceLike`.
|
|
219
|
+
*/
|
|
220
|
+
declare function preloadResources(globResult: EagerGlobResult): ResourceLike[];
|
|
221
|
+
/**
|
|
222
|
+
* Normalize a lazy `import.meta.glob` result into a `Promise<ResourceLike[]>`.
|
|
223
|
+
*
|
|
224
|
+
* Use this when resources depend on prior bootstrap (e.g., engine init) and
|
|
225
|
+
* cannot be evaluated at import time of the preload file.
|
|
226
|
+
*/
|
|
227
|
+
declare function preloadResourcesAsync(globResult: LazyGlobResult): Promise<ResourceLike[]>;
|
|
228
|
+
//#endregion
|
|
206
229
|
//#region src/factory/types.d.ts
|
|
207
230
|
type CorsOptions = Record<string, unknown> & {
|
|
208
231
|
origin?: unknown;
|
|
@@ -498,6 +521,29 @@ interface CreateAppOptions {
|
|
|
498
521
|
* separately by `multipart.limits.fileSize`. (2.15.1)
|
|
499
522
|
*/
|
|
500
523
|
bodyLimit?: number;
|
|
524
|
+
/**
|
|
525
|
+
* Maximum length of a single URL path parameter (in characters).
|
|
526
|
+
*
|
|
527
|
+
* 2.16 — Fastify's default is `100`, which silently 404s modern signed-
|
|
528
|
+
* token URLs: HMAC tracking tokens (~250 chars), JWT-in-URL, OAuth state
|
|
529
|
+
* parameters, password-reset / magic-link tokens, etc. Arc's default
|
|
530
|
+
* is **400** to match the everything-is-a-signed-token reality of
|
|
531
|
+
* production apps; hosts that need longer params can raise it further
|
|
532
|
+
* (`1024` for very long JWTs).
|
|
533
|
+
*
|
|
534
|
+
* Pass-through to Fastify's `maxParamLength` constructor option — see
|
|
535
|
+
* https://fastify.dev/docs/latest/Reference/Server/#maxparamlength.
|
|
536
|
+
*
|
|
537
|
+
* @example
|
|
538
|
+
* ```ts
|
|
539
|
+
* // App expects long HMAC tokens in the URL path
|
|
540
|
+
* createApp({ preset: 'production', maxParamLength: 1024 });
|
|
541
|
+
*
|
|
542
|
+
* // Constrain tighter than arc's default for audit reasons
|
|
543
|
+
* createApp({ preset: 'production', maxParamLength: 256 });
|
|
544
|
+
* ```
|
|
545
|
+
*/
|
|
546
|
+
maxParamLength?: number;
|
|
501
547
|
/**
|
|
502
548
|
* Auth configuration
|
|
503
549
|
*
|
|
@@ -1018,4 +1064,4 @@ interface RawBodyOptions {
|
|
|
1018
1064
|
runFirst?: boolean;
|
|
1019
1065
|
}
|
|
1020
1066
|
//#endregion
|
|
1021
|
-
export { CustomPluginAuthOption as a, RawBodyOptions as c,
|
|
1067
|
+
export { CustomPluginAuthOption as a, RawBodyOptions as c, preloadResourcesAsync as d, LoadResourcesOptions as f, loadResources as h, CustomAuthenticatorOption as i, UnderPressureOptions as l, ResourceModule as m, BetterAuthOption as n, JwtAuthOption as o, ResourceLike as p, CreateAppOptions as r, MultipartOptions as s, AuthOption as t, preloadResources as u };
|