@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,2 +1,2 @@
1
- import { a as UpstashRedisLike, i as RedisIdempotencyStoreOptions, n as RedisClient, o as ioredisAsIdempotencyClient, r as RedisIdempotencyStore, s as upstashAsIdempotencyClient, t as IoredisLike } from "../redis-DiMkdHEl.mjs";
1
+ import { a as UpstashRedisLike, i as RedisIdempotencyStoreOptions, n as RedisClient, o as ioredisAsIdempotencyClient, r as RedisIdempotencyStore, s as upstashAsIdempotencyClient, t as IoredisLike } from "../redis-Cyzrz6SX.mjs";
2
2
  export { type IoredisLike, type RedisClient, RedisIdempotencyStore, type RedisIdempotencyStoreOptions, type UpstashRedisLike, ioredisAsIdempotencyClient, upstashAsIdempotencyClient };
@@ -1,6 +1,6 @@
1
- import { r as CacheStore, t as CacheLogger } from "./interface-beEtJyWM.mjs";
2
- import { i as RequestScope, n as Mandate } from "./types-CTYvcwHe.mjs";
3
- import { c as PermissionCheck, l as PermissionContext, u as PermissionResult } from "./fields-COhcH3fk.mjs";
1
+ import { r as CacheStore, t as CacheLogger } from "./interface-CH0OQudo.mjs";
2
+ import { i as RequestScope, n as Mandate } from "./types-DVfpSfx2.mjs";
3
+ import { c as PermissionCheck, l as PermissionContext, u as PermissionResult } from "./fields-Anj0xdih.mjs";
4
4
  import { FastifyReply, FastifyRequest } from "fastify";
5
5
 
6
6
  //#region src/permissions/agent.d.ts
@@ -625,33 +625,33 @@ declare namespace presets_d_exports {
625
625
  /**
626
626
  * ResourcePermissions shape — matches the type in types/index.ts
627
627
  */
628
- interface ResourcePermissions<TDoc = any> {
628
+ interface ResourcePermissions<TDoc = Record<string, unknown>> {
629
629
  list?: PermissionCheck<TDoc>;
630
630
  get?: PermissionCheck<TDoc>;
631
631
  create?: PermissionCheck<TDoc>;
632
632
  update?: PermissionCheck<TDoc>;
633
633
  delete?: PermissionCheck<TDoc>;
634
634
  }
635
- type PermissionOverrides<TDoc = any> = Partial<ResourcePermissions<TDoc>>;
635
+ type PermissionOverrides<TDoc = Record<string, unknown>> = Partial<ResourcePermissions<TDoc>>;
636
636
  /**
637
637
  * Public read, authenticated write.
638
638
  * list + get = allowPublic(), create + update + delete = requireAuth()
639
639
  */
640
- declare function publicRead<TDoc = any>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
640
+ declare function publicRead<TDoc = Record<string, unknown>>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
641
641
  /**
642
642
  * Public read, admin write.
643
643
  * list + get = allowPublic(), create + update + delete = requireRoles(['admin'])
644
644
  */
645
- declare function publicReadAdminWrite<TDoc = any>(roles?: readonly string[], overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
645
+ declare function publicReadAdminWrite<TDoc = Record<string, unknown>>(roles?: readonly string[], overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
646
646
  /**
647
647
  * All operations require authentication.
648
648
  */
649
- declare function authenticated<TDoc = any>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
649
+ declare function authenticated<TDoc = Record<string, unknown>>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
650
650
  /**
651
651
  * All operations require specific roles.
652
652
  * @param roles - Required roles (user needs at least one). Default: ['admin']
653
653
  */
654
- declare function adminOnly<TDoc = any>(roles?: readonly string[], overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
654
+ declare function adminOnly<TDoc = Record<string, unknown>>(roles?: readonly string[], overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
655
655
  /**
656
656
  * Owner-scoped with admin bypass.
657
657
  * list = auth (scoped to owner), get = auth, create = auth,
@@ -660,16 +660,16 @@ declare function adminOnly<TDoc = any>(roles?: readonly string[], overrides?: Pe
660
660
  * @param ownerField - Field containing owner ID (default: 'userId')
661
661
  * @param bypassRoles - Roles that bypass ownership check (default: ['admin'])
662
662
  */
663
- declare function ownerWithAdminBypass<TDoc = any>(ownerField?: Extract<keyof TDoc, string> | string, bypassRoles?: readonly string[], overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
663
+ declare function ownerWithAdminBypass<TDoc = Record<string, unknown>>(ownerField?: Extract<keyof TDoc, string> | string, bypassRoles?: readonly string[], overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
664
664
  /**
665
665
  * Full public access — no auth required for any operation.
666
666
  * Use sparingly (dev/testing, truly public APIs).
667
667
  */
668
- declare function fullPublic<TDoc = any>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
668
+ declare function fullPublic<TDoc = Record<string, unknown>>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
669
669
  /**
670
670
  * Read-only: list + get authenticated, write operations denied.
671
671
  * Useful for computed/derived resources.
672
672
  */
673
- declare function readOnly<TDoc = any>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
673
+ declare function readOnly<TDoc = Record<string, unknown>>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
674
674
  //#endregion
675
675
  export { requireRoles as A, allOf as C, not as D, denyAll as E, RequireAgentScopeOptions as F, RequireMandateOptions as I, requireAgentScope as L, when as M, applyPermissionResult as N, requireAuth as O, normalizePermissionResult as P, requireDPoP as R, createOrgPermissions as S, anyOf as T, ConnectEventsOptions as _, presets_d_exports as a, PermissionEventBus as b, readOnly as c, requireOrgRole as d, requireScopeContext as f, createRoleHierarchy as g, RoleHierarchy as h, ownerWithAdminBypass as i, roles as j, requireOwnership as k, requireOrgInScope as l, requireTeamMembership as m, authenticated as n, publicRead as o, requireServiceScope as p, fullPublic as r, publicReadAdminWrite as s, adminOnly as t, requireOrgMembership as u, DynamicPermissionMatrix as v, allowPublic as w, createDynamicPermissionMatrix as x, DynamicPermissionMatrixConfig as y, requireMandate as z };
@@ -1,7 +1,8 @@
1
- import { C as RequestContext, Ct as AggregationConfig, F as FastifyWithDecorators, K as ArcFieldRule, L as RequestWithExtras, T as CrudRouterOptions, V as ResourceDefinition, Wt as AnyRecord, _t as IControllerResponse, at as ResourceConfig, ft as RouteSchemaOptions, gt as IController, q as CrudController, vt as IRequestContext } from "./index-BswOSJCE.mjs";
2
- import { i as RequestScope } from "./types-CTYvcwHe.mjs";
3
- import { c as PermissionCheck } from "./fields-COhcH3fk.mjs";
1
+ import { C as RequestContext, F as FastifyWithDecorators, H as ActionDefinition, K as ArcFieldRule, Kt as AnyRecord, L as RequestWithExtras, T as CrudRouterOptions, Tt as AggregationConfig, V as ResourceDefinition, bt as IRequestContext, ft as RouteMcpConfig, mt as RouteSchemaOptions, q as CrudController, st as ResourceConfig, vt as IController, yt as IControllerResponse } from "./index-CkW0flkU.mjs";
2
+ import { i as RequestScope } from "./types-DVfpSfx2.mjs";
3
+ import { c as PermissionCheck } from "./fields-Anj0xdih.mjs";
4
4
  import { FastifyReply, FastifyRequest, RouteHandlerMethod } from "fastify";
5
+ import { z } from "zod";
5
6
  import { AggDateBucket, AggMeasure, AggTopN } from "@classytic/repo-core/repository";
6
7
  import { LookupSpec } from "@classytic/repo-core/lookup";
7
8
 
@@ -51,6 +52,12 @@ declare const MAX_FILTER_DEPTH: 10;
51
52
  /**
52
53
  * Query parameters consumed by the framework — never treated as filters.
53
54
  * Shared by all query parsers (Arc built-in, Prisma, custom).
55
+ *
56
+ * `filter` is reserved so the bracket-wrapped form
57
+ * (`?filter[foo.bar]=X` / `?filter[price][gte]=40`) lands as the parser's
58
+ * canonical filter envelope instead of being attempted as a flat field
59
+ * filter. See `ArcQueryParser.parseFilters()` for the unwrap step that
60
+ * merges `q.filter[*]` back into the top-level filter map.
54
61
  */
55
62
  declare const RESERVED_QUERY_PARAMS: Readonly<Set<string>>;
56
63
  //#endregion
@@ -116,6 +123,50 @@ declare function createCrudRouter<TDoc = unknown>(fastify: FastifyWithDecorators
116
123
  */
117
124
  declare function createPermissionMiddleware(permission: PermissionCheck, resourceName: string, action: string): RouteHandlerMethod | null;
118
125
  //#endregion
126
+ //#region src/core/defineAction.d.ts
127
+ /**
128
+ * Config for `defineAction()`. `TSchema` is the literal Zod schema type
129
+ * captured from the call site; `TData` is its `z.infer` projection.
130
+ * Plain JSON-Schema entries skip the inference path entirely (they go
131
+ * through the untyped `ActionDefinition` form).
132
+ */
133
+ interface DefineActionConfig<TSchema extends z.ZodTypeAny | undefined = undefined, TData = (TSchema extends z.ZodTypeAny ? z.infer<TSchema> : Record<string, unknown>)> {
134
+ /** Per-action body schema (Zod v4). Drives both AJV validation and the typed `data` param. */
135
+ schema?: TSchema;
136
+ /** Per-action permission gate. Falls back to resource-level if omitted. */
137
+ permissions?: PermissionCheck;
138
+ /** OpenAPI / MCP description. */
139
+ description?: string;
140
+ /**
141
+ * Mount point — `true` (default) for `POST /<prefix>/:id/action`,
142
+ * `false` for `POST /<prefix>/action` (no `:id`, for propose/search/
143
+ * bulk-style actions).
144
+ */
145
+ id?: boolean;
146
+ /** MCP tool generation flag — `false` to skip, object for explicit overrides. */
147
+ mcp?: boolean | RouteMcpConfig;
148
+ /**
149
+ * Typed handler. `data` is inferred from `schema` — declare both and
150
+ * the compiler catches `data.stagId` typos at the use site.
151
+ *
152
+ * Handlers return arbitrary values; arc wraps them in
153
+ * `IControllerResponse` and ships them through `sendControllerResponse`
154
+ * just like the untyped `ActionDefinition.handler` does.
155
+ */
156
+ handler: (id: string, data: TData, req: RequestWithExtras) => Promise<unknown>;
157
+ }
158
+ /**
159
+ * Build an `ActionDefinition` with a typed handler. The literal schema
160
+ * type captured here flows into `data`, so `defineAction({ schema:
161
+ * z.object({...}), handler })` produces fully-typed code with no
162
+ * `as MyShape` cast.
163
+ *
164
+ * Behaviorally identical to a bare `ActionDefinition` object — same
165
+ * validation path (AJV), same permission resolution, same MCP wiring.
166
+ * The runtime shape is unchanged; only the type-level inference is new.
167
+ */
168
+ declare function defineAction<TSchema extends z.ZodTypeAny | undefined = undefined>(config: DefineActionConfig<TSchema>): ActionDefinition;
169
+ //#endregion
119
170
  //#region src/core/defineResourceVariants.d.ts
120
171
  /**
121
172
  * Required identity fields for each variant. The user MUST provide a unique
@@ -273,4 +324,4 @@ declare function isFieldReadable(rule: ArcFieldRule | undefined): boolean;
273
324
  */
274
325
  declare function collectReadBlockedFields(schemaOptions: RouteSchemaOptions | undefined): Set<string> | null;
275
326
  //#endregion
276
- export { MAX_SEARCH_LENGTH as A, DEFAULT_UPDATE_METHOD as C, HookPhase as D, HookOperation as E, MutationOperation as M, RESERVED_QUERY_PARAMS as N, MAX_FILTER_DEPTH as O, SYSTEM_FIELDS as P, DEFAULT_TENANT_FIELD as S, HOOK_PHASES as T, CrudOperation as _, createRequestContext as a, DEFAULT_MAX_LIMIT as b, sendControllerResponse as c, getEntityQuery as d, defineResourceVariants as f, CRUD_OPERATIONS as g, defineAggregation as h, createFastifyHandler as i, MUTATION_OPERATIONS as j, MAX_REGEX_LENGTH as k, getEntityId as l, createPermissionMiddleware as m, isFieldReadable as n, getControllerContext as o, createCrudRouter as p, createCrudHandlers as r, getControllerScope as s, collectReadBlockedFields as t, getEntityIdField as u, DEFAULT_ID_FIELD as v, HOOK_OPERATIONS as w, DEFAULT_SORT as x, DEFAULT_LIMIT as y };
327
+ export { MAX_FILTER_DEPTH as A, DEFAULT_SORT as C, HOOK_PHASES as D, HOOK_OPERATIONS as E, RESERVED_QUERY_PARAMS as F, SYSTEM_FIELDS as I, MAX_SEARCH_LENGTH as M, MUTATION_OPERATIONS as N, HookOperation as O, MutationOperation as P, DEFAULT_MAX_LIMIT as S, DEFAULT_UPDATE_METHOD as T, defineAggregation as _, createRequestContext as a, DEFAULT_ID_FIELD as b, sendControllerResponse as c, getEntityQuery as d, defineResourceVariants as f, createPermissionMiddleware as g, createCrudRouter as h, createFastifyHandler as i, MAX_REGEX_LENGTH as j, HookPhase as k, getEntityId as l, defineAction as m, isFieldReadable as n, getControllerContext as o, DefineActionConfig as p, createCrudHandlers as r, getControllerScope as s, collectReadBlockedFields as t, getEntityIdField as u, CRUD_OPERATIONS as v, DEFAULT_TENANT_FIELD as w, DEFAULT_LIMIT as x, CrudOperation as y };