@classytic/arc 2.30.0 → 2.32.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/LICENSE +1 -1
- package/README.md +7 -0
- package/TRADEMARK.md +22 -0
- package/dist/{BaseController-B5DwufbB.mjs → BaseController-Dk34dxhI.mjs} +21 -19
- package/dist/{EventTransport-QmY7A258.d.mts → EventTransport-2uVV34WU.d.mts} +1 -0
- package/dist/{EventTransport-C6YA8xY9.mjs → EventTransport-BV10D0oG.mjs} +1 -0
- package/dist/{HookSystem-WkIougo6.mjs → HookSystem-vimw5D7Z.mjs} +2 -1
- package/dist/{QueryCache-DOMT_iq7.d.mts → QueryCache-DFA-QrU9.d.mts} +2 -1
- package/dist/{ResourceRegistry-y9Hnypus.mjs → ResourceRegistry-BVr7PgA0.mjs} +18 -15
- package/dist/{actionPermissions-CAphcmUG.mjs → actionPermissions-Dti7ebyv.mjs} +1 -0
- package/dist/audit/index.d.mts +3 -2
- package/dist/audit/index.mjs +2 -1
- package/dist/auth/audit.d.mts +1 -0
- package/dist/auth/audit.mjs +1 -0
- package/dist/auth/index.d.mts +5 -4
- package/dist/auth/index.mjs +11 -9
- package/dist/auth/redis-session.d.mts +2 -1
- package/dist/auth/redis-session.mjs +1 -0
- package/dist/{applyPermissionResult-Cf6zUCvb.mjs → authorizationDecision-__T3EJDA.mjs} +19 -10
- package/dist/{buildHandler-BYS3Vkfz.mjs → buildHandler-Dn7rzUJo.mjs} +6 -4
- package/dist/cache/index.d.mts +4 -3
- package/dist/cache/index.mjs +4 -3
- package/dist/{caching-_NJeDd1_.mjs → caching-DFJqHyFs.mjs} +2 -1
- package/dist/cleanup/index.d.mts +39 -16
- package/dist/cleanup/index.mjs +50 -38
- package/dist/cli/commands/describe.d.mts +2 -1
- package/dist/cli/commands/describe.mjs +4 -5
- package/dist/cli/commands/docs.d.mts +1 -0
- package/dist/cli/commands/docs.mjs +3 -2
- package/dist/cli/commands/doctor.d.mts +1 -0
- package/dist/cli/commands/doctor.mjs +1 -0
- package/dist/cli/commands/generate.d.mts +2 -1
- package/dist/cli/commands/generate.mjs +2 -1
- package/dist/cli/commands/init.d.mts +2 -1
- package/dist/cli/commands/init.mjs +2 -1
- package/dist/cli/commands/introspect.d.mts +1 -0
- package/dist/cli/commands/introspect.mjs +2 -1
- package/dist/cli/index.d.mts +3 -2
- package/dist/cli/index.mjs +3 -2
- package/dist/{constants-DNre0wRg.mjs → constants-J99LGTJI.mjs} +1 -0
- package/dist/context/index.d.mts +1 -0
- package/dist/context/index.mjs +3 -2
- package/dist/core/index.d.mts +3 -2
- package/dist/core/index.mjs +7 -6
- package/dist/{core-poalJLvp.mjs → core-BwwmNSp7.mjs} +3 -2
- package/dist/{createActionRouter-BxuywVRB.mjs → createActionRouter-DkJZWo0m.mjs} +14 -10
- package/dist/{createAggregationRouter-BiY-lGdY.mjs → createAggregationRouter-B1exOVD8.mjs} +10 -7
- package/dist/{createApp-CXrKFciH.mjs → createApp-Bv0m-Q6_.mjs} +625 -229
- package/dist/{defineAggregation-ufWjUwml.mjs → defineAggregation-gX4No1gt.mjs} +1 -0
- package/dist/{defineResource-CxWqDCAy.mjs → defineResource-XFPPUu2c.mjs} +84 -50
- package/dist/discovery/index.d.mts +1 -0
- package/dist/discovery/index.mjs +1 -0
- package/dist/docs/index.d.mts +3 -2
- package/dist/docs/index.mjs +3 -2
- package/dist/{elevation-C9s5hFP_.d.mts → elevation-BXCfVcNG.d.mts} +1 -0
- package/dist/{elevation-CIz1GjGm.mjs → elevation-DNXXxgjl.mjs} +4 -3
- package/dist/encryption/index.d.mts +2 -1
- package/dist/encryption/index.mjs +5 -3
- package/dist/{errorHandler-Bq2OeEQL.mjs → errorHandler-B2AZUJUj.mjs} +3 -2
- package/dist/{errorHandler-C6yv4ZTW.d.mts → errorHandler-CpYUJmPA.d.mts} +1 -0
- package/dist/{errors-DHcHVAgk.d.mts → errors-BGdVwP25.d.mts} +1 -0
- package/dist/{errors-DkO8Nk6-.mjs → errors-Bh1KK5ps.mjs} +1 -0
- package/dist/{eventPlugin-D2NNR4py.mjs → eventPlugin-Dk_TyXeE.mjs} +8 -6
- package/dist/{eventPlugin-Bg3cP2_u.d.mts → eventPlugin-GF5nnBIq.d.mts} +2 -1
- package/dist/events/index.d.mts +112 -44
- package/dist/events/index.mjs +177 -141
- package/dist/events/transports/redis-stream-entry.d.mts +2 -1
- package/dist/events/transports/redis-stream-entry.mjs +14 -9
- package/dist/events/transports/redis.d.mts +2 -1
- package/dist/events/transports/redis.mjs +1 -0
- package/dist/{externalPaths-BE6wFpYv.d.mts → externalPaths-CmGOxOtD.d.mts} +1 -0
- package/dist/factory/index.d.mts +9 -5
- package/dist/factory/index.mjs +131 -7
- package/dist/fastify-augmentation-BppG5bMT.d.mts +179 -0
- package/dist/{fields-CQ_7KQWw.mjs → fields-DEi65pGj.mjs} +6 -10
- package/dist/{fields-D3lhgzhD.d.mts → fields-I_EeRWND.d.mts} +1 -0
- package/dist/{generate-D0wZupBg.mjs → generate-CRSG0jTv.mjs} +2 -1
- package/dist/{generate-BnsL9GBm.d.mts → generate-DCGuEbqI.d.mts} +1 -0
- package/dist/{headers-BvlQSDMB.mjs → headers-BXjQYbeC.mjs} +2 -1
- package/dist/{health-CB_m4S32.mjs → health-5XnTa2uo.mjs} +1 -0
- package/dist/hooks/index.d.mts +2 -1
- package/dist/hooks/index.mjs +2 -1
- package/dist/idempotency/index.d.mts +3 -2
- package/dist/idempotency/index.mjs +8 -5
- package/dist/idempotency/redis.d.mts +2 -1
- package/dist/idempotency/redis.mjs +1 -0
- package/dist/{index-CG4yqMDB.d.mts → index-C-481Zf2.d.mts} +74 -18
- package/dist/{index-Q5gzEIWY.d.mts → index-CpzxqePp.d.mts} +107 -32
- package/dist/{index-Cx7bro4R.d.mts → index-DXlHwvuE.d.mts} +5 -4
- package/dist/index-ZWhLTp_s.d.mts +290 -0
- package/dist/{index-Ch16aAah.d.mts → index-zq6VrjaB.d.mts} +122 -15
- package/dist/index.d.mts +9 -8
- package/dist/index.mjs +11 -10
- package/dist/{init-tlRSt667.mjs → init-BbfP8aky.mjs} +25 -27
- package/dist/{init-BPEu8cs-.d.mts → init-Cscs4lab.d.mts} +1 -0
- package/dist/integrations/event-gateway.d.mts +3 -2
- package/dist/integrations/event-gateway.mjs +2 -1
- package/dist/integrations/index.d.mts +4 -3
- package/dist/integrations/index.mjs +1 -0
- package/dist/integrations/jobs/index.d.mts +2 -1
- package/dist/integrations/jobs/index.mjs +109 -33
- package/dist/integrations/mcp/index.d.mts +6 -6
- package/dist/integrations/mcp/index.mjs +2 -1
- package/dist/integrations/mcp/testing.d.mts +3 -2
- package/dist/integrations/mcp/testing.mjs +2 -2
- package/dist/integrations/streamline.d.mts +1 -0
- package/dist/integrations/streamline.mjs +3 -2
- package/dist/integrations/webhooks.d.mts +1 -0
- package/dist/integrations/webhooks.mjs +1 -0
- package/dist/integrations/websocket-pushref-redis.d.mts +2 -1
- package/dist/integrations/websocket-pushref-redis.mjs +1 -0
- package/dist/integrations/websocket-redis.d.mts +2 -1
- package/dist/integrations/websocket-redis.mjs +1 -0
- package/dist/integrations/websocket.d.mts +3 -2
- package/dist/integrations/websocket.mjs +38 -34
- package/dist/{interface-BGZCzOGL.d.mts → interface-BOk3YnTz.d.mts} +1 -0
- package/dist/{interface-n5hpKg1d.mjs → interface-BP4IJCBO.mjs} +1 -0
- package/dist/{interface-Uk8ONJv7.d.mts → interface-DEWNOMza.d.mts} +1 -0
- package/dist/{jsonBody-BlzAoGCe.mjs → jsonBody-DDSR2HFl.mjs} +2 -1
- package/dist/{keys-Cd316u_y.mjs → keys-B-HBTGXl.mjs} +1 -0
- package/dist/{loadResources-DpU8pfjV.mjs → loadResources-DisEAmkm.mjs} +4 -2
- package/dist/{loadResourcesFromEntry-kvGT6EcO.mjs → loadResourcesFromEntry-D1MJp13f.mjs} +2 -1
- package/dist/logger/index.d.mts +1 -0
- package/dist/logger/index.mjs +1 -0
- package/dist/{mcpPlugin-nRzm5g2s.mjs → mcpPlugin-CpfVpKHE.mjs} +38 -38
- package/dist/{memory-CmnzXE5Z.mjs → memory-DsuWnj4T.mjs} +5 -4
- package/dist/{metrics-fdxI5mn_.mjs → metrics-DdQL8syd.mjs} +2 -1
- package/dist/middleware/index.d.mts +2 -1
- package/dist/middleware/index.mjs +3 -2
- package/dist/migrations/index.d.mts +1 -0
- package/dist/migrations/index.mjs +3 -2
- package/dist/module-Br81am6m.mjs +78 -0
- package/dist/{multipartBody-D0eBvkeq.mjs → multipartBody-BnkBLN7v.mjs} +3 -2
- package/dist/{openapi-B8Vkbxbn.mjs → openapi-DIRzvxC0.mjs} +6 -5
- package/dist/outbox-admin/index.d.mts +85 -0
- package/dist/outbox-admin/index.mjs +115 -0
- package/dist/permissions/index.d.mts +5 -4
- package/dist/permissions/index.mjs +6 -5
- package/dist/{permissions-Bfu_8y1U.mjs → permissions-Dl_m0NCe.mjs} +308 -42
- package/dist/{pipe-BOLmGIxa.mjs → pipe-ELHCP3zj.mjs} +3 -4
- package/dist/pipeline/index.d.mts +2 -1
- package/dist/pipeline/index.mjs +2 -1
- package/dist/{pipeline-BJnpkY9i.mjs → pipeline-CPA-jx0M.mjs} +17 -14
- package/dist/plugins/index.d.mts +8 -7
- package/dist/plugins/index.mjs +16 -15
- package/dist/plugins/response-cache.d.mts +1 -0
- package/dist/plugins/response-cache.mjs +2 -1
- package/dist/plugins/tracing-entry.d.mts +2 -1
- package/dist/plugins/tracing-entry.mjs +2 -1
- package/dist/{pluralize-BhrgwZb9.mjs → pluralize-C2ZkKbsn.mjs} +1 -0
- package/dist/{preloadResources-DSY5HGpS.mjs → preloadResources-CDs87fTw.mjs} +1 -0
- package/dist/{preloadResources-DCfa2egz.d.mts → preloadResources-T1hmlTEZ.d.mts} +117 -12
- package/dist/presets/filesUpload.d.mts +6 -5
- package/dist/presets/filesUpload.mjs +10 -12
- package/dist/presets/index.d.mts +3 -2
- package/dist/presets/index.mjs +2 -1
- package/dist/presets/multiTenant.d.mts +2 -1
- package/dist/presets/multiTenant.mjs +3 -2
- package/dist/presets/search.d.mts +3 -2
- package/dist/presets/search.mjs +2 -1
- package/dist/{presets-CJOEXLuk.mjs → presets-Dntd_pUO.mjs} +6 -4
- package/dist/{projection-UBDgfMwu.mjs → projection-CjHhM5W1.mjs} +2 -1
- package/dist/{pushref-registry-BbcnpNTm.d.mts → pushref-registry-Dov9l4qE.d.mts} +1 -0
- package/dist/{queryCachePlugin-br4otiqF.d.mts → queryCachePlugin-BzqxconG.d.mts} +3 -2
- package/dist/{queryCachePlugin-DSGuSVLW.mjs → queryCachePlugin-Dhps-Ldt.mjs} +6 -5
- package/dist/{rateLimit-DrED-C4v.mjs → rateLimit-C7mmAGs3.mjs} +7 -3
- package/dist/{rateLimitKey-BoWRH3e7.mjs → rateLimitKey-CccEFBfk.mjs} +1 -0
- package/dist/{realtime-B9nmIY5V.mjs → realtime-DVvVZZFz.mjs} +20 -9
- package/dist/{redis-UDtLaNj6.d.mts → redis-CduhKsJi.d.mts} +2 -1
- package/dist/{redis-stream-uIaauNpZ.d.mts → redis-stream-qN6A-RFv.d.mts} +2 -1
- package/dist/{registerRoute-JkxIEBJq.mjs → registerRoute-B_QrjYZS.mjs} +10 -7
- package/dist/registry/index.d.mts +3 -2
- package/dist/registry/index.mjs +3 -2
- package/dist/{registry-BYXUUg21.mjs → registry-DqUmzA9W.mjs} +2 -1
- package/dist/{renewingLease-3cuQH7h8.mjs → renewingLease-BpP9wwj7.mjs} +1 -0
- package/dist/{replyHelpers-67tRawQZ.mjs → replyHelpers-DS-P0b32.mjs} +2 -1
- package/dist/{repositoryFilter-Dz8k3S4P.mjs → repositoryFilter-DotlxG3L.mjs} +1 -0
- package/dist/{requestContext-MrlJwECf.mjs → requestContext-B6vQF-sy.mjs} +1 -0
- package/dist/{rolldown-runtime-8H4AJuhK.mjs → rolldown-runtime-BhflRrBs.mjs} +1 -0
- package/dist/{schedules-CjOd2MG9.mjs → schedules-C2Q3uv2d.mjs} +3 -2
- package/dist/{schemaConverter-DJvodiHj.mjs → schemaConverter-Crjvczi_.mjs} +70 -17
- package/dist/{schemaIR-Ca7ySNPx.mjs → schemaIR-CnyKK_1j.mjs} +2 -1
- package/dist/schemas/index.d.mts +1 -0
- package/dist/schemas/index.mjs +1 -0
- package/dist/scim/index.d.mts +1 -0
- package/dist/scim/index.mjs +2 -1
- package/dist/scope/index.d.mts +3 -2
- package/dist/scope/index.mjs +5 -4
- package/dist/{scope-DfaPntpo.mjs → scope-afz_Ieek.mjs} +4 -3
- package/dist/{sessionManager-BHOM3N_0.d.mts → sessionManager-qimlKV0P.d.mts} +1 -0
- package/dist/{simpleEqualityMatcher-Cg05HPsn.mjs → simpleEqualityMatcher-C4KiMWUa.mjs} +1 -0
- package/dist/{sse-BQ1w0dfl.mjs → sse-B9P4Y-UI.mjs} +7 -5
- package/dist/{sseStream-BQ7Qaynp.mjs → sseStream-B3zb_d1h.mjs} +2 -1
- package/dist/{storage-DLUZ04kK.d.mts → storage-Cx9Sz3Ou.d.mts} +1 -0
- package/dist/{store-helpers-DY6xq4sM.mjs → store-helpers-DmEMHlPQ.mjs} +1 -0
- package/dist/{streaming-BQcW6_Kq.mjs → streaming-DPZdQmDz.mjs} +1 -0
- package/dist/{subscribe-helpers-DfzsivM6.mjs → subscribe-helpers-sp5xTDVA.mjs} +2 -1
- package/dist/sync/changelog.d.mts +1 -0
- package/dist/sync/changelog.mjs +1 -0
- package/dist/testing/cleanupStoreContract.d.mts +2 -1
- package/dist/testing/cleanupStoreContract.mjs +10 -5
- package/dist/testing/index.d.mts +166 -12
- package/dist/testing/index.mjs +315 -43
- package/dist/testing/outboxStoreContract.d.mts +12 -2
- package/dist/testing/outboxStoreContract.mjs +110 -20
- package/dist/testing/storageContract.d.mts +2 -1
- package/dist/testing/storageContract.mjs +11 -5
- package/dist/{tracing-CsGKQJGg.d.mts → tracing-Dro5eH6j.d.mts} +1 -0
- package/dist/{transactionContext-PNdoyLLm.mjs → transactionContext-BvLKvOIL.mjs} +1 -0
- package/dist/{typeGuards-C9KXUly6.mjs → typeGuards-B_5-hKjJ.mjs} +1 -0
- package/dist/types/index.d.mts +6 -5
- package/dist/types/index.mjs +1 -0
- package/dist/types/storage.d.mts +2 -1
- package/dist/types/storage.mjs +1 -0
- package/dist/{types-ChvvVNP8.d.mts → types-B7XeLEgK.d.mts} +34 -2
- package/dist/{types-Cc91nXuA.d.mts → types-ByHn9rEO.d.mts} +1 -0
- package/dist/{types-C_ZZRcD6.d.mts → types-C4QE8qnm.d.mts} +1 -0
- package/dist/{types-D_n8L6VY.d.mts → types-CT5vu6M0.d.mts} +132 -17
- package/dist/{types-DjC-KUCz.d.mts → types-ChuShpCP.d.mts} +1 -0
- package/dist/{types-Bmmn-fO0.d.mts → types-CwcUQ610.d.mts} +2 -6
- package/dist/{types-CSyCxl2V.mjs → types-DXYX7dIR.mjs} +4 -3
- package/dist/usage/index.d.mts +3 -2
- package/dist/usage/index.mjs +0 -0
- package/dist/{userHelpers-Cg_y3fBz.mjs → userHelpers-BNsOXzOd.mjs} +1 -0
- package/dist/utils/index.d.mts +16 -7
- package/dist/utils/index.mjs +10 -9
- package/dist/{utils-taUVD4p3.mjs → utils-BtOha_Sp.mjs} +3 -2
- package/dist/{validate-Bk44F2yT.mjs → validate-PMCPR9El.mjs} +2 -1
- package/dist/{versioning-gKWyryT3.mjs → versioning-CKv2jz_U.mjs} +4 -3
- package/dist/{versioning-DXgY5BUm.d.mts → versioning-D_rhHfZm.d.mts} +5 -2
- package/dist/{websocket-_Pd0CgR0.d.mts → websocket-BOXVggMf.d.mts} +2 -1
- package/package.json +557 -539
- package/skills/arc/SKILL.md +22 -8
- package/skills/arc/references/api-reference.md +4 -0
- package/skills/arc/references/auth.md +3 -0
- package/skills/arc/references/integrations.md +33 -0
- package/skills/arc/references/mcp.md +6 -7
- package/skills/arc/references/production.md +24 -25
- package/skills/arc-code-review/references/anti-patterns.md +3 -3
- package/dist/fastify-augmentation-0WhPnUH7.d.mts +0 -76
- package/dist/index-CCzVR-N3.d.mts +0 -107
- package/dist/module-_-M7C5ES.mjs +0 -29
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { n as evaluateAndApplyPermission } from "../../authorizationDecision-__T3EJDA.mjs";
|
|
1
3
|
import fp from "fastify-plugin";
|
|
2
4
|
//#region src/integrations/jobs/execution.ts
|
|
3
5
|
async function executeTimedHandler(options) {
|
|
@@ -149,6 +151,49 @@ const jobsPluginImpl = async (fastify, options) => {
|
|
|
149
151
|
const dlqQueues = /* @__PURE__ */ new Map();
|
|
150
152
|
const workers = /* @__PURE__ */ new Map();
|
|
151
153
|
const throttledJobs = /* @__PURE__ */ new Map();
|
|
154
|
+
const seenNames = /* @__PURE__ */ new Set();
|
|
155
|
+
for (const job of jobs) {
|
|
156
|
+
if (typeof job.name !== "string" || job.name.trim() === "") throw new Error("[arc/jobs] a job definition has an empty name — names are the queue key.");
|
|
157
|
+
if (seenNames.has(job.name)) throw new Error(`[arc/jobs] duplicate job name "${job.name}". A name is the queue key, so two definitions sharing one would leave an untracked worker consuming the same queue after shutdown. Rename one, or register it in a single definition.`);
|
|
158
|
+
seenNames.add(job.name);
|
|
159
|
+
const positiveInt = (v, field) => {
|
|
160
|
+
if (v === void 0) return;
|
|
161
|
+
if (typeof v !== "number" || !Number.isInteger(v) || v <= 0) throw new Error(`[arc/jobs] Job '${job.name}' has ${field}=${String(v)} — must be a positive integer.`);
|
|
162
|
+
};
|
|
163
|
+
const nonNegativeInt = (v, field) => {
|
|
164
|
+
if (v === void 0) return;
|
|
165
|
+
if (typeof v !== "number" || !Number.isInteger(v) || v < 0) throw new Error(`[arc/jobs] Job '${job.name}' has ${field}=${String(v)} — must be a non-negative integer.`);
|
|
166
|
+
};
|
|
167
|
+
positiveInt(job.maxConcurrent, "maxConcurrent");
|
|
168
|
+
positiveInt(job.concurrency, "concurrency");
|
|
169
|
+
positiveInt(job.timeout, "timeout");
|
|
170
|
+
nonNegativeInt(job.retries, "retries");
|
|
171
|
+
nonNegativeInt(job.cancelGraceMs, "cancelGraceMs");
|
|
172
|
+
if (job.rateLimit) {
|
|
173
|
+
positiveInt(job.rateLimit.max, "rateLimit.max");
|
|
174
|
+
positiveInt(job.rateLimit.duration, "rateLimit.duration");
|
|
175
|
+
}
|
|
176
|
+
if (job.backoff) nonNegativeInt(job.backoff.delay, "backoff.delay");
|
|
177
|
+
if (job.repeat) {
|
|
178
|
+
positiveInt(job.repeat.every, "repeat.every");
|
|
179
|
+
positiveInt(job.repeat.limit, "repeat.limit");
|
|
180
|
+
if (job.repeat.pattern !== void 0 && job.repeat.pattern.trim() === "") throw new Error(`[arc/jobs] Job '${job.name}' has an empty repeat.pattern.`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (defaults) {
|
|
184
|
+
const d = defaults;
|
|
185
|
+
const defaultPositiveInt = (v, field) => {
|
|
186
|
+
if (v === void 0) return;
|
|
187
|
+
if (typeof v !== "number" || !Number.isInteger(v) || v <= 0) throw new Error(`[arc/jobs] defaults.${field}=${String(v)} — must be a positive integer.`);
|
|
188
|
+
};
|
|
189
|
+
const defaultNonNegativeInt = (v, field) => {
|
|
190
|
+
if (v === void 0) return;
|
|
191
|
+
if (typeof v !== "number" || !Number.isInteger(v) || v < 0) throw new Error(`[arc/jobs] defaults.${field}=${String(v)} — must be a non-negative integer.`);
|
|
192
|
+
};
|
|
193
|
+
defaultNonNegativeInt(d.retries, "retries");
|
|
194
|
+
defaultPositiveInt(d.timeout, "timeout");
|
|
195
|
+
if (d.backoff) defaultNonNegativeInt(d.backoff.delay, "backoff.delay");
|
|
196
|
+
}
|
|
152
197
|
for (const job of jobs) {
|
|
153
198
|
if (!job.repeat) continue;
|
|
154
199
|
const { pattern, every, tz } = job.repeat;
|
|
@@ -280,7 +325,7 @@ const jobsPluginImpl = async (fastify, options) => {
|
|
|
280
325
|
});
|
|
281
326
|
workers.set(queueName, worker);
|
|
282
327
|
}
|
|
283
|
-
const JOB_PAYLOAD_WARN_BYTES =
|
|
328
|
+
const JOB_PAYLOAD_WARN_BYTES = 102400;
|
|
284
329
|
const jobDefsByName = /* @__PURE__ */ new Map();
|
|
285
330
|
for (const job of jobs) if (!jobDefsByName.has(job.name)) jobDefsByName.set(job.name, job);
|
|
286
331
|
const dispatcher = {
|
|
@@ -296,19 +341,22 @@ const jobsPluginImpl = async (fastify, options) => {
|
|
|
296
341
|
}, `[arc/jobs] Large job payload — prefer passing IDs and reloading in the handler`);
|
|
297
342
|
} catch {}
|
|
298
343
|
const jobDef = jobDefsByName.get(name);
|
|
299
|
-
return {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
344
|
+
return {
|
|
345
|
+
queue: name,
|
|
346
|
+
jobId: (await queue.add(name, data, {
|
|
347
|
+
delay: opts.delay,
|
|
348
|
+
priority: opts.priority,
|
|
349
|
+
jobId: opts.jobId,
|
|
350
|
+
removeOnComplete: opts.removeOnComplete ?? defaults.removeOnComplete ?? 100,
|
|
351
|
+
removeOnFail: opts.removeOnFail ?? defaults.removeOnFail ?? 500,
|
|
352
|
+
attempts: jobDef?.retries ?? defaults.retries ?? 3,
|
|
353
|
+
backoff: jobDef?.backoff ?? defaults.backoff ?? {
|
|
354
|
+
type: "exponential",
|
|
355
|
+
delay: 1e3
|
|
356
|
+
},
|
|
357
|
+
repeat: jobDef?.repeat ?? opts.repeat
|
|
358
|
+
})).id
|
|
359
|
+
};
|
|
312
360
|
},
|
|
313
361
|
getQueue(name) {
|
|
314
362
|
return queues.get(name) ?? null;
|
|
@@ -327,10 +375,12 @@ const jobsPluginImpl = async (fastify, options) => {
|
|
|
327
375
|
}
|
|
328
376
|
return stats;
|
|
329
377
|
},
|
|
330
|
-
async getStatus(jobId) {
|
|
331
|
-
|
|
378
|
+
async getStatus(queueName, jobId) {
|
|
379
|
+
const queue = queues.get(queueName);
|
|
380
|
+
if (queue) {
|
|
381
|
+
const name = queueName;
|
|
332
382
|
const job = await queue.getJob(jobId);
|
|
333
|
-
if (!job)
|
|
383
|
+
if (!job) return null;
|
|
334
384
|
const state = typeof job.getState === "function" ? await job.getState() : "unknown";
|
|
335
385
|
const throttled = throttledJobs.get(name)?.has(jobId) || void 0;
|
|
336
386
|
return {
|
|
@@ -358,24 +408,50 @@ const jobsPluginImpl = async (fastify, options) => {
|
|
|
358
408
|
}
|
|
359
409
|
};
|
|
360
410
|
if (!fastify.hasDecorator("jobs")) fastify.decorate("jobs", dispatcher);
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
411
|
+
const management = options.managementRoutes;
|
|
412
|
+
if (management) {
|
|
413
|
+
const gate = management.operatorPermission;
|
|
414
|
+
if (!gate._platformOnly && !management.allowUnverifiedOperatorPermission) throw new Error("[arc/jobs] managementRoutes.operatorPermission must be platform-only. These routes are global (jobs carry no tenant identity), so an org-role gate would let a member of one organization read another's jobs. Use requirePlatformRole('platform-ops') — or requireRoles([...], { includeOrgRoles: false }) with allowUnverifiedOperatorPermission: true if you have verified the check yourself.");
|
|
415
|
+
const guard = async (req, reply) => {
|
|
416
|
+
if (!await evaluateAndApplyPermission(gate, {
|
|
417
|
+
user: req.user ?? null,
|
|
418
|
+
request: req,
|
|
419
|
+
resource: "jobs",
|
|
420
|
+
action: "read"
|
|
421
|
+
}, req, reply)) return false;
|
|
422
|
+
const policy = req._policyFilters;
|
|
423
|
+
if (policy && Object.keys(policy).length > 0) {
|
|
424
|
+
fastify.log.error("[arc/jobs] managementRoutes.operatorPermission returned a row-level policy, which this surface cannot apply — jobs carry no tenant identity. Gate it on an operator role (e.g. requireRoles(['platform-ops'])) and serve tenant-facing job status from a resource that owns its own row policy.");
|
|
425
|
+
await reply.status(403).send({
|
|
426
|
+
code: "arc.jobs.policy_unsupported",
|
|
427
|
+
message: "Job management routes are an operator surface and cannot apply a row-level policy.",
|
|
428
|
+
status: 403
|
|
429
|
+
});
|
|
430
|
+
return false;
|
|
431
|
+
}
|
|
432
|
+
return true;
|
|
365
433
|
};
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const status = await dispatcher.getStatus(id);
|
|
370
|
-
if (!status) return reply.status(404).send({
|
|
371
|
-
success: false,
|
|
372
|
-
error: "Job not found"
|
|
434
|
+
fastify.get(`${prefix}/stats`, async (req, reply) => {
|
|
435
|
+
if (!await guard(req, reply)) return reply;
|
|
436
|
+
return { stats: await dispatcher.getStats() };
|
|
373
437
|
});
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
438
|
+
fastify.get(`${prefix}/:queue/:id/status`, async (req, reply) => {
|
|
439
|
+
if (!await guard(req, reply)) return reply;
|
|
440
|
+
const { queue, id } = req.params;
|
|
441
|
+
const status = await dispatcher.getStatus(queue, id);
|
|
442
|
+
if (!status) return reply.status(404).send({
|
|
443
|
+
code: "arc.not_found",
|
|
444
|
+
message: "Job not found",
|
|
445
|
+
status: 404
|
|
446
|
+
});
|
|
447
|
+
const { returnValue, failedReason, ...safe } = status;
|
|
448
|
+
return {
|
|
449
|
+
...safe,
|
|
450
|
+
...management.exposeResult ? { returnValue } : {},
|
|
451
|
+
...management.exposeFailureReason ? { failedReason } : {}
|
|
452
|
+
};
|
|
453
|
+
});
|
|
454
|
+
}
|
|
379
455
|
fastify.addHook("onClose", async () => {
|
|
380
456
|
await dispatcher.close();
|
|
381
457
|
});
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
|
|
2
|
+
import { Ht as ServerAccessor, Rt as IControllerResponse, V as ResourceDefinition, zt as IRequestContext } from "../../index-CpzxqePp.mjs";
|
|
3
|
+
import { i as RequestScope } from "../../types-ChuShpCP.mjs";
|
|
4
|
+
import { r as PermissionCheck } from "../../types-B7XeLEgK.mjs";
|
|
5
|
+
import { n as FieldPermissionMap } from "../../fields-I_EeRWND.mjs";
|
|
6
|
+
import { _ as ToolDefinition, a as CrudDescriptionOverride, c as McpAuthResult, d as McpResourceConfig, f as PromptDefinition, g as ToolContext, h as ToolAnnotations, i as CrudDescriptionMeta, l as McpExecutionWiring, m as SessionEntry, n as CallToolResult, o as CrudOperation, p as PromptResult, r as CreateMcpServerConfig, s as McpAuthResolver, t as BetterAuthHandler, u as McpPluginOptions } from "../../types-CwcUQ610.mjs";
|
|
6
7
|
import { ErrorContract } from "@classytic/repo-core/errors";
|
|
7
8
|
import { FastifyPluginAsync } from "fastify";
|
|
8
9
|
import { z } from "zod";
|
|
@@ -529,7 +530,6 @@ declare module "fastify" {
|
|
|
529
530
|
}
|
|
530
531
|
interface ResourceFilterInputs {
|
|
531
532
|
readonly expose?: readonly string[];
|
|
532
|
-
readonly include?: readonly string[];
|
|
533
533
|
readonly exclude?: readonly string[];
|
|
534
534
|
}
|
|
535
535
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { a as defaultCrudDescription, c as mcpHandlerAdapter, d as toCallToolResult, f as toCallToolSuccess, h as resolveToolCollisions, i as fieldRulesToZod, l as permissionDeniedResult, m as createMcpServer, n as mcpPlugin, o as resolveCrudDescription, p as buildRequestContext, r as resourceToTools, s as invokeController, t as filterResourcesForMcp, u as toCallToolError } from "../../mcpPlugin-CpfVpKHE.mjs";
|
|
2
3
|
//#region src/integrations/mcp/defineTool.ts
|
|
3
4
|
/**
|
|
4
5
|
* Define a type-safe MCP tool.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
import { c as McpAuthResult, u as McpPluginOptions } from "../../types-CwcUQ610.mjs";
|
|
2
3
|
//#region src/integrations/mcp/testing.d.ts
|
|
3
4
|
interface TestMcpClientOptions {
|
|
4
5
|
/** MCP plugin options (resources, overrides, etc.) — same as mcpPlugin config */
|
|
5
|
-
pluginOptions?: Pick<McpPluginOptions, "resources" | "overrides" | "expose" | "
|
|
6
|
+
pluginOptions?: Pick<McpPluginOptions, "resources" | "overrides" | "expose" | "exclude" | "toolNamePrefix" | "extraTools" | "extraPrompts" | "instructions">;
|
|
6
7
|
/** Auth identity for the test session */
|
|
7
8
|
auth?: McpAuthResult | null;
|
|
8
9
|
/** Server name (default: 'test-mcp') */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { m as createMcpServer, r as resourceToTools, t as filterResourcesForMcp } from "../../mcpPlugin-CpfVpKHE.mjs";
|
|
2
3
|
//#region src/integrations/mcp/testing.ts
|
|
3
4
|
/**
|
|
4
5
|
* @classytic/arc/mcp/testing — MCP Test Utilities
|
|
@@ -54,7 +55,6 @@ async function createTestMcpClient(options = {}) {
|
|
|
54
55
|
const overrides = pluginOpts.overrides ?? {};
|
|
55
56
|
const tools = filterResourcesForMcp(pluginOpts.resources ?? [], {
|
|
56
57
|
expose: pluginOpts.expose,
|
|
57
|
-
include: pluginOpts.include,
|
|
58
58
|
exclude: pluginOpts.exclude
|
|
59
59
|
}).flatMap((r) => {
|
|
60
60
|
const resOverrides = overrides[r.name] ?? {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { f as createError, i as NotFoundError, r as ForbiddenError } from "../errors-Bh1KK5ps.mjs";
|
|
3
|
+
import { a as promoteStreamTokenToHeader, n as forwardedStreamHeaders } from "../streaming-DPZdQmDz.mjs";
|
|
3
4
|
import fp from "fastify-plugin";
|
|
4
5
|
//#region src/integrations/streamline.ts
|
|
5
6
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
import { c as SerializedEntry, i as Principal, n as FencedWriteOutcome, s as PushRefStore, t as EnvelopeSnapshot } from "../pushref-registry-Dov9l4qE.mjs";
|
|
2
3
|
//#region src/integrations/websocket-pushref-redis.d.ts
|
|
3
4
|
/**
|
|
4
5
|
* Minimal `ioredis` shape — typed structurally so this file doesn't
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
import { f as WebSocketAdapter } from "../websocket-BOXVggMf.mjs";
|
|
2
3
|
//#region src/integrations/websocket-redis.d.ts
|
|
3
4
|
interface RedisLike {
|
|
4
5
|
publish(channel: string, message: string): Promise<number>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { a as
|
|
1
|
+
|
|
2
|
+
import { a as GeoRoomOptions, c as WebSocketClient, d as LocalWebSocketAdapter, f as WebSocketAdapter, i as GeoRoom, l as WebSocketMessage, n as GeoPoint, o as RoomManager, r as GeoPublishOpts, s as AuthResult, t as websocketPlugin, u as WebSocketPluginOptions } from "../websocket-BOXVggMf.mjs";
|
|
3
|
+
import { a as PushRefRegistry, c as SerializedEntry, i as Principal, o as PushRefRegistryOptions, r as MemoryPushRefStore, s as PushRefStore } from "../pushref-registry-Dov9l4qE.mjs";
|
|
3
4
|
export { type AuthResult, type GeoPoint, type GeoPublishOpts, GeoRoom, type GeoRoomOptions, LocalWebSocketAdapter, MemoryPushRefStore, type Principal, PushRefRegistry, type PushRefRegistryOptions, type PushRefStore, RoomManager, type SerializedEntry, type WebSocketAdapter, type WebSocketClient, type WebSocketMessage, type WebSocketPluginOptions, websocketPlugin };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
1
2
|
import { randomUUID } from "node:crypto";
|
|
2
3
|
import sjson from "secure-json-parse";
|
|
3
4
|
import fp from "fastify-plugin";
|
|
@@ -333,19 +334,21 @@ var MemoryPushRefStore = class {
|
|
|
333
334
|
}
|
|
334
335
|
async claim(args) {
|
|
335
336
|
const existing = this.entries.get(args.pushRef);
|
|
336
|
-
if (existing)
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
337
|
+
if (existing) {
|
|
338
|
+
if (!existing.active && existing.expiresAt <= args.now) this.entries.delete(args.pushRef);
|
|
339
|
+
else {
|
|
340
|
+
if (existing.principal !== args.principal) return { outcome: "rejected" };
|
|
341
|
+
const supersededActive = existing.active === true;
|
|
342
|
+
existing.active = true;
|
|
343
|
+
existing.expiresAt = args.now + args.ttlMs;
|
|
344
|
+
existing.generation = (existing.generation ?? 0) + 1;
|
|
345
|
+
this.entries.set(args.pushRef, existing);
|
|
346
|
+
return {
|
|
347
|
+
outcome: "resumed",
|
|
348
|
+
entry: existing,
|
|
349
|
+
supersededActive
|
|
350
|
+
};
|
|
351
|
+
}
|
|
349
352
|
}
|
|
350
353
|
if (this.entries.size >= args.maxEntries && !this.evictOldestInactive()) return { outcome: "rejected" };
|
|
351
354
|
const fresh = args.mintFresh();
|
|
@@ -1052,9 +1055,7 @@ async function handleConnection(ctx, socket, request) {
|
|
|
1052
1055
|
}));
|
|
1053
1056
|
break;
|
|
1054
1057
|
}
|
|
1055
|
-
default:
|
|
1056
|
-
await options.onMessage?.(client, msg);
|
|
1057
|
-
break;
|
|
1058
|
+
default: await options.onMessage?.(client, msg);
|
|
1058
1059
|
}
|
|
1059
1060
|
});
|
|
1060
1061
|
socket.on("close", async () => {
|
|
@@ -1136,10 +1137,12 @@ function registerStatsRoute(fastify, rooms, path, expose) {
|
|
|
1136
1137
|
fastify.get(`${path}/stats`, async () => rooms.getStats());
|
|
1137
1138
|
return;
|
|
1138
1139
|
}
|
|
1139
|
-
if (expose === "authenticated")
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1140
|
+
if (expose === "authenticated") {
|
|
1141
|
+
if (fastify.hasDecorator("authenticate")) {
|
|
1142
|
+
const authenticate = fastify.authenticate;
|
|
1143
|
+
fastify.get(`${path}/stats`, { preHandler: authenticate }, async () => rooms.getStats());
|
|
1144
|
+
} else fastify.log.warn("arc-websocket: exposeStats is \"authenticated\" but fastify.authenticate is not registered — stats endpoint skipped");
|
|
1145
|
+
}
|
|
1143
1146
|
}
|
|
1144
1147
|
//#endregion
|
|
1145
1148
|
//#region src/integrations/websocket/outbound-truncate.ts
|
|
@@ -1163,7 +1166,7 @@ function registerStatsRoute(fastify, rooms, path, expose) {
|
|
|
1163
1166
|
* instance, eliminating module state.
|
|
1164
1167
|
*/
|
|
1165
1168
|
/** 5 MiB default — same as n8n's `relayViaPubSub` ceiling. */
|
|
1166
|
-
const DEFAULT_MAX_OUTBOUND_BYTES =
|
|
1169
|
+
const DEFAULT_MAX_OUTBOUND_BYTES = 5242880;
|
|
1167
1170
|
/**
|
|
1168
1171
|
* Returns either the original payload (when within `max`) or a
|
|
1169
1172
|
* placeholder JSON string (when oversize). The placeholder carries the
|
|
@@ -1206,7 +1209,7 @@ function createTruncator(max = DEFAULT_MAX_OUTBOUND_BYTES) {
|
|
|
1206
1209
|
* other instances fan out to their local sockets.
|
|
1207
1210
|
*/
|
|
1208
1211
|
/** Drop fan-out to a client whose outbound buffer exceeds this threshold. */
|
|
1209
|
-
const WS_BACKPRESSURE_LIMIT =
|
|
1212
|
+
const WS_BACKPRESSURE_LIMIT = 262144;
|
|
1210
1213
|
var RoomManager = class {
|
|
1211
1214
|
rooms = /* @__PURE__ */ new Map();
|
|
1212
1215
|
clients = /* @__PURE__ */ new Map();
|
|
@@ -1425,18 +1428,19 @@ var RoomManager = class {
|
|
|
1425
1428
|
if (client.socket.readyState !== 1) return false;
|
|
1426
1429
|
const queue = client.queue;
|
|
1427
1430
|
if (queue) {
|
|
1428
|
-
if (cls === "critical")
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1431
|
+
if (cls === "critical") {
|
|
1432
|
+
if (client.envelope) try {
|
|
1433
|
+
const parsed = JSON.parse(message);
|
|
1434
|
+
queue.send(client.envelope.wrap(parsed));
|
|
1435
|
+
if (this.registry) safeAsync(this.registry.persist(client.pushRef, client.generation), this.logger, "registry.persist", {
|
|
1436
|
+
pushRef: client.pushRef,
|
|
1437
|
+
generation: client.generation
|
|
1438
|
+
});
|
|
1439
|
+
} catch {
|
|
1440
|
+
queue.send(message);
|
|
1441
|
+
}
|
|
1442
|
+
else queue.send(message);
|
|
1443
|
+
} else queue.sendRealtime(message, coalesceKey);
|
|
1440
1444
|
return true;
|
|
1441
1445
|
}
|
|
1442
1446
|
if ((client.socket.bufferedAmount ?? 0) > WS_BACKPRESSURE_LIMIT) return false;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-BhflRrBs.mjs";
|
|
2
3
|
import { arcLog } from "./logger/index.mjs";
|
|
3
4
|
import { readdir } from "node:fs/promises";
|
|
4
5
|
import { dirname, join, resolve } from "node:path";
|
|
@@ -60,7 +61,8 @@ var loadResources_exports = /* @__PURE__ */ __exportAll({ loadResources: () => l
|
|
|
60
61
|
*/
|
|
61
62
|
async function loadResources(dir, options = {}) {
|
|
62
63
|
const { suffix = ".resource", recursive = true, exclude, include, filter } = options;
|
|
63
|
-
const
|
|
64
|
+
const resolvedDir = dir.startsWith("file://") ? dirname(fileURLToPath(dir)) : dir;
|
|
65
|
+
const absDir = resolve(resolvedDir);
|
|
64
66
|
const discovered = await collectFiles(absDir, new RegExp(`${escapeRegex(suffix)}\\.(ts|js|mts|mjs)$`), recursive);
|
|
65
67
|
discovered.sort();
|
|
66
68
|
const files = filter ? discovered.filter((f) => filter(f)) : discovered;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as ResourceRegistry } from "./ResourceRegistry-BVr7PgA0.mjs";
|
|
2
3
|
import { resolve } from "node:path";
|
|
3
4
|
import { pathToFileURL } from "node:url";
|
|
4
5
|
//#region src/cli/utils/loadResourcesFromEntry.ts
|
package/dist/logger/index.d.mts
CHANGED
package/dist/logger/index.mjs
CHANGED