@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
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
//#region src/core/aggregation/defineAggregation.ts
|
|
3
|
+
/**
|
|
4
|
+
* Declare a single resource aggregation. Exported configs flow into
|
|
5
|
+
* `defineResource({ aggregations: { ... } })` either as named keys or
|
|
6
|
+
* via auto-discovery patterns (loadAggregations — future).
|
|
7
|
+
*
|
|
8
|
+
* @example Inline
|
|
9
|
+
* ```ts
|
|
10
|
+
* defineResource({
|
|
11
|
+
* name: 'order',
|
|
12
|
+
* aggregations: {
|
|
13
|
+
* revenueByStatus: defineAggregation({
|
|
14
|
+
* groupBy: 'status',
|
|
15
|
+
* measures: { count: 'count', revenue: 'sum:totalPrice' },
|
|
16
|
+
* permissions: requireRoles(['admin']),
|
|
17
|
+
* }),
|
|
18
|
+
* },
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @example Multi-file
|
|
23
|
+
* ```ts
|
|
24
|
+
* // orders/aggregations/revenue-by-status.ts
|
|
25
|
+
* import { defineAggregation } from '@classytic/arc';
|
|
26
|
+
*
|
|
27
|
+
* export const revenueByStatus = defineAggregation({
|
|
28
|
+
* groupBy: 'status',
|
|
29
|
+
* measures: { count: 'count', revenue: 'sum:totalPrice' },
|
|
30
|
+
* permissions: requireRoles(['admin']),
|
|
31
|
+
* timeout: 5000,
|
|
32
|
+
* cache: { staleTime: 60 },
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* // orders/order.resource.ts
|
|
36
|
+
* import * as aggregations from './aggregations/index.js';
|
|
37
|
+
*
|
|
38
|
+
* defineResource({
|
|
39
|
+
* name: 'order',
|
|
40
|
+
* aggregations, // 30+ entries flow in
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
function defineAggregation(config) {
|
|
45
|
+
return config;
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
export { defineAggregation as t };
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS } from "./constants-D3Dv4LAV.mjs";
|
|
2
3
|
import { arcLog } from "./logger/index.mjs";
|
|
3
|
-
import { r as ForbiddenError } from "./errors-
|
|
4
|
-
import { n as getUserRoles } from "./userHelpers-
|
|
5
|
-
import { b as isElevated, n as PUBLIC_SCOPE, x as isMember } from "./types-
|
|
6
|
-
import { d as DEFAULT_FIELD_WRITE_DENIAL_POLICY, t as BaseController } from "./BaseController-
|
|
7
|
-
import { a as buildRouteHooks, c as buildAuthMiddleware, i as selectPluginMw, n as buildRouteConfig, o as resolveRoutePreHandlers, r as resolveRouterPluginMw, s as routeHookOptions, t as buildRateLimitConfig, u as buildArcDecorator } from "./rateLimit-
|
|
8
|
-
import {
|
|
9
|
-
import { r as buildCrudPermissionMw, t as tryRegisterRoute } from "./registerRoute-
|
|
10
|
-
import { c as getDefaultCrudSchemas } from "./utils-
|
|
11
|
-
import { n as convertRouteSchema, r as ensureSchemaConverter, t as convertOpenApiSchemas } from "./schemaConverter-
|
|
12
|
-
import { i as pipeUIMessageStreamToReply, r as isReadableStream } from "./streaming-
|
|
13
|
-
import { t as hasEvents } from "./typeGuards-
|
|
14
|
-
import { a as createFastifyHandler, i as createCrudHandlers, n as buildPipelineHandler, o as createRequestContext, r as resolvePipelineSteps
|
|
15
|
-
import {
|
|
16
|
-
import { r as getAvailablePresets, t as applyPresets } from "./presets-
|
|
17
|
-
import { t as pluralize } from "./pluralize-
|
|
18
|
-
import { t as resolveActionPermission } from "./actionPermissions-
|
|
4
|
+
import { r as ForbiddenError } from "./errors-Cj42AntO.mjs";
|
|
5
|
+
import { n as getUserRoles } from "./userHelpers-ChYJ6CdK.mjs";
|
|
6
|
+
import { b as isElevated, n as PUBLIC_SCOPE, x as isMember } from "./types-Cys0ko9Z.mjs";
|
|
7
|
+
import { d as DEFAULT_FIELD_WRITE_DENIAL_POLICY, t as BaseController } from "./BaseController-De7GqHck.mjs";
|
|
8
|
+
import { a as buildRouteHooks, c as buildAuthMiddleware, i as selectPluginMw, n as buildRouteConfig, o as resolveRoutePreHandlers, r as resolveRouterPluginMw, s as routeHookOptions, t as buildRateLimitConfig, u as buildArcDecorator } from "./rateLimit-CMPY5Qms.mjs";
|
|
9
|
+
import { i as resolveEffectiveRoles, n as applyFieldWritePermissions } from "./fields-CB5Cuzk9.mjs";
|
|
10
|
+
import { r as buildCrudPermissionMw, t as tryRegisterRoute } from "./registerRoute-CBN84fc7.mjs";
|
|
11
|
+
import { c as getDefaultCrudSchemas } from "./utils-vL8BrDE2.mjs";
|
|
12
|
+
import { n as convertRouteSchema, r as ensureSchemaConverter, t as convertOpenApiSchemas } from "./schemaConverter-D--wdJM-.mjs";
|
|
13
|
+
import { i as pipeUIMessageStreamToReply, r as isReadableStream } from "./streaming-PSZwi8JV.mjs";
|
|
14
|
+
import { t as hasEvents } from "./typeGuards-B0ryPo3I.mjs";
|
|
15
|
+
import { a as createFastifyHandler, i as createCrudHandlers, n as buildPipelineHandler, o as createRequestContext, r as resolvePipelineSteps } from "./pipeline-UPQFatit.mjs";
|
|
16
|
+
import { I as requireAuth } from "./permissions-L--QDAir.mjs";
|
|
17
|
+
import { r as getAvailablePresets, t as applyPresets } from "./presets-C4-g4_4P.mjs";
|
|
18
|
+
import { t as pluralize } from "./pluralize-O0FZgESl.mjs";
|
|
19
|
+
import { t as resolveActionPermission } from "./actionPermissions-BE5NwaQk.mjs";
|
|
19
20
|
//#region src/core/middlewares/fieldWrite.ts
|
|
20
21
|
/**
|
|
21
22
|
* Build a preHandler that enforces field-write permissions on the request body.
|
|
@@ -58,25 +59,30 @@ function methodCarriesBody(method) {
|
|
|
58
59
|
//#region src/core/createCrudRouter.ts
|
|
59
60
|
/**
|
|
60
61
|
* Mount custom routes (from presets or user-defined `routes`) on Fastify.
|
|
61
|
-
* `wrapHandler` is derived inline from
|
|
62
|
+
* `wrapHandler` is derived inline from whether `rawHandler` was set.
|
|
62
63
|
*/
|
|
63
64
|
function createCustomRoutes(fastify, routes, controller, options) {
|
|
64
65
|
const { tag, resourceName, arcDecorator, rateLimitConfig, pluginMw, pipeline, routeGuards, tenantScopeMw, fieldPermissions, onFieldWriteDenied, extensions } = options;
|
|
65
66
|
for (const route of routes) {
|
|
67
|
+
if ("raw" in route) throw new Error(`Route ${route.method} ${route.path}: \`raw\` was removed in arc 2.31 — the FIELD now carries the intent. Move the function to \`rawHandler\` (Fastify-native \`(request, reply)\`) or leave it in \`handler\` (arc pipeline, \`(ctx)\`), and delete the flag. If this route comes from a dependency, that package needs a release built against arc >=2.31.`);
|
|
66
68
|
const routeWithRefs = route;
|
|
67
|
-
const hasHandler = route.handler !== void 0;
|
|
69
|
+
const hasHandler = route.handler !== void 0 || route.rawHandler !== void 0;
|
|
68
70
|
const hasControllerMethod = typeof routeWithRefs.controllerMethod === "function";
|
|
69
71
|
if (hasHandler && hasControllerMethod) throw new Error(`Route ${route.method} ${route.path}: pass either \`handler\` or \`controllerMethod\`, not both. Prefer \`controllerMethod: (c: MyController) => c.method\` for typed handler refs (TS catches typos).`);
|
|
70
|
-
if (!hasHandler && !hasControllerMethod) throw new Error(`Route ${route.method} ${route.path}: must declare
|
|
72
|
+
if (!hasHandler && !hasControllerMethod) throw new Error(`Route ${route.method} ${route.path}: must declare one of \`handler\` (arc pipeline), \`rawHandler\` (Fastify-native), or \`controllerMethod: (c) => c.method\` (typed function-ref form).`);
|
|
71
73
|
let resolvedHandler;
|
|
72
74
|
if (hasControllerMethod) {
|
|
73
75
|
if (!controller) throw new Error(`Route ${route.method} ${route.path}: \`controllerMethod\` requires a controller. Provide one via \`defineResource({ controller, … })\`, or use \`defineResource\` with an \`adapter\` so arc auto-creates a BaseController.`);
|
|
74
76
|
const referenced = routeWithRefs.controllerMethod?.(controller);
|
|
75
77
|
if (typeof referenced !== "function") throw new Error(`Route ${route.method} ${route.path}: \`controllerMethod\` did not return a function. Return the method itself: \`controllerMethod: (c) => c.myMethod\`.`);
|
|
76
78
|
resolvedHandler = referenced.bind(controller);
|
|
77
|
-
} else
|
|
79
|
+
} else {
|
|
80
|
+
if (route.rawHandler && route.handler) throw new Error(`Route ${route.method} ${route.path}: set either \`handler\` (arc pipeline) or \`rawHandler\` (Fastify-native), not both.`);
|
|
81
|
+
resolvedHandler = route.rawHandler ?? route.handler;
|
|
82
|
+
}
|
|
78
83
|
const opName = route.operation ?? (typeof resolvedHandler === "string" ? resolvedHandler : `${route.method.toLowerCase()}${route.path.replace(/[/:]/g, "_")}`);
|
|
79
|
-
const
|
|
84
|
+
const isRaw = route.rawHandler !== void 0;
|
|
85
|
+
const wrapHandler = !isRaw;
|
|
80
86
|
let handler;
|
|
81
87
|
if (typeof resolvedHandler === "string") {
|
|
82
88
|
if (!controller) throw new Error(`Route ${route.method} ${route.path}: string handler '${resolvedHandler}' requires a controller. Either provide a controller or use a function handler instead.`);
|
|
@@ -104,7 +110,7 @@ function createCustomRoutes(fastify, routes, controller, options) {
|
|
|
104
110
|
if (!tenantScopeMw || tenantScopeMw.length === 0) throw new Error(`Route ${route.method} ${route.path}: \`tenantScope: true\` requires a multi-tenant preset. Add \`multiTenantPreset()\` (or \`flexibleMultiTenantPreset()\`) to the resource's \`presets\`, or remove the \`tenantScope\` flag from this route.`);
|
|
105
111
|
customPreHandlers.unshift(...tenantScopeMw);
|
|
106
112
|
}
|
|
107
|
-
if (
|
|
113
|
+
if (!isRaw && route.fieldWrite !== false && methodCarriesBody(route.method)) {
|
|
108
114
|
const fieldWriteMw = buildFieldWritePreHandler(fieldPermissions, onFieldWriteDenied);
|
|
109
115
|
if (fieldWriteMw) customPreHandlers.push(fieldWriteMw);
|
|
110
116
|
}
|
|
@@ -123,18 +129,18 @@ function createCustomRoutes(fastify, routes, controller, options) {
|
|
|
123
129
|
url: route.path,
|
|
124
130
|
schema,
|
|
125
131
|
...routeHookOptions(hooks),
|
|
126
|
-
handler: isStream ? async (request, reply)
|
|
132
|
+
handler: isStream ? async function streamRoute(request, reply) {
|
|
127
133
|
reply.raw.setHeader("Content-Type", "text/event-stream");
|
|
128
134
|
reply.raw.setHeader("Cache-Control", "no-cache");
|
|
129
135
|
reply.raw.setHeader("Connection", "keep-alive");
|
|
130
|
-
const result = await handler(request, reply);
|
|
136
|
+
const result = await handler.call(this, request, reply);
|
|
131
137
|
if (isReadableStream(result)) {
|
|
132
138
|
await pipeUIMessageStreamToReply(reply, result);
|
|
133
139
|
return reply;
|
|
134
140
|
}
|
|
135
141
|
return result;
|
|
136
142
|
} : handler,
|
|
137
|
-
...buildRouteConfig(route.rateLimit !== void 0 ? buildRateLimitConfig(route.rateLimit) : rateLimitConfig, extensions)
|
|
143
|
+
...buildRouteConfig(route.rateLimit !== void 0 ? buildRateLimitConfig(route.rateLimit) : rateLimitConfig, extensions, route.cors)
|
|
138
144
|
}, {
|
|
139
145
|
resourceName,
|
|
140
146
|
op: opName
|
|
@@ -462,26 +468,6 @@ function buildBaseController(resolvedConfig, adapter, repository) {
|
|
|
462
468
|
//#endregion
|
|
463
469
|
//#region src/core/defineResource/hooks.ts
|
|
464
470
|
/**
|
|
465
|
-
* Phase 6 — wire preset hooks + inline `config.hooks` onto the
|
|
466
|
-
* resource's `_pendingHooks`.
|
|
467
|
-
*
|
|
468
|
-
* Two sources feed the same array:
|
|
469
|
-
* 1. Preset hooks collected during `applyPresets()` (raw `_hooks`
|
|
470
|
-
* on the internal config). Already in the canonical
|
|
471
|
-
* `{ operation, phase, handler, priority }` shape — copied
|
|
472
|
-
* verbatim (priority defaults to 10).
|
|
473
|
-
* 2. Inline `config.hooks.beforeCreate` / `afterCreate` / etc.
|
|
474
|
-
* Authored by the user on the original `ResourceConfig`.
|
|
475
|
-
* Wrapped in a `ResourceHookContext` projection (v2.10.8) so
|
|
476
|
-
* authors can read `scope` / `context` without reaching into
|
|
477
|
-
* internal request fields.
|
|
478
|
-
*
|
|
479
|
-
* The 6 inline hook keys (before/after × create/update/delete) used
|
|
480
|
-
* to be 6 nearly-identical blocks; collapsed into a table + loop so
|
|
481
|
-
* a future hook (e.g. `beforeRead`) is one row, not seven scattered
|
|
482
|
-
* edits.
|
|
483
|
-
*/
|
|
484
|
-
/**
|
|
485
471
|
* Combined entry-point for Phase 6. Pushes preset-collected hooks
|
|
486
472
|
* first, then inline `config.hooks` (so hosts can rely on
|
|
487
473
|
* registration order if priorities tie).
|
|
@@ -544,19 +530,17 @@ const INLINE_HOOK_SPECS = [
|
|
|
544
530
|
}
|
|
545
531
|
];
|
|
546
532
|
/**
|
|
547
|
-
* Project a raw HookSystem context into a `ResourceHookContext` for
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
* fields.
|
|
533
|
+
* Project a raw HookSystem context into a `ResourceHookContext` for inline
|
|
534
|
+
* `config.hooks.*` handlers. `scope` rides in already computed — `HookContext`
|
|
535
|
+
* carries the same projection — so the two surfaces cannot drift.
|
|
551
536
|
*/
|
|
552
537
|
function buildHookContext(ctx) {
|
|
553
538
|
const context = ctx.context;
|
|
554
|
-
const rawScope = context?._scope;
|
|
555
539
|
return {
|
|
556
540
|
data: ctx.data ?? ctx.result ?? {},
|
|
557
541
|
user: ctx.user,
|
|
558
542
|
context,
|
|
559
|
-
scope:
|
|
543
|
+
scope: ctx.scope,
|
|
560
544
|
meta: ctx.meta
|
|
561
545
|
};
|
|
562
546
|
}
|
|
@@ -662,8 +646,7 @@ function expandHistory(config) {
|
|
|
662
646
|
method: "GET",
|
|
663
647
|
path: "/:id/history",
|
|
664
648
|
summary: `Change history for a ${resourceName} record (audit-backed timeline)`,
|
|
665
|
-
|
|
666
|
-
handler: async (request, reply) => {
|
|
649
|
+
rawHandler: async (request, reply) => {
|
|
667
650
|
const audit = request.server.audit;
|
|
668
651
|
if (!audit?.query || audit._noop === true) return reply.code(503).send({
|
|
669
652
|
code: "history.audit_unavailable",
|
|
@@ -802,7 +785,7 @@ function stripFromRequired(schema, fieldName) {
|
|
|
802
785
|
}
|
|
803
786
|
/**
|
|
804
787
|
* Strip framework-injected fields from the `required[]` list of every
|
|
805
|
-
* body-shaped slot in an adapter's generated schemas
|
|
788
|
+
* body-shaped slot in an adapter's generated schemas.
|
|
806
789
|
*
|
|
807
790
|
* A "framework-injected field" is any field marked `systemManaged: true`
|
|
808
791
|
* in `schemaOptions.fieldRules`. Arc populates those fields from the
|
|
@@ -957,22 +940,32 @@ const WRITE_OPERATIONS = /* @__PURE__ */ new Set([
|
|
|
957
940
|
* wiring, ...) count as gates and don't false-positive.
|
|
958
941
|
*
|
|
959
942
|
* Severity ladder:
|
|
960
|
-
* - `
|
|
961
|
-
*
|
|
943
|
+
* - `error` when any enabled WRITE op is ungated AND `strict` is on — the
|
|
944
|
+
* resource fails boot (`defineResource()` throws). This is the fail-closed
|
|
945
|
+
* production invariant: an unauthenticated write must never ship silently.
|
|
946
|
+
* - `warn` (default) when any enabled WRITE op (create/update/delete) is
|
|
947
|
+
* ungated — real exposure the host must acknowledge, but non-fatal so
|
|
948
|
+
* existing hosts are not broken.
|
|
962
949
|
* - `info` when only reads are ungated — public catalogs
|
|
963
950
|
* (`referenceData: true`) are a legitimate shape, but the host should
|
|
964
951
|
* still state intent with `permissions.fullPublic()` / `allowPublic()`.
|
|
952
|
+
*
|
|
953
|
+
* `strict` is opt-in (resource `strictPermissions: true` or the
|
|
954
|
+
* `ARC_STRICT_PERMISSIONS` env), so the default behavior is unchanged.
|
|
965
955
|
*/
|
|
966
|
-
function collectUngatedCrudDiagnostics(config) {
|
|
956
|
+
function collectUngatedCrudDiagnostics(config, strict = false) {
|
|
967
957
|
if (config.disableDefaultRoutes) return [];
|
|
968
958
|
const disabled = new Set(config.disabledRoutes ?? []);
|
|
969
959
|
const permissions = config.permissions ?? {};
|
|
970
960
|
const ungated = CRUD_OPERATIONS.filter((op) => !disabled.has(op) && typeof permissions[op] !== "function");
|
|
971
961
|
if (ungated.length === 0) return [];
|
|
962
|
+
const severity = ungated.some((op) => WRITE_OPERATIONS.has(op)) ? strict ? "error" : "warn" : "info";
|
|
972
963
|
return [{
|
|
973
|
-
severity
|
|
964
|
+
severity,
|
|
974
965
|
code: "crud-public-by-omission",
|
|
975
|
-
message: `[Arc] Resource '${config.name}' mounts ${ungated.length} CRUD route(s) with no permission gate: ${ungated.join(", ")}.\
|
|
966
|
+
message: `[Arc] Resource '${config.name}' mounts ${ungated.length} CRUD route(s) with no permission gate: ${ungated.join(", ")}.\n` + (severity === "error" ? "strictPermissions is on and an ungated WRITE is fatal. State intent explicitly:\n" : "An omitted permission mounts the route WITHOUT auth. State intent explicitly:\n") + ` permissions: permissions.fullPublic() // intentionally public
|
|
967
|
+
permissions: permissions.authenticated() // require auth on every op
|
|
968
|
+
permissions: { ${ungated[0]}: requireAuth(), ... } // per-operation`
|
|
976
969
|
}];
|
|
977
970
|
}
|
|
978
971
|
//#endregion
|
|
@@ -1217,7 +1210,7 @@ function buildResourcePlugin(resource) {
|
|
|
1217
1210
|
const isFirstMount = !resource._sharedStateRegisteredOn.has(sharedRoot);
|
|
1218
1211
|
if (isFirstMount) resource._sharedStateRegisteredOn.add(sharedRoot);
|
|
1219
1212
|
if (isFirstMount && resource._diagnostics?.length) for (const diagnostic of resource._diagnostics) {
|
|
1220
|
-
const level = diagnostic.severity === "info" ? "info" : "warn";
|
|
1213
|
+
const level = diagnostic.severity === "info" ? "info" : diagnostic.severity === "error" ? "error" : "warn";
|
|
1221
1214
|
fastify.log?.[level]?.(diagnostic.message);
|
|
1222
1215
|
}
|
|
1223
1216
|
const arc = fastify.arc;
|
|
@@ -1278,7 +1271,7 @@ function buildResourcePlugin(resource) {
|
|
|
1278
1271
|
extensions: resource.extensions
|
|
1279
1272
|
});
|
|
1280
1273
|
if (resource.actions && Object.keys(resource.actions).length > 0) {
|
|
1281
|
-
const { createActionRouter } = await import("./createActionRouter-
|
|
1274
|
+
const { createActionRouter } = await import("./createActionRouter-CDXEdasl.mjs").then((n) => n.n);
|
|
1282
1275
|
createActionRouter(typedInstance, {
|
|
1283
1276
|
...normalizeActionsToRouterConfig(resource.actions, resource.actionPermissions, resource.tag, resource.permissions, resource.name, typedInstance.log),
|
|
1284
1277
|
resourceName: resource.name,
|
|
@@ -1293,7 +1286,7 @@ function buildResourcePlugin(resource) {
|
|
|
1293
1286
|
});
|
|
1294
1287
|
}
|
|
1295
1288
|
if (resource.aggregations && Object.keys(resource.aggregations).length > 0) {
|
|
1296
|
-
const [{ createAggregationRouter }, { adapterSupportsAggregate, ArcAggregationConfigError }] = await Promise.all([import("./createAggregationRouter-
|
|
1289
|
+
const [{ createAggregationRouter }, { adapterSupportsAggregate, ArcAggregationConfigError }] = await Promise.all([import("./createAggregationRouter-KrQDzx-k.mjs"), import("./validate-_KbifpHF.mjs").then((n) => n.r)]);
|
|
1297
1290
|
const repoForAgg = resource.controller?.repository ?? resource.repository;
|
|
1298
1291
|
if (!adapterSupportsAggregate(repoForAgg)) {
|
|
1299
1292
|
const undispatchable = Object.entries(resource.aggregations).filter(([, cfg]) => !cfg.materialized).map(([name]) => name);
|
|
@@ -1549,7 +1542,7 @@ var ResourceDefinition = class {
|
|
|
1549
1542
|
summary: r.summary,
|
|
1550
1543
|
description: r.description,
|
|
1551
1544
|
permissions: r.permissions,
|
|
1552
|
-
raw: r.
|
|
1545
|
+
raw: r.rawHandler !== void 0,
|
|
1553
1546
|
schema: r.schema
|
|
1554
1547
|
})),
|
|
1555
1548
|
routes: [],
|
|
@@ -1827,17 +1820,22 @@ function validateResourceConfig(config, options = {}) {
|
|
|
1827
1820
|
}
|
|
1828
1821
|
function validateRouteHandlers(controller, routes, errors) {
|
|
1829
1822
|
const ctrl = controller;
|
|
1830
|
-
for (const route of routes)
|
|
1831
|
-
|
|
1823
|
+
for (const route of routes) {
|
|
1824
|
+
const named = typeof route.handler === "string" ? route.handler : route.rawHandler;
|
|
1825
|
+
if (typeof named !== "string") continue;
|
|
1826
|
+
if (typeof ctrl[named] !== "function") errors.push({
|
|
1832
1827
|
field: `routes[${route.method} ${route.path}]`,
|
|
1833
|
-
message: `Handler "${
|
|
1834
|
-
suggestion: `Add method "${
|
|
1828
|
+
message: `Handler "${named}" not found on controller`,
|
|
1829
|
+
suggestion: `Add method "${named}" to controller or use a function handler`
|
|
1835
1830
|
});
|
|
1836
1831
|
}
|
|
1837
1832
|
}
|
|
1838
1833
|
function validatePermissionKeys(config, options, _errors, warnings) {
|
|
1839
1834
|
const validKeys = /* @__PURE__ */ new Set([...CRUD_OPERATIONS, ...options.additionalPermissionKeys ?? []]);
|
|
1840
|
-
for (const route of config.routes ?? [])
|
|
1835
|
+
for (const route of config.routes ?? []) {
|
|
1836
|
+
if (typeof route.handler === "string") validKeys.add(route.handler);
|
|
1837
|
+
if (typeof route.rawHandler === "string") validKeys.add(route.rawHandler);
|
|
1838
|
+
}
|
|
1841
1839
|
for (const preset of config.presets ?? []) {
|
|
1842
1840
|
const presetName = typeof preset === "string" ? preset : preset.name;
|
|
1843
1841
|
if (presetName === "softDelete") {
|
|
@@ -1978,11 +1976,26 @@ function validateRoutes(routes, errors) {
|
|
|
1978
1976
|
suggestion: `Change to "/${route.path}"`
|
|
1979
1977
|
});
|
|
1980
1978
|
const routeWithRefs = route;
|
|
1981
|
-
if (!route.handler && typeof routeWithRefs.controllerMethod !== "function") errors.push({
|
|
1979
|
+
if (!route.handler && !route.rawHandler && typeof routeWithRefs.controllerMethod !== "function") errors.push({
|
|
1982
1980
|
field: `routes[${i}].handler`,
|
|
1983
|
-
message: "Route must declare
|
|
1981
|
+
message: "Route must declare one of `handler` (arc pipeline), `rawHandler` (Fastify-native), or `controllerMethod`",
|
|
1984
1982
|
suggestion: "Prefer `controllerMethod: (c: MyController) => c.method` for typed handler refs."
|
|
1985
1983
|
});
|
|
1984
|
+
if (route.handler && route.rawHandler) errors.push({
|
|
1985
|
+
field: `routes[${i}].rawHandler`,
|
|
1986
|
+
message: "Route declares BOTH `handler` and `rawHandler`",
|
|
1987
|
+
suggestion: "Use `handler` for the arc pipeline (receives IRequestContext) or `rawHandler` for a Fastify-native handler (receives request, reply) — not both."
|
|
1988
|
+
});
|
|
1989
|
+
if ("raw" in route) errors.push({
|
|
1990
|
+
field: `routes[${i}].raw`,
|
|
1991
|
+
message: "`raw` was removed in arc 2.31 — the field now carries the intent",
|
|
1992
|
+
suggestion: "Move the function to `rawHandler` (Fastify-native) or leave it in `handler` (arc pipeline), and delete the flag. If the route comes from a dependency, that package needs a release built against arc >=2.31."
|
|
1993
|
+
});
|
|
1994
|
+
if (route.streamResponse === true && route.rawHandler === void 0) errors.push({
|
|
1995
|
+
field: `routes[${i}].streamResponse`,
|
|
1996
|
+
message: "`streamResponse: true` requires `rawHandler`",
|
|
1997
|
+
suggestion: "Streaming routes are invoked with `(request, reply)` and own the socket — declare the function as `rawHandler` (not `handler` or `controllerMethod`)."
|
|
1998
|
+
});
|
|
1986
1999
|
const routeKey = `${route.method} ${route.path}`;
|
|
1987
2000
|
if (seenRoutes.has(routeKey)) errors.push({
|
|
1988
2001
|
field: `routes[${i}]`,
|
|
@@ -2169,7 +2182,12 @@ function defineResource(config) {
|
|
|
2169
2182
|
const configWithId = resolveIdField(normalisedConfig, repository);
|
|
2170
2183
|
const resolvedConfig = applyPresetsAndAutoInject(configWithId);
|
|
2171
2184
|
const hasCrudRoutes = computeHasCrudRoutes(resolvedConfig);
|
|
2172
|
-
if (!normalisedConfig.skipValidation)
|
|
2185
|
+
if (!normalisedConfig.skipValidation) {
|
|
2186
|
+
const strict = resolvedConfig.strictPermissions ?? process.env.ARC_STRICT_PERMISSIONS === "true";
|
|
2187
|
+
diagnostics = diagnostics.concat(collectUngatedCrudDiagnostics(resolvedConfig, strict));
|
|
2188
|
+
}
|
|
2189
|
+
const fatal = diagnostics.filter((d) => d.severity === "error");
|
|
2190
|
+
if (fatal.length > 0) throw new Error(fatal.map((d) => d.message).join("\n\n"));
|
|
2173
2191
|
const narrowedConfig = resolvedConfig;
|
|
2174
2192
|
const narrowedAdapter = configWithId.adapter;
|
|
2175
2193
|
const controller = resolveOrAutoCreateController(narrowedConfig, narrowedAdapter, repository, hasCrudRoutes);
|
package/dist/discovery/index.mjs
CHANGED
package/dist/docs/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
1
|
+
|
|
2
|
+
import { p as RegistryEntry } from "../index-CpzxqePp.mjs";
|
|
3
|
+
import { t as ExternalOpenApiPaths } from "../externalPaths-CmGOxOtD.mjs";
|
|
3
4
|
import { FastifyPluginAsync } from "fastify";
|
|
4
5
|
//#region src/docs/openapi/types.d.ts
|
|
5
6
|
/**
|
package/dist/docs/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import { n as
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { n as getUserRoles } from "../userHelpers-ChYJ6CdK.mjs";
|
|
3
|
+
import { n as openApiPlugin, r as openapi_default, t as buildOpenApiSpec } from "../openapi-B2L4js1v.mjs";
|
|
3
4
|
import fp from "fastify-plugin";
|
|
4
5
|
//#region src/docs/scalar.ts
|
|
5
6
|
const scalarPlugin = async (fastify, opts = {}) => {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-CUsjNX9R.mjs";
|
|
2
3
|
import { arcLog } from "./logger/index.mjs";
|
|
3
|
-
import { n as requireSingleHeaderValue } from "./headers-
|
|
4
|
-
import { n as getUserRoles } from "./userHelpers-
|
|
4
|
+
import { n as requireSingleHeaderValue } from "./headers-3zvE0rM3.mjs";
|
|
5
|
+
import { n as getUserRoles } from "./userHelpers-ChYJ6CdK.mjs";
|
|
5
6
|
import fp from "fastify-plugin";
|
|
6
7
|
//#region src/scope/elevation.ts
|
|
7
8
|
var elevation_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
import { a as JweAlg, c as KeyMaterial, i as EncryptionOptions, l as KeyProvider, n as EncryptionDirective, o as JweEnc, r as EncryptionMode, s as KeyContext, t as ActiveKey } from "../types-ByHn9rEO.mjs";
|
|
2
3
|
import { FastifyPluginAsync } from "fastify";
|
|
3
4
|
//#region src/encryption/encryptionPlugin.d.ts
|
|
4
5
|
declare const encryptionPlugin: FastifyPluginAsync<EncryptionOptions>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import { t as
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as ArcError } from "../errors-Cj42AntO.mjs";
|
|
3
|
+
import { t as parseJsonBody } from "../jsonBody-BYbLDi5D.mjs";
|
|
3
4
|
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
4
5
|
import fp from "fastify-plugin";
|
|
5
6
|
//#region src/encryption/fieldCipher.ts
|
|
@@ -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 { m as statusToArcCode, p as isArcError } from "./errors-Cj42AntO.mjs";
|
|
3
4
|
import { isHttpError, toErrorContract } from "@classytic/repo-core/errors";
|
|
4
5
|
import fp from "fastify-plugin";
|
|
5
6
|
//#region src/plugins/errorHandler.ts
|
|
@@ -1,110 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-CUsjNX9R.mjs";
|
|
2
3
|
import { arcLog } from "./logger/index.mjs";
|
|
3
|
-
import { d as createDomainError } from "./errors-
|
|
4
|
-
import { n as requestContext } from "./requestContext-
|
|
4
|
+
import { d as createDomainError } from "./errors-Cj42AntO.mjs";
|
|
5
|
+
import { n as requestContext } from "./requestContext-2TxXOJ7T.mjs";
|
|
6
|
+
import { n as createEvent, t as MemoryEventTransport } from "./EventTransport-9mlTgqzE.mjs";
|
|
5
7
|
import fp from "fastify-plugin";
|
|
6
|
-
import { createEvent, matchEventPattern } from "@classytic/primitives/events";
|
|
7
|
-
//#region src/events/EventTransport.ts
|
|
8
|
-
/**
|
|
9
|
-
* Internal arc events module — concrete in-memory transport.
|
|
10
|
-
*
|
|
11
|
-
* **Public type contracts moved out (arc 2.12).** `EventMeta`, `DomainEvent`,
|
|
12
|
-
* `EventHandler`, `EventLogger`, `EventTransport`, `DeadLetteredEvent`,
|
|
13
|
-
* `PublishManyResult`, plus the `createEvent` / `createChildEvent` /
|
|
14
|
-
* `matchEventPattern` helpers, are now owned by `@classytic/primitives/events`.
|
|
15
|
-
* Two reasons:
|
|
16
|
-
*
|
|
17
|
-
* 1. The shapes ARE the cross-package contract. arc, arc-next, mongokit's
|
|
18
|
-
* audit-log plugin, future kits and downstream services all share them.
|
|
19
|
-
* Owning them in `primitives` (pure types, zero runtime, zero deps)
|
|
20
|
-
* eliminates the "manually mirror in two places" problem the previous
|
|
21
|
-
* `primitives/src/events.ts` header explicitly called out.
|
|
22
|
-
* 2. Inverting the dependency direction lets future packages (sqlitekit
|
|
23
|
-
* audit, billing services) consume the contract without depending on
|
|
24
|
-
* arc's HTTP-coupled stack.
|
|
25
|
-
*
|
|
26
|
-
* Hosts MUST import the types from primitives directly:
|
|
27
|
-
*
|
|
28
|
-
* ```typescript
|
|
29
|
-
* import type {
|
|
30
|
-
* EventMeta, DomainEvent, EventHandler, EventTransport,
|
|
31
|
-
* DeadLetteredEvent, PublishManyResult,
|
|
32
|
-
* } from '@classytic/primitives/events';
|
|
33
|
-
* import { createEvent, createChildEvent } from '@classytic/primitives/events';
|
|
34
|
-
* ```
|
|
35
|
-
*
|
|
36
|
-
* arc's `events/index.ts` barrel does NOT re-export these — by design, so
|
|
37
|
-
* that consumer code is forced into the canonical import path and the org's
|
|
38
|
-
* "no re-exports" rule holds at every public surface.
|
|
39
|
-
*
|
|
40
|
-
* What stays here:
|
|
41
|
-
* - `MemoryEventTransport` — the in-memory `EventTransport` implementation
|
|
42
|
-
* used as arc's default transport. Its handler-set state is process-local;
|
|
43
|
-
* wrong layer for primitives.
|
|
44
|
-
* - `MemoryEventTransportOptions` — its options shape.
|
|
45
|
-
*
|
|
46
|
-
* Inside arc, files that previously imported types from `./EventTransport.js`
|
|
47
|
-
* keep working: this file re-exports them from primitives for arc's own
|
|
48
|
-
* call sites. That re-export is an internal refactor convenience — the
|
|
49
|
-
* public `events/index.ts` barrel stays clean.
|
|
50
|
-
*/
|
|
51
|
-
/**
|
|
52
|
-
* In-memory event transport (default).
|
|
53
|
-
*
|
|
54
|
-
* Events are delivered synchronously within the process. Not suitable for
|
|
55
|
-
* multi-instance deployments — pair with `RedisEventTransport` /
|
|
56
|
-
* `RedisStreamTransport` (subpath imports) for those.
|
|
57
|
-
*/
|
|
58
|
-
var MemoryEventTransport = class {
|
|
59
|
-
name = "memory";
|
|
60
|
-
handlers = /* @__PURE__ */ new Map();
|
|
61
|
-
logger;
|
|
62
|
-
constructor(options) {
|
|
63
|
-
this.logger = options?.logger ?? console;
|
|
64
|
-
}
|
|
65
|
-
async publish(event) {
|
|
66
|
-
const allHandlers = /* @__PURE__ */ new Set();
|
|
67
|
-
for (const [pattern, handlers] of this.handlers) if (matchEventPattern(pattern, event.type)) for (const h of handlers) allHandlers.add(h);
|
|
68
|
-
for (const handler of allHandlers) try {
|
|
69
|
-
await handler(event);
|
|
70
|
-
} catch (err) {
|
|
71
|
-
this.logger.error(`[EventTransport] Handler error for ${event.type}:`, err);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Reference `publishMany` implementation — delegates to `publish()` in order.
|
|
76
|
-
*
|
|
77
|
-
* Production transports (Kafka, Redis pipeline, SQS batch) should override
|
|
78
|
-
* this with a single batched network call. Memory transport has nothing to
|
|
79
|
-
* batch, so we just loop — the loop still returns a proper result map so
|
|
80
|
-
* `EventOutbox.relay` can exercise the batched code path in tests.
|
|
81
|
-
*/
|
|
82
|
-
async publishMany(events) {
|
|
83
|
-
const results = /* @__PURE__ */ new Map();
|
|
84
|
-
for (const event of events) try {
|
|
85
|
-
await this.publish(event);
|
|
86
|
-
results.set(event.meta.id, null);
|
|
87
|
-
} catch (err) {
|
|
88
|
-
results.set(event.meta.id, err instanceof Error ? err : new Error(String(err)));
|
|
89
|
-
}
|
|
90
|
-
return results;
|
|
91
|
-
}
|
|
92
|
-
async subscribe(pattern, handler) {
|
|
93
|
-
if (!this.handlers.has(pattern)) this.handlers.set(pattern, /* @__PURE__ */ new Set());
|
|
94
|
-
this.handlers.get(pattern)?.add(handler);
|
|
95
|
-
return () => {
|
|
96
|
-
const set = this.handlers.get(pattern);
|
|
97
|
-
if (set) {
|
|
98
|
-
set.delete(handler);
|
|
99
|
-
if (set.size === 0) this.handlers.delete(pattern);
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
async close() {
|
|
104
|
-
this.handlers.clear();
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
//#endregion
|
|
108
8
|
//#region src/events/retry.ts
|
|
109
9
|
/**
|
|
110
10
|
* Wrap an event handler with retry logic and dead letter support.
|
|
@@ -338,4 +238,4 @@ var eventPlugin_default = fp(eventPlugin, {
|
|
|
338
238
|
fastify: "5.x"
|
|
339
239
|
});
|
|
340
240
|
//#endregion
|
|
341
|
-
export {
|
|
241
|
+
export { withRetry as i, eventPlugin_exports as n, createDeadLetterPublisher as r, eventPlugin as t };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "./EventTransport-2uVV34WU.mjs";
|
|
2
3
|
import { FastifyPluginAsync } from "fastify";
|
|
3
4
|
//#region src/events/defineEvent.d.ts
|
|
4
5
|
interface EventSchema {
|
package/dist/events/index.d.mts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import { a as
|
|
1
|
+
|
|
2
|
+
import { a as EventTransport, i as EventLogger, n as DomainEvent, o as MemoryEventTransport, r as EventHandler, s as MemoryEventTransportOptions, t as DeadLetteredEvent } from "../EventTransport-2uVV34WU.mjs";
|
|
3
|
+
import { a as withRetry, c as EventDefinitionOutput, d as EventSchema, f as ValidationResult, i as createDeadLetterPublisher, l as EventRegistry, m as defineEvent, n as eventPlugin, o as CustomValidator, p as createEventRegistry, r as RetryOptions, s as EventDefinitionInput, t as EventPluginOptions, u as EventRegistryOptions } from "../eventPlugin-GF5nnBIq.mjs";
|
|
3
4
|
import { RedisEventTransportOptions, RedisLike } from "./transports/redis.mjs";
|
|
4
|
-
import { r as RedisStreamTransportOptions, t as RedisStreamLike } from "../redis-stream-
|
|
5
|
+
import { r as RedisStreamTransportOptions, t as RedisStreamLike } from "../redis-stream-qN6A-RFv.mjs";
|
|
5
6
|
import { OutboxAcknowledgeOptions, OutboxClaimOptions, OutboxErrorInfo, OutboxFailOptions, OutboxFailurePolicy, OutboxStore, OutboxWriteOptions } from "@classytic/primitives/outbox";
|
|
6
7
|
import { RepositoryLike } from "@classytic/repo-core/adapter";
|
|
7
8
|
//#region src/events/eventTypes.d.ts
|