@classytic/arc 2.15.4 → 2.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/README.md +1 -0
  2. package/bin/arc.js +12 -0
  3. package/dist/{BaseController-dx3m2J8V.mjs → BaseController-DlCCTIxJ.mjs} +61 -19
  4. package/dist/{HookSystem-Iiebom92.mjs → HookSystem-Cmf7-Etp.mjs} +8 -4
  5. package/dist/{QueryCache-D41bfdBB.d.mts → QueryCache-SvmT_9ti.d.mts} +1 -1
  6. package/dist/{ResourceRegistry-CTERg_2x.mjs → ResourceRegistry-f48hFk3m.mjs} +52 -9
  7. package/dist/audit/index.d.mts +1 -1
  8. package/dist/audit/index.mjs +4 -2
  9. package/dist/auth/index.d.mts +4 -4
  10. package/dist/auth/index.mjs +4 -4
  11. package/dist/auth/redis-session.d.mts +1 -1
  12. package/dist/{betterAuthOpenApi--M_i87dQ.mjs → betterAuthOpenApi-ClWxaceA.mjs} +10 -6
  13. package/dist/buildHandler-BZX6zzDM.mjs +300 -0
  14. package/dist/cache/index.d.mts +3 -3
  15. package/dist/cache/index.mjs +3 -3
  16. package/dist/{caching-SM8gghN6.mjs → caching-TeHE8G-v.mjs} +1 -1
  17. package/dist/cli/commands/describe.d.mts +35 -1
  18. package/dist/cli/commands/describe.mjs +52 -12
  19. package/dist/cli/commands/docs.d.mts +1 -4
  20. package/dist/cli/commands/docs.mjs +4 -16
  21. package/dist/cli/commands/generate.d.mts +2 -20
  22. package/dist/cli/commands/generate.mjs +1 -546
  23. package/dist/cli/commands/init.d.mts +2 -40
  24. package/dist/cli/commands/init.mjs +1 -3045
  25. package/dist/cli/commands/introspect.mjs +53 -64
  26. package/dist/cli/index.d.mts +2 -2
  27. package/dist/cli/index.mjs +2 -2
  28. package/dist/{constants-Cxde4rpC.mjs → constants-TrJVIJl0.mjs} +7 -0
  29. package/dist/core/index.d.mts +3 -3
  30. package/dist/core/index.mjs +5 -5
  31. package/dist/{core-CvmOqEms.mjs → core-DBJ_j6rX.mjs} +222 -44
  32. package/dist/createActionRouter-DUpN3Dd1.mjs +288 -0
  33. package/dist/{createAggregationRouter-B0bPDf5b.mjs → createAggregationRouter-Dq-TUCuY.mjs} +3 -2
  34. package/dist/{createApp-PFegs47-.mjs → createApp-DNccuhyI.mjs} +16 -14
  35. package/dist/{defineEvent-D5h7EvAx.mjs → defineEvent-DRwY0fYm.mjs} +1 -1
  36. package/dist/docs/index.d.mts +2 -2
  37. package/dist/docs/index.mjs +1 -1
  38. package/dist/{errorHandler-Bk-AGhkU.mjs → errorHandler-DpoXQHZ9.mjs} +17 -14
  39. package/dist/errors-C1lX_jlm.d.mts +91 -0
  40. package/dist/{eventPlugin-CaKTYkYM.mjs → eventPlugin-C2cGqtRO.mjs} +1 -1
  41. package/dist/{eventPlugin-qXpqTebY.d.mts → eventPlugin-CtHC_av1.d.mts} +1 -1
  42. package/dist/events/index.d.mts +3 -3
  43. package/dist/events/index.mjs +5 -5
  44. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  45. package/dist/events/transports/redis.d.mts +1 -1
  46. package/dist/factory/index.d.mts +1 -1
  47. package/dist/factory/index.mjs +2 -2
  48. package/dist/{fields-COhcH3fk.d.mts → fields-Anj0xdih.d.mts} +1 -1
  49. package/dist/generate-BWFwgcCM.d.mts +38 -0
  50. package/dist/generate-CYac-OLv.mjs +654 -0
  51. package/dist/hooks/index.d.mts +1 -1
  52. package/dist/hooks/index.mjs +1 -1
  53. package/dist/idempotency/index.d.mts +2 -2
  54. package/dist/idempotency/index.mjs +1 -1
  55. package/dist/idempotency/redis.d.mts +1 -1
  56. package/dist/{index-BTqLEvhu.d.mts → index-3oIimXQn.d.mts} +12 -12
  57. package/dist/{index-BstGxcc3.d.mts → index-B-ulKx5P.d.mts} +55 -4
  58. package/dist/{index-BswOSJCE.d.mts → index-CkW0flkU.d.mts} +355 -16
  59. package/dist/index.d.mts +6 -6
  60. package/dist/index.mjs +7 -8
  61. package/dist/init-Dv71MsJr.d.mts +71 -0
  62. package/dist/init-HDvoO9L5.mjs +3098 -0
  63. package/dist/integrations/event-gateway.d.mts +2 -2
  64. package/dist/integrations/event-gateway.mjs +1 -1
  65. package/dist/integrations/index.d.mts +2 -2
  66. package/dist/integrations/jobs.mjs +3 -3
  67. package/dist/integrations/mcp/index.d.mts +239 -7
  68. package/dist/integrations/mcp/index.mjs +2 -528
  69. package/dist/integrations/mcp/testing.d.mts +2 -2
  70. package/dist/integrations/mcp/testing.mjs +6 -10
  71. package/dist/integrations/streamline.mjs +26 -1
  72. package/dist/integrations/websocket-redis.d.mts +1 -1
  73. package/dist/integrations/websocket.d.mts +1 -1
  74. package/dist/integrations/websocket.mjs +1 -0
  75. package/dist/loadResourcesFromEntry-BLMEI2Xa.mjs +51 -0
  76. package/dist/{resourceToTools-tFYUNmM0.mjs → mcpPlugin-7vGV51ED.mjs} +1021 -318
  77. package/dist/{memory-UBydS5ku.mjs → memory-QOLe11D5.mjs} +2 -0
  78. package/dist/middleware/index.d.mts +1 -1
  79. package/dist/middleware/index.mjs +1 -1
  80. package/dist/{openapi-BHXhoX8O.mjs → openapi-34T9yNwd.mjs} +47 -36
  81. package/dist/permissions/index.d.mts +2 -2
  82. package/dist/permissions/index.mjs +1 -1
  83. package/dist/{permissions-ohQyv50e.mjs → permissions-CTxMrreC.mjs} +2 -2
  84. package/dist/{pipe-Zr0KXjQe.mjs → pipe-DiCyvyPN.mjs} +1 -0
  85. package/dist/pipeline/index.d.mts +1 -1
  86. package/dist/pipeline/index.mjs +1 -1
  87. package/dist/plugins/index.d.mts +5 -5
  88. package/dist/plugins/index.mjs +10 -10
  89. package/dist/plugins/response-cache.mjs +5 -5
  90. package/dist/plugins/tracing-entry.d.mts +1 -1
  91. package/dist/plugins/tracing-entry.mjs +1 -1
  92. package/dist/{pluralize-DQgqgifU.mjs → pluralize-B9M8xvy-.mjs} +2 -1
  93. package/dist/presets/filesUpload.d.mts +4 -4
  94. package/dist/presets/filesUpload.mjs +2 -2
  95. package/dist/presets/index.d.mts +1 -1
  96. package/dist/presets/index.mjs +1 -1
  97. package/dist/presets/multiTenant.d.mts +1 -1
  98. package/dist/presets/multiTenant.mjs +4 -3
  99. package/dist/presets/search.d.mts +2 -2
  100. package/dist/presets/search.mjs +1 -1
  101. package/dist/{presets-BbkjdPeH.mjs → presets-C9BE6WaZ.mjs} +2 -2
  102. package/dist/{queryCachePlugin-m1XsgAIJ.mjs → queryCachePlugin-B4XMSSe7.mjs} +2 -2
  103. package/dist/{queryCachePlugin-CqMdLI2-.d.mts → queryCachePlugin-Biqzfbi5.d.mts} +2 -2
  104. package/dist/{redis-DiMkdHEl.d.mts → redis-Cyzrz6SX.d.mts} +1 -1
  105. package/dist/{redis-stream-D6HzR1Z_.d.mts → redis-stream-DT-YjzrB.d.mts} +1 -1
  106. package/dist/registry/index.d.mts +319 -2
  107. package/dist/registry/index.mjs +3 -3
  108. package/dist/registry-BBE23CDj.mjs +576 -0
  109. package/dist/{routerShared-DrOa-26E.mjs → routerShared-CZV5aabX.mjs} +3 -3
  110. package/dist/scope/index.d.mts +3 -3
  111. package/dist/scope/index.mjs +3 -3
  112. package/dist/{sse-Bz-5ZeTt.mjs → sse-BY6sTy4P.mjs} +1 -1
  113. package/dist/testing/index.d.mts +2 -2
  114. package/dist/testing/index.mjs +16 -7
  115. package/dist/testing/storageContract.d.mts +1 -1
  116. package/dist/types/index.d.mts +5 -5
  117. package/dist/types/storage.d.mts +1 -1
  118. package/dist/{types-C_s5moIu.mjs → types-Bi0r0vjG.mjs} +53 -1
  119. package/dist/{types-BQsjgQzS.d.mts → types-BsJMEQ4D.d.mts} +106 -12
  120. package/dist/{types-DrBaUwyV.d.mts → types-D-fYtKjb.d.mts} +33 -10
  121. package/dist/{types-CTYvcwHe.d.mts → types-DVfpSfx2.d.mts} +42 -1
  122. package/dist/utils/index.d.mts +1286 -2
  123. package/dist/utils/index.mjs +1 -1
  124. package/dist/{utils-_h9B3c57.mjs → utils-DC5ycPfr.mjs} +89 -40
  125. package/dist/{buildHandler-CcFOpJLh.mjs → validate-By96rH0r.mjs} +8 -299
  126. package/dist/{versioning-hmkPcDlX.d.mts → versioning-ZwX9tmbS.d.mts} +1 -1
  127. package/package.json +21 -28
  128. package/skills/arc/SKILL.md +300 -706
  129. package/skills/arc/references/auth.md +19 -7
  130. package/skills/arc-code-review/SKILL.md +1 -1
  131. package/skills/arc-code-review/references/arc-cheatsheet.md +100 -322
  132. package/dist/createActionRouter-S3MLVYot.mjs +0 -220
  133. package/dist/index-bRjYu21O.d.mts +0 -1320
  134. package/dist/org/index.d.mts +0 -66
  135. package/dist/org/index.mjs +0 -486
  136. package/dist/org/types.d.mts +0 -82
  137. package/dist/org/types.mjs +0 -1
  138. package/dist/registry-I-ogLgL9.mjs +0 -46
  139. /package/dist/{EventTransport-CT_52aWU.d.mts → EventTransport-C-2oAHtw.d.mts} +0 -0
  140. /package/dist/{EventTransport-DLWoUMHy.mjs → EventTransport-Hxvv5QQz.mjs} +0 -0
  141. /package/dist/{actionPermissions-CyUkQu6O.mjs → actionPermissions-Bjmvn7Eb.mjs} +0 -0
  142. /package/dist/{elevation-BXOWoGCF.d.mts → elevation-0YBpa663.d.mts} +0 -0
  143. /package/dist/{elevation-DgoeTyfX.mjs → elevation-Dci0AYLT.mjs} +0 -0
  144. /package/dist/{errorHandler-DFr45ZG4.d.mts → errorHandler-mHuyWzZE.d.mts} +0 -0
  145. /package/dist/{externalPaths-BD5nw6St.d.mts → externalPaths-DFg-2KTp.d.mts} +0 -0
  146. /package/dist/{interface-beEtJyWM.d.mts → interface-CH0OQudo.d.mts} +0 -0
  147. /package/dist/{interface-DfLGcus7.d.mts → interface-NwJ_qPlY.d.mts} +0 -0
  148. /package/dist/{keys-CGcCbNyu.mjs → keys-DopsCuyQ.mjs} +0 -0
  149. /package/dist/{loadResources-DBMQg_Aj.mjs → loadResources-ChQEj8ih.mjs} +0 -0
  150. /package/dist/{metrics-Qnvwc-LQ.mjs → metrics-TuOmguhi.mjs} +0 -0
  151. /package/dist/{replyHelpers-CK-FNO8E.mjs → replyHelpers-C-gD32oF.mjs} +0 -0
  152. /package/dist/{schemaIR-lYhC2gE5.mjs → schemaIR-Ctc89DSn.mjs} +0 -0
  153. /package/dist/{sessionManager-C4Le_UB3.d.mts → sessionManager-BqFegc0W.d.mts} +0 -0
  154. /package/dist/{storage-Dfzt4VTl.d.mts → storage-D2KZJAmn.d.mts} +0 -0
  155. /package/dist/{store-helpers-BkIN9-vu.mjs → store-helpers-B0sunfZZ.mjs} +0 -0
  156. /package/dist/{tracing-QJVprktp.d.mts → tracing-Dm8n7Cnn.d.mts} +0 -0
  157. /package/dist/{versioning-BUrT5aP4.mjs → versioning-B6mimogM.mjs} +0 -0
  158. /package/dist/{websocket-ChC2rqe1.d.mts → websocket-BkjeGZRn.d.mts} +0 -0
@@ -1,12 +1,12 @@
1
- import { a as QueryCacheConfig } from "./QueryCache-D41bfdBB.mjs";
2
- import { i as RequestScope } from "./types-CTYvcwHe.mjs";
3
- import { c as PermissionCheck, d as UserBase, n as FieldPermissionMap } from "./fields-COhcH3fk.mjs";
4
- import { n as DomainEvent } from "./EventTransport-CT_52aWU.mjs";
1
+ import { a as QueryCacheConfig } from "./QueryCache-SvmT_9ti.mjs";
2
+ import { i as RequestScope } from "./types-DVfpSfx2.mjs";
3
+ import { c as PermissionCheck, d as UserBase, n as FieldPermissionMap } from "./fields-Anj0xdih.mjs";
4
+ import { n as DomainEvent } from "./EventTransport-C-2oAHtw.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: any[]) => unknown;
457
- get: (...args: any[]) => unknown;
458
- create: (...args: any[]) => unknown;
459
- update: (...args: any[]) => unknown;
460
- delete: (...args: any[]) => unknown;
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.
@@ -1964,6 +1964,62 @@ interface ControllerLike {
1964
1964
  //#region src/types/resource.d.ts
1965
1965
  /** Standard controller type alias for CRUD operations. */
1966
1966
  type CrudController<TDoc> = IController<TDoc>;
1967
+ /**
1968
+ * Tenant-cleanup declaration on a resource — compliance-grade strategy
1969
+ * for what happens to this resource's rows when the owning organization
1970
+ * is deleted. Surfaces in arc's org-delete cascade runner and in
1971
+ * registry introspection (audit scripts ask "what happens to this
1972
+ * resource on org delete?").
1973
+ *
1974
+ * Strategy variants:
1975
+ * - `hard` — permanent removal (GDPR right-to-be-forgotten).
1976
+ * - `soft` — recoverable; pair with TTL for eventual hard-purge.
1977
+ * - `anonymize` — keep the row (legal retention) but clear PII
1978
+ * (HIPAA / PCI / SOX-compatible).
1979
+ * - `skip` — explicit opt-out with mandatory `reason`.
1980
+ *
1981
+ * See {@link ResourceConfig.onTenantDelete} for the full decision tree.
1982
+ */
1983
+ interface OnTenantDeleteConfig {
1984
+ /**
1985
+ * What to do with rows whose `tenantField` matches the deleted org.
1986
+ * Discriminated union from `@classytic/repo-core/repository` — every
1987
+ * kit's `purgeByField` consumes the same shape.
1988
+ */
1989
+ strategy: TenantPurgeStrategy;
1990
+ /**
1991
+ * Resources are processed in ascending `priority` order. Use to land
1992
+ * leaf data (logs, events) before aggregate references. Default `100`.
1993
+ */
1994
+ priority?: number;
1995
+ /**
1996
+ * Rows per chunk for the underlying `purgeByField` call — bounds
1997
+ * lock contention + replication-log pressure on very large tenants.
1998
+ * Default kit-specific (~1000).
1999
+ */
2000
+ batchSize?: number;
2001
+ }
2002
+ /**
2003
+ * Resolved tenant-purge declaration — what arc actually runs when
2004
+ * `cascadeDeleteForOrganization` fires. Computed once at boot from the
2005
+ * resource's `onTenantDelete` declaration.
2006
+ *
2007
+ * Exposed via `ResourceDefinition.resolvedTenantPurge` and
2008
+ * `getCascadingResourcesWithMetadata(registry)` so audit tooling can
2009
+ * answer "is this resource really going to hard-delete?" without
2010
+ * reading the source.
2011
+ */
2012
+ interface ResolvedTenantPurge {
2013
+ readonly strategy: TenantPurgeStrategy;
2014
+ readonly priority: number;
2015
+ readonly batchSize?: number;
2016
+ /**
2017
+ * Where the strategy came from — `'declared'` (host wrote
2018
+ * `onTenantDelete` explicitly) or `'disabled'` (no declaration —
2019
+ * runner skips this resource).
2020
+ */
2021
+ readonly source: "declared" | "disabled";
2022
+ }
1967
2023
  /**
1968
2024
  * Per-resource cache configuration for QueryCache. Enables
1969
2025
  * stale-while-revalidate, auto-invalidation on mutations, and
@@ -2285,11 +2341,55 @@ interface RouteDefinition {
2285
2341
  readonly path: string;
2286
2342
  /**
2287
2343
  * Route handler.
2288
- * - String: controller method name (Arc pipeline)
2344
+ * - String: controller method name (Arc pipeline) — runtime lookup, no TS coverage on typos.
2289
2345
  * - Function without `raw: true`: receives IRequestContext, returns IControllerResponse (Arc pipeline)
2290
2346
  * - Function with `raw: true`: raw Fastify handler `(request, reply)`
2347
+ *
2348
+ * Prefer `controllerMethod` (2.16) over the string form when you want the
2349
+ * compiler to catch typos. `handler` stays optional when `controllerMethod`
2350
+ * is set — exactly one of the two must be declared.
2351
+ */
2352
+ readonly handler?: string | ControllerHandler | RouteHandlerMethod | ((request: FastifyRequest<Record<string, unknown>>, reply: FastifyReply) => unknown);
2353
+ /**
2354
+ * Typed function-reference handler (2.16). Receives the live controller
2355
+ * instance and returns the method to invoke — TypeScript catches typos
2356
+ * and surfaces autocomplete on the controller's method names. Prefer
2357
+ * this over the string `handler` form for any host that uses a typed
2358
+ * controller subclass.
2359
+ *
2360
+ * Resolved ONCE at route-registration time (the same path string
2361
+ * handlers go through), so there's no per-request lookup overhead.
2362
+ * The returned method is bound to the controller before dispatch.
2363
+ *
2364
+ * Mutually exclusive with `handler` — passing both throws at boot
2365
+ * with a clear "pick one" message. The runtime contract on what the
2366
+ * returned function accepts mirrors the `handler` rules: a plain
2367
+ * `ControllerHandler` for pipeline routes, a raw Fastify handler when
2368
+ * the route is `raw: true`.
2369
+ *
2370
+ * Typed loosely (`(controller: unknown) => …`) at the type-system
2371
+ * boundary because `RouteDefinition` is not generic over the
2372
+ * controller shape — host code annotates the parameter to opt in:
2373
+ *
2374
+ * @example
2375
+ * ```ts
2376
+ * class PostController extends BaseController<Post> {
2377
+ * async getStats(ctx: IRequestContext) { … }
2378
+ * }
2379
+ *
2380
+ * defineResource({
2381
+ * controller: new PostController(repo),
2382
+ * routes: [{
2383
+ * method: 'GET',
2384
+ * path: '/stats',
2385
+ * controllerMethod: (c: PostController) => c.getStats,
2386
+ * // ^^^^^^^^^^^^^^ TS catches typos here
2387
+ * permissions: requireAuth(),
2388
+ * }],
2389
+ * });
2390
+ * ```
2291
2391
  */
2292
- readonly handler: string | ControllerHandler | RouteHandlerMethod | ((request: FastifyRequest<Record<string, unknown>>, reply: FastifyReply) => unknown);
2392
+ readonly controllerMethod?: (controller: unknown) => ControllerHandler | RouteHandlerMethod;
2293
2393
  /** Permission check — REQUIRED */
2294
2394
  readonly permissions: PermissionCheck;
2295
2395
  /**
@@ -2309,6 +2409,24 @@ interface RouteDefinition {
2309
2409
  readonly preHandler?: RouteHandlerMethod[] | ((fastify: FastifyInstance) => RouteHandlerMethod[]);
2310
2410
  /** Pre-auth handlers (run before authentication) */
2311
2411
  readonly preAuth?: RouteHandlerMethod[];
2412
+ /**
2413
+ * Opt this custom route into the multiTenant preset's tenant scoping.
2414
+ *
2415
+ * When `true` AND the resource declares `multiTenantPreset` (or
2416
+ * `flexibleMultiTenantPreset`), arc prepends the preset's tenant
2417
+ * filter + injection middleware to this route's chain — the same
2418
+ * pair `update` gets. The handler can then read the resolved tenant
2419
+ * via `getOrgId(req.scope)` / `req._tenantFields` (or, for write
2420
+ * routes, off `req.body` after injection) without re-implementing
2421
+ * the scope read + header fallback + 400 boilerplate.
2422
+ *
2423
+ * Throws at boot if set when no multiTenant preset is wired — the
2424
+ * misconfiguration would otherwise be silently insecure (read routes
2425
+ * returning every tenant's rows).
2426
+ *
2427
+ * @default false
2428
+ */
2429
+ readonly tenantScope?: boolean;
2312
2430
  /** SSE streaming mode */
2313
2431
  readonly streamResponse?: boolean;
2314
2432
  /**
@@ -2364,6 +2482,25 @@ interface ActionDefinition {
2364
2482
  readonly schema?: unknown;
2365
2483
  /** Description for OpenAPI docs and MCP tool */
2366
2484
  readonly description?: string;
2485
+ /**
2486
+ * Whether this action needs an entity id from the URL.
2487
+ *
2488
+ * - `true` (default) — mounts under `POST /<prefix>/:id/action`. The `id`
2489
+ * path param is required; handler receives it as the first argument.
2490
+ * Use for actions that operate on an existing entity: `approve`,
2491
+ * `dispatch`, `cancel`, `archive`.
2492
+ * - `false` — mounts under `POST /<prefix>/action` (no `:id` segment).
2493
+ * Handler receives an empty-string first argument. Use for
2494
+ * collection-level actions that create / search / bulk-mutate:
2495
+ * `propose` (creates a new entity), `search` (returns rows), `bulk`.
2496
+ *
2497
+ * 2.15.5: previously every action had to live under `:id/action`, forcing
2498
+ * `propose`-style actions to swallow a meaningless URL parameter and
2499
+ * making the auto-generated MCP tool advertise an `id` field agents
2500
+ * had no value for. Setting `id: false` mounts the action at the
2501
+ * resource root and drops `id` from the MCP tool's input shape.
2502
+ */
2503
+ readonly id?: boolean;
2367
2504
  /**
2368
2505
  * MCP tool generation:
2369
2506
  * - omitted/true: auto-generate
@@ -2630,13 +2767,84 @@ interface ResourceConfig<TDoc = AnyRecord> {
2630
2767
  aggregations?: AggregationsMap;
2631
2768
  disableCrud?: boolean;
2632
2769
  disableDefaultRoutes?: boolean;
2633
- /** Specific routes to disable */
2770
+ /** Specific routes to disable (negative-form opt-out). */
2634
2771
  disabledRoutes?: CrudRouteKey[];
2772
+ /**
2773
+ * Declarative CRUD allow-list — what's ENABLED is explicit (positive form).
2774
+ *
2775
+ * Mutually exclusive with `disabledRoutes` — passing both is a config
2776
+ * error and throws at boot. Use this when you want least-privilege
2777
+ * defaults: a new CRUD op added in a future arc release won't silently
2778
+ * leak through your `disabledRoutes` list because every op is opt-in.
2779
+ *
2780
+ * - `crud: { list: true, get: true }` — only `list` + `get` mount;
2781
+ * `create` / `update` / `delete` are NOT mounted.
2782
+ * - `crud: false` — equivalent to `disableDefaultRoutes: true` (no CRUD at all).
2783
+ * - `crud: undefined` (default) — every op mounts (legacy behaviour).
2784
+ *
2785
+ * 2.16: prefer this over `disabledRoutes` for new resources. The
2786
+ * negative form stays for back-compat but won't be the documented
2787
+ * default going forward.
2788
+ *
2789
+ * @example
2790
+ * ```ts
2791
+ * defineResource({
2792
+ * name: 'audit-log',
2793
+ * crud: { list: true, get: true }, // read-only — no create/update/delete
2794
+ * permissions: { list: requireRoles(['admin']), get: requireRoles(['admin']) },
2795
+ * });
2796
+ * ```
2797
+ */
2798
+ crud?: false | { [K in CrudRouteKey]?: boolean };
2635
2799
  /**
2636
2800
  * Field name used for multi-tenant scoping (default: 'organizationId').
2637
2801
  * Override to match your schema: 'workspaceId', 'tenantId', etc.
2638
2802
  */
2639
2803
  tenantField?: string | false;
2804
+ /**
2805
+ * Tenant-cleanup declaration — what `cascadeDeleteForOrganization`
2806
+ * does with this resource's rows when an organization is deleted.
2807
+ * Required for the resource to participate in the cascade; unflagged
2808
+ * resources are never touched.
2809
+ *
2810
+ * - `{ strategy: { type: 'hard' } }` — permanent delete (GDPR).
2811
+ * - `{ strategy: { type: 'soft' } }` — set `deleted: true` + `deletedAt`
2812
+ * (recoverable; pair with TTL for eventual hard-purge).
2813
+ * - `{ strategy: { type: 'anonymize', fields: { name: '[REDACTED]', email: null } } }`
2814
+ * — keep the row (legal retention) but clear PII linkage. HIPAA /
2815
+ * PCI / SOX-compatible. Field values can be static or `(doc) =>
2816
+ * value` for derived patches (hashes, etc.).
2817
+ * - `{ strategy: { type: 'skip', reason: 'audit-retained-per-SOX' } }`
2818
+ * — explicit opt-out with **mandatory** reason. Surfaces in audit reports.
2819
+ *
2820
+ * **Priority** — lower runs first. Default `100`. Use to land leaf data
2821
+ * before aggregate references:
2822
+ * - `10` : bulk leaf data (events, logs)
2823
+ * - `50` : business entities (orders, invoices)
2824
+ * - `100` : default
2825
+ *
2826
+ * Priority groups are barriers even under concurrency — all
2827
+ * priority-10 resources finish before any priority-50 starts.
2828
+ *
2829
+ * **Batch size** — rows per chunk for the underlying `purgeByField`
2830
+ * call. Default kit-specific (~1000). Tune for very large tenants.
2831
+ *
2832
+ * @example Compliance-retained financial ledger
2833
+ * ```ts
2834
+ * defineResource({
2835
+ * name: 'invoice',
2836
+ * tenantField: 'organizationId',
2837
+ * onTenantDelete: {
2838
+ * strategy: {
2839
+ * type: 'anonymize',
2840
+ * fields: { customerName: '[REDACTED]', customerEmail: null },
2841
+ * },
2842
+ * priority: 50,
2843
+ * },
2844
+ * });
2845
+ * ```
2846
+ */
2847
+ onTenantDelete?: OnTenantDeleteConfig;
2640
2848
  /**
2641
2849
  * Default sort applied to `list` responses when the request doesn't
2642
2850
  * specify one. Arc's built-in default is `-createdAt` (Mongo convention).
@@ -2678,6 +2886,28 @@ interface ResourceConfig<TDoc = AnyRecord> {
2678
2886
  skipValidation?: boolean;
2679
2887
  /** Don't register in introspection */
2680
2888
  skipRegistry?: boolean;
2889
+ /**
2890
+ * Per-resource MCP opt-out.
2891
+ *
2892
+ * - omitted / `true` (default) — resource may be surfaced by `mcpPlugin`,
2893
+ * subject to the plugin's `expose` / `include` / `exclude` selection.
2894
+ * - `false` — opt this resource OUT of MCP tool generation entirely.
2895
+ * Always wins over the plugin's `expose` / `include` allowlist;
2896
+ * keeps the opt-out colocated with the resource definition instead
2897
+ * of in a host-side blocklist that drifts as resources are added.
2898
+ *
2899
+ * Use the local opt-out for resources that should never expose tools
2900
+ * (internal back-office, audit-trail readers, system-managed entities).
2901
+ * Use the plugin-level `expose`/`include` allowlist when the cut is
2902
+ * cross-cutting (only a handful of resources should be agent-callable
2903
+ * across the whole app).
2904
+ *
2905
+ * @example
2906
+ * ```ts
2907
+ * defineResource({ name: 'internal-job-log', mcp: false, ... });
2908
+ * ```
2909
+ */
2910
+ mcp?: boolean;
2681
2911
  /** Internal: track applied presets */
2682
2912
  _appliedPresets?: string[];
2683
2913
  /** HTTP method for update routes. Default: 'PATCH' */
@@ -2718,6 +2948,39 @@ interface ResourceConfig<TDoc = AnyRecord> {
2718
2948
  };
2719
2949
  }
2720
2950
  //#endregion
2951
+ //#region src/core/defineResource/diagnostics.d.ts
2952
+ /**
2953
+ * Boot-time diagnostics produced by the `defineResource()` validation pipeline.
2954
+ *
2955
+ * `defineResource()` runs at module load — long before any Fastify instance
2956
+ * exists — so non-fatal warnings (redundant field-rule flags, ambiguous
2957
+ * preset combinations, etc.) cannot be emitted through a logger at the
2958
+ * point they are detected. Instead we COLLECT them into a structured
2959
+ * `ResourceDiagnostic[]`, attach the array to `ResourceDefinition._diagnostics`,
2960
+ * and flush each entry through `fastify.log.warn` on first mount inside
2961
+ * `buildResourcePlugin`. Hosts thus retain full control over framework
2962
+ * output (silencing, redirecting, structured logging) — the framework
2963
+ * never reaches for `console.*` directly outside of `src/cli/`.
2964
+ *
2965
+ * Hard errors continue to `throw` inside the validation pipeline — those
2966
+ * surface synchronously at define-time, which is the right UX for
2967
+ * "this resource will never work" failures.
2968
+ */
2969
+ /**
2970
+ * One non-fatal diagnostic produced during resource validation.
2971
+ *
2972
+ * - `severity`: log level the host logger uses (`warn` for misconfigurations
2973
+ * the host should clean up, `info` for deprecation hints).
2974
+ * - `code`: stable identifier for the diagnostic — hosts and tests can match
2975
+ * on this without parsing the human-readable message.
2976
+ * - `message`: pre-formatted line, resource name already interpolated.
2977
+ */
2978
+ interface ResourceDiagnostic {
2979
+ severity: "warn" | "info";
2980
+ code: string;
2981
+ message: string;
2982
+ }
2983
+ //#endregion
2721
2984
  //#region src/core/defineResource/ResourceDefinition.d.ts
2722
2985
  /**
2723
2986
  * Constructor input shape — `ResourceConfig` plus the metadata
@@ -2767,7 +3030,23 @@ declare class ResourceDefinition<TDoc = AnyRecord> {
2767
3030
  readonly pipe?: PipelineConfig;
2768
3031
  readonly fields?: FieldPermissionMap;
2769
3032
  readonly cache?: ResourceCacheConfig;
3033
+ /**
3034
+ * Per-resource MCP opt-out. `false` keeps the resource out of every
3035
+ * `mcpPlugin` registration regardless of the plugin's `expose` /
3036
+ * `include` allowlist — local opt-out is authoritative. See
3037
+ * `ResourceConfig.mcp` for the host-facing surface.
3038
+ */
3039
+ readonly mcp: boolean;
2770
3040
  readonly tenantField?: string | false;
3041
+ /** Tenant-cleanup strategy on org delete — see `OnTenantDeleteConfig`. */
3042
+ readonly onTenantDelete?: OnTenantDeleteConfig;
3043
+ /**
3044
+ * Resolved tenant-purge strategy — what `cascadeDeleteForOrganization`
3045
+ * actually runs. Computed once at boot from `onTenantDelete`. Audit /
3046
+ * introspection tooling reads this instead of re-running the rule at
3047
+ * the call site.
3048
+ */
3049
+ readonly resolvedTenantPurge: ResolvedTenantPurge;
2771
3050
  readonly idField?: string;
2772
3051
  readonly queryParser?: QueryParserInterface;
2773
3052
  readonly _appliedPresets: string[];
@@ -2778,6 +3057,17 @@ declare class ResourceDefinition<TDoc = AnyRecord> {
2778
3057
  priority: number;
2779
3058
  }>;
2780
3059
  _registryMeta?: RegisterOptions;
3060
+ /**
3061
+ * Boot-time validation diagnostics (non-fatal — hard errors throw
3062
+ * synchronously in `validateDefineResourceConfig`). Populated when
3063
+ * the host's config contains redundant / ambiguous flags that
3064
+ * shouldn't crash the boot but the host should clean up. Flushed
3065
+ * through `fastify.log.warn` on first mount inside
3066
+ * `buildResourcePlugin` so the host's configured logger owns the
3067
+ * output — the framework never speaks to `console.*` from `src/`
3068
+ * outside of the CLI.
3069
+ */
3070
+ _diagnostics?: ResourceDiagnostic[];
2781
3071
  /**
2782
3072
  * Per-host idempotency guard used by `buildResourcePlugin` to
2783
3073
  * skip duplicate shared-state writes when the same resource is
@@ -2852,8 +3142,25 @@ interface RouteRow {
2852
3142
  }
2853
3143
  declare class ResourceRegistry {
2854
3144
  private _resources;
3145
+ /**
3146
+ * Parallel map of full `DataAdapter` instances. The public `RegistryEntry.adapter`
3147
+ * field is intentionally narrowed to `{ type, name }` so introspection can be
3148
+ * JSON-serialized — but cascade / cleanup / migration helpers need the live
3149
+ * adapter (and its `.repository`) to do real work. Stored here, behind
3150
+ * `getAdapter(name)`, so the public metadata stays serializable and the
3151
+ * runtime-only handle is still reachable.
3152
+ */
3153
+ private _adapters;
2855
3154
  private _frozen;
2856
3155
  constructor();
3156
+ /**
3157
+ * Get the live `DataAdapter` for a registered resource — the handle whose
3158
+ * `.repository` cascade / cleanup helpers actually call. Returns `undefined`
3159
+ * when the resource is unknown OR was registered without an adapter
3160
+ * (service-only resources). Typed loosely (`unknown`-shaped fields) so
3161
+ * consumers cast to their kit's adapter type at the use site.
3162
+ */
3163
+ getAdapter<T = unknown>(name: string): T | undefined;
2857
3164
  /**
2858
3165
  * Register a resource
2859
3166
  */
@@ -2923,7 +3230,16 @@ declare class ResourceRegistry {
2923
3230
  */
2924
3231
  unfreeze(): void;
2925
3232
  /**
2926
- * Reset registry — clear all resources and unfreeze
3233
+ * Reset registry — clear all resources, drop their parallel live-adapter
3234
+ * handles, and unfreeze.
3235
+ *
3236
+ * The `_adapters` map (added in 2.15.5 so cascade / cleanup helpers can
3237
+ * reach `adapter.repository` after registration) must clear alongside
3238
+ * `_resources`. Pre-2.16 this method dropped the public entries but
3239
+ * left the live adapters dangling, so a test that called `reset()`
3240
+ * between cases would see ghost adapters and either (a) leak a live
3241
+ * Mongo connection across describe blocks or (b) `cascadeDeleteForOrganization`
3242
+ * iterate over a defunct registry entry. Clear both halves together.
2927
3243
  */
2928
3244
  reset(): void;
2929
3245
  /** @internal Alias for unfreeze() */
@@ -3306,6 +3622,21 @@ interface RegistryEntry extends ResourceMetadata {
3306
3622
  } | null;
3307
3623
  events?: string[];
3308
3624
  disableDefaultRoutes?: boolean;
3625
+ /**
3626
+ * 2.15.5 — multi-tenant scoping field declared on the resource
3627
+ * (defaults to `'organizationId'`; `false` for company-wide tables).
3628
+ * Surfaced so introspection / cascade helpers can scope deletes
3629
+ * without re-reading the resource definition.
3630
+ */
3631
+ tenantField?: string | false;
3632
+ /**
3633
+ * Resolved tenant-purge strategy — what arc actually runs when
3634
+ * `cascadeDeleteForOrganization` fires for this resource. Computed
3635
+ * at boot from the resource's `onTenantDelete` declaration. Surfaced
3636
+ * here so introspection / audit scripts can answer "what happens on
3637
+ * org-delete?" without re-reading the resource definition.
3638
+ */
3639
+ resolvedTenantPurge?: ResolvedTenantPurge;
3309
3640
  openApiSchemas?: OpenApiSchemas;
3310
3641
  registeredAt?: string;
3311
3642
  /** Field-level permissions metadata (for OpenAPI data) */
@@ -3340,7 +3671,15 @@ interface RegistryEntry extends ResourceMetadata {
3340
3671
  readonly name: string;
3341
3672
  readonly description?: string; /** Raw per-action schema (JSON Schema, Zod v4, or legacy field map) */
3342
3673
  readonly schema?: unknown; /** Per-action permission check (if different from resource-level `actionPermissions`) */
3343
- readonly permissions?: PermissionCheck; /** MCP tool generation flag — `false` to skip, object for overrides */
3674
+ readonly permissions?: PermissionCheck;
3675
+ /**
3676
+ * 2.15.5: mount point — `true` (default) for `POST /:id/action`,
3677
+ * `false` for `POST /action` (resource-root, no `:id` path param).
3678
+ * Consumed by registry enumeration, OpenAPI generation, and FE
3679
+ * resource manifests so callers can pick the right URL without
3680
+ * reading the action definition itself.
3681
+ */
3682
+ readonly id?: boolean; /** MCP tool generation flag — `false` to skip, object for overrides */
3344
3683
  readonly mcp?: boolean | {
3345
3684
  readonly description?: string;
3346
3685
  readonly annotations?: Record<string, unknown>;
@@ -3463,4 +3802,4 @@ interface ValidateOptions {
3463
3802
  strict?: boolean;
3464
3803
  }
3465
3804
  //#endregion
3466
- export { OpenApiSchemas as $, SoftDeleteMixin as $t, RequestIdOptions as A, afterCreate as An, Guard as At, defineResource as B, Authenticator as Bt, RequestContext as C, HookContext as Cn, AggregationConfig as Ct, HealthCheck as D, HookRegistration as Dn, AggregationMaterializedResult as Dt, GracefulShutdownOptions as E, HookPhase as En, AggregationMaterializedContext as Et, FastifyWithDecorators as F, beforeUpdate as Fn, PipelineContext as Ft, ActionsMap as G, ApiResponse as Gt, ActionDefinition as H, JwtContext as Ht, MiddlewareHandler as I, createHookSystem as In, PipelineStep as It, CrudRouteKey as J, ObjectId as Jt, ArcFieldRule as K, ArcRequest as Kt, RequestWithExtras as L, defineHook as Ln, Transform as Lt, EventsDecorator as M, afterUpdate as Mn, NextFunction as Mt, FastifyRequestExtras as N, beforeCreate as Nn, OperationFilter as Nt, HealthOptions as O, HookSystem as On, AggregationRateLimit as Ot, FastifyWithAuth as P, beforeDelete as Pn, PipelineConfig as Pt, MiddlewareConfig as Q, SoftDeleteExt as Qt, RegisterOptions as R, AuthHelpers as Rt, QueryParserInterface as S, DefineHookOptions as Sn, AggregationCacheConfig as St, CrudRouterOptions as T, HookOperation as Tn, AggregationIndexHint as Tt, ActionEntry as U, TokenPair as Ut, ResourceDefinition as V, AuthenticatorContext as Vt, ActionHandlerFn as W, AnyRecord as Wt, EventDefinition as X, UserOrganization as Xt, CrudSchemas as Y, UserLike as Yt, FieldRule$1 as Z, BaseController as Zt, ControllerQueryOptions as _, ListResult as _n, IControllerResponse as _t, InferAdapterDoc as a, BulkMixin as an, ResourceConfig as at, ParsedQuery as b, AccessControl as bn, AggMeasureInput as bt, TypedController as c, ControllerConfigurableOptions as cn, ResourcePermissions as ct, PaginationResult as d, QueryResolverConfig as dn, RouteMethod as dt, TreeExt as en, PresetFunction as et, IntrospectionData as f, ArcCreateResult as fn, RouteSchemaOptions as ft, ArcInternalMetadata as g, ArcUpdateResult as gn, IController as gt, ResourceMetadata as h, ArcListResult as hn, FastifyHandler as ht, ValidationResult as i, BulkExt as in, ResourceCacheConfig as it, ArcDecorator as j, afterDelete as jn, Interceptor as jt, IntrospectionPluginOptions as k, HookSystemOptions as kn, AggregationsMap as kt, TypedRepository as l, ControllerConstructionOptions as ln, RouteDefinition as lt, RegistryStats as m, ArcGetResult as mn, ControllerLike as mt, ConfigError as n, SlugExt as nn, PresetResult as nt, InferDocType as o, BaseControllerOptions as on, ResourceHookContext as ot, RegistryEntry as p, ArcDeleteResult as pn, ControllerHandler as pt, CrudController as q, JWTPayload as qt, ValidateOptions as r, SlugMixin as rn, RateLimitConfig as rt, InferResourceDoc as s, BaseCrudController as sn, ResourceHooks as st, RouteHandlerMethod$1 as t, TreeMixin as tn, PresetHook as tt, TypedResourceConfig as u, QueryResolver as un, RouteMcpConfig as ut, LookupOption as v, BodySanitizer as vn, IRequestContext as vt, ServiceContext as w, HookHandler as wn, AggregationDateRangeRequirement as wt, PopulateOption as x, AccessControlConfig as xn, AggMeasureShorthand as xt, OwnershipCheck as y, BodySanitizerConfig as yn, RouteHandler as yt, ResourceRegistry as z, AuthPluginOptions as zt };
3805
+ 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 SoftDeleteMixin, A as RequestIdOptions, B as defineResource, C as RequestContext, Ct as AggregationConfig, D as HealthCheck, Dt as AggregationMaterializedResult, E as GracefulShutdownOptions, Et as AggregationMaterializedContext, F as FastifyWithDecorators, Gt as ApiResponse, J as CrudRouteKey, Kt as ArcRequest, L as RequestWithExtras, N as FastifyRequestExtras, O as HealthOptions, Ot as AggregationRateLimit, P as FastifyWithAuth, Q as MiddlewareConfig, Qt as SoftDeleteExt, S as QueryParserInterface, St as AggregationCacheConfig, T as CrudRouterOptions, Tt as AggregationIndexHint, V as ResourceDefinition, Wt as AnyRecord, X as EventDefinition, Xt as UserOrganization, Y as CrudSchemas, Z as FieldRule, Zt as BaseController, _n as ListResult, _t as IControllerResponse, a as InferAdapterDoc, an as BulkMixin, at as ResourceConfig, bt as AggMeasureInput, c as TypedController, cn as ControllerConfigurableOptions, d as PaginationResult, en as TreeExt, et as PresetFunction, f as IntrospectionData, fn as ArcCreateResult, ft as RouteSchemaOptions, g as ArcInternalMetadata, gn as ArcUpdateResult, gt as IController, h as ResourceMetadata, hn as ArcListResult, i as ValidationResult, in as BulkExt, k as IntrospectionPluginOptions, kt as AggregationsMap, l as TypedRepository, ln as ControllerConstructionOptions, m as RegistryStats, mn as ArcGetResult, mt as ControllerLike, n as ConfigError, nn as SlugExt, nt as PresetResult, o as InferDocType, on as BaseControllerOptions, p as RegistryEntry, pn as ArcDeleteResult, q as CrudController, qt as JWTPayload, r as ValidateOptions, rn as SlugMixin, rt as RateLimitConfig, s as InferResourceDoc, sn as BaseCrudController, t as RouteHandlerMethod, tn as TreeMixin, u as TypedResourceConfig, vt as IRequestContext, w as ServiceContext, wt as AggregationDateRangeRequirement, xt as AggMeasureShorthand, y as OwnershipCheck, yt as RouteHandler, zt as AuthPluginOptions } from "./index-BswOSJCE.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-COhcH3fk.mjs";
3
- import { A as MAX_SEARCH_LENGTH, C as DEFAULT_UPDATE_METHOD, D as HookPhase, E as HookOperation, M as MutationOperation, N as RESERVED_QUERY_PARAMS, O as MAX_FILTER_DEPTH, P as SYSTEM_FIELDS, S as DEFAULT_TENANT_FIELD, T as HOOK_PHASES, _ as CrudOperation, b as DEFAULT_MAX_LIMIT, f as defineResourceVariants, g as CRUD_OPERATIONS, h as defineAggregation, j as MUTATION_OPERATIONS, k as MAX_REGEX_LENGTH, s as getControllerScope, v as DEFAULT_ID_FIELD, w as HOOK_OPERATIONS, x as DEFAULT_SORT, y as DEFAULT_LIMIT } from "./index-BstGxcc3.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-BTqLEvhu.mjs";
5
- import { ct as NotFoundError, ht as createDomainError, it as ArcError, mt as ValidationError, pt as UnauthorizedError, st as ForbiddenError, t as getUserId } from "./index-bRjYu21O.mjs";
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-CkW0flkU.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-Anj0xdih.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-B-ulKx5P.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-3oIimXQn.mjs";
5
+ import { a as NotFoundError, d as ValidationError, f as createDomainError, i as ForbiddenError, t as ArcError, u as UnauthorizedError } from "./errors-C1lX_jlm.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, getUserId, ownerWithAdminBypass, presets_d_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, version, when };
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 };
package/dist/index.mjs CHANGED
@@ -1,11 +1,10 @@
1
- import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "./constants-Cxde4rpC.mjs";
1
+ import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "./constants-TrJVIJl0.mjs";
2
2
  import { d as createDomainError, i as NotFoundError, l as UnauthorizedError, r as ForbiddenError, t as ArcError, u as ValidationError } from "./errors-j4aJm1Wg.mjs";
3
- import { t as getUserId } from "./utils-_h9B3c57.mjs";
4
- import { a as BulkMixin, i as SlugMixin, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, t as BaseController } from "./BaseController-dx3m2J8V.mjs";
5
- import { C as allowPublic, D as requireAuth, O as requireOwnership, S as allOf, T as denyAll, _ as requireOrgMembership, a as presets_exports, b as requireServiceScope, c as readOnly, d as applyFieldWritePermissions, f as fields, g as requireOrgInScope, h as createOrgPermissions, i as ownerWithAdminBypass, j as when, k as requireRoles, m as createDynamicPermissionMatrix, n as authenticated, o as publicRead, r as fullPublic, s as publicReadAdminWrite, t as adminOnly, u as applyFieldReadPermissions, v as requireOrgRole, w as anyOf, x as requireTeamMembership, y as requireScopeContext } from "./permissions-ohQyv50e.mjs";
6
- import { v as getControllerScope } from "./routerShared-DrOa-26E.mjs";
7
- import { a as defineResource, i as defineResourceVariants, l as defineAggregation, o as ResourceDefinition } from "./core-CvmOqEms.mjs";
3
+ import { a as BulkMixin, i as SlugMixin, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, t as BaseController } from "./BaseController-DlCCTIxJ.mjs";
4
+ import { C as allowPublic, D as requireAuth, O as requireOwnership, S as allOf, T as denyAll, _ as requireOrgMembership, a as presets_exports, b as requireServiceScope, c as readOnly, d as applyFieldWritePermissions, f as fields, g as requireOrgInScope, h as createOrgPermissions, i as ownerWithAdminBypass, j as when, k as requireRoles, m as createDynamicPermissionMatrix, n as authenticated, o as publicRead, r as fullPublic, s as publicReadAdminWrite, t as adminOnly, u as applyFieldReadPermissions, v as requireOrgRole, w as anyOf, x as requireTeamMembership, y as requireScopeContext } from "./permissions-CTxMrreC.mjs";
5
+ import { v as getControllerScope } from "./routerShared-CZV5aabX.mjs";
6
+ import { a as defineResource, i as defineResourceVariants, o as ResourceDefinition, s as defineAction, u as defineAggregation } from "./core-DBJ_j6rX.mjs";
8
7
  //#region src/index.ts
9
- const version = "2.15.4";
8
+ const version = "2.16.0";
10
9
  //#endregion
11
- export { ArcError, BaseController, BaseCrudController, BulkMixin, CRUD_OPERATIONS, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, ForbiddenError, HOOK_OPERATIONS, HOOK_PHASES, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, NotFoundError, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugMixin, SoftDeleteMixin, TreeMixin, UnauthorizedError, ValidationError, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, createDomainError, createDynamicPermissionMatrix, createOrgPermissions, defineAggregation, defineResource, defineResourceVariants, denyAll, fields, fullPublic, getControllerScope, getUserId, ownerWithAdminBypass, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, version, when };
10
+ export { ArcError, BaseController, BaseCrudController, BulkMixin, CRUD_OPERATIONS, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, ForbiddenError, HOOK_OPERATIONS, HOOK_PHASES, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, NotFoundError, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugMixin, SoftDeleteMixin, TreeMixin, UnauthorizedError, ValidationError, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, createDomainError, createDynamicPermissionMatrix, createOrgPermissions, defineAction, defineAggregation, defineResource, defineResourceVariants, denyAll, fields, fullPublic, getControllerScope, ownerWithAdminBypass, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, version, when };
@@ -0,0 +1,71 @@
1
+ //#region src/cli/commands/init/types.d.ts
2
+ /**
3
+ * Shared types for the `arc init` scaffolder.
4
+ *
5
+ * `InitOptions` is the public CLI surface (everything callers can pass);
6
+ * `ProjectConfig` is the post-prompt resolved shape every template
7
+ * consumes. Keeping them separate lets the CLI surface evolve (more
8
+ * optional flags) without forcing every template to inspect optionality.
9
+ */
10
+ type PackageManager = "npm" | "pnpm" | "yarn" | "bun";
11
+ interface InitOptions {
12
+ name?: string;
13
+ adapter?: "mongokit" | "custom";
14
+ auth?: "jwt" | "better-auth";
15
+ tenant?: "multi" | "single";
16
+ /**
17
+ * Enable Better Auth's `apiKey` plugin (`@better-auth/api-key`) for
18
+ * machine-to-machine authentication alongside cookie/session auth.
19
+ * Only used when `auth === 'better-auth'`. Default: false.
20
+ */
21
+ apiKey?: boolean;
22
+ /**
23
+ * Session strategy when using Better Auth.
24
+ * - `cookie` (default): browser cookie + DB-backed session (BA's default)
25
+ * - `bearer`: Authorization: Bearer header (mobile apps, SPA, M2M)
26
+ * Both can coexist — `bearer: true` adds bearer alongside cookies.
27
+ */
28
+ session?: "cookie" | "bearer" | "both";
29
+ typescript?: boolean;
30
+ edge?: boolean;
31
+ /**
32
+ * Emit Dockerfile / .dockerignore / docker-compose.yml in the scaffold.
33
+ *
34
+ * 2.16: defaults to `false`. Docker / deployment topology is an
35
+ * app-level concern — many hosts ship to Cloud Run / Fly / Vercel /
36
+ * AWS Lambda / Cloudflare Workers / their own Kubernetes manifests
37
+ * and don't want arc's opinionated Docker assets cluttering the repo
38
+ * (the framework rule is "don't dictate deployment"). Opt in with
39
+ * `--docker` when you genuinely want arc's Compose-based dev setup.
40
+ *
41
+ * `edge: true` continues to imply no Docker (Workers don't run in
42
+ * containers) — the flag is ignored when `edge` is set.
43
+ */
44
+ docker?: boolean;
45
+ skipInstall?: boolean;
46
+ force?: boolean;
47
+ }
48
+ interface ProjectConfig {
49
+ name: string;
50
+ adapter: "mongokit" | "custom";
51
+ auth: "jwt" | "better-auth";
52
+ tenant: "multi" | "single";
53
+ apiKey: boolean;
54
+ session: "cookie" | "bearer" | "both";
55
+ typescript: boolean;
56
+ edge: boolean;
57
+ /** Resolved opt-in for Docker scaffolding — see `InitOptions.docker`. */
58
+ docker: boolean;
59
+ }
60
+ interface DependencyManifest {
61
+ dependencies: Record<string, string>;
62
+ devDependencies: Record<string, string>;
63
+ }
64
+ //#endregion
65
+ //#region src/cli/commands/init/index.d.ts
66
+ /**
67
+ * Initialize a new Arc project.
68
+ */
69
+ declare function init(options?: InitOptions): Promise<void>;
70
+ //#endregion
71
+ export { ProjectConfig as a, PackageManager as i, DependencyManifest as n, InitOptions as r, init as t };