@classytic/arc 2.8.5 → 2.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -38
- package/dist/{BaseController-DAGGc5Xn.mjs → BaseController-CbKKIflT.mjs} +193 -143
- package/dist/EventTransport-CUw5NNWe.d.mts +293 -0
- package/dist/{ResourceRegistry-C6uXlWe3.mjs → ResourceRegistry-BPd6NQDm.mjs} +1 -1
- package/dist/adapters/index.d.mts +3 -3
- package/dist/adapters/index.mjs +2 -2
- package/dist/{adapters-BBqAVvPK.mjs → adapters-BXY4i-hw.mjs} +210 -41
- package/dist/audit/index.d.mts +135 -11
- package/dist/audit/index.mjs +107 -20
- package/dist/auth/index.d.mts +17 -9
- package/dist/auth/index.mjs +14 -7
- package/dist/auth/redis-session.d.mts +1 -1
- package/dist/{betterAuthOpenApi-BuUcUEJq.mjs → betterAuthOpenApi-BBRVhjQN.mjs} +1 -1
- package/dist/cache/index.d.mts +17 -15
- package/dist/cache/index.mjs +15 -14
- package/dist/{caching-IMuYVjTL.mjs → caching-CBpK_SCM.mjs} +8 -3
- package/dist/cli/commands/describe.mjs +1 -1
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/generate.mjs +1 -1
- package/dist/cli/commands/init.mjs +1 -1
- package/dist/cli/commands/introspect.mjs +1 -1
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +4 -6
- package/dist/{defineResource-tcgySDo1.mjs → core-CcR01lup.mjs} +58 -61
- package/dist/{createActionRouter-BORM8f17.mjs → createActionRouter-Bp_5c_2b.mjs} +3 -3
- package/dist/{createApp-B1EY8zxa.mjs → createApp-BuvPma24.mjs} +15 -14
- package/dist/docs/index.d.mts +2 -2
- package/dist/docs/index.mjs +2 -2
- package/dist/{elevation-DtFxrG0s.mjs → elevation-C7hgL_aI.mjs} +22 -8
- package/dist/{errorHandler-f869_8PQ.mjs → errorHandler-Bb49BvPD.mjs} +59 -7
- package/dist/{errorHandler-Bah5JhBd.d.mts → errorHandler-DRQ3EqfL.d.mts} +37 -2
- package/dist/{eventPlugin-D9DKB2zM.d.mts → eventPlugin-CxWgpd6K.d.mts} +14 -2
- package/dist/{eventPlugin-CDjVTM82.mjs → eventPlugin-DCUjuiQT.mjs} +83 -5
- package/dist/events/index.d.mts +150 -36
- package/dist/events/index.mjs +355 -101
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis.d.mts +1 -1
- package/dist/factory/index.d.mts +1 -1
- package/dist/factory/index.mjs +2 -2
- package/dist/{types-DZi1aYhm.d.mts → fields-Lo1VUDpt.d.mts} +121 -1
- package/dist/{fields-ipsbIRPK.mjs → fields-bxkeltzz.mjs} +18 -5
- package/dist/{filesUpload-C7r7HIeA.mjs → filesUpload-t21LS-py.mjs} +65 -7
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.mjs +1 -1
- package/dist/idempotency/index.d.mts +32 -5
- package/dist/idempotency/index.mjs +119 -12
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/{index-DtDzOBn8.d.mts → index-8qw4y6ff.d.mts} +4 -135
- package/dist/{index-BLXBmWud.d.mts → index-ChIw3776.d.mts} +283 -408
- package/dist/{interface-CMRutPfe.d.mts → index-Cl0uoKd5.d.mts} +1758 -2506
- package/dist/{index-C1meYuDn.d.mts → index-DStwgFUK.d.mts} +81 -7
- package/dist/index.d.mts +7 -8
- package/dist/index.mjs +11 -12
- package/dist/integrations/event-gateway.d.mts +1 -1
- package/dist/integrations/event-gateway.mjs +1 -1
- package/dist/integrations/index.d.mts +1 -1
- package/dist/integrations/mcp/index.d.mts +26 -8
- package/dist/integrations/mcp/index.mjs +96 -17
- package/dist/integrations/mcp/testing.d.mts +1 -1
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/integrations/webhooks.d.mts +5 -0
- package/dist/integrations/webhooks.mjs +6 -0
- package/dist/interface-D218ikEo.d.mts +77 -0
- package/dist/{memory-Cp7_cAko.mjs → memory-B5Amv9A1.mjs} +23 -8
- package/dist/{openapi-CbKUJY_m.mjs → openapi-B5F8AddX.mjs} +3 -3
- package/dist/org/index.d.mts +2 -2
- package/dist/permissions/index.d.mts +3 -4
- package/dist/permissions/index.mjs +5 -5
- package/dist/{permissions-CH4cNwJi.mjs → permissions-Dk6mshja.mjs} +315 -397
- package/dist/plugins/index.d.mts +7 -7
- package/dist/plugins/index.mjs +14 -16
- package/dist/plugins/response-cache.mjs +2 -2
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/presets/filesUpload.d.mts +27 -5
- package/dist/presets/filesUpload.mjs +1 -1
- package/dist/presets/index.d.mts +3 -2
- package/dist/presets/index.mjs +4 -3
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/presets/multiTenant.mjs +2 -2
- package/dist/presets/search.d.mts +178 -0
- package/dist/presets/search.mjs +150 -0
- package/dist/{presets-C2xgzW6x.mjs → presets-fLJVXdVn.mjs} +1 -1
- package/dist/{queryCachePlugin-BJJGBTlu.d.mts → queryCachePlugin-BKbWjgDG.d.mts} +1 -1
- package/dist/{queryCachePlugin-BH-fidlv.mjs → queryCachePlugin-DQCEfJis.mjs} +9 -9
- package/dist/{queryParser-CgCtsjti.mjs → queryParser-DBqBB6AC.mjs} +1 -1
- package/dist/{redis-BM00zaPB.d.mts → redis-DqyeggCa.d.mts} +1 -1
- package/dist/{redis-stream-CrsfUmPt.d.mts → redis-stream-CakIQmwR.d.mts} +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +2 -2
- package/dist/{resourceToTools-8s-EsCCe.mjs → resourceToTools-BElv3xPT.mjs} +65 -48
- package/dist/{schemaConverter-Y7nCYaLJ.mjs → schemaConverter-BxFDdtXu.mjs} +1 -1
- package/dist/scope/index.d.mts +1 -1
- package/dist/scope/index.mjs +2 -2
- package/dist/{sse-Ad7ypl9e.mjs → sse-yBCgOLGu.mjs} +1 -1
- package/dist/store-helpers-ZCSMJJAX.mjs +57 -0
- package/dist/testing/index.d.mts +9 -17
- package/dist/testing/index.mjs +27 -83
- package/dist/testing/storageContract.d.mts +1 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/types/index.mjs +1 -31
- package/dist/types/storage.d.mts +1 -1
- package/dist/{types-BsbNMEDR.d.mts → types-Btdda02s.d.mts} +1 -1
- package/dist/{types-Ch9pTQbf.d.mts → types-Co8k3NyS.d.mts} +11 -9
- package/dist/types-Csi3FLfq.mjs +27 -0
- package/dist/utils/index.d.mts +208 -4
- package/dist/utils/index.mjs +5 -6
- package/dist/{utils-yYT3HDXt.mjs → utils-B2fNOD_i.mjs} +285 -2
- package/dist/{versioning-CDugduqI.mjs → versioning-C2U_bLY0.mjs} +3 -5
- package/package.json +20 -26
- package/skills/arc/SKILL.md +97 -23
- package/skills/arc/references/auth.md +94 -0
- package/skills/arc/references/events.md +200 -12
- package/skills/arc/references/mcp.md +4 -17
- package/skills/arc/references/multi-tenancy.md +43 -0
- package/skills/arc/references/production.md +34 -60
- package/dist/EventTransport-BXja8NOc.d.mts +0 -135
- package/dist/audit/mongodb.d.mts +0 -2
- package/dist/audit/mongodb.mjs +0 -2
- package/dist/circuitBreaker-cmi5XDv5.mjs +0 -284
- package/dist/circuitBreaker-dTtG-UyS.d.mts +0 -206
- package/dist/core-F0QoWBt2.mjs +0 -34
- package/dist/dynamic/index.d.mts +0 -93
- package/dist/dynamic/index.mjs +0 -122
- package/dist/fields-DpZQa_Q3.d.mts +0 -109
- package/dist/idempotency/mongodb.d.mts +0 -2
- package/dist/idempotency/mongodb.mjs +0 -123
- package/dist/interface-4y979v99.d.mts +0 -54
- package/dist/mongodb-BsP-WbhN.d.mts +0 -127
- package/dist/mongodb-CTcp0hQZ.d.mts +0 -80
- package/dist/mongodb-Utc5k_-0.mjs +0 -90
- package/dist/policies/index.d.mts +0 -432
- package/dist/policies/index.mjs +0 -318
- package/dist/rpc/index.d.mts +0 -90
- package/dist/rpc/index.mjs +0 -248
- /package/dist/{HookSystem-HprTmvVY.mjs → HookSystem-BNYKnrXF.mjs} +0 -0
- /package/dist/{applyPermissionResult-D6GPMsvh.mjs → applyPermissionResult-QhV1Pa-g.mjs} +0 -0
- /package/dist/{constants-Cxde4rpC.mjs → constants-BhY1OHoH.mjs} +0 -0
- /package/dist/{elevation-B6S5csVA.d.mts → elevation-C5SwtkAn.d.mts} +0 -0
- /package/dist/{errors-Ck2h67pm.d.mts → errors-CCSsMpXE.d.mts} +0 -0
- /package/dist/{errors-BF2bIOIS.mjs → errors-D5c-5BJL.mjs} +0 -0
- /package/dist/{externalPaths-BnkYrNzp.d.mts → externalPaths-BQ8QijNH.d.mts} +0 -0
- /package/dist/{interface-DfLGcus7.d.mts → interface-CSbZdv_3.d.mts} +0 -0
- /package/dist/{loadResources-PWd0OCpV.mjs → loadResources-BAzJItAJ.mjs} +0 -0
- /package/dist/{logger-D1YrIImS.mjs → logger-DLg8-Ueg.mjs} +0 -0
- /package/dist/{metrics-B-PU4-Yu.mjs → metrics-DuhiSEZI.mjs} +0 -0
- /package/dist/{pluralize-CWP6MB39.mjs → pluralize-A0tWEl1K.mjs} +0 -0
- /package/dist/{registry-BiTKT1Dg.mjs → registry-B3lRFBWo.mjs} +0 -0
- /package/dist/{replyHelpers-CxkYGT81.mjs → replyHelpers-CXtJDAZ0.mjs} +0 -0
- /package/dist/{requestContext-DYvHl113.mjs → requestContext-xHIKedG6.mjs} +0 -0
- /package/dist/{sessionManager-DDCmiNIo.d.mts → sessionManager-BkzVU8h2.d.mts} +0 -0
- /package/dist/{storage-Dfzt4VTl.d.mts → storage-CVk_SEn2.d.mts} +0 -0
- /package/dist/{tracing-DdN2-wHJ.d.mts → tracing-65B51Dw3.d.mts} +0 -0
- /package/dist/{typeGuards-CcFZXgU7.mjs → typeGuards-Cj5Rgvlg.mjs} +0 -0
- /package/dist/{types-ZUu_h0jp.mjs → types-DV9WDfeg.mjs} +0 -0
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as ExternalOpenApiPaths } from "../externalPaths-
|
|
3
|
-
import { _ as
|
|
4
|
-
import { t as TracingOptions } from "../tracing-
|
|
1
|
+
import { W as ResourceRegistry, at as PresetHook, dn as AnyRecord, gt as RouteSchemaOptions, nt as MiddlewareConfig, pt as RouteDefinition, tn as HookSystem } from "../index-Cl0uoKd5.mjs";
|
|
2
|
+
import { t as ExternalOpenApiPaths } from "../externalPaths-BQ8QijNH.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-DRQ3EqfL.mjs";
|
|
4
|
+
import { t as TracingOptions } from "../tracing-65B51Dw3.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
|
-
|
|
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 };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { p as MUTATION_OPERATIONS } from "../constants-
|
|
1
|
+
import { p as MUTATION_OPERATIONS } from "../constants-BhY1OHoH.mjs";
|
|
2
2
|
import { o as getOrgId } from "../types-AOD8fxIw.mjs";
|
|
3
|
-
import { t as requestContext } from "../requestContext-
|
|
4
|
-
import { t as hasEvents } from "../typeGuards-
|
|
5
|
-
import { t as HookSystem } from "../HookSystem-
|
|
6
|
-
import { t as ResourceRegistry } from "../ResourceRegistry-
|
|
7
|
-
import { n as caching_default, t as cachingPlugin } from "../caching-
|
|
8
|
-
import {
|
|
9
|
-
import { n as metrics_default, t as metricsPlugin } from "../metrics-
|
|
10
|
-
import { t as replyHelpersPlugin } from "../replyHelpers-
|
|
11
|
-
import { n as sse_default, t as ssePlugin } from "../sse-
|
|
12
|
-
import { n as versioning_default, t as versioningPlugin } from "../versioning-
|
|
3
|
+
import { t as requestContext } from "../requestContext-xHIKedG6.mjs";
|
|
4
|
+
import { t as hasEvents } from "../typeGuards-Cj5Rgvlg.mjs";
|
|
5
|
+
import { t as HookSystem } from "../HookSystem-BNYKnrXF.mjs";
|
|
6
|
+
import { t as ResourceRegistry } from "../ResourceRegistry-BPd6NQDm.mjs";
|
|
7
|
+
import { n as caching_default, t as cachingPlugin } from "../caching-CBpK_SCM.mjs";
|
|
8
|
+
import { n as errorHandlerPlugin, t as defaultIsDuplicateKeyError } from "../errorHandler-Bb49BvPD.mjs";
|
|
9
|
+
import { n as metrics_default, t as metricsPlugin } from "../metrics-DuhiSEZI.mjs";
|
|
10
|
+
import { t as replyHelpersPlugin } from "../replyHelpers-CXtJDAZ0.mjs";
|
|
11
|
+
import { n as sse_default, t as ssePlugin } from "../sse-yBCgOLGu.mjs";
|
|
12
|
+
import { n as versioning_default, t as versioningPlugin } from "../versioning-C2U_bLY0.mjs";
|
|
13
13
|
import { randomUUID } from "node:crypto";
|
|
14
14
|
import fp from "fastify-plugin";
|
|
15
15
|
//#region src/core/arcCorePlugin.ts
|
|
@@ -393,15 +393,13 @@ var health_default = fp(healthPlugin, {
|
|
|
393
393
|
const requestIdPlugin = async (fastify, opts = {}) => {
|
|
394
394
|
const { header = "x-request-id", generator = randomUUID, setResponseHeader = true } = opts;
|
|
395
395
|
if (!fastify.hasRequestDecorator("requestId")) fastify.decorateRequest("requestId", "");
|
|
396
|
-
fastify.addHook("onRequest", async (request) => {
|
|
396
|
+
fastify.addHook("onRequest", async (request, reply) => {
|
|
397
397
|
const incomingId = request.headers[header];
|
|
398
398
|
const sanitized = typeof incomingId === "string" ? incomingId.trim() : "";
|
|
399
399
|
const requestId = sanitized.length > 0 && sanitized.length <= 128 && /^[\w.:-]+$/.test(sanitized) ? sanitized : generator();
|
|
400
400
|
request.id = requestId;
|
|
401
401
|
request.requestId = requestId;
|
|
402
|
-
|
|
403
|
-
if (setResponseHeader) fastify.addHook("onSend", async (request, reply) => {
|
|
404
|
-
reply.header(header, request.requestId);
|
|
402
|
+
if (setResponseHeader) reply.header(header, requestId);
|
|
405
403
|
});
|
|
406
404
|
fastify.log?.debug?.("Request ID plugin registered");
|
|
407
405
|
};
|
|
@@ -410,4 +408,4 @@ var requestId_default = fp(requestIdPlugin, {
|
|
|
410
408
|
fastify: "5.x"
|
|
411
409
|
});
|
|
412
410
|
//#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 };
|
|
411
|
+
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-
|
|
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
|
/**
|
|
@@ -145,7 +145,7 @@ const responseCachePluginImpl = async (fastify, opts = {}) => {
|
|
|
145
145
|
request.__arcCacheTTL = 0;
|
|
146
146
|
reply.code(entry.statusCode).send(entry.body);
|
|
147
147
|
};
|
|
148
|
-
fastify.addHook("
|
|
148
|
+
fastify.addHook("preSerialization", async (request, reply, payload) => {
|
|
149
149
|
const ttl = request.__arcCacheTTL;
|
|
150
150
|
if (!ttl || ttl <= 0) return payload;
|
|
151
151
|
if (request.method !== "GET" && request.method !== "HEAD") return payload;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as traced, i as isTracingAvailable, n as _default, r as createSpan, t as TracingOptions } from "../tracing-
|
|
1
|
+
import { a as traced, i as isTracingAvailable, n as _default, r as createSpan, t as TracingOptions } from "../tracing-65B51Dw3.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.
|
|
47
|
+
const resolvedVersion = serviceVersion ?? "2.10.3";
|
|
48
48
|
const exporter = new OTLPTraceExporter({ url: exporterUrl });
|
|
49
49
|
const provider = new NodeTracerProvider({ resource: { attributes: {
|
|
50
50
|
"service.name": serviceName,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { r as RequestScope } from "../types-BD85MlEK.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-
|
|
2
|
+
import { c as PermissionCheck } from "../fields-Lo1VUDpt.mjs";
|
|
3
|
+
import { ot as PresetResult } from "../index-Cl0uoKd5.mjs";
|
|
4
|
+
import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-CVk_SEn2.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
|
-
/**
|
|
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-
|
|
1
|
+
import { t as filesUploadPreset } from "../filesUpload-t21LS-py.mjs";
|
|
2
2
|
export { filesUploadPreset };
|
package/dist/presets/index.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { St as IRequestContext, dn as AnyRecord, lt as ResourceConfig, ot as PresetResult, u as PaginationResult, xt as IControllerResponse } from "../index-Cl0uoKd5.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 };
|
package/dist/presets/index.mjs
CHANGED
|
@@ -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-
|
|
3
|
-
import { t as filesUploadPreset } from "../filesUpload-
|
|
4
|
-
|
|
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-fLJVXdVn.mjs";
|
|
3
|
+
import { t as filesUploadPreset } from "../filesUpload-t21LS-py.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 "../constants-
|
|
1
|
+
import "../constants-BhY1OHoH.mjs";
|
|
2
2
|
import { _ as isElevated, c as getRequestScope, f as getTeamId, h as hasOrgAccess, l as getScopeContext, o as getOrgId } from "../types-AOD8fxIw.mjs";
|
|
3
3
|
//#region src/presets/multiTenant.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,178 @@
|
|
|
1
|
+
import { c as PermissionCheck } from "../fields-Lo1VUDpt.mjs";
|
|
2
|
+
import { _t as ControllerHandler, mt as RouteMcpConfig, ot as PresetResult, pt as RouteDefinition } from "../index-Cl0uoKd5.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/presets/search.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Search Preset — backend-agnostic search / vector / embed routes
|
|
7
|
+
*
|
|
8
|
+
* Arc doesn't ship a search engine. It ships the **routes** that front one.
|
|
9
|
+
* The preset mounts up to three standard routes on a resource:
|
|
10
|
+
*
|
|
11
|
+
* POST /search → full-text / engine-backed search (ES, OpenSearch, Algolia, Typesense, …)
|
|
12
|
+
* POST /search-similar → vector / semantic similarity (Atlas, Pinecone, Qdrant, Milvus, …)
|
|
13
|
+
* POST /embed → text / media → vector embedding
|
|
14
|
+
*
|
|
15
|
+
* Each route is OFF by default. You opt in by providing a `handler` that calls
|
|
16
|
+
* whatever backend you use. The preset contributes:
|
|
17
|
+
* - Default path + method + permissions (customisable)
|
|
18
|
+
* - OpenAPI description + MCP tool naming
|
|
19
|
+
* - Arc envelope + pipeline (permissions, audit, hooks)
|
|
20
|
+
* - Sensible Fastify route schema defaults
|
|
21
|
+
*
|
|
22
|
+
* Paths are fully customisable — if your product wants `/abc/search` or a
|
|
23
|
+
* GET-based autocomplete, pass `path`/`method` overrides or use `routes` for
|
|
24
|
+
* fully bespoke endpoints.
|
|
25
|
+
*
|
|
26
|
+
* @example MongoKit wiring (elasticSearchPlugin + vectorPlugin)
|
|
27
|
+
* ```typescript
|
|
28
|
+
* import { Repository, methodRegistryPlugin, elasticSearchPlugin } from '@classytic/mongokit';
|
|
29
|
+
* import { vectorPlugin } from '@classytic/mongokit/ai';
|
|
30
|
+
* import { searchPreset } from '@classytic/arc/presets/search';
|
|
31
|
+
*
|
|
32
|
+
* const productRepo = new Repository(Product, [
|
|
33
|
+
* methodRegistryPlugin(),
|
|
34
|
+
* elasticSearchPlugin({ client: esClient, indexName: 'products' }),
|
|
35
|
+
* vectorPlugin({ fields: [{ path: 'embedding', dimensions: 1536 }], embedFn }),
|
|
36
|
+
* ]);
|
|
37
|
+
*
|
|
38
|
+
* defineResource({
|
|
39
|
+
* name: 'product',
|
|
40
|
+
* adapter: createMongooseAdapter({ model: Product, repository: productRepo }),
|
|
41
|
+
* presets: [
|
|
42
|
+
* searchPreset({
|
|
43
|
+
* search: { handler: (req) => productRepo.search(req.body.query, req.body) },
|
|
44
|
+
* similar: { handler: (req) => productRepo.searchSimilar(req.body.query, req.body) },
|
|
45
|
+
* }),
|
|
46
|
+
* ],
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example Custom vector backend (Pinecone)
|
|
51
|
+
* ```typescript
|
|
52
|
+
* searchPreset({
|
|
53
|
+
* similar: {
|
|
54
|
+
* path: '/vector-search', // custom path
|
|
55
|
+
* handler: async (req) => {
|
|
56
|
+
* const hits = await pinecone.query({
|
|
57
|
+
* vector: req.body.vector,
|
|
58
|
+
* topK: req.body.topK ?? 10,
|
|
59
|
+
* });
|
|
60
|
+
* return hits.matches;
|
|
61
|
+
* },
|
|
62
|
+
* schema: { body: { type: 'object', properties: { vector: { type: 'array' }, topK: { type: 'integer' } } } },
|
|
63
|
+
* mcp: false, // no MCP tool for this one
|
|
64
|
+
* },
|
|
65
|
+
* // Extra app-specific route
|
|
66
|
+
* routes: [
|
|
67
|
+
* {
|
|
68
|
+
* method: 'GET',
|
|
69
|
+
* path: '/autocomplete',
|
|
70
|
+
* handler: async (req) => algolia.suggest(req.query.q as string),
|
|
71
|
+
* permissions: allowPublic(),
|
|
72
|
+
* },
|
|
73
|
+
* ],
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
/**
|
|
78
|
+
* Feature-detected search surface. Arc's `RepositoryLike` is the cross-kit
|
|
79
|
+
* minimum (repo-core's `MinimalRepo & Partial<StandardRepo>`) and does not
|
|
80
|
+
* declare search/vector/embed methods — those are kit-specific (mongokit's
|
|
81
|
+
* `elasticSearchPlugin` + `vectorPlugin`, pgkit's `pgvector` extension,
|
|
82
|
+
* sqlitekit FTS5, or a standalone Pinecone/Algolia adapter). We type the
|
|
83
|
+
* `repository` option locally so the preset can auto-wire handlers when a
|
|
84
|
+
* kit happens to ship these methods, without forcing every repo to declare
|
|
85
|
+
* them.
|
|
86
|
+
*/
|
|
87
|
+
interface SearchableRepository {
|
|
88
|
+
search?(query: unknown, options?: unknown): Promise<unknown>;
|
|
89
|
+
searchSimilar?(query: unknown, options?: unknown): Promise<unknown>;
|
|
90
|
+
embed?(input: unknown): Promise<number[]>;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Handler contract — receives arc's `IRequestContext` (same as any `actions` or
|
|
94
|
+
* non-raw route handler) and returns either the raw result (wrapped into
|
|
95
|
+
* `{ success: true, data }` by arc) or an explicit `IControllerResponse`.
|
|
96
|
+
*/
|
|
97
|
+
type SearchHandler = ControllerHandler;
|
|
98
|
+
interface SearchRouteConfig {
|
|
99
|
+
/**
|
|
100
|
+
* User-supplied handler. When omitted, the preset auto-synthesises a handler
|
|
101
|
+
* from `options.repository` (calling `repo.search` / `repo.searchSimilar` /
|
|
102
|
+
* `repo.embed` respectively). If `repository` is also absent — or the repo
|
|
103
|
+
* doesn't expose the matching method — the route is NOT mounted.
|
|
104
|
+
*/
|
|
105
|
+
handler?: SearchHandler;
|
|
106
|
+
/** HTTP path relative to the resource prefix. Defaults per-kind: `/search`, `/search-similar`, `/embed`. */
|
|
107
|
+
path?: string;
|
|
108
|
+
/** HTTP method. Default: `POST`. */
|
|
109
|
+
method?: "GET" | "POST";
|
|
110
|
+
/** Permission check. Defaults: search/similar fall back to `permissions.list ?? allowPublic()`; embed → `requireAuth()`. */
|
|
111
|
+
permissions?: PermissionCheck;
|
|
112
|
+
/** Fastify/AJV route schema (body/querystring/params/headers/response). */
|
|
113
|
+
schema?: RouteDefinition["schema"];
|
|
114
|
+
/**
|
|
115
|
+
* MCP tool generation.
|
|
116
|
+
* - omitted/true (default): auto-generate the tool from the route
|
|
117
|
+
* - false: skip MCP
|
|
118
|
+
* - object: explicit MCP config
|
|
119
|
+
*/
|
|
120
|
+
mcp?: boolean | RouteMcpConfig;
|
|
121
|
+
/** OpenAPI summary. Defaults per-kind. */
|
|
122
|
+
summary?: string;
|
|
123
|
+
/** OpenAPI description. Defaults per-kind. */
|
|
124
|
+
description?: string;
|
|
125
|
+
/** Operation name. Defaults per-kind (`search`, `searchSimilar`, `embed`). */
|
|
126
|
+
operation?: string;
|
|
127
|
+
/** OpenAPI tags. */
|
|
128
|
+
tags?: string[];
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Shorthand shape for `search` / `similar` / `embed` sections:
|
|
132
|
+
* - `undefined` → route not mounted
|
|
133
|
+
* - `true` → mount with defaults, auto-wire from `repository`
|
|
134
|
+
* - `SearchRouteConfig` → explicit config (and optional handler override)
|
|
135
|
+
*/
|
|
136
|
+
type SearchSection = true | SearchRouteConfig;
|
|
137
|
+
interface SearchPresetOptions {
|
|
138
|
+
/**
|
|
139
|
+
* Repository exposing `search`/`searchSimilar`/`embed`. When provided,
|
|
140
|
+
* any section without an explicit `handler` is auto-wired to the matching
|
|
141
|
+
* repo method. Mongokit's `elasticSearchPlugin` + `vectorPlugin` register
|
|
142
|
+
* exactly these methods — pass the repo once and the handlers are synthesised.
|
|
143
|
+
*
|
|
144
|
+
* Sections set to `true` REQUIRE `repository` (otherwise the route is
|
|
145
|
+
* skipped silently). Sections with an explicit `handler` ignore this field.
|
|
146
|
+
*/
|
|
147
|
+
repository?: SearchableRepository;
|
|
148
|
+
/** Full-text / engine-backed search route. Opt-in. */
|
|
149
|
+
search?: SearchSection;
|
|
150
|
+
/** Vector / semantic similarity route. Opt-in. */
|
|
151
|
+
similar?: SearchSection;
|
|
152
|
+
/** Embedding route (text/media → vector). Opt-in. */
|
|
153
|
+
embed?: SearchSection;
|
|
154
|
+
/**
|
|
155
|
+
* Fully custom routes — merged as-is into the resource's route table.
|
|
156
|
+
* Use this for endpoints that don't fit search/similar/embed naming,
|
|
157
|
+
* e.g. `/autocomplete`, `/reindex`, `/facets`, `/more-like-this`.
|
|
158
|
+
*
|
|
159
|
+
* You are responsible for permissions + schema on each entry.
|
|
160
|
+
*/
|
|
161
|
+
routes?: RouteDefinition[];
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Create a search preset bound to a resource.
|
|
165
|
+
*
|
|
166
|
+
* Mounts routes only for sections the caller opts into. A section's handler
|
|
167
|
+
* is either:
|
|
168
|
+
* 1. explicit `cfg.handler` — always wins,
|
|
169
|
+
* 2. `options.repository` auto-wire — if the repo exposes the matching
|
|
170
|
+
* method (`search` / `searchSimilar` / `embed`),
|
|
171
|
+
* 3. otherwise the route is silently skipped.
|
|
172
|
+
*
|
|
173
|
+
* The preset itself stays DB-agnostic: nothing is imported from mongokit —
|
|
174
|
+
* it only feature-detects the optional methods on whatever repo you pass.
|
|
175
|
+
*/
|
|
176
|
+
declare function searchPreset(options?: SearchPresetOptions): PresetResult;
|
|
177
|
+
//#endregion
|
|
178
|
+
export { SearchHandler, SearchPresetOptions, SearchRouteConfig, SearchSection, SearchableRepository, searchPreset };
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { C as requireAuth, y as allowPublic } from "../permissions-Dk6mshja.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 {
|
|
3
|
+
import { C as requireAuth, T as requireRoles, y as allowPublic } from "./permissions-Dk6mshja.mjs";
|
|
4
4
|
//#region src/presets/ownedByUser.ts
|
|
5
5
|
/**
|
|
6
6
|
* Create ownership check middleware.
|
|
@@ -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-
|
|
4
|
-
import { t as MemoryCacheStore } from "./memory-
|
|
3
|
+
import { t as hasEvents } from "./typeGuards-Cj5Rgvlg.mjs";
|
|
4
|
+
import { t as MemoryCacheStore } from "./memory-B5Amv9A1.mjs";
|
|
5
5
|
import fp from "fastify-plugin";
|
|
6
6
|
//#region src/cache/QueryCache.ts
|
|
7
7
|
var QueryCache = class {
|
|
@@ -33,17 +33,17 @@ var QueryCache = class {
|
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
async set(key, data, config) {
|
|
36
|
-
const
|
|
37
|
-
const
|
|
36
|
+
const staleTimeSec = config.staleTime ?? 0;
|
|
37
|
+
const totalTtlSec = staleTimeSec + (config.gcTime ?? 60);
|
|
38
38
|
const now = Date.now();
|
|
39
39
|
const envelope = {
|
|
40
40
|
data,
|
|
41
41
|
createdAt: now,
|
|
42
|
-
staleAfter: now +
|
|
43
|
-
expiresAt: now +
|
|
42
|
+
staleAfter: now + staleTimeSec * 1e3,
|
|
43
|
+
expiresAt: now + totalTtlSec * 1e3,
|
|
44
44
|
tags: config.tags ?? []
|
|
45
45
|
};
|
|
46
|
-
await this.store.set(key, envelope,
|
|
46
|
+
await this.store.set(key, envelope, totalTtlSec);
|
|
47
47
|
}
|
|
48
48
|
async invalidate(key) {
|
|
49
49
|
await this.store.delete(key);
|
|
@@ -56,7 +56,7 @@ var QueryCache = class {
|
|
|
56
56
|
async bumpResourceVersion(resource) {
|
|
57
57
|
const key = versionKey(resource);
|
|
58
58
|
const newVersion = Date.now();
|
|
59
|
-
await this.store.set(key, newVersion,
|
|
59
|
+
await this.store.set(key, newVersion, 1440 * 60);
|
|
60
60
|
}
|
|
61
61
|
/** Get current version for a tag */
|
|
62
62
|
async getTagVersion(tag) {
|
|
@@ -66,7 +66,7 @@ var QueryCache = class {
|
|
|
66
66
|
async bumpTagVersion(tag) {
|
|
67
67
|
const key = tagVersionKey(tag);
|
|
68
68
|
const newVersion = Date.now();
|
|
69
|
-
await this.store.set(key, newVersion,
|
|
69
|
+
await this.store.set(key, newVersion, 1440 * 60);
|
|
70
70
|
}
|
|
71
71
|
};
|
|
72
72
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as
|
|
1
|
+
import { i as EventLogger, n as DomainEvent, o as EventTransport, r as EventHandler } from "./EventTransport-CUw5NNWe.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/events/transports/redis-stream.d.ts
|
|
4
4
|
interface RedisStreamLike {
|