@classytic/arc 2.11.3 → 2.13.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.
Files changed (185) hide show
  1. package/README.md +27 -18
  2. package/dist/{BaseController-swXruJ2_.mjs → BaseController-DX_T-bDB.mjs} +388 -423
  3. package/dist/EventTransport-CT_52aWU.d.mts +34 -0
  4. package/dist/EventTransport-DLWoUMHy.mjs +103 -0
  5. package/dist/{QueryCache-DOBNHBE0.d.mts → QueryCache-D41bfdBB.d.mts} +1 -1
  6. package/dist/{ResourceRegistry-DkAeAuTX.mjs → ResourceRegistry-CTERg_2x.mjs} +139 -66
  7. package/dist/audit/index.d.mts +2 -2
  8. package/dist/audit/index.mjs +1 -1
  9. package/dist/auth/audit.d.mts +199 -0
  10. package/dist/auth/audit.mjs +288 -0
  11. package/dist/auth/index.d.mts +5 -5
  12. package/dist/auth/index.mjs +117 -191
  13. package/dist/auth/redis-session.d.mts +1 -1
  14. package/dist/{betterAuthOpenApi-DwxtK3uG.mjs → betterAuthOpenApi--M_i87dQ.mjs} +1 -1
  15. package/dist/buildHandler-olo-gt94.mjs +610 -0
  16. package/dist/cache/index.d.mts +3 -3
  17. package/dist/cache/index.mjs +3 -3
  18. package/dist/cli/commands/describe.d.mts +89 -13
  19. package/dist/cli/commands/describe.mjs +56 -2
  20. package/dist/cli/commands/docs.mjs +2 -2
  21. package/dist/cli/commands/generate.mjs +147 -48
  22. package/dist/cli/commands/init.d.mts +13 -0
  23. package/dist/cli/commands/init.mjs +237 -112
  24. package/dist/cli/commands/introspect.mjs +8 -1
  25. package/dist/context/index.mjs +1 -1
  26. package/dist/core/index.d.mts +3 -3
  27. package/dist/core/index.mjs +5 -5
  28. package/dist/core-D72ia0EH.mjs +1399 -0
  29. package/dist/{createActionRouter-u3ql2EDo.mjs → createActionRouter-CEvzKcy8.mjs} +7 -20
  30. package/dist/createAggregationRouter-CyecOxnO.mjs +114 -0
  31. package/dist/{createApp-BFxtdKy6.mjs → createApp-XX2-N0Yd.mjs} +31 -27
  32. package/dist/defineEvent-D5h7EvAx.mjs +188 -0
  33. package/dist/docs/index.d.mts +2 -2
  34. package/dist/docs/index.mjs +2 -2
  35. package/dist/{elevation-DOFoxoDs.mjs → elevation-DgoeTyfX.mjs} +1 -1
  36. package/dist/errorHandler-Bk-AGhkU.mjs +174 -0
  37. package/dist/errorHandler-DFr45ZG4.d.mts +45 -0
  38. package/dist/errors-j4aJm1Wg.mjs +184 -0
  39. package/dist/{eventPlugin-KrFIQ097.mjs → eventPlugin-CaKTYkYM.mjs} +35 -137
  40. package/dist/{eventPlugin-CUNjYYRY.d.mts → eventPlugin-qXpqTebY.d.mts} +57 -7
  41. package/dist/events/index.d.mts +164 -5
  42. package/dist/events/index.mjs +133 -209
  43. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  44. package/dist/events/transports/redis-stream-entry.mjs +204 -31
  45. package/dist/events/transports/redis.d.mts +1 -1
  46. package/dist/factory/index.d.mts +2 -2
  47. package/dist/factory/index.mjs +2 -2
  48. package/dist/{fields-C8Y0XLAu.d.mts → fields-COhcH3fk.d.mts} +23 -2
  49. package/dist/hooks/index.d.mts +1 -1
  50. package/dist/hooks/index.mjs +1 -1
  51. package/dist/idempotency/index.d.mts +3 -3
  52. package/dist/idempotency/index.mjs +1 -20
  53. package/dist/idempotency/redis.d.mts +1 -1
  54. package/dist/idempotency/redis.mjs +1 -1
  55. package/dist/{index-BYCqHCVu.d.mts → index-BTqLEvhu.d.mts} +164 -4
  56. package/dist/{index-6u4_Gg6G.d.mts → index-BtW7qYwa.d.mts} +661 -281
  57. package/dist/{index-BdXnTPRj.d.mts → index-Ds61mrJE.d.mts} +50 -4
  58. package/dist/{index-DdQ3O9Pg.d.mts → index-Dz5IKsrE.d.mts} +360 -219
  59. package/dist/index.d.mts +6 -7
  60. package/dist/index.mjs +9 -10
  61. package/dist/integrations/event-gateway.d.mts +2 -2
  62. package/dist/integrations/event-gateway.mjs +1 -1
  63. package/dist/integrations/index.d.mts +2 -2
  64. package/dist/integrations/mcp/index.d.mts +2 -2
  65. package/dist/integrations/mcp/index.mjs +1 -1
  66. package/dist/integrations/mcp/testing.d.mts +1 -1
  67. package/dist/integrations/mcp/testing.mjs +1 -1
  68. package/dist/integrations/streamline.d.mts +60 -11
  69. package/dist/integrations/streamline.mjs +75 -85
  70. package/dist/integrations/websocket-redis.d.mts +1 -1
  71. package/dist/integrations/websocket.d.mts +1 -1
  72. package/dist/integrations/websocket.mjs +2 -8
  73. package/dist/middleware/index.d.mts +1 -1
  74. package/dist/middleware/index.mjs +2 -2
  75. package/dist/migrations/index.d.mts +23 -3
  76. package/dist/migrations/index.mjs +0 -7
  77. package/dist/{multipartBody-CvTR1Un6.mjs → multipartBody-BOvVSVCD.mjs} +11 -8
  78. package/dist/{openapi-BGUn7Ki1.mjs → openapi-CiOMVW1p.mjs} +143 -13
  79. package/dist/org/index.d.mts +2 -2
  80. package/dist/org/index.mjs +1 -1
  81. package/dist/permissions/index.d.mts +3 -3
  82. package/dist/permissions/index.mjs +3 -3
  83. package/dist/{permissions-gd_aUWrR.mjs → permissions-ohQyv50e.mjs} +404 -176
  84. package/dist/{pipe-DVoIheVC.mjs → pipe-Zr0KXjQe.mjs} +1 -1
  85. package/dist/pipeline/index.d.mts +1 -1
  86. package/dist/pipeline/index.mjs +1 -1
  87. package/dist/plugins/index.d.mts +18 -33
  88. package/dist/plugins/index.mjs +33 -13
  89. package/dist/plugins/response-cache.mjs +1 -1
  90. package/dist/plugins/tracing-entry.d.mts +1 -1
  91. package/dist/plugins/tracing-entry.mjs +1 -1
  92. package/dist/presets/filesUpload.d.mts +5 -5
  93. package/dist/presets/filesUpload.mjs +6 -9
  94. package/dist/presets/index.d.mts +1 -1
  95. package/dist/presets/index.mjs +1 -1
  96. package/dist/presets/multiTenant.d.mts +1 -1
  97. package/dist/presets/multiTenant.mjs +2 -2
  98. package/dist/presets/search.d.mts +2 -2
  99. package/dist/presets/search.mjs +6 -8
  100. package/dist/{presets-Z7P5w4gF.mjs → presets-BbkjdPeH.mjs} +6 -28
  101. package/dist/{queryCachePlugin-BUXBSm4F.d.mts → queryCachePlugin-CqMdLI2-.d.mts} +2 -2
  102. package/dist/{queryCachePlugin-Bq6bO6vc.mjs → queryCachePlugin-m1XsgAIJ.mjs} +3 -3
  103. package/dist/{redis-Cm1gnRDf.d.mts → redis-DiMkdHEl.d.mts} +1 -1
  104. package/dist/redis-stream-D6HzR1Z_.d.mts +232 -0
  105. package/dist/registry/index.d.mts +1 -1
  106. package/dist/registry/index.mjs +2 -2
  107. package/dist/{replyHelpers-ByllIXXV.mjs → replyHelpers-CK-FNO8E.mjs} +3 -21
  108. package/dist/{resourceToTools-ByZpgjeH.mjs → resourceToTools-C5coh64w.mjs} +224 -71
  109. package/dist/{routerShared-BqLRb5l7.mjs → routerShared-D6_fEGHh.mjs} +40 -36
  110. package/dist/{schemaIR-BlG9bY7v.mjs → schemaIR-7Vl611Qs.mjs} +1 -1
  111. package/dist/schemas/index.d.mts +100 -30
  112. package/dist/schemas/index.mjs +86 -29
  113. package/dist/scim/index.d.mts +264 -0
  114. package/dist/scim/index.mjs +963 -0
  115. package/dist/scope/index.d.mts +3 -3
  116. package/dist/scope/index.mjs +4 -4
  117. package/dist/{sse-V7aXc3bW.mjs → sse-Bz-5ZeTt.mjs} +1 -1
  118. package/dist/{store-helpers-BhrzxvyQ.mjs → store-helpers-BkIN9-vu.mjs} +1 -1
  119. package/dist/testing/index.d.mts +2 -8
  120. package/dist/testing/index.mjs +16 -24
  121. package/dist/testing/storageContract.d.mts +1 -1
  122. package/dist/types/index.d.mts +4 -4
  123. package/dist/types/storage.d.mts +1 -1
  124. package/dist/{types-BH7dEGvU.d.mts → types-BvqwCCSx.d.mts} +77 -29
  125. package/dist/{types-tgR4Pt8F.d.mts → types-CTYvcwHe.d.mts} +195 -1
  126. package/dist/{types-AOD8fxIw.mjs → types-C_s5moIu.mjs} +117 -1
  127. package/dist/{types-9beEMe25.d.mts → types-DQHFc8PM.d.mts} +1 -1
  128. package/dist/utils/index.d.mts +2 -2
  129. package/dist/utils/index.mjs +5 -5
  130. package/dist/{utils-CcYTj09l.mjs → utils-_h9B3c57.mjs} +1269 -1334
  131. package/dist/{versioning-M9lNLhO8.d.mts → versioning-DTTvc80y.d.mts} +1 -1
  132. package/package.json +24 -34
  133. package/skills/arc/SKILL.md +521 -785
  134. package/skills/arc/references/agent-auth.md +238 -0
  135. package/skills/arc/references/api-reference.md +187 -0
  136. package/skills/arc/references/auth.md +354 -7
  137. package/skills/arc/references/enterprise-auth.md +94 -0
  138. package/skills/arc/references/events.md +8 -6
  139. package/skills/arc/references/mcp.md +2 -2
  140. package/skills/arc/references/multi-tenancy.md +11 -2
  141. package/skills/arc/references/production.md +10 -9
  142. package/skills/arc/references/scim.md +247 -0
  143. package/skills/arc/references/testing.md +1 -1
  144. package/skills/arc-code-review/SKILL.md +141 -0
  145. package/skills/arc-code-review/references/anti-patterns.md +911 -0
  146. package/skills/arc-code-review/references/arc-cheatsheet.md +380 -0
  147. package/skills/arc-code-review/references/migration-recipes.md +700 -0
  148. package/skills/arc-code-review/references/mongokit-migration.md +386 -0
  149. package/skills/arc-code-review/references/scaffolding.md +230 -0
  150. package/skills/arc-code-review/references/severity.md +127 -0
  151. package/dist/EventTransport-CfVEGaEl.d.mts +0 -293
  152. package/dist/adapters/index.d.mts +0 -3
  153. package/dist/adapters/index.mjs +0 -2
  154. package/dist/adapters-D0tT2Tyo.mjs +0 -949
  155. package/dist/auth/mongoose.d.mts +0 -191
  156. package/dist/auth/mongoose.mjs +0 -73
  157. package/dist/core-DnUsRpuX.mjs +0 -1049
  158. package/dist/errorHandler-BQm8ZxTK.mjs +0 -173
  159. package/dist/errorHandler-Co3lnVmJ.d.mts +0 -114
  160. package/dist/errors-D5c-5BJL.mjs +0 -232
  161. package/dist/index-BbMrcvGp.d.mts +0 -362
  162. package/dist/redis-stream-CM8TXTix.d.mts +0 -110
  163. /package/dist/{HookSystem-CGsMd6oK.mjs → HookSystem-Iiebom92.mjs} +0 -0
  164. /package/dist/{actionPermissions-sUUKDhtP.mjs → actionPermissions-CyUkQu6O.mjs} +0 -0
  165. /package/dist/{caching-CheW3m-S.mjs → caching-SM8gghN6.mjs} +0 -0
  166. /package/dist/{constants-BhY1OHoH.mjs → constants-Cxde4rpC.mjs} +0 -0
  167. /package/dist/{elevation-s5ykdNHr.d.mts → elevation-BXOWoGCF.d.mts} +0 -0
  168. /package/dist/{externalPaths-Bapitwvd.d.mts → externalPaths-BD5nw6St.d.mts} +0 -0
  169. /package/dist/{interface-CkkWm5uR.d.mts → interface-DfLGcus7.d.mts} +0 -0
  170. /package/dist/{interface-Da0r7Lna.d.mts → interface-beEtJyWM.d.mts} +0 -0
  171. /package/dist/{keys-CARyUjiR.mjs → keys-CGcCbNyu.mjs} +0 -0
  172. /package/dist/{loadResources-CPpkyKfM.mjs → loadResources-DBMQg_Aj.mjs} +0 -0
  173. /package/dist/{memory-DikHSvWa.mjs → memory-UBydS5ku.mjs} +0 -0
  174. /package/dist/{metrics-Csh4nsvv.mjs → metrics-Qnvwc-LQ.mjs} +0 -0
  175. /package/dist/{pluralize-BneOJkpi.mjs → pluralize-DQgqgifU.mjs} +0 -0
  176. /package/dist/{registry-D63ee7fl.mjs → registry-I-ogLgL9.mjs} +0 -0
  177. /package/dist/{requestContext-C5XeK3VA.mjs → requestContext-SSaaTgW8.mjs} +0 -0
  178. /package/dist/{schemaConverter-B0oKLuqI.mjs → schemaConverter-De34B1ZG.mjs} +0 -0
  179. /package/dist/{sessionManager-D-oNWHz3.d.mts → sessionManager-C4Le_UB3.d.mts} +0 -0
  180. /package/dist/{storage-BwGQXUpd.d.mts → storage-Dfzt4VTl.d.mts} +0 -0
  181. /package/dist/{tracing-DokiEsuz.d.mts → tracing-QJVprktp.d.mts} +0 -0
  182. /package/dist/{typeGuards-CcFZXgU7.mjs → typeGuards-BzkXkvVv.mjs} +0 -0
  183. /package/dist/{types-DV9WDfeg.mjs → types-D57iXYb8.mjs} +0 -0
  184. /package/dist/{versioning-CGPjkqAg.mjs → versioning-BUrT5aP4.mjs} +0 -0
  185. /package/dist/{websocket-CyJ1VIFI.d.mts → websocket-ChC2rqe1.d.mts} +0 -0
@@ -1,10 +1,13 @@
1
- import { t as BaseController } from "./BaseController-swXruJ2_.mjs";
2
- import { A as normalizePermissionResult } from "./permissions-gd_aUWrR.mjs";
3
- import { u as resolvePipelineSteps } from "./routerShared-BqLRb5l7.mjs";
4
- import { t as executePipeline } from "./pipe-DVoIheVC.mjs";
5
- import { t as resolveActionPermission } from "./actionPermissions-sUUKDhtP.mjs";
6
- import { i as shouldRejectAdditionalProperties, r as schemaIRToZodShape, t as normalizeSchemaIR } from "./schemaIR-BlG9bY7v.mjs";
7
- import { t as pluralize } from "./pluralize-BneOJkpi.mjs";
1
+ import { p as isArcError } from "./errors-j4aJm1Wg.mjs";
2
+ import { t as BaseController } from "./BaseController-DX_T-bDB.mjs";
3
+ import { L as normalizePermissionResult } from "./permissions-ohQyv50e.mjs";
4
+ import { t as executePipeline } from "./pipe-Zr0KXjQe.mjs";
5
+ import { u as resolvePipelineSteps } from "./routerShared-D6_fEGHh.mjs";
6
+ import { n as executeAggregation, r as validateAggregations } from "./buildHandler-olo-gt94.mjs";
7
+ import { t as resolveActionPermission } from "./actionPermissions-CyUkQu6O.mjs";
8
+ import { i as shouldRejectAdditionalProperties, r as schemaIRToZodShape, t as normalizeSchemaIR } from "./schemaIR-7Vl611Qs.mjs";
9
+ import { t as pluralize } from "./pluralize-DQgqgifU.mjs";
10
+ import { isHttpError, toErrorContract } from "@classytic/repo-core/errors";
8
11
  import { z } from "zod";
9
12
  //#region src/integrations/mcp/createMcpServer.ts
10
13
  /**
@@ -416,15 +419,11 @@ async function evaluatePermission(check, session, resource, action, input) {
416
419
  * Convert a controller response envelope into an MCP `CallToolResult`.
417
420
  * Carries `meta` into the serialized payload so consumers see pagination
418
421
  * totals, stripped-field arrays, etc.
422
+ *
423
+ * Errors are not represented here — controllers throw `ArcError` and the
424
+ * MCP tool wrapper catches them via {@link toCallToolError}.
419
425
  */
420
426
  function toCallToolResult(result) {
421
- if (!result.success) return {
422
- content: [{
423
- type: "text",
424
- text: result.error ?? "Operation failed"
425
- }],
426
- isError: true
427
- };
428
427
  const output = result.meta ? {
429
428
  data: result.data,
430
429
  ...result.meta
@@ -435,6 +434,70 @@ function toCallToolResult(result) {
435
434
  }] };
436
435
  }
437
436
  /**
437
+ * Wrap a raw success payload as an MCP `CallToolResult`. Use when the
438
+ * tool produced a value directly (action handler return, aggregation
439
+ * rows, etc.) instead of an `IControllerResponse` envelope.
440
+ *
441
+ * Emits the value as JSON with no envelope — same no-envelope contract
442
+ * the HTTP wire follows. The `isError: true` flag on `CallToolResult`
443
+ * is the success/error discriminant for MCP, mirroring HTTP status.
444
+ */
445
+ function toCallToolSuccess(value) {
446
+ return { content: [{
447
+ type: "text",
448
+ text: JSON.stringify(value)
449
+ }] };
450
+ }
451
+ /**
452
+ * Wrap an error as an MCP `CallToolResult` with the canonical
453
+ * `ErrorContract` shape inside the text payload. Single source of truth
454
+ * for MCP error serialization — every tool surface (CRUD, action, route,
455
+ * aggregation) routes through here so the JSON shape an agent sees is
456
+ * identical to what an HTTP client sees.
457
+ *
458
+ * Accepts:
459
+ * - An `ArcError` (or any `HttpError`-shaped throw) → routes through
460
+ * `toErrorContract()` for the canonical conversion.
461
+ * - A partial contract `{code, message, status, details?}` → used as-is.
462
+ * - Any other `Error` → falls back to `arc.internal_error` 500.
463
+ */
464
+ function toCallToolError(input) {
465
+ let contract;
466
+ if (input instanceof Error) if (isArcError(input) || isHttpError(input)) contract = toErrorContract(input);
467
+ else contract = {
468
+ code: "arc.internal_error",
469
+ message: input.message || "Internal Server Error",
470
+ status: 500
471
+ };
472
+ else contract = {
473
+ code: input.code,
474
+ message: input.message,
475
+ ...input.status !== void 0 ? { status: input.status } : {},
476
+ ...input.details ? { details: input.details } : {}
477
+ };
478
+ return {
479
+ content: [{
480
+ type: "text",
481
+ text: JSON.stringify(contract)
482
+ }],
483
+ isError: true
484
+ };
485
+ }
486
+ /**
487
+ * Build the canonical permission-denied `CallToolResult` for an MCP
488
+ * tool. Discriminates 401 (no session — "Authentication required") from
489
+ * 403 (session present, denied — "Permission denied"). Mirrors the
490
+ * status split the HTTP `errorHandler` plugin uses.
491
+ */
492
+ function permissionDeniedResult(args) {
493
+ const authenticated = args.session != null;
494
+ return toCallToolError({
495
+ code: authenticated ? "arc.forbidden" : "arc.unauthorized",
496
+ message: args.reason ?? (authenticated ? `Permission denied for '${args.operation}' on '${args.resource}'` : "Authentication required"),
497
+ status: authenticated ? 403 : 401
498
+ });
499
+ }
500
+ /**
438
501
  * Auto-create a BaseController from the resource's adapter for MCP use.
439
502
  * Called when the resource has an adapter but no controller
440
503
  * (e.g. `disableDefaultRoutes: true` skips controller creation in
@@ -482,32 +545,24 @@ function createActionToolHandler(actionName, handler, permissions, resourceName,
482
545
  const session = ctx.session;
483
546
  if (allowedKeys) {
484
547
  const extras = Object.keys(input).filter((k) => !allowedKeys.has(k));
485
- if (extras.length > 0) return {
486
- content: [{
487
- type: "text",
488
- text: JSON.stringify({
489
- success: false,
490
- error: `Unknown properties not allowed: ${extras.join(", ")}`,
491
- details: {
492
- action: actionName,
493
- unexpected: extras
494
- }
495
- })
496
- }],
497
- isError: true
498
- };
548
+ if (extras.length > 0) return toCallToolError({
549
+ code: "arc.bad_request",
550
+ message: `Unknown properties not allowed: ${extras.join(", ")}`,
551
+ status: 400,
552
+ details: [{
553
+ path: "input",
554
+ code: "unknown_properties",
555
+ message: `Unexpected fields: ${extras.join(", ")}`
556
+ }]
557
+ });
499
558
  }
500
559
  const permResult = await evaluatePermission(permissions, session, resourceName, actionName, input);
501
- if (permResult && !permResult.granted) return {
502
- content: [{
503
- type: "text",
504
- text: JSON.stringify({
505
- success: false,
506
- error: permResult.reason ?? `Permission denied for action '${actionName}'`
507
- })
508
- }],
509
- isError: true
510
- };
560
+ if (permResult && !permResult.granted) return permissionDeniedResult({
561
+ resource: resourceName,
562
+ operation: `action.${actionName}`,
563
+ reason: permResult.reason,
564
+ session
565
+ });
511
566
  const reqCtx = buildRequestContext({
512
567
  ...input,
513
568
  action: actionName
@@ -515,26 +570,111 @@ function createActionToolHandler(actionName, handler, permissions, resourceName,
515
570
  const id = typeof input.id === "string" ? input.id : "";
516
571
  const { id: _discardId, ...data } = input;
517
572
  try {
518
- const result = await handler(id, data, reqCtx);
519
- return { content: [{
520
- type: "text",
521
- text: JSON.stringify({
522
- success: true,
523
- data: result
524
- })
525
- }] };
573
+ return toCallToolSuccess(await handler(id, data, reqCtx));
526
574
  } catch (err) {
527
- return {
528
- content: [{
529
- type: "text",
530
- text: `Error: ${err instanceof Error ? err.message : String(err)}`
531
- }],
532
- isError: true
533
- };
575
+ return toCallToolError(err instanceof Error ? err : new Error(String(err)));
534
576
  }
535
577
  };
536
578
  }
537
579
  //#endregion
580
+ //#region src/integrations/mcp/aggregation-tools.ts
581
+ /**
582
+ * Build MCP tools for a resource's aggregations.
583
+ *
584
+ * Returns an empty array when the resource has no aggregations or
585
+ * every aggregation opts out via `mcp: false`.
586
+ */
587
+ function buildAggregationTools(args) {
588
+ const { resourceName, displayName, aggregations, schemaOptions, repo, buildOptionsFromSession, prefix } = args;
589
+ if (!aggregations || Object.keys(aggregations).length === 0) return [];
590
+ const normalized = validateAggregations(resourceName, aggregations, schemaOptions);
591
+ const tools = [];
592
+ for (const norm of normalized) {
593
+ const config = norm.base;
594
+ if (config.mcp === false) continue;
595
+ const mcpCfg = typeof config.mcp === "object" ? config.mcp : void 0;
596
+ const description = buildAggregationToolDescription(norm, mcpCfg?.description);
597
+ const annotations = mcpCfg?.annotations ? { ...mcpCfg.annotations } : {
598
+ readOnlyHint: true,
599
+ idempotentHint: true
600
+ };
601
+ const toolName = prefix ? `${prefix}_aggregation_${norm.name}_${resourceName}` : `aggregation_${norm.name}_${resourceName}`;
602
+ tools.push({
603
+ name: toolName,
604
+ description,
605
+ annotations,
606
+ inputSchema: buildAggregationInputSchema(norm),
607
+ handler: createAggregationToolHandler({
608
+ normalized: norm,
609
+ permissions: config.permissions,
610
+ resourceName,
611
+ repo,
612
+ buildOptionsFromSession
613
+ })
614
+ });
615
+ }
616
+ return tools;
617
+ }
618
+ function buildAggregationToolDescription(norm, override) {
619
+ if (override) return override;
620
+ const config = norm.base;
621
+ const parts = [];
622
+ if (config.summary) parts.push(config.summary);
623
+ if (config.description && config.description !== config.summary) parts.push(config.description);
624
+ const groupSummary = describeGroupBy(config.groupBy);
625
+ const measureSummary = Object.keys(norm.compiled.measures).join(", ");
626
+ if (groupSummary) parts.push(`Groups by ${groupSummary}; measures: ${measureSummary}.`);
627
+ else parts.push(`Scalar aggregate. Measures: ${measureSummary}.`);
628
+ if (config.requireDateRange) parts.push(`Requires a bounded date range on \`${config.requireDateRange.field}\`.` + (config.requireDateRange.maxRangeDays ? ` Max range: ${config.requireDateRange.maxRangeDays} days.` : ""));
629
+ if (config.requireFilters?.length) parts.push(`Requires filters on: ${config.requireFilters.join(", ")}.`);
630
+ return parts.join(" ");
631
+ }
632
+ function describeGroupBy(groupBy) {
633
+ if (!groupBy) return "";
634
+ if (typeof groupBy === "string") return `\`${groupBy}\``;
635
+ if (groupBy.length === 0) return "";
636
+ return groupBy.map((g) => `\`${g}\``).join(", ");
637
+ }
638
+ /**
639
+ * Build the MCP tool input schema.
640
+ *
641
+ * Aggregation tools accept a single `filter` object mapping field
642
+ * name → value or operator object. Open-shape so agents can pass any
643
+ * caller-side narrows; safety guards inside `executeAggregation`
644
+ * enforce required fields.
645
+ */
646
+ function buildAggregationInputSchema(norm) {
647
+ const config = norm.base;
648
+ const shape = { filter: z.record(z.string(), z.unknown()).optional().describe("Caller-supplied filter narrowing. Keys are field names (or `'<alias>.<field>'` joined-alias paths when the aggregation declares lookups). Values are literals or operator objects (`{ gte, lte, in, ... }`).") };
649
+ if (config.requireFilters?.length) shape.requireFiltersHint = z.literal(config.requireFilters.join(", ")).optional().describe(`REQUIRED FILTERS — supply ${config.requireFilters.map((f) => `\`filter.${f}\``).join(" + ")} for this aggregation to run. Missing fields → 400.`);
650
+ if (config.requireDateRange) shape.requireDateRangeHint = z.literal(config.requireDateRange.field).optional().describe(`REQUIRED DATE RANGE — supply \`filter['${config.requireDateRange.field}'] = { gte: '<lower>', lte: '<upper>' }\`.` + (config.requireDateRange.maxRangeDays ? ` Range capped at ${config.requireDateRange.maxRangeDays} days.` : ""));
651
+ return shape;
652
+ }
653
+ function createAggregationToolHandler(args) {
654
+ const { normalized, permissions, resourceName, repo, buildOptionsFromSession } = args;
655
+ return async (input, ctx) => {
656
+ const permResult = await evaluatePermission(permissions, ctx.session, resourceName, `aggregation:${normalized.name}`, input);
657
+ if (permResult && !permResult.granted) return permissionDeniedResult({
658
+ resource: resourceName,
659
+ operation: `aggregation:${normalized.name}`,
660
+ reason: permResult.reason,
661
+ session: ctx.session
662
+ });
663
+ const filterInput = input.filter ?? {};
664
+ const tenantOptions = buildOptionsFromSession(ctx.session);
665
+ if (permResult?.filters) Object.assign(tenantOptions, { _policyFilters: permResult.filters });
666
+ const result = await executeAggregation(normalized, {
667
+ repo,
668
+ buildOptions: () => tenantOptions
669
+ }, {
670
+ query: filterInput,
671
+ tenantOptions
672
+ });
673
+ if (result.status === 200) return toCallToolSuccess(result.body);
674
+ return toCallToolError(result.body);
675
+ };
676
+ }
677
+ //#endregion
538
678
  //#region src/integrations/mcp/crud-tools.ts
539
679
  const ALL_CRUD_OPS = [
540
680
  "list",
@@ -928,16 +1068,12 @@ function createCustomRouteHandler(route, controller, hasId, options) {
928
1068
  return async (input, _ctx) => {
929
1069
  const session = _ctx.session;
930
1070
  const permResult = await evaluatePermission(permissions, session, resourceName, operationName, input);
931
- if (permResult && !permResult.granted) return {
932
- content: [{
933
- type: "text",
934
- text: JSON.stringify({
935
- success: false,
936
- error: permResult.reason ?? (session ? `Permission denied for '${operationName}'` : "Authentication required")
937
- })
938
- }],
939
- isError: true
940
- };
1071
+ if (permResult && !permResult.granted) return permissionDeniedResult({
1072
+ resource: resourceName,
1073
+ operation: operationName,
1074
+ reason: permResult.reason,
1075
+ session
1076
+ });
941
1077
  try {
942
1078
  const reqCtx = buildRequestContext(input, session, hasId ? "update" : "create", permResult?.filters, permResult?.scope);
943
1079
  if (typeof route.handler === "function") {
@@ -948,16 +1084,10 @@ function createCustomRouteHandler(route, controller, hasId, options) {
948
1084
  operation: operationName
949
1085
  }, async (ctx) => {
950
1086
  const raw = await fn(ctx);
951
- return raw !== null && typeof raw === "object" && "success" in raw ? raw : {
952
- success: true,
953
- data: raw
954
- };
1087
+ return raw !== null && typeof raw === "object" && "data" in raw ? raw : { data: raw };
955
1088
  }, operationName));
956
1089
  const out = await fn(reqCtx);
957
- return toCallToolResult(out !== null && typeof out === "object" && "success" in out ? out : {
958
- success: true,
959
- data: out
960
- });
1090
+ return toCallToolResult(out !== null && typeof out === "object" && "data" in out ? out : { data: out });
961
1091
  }
962
1092
  if (!ctrl) return {
963
1093
  content: [{
@@ -1154,6 +1284,29 @@ function resourceToTools(resource, config = {}) {
1154
1284
  handler: createActionToolHandler(actionName, handler, actionPerms, resource.name, resource.permissions, rawSchema)
1155
1285
  });
1156
1286
  }
1287
+ if (resource.aggregations && Object.keys(resource.aggregations).length > 0) {
1288
+ const repoForAgg = resource.controller?.repository;
1289
+ const buildOptionsFromSession = (session) => {
1290
+ const s = session;
1291
+ const out = {};
1292
+ const orgId = s?.scope?.organizationId;
1293
+ if (orgId) out.organizationId = orgId;
1294
+ const userId = s?.scope?.userId ?? s?.user?.id;
1295
+ if (userId) out.userId = userId;
1296
+ if (s?.user) out.user = s.user;
1297
+ if (s?.requestId) out.requestId = s.requestId;
1298
+ return out;
1299
+ };
1300
+ tools.push(...buildAggregationTools({
1301
+ resourceName: resource.name,
1302
+ displayName: resource.displayName ?? resource.name,
1303
+ aggregations: resource.aggregations,
1304
+ schemaOptions: resource.schemaOptions,
1305
+ repo: repoForAgg,
1306
+ buildOptionsFromSession,
1307
+ prefix
1308
+ }));
1309
+ }
1157
1310
  return tools;
1158
1311
  }
1159
1312
  //#endregion
@@ -1,8 +1,10 @@
1
- import { _ as isElevated, n as PUBLIC_SCOPE, o as getOrgId, p as getUserId, v as isMember } from "./types-AOD8fxIw.mjs";
2
- import { P as resolveEffectiveRoles, j as applyFieldReadPermissions, k as evaluateAndApplyPermission } from "./permissions-gd_aUWrR.mjs";
3
- import { t as getUserRoles } from "./types-DV9WDfeg.mjs";
4
- import { t as requestContext } from "./requestContext-C5XeK3VA.mjs";
5
- import { t as executePipeline } from "./pipe-DVoIheVC.mjs";
1
+ import { f as createError } from "./errors-j4aJm1Wg.mjs";
2
+ import { b as isMember, c as getOrgId, h as getUserId, n as PUBLIC_SCOPE, y as isElevated } from "./types-C_s5moIu.mjs";
3
+ import { t as requestContext } from "./requestContext-SSaaTgW8.mjs";
4
+ import { I as evaluateAndApplyPermission, p as resolveEffectiveRoles, u as applyFieldReadPermissions } from "./permissions-ohQyv50e.mjs";
5
+ import { t as getUserRoles } from "./types-D57iXYb8.mjs";
6
+ import { t as executePipeline } from "./pipe-Zr0KXjQe.mjs";
7
+ import { isPaginatedResult, toCanonicalList } from "@classytic/repo-core/pagination";
6
8
  //#region src/scope/projection.ts
7
9
  /**
8
10
  * Compute the request-scope projection. Returns `undefined` when no
@@ -165,32 +167,44 @@ function sendControllerResponse(reply, response, request) {
165
167
  return result;
166
168
  };
167
169
  if (response.headers) for (const [key, value] of Object.entries(response.headers)) reply.header(key, value);
168
- if (response.success && response.data && typeof response.data === "object" && "docs" in response.data) {
169
- const paginatedData = response.data;
170
- const filteredDocs = hasFieldRestrictions ? applyPermissions(paginatedData.docs) : paginatedData.docs;
170
+ if (response.data && typeof response.data === "object" && Array.isArray(response.data.data)) {
171
+ const payload = response.data;
172
+ const filteredRows = hasFieldRestrictions ? applyPermissions(payload.data) : payload.data;
173
+ let canonical;
174
+ if (isPaginatedResult(payload)) canonical = toCanonicalList({
175
+ ...payload,
176
+ data: filteredRows
177
+ });
178
+ else if (typeof payload.page === "number" && typeof payload.limit === "number" && typeof payload.total === "number") canonical = toCanonicalList({
179
+ method: "offset",
180
+ data: filteredRows,
181
+ page: payload.page,
182
+ limit: payload.limit,
183
+ total: payload.total,
184
+ pages: payload.pages ?? Math.ceil(payload.total / Math.max(1, payload.limit)),
185
+ hasNext: payload.hasNext ?? false,
186
+ hasPrev: payload.hasPrev ?? false
187
+ });
188
+ else canonical = toCanonicalList(filteredRows);
171
189
  reply.code(response.status ?? 200).send({
172
- success: true,
173
- docs: filteredDocs,
174
- page: paginatedData.page,
175
- limit: paginatedData.limit,
176
- total: paginatedData.total,
177
- pages: paginatedData.pages,
178
- hasNext: paginatedData.hasNext,
179
- hasPrev: paginatedData.hasPrev,
190
+ ...canonical,
180
191
  ...response.meta ?? {},
181
192
  ...fieldCaps ? { fieldPermissions: fieldCaps } : {}
182
193
  });
183
194
  return;
184
195
  }
185
- const filteredData = hasFieldRestrictions ? applyPermissions(response.data) : response.data;
186
- reply.code(response.status ?? (response.success ? 200 : 400)).send({
187
- success: response.success,
188
- data: filteredData,
189
- error: response.error,
190
- details: response.details,
191
- ...response.meta ?? {},
192
- ...fieldCaps ? { fieldPermissions: fieldCaps } : {}
193
- });
196
+ const rawData = hasFieldRestrictions ? applyPermissions(response.data) : response.data;
197
+ const filteredData = rawData !== null && typeof rawData === "object" && typeof rawData.toJSON === "function" ? rawData.toJSON() : rawData;
198
+ const status = response.status ?? 200;
199
+ if (filteredData !== null && typeof filteredData === "object" && !Array.isArray(filteredData) && (response.meta || fieldCaps)) {
200
+ reply.code(status).send({
201
+ ...filteredData,
202
+ ...response.meta ?? {},
203
+ ...fieldCaps ? { fieldPermissions: fieldCaps } : {}
204
+ });
205
+ return;
206
+ }
207
+ reply.code(status).send(filteredData);
194
208
  }
195
209
  /**
196
210
  * Create Fastify route handler from IController method
@@ -370,15 +384,7 @@ function buildActionPermissionMw(actionEnum, actionPermissions, globalAuth, reso
370
384
  return async (req, reply) => {
371
385
  const body = req.body ?? {};
372
386
  const action = body.action;
373
- if (!action || !enumSet.has(action)) {
374
- sendControllerResponse(reply, {
375
- success: false,
376
- status: 400,
377
- error: `Invalid action '${action ?? ""}'. Valid actions: ${validActions.join(", ")}`,
378
- meta: { validActions }
379
- }, req);
380
- return;
381
- }
387
+ if (!action || !enumSet.has(action)) throw createError(400, `Invalid action '${action ?? ""}'. Valid actions: ${validActions.join(", ")}`, { validActions });
382
388
  const permissionCheck = actionPermissions[action] ?? globalAuth;
383
389
  if (!permissionCheck) return;
384
390
  const { action: _discard, ...data } = body;
@@ -432,7 +438,6 @@ function buildPipelineHandler(controllerMethod, steps, operation, resourceName)
432
438
  */
433
439
  function buildActionPipelineHandler(handler, steps, operation, resourceName) {
434
440
  if (steps.length === 0) return async (id, data, req) => ({
435
- success: true,
436
441
  status: 200,
437
442
  data: await handler(id, data, req)
438
443
  });
@@ -442,7 +447,6 @@ function buildActionPipelineHandler(handler, steps, operation, resourceName) {
442
447
  resource: resourceName,
443
448
  operation
444
449
  }, async (_ctx) => ({
445
- success: true,
446
450
  status: 200,
447
451
  data: await handler(id, data, req)
448
452
  }), operation);
@@ -1,4 +1,4 @@
1
- import { a as toJsonSchema } from "./schemaConverter-B0oKLuqI.mjs";
1
+ import { a as toJsonSchema } from "./schemaConverter-De34B1ZG.mjs";
2
2
  import { z } from "zod";
3
3
  //#region src/core/schemaIR.ts
4
4
  /**
@@ -1,15 +1,54 @@
1
+ import { ErrorContract, ErrorDetail } from "@classytic/repo-core/errors";
1
2
  import { FastifyPluginAsyncTypebox, FastifyPluginCallbackTypebox, TypeBoxTypeProvider, TypeBoxValidatorCompiler } from "@fastify/type-provider-typebox";
2
3
  import * as _$_sinclair_typebox0 from "@sinclair/typebox";
3
4
  import { Static, TObject, TSchema, TSchema as TSchema$1, Type } from "@sinclair/typebox";
4
5
 
5
6
  //#region src/schemas/index.d.ts
6
7
  /**
7
- * Paginated list response — matches Arc's runtime format:
8
- * `{ success, docs: [...], page, limit, total, pages, hasNext, hasPrev }`
8
+ * Paginated list response — full union of every wire shape `toCanonicalList`
9
+ * emits. Mirrors `PaginatedResult<T>` from `@classytic/repo-core/pagination`:
10
+ *
11
+ * - `{ method: 'offset', data, page, limit, total, pages, hasNext, hasPrev }`
12
+ * - `{ method: 'keyset', data, limit, hasMore, next: string | null }`
13
+ * - `{ method: 'aggregate', ...same as offset }`
14
+ * - `{ data }` (bare list, no `method`)
15
+ *
16
+ * Use `ArcOffsetListResponse` / `ArcKeysetListResponse` /
17
+ * `ArcAggregateListResponse` / `ArcBareListResponse` to pin a single
18
+ * variant when your endpoint never emits the others. HTTP status
19
+ * discriminates success vs error — no `success` field.
9
20
  */
10
- declare function ArcListResponse<T extends TSchema$1>(itemSchema: T): _$_sinclair_typebox0.TObject<{
11
- success: _$_sinclair_typebox0.TBoolean;
12
- docs: _$_sinclair_typebox0.TArray<T>;
21
+ declare function ArcListResponse<T extends TSchema$1>(itemSchema: T): _$_sinclair_typebox0.TUnion<[_$_sinclair_typebox0.TObject<{
22
+ method: _$_sinclair_typebox0.TLiteral<"offset">;
23
+ data: _$_sinclair_typebox0.TArray<T>;
24
+ page: _$_sinclair_typebox0.TInteger;
25
+ limit: _$_sinclair_typebox0.TInteger;
26
+ total: _$_sinclair_typebox0.TInteger;
27
+ pages: _$_sinclair_typebox0.TInteger;
28
+ hasNext: _$_sinclair_typebox0.TBoolean;
29
+ hasPrev: _$_sinclair_typebox0.TBoolean;
30
+ }>, _$_sinclair_typebox0.TObject<{
31
+ method: _$_sinclair_typebox0.TLiteral<"keyset">;
32
+ data: _$_sinclair_typebox0.TArray<T>;
33
+ limit: _$_sinclair_typebox0.TInteger;
34
+ hasMore: _$_sinclair_typebox0.TBoolean;
35
+ next: _$_sinclair_typebox0.TUnion<[_$_sinclair_typebox0.TString, _$_sinclair_typebox0.TNull]>;
36
+ }>, _$_sinclair_typebox0.TObject<{
37
+ method: _$_sinclair_typebox0.TLiteral<"aggregate">;
38
+ data: _$_sinclair_typebox0.TArray<T>;
39
+ page: _$_sinclair_typebox0.TInteger;
40
+ limit: _$_sinclair_typebox0.TInteger;
41
+ total: _$_sinclair_typebox0.TInteger;
42
+ pages: _$_sinclair_typebox0.TInteger;
43
+ hasNext: _$_sinclair_typebox0.TBoolean;
44
+ hasPrev: _$_sinclair_typebox0.TBoolean;
45
+ }>, _$_sinclair_typebox0.TObject<{
46
+ data: _$_sinclair_typebox0.TArray<T>;
47
+ }>]>;
48
+ /** Offset variant — `{ method: 'offset', data, page, limit, total, pages, hasNext, hasPrev }`. */
49
+ declare function ArcOffsetListResponse<T extends TSchema$1>(itemSchema: T): _$_sinclair_typebox0.TObject<{
50
+ method: _$_sinclair_typebox0.TLiteral<"offset">;
51
+ data: _$_sinclair_typebox0.TArray<T>;
13
52
  page: _$_sinclair_typebox0.TInteger;
14
53
  limit: _$_sinclair_typebox0.TInteger;
15
54
  total: _$_sinclair_typebox0.TInteger;
@@ -17,47 +56,78 @@ declare function ArcListResponse<T extends TSchema$1>(itemSchema: T): _$_sinclai
17
56
  hasNext: _$_sinclair_typebox0.TBoolean;
18
57
  hasPrev: _$_sinclair_typebox0.TBoolean;
19
58
  }>;
20
- /**
21
- * Single item response — `{ success, data: {...} }`
22
- */
23
- declare function ArcItemResponse<T extends TSchema$1>(itemSchema: T): _$_sinclair_typebox0.TObject<{
24
- success: _$_sinclair_typebox0.TBoolean;
25
- data: T;
59
+ /** Keyset variant — `{ method: 'keyset', data, limit, hasMore, next: string | null }`. */
60
+ declare function ArcKeysetListResponse<T extends TSchema$1>(itemSchema: T): _$_sinclair_typebox0.TObject<{
61
+ method: _$_sinclair_typebox0.TLiteral<"keyset">;
62
+ data: _$_sinclair_typebox0.TArray<T>;
63
+ limit: _$_sinclair_typebox0.TInteger;
64
+ hasMore: _$_sinclair_typebox0.TBoolean;
65
+ next: _$_sinclair_typebox0.TUnion<[_$_sinclair_typebox0.TString, _$_sinclair_typebox0.TNull]>;
26
66
  }>;
27
- /**
28
- * Mutation (create/update) response — `{ success, data: {...}, message? }`
29
- */
30
- declare function ArcMutationResponse<T extends TSchema$1>(itemSchema: T): _$_sinclair_typebox0.TObject<{
31
- success: _$_sinclair_typebox0.TBoolean;
32
- data: T;
33
- message: _$_sinclair_typebox0.TOptional<_$_sinclair_typebox0.TString>;
67
+ /** Aggregate variant — `{ method: 'aggregate', ...same as offset }`. */
68
+ declare function ArcAggregateListResponse<T extends TSchema$1>(itemSchema: T): _$_sinclair_typebox0.TObject<{
69
+ method: _$_sinclair_typebox0.TLiteral<"aggregate">;
70
+ data: _$_sinclair_typebox0.TArray<T>;
71
+ page: _$_sinclair_typebox0.TInteger;
72
+ limit: _$_sinclair_typebox0.TInteger;
73
+ total: _$_sinclair_typebox0.TInteger;
74
+ pages: _$_sinclair_typebox0.TInteger;
75
+ hasNext: _$_sinclair_typebox0.TBoolean;
76
+ hasPrev: _$_sinclair_typebox0.TBoolean;
77
+ }>;
78
+ /** Bare variant — `{ data }`, no `method` discriminant. */
79
+ declare function ArcBareListResponse<T extends TSchema$1>(itemSchema: T): _$_sinclair_typebox0.TObject<{
80
+ data: _$_sinclair_typebox0.TArray<T>;
34
81
  }>;
35
82
  /**
36
- * Delete response — `{ success, message }`
83
+ * Delete response — `{ message, id?, soft? }` raw at the top level.
37
84
  */
38
85
  declare function ArcDeleteResponse(): _$_sinclair_typebox0.TObject<{
39
- success: _$_sinclair_typebox0.TBoolean;
40
- message: _$_sinclair_typebox0.TOptional<_$_sinclair_typebox0.TString>;
86
+ message: _$_sinclair_typebox0.TString;
87
+ id: _$_sinclair_typebox0.TOptional<_$_sinclair_typebox0.TString>;
88
+ soft: _$_sinclair_typebox0.TOptional<_$_sinclair_typebox0.TBoolean>;
41
89
  }>;
42
90
  /**
43
- * Error response schema
91
+ * Single field-scoped error detail — `Type.Unsafe<ErrorDetail>` over the
92
+ * canonical JSON Schema `errorDetailSchema` from
93
+ * `@classytic/repo-core/errors`. One schema constant, two adapters
94
+ * (JSON-Schema + TypeBox), zero drift surface — the schema and the TS
95
+ * type both come from repo-core.
96
+ *
97
+ * Exported standalone so hosts can embed it in custom 422 / 409 response
98
+ * schemas.
44
99
  */
45
- declare function ArcErrorResponse(): _$_sinclair_typebox0.TObject<{
46
- success: _$_sinclair_typebox0.TLiteral<false>;
47
- error: _$_sinclair_typebox0.TString;
48
- code: _$_sinclair_typebox0.TOptional<_$_sinclair_typebox0.TString>;
49
- message: _$_sinclair_typebox0.TOptional<_$_sinclair_typebox0.TString>;
50
- }>;
100
+ declare function ArcErrorDetail(): _$_sinclair_typebox0.TUnsafe<ErrorDetail>;
101
+ /**
102
+ * Error response schema — `Type.Unsafe<ErrorContract>` over the canonical
103
+ * JSON Schema `errorContractSchema` from `@classytic/repo-core/errors`.
104
+ * Same trick as `ArcErrorDetail`: the schema bytes and the TS type both
105
+ * come from repo-core, so the JSON-Schema sibling
106
+ * (`errorContractSchema`) and this TypeBox helper cannot drift —
107
+ * literally one source.
108
+ */
109
+ declare function ArcErrorResponse(): _$_sinclair_typebox0.TUnsafe<ErrorContract>;
51
110
  /**
52
111
  * Standard pagination + sorting + filtering query parameters.
53
112
  * Matches Arc's list endpoint conventions.
113
+ *
114
+ * `select` accepts every shape `QueryResolver` preserves DB-agnostically
115
+ * (gotcha #5):
116
+ *
117
+ * - `string` — `"name email -password"` (Mongoose space-separated)
118
+ * - `string[]` — `["name", "email", "-password"]` (Arc parser)
119
+ * - `Record<string, 0 | 1>` — `{ name: 1, email: 1, password: 0 }` (Mongo projection)
120
+ *
121
+ * Narrowing `select` to `string` would have rejected the array and
122
+ * projection forms at the request-validation gate even though arc passes
123
+ * them through unchanged.
54
124
  */
55
125
  declare function ArcPaginationQuery(): _$_sinclair_typebox0.TObject<{
56
126
  page: _$_sinclair_typebox0.TOptional<_$_sinclair_typebox0.TInteger>;
57
127
  limit: _$_sinclair_typebox0.TOptional<_$_sinclair_typebox0.TInteger>;
58
128
  sort: _$_sinclair_typebox0.TOptional<_$_sinclair_typebox0.TString>;
59
- select: _$_sinclair_typebox0.TOptional<_$_sinclair_typebox0.TString>;
129
+ select: _$_sinclair_typebox0.TOptional<_$_sinclair_typebox0.TUnion<[_$_sinclair_typebox0.TString, _$_sinclair_typebox0.TArray<_$_sinclair_typebox0.TString>, _$_sinclair_typebox0.TRecord<_$_sinclair_typebox0.TString, _$_sinclair_typebox0.TUnion<[_$_sinclair_typebox0.TLiteral<0>, _$_sinclair_typebox0.TLiteral<1>]>>]>>;
60
130
  populate: _$_sinclair_typebox0.TOptional<_$_sinclair_typebox0.TAny>;
61
131
  }>;
62
132
  //#endregion
63
- export { ArcDeleteResponse, ArcErrorResponse, ArcItemResponse, ArcListResponse, ArcMutationResponse, ArcPaginationQuery, type FastifyPluginAsyncTypebox, type FastifyPluginCallbackTypebox, type Static, type TObject, type TSchema, Type, type TypeBoxTypeProvider, TypeBoxValidatorCompiler };
133
+ export { ArcAggregateListResponse, ArcBareListResponse, ArcDeleteResponse, ArcErrorDetail, ArcErrorResponse, ArcKeysetListResponse, ArcListResponse, ArcOffsetListResponse, ArcPaginationQuery, type FastifyPluginAsyncTypebox, type FastifyPluginCallbackTypebox, type Static, type TObject, type TSchema, Type, type TypeBoxTypeProvider, TypeBoxValidatorCompiler };