@classytic/arc 2.8.5 → 2.9.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 (140) hide show
  1. package/README.md +88 -5
  2. package/dist/{BaseController-DAGGc5Xn.mjs → BaseController-Vu2yc56T.mjs} +188 -102
  3. package/dist/EventTransport-CqZ8FyM_.d.mts +293 -0
  4. package/dist/adapters/index.d.mts +2 -2
  5. package/dist/audit/index.d.mts +100 -11
  6. package/dist/audit/index.mjs +71 -18
  7. package/dist/auth/index.d.mts +16 -8
  8. package/dist/auth/index.mjs +13 -6
  9. package/dist/auth/redis-session.d.mts +1 -1
  10. package/dist/{betterAuthOpenApi-BuUcUEJq.mjs → betterAuthOpenApi--rdY15Ld.mjs} +1 -1
  11. package/dist/cache/index.d.mts +2 -2
  12. package/dist/cache/index.mjs +2 -2
  13. package/dist/cli/commands/docs.mjs +2 -2
  14. package/dist/cli/commands/introspect.mjs +1 -1
  15. package/dist/core/index.d.mts +3 -3
  16. package/dist/core/index.mjs +4 -5
  17. package/dist/{core-F0QoWBt2.mjs → core-DNncu0xF.mjs} +1 -1
  18. package/dist/{createActionRouter-BORM8f17.mjs → createActionRouter-DH1YFL9m.mjs} +3 -3
  19. package/dist/{createApp-B1EY8zxa.mjs → createApp-CBJUJKGP.mjs} +13 -12
  20. package/dist/{defineResource-tcgySDo1.mjs → defineResource-C__jkwvs.mjs} +22 -57
  21. package/dist/docs/index.d.mts +2 -2
  22. package/dist/docs/index.mjs +1 -1
  23. package/dist/dynamic/index.d.mts +1 -1
  24. package/dist/dynamic/index.mjs +3 -3
  25. package/dist/{elevation-DtFxrG0s.mjs → elevation-DxQ6ACbt.mjs} +21 -7
  26. package/dist/{errorHandler-f869_8PQ.mjs → errorHandler-CZDW4EXS.mjs} +59 -7
  27. package/dist/{errorHandler-Bah5JhBd.d.mts → errorHandler-DixGcttC.d.mts} +37 -2
  28. package/dist/{eventPlugin-D9DKB2zM.d.mts → eventPlugin-BxvaCIZF.d.mts} +14 -2
  29. package/dist/{eventPlugin-CDjVTM82.mjs → eventPlugin-Dl7MoVWH.mjs} +83 -5
  30. package/dist/events/index.d.mts +147 -36
  31. package/dist/events/index.mjs +338 -101
  32. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  33. package/dist/events/transports/redis.d.mts +1 -1
  34. package/dist/factory/index.d.mts +1 -1
  35. package/dist/factory/index.mjs +2 -2
  36. package/dist/{fields-DpZQa_Q3.d.mts → fields-BC7zcmI9.d.mts} +15 -3
  37. package/dist/{fields-ipsbIRPK.mjs → fields-CU6FlaDV.mjs} +18 -5
  38. package/dist/{filesUpload-C7r7HIeA.mjs → filesUpload-q8oHt--L.mjs} +65 -7
  39. package/dist/hooks/index.d.mts +1 -1
  40. package/dist/hooks/index.mjs +1 -1
  41. package/dist/idempotency/index.d.mts +29 -5
  42. package/dist/idempotency/index.mjs +111 -2
  43. package/dist/idempotency/redis.d.mts +1 -1
  44. package/dist/{index-BLXBmWud.d.mts → index-C-xjcA6F.d.mts} +1 -1
  45. package/dist/{index-DtDzOBn8.d.mts → index-Cibkchnx.d.mts} +3 -134
  46. package/dist/{index-C1meYuDn.d.mts → index-CtGKT0lf.d.mts} +1 -1
  47. package/dist/index.d.mts +7 -7
  48. package/dist/index.mjs +9 -9
  49. package/dist/integrations/event-gateway.d.mts +1 -1
  50. package/dist/integrations/event-gateway.mjs +1 -1
  51. package/dist/integrations/index.d.mts +1 -1
  52. package/dist/integrations/mcp/index.d.mts +26 -8
  53. package/dist/integrations/mcp/index.mjs +96 -17
  54. package/dist/integrations/mcp/testing.d.mts +1 -1
  55. package/dist/integrations/mcp/testing.mjs +1 -1
  56. package/dist/integrations/webhooks.d.mts +5 -0
  57. package/dist/integrations/webhooks.mjs +6 -0
  58. package/dist/{interface-CMRutPfe.d.mts → interface-YrWsmKqE.d.mts} +287 -179
  59. package/dist/{openapi-CbKUJY_m.mjs → openapi-CXuTG1M9.mjs} +2 -2
  60. package/dist/org/index.d.mts +1 -1
  61. package/dist/permissions/index.d.mts +2 -2
  62. package/dist/permissions/index.mjs +3 -3
  63. package/dist/{permissions-CH4cNwJi.mjs → permissions-oNZawnkR.mjs} +1 -1
  64. package/dist/plugins/index.d.mts +7 -7
  65. package/dist/plugins/index.mjs +11 -11
  66. package/dist/plugins/response-cache.mjs +1 -1
  67. package/dist/plugins/tracing-entry.d.mts +1 -1
  68. package/dist/plugins/tracing-entry.mjs +1 -1
  69. package/dist/policies/index.d.mts +25 -32
  70. package/dist/presets/filesUpload.d.mts +26 -4
  71. package/dist/presets/filesUpload.mjs +1 -1
  72. package/dist/presets/index.d.mts +3 -2
  73. package/dist/presets/index.mjs +4 -3
  74. package/dist/presets/multiTenant.d.mts +1 -1
  75. package/dist/presets/multiTenant.mjs +1 -1
  76. package/dist/presets/search.d.mts +91 -0
  77. package/dist/presets/search.mjs +150 -0
  78. package/dist/{presets-C2xgzW6x.mjs → presets-hM4WhNWY.mjs} +1 -1
  79. package/dist/{queryCachePlugin-BJJGBTlu.d.mts → queryCachePlugin-CnTZZTC5.d.mts} +1 -1
  80. package/dist/{queryCachePlugin-BH-fidlv.mjs → queryCachePlugin-DbUVroUG.mjs} +2 -2
  81. package/dist/{redis-BM00zaPB.d.mts → redis-MXLp1oOf.d.mts} +1 -1
  82. package/dist/{redis-stream-CrsfUmPt.d.mts → redis-stream-Bz-4q96t.d.mts} +1 -1
  83. package/dist/registry/index.d.mts +1 -1
  84. package/dist/registry/index.mjs +2 -2
  85. package/dist/{resourceToTools-8s-EsCCe.mjs → resourceToTools-C3cWymnW.mjs} +64 -47
  86. package/dist/rpc/index.d.mts +1 -1
  87. package/dist/rpc/index.mjs +1 -1
  88. package/dist/{schemaConverter-Y7nCYaLJ.mjs → schemaConverter-BxFDdtXu.mjs} +1 -1
  89. package/dist/scope/index.mjs +1 -1
  90. package/dist/{sse-Ad7ypl9e.mjs → sse-CJpt7LGI.mjs} +1 -1
  91. package/dist/store-helpers-DFiZl5TL.mjs +57 -0
  92. package/dist/testing/index.d.mts +5 -14
  93. package/dist/testing/index.mjs +21 -75
  94. package/dist/testing/storageContract.d.mts +1 -1
  95. package/dist/types/index.d.mts +2 -2
  96. package/dist/types/storage.d.mts +1 -1
  97. package/dist/{types-BsbNMEDR.d.mts → types-CoSzA-s-.d.mts} +1 -1
  98. package/dist/{types-Ch9pTQbf.d.mts → types-CunEX4UX.d.mts} +10 -8
  99. package/dist/utils/index.d.mts +4 -4
  100. package/dist/utils/index.mjs +6 -6
  101. package/dist/{utils-yYT3HDXt.mjs → utils-B7FuRr9w.mjs} +1 -1
  102. package/package.json +8 -11
  103. package/skills/arc/SKILL.md +92 -14
  104. package/skills/arc/references/auth.md +94 -0
  105. package/skills/arc/references/events.md +200 -12
  106. package/skills/arc/references/mcp.md +4 -17
  107. package/skills/arc/references/multi-tenancy.md +43 -0
  108. package/skills/arc/references/production.md +34 -19
  109. package/dist/EventTransport-BXja8NOc.d.mts +0 -135
  110. package/dist/audit/mongodb.d.mts +0 -2
  111. package/dist/audit/mongodb.mjs +0 -2
  112. package/dist/idempotency/mongodb.d.mts +0 -2
  113. package/dist/idempotency/mongodb.mjs +0 -123
  114. package/dist/mongodb-BsP-WbhN.d.mts +0 -127
  115. package/dist/mongodb-CTcp0hQZ.d.mts +0 -80
  116. package/dist/mongodb-Utc5k_-0.mjs +0 -90
  117. /package/dist/{HookSystem-HprTmvVY.mjs → HookSystem-BjFu7zf1.mjs} +0 -0
  118. /package/dist/{ResourceRegistry-C6uXlWe3.mjs → ResourceRegistry-Dq3_zBQP.mjs} +0 -0
  119. /package/dist/{applyPermissionResult-D6GPMsvh.mjs → applyPermissionResult-bqGpo9ML.mjs} +0 -0
  120. /package/dist/{caching-IMuYVjTL.mjs → caching-CjybdRwx.mjs} +0 -0
  121. /package/dist/{circuitBreaker-dTtG-UyS.d.mts → circuitBreaker-CvXkjfrW.d.mts} +0 -0
  122. /package/dist/{circuitBreaker-cmi5XDv5.mjs → circuitBreaker-l18oRgL5.mjs} +0 -0
  123. /package/dist/{errors-Ck2h67pm.d.mts → errors-BI8kEKsO.d.mts} +0 -0
  124. /package/dist/{errors-BF2bIOIS.mjs → errors-CqWnSqM-.mjs} +0 -0
  125. /package/dist/{externalPaths-BnkYrNzp.d.mts → externalPaths-Bapitwvd.d.mts} +0 -0
  126. /package/dist/{interface-DfLGcus7.d.mts → interface-B-pe8fhj.d.mts} +0 -0
  127. /package/dist/{interface-4y979v99.d.mts → interface-DplgQO2e.d.mts} +0 -0
  128. /package/dist/{loadResources-PWd0OCpV.mjs → loadResources-Bksk8ydA.mjs} +0 -0
  129. /package/dist/{logger-D1YrIImS.mjs → logger-CDjpjySd.mjs} +0 -0
  130. /package/dist/{memory-Cp7_cAko.mjs → memory-BFAYkf8H.mjs} +0 -0
  131. /package/dist/{metrics-B-PU4-Yu.mjs → metrics-TuOmguhi.mjs} +0 -0
  132. /package/dist/{queryParser-CgCtsjti.mjs → queryParser-Cs-6SHQK.mjs} +0 -0
  133. /package/dist/{registry-BiTKT1Dg.mjs → registry-B0Wl7uVV.mjs} +0 -0
  134. /package/dist/{replyHelpers-CxkYGT81.mjs → replyHelpers-BLojtuvR.mjs} +0 -0
  135. /package/dist/{requestContext-DYvHl113.mjs → requestContext-DYtmNpm5.mjs} +0 -0
  136. /package/dist/{sessionManager-DDCmiNIo.d.mts → sessionManager-D-oNWHz3.d.mts} +0 -0
  137. /package/dist/{storage-Dfzt4VTl.d.mts → storage-BwGQXUpd.d.mts} +0 -0
  138. /package/dist/{tracing-DdN2-wHJ.d.mts → tracing-xqXzWeaf.d.mts} +0 -0
  139. /package/dist/{typeGuards-CcFZXgU7.mjs → typeGuards-Cj5Rgvlg.mjs} +0 -0
  140. /package/dist/{versioning-CDugduqI.mjs → versioning-Cm8qoFDg.mjs} +0 -0
@@ -1,4 +1,4 @@
1
- import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, r as FieldPermissionType, s as resolveEffectiveRoles, t as FieldPermission } from "../fields-DpZQa_Q3.mjs";
1
+ import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, r as FieldPermissionType, s as resolveEffectiveRoles, t as FieldPermission } from "../fields-BC7zcmI9.mjs";
2
2
  import { a as getUserRoles, i as UserBase, n as PermissionContext, o as normalizeRoles, r as PermissionResult, t as PermissionCheck } from "../types-DZi1aYhm.mjs";
3
- import { A as RoleHierarchy, C as authenticated, D as publicRead, E as presets_d_exports, M as applyPermissionResult, N as normalizePermissionResult, O as publicReadAdminWrite, S as adminOnly, T as ownerWithAdminBypass, _ as requireScopeContext, a as allOf, b as roles, c as createDynamicPermissionMatrix, d as requireAuth, f as requireOrgInScope, g as requireRoles, h as requireOwnership, i as PermissionEventBus, j as createRoleHierarchy, k as readOnly, l as createOrgPermissions, m as requireOrgRole, n as DynamicPermissionMatrix, o as allowPublic, p as requireOrgMembership, r as DynamicPermissionMatrixConfig, s as anyOf, t as ConnectEventsOptions, u as denyAll, v as requireServiceScope, w as fullPublic, x as when, y as requireTeamMembership } from "../index-BLXBmWud.mjs";
3
+ import { A as RoleHierarchy, C as authenticated, D as publicRead, E as presets_d_exports, M as applyPermissionResult, N as normalizePermissionResult, O as publicReadAdminWrite, S as adminOnly, T as ownerWithAdminBypass, _ as requireScopeContext, a as allOf, b as roles, c as createDynamicPermissionMatrix, d as requireAuth, f as requireOrgInScope, g as requireRoles, h as requireOwnership, i as PermissionEventBus, j as createRoleHierarchy, k as readOnly, l as createOrgPermissions, m as requireOrgRole, n as DynamicPermissionMatrix, o as allowPublic, p as requireOrgMembership, r as DynamicPermissionMatrixConfig, s as anyOf, t as ConnectEventsOptions, u as denyAll, v as requireServiceScope, w as fullPublic, x as when, y as requireTeamMembership } from "../index-C-xjcA6F.mjs";
4
4
  export { ConnectEventsOptions, DynamicPermissionMatrix, DynamicPermissionMatrixConfig, FieldPermission, FieldPermissionMap, FieldPermissionType, PermissionCheck, PermissionContext, PermissionEventBus, PermissionResult, RoleHierarchy, UserBase, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, applyPermissionResult, authenticated, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, denyAll, fields, fullPublic, getUserRoles, normalizePermissionResult, normalizeRoles, ownerWithAdminBypass, presets_d_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, when };
@@ -1,5 +1,5 @@
1
- import { i as resolveEffectiveRoles, n as applyFieldWritePermissions, r as fields, t as applyFieldReadPermissions } from "../fields-ipsbIRPK.mjs";
1
+ import { i as resolveEffectiveRoles, n as applyFieldWritePermissions, r as fields, t as applyFieldReadPermissions } from "../fields-CU6FlaDV.mjs";
2
2
  import { n as normalizeRoles, t as getUserRoles } from "../types-ZUu_h0jp.mjs";
3
- import { n as normalizePermissionResult, t as applyPermissionResult } from "../applyPermissionResult-D6GPMsvh.mjs";
4
- import { C as publicRead, E as createRoleHierarchy, S as presets_exports, T as readOnly, _ as when, a as createOrgPermissions, b as fullPublic, c as requireOrgInScope, d as requireOwnership, f as requireRoles, g as roles, h as requireTeamMembership, i as createDynamicPermissionMatrix, l as requireOrgMembership, m as requireServiceScope, n as allowPublic, o as denyAll, p as requireScopeContext, r as anyOf, s as requireAuth, t as allOf, u as requireOrgRole, v as adminOnly, w as publicReadAdminWrite, x as ownerWithAdminBypass, y as authenticated } from "../permissions-CH4cNwJi.mjs";
3
+ import { n as normalizePermissionResult, t as applyPermissionResult } from "../applyPermissionResult-bqGpo9ML.mjs";
4
+ import { C as publicRead, E as createRoleHierarchy, S as presets_exports, T as readOnly, _ as when, a as createOrgPermissions, b as fullPublic, c as requireOrgInScope, d as requireOwnership, f as requireRoles, g as roles, h as requireTeamMembership, i as createDynamicPermissionMatrix, l as requireOrgMembership, m as requireServiceScope, n as allowPublic, o as denyAll, p as requireScopeContext, r as anyOf, s as requireAuth, t as allOf, u as requireOrgRole, v as adminOnly, w as publicReadAdminWrite, x as ownerWithAdminBypass, y as authenticated } from "../permissions-oNZawnkR.mjs";
5
5
  export { adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, applyPermissionResult, authenticated, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, denyAll, fields, fullPublic, getUserRoles, normalizePermissionResult, normalizeRoles, ownerWithAdminBypass, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, when };
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
2
2
  import { _ as isElevated, b as isService, c as getRequestScope, d as getServiceScopes, f as getTeamId, h as hasOrgAccess, l as getScopeContext, p as getUserId, u as getScopeContextMap, v as isMember, y as isOrgInScope } from "./types-AOD8fxIw.mjs";
3
3
  import { t as getUserRoles } from "./types-ZUu_h0jp.mjs";
4
- import { t as MemoryCacheStore } from "./memory-Cp7_cAko.mjs";
4
+ import { t as MemoryCacheStore } from "./memory-BFAYkf8H.mjs";
5
5
  import { randomUUID } from "node:crypto";
6
6
  //#region src/permissions/roleHierarchy.ts
7
7
  /**
@@ -1,7 +1,7 @@
1
- import { K as MiddlewareConfig, Kt as ResourceRegistry, Tn as HookSystem, et as PresetHook, m as AnyRecord, p as AdditionalRoute, vt as RouteSchemaOptions } from "../interface-CMRutPfe.mjs";
2
- import { t as ExternalOpenApiPaths } from "../externalPaths-BnkYrNzp.mjs";
3
- import { _ as _default$1, a as _default$7, c as MetricsCollector, d as metricsPlugin, f as SSEOptions, g as CachingRule, h as CachingOptions, i as VersioningOptions, l as MetricsOptions, m as ssePlugin, n as ErrorMapper, o as versioningPlugin, p as _default$6, r as errorHandlerPlugin, s as MetricEntry, t as ErrorHandlerOptions, u as _default$4, v as cachingPlugin } from "../errorHandler-Bah5JhBd.mjs";
4
- import { t as TracingOptions } from "../tracing-DdN2-wHJ.mjs";
1
+ import { $ as PresetHook, G as MiddlewareConfig, Gt as ResourceRegistry, Tn as HookSystem, _t as RouteSchemaOptions, mt as RouteDefinition, p as AnyRecord } from "../interface-YrWsmKqE.mjs";
2
+ import { t as ExternalOpenApiPaths } from "../externalPaths-Bapitwvd.mjs";
3
+ import { _ as CachingRule, a as VersioningOptions, c as MetricEntry, d as _default$4, f as metricsPlugin, g as CachingOptions, h as ssePlugin, i as errorHandlerPlugin, l as MetricsCollector, m as _default$6, n as ErrorMapper, o as _default$7, p as SSEOptions, r as defaultIsDuplicateKeyError, s as versioningPlugin, t as ErrorHandlerOptions, u as MetricsOptions, v as _default$1, y as cachingPlugin } from "../errorHandler-DixGcttC.mjs";
4
+ import { t as TracingOptions } from "../tracing-xqXzWeaf.mjs";
5
5
  import { FastifyInstance, FastifyPluginAsync } from "fastify";
6
6
  import * as _$node_stream0 from "node:stream";
7
7
 
@@ -42,8 +42,8 @@ declare const _default: FastifyPluginAsync<ArcCorePluginOptions>;
42
42
  //#endregion
43
43
  //#region src/plugins/createPlugin.d.ts
44
44
  interface PluginResourceResult {
45
- /** Additional routes to add to the resource */
46
- additionalRoutes?: AdditionalRoute[];
45
+ /** Additional routes to add to the resource (v2.8 `RouteDefinition` shape) */
46
+ routes?: RouteDefinition[];
47
47
  /** Middlewares per operation */
48
48
  middlewares?: MiddlewareConfig;
49
49
  /** Hooks to register */
@@ -213,4 +213,4 @@ declare module "fastify" {
213
213
  declare const requestIdPlugin: FastifyPluginAsync<RequestIdOptions>;
214
214
  declare const _default$5: FastifyPluginAsync<RequestIdOptions>;
215
215
  //#endregion
216
- export { type ArcCore, type ArcCorePluginOptions, type ArcPlugin, type CachingOptions, type CachingRule, type CreatePluginDefinition, type ErrorHandlerOptions, type ErrorMapper, type GracefulShutdownOptions, type HealthCheck, type HealthOptions, type MetricEntry, type MetricsCollector, type MetricsOptions, type PluginMeta, type PluginResourceResult, type RequestIdOptions, type SSEOptions, type TracingOptions, type VersioningOptions, _default as arcCorePlugin, arcCorePlugin as arcCorePluginFn, _default$1 as cachingPlugin, cachingPlugin as cachingPluginFn, createPlugin, errorHandlerPlugin, errorHandlerPlugin as errorHandlerPluginFn, _default$2 as gracefulShutdownPlugin, gracefulShutdownPlugin as gracefulShutdownPluginFn, _default$3 as healthPlugin, healthPlugin as healthPluginFn, _default$4 as metricsPlugin, metricsPlugin as metricsPluginFn, replyHelpersPlugin, _default$5 as requestIdPlugin, requestIdPlugin as requestIdPluginFn, _default$6 as ssePlugin, ssePlugin as ssePluginFn, _default$7 as versioningPlugin, versioningPlugin as versioningPluginFn };
216
+ export { type ArcCore, type ArcCorePluginOptions, type ArcPlugin, type CachingOptions, type CachingRule, type CreatePluginDefinition, type ErrorHandlerOptions, type ErrorMapper, type GracefulShutdownOptions, type HealthCheck, type HealthOptions, type MetricEntry, type MetricsCollector, type MetricsOptions, type PluginMeta, type PluginResourceResult, type RequestIdOptions, type SSEOptions, type TracingOptions, type VersioningOptions, _default as arcCorePlugin, arcCorePlugin as arcCorePluginFn, _default$1 as cachingPlugin, cachingPlugin as cachingPluginFn, createPlugin, defaultIsDuplicateKeyError, errorHandlerPlugin, errorHandlerPlugin as errorHandlerPluginFn, _default$2 as gracefulShutdownPlugin, gracefulShutdownPlugin as gracefulShutdownPluginFn, _default$3 as healthPlugin, healthPlugin as healthPluginFn, _default$4 as metricsPlugin, metricsPlugin as metricsPluginFn, replyHelpersPlugin, _default$5 as requestIdPlugin, requestIdPlugin as requestIdPluginFn, _default$6 as ssePlugin, ssePlugin as ssePluginFn, _default$7 as versioningPlugin, versioningPlugin as versioningPluginFn };
@@ -1,15 +1,15 @@
1
1
  import { p as MUTATION_OPERATIONS } from "../constants-Cxde4rpC.mjs";
2
2
  import { o as getOrgId } from "../types-AOD8fxIw.mjs";
3
- import { t as requestContext } from "../requestContext-DYvHl113.mjs";
4
- import { t as hasEvents } from "../typeGuards-CcFZXgU7.mjs";
5
- import { t as HookSystem } from "../HookSystem-HprTmvVY.mjs";
6
- import { t as ResourceRegistry } from "../ResourceRegistry-C6uXlWe3.mjs";
7
- import { n as caching_default, t as cachingPlugin } from "../caching-IMuYVjTL.mjs";
8
- import { t as errorHandlerPlugin } from "../errorHandler-f869_8PQ.mjs";
9
- import { n as metrics_default, t as metricsPlugin } from "../metrics-B-PU4-Yu.mjs";
10
- import { t as replyHelpersPlugin } from "../replyHelpers-CxkYGT81.mjs";
11
- import { n as sse_default, t as ssePlugin } from "../sse-Ad7ypl9e.mjs";
12
- import { n as versioning_default, t as versioningPlugin } from "../versioning-CDugduqI.mjs";
3
+ import { t as requestContext } from "../requestContext-DYtmNpm5.mjs";
4
+ import { t as hasEvents } from "../typeGuards-Cj5Rgvlg.mjs";
5
+ import { t as HookSystem } from "../HookSystem-BjFu7zf1.mjs";
6
+ import { t as ResourceRegistry } from "../ResourceRegistry-Dq3_zBQP.mjs";
7
+ import { n as caching_default, t as cachingPlugin } from "../caching-CjybdRwx.mjs";
8
+ import { n as errorHandlerPlugin, t as defaultIsDuplicateKeyError } from "../errorHandler-CZDW4EXS.mjs";
9
+ import { n as metrics_default, t as metricsPlugin } from "../metrics-TuOmguhi.mjs";
10
+ import { t as replyHelpersPlugin } from "../replyHelpers-BLojtuvR.mjs";
11
+ import { n as sse_default, t as ssePlugin } from "../sse-CJpt7LGI.mjs";
12
+ import { n as versioning_default, t as versioningPlugin } from "../versioning-Cm8qoFDg.mjs";
13
13
  import { randomUUID } from "node:crypto";
14
14
  import fp from "fastify-plugin";
15
15
  //#region src/core/arcCorePlugin.ts
@@ -410,4 +410,4 @@ var requestId_default = fp(requestIdPlugin, {
410
410
  fastify: "5.x"
411
411
  });
412
412
  //#endregion
413
- export { arcCorePlugin_default as arcCorePlugin, arcCorePlugin as arcCorePluginFn, caching_default as cachingPlugin, cachingPlugin as cachingPluginFn, createPlugin, errorHandlerPlugin, errorHandlerPlugin as errorHandlerPluginFn, gracefulShutdown_default as gracefulShutdownPlugin, gracefulShutdownPlugin as gracefulShutdownPluginFn, health_default as healthPlugin, healthPlugin as healthPluginFn, metrics_default as metricsPlugin, metricsPlugin as metricsPluginFn, replyHelpersPlugin, requestId_default as requestIdPlugin, requestIdPlugin as requestIdPluginFn, sse_default as ssePlugin, ssePlugin as ssePluginFn, versioning_default as versioningPlugin, versioningPlugin as versioningPluginFn };
413
+ export { arcCorePlugin_default as arcCorePlugin, arcCorePlugin as arcCorePluginFn, caching_default as cachingPlugin, cachingPlugin as cachingPluginFn, createPlugin, defaultIsDuplicateKeyError, errorHandlerPlugin, errorHandlerPlugin as errorHandlerPluginFn, gracefulShutdown_default as gracefulShutdownPlugin, gracefulShutdownPlugin as gracefulShutdownPluginFn, health_default as healthPlugin, healthPlugin as healthPluginFn, metrics_default as metricsPlugin, metricsPlugin as metricsPluginFn, replyHelpersPlugin, requestId_default as requestIdPlugin, requestIdPlugin as requestIdPluginFn, sse_default as ssePlugin, ssePlugin as ssePluginFn, versioning_default as versioningPlugin, versioningPlugin as versioningPluginFn };
@@ -1,4 +1,4 @@
1
- import { t as hasEvents } from "../typeGuards-CcFZXgU7.mjs";
1
+ import { t as hasEvents } from "../typeGuards-Cj5Rgvlg.mjs";
2
2
  import fp from "fastify-plugin";
3
3
  //#region src/plugins/response-cache.ts
4
4
  /**
@@ -1,2 +1,2 @@
1
- import { a as traced, i as isTracingAvailable, n as _default, r as createSpan, t as TracingOptions } from "../tracing-DdN2-wHJ.mjs";
1
+ import { a as traced, i as isTracingAvailable, n as _default, r as createSpan, t as TracingOptions } from "../tracing-xqXzWeaf.mjs";
2
2
  export { type TracingOptions, createSpan, isTracingAvailable, traced, _default as tracingPlugin };
@@ -44,7 +44,7 @@ try {
44
44
  function createTracerProvider(options) {
45
45
  if (!isAvailable) return null;
46
46
  const { serviceName = "@classytic/arc", serviceVersion, exporterUrl = "http://localhost:4318/v1/traces" } = options;
47
- const resolvedVersion = serviceVersion ?? "2.8.5";
47
+ const resolvedVersion = serviceVersion ?? "2.9.1";
48
48
  const exporter = new OTLPTraceExporter({ url: exporterUrl });
49
49
  const provider = new NodeTracerProvider({ resource: { attributes: {
50
50
  "service.name": serviceName,
@@ -16,21 +16,21 @@ interface PolicyResult {
16
16
  */
17
17
  reason?: string;
18
18
  /**
19
- * Query filters to apply (for list operations)
19
+ * Query filters to apply (for list operations).
20
+ *
21
+ * Values are `unknown` because filter dialects differ (MongoDB operator
22
+ * objects, SQL WHERE AST, structured DSLs) — adapters narrow at the edge.
20
23
  *
21
24
  * @example
22
25
  * ```typescript
23
26
  * // Multi-tenant filter
24
27
  * { organizationId: user.organizationId }
25
28
  *
26
- * // Ownership filter
27
- * { userId: user.id }
28
- *
29
29
  * // Complex filter
30
30
  * { $or: [{ public: true }, { createdBy: user.id }] }
31
31
  * ```
32
32
  */
33
- filters?: Record<string, any>;
33
+ filters?: Record<string, unknown>;
34
34
  /**
35
35
  * Fields to include/exclude in response
36
36
  *
@@ -48,7 +48,7 @@ interface PolicyResult {
48
48
  exclude?: string[];
49
49
  };
50
50
  /**
51
- * Additional context for downstream middleware
51
+ * Additional context for downstream middleware.
52
52
  *
53
53
  * @example
54
54
  * ```typescript
@@ -58,34 +58,27 @@ interface PolicyResult {
58
58
  * }
59
59
  * ```
60
60
  */
61
- metadata?: Record<string, any>;
61
+ metadata?: Record<string, unknown>;
62
62
  }
63
63
  /**
64
- * Policy context provided to can() method
64
+ * Policy context provided to `can()`.
65
+ *
66
+ * Fields are `unknown` by design: the shape depends on the adapter and the
67
+ * operation (e.g. `document` is the repository's row type, `body` is the
68
+ * wire DTO). Implementations narrow at the call site with a type guard or
69
+ * generic — this is the only honest contract across adapters.
65
70
  */
66
71
  interface PolicyContext {
67
- /**
68
- * The document being accessed (for update/delete/get)
69
- * Populated by fetchDocument middleware
70
- */
71
- document?: any;
72
- /**
73
- * Request body (for create/update)
74
- */
75
- body?: any;
76
- /**
77
- * Request params (e.g., :id from route)
78
- */
79
- params?: any;
80
- /**
81
- * Request query parameters
82
- */
83
- query?: any;
84
- /**
85
- * Additional app-specific context
86
- * Can include anything your policy needs to make decisions
87
- */
88
- [key: string]: any;
72
+ /** The document being accessed (for update/delete/get). Populated by fetchDocument middleware. */
73
+ document?: unknown;
74
+ /** Request body (for create/update). */
75
+ body?: unknown;
76
+ /** Request params (e.g., `:id` from route). */
77
+ params?: unknown;
78
+ /** Request query parameters. */
79
+ query?: unknown;
80
+ /** Additional app-specific context keyed by policy-defined names. */
81
+ [key: string]: unknown;
89
82
  }
90
83
  /**
91
84
  * Policy Engine Interface
@@ -193,7 +186,7 @@ interface PolicyEngine {
193
186
  * }
194
187
  * ```
195
188
  */
196
- can(user: any, operation: string, context?: PolicyContext): PolicyResult | Promise<PolicyResult>;
189
+ can(user: unknown, operation: string, context?: PolicyContext): PolicyResult | Promise<PolicyResult>;
197
190
  /**
198
191
  * Generate Fastify middleware for this policy
199
192
  *
@@ -235,7 +228,7 @@ interface PolicyEngine {
235
228
  * });
236
229
  * ```
237
230
  */
238
- type PolicyFactory<TConfig = any> = (config: TConfig) => PolicyEngine;
231
+ type PolicyFactory<TConfig = unknown> = (config: TConfig) => PolicyEngine;
239
232
  /**
240
233
  * Extended Fastify request with policy result
241
234
  */
@@ -1,7 +1,7 @@
1
1
  import { r as RequestScope } from "../types-BD85MlEK.mjs";
2
- import { tt as PresetResult } from "../interface-CMRutPfe.mjs";
2
+ import { et as PresetResult } from "../interface-YrWsmKqE.mjs";
3
3
  import { t as PermissionCheck } from "../types-DZi1aYhm.mjs";
4
- import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-Dfzt4VTl.mjs";
4
+ import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-BwGQXUpd.mjs";
5
5
 
6
6
  //#region src/presets/filesUpload.d.ts
7
7
  interface FilesUploadPresetRoutes {
@@ -14,6 +14,20 @@ interface FilesUploadPresetPermissions {
14
14
  read?: PermissionCheck;
15
15
  delete?: PermissionCheck;
16
16
  }
17
+ /**
18
+ * Filename policy — controls how user-supplied filenames are validated before
19
+ * reaching the `Storage.upload()` adapter.
20
+ *
21
+ * - `true` (default): strict — rejects path separators, NULs, `.`/`..`, empty,
22
+ * and names >255 chars. Safe default for disk/S3/prefix-joining adapters.
23
+ * - `false` | `'*'`: accept any filename verbatim. Use when the filename is a
24
+ * user-supplied *label* and the adapter generates the storage key itself —
25
+ * typical for microservice ingress, API-server proxies, or content stores
26
+ * that use `id` for the path and treat `filename` as metadata.
27
+ * - function: custom policy. Return a string to *transform* the filename,
28
+ * `false` to reject (triggers `ValidationError`), or `true`/`void` to accept.
29
+ */
30
+ type FilenamePolicy = boolean | "*" | ((filename: string) => string | boolean | void);
17
31
  interface FilesUploadPresetOptions {
18
32
  /** Any implementation of the `Storage` interface. App owns it. */
19
33
  storage: Storage;
@@ -21,8 +35,16 @@ interface FilesUploadPresetOptions {
21
35
  fieldName?: string;
22
36
  /** Max bytes per file. Forwarded to `multipartBody`. Default: 10 MB. */
23
37
  maxFileSize?: number;
24
- /** IANA MIME allow-list. Forwarded to `multipartBody`. Default: no filter. */
38
+ /**
39
+ * IANA MIME allow-list. Forwarded to `multipartBody`. Default: no filter.
40
+ * Pass `['*']` to explicitly allow any type (equivalent to omitting).
41
+ */
25
42
  allowedMimeTypes?: string[];
43
+ /**
44
+ * Filename validation policy. Default: `true` (strict).
45
+ * See {@link FilenamePolicy}.
46
+ */
47
+ sanitizeFilename?: FilenamePolicy;
26
48
  /**
27
49
  * Per-route permissions.
28
50
  * Defaults: upload → `requireAuth()`, read → `allowPublic()`, delete → `requireAuth()`.
@@ -46,4 +68,4 @@ interface FilesUploadPresetOptions {
46
68
  */
47
69
  declare function filesUploadPreset(options: FilesUploadPresetOptions): PresetResult;
48
70
  //#endregion
49
- export { FilesUploadPresetOptions, FilesUploadPresetPermissions, FilesUploadPresetRoutes, type Storage, type StorageContext, type StorageFile, type StorageReadRange, type StorageReadResult, type StorageUploadInput, filesUploadPreset };
71
+ export { FilenamePolicy, FilesUploadPresetOptions, FilesUploadPresetPermissions, FilesUploadPresetRoutes, type Storage, type StorageContext, type StorageFile, type StorageReadRange, type StorageReadResult, type StorageUploadInput, filesUploadPreset };
@@ -1,2 +1,2 @@
1
- import { t as filesUploadPreset } from "../filesUpload-C7r7HIeA.mjs";
1
+ import { t as filesUploadPreset } from "../filesUpload-q8oHt--L.mjs";
2
2
  export { filesUploadPreset };
@@ -1,6 +1,7 @@
1
- import { Ht as IControllerResponse, Ut as IRequestContext, m as AnyRecord, on as PaginationResult, tt as PresetResult, ut as ResourceConfig } from "../interface-CMRutPfe.mjs";
1
+ import { Ht as IRequestContext, Vt as IControllerResponse, et as PresetResult, lt as ResourceConfig, on as PaginationResult, p as AnyRecord } from "../interface-YrWsmKqE.mjs";
2
2
  import { FilesUploadPresetOptions, FilesUploadPresetPermissions, FilesUploadPresetRoutes, filesUploadPreset } from "./filesUpload.mjs";
3
3
  import { MultiTenantOptions, TenantFieldSpec, multiTenantPreset } from "./multiTenant.mjs";
4
+ import { SearchHandler, SearchPresetOptions, SearchRouteConfig, searchPreset } from "./search.mjs";
4
5
 
5
6
  //#region src/presets/ownedByUser.d.ts
6
7
  interface OwnedByUserOptions {
@@ -272,4 +273,4 @@ type PresetInput = string | PresetResult | {
272
273
  */
273
274
  declare function applyPresets<TDoc = AnyRecord>(config: ResourceConfig<TDoc>, presets?: PresetInput[]): ResourceConfig<TDoc>;
274
275
  //#endregion
275
- export { type AuditedPresetOptions, type BulkOperation, type BulkPresetOptions, type FilesUploadPresetOptions, type FilesUploadPresetPermissions, type FilesUploadPresetRoutes, type IAuditedPreset, type IMultiTenantPreset, type IOwnedByUserPreset, type IPresetController, type ISlugLookupController, type ISoftDeleteController, type ITreeController, type MultiTenantOptions, type OwnedByUserOptions, type SlugLookupOptions, type TenantFieldSpec, type TreeOptions, applyPresets, auditedPreset, bulkPreset, filesUploadPreset, flexibleMultiTenantPreset, getAvailablePresets, getPreset, multiTenantPreset, ownedByUserPreset, registerPreset, slugLookupPreset, softDeletePreset, treePreset };
276
+ export { type AuditedPresetOptions, type BulkOperation, type BulkPresetOptions, type FilesUploadPresetOptions, type FilesUploadPresetPermissions, type FilesUploadPresetRoutes, type IAuditedPreset, type IMultiTenantPreset, type IOwnedByUserPreset, type IPresetController, type ISlugLookupController, type ISoftDeleteController, type ITreeController, type MultiTenantOptions, type OwnedByUserOptions, type SearchHandler, type SearchPresetOptions, type SearchRouteConfig, type SlugLookupOptions, type TenantFieldSpec, type TreeOptions, applyPresets, auditedPreset, bulkPreset, filesUploadPreset, flexibleMultiTenantPreset, getAvailablePresets, getPreset, multiTenantPreset, ownedByUserPreset, registerPreset, searchPreset, slugLookupPreset, softDeletePreset, treePreset };
@@ -1,4 +1,5 @@
1
1
  import { multiTenantPreset } from "./multiTenant.mjs";
2
- import { a as registerPreset, c as auditedPreset, d as ownedByUserPreset, i as getPreset, l as softDeletePreset, n as flexibleMultiTenantPreset, o as treePreset, r as getAvailablePresets, s as bulkPreset, t as applyPresets, u as slugLookupPreset } from "../presets-C2xgzW6x.mjs";
3
- import { t as filesUploadPreset } from "../filesUpload-C7r7HIeA.mjs";
4
- export { applyPresets, auditedPreset, bulkPreset, filesUploadPreset, flexibleMultiTenantPreset, getAvailablePresets, getPreset, multiTenantPreset, ownedByUserPreset, registerPreset, slugLookupPreset, softDeletePreset, treePreset };
2
+ import { a as registerPreset, c as auditedPreset, d as ownedByUserPreset, i as getPreset, l as softDeletePreset, n as flexibleMultiTenantPreset, o as treePreset, r as getAvailablePresets, s as bulkPreset, t as applyPresets, u as slugLookupPreset } from "../presets-hM4WhNWY.mjs";
3
+ import { t as filesUploadPreset } from "../filesUpload-q8oHt--L.mjs";
4
+ import { searchPreset } from "./search.mjs";
5
+ export { applyPresets, auditedPreset, bulkPreset, filesUploadPreset, flexibleMultiTenantPreset, getAvailablePresets, getPreset, multiTenantPreset, ownedByUserPreset, registerPreset, searchPreset, slugLookupPreset, softDeletePreset, treePreset };
@@ -1,4 +1,4 @@
1
- import { E as CrudRouteKey, tt as PresetResult } from "../interface-CMRutPfe.mjs";
1
+ import { T as CrudRouteKey, et as PresetResult } from "../interface-YrWsmKqE.mjs";
2
2
 
3
3
  //#region src/presets/multiTenant.d.ts
4
4
  /**
@@ -144,7 +144,7 @@ function multiTenantPreset(options = {}) {
144
144
  list: [getFilter("list")],
145
145
  get: [getFilter("get")],
146
146
  create: [tenantInjection],
147
- update: [getFilter("update")],
147
+ update: [getFilter("update"), tenantInjection],
148
148
  delete: [getFilter("delete")]
149
149
  }
150
150
  };
@@ -0,0 +1,91 @@
1
+ import { Lt as ControllerHandler, et as PresetResult, gt as RouteMcpConfig, mt as RouteDefinition, o as RepositoryLike } from "../interface-YrWsmKqE.mjs";
2
+ import { t as PermissionCheck } from "../types-DZi1aYhm.mjs";
3
+
4
+ //#region src/presets/search.d.ts
5
+ /**
6
+ * Handler contract — receives arc's `IRequestContext` (same as any `actions` or
7
+ * non-raw route handler) and returns either the raw result (wrapped into
8
+ * `{ success: true, data }` by arc) or an explicit `IControllerResponse`.
9
+ */
10
+ type SearchHandler = ControllerHandler;
11
+ interface SearchRouteConfig {
12
+ /**
13
+ * User-supplied handler. When omitted, the preset auto-synthesises a handler
14
+ * from `options.repository` (calling `repo.search` / `repo.searchSimilar` /
15
+ * `repo.embed` respectively). If `repository` is also absent — or the repo
16
+ * doesn't expose the matching method — the route is NOT mounted.
17
+ */
18
+ handler?: SearchHandler;
19
+ /** HTTP path relative to the resource prefix. Defaults per-kind: `/search`, `/search-similar`, `/embed`. */
20
+ path?: string;
21
+ /** HTTP method. Default: `POST`. */
22
+ method?: "GET" | "POST";
23
+ /** Permission check. Defaults: search/similar fall back to `permissions.list ?? allowPublic()`; embed → `requireAuth()`. */
24
+ permissions?: PermissionCheck;
25
+ /** Fastify/AJV route schema (body/querystring/params/headers/response). */
26
+ schema?: RouteDefinition["schema"];
27
+ /**
28
+ * MCP tool generation.
29
+ * - omitted/true (default): auto-generate the tool from the route
30
+ * - false: skip MCP
31
+ * - object: explicit MCP config
32
+ */
33
+ mcp?: boolean | RouteMcpConfig;
34
+ /** OpenAPI summary. Defaults per-kind. */
35
+ summary?: string;
36
+ /** OpenAPI description. Defaults per-kind. */
37
+ description?: string;
38
+ /** Operation name. Defaults per-kind (`search`, `searchSimilar`, `embed`). */
39
+ operation?: string;
40
+ /** OpenAPI tags. */
41
+ tags?: string[];
42
+ }
43
+ /**
44
+ * Shorthand shape for `search` / `similar` / `embed` sections:
45
+ * - `undefined` → route not mounted
46
+ * - `true` → mount with defaults, auto-wire from `repository`
47
+ * - `SearchRouteConfig` → explicit config (and optional handler override)
48
+ */
49
+ type SearchSection = true | SearchRouteConfig;
50
+ interface SearchPresetOptions {
51
+ /**
52
+ * Repository exposing `search`/`searchSimilar`/`embed`. When provided,
53
+ * any section without an explicit `handler` is auto-wired to the matching
54
+ * repo method. Mongokit's `elasticSearchPlugin` + `vectorPlugin` register
55
+ * exactly these methods — pass the repo once and the handlers are synthesised.
56
+ *
57
+ * Sections set to `true` REQUIRE `repository` (otherwise the route is
58
+ * skipped silently). Sections with an explicit `handler` ignore this field.
59
+ */
60
+ repository?: Pick<RepositoryLike, "search" | "searchSimilar" | "embed">;
61
+ /** Full-text / engine-backed search route. Opt-in. */
62
+ search?: SearchSection;
63
+ /** Vector / semantic similarity route. Opt-in. */
64
+ similar?: SearchSection;
65
+ /** Embedding route (text/media → vector). Opt-in. */
66
+ embed?: SearchSection;
67
+ /**
68
+ * Fully custom routes — merged as-is into the resource's route table.
69
+ * Use this for endpoints that don't fit search/similar/embed naming,
70
+ * e.g. `/autocomplete`, `/reindex`, `/facets`, `/more-like-this`.
71
+ *
72
+ * You are responsible for permissions + schema on each entry.
73
+ */
74
+ routes?: RouteDefinition[];
75
+ }
76
+ /**
77
+ * Create a search preset bound to a resource.
78
+ *
79
+ * Mounts routes only for sections the caller opts into. A section's handler
80
+ * is either:
81
+ * 1. explicit `cfg.handler` — always wins,
82
+ * 2. `options.repository` auto-wire — if the repo exposes the matching
83
+ * method (`search` / `searchSimilar` / `embed`),
84
+ * 3. otherwise the route is silently skipped.
85
+ *
86
+ * The preset itself stays DB-agnostic: nothing is imported from mongokit —
87
+ * it only feature-detects the optional methods on whatever repo you pass.
88
+ */
89
+ declare function searchPreset(options?: SearchPresetOptions): PresetResult;
90
+ //#endregion
91
+ export { SearchHandler, SearchPresetOptions, SearchRouteConfig, SearchSection, searchPreset };
@@ -0,0 +1,150 @@
1
+ import { n as allowPublic, s as requireAuth } from "../permissions-oNZawnkR.mjs";
2
+ //#region src/presets/search.ts
3
+ const BUILTINS = [
4
+ {
5
+ key: "search",
6
+ defaultPath: "/search",
7
+ defaultOperation: "search",
8
+ defaultSummary: "Search",
9
+ defaultDescription: "Full-text / engine-backed search. Delegates to the configured backend.",
10
+ permissionFallback: (p) => p.list ?? allowPublic()
11
+ },
12
+ {
13
+ key: "similar",
14
+ defaultPath: "/search-similar",
15
+ defaultOperation: "searchSimilar",
16
+ defaultSummary: "Semantic search",
17
+ defaultDescription: "Vector / similarity search. Delegates to the configured backend.",
18
+ permissionFallback: (p) => p.list ?? allowPublic()
19
+ },
20
+ {
21
+ key: "embed",
22
+ defaultPath: "/embed",
23
+ defaultOperation: "embed",
24
+ defaultSummary: "Embed",
25
+ defaultDescription: "Return the vector embedding for a text / media input.",
26
+ permissionFallback: () => requireAuth()
27
+ }
28
+ ];
29
+ /**
30
+ * Wrap the user handler to normalise the return shape into arc's envelope.
31
+ * If the handler already returns `{ success, data }`, arc passes it through;
32
+ * otherwise we wrap the raw return value so callers don't have to.
33
+ */
34
+ function wrapEnvelope(handler) {
35
+ return async (req) => {
36
+ const out = await handler(req);
37
+ if (out !== null && typeof out === "object" && "success" in out) return out;
38
+ return {
39
+ success: true,
40
+ data: out
41
+ };
42
+ };
43
+ }
44
+ /**
45
+ * Normalise a section value — `true` → empty config, `undefined` → undefined,
46
+ * object → passthrough. Lets callers write `search: true` to mount with
47
+ * defaults + auto-wire.
48
+ */
49
+ function normaliseSection(value) {
50
+ if (value === void 0) return void 0;
51
+ if (value === true) return {};
52
+ return value;
53
+ }
54
+ /**
55
+ * Build an auto-synthesised handler that proxies the request body to
56
+ * `repo[method]` using each kit's native calling convention. Returns
57
+ * `undefined` when the method isn't present so the caller can fall back to
58
+ * an explicit `cfg.handler` or skip the route.
59
+ *
60
+ * Conventions (verified against mongokit 3.6):
61
+ *
62
+ * - **`search`** (mongokit `elasticSearchPlugin`):
63
+ * `search(query, { limit?, from?, mongoOptions? })` — positional. `query`
64
+ * is the engine-native DSL (e.g. ES `match` clause). Arc passes
65
+ * `(body.query, body)` so the rest of the body flows into options.
66
+ *
67
+ * - **`searchSimilar`** (mongokit `vectorPlugin`):
68
+ * `searchSimilar(params: VectorSearchParams)` — **single object**. `params`
69
+ * carries `query` (vector, text, or multimodal), `limit`, `filter`,
70
+ * `numCandidates`, `exact`, `field`, `minScore`, etc. Arc passes `body`
71
+ * directly so the shapes align. Passing positional args here would
72
+ * silently break (first arg becomes the whole `params`, second arg
73
+ * is ignored).
74
+ *
75
+ * - **`embed`** (mongokit `vectorPlugin`):
76
+ * `embed(input: string | EmbeddingInput)` — single arg. Arc passes
77
+ * `body.input ?? body`, so callers may wrap as `{ input: "…" }` or send
78
+ * the `EmbeddingInput` shape directly.
79
+ */
80
+ function autoHandlerFor(repo, method) {
81
+ if (!repo) return void 0;
82
+ const fn = repo[method];
83
+ if (typeof fn !== "function") return void 0;
84
+ if (method === "embed") return async (req) => {
85
+ const body = req.body ?? {};
86
+ return fn(body.input ?? body);
87
+ };
88
+ if (method === "searchSimilar") return async (req) => {
89
+ return fn(req.body ?? {});
90
+ };
91
+ return async (req) => {
92
+ const body = req.body ?? {};
93
+ return fn(body.query, body);
94
+ };
95
+ }
96
+ /**
97
+ * Create a search preset bound to a resource.
98
+ *
99
+ * Mounts routes only for sections the caller opts into. A section's handler
100
+ * is either:
101
+ * 1. explicit `cfg.handler` — always wins,
102
+ * 2. `options.repository` auto-wire — if the repo exposes the matching
103
+ * method (`search` / `searchSimilar` / `embed`),
104
+ * 3. otherwise the route is silently skipped.
105
+ *
106
+ * The preset itself stays DB-agnostic: nothing is imported from mongokit —
107
+ * it only feature-detects the optional methods on whatever repo you pass.
108
+ */
109
+ function searchPreset(options = {}) {
110
+ const sections = {
111
+ search: normaliseSection(options.search),
112
+ similar: normaliseSection(options.similar),
113
+ embed: normaliseSection(options.embed)
114
+ };
115
+ const extraRoutes = options.routes ?? [];
116
+ const repoMethodFor = {
117
+ search: "search",
118
+ similar: "searchSimilar",
119
+ embed: "embed"
120
+ };
121
+ return {
122
+ name: "search",
123
+ routes: (permissions) => {
124
+ const mounted = [];
125
+ for (const spec of BUILTINS) {
126
+ const cfg = sections[spec.key];
127
+ if (!cfg) continue;
128
+ const handler = cfg.handler ?? autoHandlerFor(options.repository, repoMethodFor[spec.key]);
129
+ if (!handler) continue;
130
+ const route = {
131
+ method: cfg.method ?? "POST",
132
+ path: cfg.path ?? spec.defaultPath,
133
+ operation: cfg.operation ?? spec.defaultOperation,
134
+ summary: cfg.summary ?? spec.defaultSummary,
135
+ description: cfg.description ?? spec.defaultDescription,
136
+ tags: cfg.tags,
137
+ permissions: cfg.permissions ?? spec.permissionFallback(permissions),
138
+ schema: cfg.schema,
139
+ mcp: cfg.mcp,
140
+ handler: wrapEnvelope(handler)
141
+ };
142
+ mounted.push(route);
143
+ }
144
+ for (const r of extraRoutes) mounted.push(r);
145
+ return mounted;
146
+ }
147
+ };
148
+ }
149
+ //#endregion
150
+ export { searchPreset };
@@ -1,6 +1,6 @@
1
1
  import { _ as isElevated, n as PUBLIC_SCOPE } from "./types-AOD8fxIw.mjs";
2
2
  import { multiTenantPreset } from "./presets/multiTenant.mjs";
3
- import { f as requireRoles, n as allowPublic, s as requireAuth } from "./permissions-CH4cNwJi.mjs";
3
+ import { f as requireRoles, n as allowPublic, s as requireAuth } from "./permissions-oNZawnkR.mjs";
4
4
  //#region src/presets/ownedByUser.ts
5
5
  /**
6
6
  * Create ownership check middleware.
@@ -1,4 +1,4 @@
1
- import { i as CacheStore } from "./interface-4y979v99.mjs";
1
+ import { i as CacheStore } from "./interface-DplgQO2e.mjs";
2
2
  import { FastifyPluginAsync } from "fastify";
3
3
 
4
4
  //#region src/cache/QueryCache.d.ts
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
2
2
  import { i as versionKey, r as tagVersionKey } from "./keys-qcD-TVJl.mjs";
3
- import { t as hasEvents } from "./typeGuards-CcFZXgU7.mjs";
4
- import { t as MemoryCacheStore } from "./memory-Cp7_cAko.mjs";
3
+ import { t as hasEvents } from "./typeGuards-Cj5Rgvlg.mjs";
4
+ import { t as MemoryCacheStore } from "./memory-BFAYkf8H.mjs";
5
5
  import fp from "fastify-plugin";
6
6
  //#region src/cache/QueryCache.ts
7
7
  var QueryCache = class {
@@ -1,4 +1,4 @@
1
- import { n as IdempotencyResult, r as IdempotencyStore } from "./interface-DfLGcus7.mjs";
1
+ import { n as IdempotencyResult, r as IdempotencyStore } from "./interface-B-pe8fhj.mjs";
2
2
 
3
3
  //#region src/idempotency/stores/redis.d.ts
4
4
  interface RedisClient {
@@ -1,4 +1,4 @@
1
- import { i as EventTransport, n as EventHandler, r as EventLogger, t as DomainEvent } from "./EventTransport-BXja8NOc.mjs";
1
+ import { i as EventLogger, n as DomainEvent, o as EventTransport, r as EventHandler } from "./EventTransport-CqZ8FyM_.mjs";
2
2
 
3
3
  //#region src/events/transports/redis-stream.d.ts
4
4
  interface RedisStreamLike {
@@ -1,4 +1,4 @@
1
- import { Gt as RegisterOptions, H as IntrospectionPluginOptions, Kt as ResourceRegistry } from "../interface-CMRutPfe.mjs";
1
+ import { Gt as ResourceRegistry, V as IntrospectionPluginOptions, Wt as RegisterOptions } from "../interface-YrWsmKqE.mjs";
2
2
  import { FastifyPluginAsync } from "fastify";
3
3
 
4
4
  //#region src/registry/introspectionPlugin.d.ts
@@ -1,3 +1,3 @@
1
- import { n as introspectionPlugin_default, t as introspectionPlugin } from "../registry-BiTKT1Dg.mjs";
2
- import { t as ResourceRegistry } from "../ResourceRegistry-C6uXlWe3.mjs";
1
+ import { n as introspectionPlugin_default, t as introspectionPlugin } from "../registry-B0Wl7uVV.mjs";
2
+ import { t as ResourceRegistry } from "../ResourceRegistry-Dq3_zBQP.mjs";
3
3
  export { ResourceRegistry, introspectionPlugin_default as introspectionPlugin, introspectionPlugin as introspectionPluginFn };