@classytic/arc 2.19.0 → 2.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/arc.js +37 -0
- package/dist/{BaseController-Dy6EQHjM.mjs → BaseController-BnLYgE9A.mjs} +4 -4
- package/dist/{EventTransport-IEn7Tn-Q.d.mts → EventTransport-QmY7A258.d.mts} +0 -1
- package/dist/{QueryCache-TRfXau3W.d.mts → QueryCache-Z1B38koh.d.mts} +0 -1
- package/dist/{ResourceRegistry-5fKZwhK_.mjs → ResourceRegistry-7RnrEWNP.mjs} +1 -1
- package/dist/{actionPermissions-D7NGwcAR.mjs → actionPermissions-ze70xXJi.mjs} +1 -1
- package/dist/audit/index.d.mts +9 -5
- package/dist/audit/index.mjs +1 -1
- package/dist/auth/audit.d.mts +7 -4
- package/dist/auth/audit.mjs +5 -0
- package/dist/auth/index.d.mts +7 -14
- package/dist/auth/index.mjs +7 -5
- package/dist/auth/redis-session.d.mts +1 -2
- package/dist/{buildHandler-B0qvAguf.mjs → buildHandler-D_2ULWxZ.mjs} +3 -3
- package/dist/cache/index.d.mts +2 -3
- package/dist/cache/index.mjs +2 -2
- package/dist/cli/commands/describe.d.mts +1 -2
- package/dist/cli/commands/describe.mjs +2 -2
- 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 +4 -13
- package/dist/cli/index.mjs +2 -2
- package/dist/{constants-gaEeMlz-.mjs → constants-DNre0wRg.mjs} +1 -1
- package/dist/context/index.d.mts +2 -2
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +5 -5
- package/dist/{core-Ba-6Sue6.mjs → core-DZ6Xe1jR.mjs} +182 -55
- package/dist/{createActionRouter-B_WzBFyf.mjs → createActionRouter-BWMDW-dL.mjs} +4 -4
- package/dist/{createAggregationRouter-B_G_nIjm.mjs → createAggregationRouter-l5mNdYrZ.mjs} +5 -4
- package/dist/{createApp--703hQE1.mjs → createApp-Bi61XxqU.mjs} +229 -24
- package/dist/discovery/index.d.mts +0 -1
- package/dist/docs/index.d.mts +1 -2
- package/dist/docs/index.mjs +1 -1
- package/dist/{elevation-xGUBq6p_.d.mts → elevation-C9s5hFP_.d.mts} +0 -1
- package/dist/encryption/index.d.mts +2 -144
- package/dist/{errorHandler-BtUUDPEa.d.mts → errorHandler-B0e-bq-O.d.mts} +0 -1
- package/dist/{errors-DOHkjQlD.d.mts → errors-DHcHVAgk.d.mts} +0 -1
- package/dist/{eventPlugin-DbBFd3x_.d.mts → eventPlugin-A6EbthXR.d.mts} +10 -6
- package/dist/events/index.d.mts +9 -6
- package/dist/events/index.mjs +9 -6
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis.d.mts +1 -2
- package/dist/factory/index.d.mts +5 -4
- package/dist/factory/index.mjs +3 -3
- package/dist/{fastify-augmentation-D-5_yQJi.d.mts → fastify-augmentation-DafigGQp.d.mts} +12 -2
- package/dist/{fields-C7ahdGYf.d.mts → fields-BGqrAa_u.d.mts} +1 -2
- package/dist/{generate-Brans3fW.mjs → generate-usRSdQmP.mjs} +4 -3
- package/dist/hooks/index.d.mts +1 -1
- package/dist/idempotency/index.d.mts +4 -3
- package/dist/idempotency/index.mjs +1 -1
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/{index-CP6A1Ffj.d.mts → index-B5N-NaHs.d.mts} +88 -7
- package/dist/{index-CRKiiP5o.d.mts → index-B5PoNbfu.d.mts} +41 -7
- package/dist/{index-CUTG2Cuo.d.mts → index-Dtrj6XZk.d.mts} +90 -29
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +7 -7
- package/dist/{init-Bqpt1Hxf.mjs → init-0YhHkXGk.mjs} +239 -140
- package/dist/integrations/event-gateway.d.mts +2 -3
- package/dist/integrations/index.d.mts +2 -2
- package/dist/integrations/jobs.d.mts +0 -1
- package/dist/integrations/mcp/index.d.mts +6 -7
- package/dist/integrations/mcp/index.mjs +1 -1
- package/dist/integrations/mcp/testing.d.mts +1 -2
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/integrations/streamline.d.mts +19 -7
- package/dist/integrations/streamline.mjs +9 -5
- package/dist/integrations/webhooks.d.mts +0 -1
- package/dist/integrations/websocket-pushref-redis.d.mts +1 -2
- package/dist/integrations/websocket-redis.d.mts +1 -2
- package/dist/integrations/websocket.d.mts +2 -2
- package/dist/{loadResources-B8UmpITt.mjs → loadResources-DpU8pfjV.mjs} +4 -3
- package/dist/{loadResourcesFromEntry-BTlFEx05.mjs → loadResourcesFromEntry-OMCvIEE7.mjs} +1 -1
- package/dist/{mcpPlugin-C088Nd-G.mjs → mcpPlugin-B9XjjNVG.mjs} +148 -49
- package/dist/middleware/index.d.mts +1 -2
- package/dist/middleware/index.mjs +1 -1
- package/dist/module-WeuU5jfd.d.mts +429 -0
- package/dist/{openapi-DZ-5a5Op.mjs → openapi-Kyod_di6.mjs} +3 -3
- package/dist/permissions/index.d.mts +3 -3
- package/dist/permissions/index.mjs +2 -2
- package/dist/{permissions-BPB1xqGf.mjs → permissions-BJMuKMl7.mjs} +43 -3
- package/dist/pipeline/index.d.mts +1 -2
- package/dist/plugins/index.d.mts +87 -10
- package/dist/plugins/index.mjs +91 -4
- package/dist/plugins/response-cache.d.mts +5 -3
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/{pluralize-DccFV9R7.mjs → pluralize-BhrgwZb9.mjs} +3 -3
- package/dist/presets/filesUpload.d.mts +4 -5
- package/dist/presets/filesUpload.mjs +1 -1
- package/dist/presets/index.d.mts +16 -3
- package/dist/presets/index.mjs +1 -1
- package/dist/presets/multiTenant.d.mts +1 -2
- package/dist/presets/multiTenant.mjs +1 -1
- package/dist/presets/search.d.mts +2 -3
- package/dist/presets/search.mjs +3 -2
- package/dist/{presets-BtyFwTO4.mjs → presets-gw0ciIUD.mjs} +1 -1
- package/dist/{pushref-registry-DnCqL3aa.d.mts → pushref-registry-BbcnpNTm.d.mts} +4 -2
- package/dist/{queryCachePlugin-xzFyKAjT.d.mts → queryCachePlugin-CfYWq-Ak.d.mts} +1 -2
- package/dist/{queryCachePlugin-emHb0CuX.mjs → queryCachePlugin-DzqLN904.mjs} +2 -2
- package/dist/{redis-C3W0qbz8.d.mts → redis-UDtLaNj6.d.mts} +0 -1
- package/dist/{redis-stream-DsP1vqZB.d.mts → redis-stream-iVR2l7aS.d.mts} +1 -2
- package/dist/{registerRoute-BdV8DDwU.mjs → registerRoute-oGAl0oA8.mjs} +1 -1
- package/dist/registry/index.d.mts +2 -2
- package/dist/registry/index.mjs +2 -2
- package/dist/{registry-Bm9LjWKs.mjs → registry-vcOCtPij.mjs} +1 -1
- package/dist/{schemaIR-D1MJwqmp.mjs → schemaIR-ajetw3Fv.mjs} +1 -42
- package/dist/schemas/index.d.mts +0 -1
- package/dist/scim/index.d.mts +0 -1
- package/dist/scim/index.mjs +2 -2
- package/dist/scope/index.d.mts +2 -3
- package/dist/{sessionManager-BXG-HGwG.d.mts → sessionManager-BHOM3N_0.d.mts} +10 -6
- package/dist/{storage-Co_PQpeQ.d.mts → storage-DLUZ04kK.d.mts} +8 -4
- package/dist/sync/changelog.d.mts +2 -0
- package/dist/sync/changelog.mjs +2 -0
- package/dist/testing/index.d.mts +2 -3
- package/dist/testing/index.mjs +6 -3
- package/dist/testing/storageContract.d.mts +1 -2
- package/dist/{tracing-D8jlGXP7.d.mts → tracing-CsGKQJGg.d.mts} +0 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/types/storage.d.mts +1 -1
- package/dist/types-Cc91nXuA.d.mts +132 -0
- package/dist/{types-LNebCoJx.d.mts → types-DH0GupI7.d.mts} +8 -4
- package/dist/{types-DpvSF5Hh.d.mts → types-DRj-Ut4n.d.mts} +1 -2
- package/dist/{types-9_wtNPsI.d.mts → types-DpxoNX5v.d.mts} +112 -214
- package/dist/utils/index.d.mts +182 -128
- package/dist/utils/index.mjs +2 -2
- package/dist/{utils-C6QQ9-hd.mjs → utils-CO8a3B_1.mjs} +1435 -1391
- package/dist/{validate-CRcaWzp2.mjs → validate-C2mGgSXg.mjs} +3 -3
- package/dist/{versioning-D_eBCfNr.d.mts → versioning-DQ4mCvg0.d.mts} +1 -2
- package/dist/{websocket-MlYlrYq0.d.mts → websocket-uuWqM6UY.d.mts} +5 -4
- package/package.json +18 -13
- package/skills/arc/SKILL.md +10 -0
- package/skills/arc/references/mcp.md +2 -0
- package/skills/arc-module-publishing/SKILL.md +242 -0
- package/skills/arc-module-publishing/references/authoring-modules.md +272 -0
- package/skills/arc-module-publishing/references/package-manifest.md +155 -0
- package/skills/arc-module-publishing/references/publishing-workflow.md +182 -0
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { Q as MiddlewareConfig, ft as RouteDefinition, ht as RouteSchemaOptions, nt as PresetHook, qt as AnyRecord } from "../index-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { i as
|
|
5
|
-
import { t as TracingOptions } from "../tracing-
|
|
1
|
+
import { Q as MiddlewareConfig, ft as RouteDefinition, ht as RouteSchemaOptions, nt as PresetHook, qt as AnyRecord } from "../index-Dtrj6XZk.mjs";
|
|
2
|
+
import { i as errorHandlerPlugin, n as ErrorMapper, r as defaultIsDuplicateKeyError, t as ErrorHandlerOptions } from "../errorHandler-B0e-bq-O.mjs";
|
|
3
|
+
import { a as arcCorePlugin, i as _default, n as ArcCorePluginOptions, r as PluginMeta, t as ArcCore } from "../fastify-augmentation-DafigGQp.mjs";
|
|
4
|
+
import { _ as HealthOptions, a as MetricsCollector, c as metricsPlugin, d as ssePlugin, f as CachingOptions, g as HealthCheck, h as cachingPlugin, i as MetricEntry, l as SSEOptions, m as _default$1, n as _default$8, o as MetricsOptions, p as CachingRule, r as versioningPlugin, s as _default$4, t as VersioningOptions, u as _default$7, v as _default$3, y as healthPlugin } from "../versioning-DQ4mCvg0.mjs";
|
|
5
|
+
import { t as TracingOptions } from "../tracing-CsGKQJGg.mjs";
|
|
6
6
|
import { PaginatedResult } from "@classytic/repo-core/pagination";
|
|
7
7
|
import { FastifyInstance, FastifyPluginAsync } from "fastify";
|
|
8
|
-
|
|
9
8
|
//#region src/plugins/createPlugin.d.ts
|
|
10
9
|
interface PluginResourceResult {
|
|
11
10
|
/** Additional routes to add to the resource (v2.8 `RouteDefinition` shape) */
|
|
@@ -24,10 +23,15 @@ interface CreatePluginDefinition<TRootOpts extends AnyRecord = AnyRecord, TResou
|
|
|
24
23
|
*/
|
|
25
24
|
forRoot?: (fastify: FastifyInstance, opts: TRootOpts) => void | Promise<void>;
|
|
26
25
|
/**
|
|
27
|
-
* Per-resource configuration function. Called
|
|
28
|
-
*
|
|
26
|
+
* Per-resource configuration function. Called (via `plugin.forResource(opts)`)
|
|
27
|
+
* to PRODUCE a partial resource config — hooks, routes, middlewares — that the
|
|
28
|
+
* host spreads into `defineResource(...)`. It receives only the plugin's own
|
|
29
|
+
* `opts`: the resource does not exist yet at this call site, so it cannot be
|
|
30
|
+
* inspected here (that was a false promise pre-2.20; the unused `resourceConfig`
|
|
31
|
+
* parameter is removed). For behavior that must vary by resource, key off the
|
|
32
|
+
* plugin's `opts` the host passes per resource.
|
|
29
33
|
*/
|
|
30
|
-
forResource?: (
|
|
34
|
+
forResource?: (opts: TResourceOpts) => PluginResourceResult;
|
|
31
35
|
}
|
|
32
36
|
interface ArcPlugin<TRootOpts extends AnyRecord = AnyRecord, TResourceOpts extends AnyRecord = AnyRecord> {
|
|
33
37
|
/** Plugin name */
|
|
@@ -144,4 +148,77 @@ declare module "fastify" {
|
|
|
144
148
|
declare const requestIdPlugin: FastifyPluginAsync<RequestIdOptions>;
|
|
145
149
|
declare const _default$5: FastifyPluginAsync<RequestIdOptions>;
|
|
146
150
|
//#endregion
|
|
147
|
-
|
|
151
|
+
//#region src/plugins/schedules.d.ts
|
|
152
|
+
/**
|
|
153
|
+
* Structural view of the ecosystem lock contract — matches
|
|
154
|
+
* `LockAdapter` from `@classytic/repo-core/lock` (and every kit
|
|
155
|
+
* implementation) WITHOUT importing the subpath, so arc's emitted
|
|
156
|
+
* declarations carry no repo-core@>=0.8 subpath reference and the
|
|
157
|
+
* peer floor stays honest. Any conforming adapter assigns.
|
|
158
|
+
*/
|
|
159
|
+
interface ScheduleLockLike {
|
|
160
|
+
tryAcquire(name: string, holderId: string, leaseMs: number): Promise<boolean> | boolean;
|
|
161
|
+
release(name: string, holderId: string): Promise<boolean> | boolean;
|
|
162
|
+
}
|
|
163
|
+
interface ScheduleDefinition {
|
|
164
|
+
/** Unique name — also the lock key (`arc:schedule:<name>`). */
|
|
165
|
+
name: string;
|
|
166
|
+
/** Interval in milliseconds between the END of one run and the next tick. */
|
|
167
|
+
every: number;
|
|
168
|
+
/** The work. Receives the Fastify instance; errors are logged, never fatal. */
|
|
169
|
+
handler: (fastify: FastifyInstance) => void | Promise<void>;
|
|
170
|
+
/** Fire once immediately when the app becomes ready (default: false). */
|
|
171
|
+
runOnStart?: boolean;
|
|
172
|
+
/**
|
|
173
|
+
* Random extra delay in `[0, jitterMs)` added to the FIRST tick only.
|
|
174
|
+
* Spreads boot-aligned jobs so multiple same-cadence schedules don't all
|
|
175
|
+
* fire at exactly `boot + every` after every restart (and, with a lock,
|
|
176
|
+
* de-synchronizes replicas competing for the same lease). Ignored when
|
|
177
|
+
* `runOnStart` is true.
|
|
178
|
+
*/
|
|
179
|
+
jitterMs?: number;
|
|
180
|
+
/**
|
|
181
|
+
* Lease duration when a `lock` is configured. Default: `every * 0.9`
|
|
182
|
+
* (capped at 5 minutes) — long enough that other replicas skip the same
|
|
183
|
+
* tick, short enough that a crashed leader fails over within one cycle.
|
|
184
|
+
*/
|
|
185
|
+
leaseMs?: number;
|
|
186
|
+
/** Per-schedule kill switch (default: true). */
|
|
187
|
+
enabled?: boolean;
|
|
188
|
+
}
|
|
189
|
+
interface SchedulesPluginOptions {
|
|
190
|
+
schedules: ScheduleDefinition[];
|
|
191
|
+
/**
|
|
192
|
+
* Ecosystem lock adapter for multi-replica deployments. Omit for
|
|
193
|
+
* single-instance apps — every tick runs locally.
|
|
194
|
+
*/
|
|
195
|
+
lock?: ScheduleLockLike;
|
|
196
|
+
/**
|
|
197
|
+
* Identity of this replica for lease ownership. Default: a random id per
|
|
198
|
+
* process (repo-core's `getInstanceId()` is a good explicit value).
|
|
199
|
+
*/
|
|
200
|
+
holderId?: string;
|
|
201
|
+
/**
|
|
202
|
+
* Master switch — `false` registers a typed no-op (config-gated
|
|
203
|
+
* environments), same pattern as `idempotencyPlugin`.
|
|
204
|
+
*/
|
|
205
|
+
enabled?: boolean;
|
|
206
|
+
}
|
|
207
|
+
/** Per-schedule runtime counters, readable via `fastify.getScheduleStats()`. */
|
|
208
|
+
interface ScheduleStats {
|
|
209
|
+
name: string;
|
|
210
|
+
runs: number;
|
|
211
|
+
failures: number;
|
|
212
|
+
skippedByLock: number;
|
|
213
|
+
lastRunAt: string | null;
|
|
214
|
+
lastError: string | null;
|
|
215
|
+
}
|
|
216
|
+
declare module "fastify" {
|
|
217
|
+
interface FastifyInstance {
|
|
218
|
+
getScheduleStats?: () => ScheduleStats[];
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
declare const schedulesPlugin: FastifyPluginAsync<SchedulesPluginOptions>;
|
|
222
|
+
declare const _default$6: FastifyPluginAsync<SchedulesPluginOptions>;
|
|
223
|
+
//#endregion
|
|
224
|
+
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 ScheduleDefinition, type ScheduleLockLike, type ScheduleStats, type SchedulesPluginOptions, 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 schedulesPlugin, schedulesPlugin as schedulesPluginFn, _default$7 as ssePlugin, ssePlugin as ssePluginFn, _default$8 as versioningPlugin, versioningPlugin as versioningPluginFn };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { p as MUTATION_OPERATIONS } from "../constants-
|
|
1
|
+
import { p as MUTATION_OPERATIONS } from "../constants-DNre0wRg.mjs";
|
|
2
2
|
import { c as getOrgId } from "../types-bHblZ9YN.mjs";
|
|
3
3
|
import { n as requestContext } from "../requestContext-BZKOr13H.mjs";
|
|
4
4
|
import { t as hasEvents } from "../typeGuards-C9KXUly6.mjs";
|
|
5
5
|
import { t as HookSystem } from "../HookSystem-C1vB_Gc9.mjs";
|
|
6
|
-
import { t as ResourceRegistry } from "../ResourceRegistry-
|
|
6
|
+
import { t as ResourceRegistry } from "../ResourceRegistry-7RnrEWNP.mjs";
|
|
7
7
|
import { n as caching_default, t as cachingPlugin } from "../caching-_NJeDd1_.mjs";
|
|
8
8
|
import { n as errorHandlerPlugin, t as defaultIsDuplicateKeyError } from "../errorHandler-Dxf6P_kV.mjs";
|
|
9
9
|
import { n as metrics_default, t as metricsPlugin } from "../metrics-fdxI5mn_.mjs";
|
|
@@ -131,7 +131,7 @@ function createPlugin(name, definition) {
|
|
|
131
131
|
},
|
|
132
132
|
forResource(opts) {
|
|
133
133
|
if (!definition.forResource) return {};
|
|
134
|
-
return definition.forResource(
|
|
134
|
+
return definition.forResource(opts ?? {});
|
|
135
135
|
}
|
|
136
136
|
};
|
|
137
137
|
}
|
|
@@ -469,4 +469,91 @@ var requestId_default = fp(requestIdPlugin, {
|
|
|
469
469
|
fastify: "5.x"
|
|
470
470
|
});
|
|
471
471
|
//#endregion
|
|
472
|
-
|
|
472
|
+
//#region src/plugins/schedules.ts
|
|
473
|
+
const MIN_SAFE_INTERVAL_MS = 1e3;
|
|
474
|
+
const MAX_DEFAULT_LEASE_MS = 3e5;
|
|
475
|
+
const schedulesPlugin = async (fastify, opts) => {
|
|
476
|
+
const { schedules, lock, enabled = true } = opts;
|
|
477
|
+
const holderId = opts.holderId ?? `arc-${process.pid}-${Math.random().toString(36).slice(2, 10)}`;
|
|
478
|
+
const stats = /* @__PURE__ */ new Map();
|
|
479
|
+
fastify.decorate("getScheduleStats", () => [...stats.values()].map((s) => ({ ...s })));
|
|
480
|
+
if (!enabled) {
|
|
481
|
+
fastify.log.debug("schedulesPlugin disabled — registered as no-op");
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
const seen = /* @__PURE__ */ new Set();
|
|
485
|
+
for (const s of schedules) {
|
|
486
|
+
if (!s.name) throw new TypeError("[arc-schedules] every schedule needs a name");
|
|
487
|
+
if (seen.has(s.name)) throw new TypeError(`[arc-schedules] duplicate schedule name "${s.name}"`);
|
|
488
|
+
seen.add(s.name);
|
|
489
|
+
if (!Number.isFinite(s.every) || s.every <= 0) throw new TypeError(`[arc-schedules] "${s.name}": \`every\` must be a positive number of ms`);
|
|
490
|
+
if (s.every < MIN_SAFE_INTERVAL_MS) fastify.log.warn(`[arc-schedules] "${s.name}" runs every ${s.every}ms — sub-second schedules are almost always a bug in production (DB pressure, lock churn). Intended for tests only.`);
|
|
491
|
+
}
|
|
492
|
+
const timers = /* @__PURE__ */ new Map();
|
|
493
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
494
|
+
let closing = false;
|
|
495
|
+
async function tick(s) {
|
|
496
|
+
const stat = stats.get(s.name);
|
|
497
|
+
if (!stat) return;
|
|
498
|
+
try {
|
|
499
|
+
if (lock) {
|
|
500
|
+
const leaseMs = s.leaseMs ?? Math.min(Math.floor(s.every * .9), MAX_DEFAULT_LEASE_MS);
|
|
501
|
+
if (!await lock.tryAcquire(`arc:schedule:${s.name}`, holderId, leaseMs)) {
|
|
502
|
+
stat.skippedByLock++;
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
stat.runs++;
|
|
507
|
+
stat.lastRunAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
508
|
+
await s.handler(fastify);
|
|
509
|
+
stat.lastError = null;
|
|
510
|
+
} catch (err) {
|
|
511
|
+
stat.failures++;
|
|
512
|
+
stat.lastError = err instanceof Error ? err.message : String(err);
|
|
513
|
+
fastify.log.error({
|
|
514
|
+
err,
|
|
515
|
+
schedule: s.name
|
|
516
|
+
}, "[arc-schedules] schedule run failed");
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
function scheduleNext(s, delay) {
|
|
520
|
+
if (closing) return;
|
|
521
|
+
const timer = setTimeout(() => {
|
|
522
|
+
const run = tick(s).finally(() => {
|
|
523
|
+
inFlight.delete(s.name);
|
|
524
|
+
scheduleNext(s, s.every);
|
|
525
|
+
});
|
|
526
|
+
inFlight.set(s.name, run);
|
|
527
|
+
}, delay);
|
|
528
|
+
timer.unref?.();
|
|
529
|
+
timers.set(s.name, timer);
|
|
530
|
+
}
|
|
531
|
+
fastify.addHook("onReady", async () => {
|
|
532
|
+
for (const s of schedules) {
|
|
533
|
+
if (s.enabled === false) continue;
|
|
534
|
+
stats.set(s.name, {
|
|
535
|
+
name: s.name,
|
|
536
|
+
runs: 0,
|
|
537
|
+
failures: 0,
|
|
538
|
+
skippedByLock: 0,
|
|
539
|
+
lastRunAt: null,
|
|
540
|
+
lastError: null
|
|
541
|
+
});
|
|
542
|
+
const jitter = !s.runOnStart && s.jitterMs ? Math.floor(Math.random() * s.jitterMs) : 0;
|
|
543
|
+
scheduleNext(s, s.runOnStart ? 0 : s.every + jitter);
|
|
544
|
+
}
|
|
545
|
+
if (stats.size > 0) fastify.log.debug(`[arc-schedules] ${stats.size} schedule(s) armed${lock ? ` (leader-safe, holder ${holderId})` : ""}`);
|
|
546
|
+
});
|
|
547
|
+
fastify.addHook("onClose", async () => {
|
|
548
|
+
closing = true;
|
|
549
|
+
for (const timer of timers.values()) clearTimeout(timer);
|
|
550
|
+
timers.clear();
|
|
551
|
+
await Promise.allSettled([...inFlight.values()]);
|
|
552
|
+
});
|
|
553
|
+
};
|
|
554
|
+
var schedules_default = fp(schedulesPlugin, {
|
|
555
|
+
name: "arc-schedules",
|
|
556
|
+
fastify: "5.x"
|
|
557
|
+
});
|
|
558
|
+
//#endregion
|
|
559
|
+
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, schedules_default as schedulesPlugin, schedulesPlugin as schedulesPluginFn, sse_default as ssePlugin, ssePlugin as ssePluginFn, versioning_default as versioningPlugin, versioningPlugin as versioningPluginFn };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { FastifyPluginAsync, FastifyRequest } from "fastify";
|
|
2
|
-
|
|
3
2
|
//#region src/plugins/response-cache.d.ts
|
|
4
3
|
interface ResponseCacheRule {
|
|
5
4
|
/** Path prefix to match (e.g., '/api/products') */
|
|
@@ -57,8 +56,11 @@ interface ResponseCacheStats {
|
|
|
57
56
|
declare module "fastify" {
|
|
58
57
|
interface FastifyInstance {
|
|
59
58
|
responseCache: {
|
|
60
|
-
/** Invalidate all cached responses matching a path prefix */
|
|
61
|
-
|
|
59
|
+
/** Invalidate all cached responses matching a path prefix */
|
|
60
|
+
invalidate: (pathPrefix: string) => number;
|
|
61
|
+
/** Clear the entire cache */
|
|
62
|
+
invalidateAll: () => void;
|
|
63
|
+
/** Get cache statistics */
|
|
62
64
|
stats: () => ResponseCacheStats;
|
|
63
65
|
/**
|
|
64
66
|
* Route-level preHandler for cache lookup.
|
|
@@ -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-CsGKQJGg.mjs";
|
|
2
2
|
export { type TracingOptions, createSpan, isTracingAvailable, traced, _default as tracingPlugin };
|
|
@@ -58,7 +58,7 @@ try {
|
|
|
58
58
|
function createTracerProvider(options) {
|
|
59
59
|
if (!isAvailable || !NodeTracerProvider || !BatchSpanProcessor || !OTLPTraceExporter) return null;
|
|
60
60
|
const { serviceName = "@classytic/arc", serviceVersion, exporterUrl = "http://localhost:4318/v1/traces" } = options;
|
|
61
|
-
const resolvedVersion = serviceVersion ?? "2.
|
|
61
|
+
const resolvedVersion = serviceVersion ?? "2.21.0";
|
|
62
62
|
const exporter = new OTLPTraceExporter({ url: exporterUrl });
|
|
63
63
|
const provider = new NodeTracerProvider({ resource: { attributes: {
|
|
64
64
|
"service.name": serviceName,
|
|
@@ -34,7 +34,7 @@ const IRREGULARS = {
|
|
|
34
34
|
vertex: "vertices",
|
|
35
35
|
criterion: "criteria"
|
|
36
36
|
};
|
|
37
|
-
const UNCOUNTABLES = new Set([
|
|
37
|
+
const UNCOUNTABLES = /* @__PURE__ */ new Set([
|
|
38
38
|
"sheep",
|
|
39
39
|
"fish",
|
|
40
40
|
"deer",
|
|
@@ -65,7 +65,7 @@ function pluralize(word) {
|
|
|
65
65
|
if (lower.endsWith("f") && !lower.endsWith("ff") && !lower.endsWith("roof") && !lower.endsWith("chief") && !lower.endsWith("belief")) return `${word.slice(0, -1)}ves`;
|
|
66
66
|
if (lower.endsWith("y") && !/[aeiou]y$/i.test(lower)) return `${word.slice(0, -1)}ies`;
|
|
67
67
|
if (lower.endsWith("is")) return `${word.slice(0, -2)}es`;
|
|
68
|
-
if (new Set([
|
|
68
|
+
if ((/* @__PURE__ */ new Set([
|
|
69
69
|
"cactus",
|
|
70
70
|
"stimulus",
|
|
71
71
|
"focus",
|
|
@@ -76,7 +76,7 @@ function pluralize(word) {
|
|
|
76
76
|
"alumnus",
|
|
77
77
|
"terminus",
|
|
78
78
|
"bacillus"
|
|
79
|
-
]).has(lower)) return `${word.slice(0, -2)}i`;
|
|
79
|
+
])).has(lower)) return `${word.slice(0, -2)}i`;
|
|
80
80
|
if (lower.endsWith("z") && !lower.endsWith("zz")) return `${word}zes`;
|
|
81
81
|
if (/(?:s|sh|ch|x|zz)$/i.test(lower)) return `${word}es`;
|
|
82
82
|
if (lower.endsWith("o") && !/[aeiou]o$/i.test(lower)) return `${word}es`;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { rt as PresetResult } from "../index-
|
|
2
|
-
import { i as RequestScope } from "../types-
|
|
3
|
-
import { c as PermissionCheck } from "../fields-
|
|
4
|
-
import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-
|
|
5
|
-
|
|
1
|
+
import { rt as PresetResult } from "../index-Dtrj6XZk.mjs";
|
|
2
|
+
import { i as RequestScope } from "../types-DH0GupI7.mjs";
|
|
3
|
+
import { c as PermissionCheck } from "../fields-BGqrAa_u.mjs";
|
|
4
|
+
import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-DLUZ04kK.mjs";
|
|
6
5
|
//#region src/presets/filesUpload.d.ts
|
|
7
6
|
interface FilesUploadPresetRoutes {
|
|
8
7
|
upload?: boolean;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as NotFoundError, u as ValidationError } from "../errors-DkO8Nk6-.mjs";
|
|
2
2
|
import { c as getOrgId, g as getUserId } from "../types-bHblZ9YN.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { b as allowPublic, w as requireAuth } from "../permissions-BJMuKMl7.mjs";
|
|
4
4
|
import { t as multipartBody } from "../multipartBody-CHEQSZ6G.mjs";
|
|
5
5
|
//#region src/presets/filesUpload.ts
|
|
6
6
|
const DEFAULT_FIELD_NAME = "file";
|
package/dist/presets/index.d.mts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { bt as IControllerResponse, d as PaginationResult, qt as AnyRecord, rt as PresetResult, st as ResourceConfig, xt as IRequestContext } from "../index-
|
|
1
|
+
import { bt as IControllerResponse, d as PaginationResult, qt as AnyRecord, rt as PresetResult, st as ResourceConfig, xt as IRequestContext } from "../index-Dtrj6XZk.mjs";
|
|
2
2
|
import { FilesUploadPresetOptions, FilesUploadPresetPermissions, FilesUploadPresetRoutes, filesUploadPreset } from "./filesUpload.mjs";
|
|
3
3
|
import { MultiTenantOptions, TenantFieldSpec, multiTenantPreset } from "./multiTenant.mjs";
|
|
4
4
|
import { SearchHandler, SearchPresetOptions, SearchRouteConfig, searchPreset } from "./search.mjs";
|
|
5
|
-
|
|
6
5
|
//#region src/presets/ownedByUser.d.ts
|
|
7
6
|
interface OwnedByUserOptions {
|
|
8
7
|
ownerField?: string;
|
|
@@ -237,7 +236,21 @@ type IAuditedPreset = never;
|
|
|
237
236
|
* }
|
|
238
237
|
* ```
|
|
239
238
|
*/
|
|
240
|
-
|
|
239
|
+
/** Preset name → controller contract. Lookup table for {@link IPresetController}. */
|
|
240
|
+
interface PresetControllerContracts<TDoc> {
|
|
241
|
+
softDelete: ISoftDeleteController<TDoc>;
|
|
242
|
+
slugLookup: ISlugLookupController<TDoc>;
|
|
243
|
+
tree: ITreeController<TDoc>;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Collapse a union into an intersection. The pre-2.20 implementation used a
|
|
247
|
+
* distributive conditional, so `IPresetController<T, 'softDelete' | 'tree'>`
|
|
248
|
+
* produced a UNION of contracts — which a class cannot `implements`; the
|
|
249
|
+
* documented multi-preset example didn't compile. An indexed lookup over the
|
|
250
|
+
* union followed by this fold yields the intersection the example promises.
|
|
251
|
+
*/
|
|
252
|
+
type UnionToIntersection<U> = (U extends unknown ? (x: U) => void : never) extends ((x: infer I) => void) ? I : never;
|
|
253
|
+
type IPresetController<TDoc = unknown, TPresets extends keyof PresetControllerContracts<TDoc> = never> = UnionToIntersection<PresetControllerContracts<TDoc>[TPresets]>;
|
|
241
254
|
//#endregion
|
|
242
255
|
//#region src/presets/index.d.ts
|
|
243
256
|
/**
|
package/dist/presets/index.mjs
CHANGED
|
@@ -1,5 +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-
|
|
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-gw0ciIUD.mjs";
|
|
3
3
|
import { filesUploadPreset } from "./filesUpload.mjs";
|
|
4
4
|
import { searchPreset } from "./search.mjs";
|
|
5
5
|
export { applyPresets, auditedPreset, bulkPreset, filesUploadPreset, flexibleMultiTenantPreset, getAvailablePresets, getPreset, multiTenantPreset, ownedByUserPreset, registerPreset, searchPreset, slugLookupPreset, softDeletePreset, treePreset };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { J as CrudRouteKey, rt as PresetResult } from "../index-
|
|
2
|
-
|
|
1
|
+
import { J as CrudRouteKey, rt as PresetResult } from "../index-Dtrj6XZk.mjs";
|
|
3
2
|
//#region src/presets/multiTenant.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* One tenant dimension for multi-field filtering. Discriminated by source:
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { ft as RouteDefinition, gt as ControllerHandler, pt as RouteMcpConfig, rt as PresetResult } from "../index-
|
|
2
|
-
import { c as PermissionCheck } from "../fields-
|
|
3
|
-
|
|
1
|
+
import { ft as RouteDefinition, gt as ControllerHandler, pt as RouteMcpConfig, rt as PresetResult } from "../index-Dtrj6XZk.mjs";
|
|
2
|
+
import { c as PermissionCheck } from "../fields-BGqrAa_u.mjs";
|
|
4
3
|
//#region src/presets/search.d.ts
|
|
5
4
|
/**
|
|
6
5
|
* Search Preset — backend-agnostic search / vector / embed routes
|
package/dist/presets/search.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b as allowPublic, w as requireAuth } from "../permissions-BJMuKMl7.mjs";
|
|
2
2
|
//#region src/presets/search.ts
|
|
3
3
|
const BUILTINS = [
|
|
4
4
|
{
|
|
@@ -84,7 +84,8 @@ function autoHandlerFor(repo, method) {
|
|
|
84
84
|
return fn(body.input ?? body);
|
|
85
85
|
};
|
|
86
86
|
if (method === "searchSimilar") return async (req) => {
|
|
87
|
-
|
|
87
|
+
const body = req.body ?? {};
|
|
88
|
+
return fn(body);
|
|
88
89
|
};
|
|
89
90
|
return async (req) => {
|
|
90
91
|
const body = req.body ?? {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { b as isElevated, n as PUBLIC_SCOPE } from "./types-bHblZ9YN.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { E as requireRoles, b as allowPublic, w as requireAuth } from "./permissions-BJMuKMl7.mjs";
|
|
3
3
|
import { multiTenantPreset } from "./presets/multiTenant.mjs";
|
|
4
4
|
//#region src/presets/ownedByUser.ts
|
|
5
5
|
/**
|
|
@@ -244,8 +244,10 @@ interface PushRefStore {
|
|
|
244
244
|
* pre-compute it without re-introducing the very race we're closing.
|
|
245
245
|
*/
|
|
246
246
|
stageIfInactive(args: {
|
|
247
|
-
pushRef: string;
|
|
248
|
-
|
|
247
|
+
pushRef: string;
|
|
248
|
+
/** Raw payload (NOT pre-wrapped). The store assigns seq + wraps atomically. */
|
|
249
|
+
payload: unknown;
|
|
250
|
+
/** Server timestamp (ms) — passed in so tests can pin the clock. */
|
|
249
251
|
timestamp: number;
|
|
250
252
|
expiresAt: number;
|
|
251
253
|
}): Promise<"ok" | "missing" | "active" | "raw">;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { r as CacheStore } from "./interface-C1_WLTMK.mjs";
|
|
2
|
-
import { i as QueryCache } from "./QueryCache-
|
|
2
|
+
import { i as QueryCache } from "./QueryCache-Z1B38koh.mjs";
|
|
3
3
|
import { FastifyPluginAsync } from "fastify";
|
|
4
|
-
|
|
5
4
|
//#region src/cache/queryCachePlugin.d.ts
|
|
6
5
|
interface QueryCachePluginOptions {
|
|
7
6
|
/** CacheStore instance. Default: MemoryCacheStore with default options. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
|
|
2
|
-
import { i as versionKey, r as tagVersionKey } from "./keys-Cd316u_y.mjs";
|
|
3
2
|
import { t as MemoryCacheStore } from "./memory-CLXA2VeJ.mjs";
|
|
4
3
|
import { t as hasEvents } from "./typeGuards-C9KXUly6.mjs";
|
|
4
|
+
import { i as versionKey, r as tagVersionKey } from "./keys-Cd316u_y.mjs";
|
|
5
5
|
import fp from "fastify-plugin";
|
|
6
6
|
//#region src/cache/QueryCache.ts
|
|
7
7
|
var QueryCache = class {
|
|
@@ -72,7 +72,7 @@ var QueryCache = class {
|
|
|
72
72
|
//#endregion
|
|
73
73
|
//#region src/cache/queryCachePlugin.ts
|
|
74
74
|
var queryCachePlugin_exports = /* @__PURE__ */ __exportAll({ queryCachePlugin: () => queryCachePlugin });
|
|
75
|
-
const CRUD_SUFFIXES = new Set([
|
|
75
|
+
const CRUD_SUFFIXES = /* @__PURE__ */ new Set([
|
|
76
76
|
"created",
|
|
77
77
|
"updated",
|
|
78
78
|
"deleted"
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "./EventTransport-
|
|
2
|
-
|
|
1
|
+
import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "./EventTransport-QmY7A258.mjs";
|
|
3
2
|
//#region src/events/transports/redis-stream.d.ts
|
|
4
3
|
interface RedisStreamLike {
|
|
5
4
|
xadd(key: string, id: string, ...fieldValues: string[]): Promise<string | null>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { f as createError } from "./errors-DkO8Nk6-.mjs";
|
|
2
|
-
import { M as evaluateAndApplyPermission } from "./permissions-BPB1xqGf.mjs";
|
|
3
2
|
import { n as requestContext } from "./requestContext-BZKOr13H.mjs";
|
|
3
|
+
import { N as evaluateAndApplyPermission } from "./permissions-BJMuKMl7.mjs";
|
|
4
4
|
//#region src/core/middlewares/arcDecorator.ts
|
|
5
5
|
/**
|
|
6
6
|
* Build the `arcDecorator` preHandler for a resource.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { J as CrudRouteKey, R as RegisterOptions, V as ResourceDefinition, at as ResolvedTenantPurge, k as IntrospectionPluginOptions, p as RegistryEntry, z as ResourceRegistry } from "../index-
|
|
1
|
+
import { J as CrudRouteKey, R as RegisterOptions, V as ResourceDefinition, at as ResolvedTenantPurge, k as IntrospectionPluginOptions, p as RegistryEntry, z as ResourceRegistry } from "../index-Dtrj6XZk.mjs";
|
|
2
|
+
import "../fastify-augmentation-DafigGQp.mjs";
|
|
2
3
|
import { FastifyPluginAsync } from "fastify";
|
|
3
4
|
import { TenantPurgeProgress, TenantPurgeStrategy } from "@classytic/repo-core/repository";
|
|
4
|
-
|
|
5
5
|
//#region src/registry/assertNoTenantData.d.ts
|
|
6
6
|
interface AssertNoTenantDataOptions {
|
|
7
7
|
readonly organizationId: string;
|
package/dist/registry/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as cascadeDeleteForOrganization, c as assertNoTenantData, i as introspectionPlugin_default, n as buildResourceManifestFromRegistry, o as getCascadingResources, r as introspectionPlugin, s as getCascadingResourcesWithMetadata, t as buildResourceManifest } from "../registry-
|
|
2
|
-
import { t as ResourceRegistry } from "../ResourceRegistry-
|
|
1
|
+
import { a as cascadeDeleteForOrganization, c as assertNoTenantData, i as introspectionPlugin_default, n as buildResourceManifestFromRegistry, o as getCascadingResources, r as introspectionPlugin, s as getCascadingResourcesWithMetadata, t as buildResourceManifest } from "../registry-vcOCtPij.mjs";
|
|
2
|
+
import { t as ResourceRegistry } from "../ResourceRegistry-7RnrEWNP.mjs";
|
|
3
3
|
export { ResourceRegistry, assertNoTenantData, buildResourceManifest, buildResourceManifestFromRegistry, cascadeDeleteForOrganization, getCascadingResources, getCascadingResourcesWithMetadata, introspectionPlugin_default as introspectionPlugin, introspectionPlugin as introspectionPluginFn };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { a as toJsonSchema } from "./schemaConverter-U0MnO9vd.mjs";
|
|
2
|
-
import { z } from "zod";
|
|
3
2
|
//#region src/core/schemaIR.ts
|
|
4
3
|
/**
|
|
5
4
|
* Schema IR — one canonical representation, two adapters.
|
|
@@ -98,27 +97,6 @@ function schemaIRToJsonSchemaBranch(ir, extras = {}) {
|
|
|
98
97
|
};
|
|
99
98
|
}
|
|
100
99
|
/**
|
|
101
|
-
* Emit a flat Zod shape from the IR. The MCP SDK wraps the returned record
|
|
102
|
-
* in `z.object()` internally, so we return the bare shape (same contract
|
|
103
|
-
* as `ToolDefinition.inputSchema`).
|
|
104
|
-
*
|
|
105
|
-
* `additionalProperties: false` is honored at the MCP handler layer rather
|
|
106
|
-
* than baked into the Zod shape — the SDK's input validation happens before
|
|
107
|
-
* the handler runs, and flat shapes can't express `.strict()` mode.
|
|
108
|
-
* `strictAdditionalProperties(ir)` returns the flag so callers can gate
|
|
109
|
-
* their handler on it.
|
|
110
|
-
*/
|
|
111
|
-
function schemaIRToZodShape(ir) {
|
|
112
|
-
const requiredSet = new Set(ir.required);
|
|
113
|
-
const result = {};
|
|
114
|
-
for (const [name, prop] of Object.entries(ir.properties)) {
|
|
115
|
-
const desc = typeof prop.description === "string" && prop.description.length > 0 ? prop.description : name;
|
|
116
|
-
const base = jsonSchemaPropToZod(prop);
|
|
117
|
-
result[name] = requiredSet.has(name) ? base.describe(desc) : base.optional().describe(desc);
|
|
118
|
-
}
|
|
119
|
-
return result;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
100
|
* Returns `true` when the IR declares `additionalProperties: false`. MCP
|
|
123
101
|
* tool handlers should reject inputs with unknown keys when this is true,
|
|
124
102
|
* matching HTTP's AJV-level strict enforcement.
|
|
@@ -126,24 +104,5 @@ function schemaIRToZodShape(ir) {
|
|
|
126
104
|
function shouldRejectAdditionalProperties(ir) {
|
|
127
105
|
return ir.additionalProperties === false;
|
|
128
106
|
}
|
|
129
|
-
/**
|
|
130
|
-
* Convert a single JSON Schema property to a Zod type. Understands enum,
|
|
131
|
-
* numeric/integer/boolean/array/object, and falls back to string for
|
|
132
|
-
* unrecognized types (matches MCP's "strings for opaque fields" convention).
|
|
133
|
-
*
|
|
134
|
-
* Internal — use `schemaIRToZodShape` which wires this up with required/optional
|
|
135
|
-
* + description handling.
|
|
136
|
-
*/
|
|
137
|
-
function jsonSchemaPropToZod(schema) {
|
|
138
|
-
if (Array.isArray(schema.enum) && schema.enum.length > 0) return z.enum(schema.enum);
|
|
139
|
-
switch (typeof schema.type === "string" ? schema.type : "string") {
|
|
140
|
-
case "number":
|
|
141
|
-
case "integer": return z.number();
|
|
142
|
-
case "boolean": return z.boolean();
|
|
143
|
-
case "array": return z.array(z.unknown());
|
|
144
|
-
case "object": return z.record(z.string(), z.unknown());
|
|
145
|
-
default: return z.string();
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
107
|
//#endregion
|
|
149
|
-
export {
|
|
108
|
+
export { schemaIRToJsonSchemaBranch as n, shouldRejectAdditionalProperties as r, normalizeSchemaIR as t };
|
package/dist/schemas/index.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ErrorContract, ErrorDetail } from "@classytic/repo-core/errors";
|
|
2
2
|
import { FastifyPluginAsyncTypebox, FastifyPluginCallbackTypebox, TypeBoxTypeProvider, TypeBoxValidatorCompiler } from "@fastify/type-provider-typebox";
|
|
3
3
|
import { Static, TObject, TSchema, TSchema as TSchema$1, Type } from "@sinclair/typebox";
|
|
4
|
-
|
|
5
4
|
//#region src/schemas/index.d.ts
|
|
6
5
|
/**
|
|
7
6
|
* Paginated list response — full union of every wire shape `toCanonicalList`
|
package/dist/scim/index.d.mts
CHANGED
package/dist/scim/index.mjs
CHANGED
|
@@ -381,7 +381,7 @@ function resourceToScim(resource, mapping, baseUrl) {
|
|
|
381
381
|
* parseScimFilter('active eq true and name.familyName sw "S"')
|
|
382
382
|
* → { $and: [{ active: true }, { 'name.familyName': { $regex: '^S' } }] }
|
|
383
383
|
*/
|
|
384
|
-
const COMPARISON_OPS = new Set([
|
|
384
|
+
const COMPARISON_OPS = /* @__PURE__ */ new Set([
|
|
385
385
|
"eq",
|
|
386
386
|
"ne",
|
|
387
387
|
"co",
|
|
@@ -393,7 +393,7 @@ const COMPARISON_OPS = new Set([
|
|
|
393
393
|
"le",
|
|
394
394
|
"pr"
|
|
395
395
|
]);
|
|
396
|
-
const LOGICAL_OPS = new Set([
|
|
396
|
+
const LOGICAL_OPS = /* @__PURE__ */ new Set([
|
|
397
397
|
"and",
|
|
398
398
|
"or",
|
|
399
399
|
"not"
|
package/dist/scope/index.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { C as isMember, D as requireOrgId, E as requireClientId, O as requireTeamId, S as isElevated, T as isService, _ as getTenantFromRequest, a as getAncestorOrgIds, b as hasOrgAccess, c as getMandate, d as getOrgRoles, f as getRequestScope, g as getTeamId, h as getServiceScopes, i as RequestScope, k as requireUserId, l as getOrgContext, m as getScopeContextMap, n as Mandate, o as getClientId, p as getScopeContext, r as PUBLIC_SCOPE, s as getDPoPJkt, t as AUTHENTICATED_SCOPE, u as getOrgId, v as getUserId, w as isOrgInScope, x as isAuthenticated, y as getUserRoles } from "../types-
|
|
2
|
-
import { i as elevationPlugin, n as ElevationOptions, r as _default, t as ElevationEvent } from "../elevation-
|
|
1
|
+
import { C as isMember, D as requireOrgId, E as requireClientId, O as requireTeamId, S as isElevated, T as isService, _ as getTenantFromRequest, a as getAncestorOrgIds, b as hasOrgAccess, c as getMandate, d as getOrgRoles, f as getRequestScope, g as getTeamId, h as getServiceScopes, i as RequestScope, k as requireUserId, l as getOrgContext, m as getScopeContextMap, n as Mandate, o as getClientId, p as getScopeContext, r as PUBLIC_SCOPE, s as getDPoPJkt, t as AUTHENTICATED_SCOPE, u as getOrgId, v as getUserId, w as isOrgInScope, x as isAuthenticated, y as getUserRoles } from "../types-DH0GupI7.mjs";
|
|
2
|
+
import { i as elevationPlugin, n as ElevationOptions, r as _default, t as ElevationEvent } from "../elevation-C9s5hFP_.mjs";
|
|
3
3
|
import { FastifyReply, FastifyRequest } from "fastify";
|
|
4
|
-
|
|
5
4
|
//#region src/scope/rateLimitKey.d.ts
|
|
6
5
|
interface RateLimitKeyContext {
|
|
7
6
|
ip: string;
|