@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
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { a as QueryCacheConfig } from "./QueryCache-
|
|
2
|
-
import { i as RequestScope } from "./types-
|
|
3
|
-
import { c as PermissionCheck, d as UserBase, n as FieldPermissionMap } from "./fields-
|
|
4
|
-
import { n as DomainEvent } from "./EventTransport-
|
|
1
|
+
import { a as QueryCacheConfig } from "./QueryCache-8YmAQ-zW.mjs";
|
|
2
|
+
import { i as RequestScope } from "./types-CfapW2t8.mjs";
|
|
3
|
+
import { c as PermissionCheck, d as UserBase, n as FieldPermissionMap } from "./fields-DqZLp5d6.mjs";
|
|
4
|
+
import { n as DomainEvent } from "./EventTransport-B1GFiYUy.mjs";
|
|
5
5
|
import { KeysetPaginationResult, OffsetPaginationResult } from "@classytic/repo-core/pagination";
|
|
6
6
|
import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest, RouteHandlerMethod, RouteHandlerMethod as RouteHandlerMethod$1 } from "fastify";
|
|
7
7
|
import * as _$_classytic_repo_core_adapter0 from "@classytic/repo-core/adapter";
|
|
8
8
|
import { DataAdapter, RepositoryLike } from "@classytic/repo-core/adapter";
|
|
9
|
-
import { AggDateBucket, AggMeasure, AggTopN, QueryOptions, StandardRepo } from "@classytic/repo-core/repository";
|
|
9
|
+
import { AggDateBucket, AggMeasure, AggTopN, QueryOptions, StandardRepo, TenantPurgeStrategy } from "@classytic/repo-core/repository";
|
|
10
10
|
import { LookupSpec } from "@classytic/repo-core/lookup";
|
|
11
11
|
import { FieldRule, SchemaBuilderOptions } from "@classytic/repo-core/schema";
|
|
12
12
|
|
|
@@ -453,11 +453,11 @@ type CacheStatus = "HIT" | "STALE" | "MISS";
|
|
|
453
453
|
* `BaseCrudController` / `BaseController` declarations.
|
|
454
454
|
*/
|
|
455
455
|
type ArcControllerLike = {
|
|
456
|
-
list: (...args:
|
|
457
|
-
get: (...args:
|
|
458
|
-
create: (...args:
|
|
459
|
-
update: (...args:
|
|
460
|
-
delete: (...args:
|
|
456
|
+
list: (...args: never[]) => unknown;
|
|
457
|
+
get: (...args: never[]) => unknown;
|
|
458
|
+
create: (...args: never[]) => unknown;
|
|
459
|
+
update: (...args: never[]) => unknown;
|
|
460
|
+
delete: (...args: never[]) => unknown;
|
|
461
461
|
};
|
|
462
462
|
/**
|
|
463
463
|
* Return type of the controller's `list` method.
|
|
@@ -1569,8 +1569,39 @@ interface AggregationConfig {
|
|
|
1569
1569
|
having?: AnyRecord;
|
|
1570
1570
|
/** Order grouped rows by groupBy field, measure alias, or joined-alias path. */
|
|
1571
1571
|
sort?: Record<string, 1 | -1>;
|
|
1572
|
-
/**
|
|
1572
|
+
/**
|
|
1573
|
+
* Static hard cap on result rows. Always applied at the IR level
|
|
1574
|
+
* (LIMIT / `$limit`), regardless of URL params. Use when the
|
|
1575
|
+
* aggregation has a fixed-size shape ("top 10 categories"). Mutually
|
|
1576
|
+
* exclusive with `defaultLimit` / `maxLimit` — pick the static form
|
|
1577
|
+
* OR the URL-driven form, not both.
|
|
1578
|
+
*/
|
|
1573
1579
|
limit?: number;
|
|
1580
|
+
/**
|
|
1581
|
+
* URL-driven row limit — applied when the caller passes `?limit=N`.
|
|
1582
|
+
* When set, the auto-route reads `query.limit`, parses it as a
|
|
1583
|
+
* positive integer, caps it at `maxLimit` (or the framework default
|
|
1584
|
+
* if `maxLimit` is unset), and writes the result into `AggRequest.limit`.
|
|
1585
|
+
* When the caller omits `?limit`, this default applies.
|
|
1586
|
+
*
|
|
1587
|
+
* **DoS defense.** Auto-generated `/aggregations/:name` routes today
|
|
1588
|
+
* have no upper bound on response size. A `groupBy: 'userId'` on a
|
|
1589
|
+
* 10M-user table without `defaultLimit` returns a 10M-row JSON. Setting
|
|
1590
|
+
* `defaultLimit: 100, maxLimit: 1000` bounds the response shape while
|
|
1591
|
+
* letting power users request up to 1000 rows when they need them.
|
|
1592
|
+
*
|
|
1593
|
+
* Mutually exclusive with the static `limit` — boot error if both set.
|
|
1594
|
+
* Setting `defaultLimit` without `maxLimit` uses the framework
|
|
1595
|
+
* default cap (`AGG_FRAMEWORK_MAX_LIMIT = 1000`) — explicit is better.
|
|
1596
|
+
*/
|
|
1597
|
+
defaultLimit?: number;
|
|
1598
|
+
/**
|
|
1599
|
+
* Hard ceiling for URL-driven `?limit=N`. Only meaningful when
|
|
1600
|
+
* `defaultLimit` is set; ignored otherwise. Defaults to
|
|
1601
|
+
* `AGG_FRAMEWORK_MAX_LIMIT` (1000) when omitted but `defaultLimit` is
|
|
1602
|
+
* present. Boot validation: must be ≥ `defaultLimit`.
|
|
1603
|
+
*/
|
|
1604
|
+
maxLimit?: number;
|
|
1574
1605
|
/**
|
|
1575
1606
|
* Top-N-per-group filter. Keeps only the top `limit` rows per
|
|
1576
1607
|
* partition, ranked by `sortBy`. The classic "top 3 products per
|
|
@@ -1964,6 +1995,62 @@ interface ControllerLike {
|
|
|
1964
1995
|
//#region src/types/resource.d.ts
|
|
1965
1996
|
/** Standard controller type alias for CRUD operations. */
|
|
1966
1997
|
type CrudController<TDoc> = IController<TDoc>;
|
|
1998
|
+
/**
|
|
1999
|
+
* Tenant-cleanup declaration on a resource — compliance-grade strategy
|
|
2000
|
+
* for what happens to this resource's rows when the owning organization
|
|
2001
|
+
* is deleted. Surfaces in arc's org-delete cascade runner and in
|
|
2002
|
+
* registry introspection (audit scripts ask "what happens to this
|
|
2003
|
+
* resource on org delete?").
|
|
2004
|
+
*
|
|
2005
|
+
* Strategy variants:
|
|
2006
|
+
* - `hard` — permanent removal (GDPR right-to-be-forgotten).
|
|
2007
|
+
* - `soft` — recoverable; pair with TTL for eventual hard-purge.
|
|
2008
|
+
* - `anonymize` — keep the row (legal retention) but clear PII
|
|
2009
|
+
* (HIPAA / PCI / SOX-compatible).
|
|
2010
|
+
* - `skip` — explicit opt-out with mandatory `reason`.
|
|
2011
|
+
*
|
|
2012
|
+
* See {@link ResourceConfig.onTenantDelete} for the full decision tree.
|
|
2013
|
+
*/
|
|
2014
|
+
interface OnTenantDeleteConfig {
|
|
2015
|
+
/**
|
|
2016
|
+
* What to do with rows whose `tenantField` matches the deleted org.
|
|
2017
|
+
* Discriminated union from `@classytic/repo-core/repository` — every
|
|
2018
|
+
* kit's `purgeByField` consumes the same shape.
|
|
2019
|
+
*/
|
|
2020
|
+
strategy: TenantPurgeStrategy;
|
|
2021
|
+
/**
|
|
2022
|
+
* Resources are processed in ascending `priority` order. Use to land
|
|
2023
|
+
* leaf data (logs, events) before aggregate references. Default `100`.
|
|
2024
|
+
*/
|
|
2025
|
+
priority?: number;
|
|
2026
|
+
/**
|
|
2027
|
+
* Rows per chunk for the underlying `purgeByField` call — bounds
|
|
2028
|
+
* lock contention + replication-log pressure on very large tenants.
|
|
2029
|
+
* Default kit-specific (~1000).
|
|
2030
|
+
*/
|
|
2031
|
+
batchSize?: number;
|
|
2032
|
+
}
|
|
2033
|
+
/**
|
|
2034
|
+
* Resolved tenant-purge declaration — what arc actually runs when
|
|
2035
|
+
* `cascadeDeleteForOrganization` fires. Computed once at boot from the
|
|
2036
|
+
* resource's `onTenantDelete` declaration.
|
|
2037
|
+
*
|
|
2038
|
+
* Exposed via `ResourceDefinition.resolvedTenantPurge` and
|
|
2039
|
+
* `getCascadingResourcesWithMetadata(registry)` so audit tooling can
|
|
2040
|
+
* answer "is this resource really going to hard-delete?" without
|
|
2041
|
+
* reading the source.
|
|
2042
|
+
*/
|
|
2043
|
+
interface ResolvedTenantPurge {
|
|
2044
|
+
readonly strategy: TenantPurgeStrategy;
|
|
2045
|
+
readonly priority: number;
|
|
2046
|
+
readonly batchSize?: number;
|
|
2047
|
+
/**
|
|
2048
|
+
* Where the strategy came from — `'declared'` (host wrote
|
|
2049
|
+
* `onTenantDelete` explicitly) or `'disabled'` (no declaration —
|
|
2050
|
+
* runner skips this resource).
|
|
2051
|
+
*/
|
|
2052
|
+
readonly source: "declared" | "disabled";
|
|
2053
|
+
}
|
|
1967
2054
|
/**
|
|
1968
2055
|
* Per-resource cache configuration for QueryCache. Enables
|
|
1969
2056
|
* stale-while-revalidate, auto-invalidation on mutations, and
|
|
@@ -2285,11 +2372,55 @@ interface RouteDefinition {
|
|
|
2285
2372
|
readonly path: string;
|
|
2286
2373
|
/**
|
|
2287
2374
|
* Route handler.
|
|
2288
|
-
* - String: controller method name (Arc pipeline)
|
|
2375
|
+
* - String: controller method name (Arc pipeline) — runtime lookup, no TS coverage on typos.
|
|
2289
2376
|
* - Function without `raw: true`: receives IRequestContext, returns IControllerResponse (Arc pipeline)
|
|
2290
2377
|
* - Function with `raw: true`: raw Fastify handler `(request, reply)`
|
|
2378
|
+
*
|
|
2379
|
+
* Prefer `controllerMethod` (2.16) over the string form when you want the
|
|
2380
|
+
* compiler to catch typos. `handler` stays optional when `controllerMethod`
|
|
2381
|
+
* is set — exactly one of the two must be declared.
|
|
2291
2382
|
*/
|
|
2292
|
-
readonly handler
|
|
2383
|
+
readonly handler?: string | ControllerHandler | RouteHandlerMethod | ((request: FastifyRequest<Record<string, unknown>>, reply: FastifyReply) => unknown);
|
|
2384
|
+
/**
|
|
2385
|
+
* Typed function-reference handler (2.16). Receives the live controller
|
|
2386
|
+
* instance and returns the method to invoke — TypeScript catches typos
|
|
2387
|
+
* and surfaces autocomplete on the controller's method names. Prefer
|
|
2388
|
+
* this over the string `handler` form for any host that uses a typed
|
|
2389
|
+
* controller subclass.
|
|
2390
|
+
*
|
|
2391
|
+
* Resolved ONCE at route-registration time (the same path string
|
|
2392
|
+
* handlers go through), so there's no per-request lookup overhead.
|
|
2393
|
+
* The returned method is bound to the controller before dispatch.
|
|
2394
|
+
*
|
|
2395
|
+
* Mutually exclusive with `handler` — passing both throws at boot
|
|
2396
|
+
* with a clear "pick one" message. The runtime contract on what the
|
|
2397
|
+
* returned function accepts mirrors the `handler` rules: a plain
|
|
2398
|
+
* `ControllerHandler` for pipeline routes, a raw Fastify handler when
|
|
2399
|
+
* the route is `raw: true`.
|
|
2400
|
+
*
|
|
2401
|
+
* Typed loosely (`(controller: unknown) => …`) at the type-system
|
|
2402
|
+
* boundary because `RouteDefinition` is not generic over the
|
|
2403
|
+
* controller shape — host code annotates the parameter to opt in:
|
|
2404
|
+
*
|
|
2405
|
+
* @example
|
|
2406
|
+
* ```ts
|
|
2407
|
+
* class PostController extends BaseController<Post> {
|
|
2408
|
+
* async getStats(ctx: IRequestContext) { … }
|
|
2409
|
+
* }
|
|
2410
|
+
*
|
|
2411
|
+
* defineResource({
|
|
2412
|
+
* controller: new PostController(repo),
|
|
2413
|
+
* routes: [{
|
|
2414
|
+
* method: 'GET',
|
|
2415
|
+
* path: '/stats',
|
|
2416
|
+
* controllerMethod: (c: PostController) => c.getStats,
|
|
2417
|
+
* // ^^^^^^^^^^^^^^ TS catches typos here
|
|
2418
|
+
* permissions: requireAuth(),
|
|
2419
|
+
* }],
|
|
2420
|
+
* });
|
|
2421
|
+
* ```
|
|
2422
|
+
*/
|
|
2423
|
+
readonly controllerMethod?: (controller: unknown) => ControllerHandler | RouteHandlerMethod;
|
|
2293
2424
|
/** Permission check — REQUIRED */
|
|
2294
2425
|
readonly permissions: PermissionCheck;
|
|
2295
2426
|
/**
|
|
@@ -2309,6 +2440,24 @@ interface RouteDefinition {
|
|
|
2309
2440
|
readonly preHandler?: RouteHandlerMethod[] | ((fastify: FastifyInstance) => RouteHandlerMethod[]);
|
|
2310
2441
|
/** Pre-auth handlers (run before authentication) */
|
|
2311
2442
|
readonly preAuth?: RouteHandlerMethod[];
|
|
2443
|
+
/**
|
|
2444
|
+
* Opt this custom route into the multiTenant preset's tenant scoping.
|
|
2445
|
+
*
|
|
2446
|
+
* When `true` AND the resource declares `multiTenantPreset` (or
|
|
2447
|
+
* `flexibleMultiTenantPreset`), arc prepends the preset's tenant
|
|
2448
|
+
* filter + injection middleware to this route's chain — the same
|
|
2449
|
+
* pair `update` gets. The handler can then read the resolved tenant
|
|
2450
|
+
* via `getOrgId(req.scope)` / `req._tenantFields` (or, for write
|
|
2451
|
+
* routes, off `req.body` after injection) without re-implementing
|
|
2452
|
+
* the scope read + header fallback + 400 boilerplate.
|
|
2453
|
+
*
|
|
2454
|
+
* Throws at boot if set when no multiTenant preset is wired — the
|
|
2455
|
+
* misconfiguration would otherwise be silently insecure (read routes
|
|
2456
|
+
* returning every tenant's rows).
|
|
2457
|
+
*
|
|
2458
|
+
* @default false
|
|
2459
|
+
*/
|
|
2460
|
+
readonly tenantScope?: boolean;
|
|
2312
2461
|
/** SSE streaming mode */
|
|
2313
2462
|
readonly streamResponse?: boolean;
|
|
2314
2463
|
/**
|
|
@@ -2364,6 +2513,25 @@ interface ActionDefinition {
|
|
|
2364
2513
|
readonly schema?: unknown;
|
|
2365
2514
|
/** Description for OpenAPI docs and MCP tool */
|
|
2366
2515
|
readonly description?: string;
|
|
2516
|
+
/**
|
|
2517
|
+
* Whether this action needs an entity id from the URL.
|
|
2518
|
+
*
|
|
2519
|
+
* - `true` (default) — mounts under `POST /<prefix>/:id/action`. The `id`
|
|
2520
|
+
* path param is required; handler receives it as the first argument.
|
|
2521
|
+
* Use for actions that operate on an existing entity: `approve`,
|
|
2522
|
+
* `dispatch`, `cancel`, `archive`.
|
|
2523
|
+
* - `false` — mounts under `POST /<prefix>/action` (no `:id` segment).
|
|
2524
|
+
* Handler receives an empty-string first argument. Use for
|
|
2525
|
+
* collection-level actions that create / search / bulk-mutate:
|
|
2526
|
+
* `propose` (creates a new entity), `search` (returns rows), `bulk`.
|
|
2527
|
+
*
|
|
2528
|
+
* 2.15.5: previously every action had to live under `:id/action`, forcing
|
|
2529
|
+
* `propose`-style actions to swallow a meaningless URL parameter and
|
|
2530
|
+
* making the auto-generated MCP tool advertise an `id` field agents
|
|
2531
|
+
* had no value for. Setting `id: false` mounts the action at the
|
|
2532
|
+
* resource root and drops `id` from the MCP tool's input shape.
|
|
2533
|
+
*/
|
|
2534
|
+
readonly id?: boolean;
|
|
2367
2535
|
/**
|
|
2368
2536
|
* MCP tool generation:
|
|
2369
2537
|
* - omitted/true: auto-generate
|
|
@@ -2570,13 +2738,37 @@ interface ResourceConfig<TDoc = AnyRecord> {
|
|
|
2570
2738
|
/**
|
|
2571
2739
|
* Custom routes beyond CRUD. Presets also merge their routes here.
|
|
2572
2740
|
*
|
|
2573
|
-
*
|
|
2741
|
+
* **Route handlers return `IControllerResponse<T>` shape** —
|
|
2742
|
+
* `{ data, status?, meta?, headers? }`. Returning a bare value (array,
|
|
2743
|
+
* object, primitive) is supported via auto-envelope (2.17+) but the
|
|
2744
|
+
* explicit envelope is the canonical contract — declared `fields:`
|
|
2745
|
+
* permissions, custom `status`, `meta`, and `headers` only work when
|
|
2746
|
+
* you return the envelope. Set `raw: true` on a route to opt out of
|
|
2747
|
+
* arc's pipeline entirely (custom streaming, SSE, manual `reply.send()`).
|
|
2748
|
+
*
|
|
2749
|
+
* **Path collisions with auto-CRUD are detected at `defineResource()` time.**
|
|
2750
|
+
* If you declare a route that shares method+path with an auto-CRUD op
|
|
2751
|
+
* (e.g. `POST /` collides with `create`), validation throws with the
|
|
2752
|
+
* exact `disabledRoutes` line to add. Use one of:
|
|
2753
|
+
* - `disabledRoutes: ['create']` — suppress the auto-CRUD op
|
|
2754
|
+
* - `crud: { list: true, get: true }` — opt-in allow-list (preferred)
|
|
2755
|
+
* - `disableDefaultRoutes: true` — turn off all auto-CRUD on this resource
|
|
2756
|
+
*
|
|
2757
|
+
* @example Custom route alongside default CRUD:
|
|
2574
2758
|
* ```typescript
|
|
2575
2759
|
* routes: [
|
|
2576
2760
|
* { method: 'GET', path: '/stats', handler: 'getStats', permissions: auth() },
|
|
2577
2761
|
* { method: 'POST', path: '/webhook', handler: webhookFn, raw: true, permissions: auth() },
|
|
2578
2762
|
* ]
|
|
2579
2763
|
* ```
|
|
2764
|
+
*
|
|
2765
|
+
* @example Custom POST replacing the auto-CRUD `create`:
|
|
2766
|
+
* ```typescript
|
|
2767
|
+
* disabledRoutes: ['create'],
|
|
2768
|
+
* routes: [
|
|
2769
|
+
* { method: 'POST', path: '/', handler: customCreate, permissions: requireAuth() },
|
|
2770
|
+
* ]
|
|
2771
|
+
* ```
|
|
2580
2772
|
*/
|
|
2581
2773
|
routes?: RouteDefinition[];
|
|
2582
2774
|
/**
|
|
@@ -2630,13 +2822,84 @@ interface ResourceConfig<TDoc = AnyRecord> {
|
|
|
2630
2822
|
aggregations?: AggregationsMap;
|
|
2631
2823
|
disableCrud?: boolean;
|
|
2632
2824
|
disableDefaultRoutes?: boolean;
|
|
2633
|
-
/** Specific routes to disable */
|
|
2825
|
+
/** Specific routes to disable (negative-form opt-out). */
|
|
2634
2826
|
disabledRoutes?: CrudRouteKey[];
|
|
2827
|
+
/**
|
|
2828
|
+
* Declarative CRUD allow-list — what's ENABLED is explicit (positive form).
|
|
2829
|
+
*
|
|
2830
|
+
* Mutually exclusive with `disabledRoutes` — passing both is a config
|
|
2831
|
+
* error and throws at boot. Use this when you want least-privilege
|
|
2832
|
+
* defaults: a new CRUD op added in a future arc release won't silently
|
|
2833
|
+
* leak through your `disabledRoutes` list because every op is opt-in.
|
|
2834
|
+
*
|
|
2835
|
+
* - `crud: { list: true, get: true }` — only `list` + `get` mount;
|
|
2836
|
+
* `create` / `update` / `delete` are NOT mounted.
|
|
2837
|
+
* - `crud: false` — equivalent to `disableDefaultRoutes: true` (no CRUD at all).
|
|
2838
|
+
* - `crud: undefined` (default) — every op mounts (legacy behaviour).
|
|
2839
|
+
*
|
|
2840
|
+
* 2.16: prefer this over `disabledRoutes` for new resources. The
|
|
2841
|
+
* negative form stays for back-compat but won't be the documented
|
|
2842
|
+
* default going forward.
|
|
2843
|
+
*
|
|
2844
|
+
* @example
|
|
2845
|
+
* ```ts
|
|
2846
|
+
* defineResource({
|
|
2847
|
+
* name: 'audit-log',
|
|
2848
|
+
* crud: { list: true, get: true }, // read-only — no create/update/delete
|
|
2849
|
+
* permissions: { list: requireRoles(['admin']), get: requireRoles(['admin']) },
|
|
2850
|
+
* });
|
|
2851
|
+
* ```
|
|
2852
|
+
*/
|
|
2853
|
+
crud?: false | { [K in CrudRouteKey]?: boolean };
|
|
2635
2854
|
/**
|
|
2636
2855
|
* Field name used for multi-tenant scoping (default: 'organizationId').
|
|
2637
2856
|
* Override to match your schema: 'workspaceId', 'tenantId', etc.
|
|
2638
2857
|
*/
|
|
2639
2858
|
tenantField?: string | false;
|
|
2859
|
+
/**
|
|
2860
|
+
* Tenant-cleanup declaration — what `cascadeDeleteForOrganization`
|
|
2861
|
+
* does with this resource's rows when an organization is deleted.
|
|
2862
|
+
* Required for the resource to participate in the cascade; unflagged
|
|
2863
|
+
* resources are never touched.
|
|
2864
|
+
*
|
|
2865
|
+
* - `{ strategy: { type: 'hard' } }` — permanent delete (GDPR).
|
|
2866
|
+
* - `{ strategy: { type: 'soft' } }` — set `deleted: true` + `deletedAt`
|
|
2867
|
+
* (recoverable; pair with TTL for eventual hard-purge).
|
|
2868
|
+
* - `{ strategy: { type: 'anonymize', fields: { name: '[REDACTED]', email: null } } }`
|
|
2869
|
+
* — keep the row (legal retention) but clear PII linkage. HIPAA /
|
|
2870
|
+
* PCI / SOX-compatible. Field values can be static or `(doc) =>
|
|
2871
|
+
* value` for derived patches (hashes, etc.).
|
|
2872
|
+
* - `{ strategy: { type: 'skip', reason: 'audit-retained-per-SOX' } }`
|
|
2873
|
+
* — explicit opt-out with **mandatory** reason. Surfaces in audit reports.
|
|
2874
|
+
*
|
|
2875
|
+
* **Priority** — lower runs first. Default `100`. Use to land leaf data
|
|
2876
|
+
* before aggregate references:
|
|
2877
|
+
* - `10` : bulk leaf data (events, logs)
|
|
2878
|
+
* - `50` : business entities (orders, invoices)
|
|
2879
|
+
* - `100` : default
|
|
2880
|
+
*
|
|
2881
|
+
* Priority groups are barriers even under concurrency — all
|
|
2882
|
+
* priority-10 resources finish before any priority-50 starts.
|
|
2883
|
+
*
|
|
2884
|
+
* **Batch size** — rows per chunk for the underlying `purgeByField`
|
|
2885
|
+
* call. Default kit-specific (~1000). Tune for very large tenants.
|
|
2886
|
+
*
|
|
2887
|
+
* @example Compliance-retained financial ledger
|
|
2888
|
+
* ```ts
|
|
2889
|
+
* defineResource({
|
|
2890
|
+
* name: 'invoice',
|
|
2891
|
+
* tenantField: 'organizationId',
|
|
2892
|
+
* onTenantDelete: {
|
|
2893
|
+
* strategy: {
|
|
2894
|
+
* type: 'anonymize',
|
|
2895
|
+
* fields: { customerName: '[REDACTED]', customerEmail: null },
|
|
2896
|
+
* },
|
|
2897
|
+
* priority: 50,
|
|
2898
|
+
* },
|
|
2899
|
+
* });
|
|
2900
|
+
* ```
|
|
2901
|
+
*/
|
|
2902
|
+
onTenantDelete?: OnTenantDeleteConfig;
|
|
2640
2903
|
/**
|
|
2641
2904
|
* Default sort applied to `list` responses when the request doesn't
|
|
2642
2905
|
* specify one. Arc's built-in default is `-createdAt` (Mongo convention).
|
|
@@ -2678,6 +2941,28 @@ interface ResourceConfig<TDoc = AnyRecord> {
|
|
|
2678
2941
|
skipValidation?: boolean;
|
|
2679
2942
|
/** Don't register in introspection */
|
|
2680
2943
|
skipRegistry?: boolean;
|
|
2944
|
+
/**
|
|
2945
|
+
* Per-resource MCP opt-out.
|
|
2946
|
+
*
|
|
2947
|
+
* - omitted / `true` (default) — resource may be surfaced by `mcpPlugin`,
|
|
2948
|
+
* subject to the plugin's `expose` / `include` / `exclude` selection.
|
|
2949
|
+
* - `false` — opt this resource OUT of MCP tool generation entirely.
|
|
2950
|
+
* Always wins over the plugin's `expose` / `include` allowlist;
|
|
2951
|
+
* keeps the opt-out colocated with the resource definition instead
|
|
2952
|
+
* of in a host-side blocklist that drifts as resources are added.
|
|
2953
|
+
*
|
|
2954
|
+
* Use the local opt-out for resources that should never expose tools
|
|
2955
|
+
* (internal back-office, audit-trail readers, system-managed entities).
|
|
2956
|
+
* Use the plugin-level `expose`/`include` allowlist when the cut is
|
|
2957
|
+
* cross-cutting (only a handful of resources should be agent-callable
|
|
2958
|
+
* across the whole app).
|
|
2959
|
+
*
|
|
2960
|
+
* @example
|
|
2961
|
+
* ```ts
|
|
2962
|
+
* defineResource({ name: 'internal-job-log', mcp: false, ... });
|
|
2963
|
+
* ```
|
|
2964
|
+
*/
|
|
2965
|
+
mcp?: boolean;
|
|
2681
2966
|
/** Internal: track applied presets */
|
|
2682
2967
|
_appliedPresets?: string[];
|
|
2683
2968
|
/** HTTP method for update routes. Default: 'PATCH' */
|
|
@@ -2718,6 +3003,39 @@ interface ResourceConfig<TDoc = AnyRecord> {
|
|
|
2718
3003
|
};
|
|
2719
3004
|
}
|
|
2720
3005
|
//#endregion
|
|
3006
|
+
//#region src/core/defineResource/diagnostics.d.ts
|
|
3007
|
+
/**
|
|
3008
|
+
* Boot-time diagnostics produced by the `defineResource()` validation pipeline.
|
|
3009
|
+
*
|
|
3010
|
+
* `defineResource()` runs at module load — long before any Fastify instance
|
|
3011
|
+
* exists — so non-fatal warnings (redundant field-rule flags, ambiguous
|
|
3012
|
+
* preset combinations, etc.) cannot be emitted through a logger at the
|
|
3013
|
+
* point they are detected. Instead we COLLECT them into a structured
|
|
3014
|
+
* `ResourceDiagnostic[]`, attach the array to `ResourceDefinition._diagnostics`,
|
|
3015
|
+
* and flush each entry through `fastify.log.warn` on first mount inside
|
|
3016
|
+
* `buildResourcePlugin`. Hosts thus retain full control over framework
|
|
3017
|
+
* output (silencing, redirecting, structured logging) — the framework
|
|
3018
|
+
* never reaches for `console.*` directly outside of `src/cli/`.
|
|
3019
|
+
*
|
|
3020
|
+
* Hard errors continue to `throw` inside the validation pipeline — those
|
|
3021
|
+
* surface synchronously at define-time, which is the right UX for
|
|
3022
|
+
* "this resource will never work" failures.
|
|
3023
|
+
*/
|
|
3024
|
+
/**
|
|
3025
|
+
* One non-fatal diagnostic produced during resource validation.
|
|
3026
|
+
*
|
|
3027
|
+
* - `severity`: log level the host logger uses (`warn` for misconfigurations
|
|
3028
|
+
* the host should clean up, `info` for deprecation hints).
|
|
3029
|
+
* - `code`: stable identifier for the diagnostic — hosts and tests can match
|
|
3030
|
+
* on this without parsing the human-readable message.
|
|
3031
|
+
* - `message`: pre-formatted line, resource name already interpolated.
|
|
3032
|
+
*/
|
|
3033
|
+
interface ResourceDiagnostic {
|
|
3034
|
+
severity: "warn" | "info";
|
|
3035
|
+
code: string;
|
|
3036
|
+
message: string;
|
|
3037
|
+
}
|
|
3038
|
+
//#endregion
|
|
2721
3039
|
//#region src/core/defineResource/ResourceDefinition.d.ts
|
|
2722
3040
|
/**
|
|
2723
3041
|
* Constructor input shape — `ResourceConfig` plus the metadata
|
|
@@ -2767,7 +3085,23 @@ declare class ResourceDefinition<TDoc = AnyRecord> {
|
|
|
2767
3085
|
readonly pipe?: PipelineConfig;
|
|
2768
3086
|
readonly fields?: FieldPermissionMap;
|
|
2769
3087
|
readonly cache?: ResourceCacheConfig;
|
|
3088
|
+
/**
|
|
3089
|
+
* Per-resource MCP opt-out. `false` keeps the resource out of every
|
|
3090
|
+
* `mcpPlugin` registration regardless of the plugin's `expose` /
|
|
3091
|
+
* `include` allowlist — local opt-out is authoritative. See
|
|
3092
|
+
* `ResourceConfig.mcp` for the host-facing surface.
|
|
3093
|
+
*/
|
|
3094
|
+
readonly mcp: boolean;
|
|
2770
3095
|
readonly tenantField?: string | false;
|
|
3096
|
+
/** Tenant-cleanup strategy on org delete — see `OnTenantDeleteConfig`. */
|
|
3097
|
+
readonly onTenantDelete?: OnTenantDeleteConfig;
|
|
3098
|
+
/**
|
|
3099
|
+
* Resolved tenant-purge strategy — what `cascadeDeleteForOrganization`
|
|
3100
|
+
* actually runs. Computed once at boot from `onTenantDelete`. Audit /
|
|
3101
|
+
* introspection tooling reads this instead of re-running the rule at
|
|
3102
|
+
* the call site.
|
|
3103
|
+
*/
|
|
3104
|
+
readonly resolvedTenantPurge: ResolvedTenantPurge;
|
|
2771
3105
|
readonly idField?: string;
|
|
2772
3106
|
readonly queryParser?: QueryParserInterface;
|
|
2773
3107
|
readonly _appliedPresets: string[];
|
|
@@ -2778,6 +3112,17 @@ declare class ResourceDefinition<TDoc = AnyRecord> {
|
|
|
2778
3112
|
priority: number;
|
|
2779
3113
|
}>;
|
|
2780
3114
|
_registryMeta?: RegisterOptions;
|
|
3115
|
+
/**
|
|
3116
|
+
* Boot-time validation diagnostics (non-fatal — hard errors throw
|
|
3117
|
+
* synchronously in `validateDefineResourceConfig`). Populated when
|
|
3118
|
+
* the host's config contains redundant / ambiguous flags that
|
|
3119
|
+
* shouldn't crash the boot but the host should clean up. Flushed
|
|
3120
|
+
* through `fastify.log.warn` on first mount inside
|
|
3121
|
+
* `buildResourcePlugin` so the host's configured logger owns the
|
|
3122
|
+
* output — the framework never speaks to `console.*` from `src/`
|
|
3123
|
+
* outside of the CLI.
|
|
3124
|
+
*/
|
|
3125
|
+
_diagnostics?: ResourceDiagnostic[];
|
|
2781
3126
|
/**
|
|
2782
3127
|
* Per-host idempotency guard used by `buildResourcePlugin` to
|
|
2783
3128
|
* skip duplicate shared-state writes when the same resource is
|
|
@@ -2852,8 +3197,25 @@ interface RouteRow {
|
|
|
2852
3197
|
}
|
|
2853
3198
|
declare class ResourceRegistry {
|
|
2854
3199
|
private _resources;
|
|
3200
|
+
/**
|
|
3201
|
+
* Parallel map of full `DataAdapter` instances. The public `RegistryEntry.adapter`
|
|
3202
|
+
* field is intentionally narrowed to `{ type, name }` so introspection can be
|
|
3203
|
+
* JSON-serialized — but cascade / cleanup / migration helpers need the live
|
|
3204
|
+
* adapter (and its `.repository`) to do real work. Stored here, behind
|
|
3205
|
+
* `getAdapter(name)`, so the public metadata stays serializable and the
|
|
3206
|
+
* runtime-only handle is still reachable.
|
|
3207
|
+
*/
|
|
3208
|
+
private _adapters;
|
|
2855
3209
|
private _frozen;
|
|
2856
3210
|
constructor();
|
|
3211
|
+
/**
|
|
3212
|
+
* Get the live `DataAdapter` for a registered resource — the handle whose
|
|
3213
|
+
* `.repository` cascade / cleanup helpers actually call. Returns `undefined`
|
|
3214
|
+
* when the resource is unknown OR was registered without an adapter
|
|
3215
|
+
* (service-only resources). Typed loosely (`unknown`-shaped fields) so
|
|
3216
|
+
* consumers cast to their kit's adapter type at the use site.
|
|
3217
|
+
*/
|
|
3218
|
+
getAdapter<T = unknown>(name: string): T | undefined;
|
|
2857
3219
|
/**
|
|
2858
3220
|
* Register a resource
|
|
2859
3221
|
*/
|
|
@@ -2923,7 +3285,16 @@ declare class ResourceRegistry {
|
|
|
2923
3285
|
*/
|
|
2924
3286
|
unfreeze(): void;
|
|
2925
3287
|
/**
|
|
2926
|
-
* Reset registry — clear all resources
|
|
3288
|
+
* Reset registry — clear all resources, drop their parallel live-adapter
|
|
3289
|
+
* handles, and unfreeze.
|
|
3290
|
+
*
|
|
3291
|
+
* The `_adapters` map (added in 2.15.5 so cascade / cleanup helpers can
|
|
3292
|
+
* reach `adapter.repository` after registration) must clear alongside
|
|
3293
|
+
* `_resources`. Pre-2.16 this method dropped the public entries but
|
|
3294
|
+
* left the live adapters dangling, so a test that called `reset()`
|
|
3295
|
+
* between cases would see ghost adapters and either (a) leak a live
|
|
3296
|
+
* Mongo connection across describe blocks or (b) `cascadeDeleteForOrganization`
|
|
3297
|
+
* iterate over a defunct registry entry. Clear both halves together.
|
|
2927
3298
|
*/
|
|
2928
3299
|
reset(): void;
|
|
2929
3300
|
/** @internal Alias for unfreeze() */
|
|
@@ -3306,6 +3677,21 @@ interface RegistryEntry extends ResourceMetadata {
|
|
|
3306
3677
|
} | null;
|
|
3307
3678
|
events?: string[];
|
|
3308
3679
|
disableDefaultRoutes?: boolean;
|
|
3680
|
+
/**
|
|
3681
|
+
* 2.15.5 — multi-tenant scoping field declared on the resource
|
|
3682
|
+
* (defaults to `'organizationId'`; `false` for company-wide tables).
|
|
3683
|
+
* Surfaced so introspection / cascade helpers can scope deletes
|
|
3684
|
+
* without re-reading the resource definition.
|
|
3685
|
+
*/
|
|
3686
|
+
tenantField?: string | false;
|
|
3687
|
+
/**
|
|
3688
|
+
* Resolved tenant-purge strategy — what arc actually runs when
|
|
3689
|
+
* `cascadeDeleteForOrganization` fires for this resource. Computed
|
|
3690
|
+
* at boot from the resource's `onTenantDelete` declaration. Surfaced
|
|
3691
|
+
* here so introspection / audit scripts can answer "what happens on
|
|
3692
|
+
* org-delete?" without re-reading the resource definition.
|
|
3693
|
+
*/
|
|
3694
|
+
resolvedTenantPurge?: ResolvedTenantPurge;
|
|
3309
3695
|
openApiSchemas?: OpenApiSchemas;
|
|
3310
3696
|
registeredAt?: string;
|
|
3311
3697
|
/** Field-level permissions metadata (for OpenAPI data) */
|
|
@@ -3340,7 +3726,15 @@ interface RegistryEntry extends ResourceMetadata {
|
|
|
3340
3726
|
readonly name: string;
|
|
3341
3727
|
readonly description?: string; /** Raw per-action schema (JSON Schema, Zod v4, or legacy field map) */
|
|
3342
3728
|
readonly schema?: unknown; /** Per-action permission check (if different from resource-level `actionPermissions`) */
|
|
3343
|
-
readonly permissions?: PermissionCheck;
|
|
3729
|
+
readonly permissions?: PermissionCheck;
|
|
3730
|
+
/**
|
|
3731
|
+
* 2.15.5: mount point — `true` (default) for `POST /:id/action`,
|
|
3732
|
+
* `false` for `POST /action` (resource-root, no `:id` path param).
|
|
3733
|
+
* Consumed by registry enumeration, OpenAPI generation, and FE
|
|
3734
|
+
* resource manifests so callers can pick the right URL without
|
|
3735
|
+
* reading the action definition itself.
|
|
3736
|
+
*/
|
|
3737
|
+
readonly id?: boolean; /** MCP tool generation flag — `false` to skip, object for overrides */
|
|
3344
3738
|
readonly mcp?: boolean | {
|
|
3345
3739
|
readonly description?: string;
|
|
3346
3740
|
readonly annotations?: Record<string, unknown>;
|
|
@@ -3374,7 +3768,24 @@ interface RegistryEntry extends ResourceMetadata {
|
|
|
3374
3768
|
field: string;
|
|
3375
3769
|
maxRangeDays?: number;
|
|
3376
3770
|
}; /** Whether the aggregation requires named filters — surfaced in docs. */
|
|
3377
|
-
readonly requireFilters?: readonly string[];
|
|
3771
|
+
readonly requireFilters?: readonly string[];
|
|
3772
|
+
/**
|
|
3773
|
+
* Static result-row cap (no URL override). Mutually exclusive with
|
|
3774
|
+
* `defaultLimit` / `maxLimit`. Surfaced so OpenAPI docs can mention
|
|
3775
|
+
* the fixed cap in the description.
|
|
3776
|
+
*/
|
|
3777
|
+
readonly limit?: number;
|
|
3778
|
+
/**
|
|
3779
|
+
* URL-driven default limit (caller may pass `?limit=N`). When set,
|
|
3780
|
+
* OpenAPI docs render `?limit` as a query parameter with this
|
|
3781
|
+
* default and `maxLimit` as the maximum.
|
|
3782
|
+
*/
|
|
3783
|
+
readonly defaultLimit?: number;
|
|
3784
|
+
/**
|
|
3785
|
+
* URL-driven limit ceiling (only meaningful with `defaultLimit`).
|
|
3786
|
+
* OpenAPI docs render this as the `maximum` constraint on `?limit`.
|
|
3787
|
+
*/
|
|
3788
|
+
readonly maxLimit?: number; /** MCP tool generation flag — `false` to skip, object for overrides. */
|
|
3378
3789
|
readonly mcp?: boolean | {
|
|
3379
3790
|
readonly description?: string;
|
|
3380
3791
|
readonly annotations?: Record<string, unknown>;
|
|
@@ -3463,4 +3874,4 @@ interface ValidateOptions {
|
|
|
3463
3874
|
strict?: boolean;
|
|
3464
3875
|
}
|
|
3465
3876
|
//#endregion
|
|
3466
|
-
export {
|
|
3877
|
+
export { OnTenantDeleteConfig as $, BaseController as $t, RequestIdOptions as A, HookSystem as An, AggregationRateLimit as At, defineResource as B, AuthHelpers as Bt, RequestContext as C, AccessControlConfig as Cn, AggMeasureShorthand as Ct, HealthCheck as D, HookOperation as Dn, AggregationIndexHint as Dt, GracefulShutdownOptions as E, HookHandler as En, AggregationDateRangeRequirement as Et, FastifyWithDecorators as F, beforeCreate as Fn, OperationFilter as Ft, ActionsMap as G, TokenPair as Gt, ActionDefinition as H, Authenticator as Ht, MiddlewareHandler as I, beforeDelete as In, PipelineConfig as It, CrudRouteKey as J, ArcRequest as Jt, ArcFieldRule as K, AnyRecord as Kt, RequestWithExtras as L, beforeUpdate as Ln, PipelineContext as Lt, EventsDecorator as M, afterCreate as Mn, Guard as Mt, FastifyRequestExtras as N, afterDelete as Nn, Interceptor as Nt, HealthOptions as O, HookPhase as On, AggregationMaterializedContext as Ot, FastifyWithAuth as P, afterUpdate as Pn, NextFunction as Pt, MiddlewareConfig as Q, UserOrganization as Qt, RegisterOptions as R, createHookSystem as Rn, PipelineStep as Rt, QueryParserInterface as S, AccessControl as Sn, AggMeasureInput as St, CrudRouterOptions as T, HookContext as Tn, AggregationConfig as Tt, ActionEntry as U, AuthenticatorContext as Ut, ResourceDefinition as V, AuthPluginOptions as Vt, ActionHandlerFn as W, JwtContext as Wt, EventDefinition as X, ObjectId as Xt, CrudSchemas as Y, JWTPayload as Yt, FieldRule$1 as Z, UserLike as Zt, ControllerQueryOptions as _, ArcListResult as _n, FastifyHandler as _t, InferAdapterDoc as a, SlugMixin as an, ResolvedTenantPurge as at, ParsedQuery as b, BodySanitizer as bn, IRequestContext as bt, TypedController as c, BaseControllerOptions as cn, ResourceHookContext as ct, PaginationResult as d, ControllerConstructionOptions as dn, RouteDefinition as dt, SoftDeleteExt as en, OpenApiSchemas as et, IntrospectionData as f, QueryResolver as fn, RouteMcpConfig as ft, ArcInternalMetadata as g, ArcGetResult as gn, ControllerLike as gt, ResourceMetadata as h, ArcDeleteResult as hn, ControllerHandler as ht, ValidationResult as i, SlugExt as in, RateLimitConfig as it, ArcDecorator as j, HookSystemOptions as jn, AggregationsMap as jt, IntrospectionPluginOptions as k, HookRegistration as kn, AggregationMaterializedResult as kt, TypedRepository as l, BaseCrudController as ln, ResourceHooks as lt, RegistryStats as m, ArcCreateResult as mn, RouteSchemaOptions as mt, ConfigError as n, TreeExt as nn, PresetHook as nt, InferDocType as o, BulkExt as on, ResourceCacheConfig as ot, RegistryEntry as p, QueryResolverConfig as pn, RouteMethod as pt, CrudController as q, ApiResponse as qt, ValidateOptions as r, TreeMixin as rn, PresetResult as rt, InferResourceDoc as s, BulkMixin as sn, ResourceConfig as st, RouteHandlerMethod$1 as t, SoftDeleteMixin as tn, PresetFunction as tt, TypedResourceConfig as u, ControllerConfigurableOptions as un, ResourcePermissions as ut, LookupOption as v, ArcUpdateResult as vn, IController as vt, ServiceContext as w, DefineHookOptions as wn, AggregationCacheConfig as wt, PopulateOption as x, BodySanitizerConfig as xn, RouteHandler as xt, OwnershipCheck as y, ListResult as yn, IControllerResponse as yt, ResourceRegistry as z, defineHook as zn, Transform as zt };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { $t as
|
|
2
|
-
import { a as applyFieldWritePermissions, c as PermissionCheck, d as UserBase, i as applyFieldReadPermissions, l as PermissionContext, n as FieldPermissionMap, o as fields, t as FieldPermission, u as PermissionResult } from "./fields-
|
|
3
|
-
import { A as
|
|
4
|
-
import { A as requireRoles, C as allOf, E as denyAll, M as when, O as requireAuth, S as createOrgPermissions, T as anyOf, a as presets_d_exports, c as readOnly, d as requireOrgRole, f as requireScopeContext, i as ownerWithAdminBypass, k as requireOwnership, l as requireOrgInScope, m as requireTeamMembership, n as authenticated, o as publicRead, p as requireServiceScope, r as fullPublic, s as publicReadAdminWrite, t as adminOnly, u as requireOrgMembership, v as DynamicPermissionMatrix, w as allowPublic, x as createDynamicPermissionMatrix, y as DynamicPermissionMatrixConfig } from "./index-
|
|
5
|
-
import {
|
|
1
|
+
import { $t as BaseController, A as RequestIdOptions, At as AggregationRateLimit, B as defineResource, C as RequestContext, Ct as AggMeasureShorthand, D as HealthCheck, Dt as AggregationIndexHint, E as GracefulShutdownOptions, Et as AggregationDateRangeRequirement, F as FastifyWithDecorators, J as CrudRouteKey, Jt as ArcRequest, Kt as AnyRecord, L as RequestWithExtras, N as FastifyRequestExtras, O as HealthOptions, Ot as AggregationMaterializedContext, P as FastifyWithAuth, Q as MiddlewareConfig, Qt as UserOrganization, S as QueryParserInterface, St as AggMeasureInput, T as CrudRouterOptions, Tt as AggregationConfig, V as ResourceDefinition, Vt as AuthPluginOptions, X as EventDefinition, Y as CrudSchemas, Yt as JWTPayload, Z as FieldRule, _n as ArcListResult, a as InferAdapterDoc, an as SlugMixin, bt as IRequestContext, c as TypedController, cn as BaseControllerOptions, d as PaginationResult, dn as ControllerConstructionOptions, en as SoftDeleteExt, f as IntrospectionData, g as ArcInternalMetadata, gn as ArcGetResult, gt as ControllerLike, h as ResourceMetadata, hn as ArcDeleteResult, i as ValidationResult, in as SlugExt, it as RateLimitConfig, jt as AggregationsMap, k as IntrospectionPluginOptions, kt as AggregationMaterializedResult, l as TypedRepository, ln as BaseCrudController, m as RegistryStats, mn as ArcCreateResult, mt as RouteSchemaOptions, n as ConfigError, nn as TreeExt, o as InferDocType, on as BulkExt, p as RegistryEntry, q as CrudController, qt as ApiResponse, r as ValidateOptions, rn as TreeMixin, rt as PresetResult, s as InferResourceDoc, sn as BulkMixin, st as ResourceConfig, t as RouteHandlerMethod, tn as SoftDeleteMixin, tt as PresetFunction, u as TypedResourceConfig, un as ControllerConfigurableOptions, vn as ArcUpdateResult, vt as IController, w as ServiceContext, wt as AggregationCacheConfig, xt as RouteHandler, y as OwnershipCheck, yn as ListResult, yt as IControllerResponse } from "./index-DBDgy6Hw.mjs";
|
|
2
|
+
import { a as applyFieldWritePermissions, c as PermissionCheck, d as UserBase, i as applyFieldReadPermissions, l as PermissionContext, n as FieldPermissionMap, o as fields, t as FieldPermission, u as PermissionResult } from "./fields-DqZLp5d6.mjs";
|
|
3
|
+
import { A as MAX_FILTER_DEPTH, C as DEFAULT_SORT, D as HOOK_PHASES, E as HOOK_OPERATIONS, F as RESERVED_QUERY_PARAMS, I as SYSTEM_FIELDS, M as MAX_SEARCH_LENGTH, N as MUTATION_OPERATIONS, O as HookOperation, P as MutationOperation, S as DEFAULT_MAX_LIMIT, T as DEFAULT_UPDATE_METHOD, _ as defineAggregation, b as DEFAULT_ID_FIELD, f as defineResourceVariants, j as MAX_REGEX_LENGTH, k as HookPhase, m as defineAction, s as getControllerScope, v as CRUD_OPERATIONS, w as DEFAULT_TENANT_FIELD, x as DEFAULT_LIMIT, y as CrudOperation } from "./index-CC_pgZjY.mjs";
|
|
4
|
+
import { A as requireRoles, C as allOf, E as denyAll, M as when, O as requireAuth, S as createOrgPermissions, T as anyOf, a as presets_d_exports, c as readOnly, d as requireOrgRole, f as requireScopeContext, i as ownerWithAdminBypass, k as requireOwnership, l as requireOrgInScope, m as requireTeamMembership, n as authenticated, o as publicRead, p as requireServiceScope, r as fullPublic, s as publicReadAdminWrite, t as adminOnly, u as requireOrgMembership, v as DynamicPermissionMatrix, w as allowPublic, x as createDynamicPermissionMatrix, y as DynamicPermissionMatrixConfig } from "./index-3L-adFJO.mjs";
|
|
5
|
+
import { a as NotFoundError, d as ValidationError, f as createDomainError, i as ForbiddenError, t as ArcError, u as UnauthorizedError } from "./errors-4ZloYFvm.mjs";
|
|
6
6
|
|
|
7
7
|
//#region src/index.d.ts
|
|
8
8
|
declare const version: string;
|
|
9
9
|
//#endregion
|
|
10
|
-
export { type AggMeasureInput, type AggMeasureShorthand, type AggregationCacheConfig, type AggregationConfig, type AggregationDateRangeRequirement, type AggregationIndexHint, type AggregationMaterializedContext, type AggregationMaterializedResult, type AggregationRateLimit, type AggregationsMap, type AnyRecord, type ApiResponse, type ArcCreateResult, type ArcDeleteResult, ArcError, type ArcGetResult, type ArcInternalMetadata, type ArcListResult, type ArcRequest, type ArcUpdateResult, type AuthPluginOptions, BaseController, type BaseControllerOptions, BaseCrudController, type BulkExt, BulkMixin, CRUD_OPERATIONS, type ConfigError, type ControllerConfigurableOptions, type ControllerConstructionOptions, type ControllerLike, type CrudController, type CrudOperation, type CrudRouteKey, type CrudRouterOptions, type CrudSchemas, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, type DynamicPermissionMatrix, type DynamicPermissionMatrixConfig, type EventDefinition, type FastifyRequestExtras, type FastifyWithAuth, type FastifyWithDecorators, type FieldPermission, type FieldPermissionMap, type FieldRule, ForbiddenError, type GracefulShutdownOptions, HOOK_OPERATIONS, HOOK_PHASES, type HealthCheck, type HealthOptions, type HookOperation, type HookPhase, type IController, type IControllerResponse, type IRequestContext, type InferAdapterDoc, type InferDocType, type InferResourceDoc, type IntrospectionData, type IntrospectionPluginOptions, type JWTPayload, type ListResult, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, type MiddlewareConfig, type MutationOperation, NotFoundError, type OwnershipCheck, type PaginationResult, type PermissionCheck, type PermissionContext, type PermissionResult, type PresetFunction, type PresetResult, type QueryParserInterface, RESERVED_QUERY_PARAMS, type RateLimitConfig, type RegistryEntry, type RegistryStats, type RequestContext, type RequestIdOptions, type RequestWithExtras, type ResourceConfig, ResourceDefinition, type ResourceMetadata, type RouteHandler, type RouteHandlerMethod, type RouteSchemaOptions, SYSTEM_FIELDS, type ServiceContext, type SlugExt, SlugMixin, type SoftDeleteExt, SoftDeleteMixin, type TreeExt, TreeMixin, type TypedController, type TypedRepository, type TypedResourceConfig, UnauthorizedError, type UserBase, type UserOrganization, type ValidateOptions, ValidationError, type ValidationResult, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, createDomainError, createDynamicPermissionMatrix, createOrgPermissions, defineAggregation, defineResource, defineResourceVariants, denyAll, fields, fullPublic, getControllerScope,
|
|
10
|
+
export { type AggMeasureInput, type AggMeasureShorthand, type AggregationCacheConfig, type AggregationConfig, type AggregationDateRangeRequirement, type AggregationIndexHint, type AggregationMaterializedContext, type AggregationMaterializedResult, type AggregationRateLimit, type AggregationsMap, type AnyRecord, type ApiResponse, type ArcCreateResult, type ArcDeleteResult, ArcError, type ArcGetResult, type ArcInternalMetadata, type ArcListResult, type ArcRequest, type ArcUpdateResult, type AuthPluginOptions, BaseController, type BaseControllerOptions, BaseCrudController, type BulkExt, BulkMixin, CRUD_OPERATIONS, type ConfigError, type ControllerConfigurableOptions, type ControllerConstructionOptions, type ControllerLike, type CrudController, type CrudOperation, type CrudRouteKey, type CrudRouterOptions, type CrudSchemas, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, type DynamicPermissionMatrix, type DynamicPermissionMatrixConfig, type EventDefinition, type FastifyRequestExtras, type FastifyWithAuth, type FastifyWithDecorators, type FieldPermission, type FieldPermissionMap, type FieldRule, ForbiddenError, type GracefulShutdownOptions, HOOK_OPERATIONS, HOOK_PHASES, type HealthCheck, type HealthOptions, type HookOperation, type HookPhase, type IController, type IControllerResponse, type IRequestContext, type InferAdapterDoc, type InferDocType, type InferResourceDoc, type IntrospectionData, type IntrospectionPluginOptions, type JWTPayload, type ListResult, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, type MiddlewareConfig, type MutationOperation, NotFoundError, type OwnershipCheck, type PaginationResult, type PermissionCheck, type PermissionContext, type PermissionResult, type PresetFunction, type PresetResult, type QueryParserInterface, RESERVED_QUERY_PARAMS, type RateLimitConfig, type RegistryEntry, type RegistryStats, type RequestContext, type RequestIdOptions, type RequestWithExtras, type ResourceConfig, ResourceDefinition, type ResourceMetadata, type RouteHandler, type RouteHandlerMethod, type RouteSchemaOptions, SYSTEM_FIELDS, type ServiceContext, type SlugExt, SlugMixin, type SoftDeleteExt, SoftDeleteMixin, type TreeExt, TreeMixin, type TypedController, type TypedRepository, type TypedResourceConfig, UnauthorizedError, type UserBase, type UserOrganization, type ValidateOptions, ValidationError, type ValidationResult, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, createDomainError, createDynamicPermissionMatrix, createOrgPermissions, defineAction, defineAggregation, defineResource, defineResourceVariants, denyAll, fields, fullPublic, getControllerScope, ownerWithAdminBypass, presets_d_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, version, when };
|