@classytic/arc 2.4.3 → 2.6.2
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 +57 -6
- package/dist/{BaseController-CkM5dUh_.mjs → BaseController-AbbRx3e0.mjs} +5 -2
- package/dist/{ResourceRegistry-DeCIFlix.mjs → ResourceRegistry-C6ngvOnn.mjs} +1 -0
- package/dist/adapters/index.d.mts +2 -2
- package/dist/adapters/index.mjs +1 -1
- package/dist/{adapters-DTC4Ug66.mjs → adapters-CTn28N4y.mjs} +72 -11
- package/dist/audit/index.d.mts +32 -6
- package/dist/audit/index.mjs +32 -4
- package/dist/audit/mongodb.d.mts +1 -1
- package/dist/auth/index.d.mts +1 -1
- package/dist/auth/index.mjs +2 -2
- package/dist/cli/commands/docs.mjs +1 -1
- package/dist/cli/commands/init.mjs +12 -9
- package/dist/cli/commands/introspect.mjs +1 -1
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.mjs +2 -2
- package/dist/{createApp-CBgVaFyh.mjs → createApp-D2w0LdYJ.mjs} +431 -290
- package/dist/{defineResource-B22gcNvn.mjs → defineResource-Ckxg6HrZ.mjs} +125 -22
- package/dist/discovery/index.mjs +1 -1
- package/dist/docs/index.d.mts +1 -1
- package/dist/dynamic/index.d.mts +1 -1
- package/dist/dynamic/index.mjs +2 -2
- package/dist/{elevation-Ca_yveIO.d.mts → elevation-C_taLQrM.d.mts} +27 -1
- package/dist/{errorHandler-DMbGdzBG.mjs → errorHandler-r2595m8T.mjs} +1 -1
- package/dist/{errors-CPpvPHT0.d.mts → errors-CcVbl1-T.d.mts} +17 -1
- package/dist/{errors-rxhfP7Hf.mjs → errors-NoQKsbAT.mjs} +23 -1
- package/dist/{eventPlugin-iGrSEmwJ.d.mts → eventPlugin-DW45v4V5.d.mts} +30 -2
- package/dist/events/index.d.mts +2 -2
- package/dist/events/index.mjs +40 -10
- package/dist/factory/index.d.mts +44 -23
- package/dist/factory/index.mjs +152 -2
- package/dist/hooks/index.d.mts +1 -1
- package/dist/idempotency/index.d.mts +3 -3
- package/dist/idempotency/mongodb.d.mts +1 -1
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/{index-BL8CaQih.d.mts → index-B4uZm82R.d.mts} +2 -2
- package/dist/{index-yhxyjqNb.d.mts → index-DrCqa3Jq.d.mts} +4 -8
- package/dist/{index-Diqcm14c.d.mts → index-NGZksqM5.d.mts} +30 -1
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +8 -7
- package/dist/integrations/event-gateway.mjs +1 -1
- package/dist/integrations/index.d.mts +1 -1
- package/dist/integrations/mcp/index.d.mts +4 -2
- 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/{interface-DGmPxakH.d.mts → interface-CrN45qz1.d.mts} +229 -13
- package/dist/{mongodb-CUpYfxfD.d.mts → mongodb-kltrBPa1.d.mts} +10 -0
- package/dist/{mongodb-bga9AbkD.d.mts → mongodb-pMvOlR5_.d.mts} +1 -1
- package/dist/org/index.d.mts +1 -1
- package/dist/org/index.mjs +1 -1
- package/dist/permissions/index.d.mts +2 -2
- package/dist/permissions/index.mjs +2 -2
- package/dist/{permissions-Jk5x3sxz.mjs → permissions-C8ImI8gC.mjs} +44 -2
- package/dist/plugins/index.d.mts +1 -1
- package/dist/plugins/index.mjs +4 -4
- package/dist/plugins/tracing-entry.mjs +1 -1
- 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 +1 -1
- package/dist/{presets-OMPaHMTY.mjs → presets-BMfdy34e.mjs} +2 -2
- package/dist/{redis-CQ5YxMC5.d.mts → redis-D0Qc-9EW.d.mts} +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +1 -1
- package/dist/{resourceToTools-PMFE8HIv.mjs → resourceToTools-DH3c3e-T.mjs} +81 -7
- package/dist/scope/index.d.mts +2 -2
- package/dist/scope/index.mjs +2 -2
- package/dist/{sse-BkViJPlT.mjs → sse-BF7GR7IB.mjs} +1 -1
- package/dist/testing/index.d.mts +26 -3
- package/dist/testing/index.mjs +46 -2
- package/dist/types/index.d.mts +3 -3
- package/dist/types/index.mjs +23 -2
- package/dist/{types-C6TQjtdi.mjs → types-BhtYdxZU.mjs} +26 -1
- package/dist/{types-Dt0-AI6E.d.mts → types-C1Z28coa.d.mts} +195 -6
- package/dist/{types-BJmgxNbF.d.mts → types-DurlBP2N.d.mts} +1 -1
- package/dist/utils/index.d.mts +2 -2
- package/dist/utils/index.mjs +1 -1
- package/package.json +6 -5
- package/skills/arc/SKILL.md +151 -4
- package/skills/arc/references/mcp.md +160 -2
- /package/dist/{interface-B4awm1RJ.d.mts → interface-gr-7qo9j.d.mts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { s as RequestScope } from "./elevation-
|
|
1
|
+
import { s as RequestScope } from "./elevation-C_taLQrM.mjs";
|
|
2
2
|
import { n as FieldPermissionMap } from "./fields-DFwdaWCq.mjs";
|
|
3
3
|
import { i as UserBase, t as PermissionCheck } from "./types-BNUccdcf.mjs";
|
|
4
4
|
import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest, RouteHandlerMethod, RouteHandlerMethod as RouteHandlerMethod$1 } from "fastify";
|
|
@@ -470,10 +470,14 @@ declare class ResourceDefinition<TDoc = AnyRecord> {
|
|
|
470
470
|
readonly disabledRoutes: CrudRouteKey[];
|
|
471
471
|
readonly events: Record<string, EventDefinition>;
|
|
472
472
|
readonly rateLimit?: RateLimitConfig | false;
|
|
473
|
+
readonly audit?: boolean | {
|
|
474
|
+
operations?: ("create" | "update" | "delete")[];
|
|
475
|
+
};
|
|
473
476
|
readonly updateMethod?: "PUT" | "PATCH" | "both";
|
|
474
477
|
readonly pipe?: PipelineConfig;
|
|
475
478
|
readonly fields?: FieldPermissionMap;
|
|
476
479
|
readonly cache?: ResourceCacheConfig;
|
|
480
|
+
readonly skipGlobalPrefix: boolean;
|
|
477
481
|
readonly tenantField?: string | false;
|
|
478
482
|
readonly idField?: string;
|
|
479
483
|
readonly queryParser?: QueryParserInterface;
|
|
@@ -1073,6 +1077,46 @@ declare module 'fastify' {
|
|
|
1073
1077
|
_ownershipCheck?: Record<string, unknown>;
|
|
1074
1078
|
}
|
|
1075
1079
|
}
|
|
1080
|
+
/**
|
|
1081
|
+
* Typed Fastify request with Arc decorations.
|
|
1082
|
+
*
|
|
1083
|
+
* Use this in `wrapHandler: false` handlers instead of `(req as any).user`.
|
|
1084
|
+
*
|
|
1085
|
+
* @example
|
|
1086
|
+
* ```typescript
|
|
1087
|
+
* import type { ArcRequest } from '@classytic/arc';
|
|
1088
|
+
*
|
|
1089
|
+
* handler: async (req: ArcRequest, reply: FastifyReply) => {
|
|
1090
|
+
* req.user?.id; // typed
|
|
1091
|
+
* req.scope.organizationId; // typed (when member)
|
|
1092
|
+
* req.signal; // AbortSignal (Fastify 5)
|
|
1093
|
+
* }
|
|
1094
|
+
* ```
|
|
1095
|
+
*/
|
|
1096
|
+
type ArcRequest = FastifyRequest & {
|
|
1097
|
+
scope: RequestScope;
|
|
1098
|
+
user: Record<string, unknown> | undefined;
|
|
1099
|
+
signal: AbortSignal;
|
|
1100
|
+
};
|
|
1101
|
+
/**
|
|
1102
|
+
* Response envelope helper — wraps data in Arc's standard `{ success, data }` format.
|
|
1103
|
+
*
|
|
1104
|
+
* @example
|
|
1105
|
+
* ```typescript
|
|
1106
|
+
* import { envelope } from '@classytic/arc';
|
|
1107
|
+
*
|
|
1108
|
+
* handler: async (req, reply) => {
|
|
1109
|
+
* const data = await getResults();
|
|
1110
|
+
* return envelope(data);
|
|
1111
|
+
* // → { success: true, data }
|
|
1112
|
+
* }
|
|
1113
|
+
* ```
|
|
1114
|
+
*/
|
|
1115
|
+
declare function envelope<T>(data: T, meta?: Record<string, unknown>): {
|
|
1116
|
+
success: true;
|
|
1117
|
+
data: T;
|
|
1118
|
+
[key: string]: unknown;
|
|
1119
|
+
};
|
|
1076
1120
|
type AnyRecord = Record<string, unknown>;
|
|
1077
1121
|
/** MongoDB ObjectId — accepts string or any object with a `toString()` (e.g. mongoose ObjectId). */
|
|
1078
1122
|
type ObjectId = string | {
|
|
@@ -1188,8 +1232,8 @@ interface LookupOption {
|
|
|
1188
1232
|
as?: string;
|
|
1189
1233
|
/** Return a single object instead of array (default: false) */
|
|
1190
1234
|
single?: boolean;
|
|
1191
|
-
/** Field selection on the joined collection (comma-separated) */
|
|
1192
|
-
select?: string
|
|
1235
|
+
/** Field selection on the joined collection (comma-separated string or projection object) */
|
|
1236
|
+
select?: string | Record<string, 0 | 1>;
|
|
1193
1237
|
}
|
|
1194
1238
|
/**
|
|
1195
1239
|
* Mongoose-compatible populate option for advanced field selection
|
|
@@ -1412,6 +1456,18 @@ interface ResourceConfig<TDoc = AnyRecord> {
|
|
|
1412
1456
|
displayName?: string;
|
|
1413
1457
|
tag?: string;
|
|
1414
1458
|
prefix?: string;
|
|
1459
|
+
/**
|
|
1460
|
+
* Skip the global `resourcePrefix` from `createApp()`.
|
|
1461
|
+
* The resource registers at its own `prefix` (or `/${name}s`) directly on root.
|
|
1462
|
+
* Useful for webhooks, health, admin routes that shouldn't be under `/api/v1`.
|
|
1463
|
+
*
|
|
1464
|
+
* @example
|
|
1465
|
+
* ```typescript
|
|
1466
|
+
* defineResource({ name: 'webhook', prefix: '/webhooks', skipGlobalPrefix: true })
|
|
1467
|
+
* // Registers at /webhooks even when createApp({ resourcePrefix: '/api/v1' })
|
|
1468
|
+
* ```
|
|
1469
|
+
*/
|
|
1470
|
+
skipGlobalPrefix?: boolean;
|
|
1415
1471
|
adapter?: DataAdapter<TDoc>;
|
|
1416
1472
|
/** Controller instance - accepts any object with CRUD methods */
|
|
1417
1473
|
controller?: IController<TDoc> | ControllerLike;
|
|
@@ -1475,6 +1531,22 @@ interface ResourceConfig<TDoc = AnyRecord> {
|
|
|
1475
1531
|
skipValidation?: boolean;
|
|
1476
1532
|
skipRegistry?: boolean;
|
|
1477
1533
|
_appliedPresets?: string[];
|
|
1534
|
+
/**
|
|
1535
|
+
* Called during plugin registration with the scoped Fastify instance.
|
|
1536
|
+
* Use for wiring singletons, reading decorators, or setting up resource-specific
|
|
1537
|
+
* services that need access to the Fastify instance.
|
|
1538
|
+
*
|
|
1539
|
+
* @example
|
|
1540
|
+
* ```typescript
|
|
1541
|
+
* defineResource({
|
|
1542
|
+
* name: 'notification',
|
|
1543
|
+
* onRegister: (fastify) => {
|
|
1544
|
+
* setSseManager(fastify.sseManager);
|
|
1545
|
+
* },
|
|
1546
|
+
* })
|
|
1547
|
+
* ```
|
|
1548
|
+
*/
|
|
1549
|
+
onRegister?: (fastify: FastifyInstance) => void | Promise<void>;
|
|
1478
1550
|
/** HTTP method for update routes. Default: 'PATCH' */
|
|
1479
1551
|
updateMethod?: 'PUT' | 'PATCH' | 'both';
|
|
1480
1552
|
/**
|
|
@@ -1489,6 +1561,34 @@ interface ResourceConfig<TDoc = AnyRecord> {
|
|
|
1489
1561
|
* Requires `queryCachePlugin` to be registered.
|
|
1490
1562
|
*/
|
|
1491
1563
|
cache?: ResourceCacheConfig;
|
|
1564
|
+
/**
|
|
1565
|
+
* Per-resource audit opt-in. When `auditPlugin` is registered with
|
|
1566
|
+
* `autoAudit: { perResource: true }`, only resources with this flag are audited.
|
|
1567
|
+
*
|
|
1568
|
+
* The cleanest pattern for apps where most resources don't need auditing —
|
|
1569
|
+
* no growing exclude lists, no centralized allowlist to maintain.
|
|
1570
|
+
*
|
|
1571
|
+
* - `true`: Audit create/update/delete on this resource
|
|
1572
|
+
* - `{ operations: ['delete'] }`: Audit only specific operations
|
|
1573
|
+
* - `false` or omit: Not audited (default)
|
|
1574
|
+
*
|
|
1575
|
+
* @example
|
|
1576
|
+
* ```ts
|
|
1577
|
+
* // app.ts
|
|
1578
|
+
* await fastify.register(auditPlugin, {
|
|
1579
|
+
* autoAudit: { perResource: true },
|
|
1580
|
+
* });
|
|
1581
|
+
*
|
|
1582
|
+
* // order.resource.ts
|
|
1583
|
+
* defineResource({ name: 'order', audit: true });
|
|
1584
|
+
*
|
|
1585
|
+
* // payment.resource.ts
|
|
1586
|
+
* defineResource({ name: 'payment', audit: { operations: ['delete'] } });
|
|
1587
|
+
* ```
|
|
1588
|
+
*/
|
|
1589
|
+
audit?: boolean | {
|
|
1590
|
+
operations?: ("create" | "update" | "delete")[];
|
|
1591
|
+
};
|
|
1492
1592
|
}
|
|
1493
1593
|
/**
|
|
1494
1594
|
* Resource-level permissions
|
|
@@ -1501,13 +1601,53 @@ interface ResourcePermissions {
|
|
|
1501
1601
|
update?: PermissionCheck;
|
|
1502
1602
|
delete?: PermissionCheck;
|
|
1503
1603
|
}
|
|
1604
|
+
/**
|
|
1605
|
+
* Hook context passed to resource-level hook handlers.
|
|
1606
|
+
* Mirrors HookSystem's HookContext but with a simpler API for inline use.
|
|
1607
|
+
*/
|
|
1608
|
+
interface ResourceHookContext {
|
|
1609
|
+
/** The document data (create/update body, or existing doc for delete) */
|
|
1610
|
+
data: AnyRecord;
|
|
1611
|
+
/** Authenticated user or null */
|
|
1612
|
+
user?: UserBase;
|
|
1613
|
+
/** Additional metadata (e.g. `{ id, existing }` for update/delete) */
|
|
1614
|
+
meta?: AnyRecord;
|
|
1615
|
+
}
|
|
1616
|
+
/**
|
|
1617
|
+
* Inline lifecycle hooks on a resource definition.
|
|
1618
|
+
* These are wired into the HookSystem automatically — same pipeline as presets and app-level hooks.
|
|
1619
|
+
*
|
|
1620
|
+
* @example
|
|
1621
|
+
* ```typescript
|
|
1622
|
+
* defineResource({
|
|
1623
|
+
* name: 'chat',
|
|
1624
|
+
* hooks: {
|
|
1625
|
+
* afterCreate: async (ctx) => {
|
|
1626
|
+
* analytics.track('chat.created', { chatId: ctx.data._id, userId: ctx.user?.id });
|
|
1627
|
+
* },
|
|
1628
|
+
* beforeDelete: async (ctx) => {
|
|
1629
|
+
* if (ctx.data.isProtected) throw new Error('Cannot delete protected chat');
|
|
1630
|
+
* },
|
|
1631
|
+
* afterDelete: async (ctx) => {
|
|
1632
|
+
* await notificationService.send('chat.deleted', { id: ctx.meta?.id });
|
|
1633
|
+
* },
|
|
1634
|
+
* },
|
|
1635
|
+
* });
|
|
1636
|
+
* ```
|
|
1637
|
+
*/
|
|
1504
1638
|
interface ResourceHooks {
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1639
|
+
/** Runs before create — can modify data by returning a new object */
|
|
1640
|
+
beforeCreate?: (ctx: ResourceHookContext) => Promise<AnyRecord | void> | AnyRecord | void;
|
|
1641
|
+
/** Runs after create — receives the created document */
|
|
1642
|
+
afterCreate?: (ctx: ResourceHookContext) => Promise<void> | void;
|
|
1643
|
+
/** Runs before update — ctx.meta.id has the resource ID, ctx.meta.existing has the current doc */
|
|
1644
|
+
beforeUpdate?: (ctx: ResourceHookContext) => Promise<AnyRecord | void> | AnyRecord | void;
|
|
1645
|
+
/** Runs after update — receives the updated document */
|
|
1646
|
+
afterUpdate?: (ctx: ResourceHookContext) => Promise<void> | void;
|
|
1647
|
+
/** Runs before delete — ctx.data is the existing doc, ctx.meta.id has the resource ID */
|
|
1648
|
+
beforeDelete?: (ctx: ResourceHookContext) => Promise<void> | void;
|
|
1649
|
+
/** Runs after delete — ctx.data is the deleted doc, ctx.meta.id has the resource ID */
|
|
1650
|
+
afterDelete?: (ctx: ResourceHookContext) => Promise<void> | void;
|
|
1511
1651
|
}
|
|
1512
1652
|
/**
|
|
1513
1653
|
* Additional route definition for custom endpoints
|
|
@@ -1518,10 +1658,16 @@ interface AdditionalRoute {
|
|
|
1518
1658
|
/** Route path (relative to resource prefix) */
|
|
1519
1659
|
path: string;
|
|
1520
1660
|
/**
|
|
1521
|
-
* Handler - string (controller method name) or function
|
|
1522
|
-
*
|
|
1661
|
+
* Handler - string (controller method name) or function.
|
|
1662
|
+
*
|
|
1663
|
+
* When `wrapHandler: true`:
|
|
1664
|
+
* - `string` — calls controller method by name (e.g., `'approve'`)
|
|
1665
|
+
* - `ControllerHandler` — receives `IRequestContext`, returns `IControllerResponse`
|
|
1666
|
+
*
|
|
1667
|
+
* When `wrapHandler: false`:
|
|
1668
|
+
* - Fastify handler `(request, reply) => unknown`
|
|
1523
1669
|
*/
|
|
1524
|
-
handler: string | RouteHandlerMethod | ((request: FastifyRequest<any>, reply: FastifyReply) => unknown);
|
|
1670
|
+
handler: string | ControllerHandler | RouteHandlerMethod | ((request: FastifyRequest<any>, reply: FastifyReply) => unknown);
|
|
1525
1671
|
/** Permission check - REQUIRED */
|
|
1526
1672
|
permissions: PermissionCheck;
|
|
1527
1673
|
/**
|
|
@@ -1556,6 +1702,41 @@ interface AdditionalRoute {
|
|
|
1556
1702
|
* preHandler: (fastify) => [fastify.customerContext({ required: true })]
|
|
1557
1703
|
*/
|
|
1558
1704
|
preHandler?: RouteHandlerMethod[] | ((fastify: FastifyInstance) => RouteHandlerMethod[]);
|
|
1705
|
+
/**
|
|
1706
|
+
* Pre-auth handlers — run BEFORE authentication middleware.
|
|
1707
|
+
* Use for promoting query params to headers (e.g., EventSource ?token= → Authorization).
|
|
1708
|
+
*
|
|
1709
|
+
* @example
|
|
1710
|
+
* ```typescript
|
|
1711
|
+
* preAuth: [(req) => {
|
|
1712
|
+
* const token = (req.query as Record<string, string>)?.token;
|
|
1713
|
+
* if (token) req.headers.authorization = `Bearer ${token}`;
|
|
1714
|
+
* }]
|
|
1715
|
+
* ```
|
|
1716
|
+
*/
|
|
1717
|
+
preAuth?: RouteHandlerMethod[];
|
|
1718
|
+
/**
|
|
1719
|
+
* Streaming response mode — designed for SSE and AI streaming routes.
|
|
1720
|
+
* When `true`:
|
|
1721
|
+
* - Forces `wrapHandler: false` (no `{ success, data }` wrapper)
|
|
1722
|
+
* - Sets SSE headers: `Content-Type: text/event-stream`, `Cache-Control: no-cache`, `Connection: keep-alive`
|
|
1723
|
+
* - `request.signal` (Fastify 5 built-in) is available for abort-on-disconnect
|
|
1724
|
+
*
|
|
1725
|
+
* @example
|
|
1726
|
+
* ```typescript
|
|
1727
|
+
* {
|
|
1728
|
+
* method: 'POST',
|
|
1729
|
+
* path: '/stream',
|
|
1730
|
+
* streamResponse: true,
|
|
1731
|
+
* permissions: requireAuth(),
|
|
1732
|
+
* handler: async (request, reply) => {
|
|
1733
|
+
* const { stream } = await generateStream({ abortSignal: request.signal });
|
|
1734
|
+
* return reply.send(stream);
|
|
1735
|
+
* },
|
|
1736
|
+
* }
|
|
1737
|
+
* ```
|
|
1738
|
+
*/
|
|
1739
|
+
streamResponse?: boolean;
|
|
1559
1740
|
/** Fastify route schema */
|
|
1560
1741
|
schema?: Record<string, unknown>;
|
|
1561
1742
|
/**
|
|
@@ -2064,6 +2245,10 @@ interface RegistryEntry extends ResourceMetadata {
|
|
|
2064
2245
|
disabledRoutes?: string[];
|
|
2065
2246
|
/** Rate limit config */
|
|
2066
2247
|
rateLimit?: RateLimitConfig | false;
|
|
2248
|
+
/** Per-resource audit opt-in flag (read by auditPlugin perResource mode) */
|
|
2249
|
+
audit?: boolean | {
|
|
2250
|
+
operations?: ("create" | "update" | "delete")[];
|
|
2251
|
+
};
|
|
2067
2252
|
}
|
|
2068
2253
|
interface RegistryStats {
|
|
2069
2254
|
total?: number;
|
|
@@ -2126,12 +2311,43 @@ type TypedRepository<TDoc> = CrudRepository<TDoc>;
|
|
|
2126
2311
|
*
|
|
2127
2312
|
* CrudRepository<TDoc> and MongoKit Repository both satisfy this interface.
|
|
2128
2313
|
*/
|
|
2314
|
+
/**
|
|
2315
|
+
* Minimal repository interface for flexible adapter compatibility.
|
|
2316
|
+
* Any repository with these method signatures is accepted.
|
|
2317
|
+
*
|
|
2318
|
+
* **Required** — core CRUD (every resource needs these):
|
|
2319
|
+
* getAll, getById, create, update, delete
|
|
2320
|
+
*
|
|
2321
|
+
* **Recommended** — used by AccessControl for compound queries:
|
|
2322
|
+
* getOne
|
|
2323
|
+
*
|
|
2324
|
+
* **Optional** — enabled by presets, checked at runtime:
|
|
2325
|
+
* getBySlug — slugLookup preset
|
|
2326
|
+
* getDeleted — softDelete preset (list soft-deleted)
|
|
2327
|
+
* restore — softDelete preset (restore soft-deleted)
|
|
2328
|
+
* getTree — tree preset (hierarchical queries)
|
|
2329
|
+
* getChildren — tree preset (child nodes)
|
|
2330
|
+
* createMany — bulk preset (batch create)
|
|
2331
|
+
* updateMany — bulk preset (batch update by filter)
|
|
2332
|
+
* deleteMany — bulk preset (batch delete by filter)
|
|
2333
|
+
*/
|
|
2129
2334
|
interface RepositoryLike {
|
|
2130
2335
|
getAll(params?: unknown): Promise<unknown>;
|
|
2131
2336
|
getById(id: string, options?: unknown): Promise<unknown>;
|
|
2132
2337
|
create(data: unknown, options?: unknown): Promise<unknown>;
|
|
2133
2338
|
update(id: string, data: unknown, options?: unknown): Promise<unknown>;
|
|
2134
2339
|
delete(id: string, options?: unknown): Promise<unknown>;
|
|
2340
|
+
/** Find single doc by compound filter — used by AccessControl for idField + org/policy scoping.
|
|
2341
|
+
* Without this, Arc falls back to getById + post-fetch security checks. */
|
|
2342
|
+
getOne?(filter: Record<string, unknown>, options?: unknown): Promise<unknown>;
|
|
2343
|
+
getBySlug?(slug: string, options?: unknown): Promise<unknown>;
|
|
2344
|
+
getDeleted?(options?: unknown): Promise<unknown>;
|
|
2345
|
+
restore?(id: string): Promise<unknown>;
|
|
2346
|
+
getTree?(options?: unknown): Promise<unknown>;
|
|
2347
|
+
getChildren?(parentId: string, options?: unknown): Promise<unknown>;
|
|
2348
|
+
createMany?(items: unknown[], options?: unknown): Promise<unknown>;
|
|
2349
|
+
updateMany?(filter: Record<string, unknown>, data: unknown): Promise<unknown>;
|
|
2350
|
+
deleteMany?(filter: Record<string, unknown>): Promise<unknown>;
|
|
2135
2351
|
[key: string]: unknown;
|
|
2136
2352
|
}
|
|
2137
2353
|
interface DataAdapter<TDoc = unknown> {
|
|
@@ -2210,4 +2426,4 @@ interface ValidationResult {
|
|
|
2210
2426
|
}
|
|
2211
2427
|
type AdapterFactory<TDoc> = (config: unknown) => DataAdapter<TDoc>;
|
|
2212
2428
|
//#endregion
|
|
2213
|
-
export {
|
|
2429
|
+
export { RegistryEntry as $, PipelineStep as $t, GracefulShutdownOptions as A, AccessControlConfig as At, LookupOption as B, ResourceDefinition as Bt, CrudSchemas as C, BaseController as Ct, FastifyWithAuth as D, BodySanitizer as Dt, FastifyRequestExtras as E, QueryResolverConfig as Et, InferResourceDoc as F, IControllerResponse as Ft, OwnershipCheck as G, PaginationParams as Gt, MiddlewareHandler as H, CrudRepository as Ht, IntrospectionData as I, IRequestContext as It, PresetFunction as J, Interceptor as Jt, ParsedQuery as K, QueryOptions as Kt, IntrospectionPluginOptions as L, RouteHandler as Lt, HealthOptions as M, ControllerLike as Mt, InferAdapterDoc as N, FastifyHandler as Nt, FastifyWithDecorators as O, BodySanitizerConfig as Ot, InferDocType as P, IController as Pt, RateLimitConfig as Q, PipelineContext as Qt, JWTPayload as R, RegisterOptions as Rt, CrudRouterOptions as S, getUserId as St, EventsDecorator as T, QueryResolver as Tt, ObjectId as U, InferDoc as Ut, MiddlewareConfig as V, defineResource as Vt, OpenApiSchemas as W, PaginatedResult as Wt, PresetResult as X, OperationFilter as Xt, PresetHook as Y, NextFunction as Yt, QueryParserInterface as Z, PipelineConfig as Zt, AuthenticatorContext as _, UserLike as _t, RepositoryLike as a, HookPhase as an, ResourceConfig as at, CrudController as b, ValidationResult$1 as bt, AdditionalRoute as c, HookSystemOptions as cn, ResourceMetadata as ct, ArcDecorator as d, afterUpdate as dn, RouteSchemaOptions as dt, Transform as en, RegistryStats as et, ArcInternalMetadata as f, beforeCreate as fn, ServiceContext as ft, Authenticator as g, defineHook as gn, TypedResourceConfig as gt, AuthPluginOptions as h, createHookSystem as hn, TypedRepository as ht, RelationMetadata as i, HookOperation as in, ResourceCacheConfig as it, HealthCheck as j, ControllerHandler as jt, FieldRule as k, AccessControl as kt, AnyRecord as l, afterCreate as ln, ResourcePermissions as lt, AuthHelpers as m, beforeUpdate as mn, TypedController as mt, DataAdapter as n, HookContext as nn, RequestIdOptions as nt, SchemaMetadata as o, HookRegistration as on, ResourceHookContext as ot, ArcRequest as p, beforeDelete as pn, TokenPair as pt, PopulateOption as q, Guard as qt, FieldMetadata as r, HookHandler as rn, RequestWithExtras as rt, ValidationResult as s, HookSystem as sn, ResourceHooks as st, AdapterFactory as t, DefineHookOptions as tn, RequestContext as tt, ApiResponse as u, afterDelete as un, RouteHandlerMethod$1 as ut, ConfigError as v, UserOrganization as vt, EventDefinition as w, BaseControllerOptions as wt, CrudRouteKey as x, envelope as xt, ControllerQueryOptions as y, ValidateOptions as yt, JwtContext as z, ResourceRegistry as zt };
|
|
@@ -89,6 +89,16 @@ interface MongoAuditStoreOptions {
|
|
|
89
89
|
/** TTL in days (default: 90, 0 = no expiry) */
|
|
90
90
|
ttlDays?: number;
|
|
91
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Minimal MongoDB connection interface — DB-agnostic.
|
|
94
|
+
*
|
|
95
|
+
* Accepts:
|
|
96
|
+
* - Native MongoDB `Db` instance (has `.collection()`)
|
|
97
|
+
* - Mongoose `connection.db` (has `.collection()`)
|
|
98
|
+
* - Any object with `.collection(name)` method
|
|
99
|
+
*
|
|
100
|
+
* For Mongoose users: pass `mongoose.connection.db`, not `mongoose.connection`.
|
|
101
|
+
*/
|
|
92
102
|
interface MongoConnection {
|
|
93
103
|
collection: (name: string) => MongoCollection;
|
|
94
104
|
}
|
package/dist/org/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Lt as RouteHandler } from "../interface-CrN45qz1.mjs";
|
|
2
2
|
import { i as UserBase } from "../types-BNUccdcf.mjs";
|
|
3
3
|
import { InvitationAdapter, InvitationDoc, MemberDoc, OrgAdapter, OrgDoc, OrgPermissionStatement, OrgRole, OrganizationPluginOptions } from "./types.mjs";
|
|
4
4
|
import { FastifyPluginAsync, RouteHandlerMethod } from "fastify";
|
package/dist/org/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as getOrgRoles, d as isElevated, f as isMember, l as hasOrgAccess, n as PUBLIC_SCOPE } from "../types-BhtYdxZU.mjs";
|
|
2
2
|
import fp from "fastify-plugin";
|
|
3
3
|
//#region src/org/organizationPlugin.ts
|
|
4
4
|
const DEFAULT_ROLES = [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, r as FieldPermissionType, s as resolveEffectiveRoles, t as FieldPermission } from "../fields-DFwdaWCq.mjs";
|
|
2
2
|
import { a as getUserRoles, i as UserBase, n as PermissionContext, o as normalizeRoles, r as PermissionResult, t as PermissionCheck } from "../types-BNUccdcf.mjs";
|
|
3
|
-
import { C as
|
|
4
|
-
export { ConnectEventsOptions, DynamicPermissionMatrix, DynamicPermissionMatrixConfig, FieldPermission, FieldPermissionMap, FieldPermissionType, PermissionCheck, PermissionContext, PermissionEventBus, PermissionResult, RoleHierarchy, UserBase, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, denyAll, fields, fullPublic, getUserRoles, normalizeRoles, ownerWithAdminBypass, presets_d_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireTeamMembership, resolveEffectiveRoles, when };
|
|
3
|
+
import { C as presets_d_exports, D as RoleHierarchy, E as readOnly, O as createRoleHierarchy, S as ownerWithAdminBypass, T as publicReadAdminWrite, _ as roles, a as allOf, b as authenticated, c as createDynamicPermissionMatrix, d as requireAuth, f as requireOrgMembership, g as requireTeamMembership, h as requireRoles, i as PermissionEventBus, l as createOrgPermissions, m as requireOwnership, n as DynamicPermissionMatrix, o as allowPublic, p as requireOrgRole, r as DynamicPermissionMatrixConfig, s as anyOf, t as ConnectEventsOptions, u as denyAll, v as when, w as publicRead, x as fullPublic, y as adminOnly } from "../index-NGZksqM5.mjs";
|
|
4
|
+
export { ConnectEventsOptions, DynamicPermissionMatrix, DynamicPermissionMatrixConfig, FieldPermission, FieldPermissionMap, FieldPermissionType, PermissionCheck, PermissionContext, PermissionEventBus, PermissionResult, RoleHierarchy, UserBase, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, denyAll, fields, fullPublic, getUserRoles, normalizeRoles, ownerWithAdminBypass, presets_d_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireTeamMembership, resolveEffectiveRoles, roles, when };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { i as resolveEffectiveRoles, n as applyFieldWritePermissions, r as fields, t as applyFieldReadPermissions } from "../fields-ipsbIRPK.mjs";
|
|
2
2
|
import { n as normalizeRoles, t as getUserRoles } from "../types-ZUu_h0jp.mjs";
|
|
3
|
-
import {
|
|
4
|
-
export { adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, denyAll, fields, fullPublic, getUserRoles, normalizeRoles, ownerWithAdminBypass, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireTeamMembership, resolveEffectiveRoles, when };
|
|
3
|
+
import { C as createRoleHierarchy, S as readOnly, _ as fullPublic, a as createOrgPermissions, b as publicRead, c as requireOrgMembership, d as requireRoles, f as requireTeamMembership, g as authenticated, h as adminOnly, i as createDynamicPermissionMatrix, l as requireOrgRole, m as when, n as allowPublic, o as denyAll, p as roles, r as anyOf, s as requireAuth, t as allOf, u as requireOwnership, v as ownerWithAdminBypass, x as publicReadAdminWrite, y as presets_exports } from "../permissions-C8ImI8gC.mjs";
|
|
4
|
+
export { adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, denyAll, fields, fullPublic, getUserRoles, normalizeRoles, ownerWithAdminBypass, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireTeamMembership, resolveEffectiveRoles, roles, when };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { d as isElevated, f as isMember, n as PUBLIC_SCOPE, o as getTeamId, s as getUserId } from "./types-BhtYdxZU.mjs";
|
|
3
3
|
import { t as getUserRoles } from "./types-ZUu_h0jp.mjs";
|
|
4
4
|
import { t as MemoryCacheStore } from "./memory-BFAYkf8H.mjs";
|
|
5
5
|
import { randomUUID } from "node:crypto";
|
|
@@ -244,6 +244,10 @@ function requireRoles(roles, options) {
|
|
|
244
244
|
const userRoles = getUserRoles(ctx.user);
|
|
245
245
|
if (options?.bypassRoles?.some((r) => userRoles.includes(r))) return true;
|
|
246
246
|
if (roles.some((r) => userRoles.includes(r))) return true;
|
|
247
|
+
if (options?.includeOrgRoles) {
|
|
248
|
+
const scope = getScope(ctx.request);
|
|
249
|
+
if (isMember(scope) && roles.some((r) => scope.orgRoles.includes(r))) return true;
|
|
250
|
+
}
|
|
247
251
|
return {
|
|
248
252
|
granted: false,
|
|
249
253
|
reason: `Required roles: ${roles.join(", ")}`
|
|
@@ -253,6 +257,44 @@ function requireRoles(roles, options) {
|
|
|
253
257
|
return check;
|
|
254
258
|
}
|
|
255
259
|
/**
|
|
260
|
+
* Unified role check — checks both platform roles AND org roles.
|
|
261
|
+
*
|
|
262
|
+
* This is the recommended helper for Better Auth organization plugin users.
|
|
263
|
+
* It checks `user.role` (platform) first, then `scope.orgRoles` (org membership).
|
|
264
|
+
* Elevated scope always passes.
|
|
265
|
+
*
|
|
266
|
+
* For platform-only checks: use `requireRoles(['admin'])`
|
|
267
|
+
* For org-only checks: use `requireOrgRole('admin')`
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```typescript
|
|
271
|
+
* permissions: {
|
|
272
|
+
* create: roles('admin', 'editor'), // passes if user has role at either level
|
|
273
|
+
* delete: roles('admin'),
|
|
274
|
+
* }
|
|
275
|
+
* ```
|
|
276
|
+
*/
|
|
277
|
+
function roles(...args) {
|
|
278
|
+
const roleList = Array.isArray(args[0]) ? args[0] : args;
|
|
279
|
+
const check = (ctx) => {
|
|
280
|
+
if (!ctx.user) return {
|
|
281
|
+
granted: false,
|
|
282
|
+
reason: "Authentication required"
|
|
283
|
+
};
|
|
284
|
+
const userRoles = getUserRoles(ctx.user);
|
|
285
|
+
if (roleList.some((r) => userRoles.includes(r))) return true;
|
|
286
|
+
const scope = getScope(ctx.request);
|
|
287
|
+
if (isElevated(scope)) return true;
|
|
288
|
+
if (isMember(scope) && roleList.some((r) => scope.orgRoles.includes(r))) return true;
|
|
289
|
+
return {
|
|
290
|
+
granted: false,
|
|
291
|
+
reason: `Required roles: ${roleList.join(", ")}`
|
|
292
|
+
};
|
|
293
|
+
};
|
|
294
|
+
check._roles = roleList;
|
|
295
|
+
return check;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
256
298
|
* Require resource ownership
|
|
257
299
|
*
|
|
258
300
|
* Returns filters to scope queries to user's owned resources.
|
|
@@ -748,4 +790,4 @@ function requireTeamMembership() {
|
|
|
748
790
|
return check;
|
|
749
791
|
}
|
|
750
792
|
//#endregion
|
|
751
|
-
export { createRoleHierarchy as S,
|
|
793
|
+
export { createRoleHierarchy as C, readOnly as S, fullPublic as _, createOrgPermissions as a, publicRead as b, requireOrgMembership as c, requireRoles as d, requireTeamMembership as f, authenticated as g, adminOnly as h, createDynamicPermissionMatrix as i, requireOrgRole as l, when as m, allowPublic as n, denyAll as o, roles as p, anyOf as r, requireAuth as s, allOf as t, requireOwnership as u, ownerWithAdminBypass as v, publicReadAdminWrite as x, presets_exports as y };
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { V as MiddlewareConfig, Y as PresetHook, c as AdditionalRoute, dt as RouteSchemaOptions, l as AnyRecord, sn as HookSystem, zt as ResourceRegistry } from "../interface-CrN45qz1.mjs";
|
|
2
2
|
import { t as ExternalOpenApiPaths } from "../externalPaths-DpO-s7r8.mjs";
|
|
3
3
|
import { _ as cachingPlugin, a as versioningPlugin, c as MetricsOptions, d as SSEOptions, f as _default$6, g as _default$1, h as CachingRule, i as _default$7, l as _default$4, m as CachingOptions, n as errorHandlerPlugin, o as MetricEntry, p as ssePlugin, r as VersioningOptions, s as MetricsCollector, t as ErrorHandlerOptions, u as metricsPlugin } from "../errorHandler-Do4vVQ1f.mjs";
|
|
4
4
|
import { t as TracingOptions } from "../tracing-bz_U4EM1.mjs";
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { p as MUTATION_OPERATIONS } from "../constants-Cxde4rpC.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { i as getOrgId } from "../types-BhtYdxZU.mjs";
|
|
3
3
|
import { t as requestContext } from "../requestContext-DYtmNpm5.mjs";
|
|
4
4
|
import { t as hasEvents } from "../typeGuards-Cj5Rgvlg.mjs";
|
|
5
5
|
import { t as HookSystem } from "../HookSystem-COkyWztM.mjs";
|
|
6
|
-
import { t as ResourceRegistry } from "../ResourceRegistry-
|
|
6
|
+
import { t as ResourceRegistry } from "../ResourceRegistry-C6ngvOnn.mjs";
|
|
7
7
|
import { n as caching_default, t as cachingPlugin } from "../caching-BSXB-Xr7.mjs";
|
|
8
|
-
import { t as errorHandlerPlugin } from "../errorHandler-
|
|
8
|
+
import { t as errorHandlerPlugin } from "../errorHandler-r2595m8T.mjs";
|
|
9
9
|
import { n as metrics_default, t as metricsPlugin } from "../metrics-Csh4nsvv.mjs";
|
|
10
|
-
import { n as sse_default, t as ssePlugin } from "../sse-
|
|
10
|
+
import { n as sse_default, t as ssePlugin } from "../sse-BF7GR7IB.mjs";
|
|
11
11
|
import { n as versioning_default, t as versioningPlugin } from "../versioning-BzfeHmhj.mjs";
|
|
12
12
|
import { randomUUID } from "node:crypto";
|
|
13
13
|
import fp from "fastify-plugin";
|
|
@@ -44,7 +44,7 @@ try {
|
|
|
44
44
|
function createTracerProvider(options) {
|
|
45
45
|
if (!isAvailable) return null;
|
|
46
46
|
const { serviceName = "@classytic/arc", serviceVersion, exporterUrl = "http://localhost:4318/v1/traces" } = options;
|
|
47
|
-
const resolvedVersion = serviceVersion ?? "2.
|
|
47
|
+
const resolvedVersion = serviceVersion ?? "2.6.2";
|
|
48
48
|
const exporter = new OTLPTraceExporter({ url: exporterUrl });
|
|
49
49
|
const provider = new NodeTracerProvider({ resource: { attributes: {
|
|
50
50
|
"service.name": serviceName,
|
package/dist/presets/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ft as IControllerResponse, It as IRequestContext, Wt as PaginatedResult, X as PresetResult, at as ResourceConfig, l as AnyRecord } from "../interface-CrN45qz1.mjs";
|
|
2
2
|
import { MultiTenantOptions, multiTenantPreset } from "./multiTenant.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/presets/ownedByUser.d.ts
|
package/dist/presets/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { multiTenantPreset } from "./multiTenant.mjs";
|
|
2
|
-
import { a as registerPreset, c as auditedPreset, d as ownedByUserPreset, i as getPreset, l as softDeletePreset, n as flexibleMultiTenantPreset, o as treePreset, r as getAvailablePresets, s as bulkPreset, t as applyPresets, u as slugLookupPreset } from "../presets-
|
|
2
|
+
import { a as registerPreset, c as auditedPreset, d as ownedByUserPreset, i as getPreset, l as softDeletePreset, n as flexibleMultiTenantPreset, o as treePreset, r as getAvailablePresets, s as bulkPreset, t as applyPresets, u as slugLookupPreset } from "../presets-BMfdy34e.mjs";
|
|
3
3
|
export { applyPresets, auditedPreset, bulkPreset, flexibleMultiTenantPreset, getAvailablePresets, getPreset, multiTenantPreset, ownedByUserPreset, registerPreset, slugLookupPreset, softDeletePreset, treePreset };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { o as DEFAULT_TENANT_FIELD } from "../constants-Cxde4rpC.mjs";
|
|
2
|
-
import { d as
|
|
2
|
+
import { d as isElevated, f as isMember, i as getOrgId, n as PUBLIC_SCOPE } from "../types-BhtYdxZU.mjs";
|
|
3
3
|
//#region src/presets/multiTenant.ts
|
|
4
4
|
/** Read request.scope safely */
|
|
5
5
|
function getScope(request) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { d as isElevated, n as PUBLIC_SCOPE } from "./types-BhtYdxZU.mjs";
|
|
2
2
|
import { multiTenantPreset } from "./presets/multiTenant.mjs";
|
|
3
|
-
import { d as requireRoles, n as allowPublic, s as requireAuth } from "./permissions-
|
|
3
|
+
import { d as requireRoles, n as allowPublic, s as requireAuth } from "./permissions-C8ImI8gC.mjs";
|
|
4
4
|
//#region src/presets/ownedByUser.ts
|
|
5
5
|
/**
|
|
6
6
|
* Create ownership check middleware.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { L as IntrospectionPluginOptions, Rt as RegisterOptions, zt as ResourceRegistry } from "../interface-CrN45qz1.mjs";
|
|
2
2
|
import { FastifyPluginAsync } from "fastify";
|
|
3
3
|
|
|
4
4
|
//#region src/registry/introspectionPlugin.d.ts
|
package/dist/registry/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { n as introspectionPlugin_default, t as introspectionPlugin } from "../registry-I-ogLgL9.mjs";
|
|
2
|
-
import { t as ResourceRegistry } from "../ResourceRegistry-
|
|
2
|
+
import { t as ResourceRegistry } from "../ResourceRegistry-C6ngvOnn.mjs";
|
|
3
3
|
export { ResourceRegistry, introspectionPlugin_default as introspectionPlugin, introspectionPlugin as introspectionPluginFn };
|