@classytic/arc 2.28.0 → 2.31.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-B65zbz9m.mjs → BaseController-De7GqHck.mjs} +25 -24
- package/dist/{EventTransport-QmY7A258.d.mts → EventTransport-2uVV34WU.d.mts} +1 -0
- package/dist/EventTransport-9mlTgqzE.mjs +104 -0
- package/dist/{HookSystem-C1vB_Gc9.mjs → HookSystem-BcmPyq5I.mjs} +16 -35
- package/dist/{QueryCache-DOMT_iq7.d.mts → QueryCache-DFA-QrU9.d.mts} +2 -1
- package/dist/{ResourceRegistry-y9Hnypus.mjs → ResourceRegistry-qq0mn2s9.mjs} +3 -2
- package/dist/{actionPermissions-CAphcmUG.mjs → actionPermissions-BE5NwaQk.mjs} +1 -0
- package/dist/audit/index.d.mts +3 -2
- package/dist/audit/index.mjs +3 -2
- 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 +6 -5
- package/dist/auth/redis-session.d.mts +2 -1
- package/dist/auth/redis-session.mjs +1 -0
- package/dist/authorizationDecision-ChvUQGG1.mjs +266 -0
- package/dist/{buildHandler-Dtwd8fdz.mjs → buildHandler-CDrCJzmB.mjs} +34 -7
- package/dist/cache/index.d.mts +4 -3
- package/dist/cache/index.mjs +4 -3
- package/dist/{caching-_NJeDd1_.mjs → caching-BFHA6Scf.mjs} +2 -1
- package/dist/cleanup/index.d.mts +4 -3
- package/dist/cleanup/index.mjs +9 -13
- package/dist/cli/commands/describe.d.mts +2 -1
- package/dist/cli/commands/describe.mjs +3 -2
- 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-D3Dv4LAV.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 -5
- package/dist/{core-BGa8TXJR.mjs → core-BGpIxINN.mjs} +4 -49
- package/dist/{createActionRouter-C-N7z2EL.mjs → createActionRouter-CDXEdasl.mjs} +8 -7
- package/dist/{createAggregationRouter-wzwFa_dW.mjs → createAggregationRouter-KrQDzx-k.mjs} +10 -22
- package/dist/{createApp-Du5G54TM.mjs → createApp-Df89BEni.mjs} +505 -209
- package/dist/defineAggregation-DbPPS8RI.mjs +48 -0
- package/dist/{defineResource-2zvVVpxg.mjs → defineResource-Bv6EtN1x.mjs} +90 -72
- 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-D2l1mh4g.mjs} +4 -3
- package/dist/encryption/index.d.mts +2 -1
- package/dist/encryption/index.mjs +3 -2
- package/dist/{errorHandler-Bq2OeEQL.mjs → errorHandler-C5NeD6bT.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-Cj42AntO.mjs} +1 -0
- package/dist/{eventPlugin-DrQ_FesK.mjs → eventPlugin-CkffEihm.mjs} +6 -106
- package/dist/{eventPlugin-Bg3cP2_u.d.mts → eventPlugin-GF5nnBIq.d.mts} +2 -1
- package/dist/events/index.d.mts +4 -3
- package/dist/events/index.mjs +17 -340
- package/dist/events/transports/redis-stream-entry.d.mts +2 -1
- package/dist/events/transports/redis-stream-entry.mjs +1 -0
- 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 +7 -6
- package/dist/{fastify-augmentation-OzYGIiU1.d.mts → fastify-augmentation-zh0_AYHa.d.mts} +13 -4
- package/dist/{applyPermissionResult-BnyVE9eD.mjs → fields-CB5Cuzk9.mjs} +2 -107
- package/dist/{fields-D3lhgzhD.d.mts → fields-I_EeRWND.d.mts} +1 -0
- package/dist/{generate-BnsL9GBm.d.mts → generate-DCGuEbqI.d.mts} +1 -0
- package/dist/{generate-D0wZupBg.mjs → generate-EcA6ui4i.mjs} +2 -1
- package/dist/{headers-BvlQSDMB.mjs → headers-3zvE0rM3.mjs} +2 -1
- package/dist/{health-CB_m4S32.mjs → health-DjZYjM7H.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 +5 -4
- package/dist/idempotency/redis.d.mts +2 -1
- package/dist/idempotency/redis.mjs +1 -0
- package/dist/{index-CjVg-Epg.d.mts → index-Bc2ox8_U.d.mts} +6 -5
- package/dist/{index-CG4yqMDB.d.mts → index-C-481Zf2.d.mts} +74 -18
- package/dist/{index-BMnbzvtO.d.mts → index-CEJNZFtX.d.mts} +242 -24
- package/dist/index-CFThn1K9.d.mts +224 -0
- package/dist/{index-DPRH0Cme.d.mts → index-CpzxqePp.d.mts} +203 -97
- package/dist/index.d.mts +9 -8
- package/dist/index.mjs +11 -9
- package/dist/{init-tlRSt667.mjs → init-BEiNZBsJ.mjs} +19 -23
- 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 +108 -32
- package/dist/integrations/mcp/index.d.mts +9 -9
- 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 +1 -0
- package/dist/{interface-BGZCzOGL.d.mts → interface-BOk3YnTz.d.mts} +1 -0
- package/dist/{interface-Uk8ONJv7.d.mts → interface-DEWNOMza.d.mts} +1 -0
- package/dist/{interface-n5hpKg1d.mjs → interface-DYzM0q-u.mjs} +1 -0
- package/dist/{jsonBody-BlzAoGCe.mjs → jsonBody-BYbLDi5D.mjs} +2 -1
- package/dist/{keys-Cd316u_y.mjs → keys-C0_pa1tY.mjs} +1 -0
- package/dist/{loadResources-DpU8pfjV.mjs → loadResources-yawi9tAE.mjs} +2 -1
- package/dist/{loadResourcesFromEntry-kvGT6EcO.mjs → loadResourcesFromEntry-BAjYZonx.mjs} +2 -1
- package/dist/logger/index.d.mts +1 -0
- package/dist/logger/index.mjs +1 -0
- package/dist/{mcpPlugin-Cs6nRGCt.mjs → mcpPlugin-B_es0hiF.mjs} +52 -60
- package/dist/{memory-CmnzXE5Z.mjs → memory-DR6wpa9F.mjs} +2 -1
- package/dist/{metrics-fdxI5mn_.mjs → metrics-CUdw_wLB.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 -3
- package/dist/migrations/index.mjs +2 -4
- package/dist/module-0pFJA6YW.mjs +78 -0
- package/dist/{multipartBody-D0eBvkeq.mjs → multipartBody-wOgj_fnj.mjs} +1 -0
- package/dist/{openapi-BLV4OMXb.mjs → openapi-B2L4js1v.mjs} +6 -5
- package/dist/permissions/index.d.mts +5 -4
- package/dist/permissions/index.mjs +6 -4
- package/dist/{permissions-BrtiBKGs.mjs → permissions-L--QDAir.mjs} +518 -316
- package/dist/{pipe-BOLmGIxa.mjs → pipe-DRDNsI2T.mjs} +2 -1
- package/dist/pipeline/index.d.mts +2 -1
- package/dist/pipeline/index.mjs +2 -1
- package/dist/{pipeline-BGRnV-To.mjs → pipeline-UPQFatit.mjs} +7 -20
- 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-O0FZgESl.mjs} +1 -0
- package/dist/{preloadResources-CM4uUaFv.d.mts → preloadResources-CyoJMSiO.d.mts} +117 -12
- package/dist/{preloadResources-DSY5HGpS.mjs → preloadResources-Dz6BjzM6.mjs} +1 -0
- package/dist/presets/filesUpload.d.mts +6 -5
- package/dist/presets/filesUpload.mjs +9 -11
- package/dist/presets/index.d.mts +15 -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-DwFDVKP0.mjs → presets-C4-g4_4P.mjs} +27 -10
- package/dist/projection-BHw6xlOQ.mjs +18 -0
- package/dist/{pushref-registry-BbcnpNTm.d.mts → pushref-registry-Dov9l4qE.d.mts} +1 -0
- package/dist/{queryCachePlugin-DSGuSVLW.mjs → queryCachePlugin-BZr8v46E.mjs} +5 -4
- package/dist/{queryCachePlugin-br4otiqF.d.mts → queryCachePlugin-BzqxconG.d.mts} +3 -2
- package/dist/{rateLimit-DrED-C4v.mjs → rateLimit-CMPY5Qms.mjs} +7 -3
- package/dist/{rateLimitKey-BoWRH3e7.mjs → rateLimitKey-Dn5JNmkj.mjs} +1 -0
- package/dist/{realtime-DEuDu9io.mjs → realtime-C5NoxWFY.mjs} +20 -8
- 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-DTp18Ah_.mjs → registerRoute-CBN84fc7.mjs} +5 -2
- package/dist/registry/index.d.mts +3 -2
- package/dist/registry/index.mjs +3 -2
- package/dist/{registry-9km_w1aP.mjs → registry-4213U4zb.mjs} +3 -2
- package/dist/{renewingLease-3cuQH7h8.mjs → renewingLease-Dll8mGgc.mjs} +1 -0
- package/dist/{replyHelpers-67tRawQZ.mjs → replyHelpers-DIiZKGUt.mjs} +2 -1
- package/dist/repositoryFilter-f9eAfq_l.mjs +45 -0
- package/dist/{requestContext-MrlJwECf.mjs → requestContext-2TxXOJ7T.mjs} +1 -0
- package/dist/{rolldown-runtime-8H4AJuhK.mjs → rolldown-runtime-CUsjNX9R.mjs} +1 -0
- package/dist/{schedules-CjOd2MG9.mjs → schedules-DdtlICTf.mjs} +3 -2
- package/dist/{schemaConverter-DJvodiHj.mjs → schemaConverter-D--wdJM-.mjs} +70 -17
- package/dist/{schemaIR-Ca7ySNPx.mjs → schemaIR-Bm2enbnh.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-DHx5Fous.mjs} +4 -3
- package/dist/{sessionManager-BHOM3N_0.d.mts → sessionManager-qimlKV0P.d.mts} +1 -0
- package/dist/{simpleEqualityMatcher-Cg05HPsn.mjs → simpleEqualityMatcher-DjQJ7FKA.mjs} +1 -0
- package/dist/{sse-BQ1w0dfl.mjs → sse-CUTo9y0X.mjs} +5 -4
- package/dist/{sseStream-BQ7Qaynp.mjs → sseStream-B_5XcVVd.mjs} +2 -1
- package/dist/{storage-DLUZ04kK.d.mts → storage-Cx9Sz3Ou.d.mts} +1 -0
- package/dist/{store-helpers-DY6xq4sM.mjs → store-helpers-D1MP_gRG.mjs} +1 -0
- package/dist/{streaming-BQcW6_Kq.mjs → streaming-PSZwi8JV.mjs} +1 -0
- package/dist/subscribe-helpers-C0Tb2aUp.mjs +340 -0
- 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 +1 -0
- package/dist/testing/index.d.mts +167 -12
- package/dist/testing/index.mjs +522 -205
- package/dist/testing/outboxStoreContract.d.mts +1 -0
- package/dist/testing/outboxStoreContract.mjs +1 -0
- package/dist/testing/storageContract.d.mts +2 -1
- package/dist/testing/storageContract.mjs +1 -0
- package/dist/{tracing-CsGKQJGg.d.mts → tracing-Dro5eH6j.d.mts} +1 -0
- package/dist/{transactionContext-PNdoyLLm.mjs → transactionContext-dAfBVUrk.mjs} +1 -0
- package/dist/{typeGuards-C9KXUly6.mjs → typeGuards-B0ryPo3I.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-Dmw-6Qeo.d.mts → types-B7XeLEgK.d.mts} +127 -90
- 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-Cu6vVJmh.d.mts → types-CBgvkp8O.d.mts} +82 -12
- package/dist/{types-DjC-KUCz.d.mts → types-ChuShpCP.d.mts} +1 -0
- package/dist/{types-QFGc3Cjv.d.mts → types-CwcUQ610.d.mts} +2 -6
- package/dist/{types-CSyCxl2V.mjs → types-Cys0ko9Z.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-ChYJ6CdK.mjs} +1 -0
- package/dist/utils/index.d.mts +16 -10
- package/dist/utils/index.mjs +10 -9
- package/dist/{utils-taUVD4p3.mjs → utils-vL8BrDE2.mjs} +3 -2
- package/dist/{validate-Bk44F2yT.mjs → validate-_KbifpHF.mjs} +2 -1
- package/dist/{versioning-gKWyryT3.mjs → versioning-CHDTor3P.mjs} +3 -2
- 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 +15 -7
- 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/index-CZY4EGga.d.mts +0 -107
- package/dist/module-_-M7C5ES.mjs +0 -29
package/dist/utils/index.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import { n as
|
|
3
|
-
import { n as
|
|
4
|
-
import { t as
|
|
5
|
-
import {
|
|
6
|
-
import { a as
|
|
7
|
-
import { a as
|
|
8
|
-
import { t as
|
|
9
|
-
import { t as
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { a as OrgAccessDeniedError, c as ServiceUnavailableError, d as createDomainError, f as createError, i as NotFoundError, l as UnauthorizedError, n as ConflictError, o as OrgRequiredError, p as isArcError, r as ForbiddenError, s as RateLimitError, t as ArcError, u as ValidationError } from "../errors-Cj42AntO.mjs";
|
|
3
|
+
import { n as requireSingleHeaderValue, t as getHeader } from "../headers-3zvE0rM3.mjs";
|
|
4
|
+
import { n as getUserRoles, r as normalizeRoles, t as getUserId } from "../userHelpers-ChYJ6CdK.mjs";
|
|
5
|
+
import { t as simpleEqualityMatcher } from "../simpleEqualityMatcher-DjQJ7FKA.mjs";
|
|
6
|
+
import { A as createCircuitBreakerRegistry, C as defineCompensation, D as CircuitBreakerRegistry, E as CircuitBreakerError, O as CircuitState, S as defineErrorMapper, T as CircuitBreaker, _ as createQueryParser, a as deleteResponse, b as NEUTRAL_DIALECT, c as getDefaultCrudSchemas, d as listResponse, f as offsetListResponse, g as ArcQueryParser, h as responses, i as bareListResponse, k as createCircuitBreaker, l as getListQueryParams, m as queryParams, n as scheduleBackground, o as errorContractSchema, p as paginationSchema, r as aggregateListResponse, s as errorDetailSchema, t as createStateMachine, u as keysetListResponse, v as handleRaw, w as withCompensation, x as defineGuard, y as MONGO_DIALECT } from "../utils-vL8BrDE2.mjs";
|
|
7
|
+
import { a as isZodSchema, i as isJsonSchema, n as convertRouteSchema, o as toJsonSchema, t as convertOpenApiSchemas } from "../schemaConverter-D--wdJM-.mjs";
|
|
8
|
+
import { a as promoteStreamTokenToHeader, i as pipeUIMessageStreamToReply, n as forwardedStreamHeaders, r as isReadableStream, t as UI_MESSAGE_STREAM_HEADERS } from "../streaming-PSZwi8JV.mjs";
|
|
9
|
+
import { t as openSseStream } from "../sseStream-B_5XcVVd.mjs";
|
|
10
|
+
import { t as hasEvents } from "../typeGuards-B0ryPo3I.mjs";
|
|
10
11
|
export { ArcError, ArcQueryParser, CircuitBreaker, CircuitBreakerError, CircuitBreakerRegistry, CircuitState, ConflictError, ForbiddenError, MONGO_DIALECT, NEUTRAL_DIALECT, NotFoundError, OrgAccessDeniedError, OrgRequiredError, RateLimitError, ServiceUnavailableError, UI_MESSAGE_STREAM_HEADERS, UnauthorizedError, ValidationError, aggregateListResponse, bareListResponse, convertOpenApiSchemas, convertRouteSchema, createCircuitBreaker, createCircuitBreakerRegistry, createDomainError, createError, createQueryParser, createStateMachine, defineCompensation, defineErrorMapper, defineGuard, deleteResponse, errorContractSchema, errorDetailSchema, forwardedStreamHeaders, getDefaultCrudSchemas, getHeader, getListQueryParams, getUserId, getUserRoles, handleRaw, hasEvents, isArcError, isJsonSchema, isReadableStream, isZodSchema, keysetListResponse, listResponse, normalizeRoles, offsetListResponse, openSseStream, paginationSchema, pipeUIMessageStreamToReply, promoteStreamTokenToHeader, queryParams, requireSingleHeaderValue, responses, scheduleBackground, simpleEqualityMatcher, toJsonSchema, withCompensation };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { m as RESERVED_QUERY_PARAMS } from "./constants-D3Dv4LAV.mjs";
|
|
2
3
|
import { arcLog } from "./logger/index.mjs";
|
|
3
|
-
import { t as ArcError } from "./errors-
|
|
4
|
+
import { t as ArcError } from "./errors-Cj42AntO.mjs";
|
|
4
5
|
import { errorContractSchema as errorContractSchema$1, errorDetailSchema as errorDetailSchema$1 } from "@classytic/repo-core/errors";
|
|
5
6
|
import { scheduleBackground } from "@classytic/repo-core/cache";
|
|
6
7
|
//#region src/utils/circuitBreaker.ts
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-CUsjNX9R.mjs";
|
|
2
3
|
//#region src/core/aggregation/normalize.ts
|
|
3
4
|
/**
|
|
4
5
|
* Framework cap on URL-driven aggregation limits when the host opts
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-CUsjNX9R.mjs";
|
|
3
|
+
import { d as createDomainError } from "./errors-Cj42AntO.mjs";
|
|
3
4
|
import fp from "fastify-plugin";
|
|
4
5
|
//#region src/plugins/versioning.ts
|
|
5
6
|
var versioning_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
import { n as DomainEvent } from "./EventTransport-2uVV34WU.mjs";
|
|
2
3
|
import { FastifyPluginAsync, FastifyRequest } from "fastify";
|
|
3
4
|
//#region src/plugins/caching.d.ts
|
|
4
5
|
interface CachingRule {
|
|
@@ -85,7 +86,9 @@ interface RealtimeOptions {
|
|
|
85
86
|
* the feed when the auth token's `exp` passes (forcing reconnect +
|
|
86
87
|
* re-authorization with fresh filters) — this option adds a cap for
|
|
87
88
|
* session/cookie auth that carries no `exp`, or to tighten below the
|
|
88
|
-
* token TTL.
|
|
89
|
+
* token TTL. **Defaults to 30 min** ({@link DEFAULT_MAX_CONNECTION_MS}) so a
|
|
90
|
+
* feed is NEVER unbounded by omission; set a large explicit value (up to
|
|
91
|
+
* ~24.8 days) for a deliberately long-lived feed.
|
|
89
92
|
*/
|
|
90
93
|
maxConnectionMs?: number;
|
|
91
94
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
import { a as PushRefRegistry, l as EnvelopeWriter, s as PushRefStore } from "./pushref-registry-Dov9l4qE.mjs";
|
|
2
3
|
import { FastifyBaseLogger, FastifyPluginAsync } from "fastify";
|
|
3
4
|
//#region src/integrations/websocket/adapter.d.ts
|
|
4
5
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@classytic/arc",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.31.0",
|
|
4
4
|
"description": "Resource-oriented backend framework for Fastify - clean, minimal, powerful, tree-shakable",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -297,7 +297,8 @@
|
|
|
297
297
|
"dist",
|
|
298
298
|
"bin",
|
|
299
299
|
"skills",
|
|
300
|
-
"llms.txt"
|
|
300
|
+
"llms.txt",
|
|
301
|
+
"TRADEMARK.md"
|
|
301
302
|
],
|
|
302
303
|
"scripts": {
|
|
303
304
|
"build": "tsdown",
|
|
@@ -336,13 +337,14 @@
|
|
|
336
337
|
"check:peer-skew": "node scripts/check-peer-skew.mjs",
|
|
337
338
|
"check:docs-drift": "node scripts/check-docs-drift.mjs",
|
|
338
339
|
"check:boundaries": "node scripts/check-boundaries.mjs",
|
|
339
|
-
"prepublishOnly": "npm run check:peer-skew && npm run check:docs-drift && npm run check:boundaries && npm run typecheck && npm run lint && npm run build && npm run check:api-surface && npm run check:package && npm run test:ci && npm run smoke:consumer"
|
|
340
|
+
"prepublishOnly": "npm run check:peer-skew && npm run check:docs-drift && npm run check:route-api && npm run check:boundaries && npm run typecheck && npm run lint && npm run build && npm run check:api-surface && npm run check:package && npm run test:ci && npm run smoke:consumer",
|
|
341
|
+
"check:route-api": "node scripts/check-removed-route-api.mjs"
|
|
340
342
|
},
|
|
341
343
|
"engines": {
|
|
342
344
|
"node": ">=22"
|
|
343
345
|
},
|
|
344
346
|
"peerDependencies": {
|
|
345
|
-
"@classytic/primitives": ">=0.
|
|
347
|
+
"@classytic/primitives": ">=0.18.0",
|
|
346
348
|
"@classytic/repo-core": ">=0.17.0",
|
|
347
349
|
"@classytic/streamline": ">=2.8.0",
|
|
348
350
|
"@fastify/cors": ">=11.0.0",
|
|
@@ -363,14 +365,15 @@
|
|
|
363
365
|
"@opentelemetry/sdk-node": ">=0.50.0",
|
|
364
366
|
"better-auth": ">=1.6.2",
|
|
365
367
|
"bullmq": ">=5.0.0",
|
|
366
|
-
"fastify": "
|
|
368
|
+
"fastify": ">=5.8.5",
|
|
367
369
|
"fastify-raw-body": ">=5.0.0",
|
|
368
370
|
"h3-js": ">=4.0.0",
|
|
369
371
|
"ioredis": ">=5.0.0",
|
|
370
372
|
"jose": ">=5.0.0",
|
|
371
373
|
"pino-pretty": ">=13.0.0",
|
|
372
374
|
"typebox": ">=1.0.0",
|
|
373
|
-
"zod": ">=4.
|
|
375
|
+
"zod": ">=4.4.0",
|
|
376
|
+
"@fastify/static": ">=8.0.0"
|
|
374
377
|
},
|
|
375
378
|
"peerDependenciesMeta": {
|
|
376
379
|
"better-auth": {
|
|
@@ -450,6 +453,9 @@
|
|
|
450
453
|
},
|
|
451
454
|
"@modelcontextprotocol/sdk": {
|
|
452
455
|
"optional": true
|
|
456
|
+
},
|
|
457
|
+
"@fastify/static": {
|
|
458
|
+
"optional": true
|
|
453
459
|
}
|
|
454
460
|
},
|
|
455
461
|
"dependencies": {
|
|
@@ -466,7 +472,7 @@
|
|
|
466
472
|
"@classytic/gitkit": ">=0.1.0",
|
|
467
473
|
"@classytic/mongokit": "^3.28.0",
|
|
468
474
|
"@classytic/pgkit": "^0.1.0",
|
|
469
|
-
"@classytic/primitives": "^0.
|
|
475
|
+
"@classytic/primitives": "^0.18.0",
|
|
470
476
|
"@classytic/repo-core": "^0.17.0",
|
|
471
477
|
"@classytic/sqlitekit": "^0.6.0",
|
|
472
478
|
"@classytic/streamline": "^2.8.2",
|
|
@@ -477,6 +483,7 @@
|
|
|
477
483
|
"@fastify/multipart": "^10.0.0",
|
|
478
484
|
"@fastify/rate-limit": "^11.0.0",
|
|
479
485
|
"@fastify/sensible": "^6.0.4",
|
|
486
|
+
"@fastify/static": "^10.1.2",
|
|
480
487
|
"@fastify/type-provider-typebox": "^6.1.0",
|
|
481
488
|
"@fastify/under-pressure": "^9.0.3",
|
|
482
489
|
"@fastify/websocket": "^11.2.0",
|
|
@@ -534,6 +541,7 @@
|
|
|
534
541
|
],
|
|
535
542
|
"author": "Classytic",
|
|
536
543
|
"license": "MIT",
|
|
544
|
+
"homepage": "https://classytic.com",
|
|
537
545
|
"repository": {
|
|
538
546
|
"type": "git",
|
|
539
547
|
"url": "git+https://github.com/classytic/arc.git"
|
package/skills/arc/SKILL.md
CHANGED
|
@@ -123,7 +123,7 @@ export default defineResource({
|
|
|
123
123
|
|
|
124
124
|
routes: [
|
|
125
125
|
{ method: 'GET', path: '/featured', handler: 'getFeatured', permissions: allowPublic() },
|
|
126
|
-
{ method: 'POST', path: '/webhook',
|
|
126
|
+
{ method: 'POST', path: '/webhook', rawHandler: webhookFn, permissions: requireAuth() },
|
|
127
127
|
],
|
|
128
128
|
actions: {
|
|
129
129
|
approve: { handler: approveOrder, permissions: requireRoles(['admin']) },
|
|
@@ -133,6 +133,20 @@ export default defineResource({
|
|
|
133
133
|
|
|
134
134
|
**Auto-generated:** `GET /`, `GET /:id`, `POST /`, `PATCH /:id`, `DELETE /:id`. Presets add their own routes (see table below).
|
|
135
135
|
|
|
136
|
+
### Custom routes: `handler` vs `rawHandler`
|
|
137
|
+
|
|
138
|
+
A route declares its execution model by WHICH FIELD it fills — there is no `raw` flag (removed in 2.31).
|
|
139
|
+
|
|
140
|
+
| Field | Signature | Behaviour |
|
|
141
|
+
|---|---|---|
|
|
142
|
+
| `handler` | `(ctx: IRequestContext)` or a controller-method name | Arc pipeline: envelope shaping, field-write permissions, MCP tool by default |
|
|
143
|
+
| `rawHandler` | `(request, reply)` or a controller-method name | Fastify-native: owns the response, no pipeline, no MCP unless `mcpHandler` is set |
|
|
144
|
+
| `controllerMethod` | `(c: MyController) => c.method` | Typed ref for the pipeline — TS catches typos |
|
|
145
|
+
|
|
146
|
+
Declaring both `handler` and `rawHandler` throws at boot. `streamResponse: true` requires `rawHandler` (the handler is invoked with `(request, reply)` and owns the socket).
|
|
147
|
+
|
|
148
|
+
Inline `rawHandler` parameters infer — no `req: FastifyRequest` annotation — and typed generics (`FastifyRequest<{ Body: CreateBody }>`) assign without a cast.
|
|
149
|
+
|
|
136
150
|
**Resource shorthands:**
|
|
137
151
|
|
|
138
152
|
```typescript
|
|
@@ -317,8 +331,8 @@ defineResource({
|
|
|
317
331
|
name: 'procurement',
|
|
318
332
|
routeGuards: [tenantGuard.preHandler],
|
|
319
333
|
routes: [{
|
|
320
|
-
method: 'GET', path: '/summary',
|
|
321
|
-
|
|
334
|
+
method: 'GET', path: '/summary', permissions: requireAuth(),
|
|
335
|
+
rawHandler: async (req, reply) => {
|
|
322
336
|
const { orgId } = tenantGuard.from(req);
|
|
323
337
|
reply.send({ orgId });
|
|
324
338
|
},
|
|
@@ -570,9 +584,9 @@ defineResource({
|
|
|
570
584
|
name: 'chat',
|
|
571
585
|
customRoutesOnly: true,
|
|
572
586
|
routes: [{
|
|
573
|
-
method: 'POST', path: '/', streamResponse: true,
|
|
587
|
+
method: 'POST', path: '/', streamResponse: true,
|
|
574
588
|
permissions: requireAuth(),
|
|
575
|
-
|
|
589
|
+
rawHandler: async (req) => {
|
|
576
590
|
const result = streamText({ model, messages: req.body.messages });
|
|
577
591
|
return result.toUIMessageStream(); // arc pipes it for you
|
|
578
592
|
},
|
|
@@ -692,7 +706,7 @@ import { envelope } from '@classytic/arc';
|
|
|
692
706
|
import { multipartBody } from '@classytic/arc/middleware';
|
|
693
707
|
|
|
694
708
|
// Typed request — no `(req as any).user`
|
|
695
|
-
|
|
709
|
+
rawHandler: async (req: ArcRequest, reply) => { req.user?.id; req.scope; req.signal; }
|
|
696
710
|
|
|
697
711
|
// File upload — no-op for JSON requests, safe to always add
|
|
698
712
|
defineResource({
|
|
@@ -706,10 +720,10 @@ defineResource({
|
|
|
706
720
|
},
|
|
707
721
|
});
|
|
708
722
|
|
|
709
|
-
// SSE — preAuth runs before auth (EventSource can't set headers);
|
|
723
|
+
// SSE — preAuth runs before auth (EventSource can't set headers); rawHandler streams the response
|
|
710
724
|
routes: [
|
|
711
725
|
{ preAuth: [(req) => { req.headers.authorization = `Bearer ${req.query.token}`; }] },
|
|
712
|
-
{ method: 'GET', path: '/stream',
|
|
726
|
+
{ method: 'GET', path: '/stream', rawHandler: async (req, reply) => reply.send(stream) },
|
|
713
727
|
]
|
|
714
728
|
|
|
715
729
|
// Per-route rate limit (2.20) — overrides the resource/app default for ONE endpoint.
|
|
@@ -60,6 +60,10 @@ import {
|
|
|
60
60
|
allowPublic, requireAuth, requireRoles, requireOwnership,
|
|
61
61
|
requireOrgMembership, requireOrgRole, requireTeamMembership,
|
|
62
62
|
requireServiceScope, requireScopeContext, requireOrgInScope,
|
|
63
|
+
// Platform-only role gate — an ORG role can never satisfy it. Required by
|
|
64
|
+
// globally-scoped surfaces (jobsPlugin managementRoutes) that cannot filter by tenant.
|
|
65
|
+
requirePlatformRole,
|
|
66
|
+
|
|
63
67
|
// Agent-auth (2.13) — DPoP + capability mandates (AP2 / x402 / MCP)
|
|
64
68
|
requireAgentScope, requireMandate, requireDPoP,
|
|
65
69
|
type RequireAgentScopeOptions, type RequireMandateOptions,
|
|
@@ -484,6 +484,9 @@ auth: false
|
|
|
484
484
|
import {
|
|
485
485
|
allowPublic, requireAuth, requireRoles, requireOwnership,
|
|
486
486
|
requireOrgMembership, requireOrgRole, requireTeamMembership,
|
|
487
|
+
// Platform-only role gate — an ORG role can never satisfy it. Required by
|
|
488
|
+
// globally-scoped surfaces (jobsPlugin managementRoutes) that cannot filter by tenant.
|
|
489
|
+
requirePlatformRole,
|
|
487
490
|
allOf, anyOf, when, denyAll,
|
|
488
491
|
} from '@classytic/arc';
|
|
489
492
|
```
|
|
@@ -71,11 +71,44 @@ await fastify.jobs.dispatch('process-image', { url: '...', width: 800 }, {
|
|
|
71
71
|
removeOnComplete: true,
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
+
// dispatch returns a JobHandle — the queue is part of the identity because
|
|
75
|
+
// BullMQ ids are queue-LOCAL (two queues can both hold "123").
|
|
76
|
+
const { queue, jobId } = await fastify.jobs.dispatch('send-email', { to: 'a@b.com' });
|
|
77
|
+
const status = await fastify.jobs.getStatus(queue, jobId);
|
|
78
|
+
|
|
74
79
|
// Get stats
|
|
75
80
|
const stats = await fastify.jobs.getStats();
|
|
76
81
|
// { 'send-email': { waiting: 5, active: 2, completed: 100, failed: 3, delayed: 0 } }
|
|
77
82
|
```
|
|
78
83
|
|
|
84
|
+
### Management routes (off by default)
|
|
85
|
+
|
|
86
|
+
`GET /jobs/stats` and `GET /jobs/:queue/:id/status` are NOT mounted unless you
|
|
87
|
+
ask for them. A status carries `returnValue` and `failedReason` — your handler's
|
|
88
|
+
own output and error text — so an unauthenticated route turns a job id into a
|
|
89
|
+
read primitive over other tenants' work.
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
jobsPlugin({
|
|
93
|
+
connection,
|
|
94
|
+
jobs,
|
|
95
|
+
managementRoutes: {
|
|
96
|
+
// Must be PLATFORM-only, verified at boot. These routes are global: /stats
|
|
97
|
+
// spans every queue and a job carries no tenant identity, so an org-role
|
|
98
|
+
// gate would let org A's manager read org B's job.
|
|
99
|
+
operatorPermission: requirePlatformRole('platform-ops'),
|
|
100
|
+
exposeResult: false, // default — opt in knowing what your handlers return
|
|
101
|
+
exposeFailureReason: false, // default
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`requireOrgRole('manager')` and the default `requireRoles(['platform-ops'])` are
|
|
107
|
+
REFUSED at boot: both grant on an organization role and return no policy, so
|
|
108
|
+
nothing at request time can tell them apart from a real operator gate. Use
|
|
109
|
+
`requirePlatformRole`, or `allowUnverifiedOperatorPermission: true` for a custom
|
|
110
|
+
check you have verified yourself.
|
|
111
|
+
|
|
79
112
|
### Timeout & DLQ
|
|
80
113
|
|
|
81
114
|
Job timeout via `Promise.race` (timer always cleaned up). DLQ queues tracked and closed on shutdown:
|
|
@@ -568,12 +568,12 @@ Use to verify the MCP server is alive before configuring Claude CLI.
|
|
|
568
568
|
|
|
569
569
|
### ArcRequest — Typed Fastify Request
|
|
570
570
|
|
|
571
|
-
For `
|
|
571
|
+
For `rawHandler` routes, use `ArcRequest` instead of `(req as any).user`:
|
|
572
572
|
|
|
573
573
|
```typescript
|
|
574
574
|
import type { ArcRequest } from '@classytic/arc';
|
|
575
575
|
|
|
576
|
-
|
|
576
|
+
rawHandler: async (req: ArcRequest, reply) => {
|
|
577
577
|
req.user?.id; // typed
|
|
578
578
|
req.scope.organizationId; // typed (when member)
|
|
579
579
|
req.signal; // AbortSignal (Fastify 5 built-in)
|
|
@@ -585,7 +585,7 @@ handler: async (req: ArcRequest, reply) => {
|
|
|
585
585
|
```typescript
|
|
586
586
|
import { envelope } from '@classytic/arc';
|
|
587
587
|
|
|
588
|
-
|
|
588
|
+
rawHandler: async (req, reply) => {
|
|
589
589
|
const data = await service.getResults();
|
|
590
590
|
return reply.send(envelope(data));
|
|
591
591
|
// → { data }
|
|
@@ -601,7 +601,7 @@ Eliminates duplicated `req.user.organizationId || req.headers['x-organization-id
|
|
|
601
601
|
```typescript
|
|
602
602
|
import { getOrgContext } from '@classytic/arc/scope';
|
|
603
603
|
|
|
604
|
-
|
|
604
|
+
rawHandler: async (req, reply) => {
|
|
605
605
|
const { userId, organizationId, roles, orgRoles } = getOrgContext(req);
|
|
606
606
|
// Works regardless of auth type (JWT, Better Auth, custom)
|
|
607
607
|
}
|
|
@@ -628,13 +628,12 @@ Run before auth middleware. Use for promoting `?token=` to `Authorization` heade
|
|
|
628
628
|
routes: [{
|
|
629
629
|
method: 'GET',
|
|
630
630
|
path: '/stream',
|
|
631
|
-
raw: true,
|
|
632
631
|
permissions: requireAuth(),
|
|
633
632
|
preAuth: [(req) => {
|
|
634
633
|
const token = req.query?.token;
|
|
635
634
|
if (token) req.headers.authorization = `Bearer ${token}`;
|
|
636
635
|
}],
|
|
637
|
-
|
|
636
|
+
rawHandler: sseHandler,
|
|
638
637
|
}]
|
|
639
638
|
```
|
|
640
639
|
|
|
@@ -648,7 +647,7 @@ routes: [{
|
|
|
648
647
|
path: '/stream',
|
|
649
648
|
streamResponse: true, // SSE headers + no { success, data } wrapper
|
|
650
649
|
permissions: requireAuth(),
|
|
651
|
-
|
|
650
|
+
rawHandler: async (request, reply) => {
|
|
652
651
|
const { stream } = await generateStream({ abortSignal: request.signal });
|
|
653
652
|
return reply.send(stream);
|
|
654
653
|
},
|
|
@@ -696,8 +696,7 @@ defineResource({
|
|
|
696
696
|
method: 'POST',
|
|
697
697
|
path: '/:id/checkout',
|
|
698
698
|
permissions: requireAuth(),
|
|
699
|
-
|
|
700
|
-
handler: async (request, reply) => {
|
|
699
|
+
rawHandler: async (request, reply) => {
|
|
701
700
|
const result = await withCompensation('checkout', steps, { orderId: request.params.id });
|
|
702
701
|
if (!result.success) return reply.code(422).send({ error: result.error });
|
|
703
702
|
return reply.send({ data: result.results });
|
|
@@ -709,26 +708,26 @@ defineResource({
|
|
|
709
708
|
**Compensation errors**: collected in `result.compensationErrors[]` without stopping rollback. **Context**: mutable `Record<string, unknown>` shared across all steps.
|
|
710
709
|
|
|
711
710
|
**Scope**: In-process primitive. Process crash = no compensation. For durable distributed workflows, use Temporal, Inngest, or `@classytic/streamline`.
|
|
712
|
-
|
|
713
|
-
## Multi-Domain Deployment
|
|
714
|
-
|
|
715
|
-
Arc supports multi-domain applications through COMPOSITION — it deliberately owns no domain routing, domain databases, certificate provisioning, or wildcard-domain management. The deployment shape:
|
|
716
|
-
|
|
717
|
-
```
|
|
718
|
-
api.example.com → arc API
|
|
719
|
-
auth.example.com → Better Auth (or auth module)
|
|
720
|
-
events.example.com → SSE/WebSocket edge tier
|
|
721
|
-
admin.example.com → frontend
|
|
722
|
-
customer-domain.com → gateway/domain resolver → tenant context
|
|
723
|
-
```
|
|
724
|
-
|
|
725
|
-
The primitives are already there: CORS allowlists, Better Auth trusted origins, tenant scope, request context, `trustProxy` configuration, resource/module prefixes.
|
|
726
|
-
|
|
727
|
-
**Custom tenant domains**: resolve the domain at a gateway or an early host plugin, then convert it into a trusted `RequestScope` — a small host-provided resolver is enough:
|
|
728
|
-
|
|
729
|
-
```typescript
|
|
730
|
-
// onRequest, before auth: map host → tenant hint
|
|
731
|
-
const tenant = await resolveTenantDomain(request.hostname); // → { organizationId } | null
|
|
732
|
-
```
|
|
733
|
-
|
|
734
|
-
Then validate membership or service scope through the NORMAL permission path. **Never treat raw `Host` / `X-Forwarded-Host` as tenant authorization by itself** — behind a misconfigured proxy those are attacker-controlled (see the `trustProxy` boot warning). The header selects the tenant *candidate*; membership resolution authorizes it — same rule `resolveOrgFromHeader` follows for `x-organization-id`.
|
|
711
|
+
|
|
712
|
+
## Multi-Domain Deployment
|
|
713
|
+
|
|
714
|
+
Arc supports multi-domain applications through COMPOSITION — it deliberately owns no domain routing, domain databases, certificate provisioning, or wildcard-domain management. The deployment shape:
|
|
715
|
+
|
|
716
|
+
```
|
|
717
|
+
api.example.com → arc API
|
|
718
|
+
auth.example.com → Better Auth (or auth module)
|
|
719
|
+
events.example.com → SSE/WebSocket edge tier
|
|
720
|
+
admin.example.com → frontend
|
|
721
|
+
customer-domain.com → gateway/domain resolver → tenant context
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
The primitives are already there: CORS allowlists, Better Auth trusted origins, tenant scope, request context, `trustProxy` configuration, resource/module prefixes.
|
|
725
|
+
|
|
726
|
+
**Custom tenant domains**: resolve the domain at a gateway or an early host plugin, then convert it into a trusted `RequestScope` — a small host-provided resolver is enough:
|
|
727
|
+
|
|
728
|
+
```typescript
|
|
729
|
+
// onRequest, before auth: map host → tenant hint
|
|
730
|
+
const tenant = await resolveTenantDomain(request.hostname); // → { organizationId } | null
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
Then validate membership or service scope through the NORMAL permission path. **Never treat raw `Host` / `X-Forwarded-Host` as tenant authorization by itself** — behind a misconfigured proxy those are attacker-controlled (see the `trustProxy` boot warning). The header selects the tenant *candidate*; membership resolution authorizes it — same rule `resolveOrgFromHeader` follows for `x-organization-id`.
|
|
@@ -627,7 +627,7 @@ output_mode: content
|
|
|
627
627
|
|
|
628
628
|
**Why critical:** `verifySignature(body, ...)` throws `TypeError` if body isn't string/Buffer. Parsed body silently fails verification → forged webhooks accepted.
|
|
629
629
|
|
|
630
|
-
**Fix:** `verifySignature(req.rawBody, ...)`.
|
|
630
|
+
**Fix:** `verifySignature(req.rawBody, ...)`. Declare webhook routes via `rawHandler` and ensure `@fastify/raw-body` is registered (arc registers it automatically when needed).
|
|
631
631
|
|
|
632
632
|
---
|
|
633
633
|
|
|
@@ -655,10 +655,10 @@ Or `presets: [{ name: 'filesUpload', storage, allowedMimeTypes, maxFileSize }]`.
|
|
|
655
655
|
```typescript
|
|
656
656
|
routes: [
|
|
657
657
|
{
|
|
658
|
-
method: 'GET', path: '/stream',
|
|
658
|
+
method: 'GET', path: '/stream',
|
|
659
659
|
preAuth: [(req) => { req.headers.authorization = `Bearer ${req.query.token}`; }],
|
|
660
660
|
permissions: requireAuth(),
|
|
661
|
-
|
|
661
|
+
rawHandler: async (req, reply) => reply.send(stream),
|
|
662
662
|
},
|
|
663
663
|
],
|
|
664
664
|
```
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { a as ModuleContribution, h as HealthCheck, n as ArcModuleInput, r as ArcModuleRegistry, t as ArcModule, u as ScheduleDefinition } from "./types-Cu6vVJmh.mjs";
|
|
2
|
-
import { FastifyInstance } from "fastify";
|
|
3
|
-
//#region src/factory/module/contributions.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* Collect every module's `healthChecks` in the caller's order. Fails at boot
|
|
6
|
-
* on a duplicate check `name` across modules, naming BOTH owning modules.
|
|
7
|
-
* The host's app-level checks are appended AFTER this (modules-first,
|
|
8
|
-
* host-last) by the caller.
|
|
9
|
-
*/
|
|
10
|
-
declare function collectModuleHealthChecks(modules: readonly ArcModule[]): HealthCheck[];
|
|
11
|
-
/**
|
|
12
|
-
* Collect every module's `workflows`. Resolves factory contributions (so a
|
|
13
|
-
* factory can close over a container the caller has already decorated on
|
|
14
|
-
* `fastify`) and flattens to a single opaque array. Arc core deliberately
|
|
15
|
-
* does NOT validate or interpret the values — the streamline integration
|
|
16
|
-
* owns name/shape checks and registration. Called by the integration at init
|
|
17
|
-
* time, not by arc's boot pipeline (workflows depend on the integration's
|
|
18
|
-
* container).
|
|
19
|
-
*/
|
|
20
|
-
declare function collectModuleWorkflows(fastify: FastifyInstance, modules: readonly ArcModule[]): Promise<unknown[]>;
|
|
21
|
-
/**
|
|
22
|
-
* Collect every module's `scheduledJobs`. Resolves factory contributions
|
|
23
|
-
* (after bootstraps) and fails at boot on a duplicate job `name` across
|
|
24
|
-
* modules. The caller passes the returned definitions to the canonical
|
|
25
|
-
* schedules plugin; factories must therefore be resolved only once.
|
|
26
|
-
*/
|
|
27
|
-
declare function collectModuleScheduledJobs(fastify: FastifyInstance, modules: readonly ArcModule[]): Promise<ScheduleDefinition[]>;
|
|
28
|
-
//#endregion
|
|
29
|
-
//#region src/factory/module/lifecycle.d.ts
|
|
30
|
-
/**
|
|
31
|
-
* Subscribe every module's `eventHandlers` in dependency order (pass the
|
|
32
|
-
* `orderModules`-sorted list). Returns the ordered list of unsubscribe
|
|
33
|
-
* functions so the caller can tear them down at shutdown BEFORE module
|
|
34
|
-
* `onClose` (while module deps are still alive). Fails at boot on:
|
|
35
|
-
* - a duplicate NAMED handler across modules (attributing both owners);
|
|
36
|
-
* - a module declaring handlers while the event subsystem is unavailable.
|
|
37
|
-
* Resolves factory contributions (after bootstraps) so a handler can close over
|
|
38
|
-
* booted engines rather than a global getter.
|
|
39
|
-
*/
|
|
40
|
-
declare function subscribeModuleEventHandlers(fastify: FastifyInstance, modules: readonly ArcModule[]): Promise<Array<() => void | Promise<void>>>;
|
|
41
|
-
//#endregion
|
|
42
|
-
//#region src/factory/module/order.d.ts
|
|
43
|
-
/**
|
|
44
|
-
* Order modules for composition by their `dependsOn` edges — a STABLE
|
|
45
|
-
* topological sort. Called once at the start of the bootstrap phase; every
|
|
46
|
-
* subsequent phase (bootstrap, resources, afterResources, and reverse-order
|
|
47
|
-
* onClose) iterates the returned list, so a module's declared dependencies are
|
|
48
|
-
* always composed before it.
|
|
49
|
-
*
|
|
50
|
-
* "Stable" = modules with no edge between them keep their original list order,
|
|
51
|
-
* so declaring `dependsOn` on one module never silently reorders an unrelated
|
|
52
|
-
* one. Backward compatible: a `modules` array with NO `dependsOn` anywhere is
|
|
53
|
-
* returned unchanged.
|
|
54
|
-
*
|
|
55
|
-
* Fail-fast — throws (never reorders past a broken contract) on:
|
|
56
|
-
* - duplicate module names (the name is the graph key)
|
|
57
|
-
* - a `dependsOn` name not present in the composed set
|
|
58
|
-
* - a self-reference (`dependsOn` includes the module's own name)
|
|
59
|
-
* - a dependency cycle (reports the concrete `a → b → … → a` path)
|
|
60
|
-
*/
|
|
61
|
-
declare function orderModules(modules: readonly ArcModule[]): ArcModule[];
|
|
62
|
-
//#endregion
|
|
63
|
-
//#region src/factory/module/resolve.d.ts
|
|
64
|
-
/**
|
|
65
|
-
* Resolve any module-input form to a concrete `ArcModule`. A thunk is invoked
|
|
66
|
-
* (this is where a dynamic `import()` fires); a promise (or plain module) is
|
|
67
|
-
* awaited. Called once per module at the start of the bootstrap phase.
|
|
68
|
-
*/
|
|
69
|
-
declare function resolveModule(input: ArcModuleInput): Promise<ArcModule>;
|
|
70
|
-
/** Resolve a `ModuleContribution` to a concrete array (array passthrough or factory call). */
|
|
71
|
-
declare function resolveContribution<T>(contribution: ModuleContribution<T> | undefined, fastify: FastifyInstance): Promise<readonly T[]>;
|
|
72
|
-
//#endregion
|
|
73
|
-
//#region src/factory/module/index.d.ts
|
|
74
|
-
/**
|
|
75
|
-
* Identity helper for authoring a typed module — mirrors `defineResource`.
|
|
76
|
-
* Gives inference + a single obvious construction site; does no work.
|
|
77
|
-
*
|
|
78
|
-
* `TExports` is inferred from the `bootstrap` return value, so a module
|
|
79
|
-
* author gets a typed public export for free:
|
|
80
|
-
*
|
|
81
|
-
* ```ts
|
|
82
|
-
* export const accountingModule = (deps: Deps) =>
|
|
83
|
-
* defineModule({
|
|
84
|
-
* name: "accounting",
|
|
85
|
-
* bootstrap: async () => createAccountingEngine(deps), // TExports inferred
|
|
86
|
-
* });
|
|
87
|
-
* ```
|
|
88
|
-
*/
|
|
89
|
-
declare function defineModule<TExports = unknown>(module: ArcModule<TExports>): ArcModule<TExports>;
|
|
90
|
-
/**
|
|
91
|
-
* Typed accessor for a module's public export (its `bootstrap` return value),
|
|
92
|
-
* recorded at `fastify.arc.modules[name]`.
|
|
93
|
-
*
|
|
94
|
-
* Throwing, in line with the fail-fast contract (and `requireOrgId`-style
|
|
95
|
-
* accessors): a missing entry means the module either isn't composed, is
|
|
96
|
-
* composed AFTER the caller (list order = init order), or returned nothing —
|
|
97
|
-
* all wiring bugs that must surface at boot, not as `undefined` downstream.
|
|
98
|
-
*
|
|
99
|
-
* The type parameter is an assertion, not a proof. Two ways to type it:
|
|
100
|
-
* - augment `ArcModuleRegistry` once — then the name alone infers the type:
|
|
101
|
-
* `getModuleExports(f, "accounting")` → `AccountingEngine`.
|
|
102
|
-
* - or pass it inline: `getModuleExports<AccountingEngine>(f, "accounting")`.
|
|
103
|
-
*/
|
|
104
|
-
declare function getModuleExports<K extends keyof ArcModuleRegistry>(fastify: FastifyInstance, name: K): ArcModuleRegistry[K];
|
|
105
|
-
declare function getModuleExports<TExports = unknown>(fastify: FastifyInstance, name: string): TExports;
|
|
106
|
-
//#endregion
|
|
107
|
-
export { orderModules as a, collectModuleScheduledJobs as c, resolveModule as i, collectModuleWorkflows as l, getModuleExports as n, subscribeModuleEventHandlers as o, resolveContribution as r, collectModuleHealthChecks as s, defineModule as t };
|
package/dist/module-_-M7C5ES.mjs
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
//#region src/factory/module/index.ts
|
|
2
|
-
/**
|
|
3
|
-
* Identity helper for authoring a typed module — mirrors `defineResource`.
|
|
4
|
-
* Gives inference + a single obvious construction site; does no work.
|
|
5
|
-
*
|
|
6
|
-
* `TExports` is inferred from the `bootstrap` return value, so a module
|
|
7
|
-
* author gets a typed public export for free:
|
|
8
|
-
*
|
|
9
|
-
* ```ts
|
|
10
|
-
* export const accountingModule = (deps: Deps) =>
|
|
11
|
-
* defineModule({
|
|
12
|
-
* name: "accounting",
|
|
13
|
-
* bootstrap: async () => createAccountingEngine(deps), // TExports inferred
|
|
14
|
-
* });
|
|
15
|
-
* ```
|
|
16
|
-
*/
|
|
17
|
-
function defineModule(module) {
|
|
18
|
-
return module;
|
|
19
|
-
}
|
|
20
|
-
function getModuleExports(fastify, name) {
|
|
21
|
-
const modules = fastify.arc?.modules;
|
|
22
|
-
if (!modules || !Object.hasOwn(modules, name)) {
|
|
23
|
-
const available = modules ? Object.keys(modules) : [];
|
|
24
|
-
throw new Error(`[arc] no public export recorded for module "${name}".\nA module's export is its bootstrap() return value; it is readable only AFTER that module's bootstrap ran (dependsOn / list order = init order).\nModules with recorded exports: ${available.length ? available.join(", ") : "(none)"}.`);
|
|
25
|
-
}
|
|
26
|
-
return modules[name];
|
|
27
|
-
}
|
|
28
|
-
//#endregion
|
|
29
|
-
export { getModuleExports as n, defineModule as t };
|