@classytic/arc 2.41.1 → 2.44.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/dist/{EventTransport-CbUKDzZZ.d.mts → EventTransport-CiicKz2Z.d.mts} +1 -1
- package/dist/{EventTransport-DSqD_Xsg.mjs → EventTransport-DZWDsaPa.mjs} +22 -17
- package/dist/{HookSystem-CMF94SEA.mjs → HookSystem-yjEgn7Cm.mjs} +2 -2
- package/dist/{QueryCache-DFA-QrU9.d.mts → QueryCache--5uAuYPW.d.mts} +7 -3
- package/dist/{ResourceRegistry-MGpXoxHZ.mjs → ResourceRegistry-DJxHUpE4.mjs} +44 -13
- package/dist/acquire-BozJ-9yt.mjs +35 -0
- package/dist/actionPermissions-5N04zBL4.mjs +772 -0
- package/dist/audit/index.d.mts +46 -8
- package/dist/audit/index.mjs +48 -26
- package/dist/auth/audit.d.mts +8 -8
- package/dist/auth/audit.mjs +1 -1
- package/dist/auth/index.d.mts +46 -16
- package/dist/auth/index.mjs +134 -156
- package/dist/auth/redis-session.d.mts +4 -5
- package/dist/auth/redis-session.mjs +1 -1
- package/dist/{authorizationDecision-DawKGoXb.mjs → authorizationDecision-wX3SA9w_.mjs} +7 -102
- package/dist/{base-CxrV1LmG.d.mts → base-CZyixEQR.d.mts} +27 -5
- package/dist/boundedMap-DWiKW7lP.mjs +57 -0
- package/dist/{buildHandler-CvxKOc0m.mjs → buildHandler-Bswu_vNb.mjs} +4 -4
- package/dist/cache/index.d.mts +31 -43
- package/dist/cache/index.mjs +4 -4
- package/dist/{caching-DbCBxlgw.mjs → caching-Drp68DIS.mjs} +3 -3
- package/dist/claimed-DYvQoZLv.mjs +8 -0
- package/dist/cleanup/index.d.mts +18 -22
- package/dist/cleanup/index.mjs +27 -73
- package/dist/cli/commands/describe.d.mts +7 -5
- package/dist/cli/commands/describe.mjs +7 -4
- package/dist/cli/commands/docs.d.mts +2 -3
- package/dist/cli/commands/docs.mjs +3 -3
- package/dist/cli/commands/doctor.d.mts +2 -3
- package/dist/cli/commands/doctor.mjs +1 -1
- package/dist/cli/commands/generate.mjs +2 -3
- package/dist/cli/commands/init.mjs +2 -3
- package/dist/cli/commands/introspect.d.mts +2 -3
- package/dist/cli/commands/introspect.mjs +2 -2
- package/dist/cli/index.mjs +3 -3
- package/dist/{constants-D5Ubn1fe.mjs → constants-B2QHb6u6.mjs} +4 -2
- package/dist/context/index.d.mts +11 -14
- package/dist/context/index.mjs +18 -38
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +8 -8
- package/dist/{core-5lazhva9.mjs → core-COcqo0Cp.mjs} +15 -5
- package/dist/{createActionRouter-DNqoaK81.mjs → createActionRouter-zG13rpPJ.mjs} +97 -39
- package/dist/{createAggregationRouter-BcbQJf10.mjs → createAggregationRouter-CWRz96Vr.mjs} +11 -8
- package/dist/{preloadResources-f3boenVZ.mjs → createApp-BGLYtErt.mjs} +305 -394
- package/dist/{createMcpServer-CbDWkZ1T.d.mts → createMcpServer-DSztofa9.d.mts} +1 -1
- package/dist/{defineAggregation-D_eJjm5A.mjs → defineAggregation--3xguLkk.mjs} +1 -1
- package/dist/{defineResource-DxkMTjRn.mjs → defineResource-gUp9ug66.mjs} +118 -1024
- package/dist/discovery/index.d.mts +6 -7
- package/dist/discovery/index.mjs +1 -1
- package/dist/docs/index.d.mts +11 -5
- package/dist/docs/index.mjs +4 -4
- package/dist/{elevation-CkvG0LG2.mjs → elevation-BG4gnMsJ.mjs} +41 -12
- package/dist/{elevation-BXCfVcNG.d.mts → elevation-BW2J3tNj.d.mts} +1 -2
- package/dist/encryption/index.d.mts +5 -5
- package/dist/encryption/index.mjs +3 -3
- package/dist/{errorHandler-D1GHKGlV.mjs → errorHandler-COHw3N1b.mjs} +26 -5
- package/dist/{errors-BH7YU_9O.mjs → errors-CW4anJBy.mjs} +58 -23
- package/dist/{errors-BGdVwP25.d.mts → errors-JYc9vwqE.d.mts} +9 -0
- package/dist/{eventPlugin-B52abJ8W.d.mts → eventPlugin-BtmA4-3P.d.mts} +65 -9
- package/dist/{eventPlugin-zZY-unhr.mjs → eventPlugin-BweHAVws.mjs} +82 -21
- package/dist/{subscribe-helpers-DatDkcuG.mjs → eventTypes-N4-omQFR.mjs} +151 -17
- package/dist/events/index.d.mts +43 -18
- package/dist/events/index.mjs +49 -53
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis-stream-entry.mjs +139 -157
- package/dist/events/transports/redis.d.mts +5 -6
- package/dist/events/transports/redis.mjs +2 -2
- package/dist/factory/index.d.mts +42 -27
- package/dist/factory/index.mjs +213 -32
- package/dist/{fastify-augmentation-Cq2nHVaW.d.mts → fastify-augmentation-DRlCIWE9.d.mts} +11 -25
- package/dist/{fields-BHrkoF5y.mjs → fields-A5crhsJb.mjs} +1 -1
- package/dist/{fields-I_EeRWND.d.mts → fields-BBSpf8pS.d.mts} +1 -1
- package/dist/filter-merge-DGM-GQ1J.mjs +99 -0
- package/dist/{generate-BLRf2m3y.mjs → generate-BXKo2Gc8.mjs} +2 -2
- package/dist/{headers-BIXWKrzQ.mjs → headers-DKZQKL-Z.mjs} +2 -2
- package/dist/health-BYAwA6YS.mjs +22 -0
- package/dist/{health-ZRHeDHXH.mjs → health-CrqUp3sz.mjs} +115 -55
- package/dist/hooks/index.d.mts +2 -2
- package/dist/hooks/index.mjs +2 -3
- package/dist/idempotency/index.d.mts +36 -10
- package/dist/idempotency/index.mjs +230 -111
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/idempotency/redis.mjs +77 -12
- package/dist/{index-D4u76eQW.d.mts → index-Beg3aNnK.d.mts} +23 -101
- package/dist/{preloadResources-CjS2OfpU.d.mts → index-BkV55WlV.d.mts} +37 -38
- package/dist/{index-BHdZD8zK.d.mts → index-Bxriq3so.d.mts} +84 -21
- package/dist/index-CUJvoyw3.d.mts +510 -0
- package/dist/{index-CbJiYrfv.d.mts → index-Chgz3d0i.d.mts} +1 -1
- package/dist/{index-DHbyPo5j.d.mts → index-WH7xgvxS.d.mts} +304 -254
- package/dist/index.d.mts +9 -9
- package/dist/index.mjs +11 -11
- package/dist/{init-CpLkjU18.mjs → init-BPzK5Lnr.mjs} +1 -1
- package/dist/integrations/event-gateway.d.mts +11 -7
- package/dist/integrations/event-gateway.mjs +4 -4
- package/dist/integrations/index.d.mts +3 -3
- package/dist/integrations/index.mjs +1 -1
- package/dist/integrations/jobs/index.d.mts +1 -1
- package/dist/integrations/jobs/index.mjs +18 -5
- package/dist/integrations/mcp/index.d.mts +102 -89
- package/dist/integrations/mcp/index.mjs +19 -4
- package/dist/integrations/mcp/testing.d.mts +8 -9
- package/dist/integrations/mcp/testing.mjs +2 -2
- package/dist/integrations/streamline.d.mts +85 -144
- package/dist/integrations/streamline.mjs +131 -55
- package/dist/integrations/webhooks.d.mts +83 -143
- package/dist/integrations/webhooks.mjs +36 -80
- package/dist/integrations/websocket-pushref-redis.d.mts +5 -6
- package/dist/integrations/websocket-pushref-redis.mjs +1 -1
- package/dist/integrations/websocket-redis.d.mts +5 -6
- package/dist/integrations/websocket-redis.mjs +1 -1
- package/dist/integrations/websocket.d.mts +3 -3
- package/dist/integrations/websocket.mjs +2 -2
- package/dist/{interface-DEWNOMza.d.mts → interface-JJzwH4Ro.d.mts} +34 -2
- package/dist/{jsonBody-ELR9lfeU.mjs → jsonBody-YIq-vGLv.mjs} +2 -2
- package/dist/{keys-cpZCtcIE.mjs → keys-CpoiZ8hU.mjs} +7 -18
- package/dist/{loadResources-BPfWiI5s.mjs → loadResources-6jO52-RR.mjs} +3 -3
- package/dist/{loadResourcesFromEntry-ixtfL3J2.mjs → loadResourcesFromEntry-MP8xEppu.mjs} +2 -2
- package/dist/logger/index.d.mts +9 -17
- package/dist/logger/index.mjs +2 -153
- package/dist/logger-D4V1zGLI.mjs +160 -0
- package/dist/{mcpPlugin-BX5PujI0.mjs → mcpPlugin-srPc7ItN.mjs} +446 -170
- package/dist/{memory-Iotz0cCx.mjs → memory-CTa5pOCW.mjs} +36 -34
- package/dist/{metrics-NMsmpRmY.mjs → metrics-DsZrvnpB.mjs} +39 -72
- package/dist/middleware/index.d.mts +5 -5
- package/dist/middleware/index.mjs +3 -3
- package/dist/migrations/index.d.mts +13 -13
- package/dist/migrations/index.mjs +2 -2
- package/dist/{module-DpLJG2_N.mjs → module--L0iBIZz.mjs} +8 -8
- package/dist/mongodb-memory-server-CHhYSq5y.mjs +35539 -0
- package/dist/mongoose-CYJCLyi-.mjs +67451 -0
- package/dist/multiTenant-CAtYlW6H.d.mts +104 -0
- package/dist/{multipartBody-DtRWM6_U.mjs → multipartBody-Cc7eZ9cq.mjs} +46 -7
- package/dist/node-D8UZv_8c.mjs +41236 -0
- package/dist/{openapi-CmFf3yq_.mjs → openapi-CMegfsm8.mjs} +48 -10
- package/dist/outbox-admin/index.d.mts +5 -5
- package/dist/outbox-admin/index.mjs +6 -18
- package/dist/{outbox-module-D2z5WkDY.mjs → outbox-module-Ryk270jd.mjs} +203 -33
- package/dist/{outbox-module-BHdUnuuK.d.mts → outbox-module-gZCHoE4H.d.mts} +79 -6
- package/dist/permissions/index.d.mts +5 -4
- package/dist/permissions/index.mjs +8 -6
- package/dist/{permissions-D8TBH44E.mjs → permissions-C5ijIz5Q.mjs} +149 -33
- package/dist/{pipe-FMWNheSO.mjs → pipe-D81zMtWs.mjs} +2 -2
- package/dist/pipeline/index.d.mts +7 -7
- package/dist/pipeline/index.mjs +2 -2
- package/dist/plan-CJGMKoui.mjs +565 -0
- package/dist/{BaseController-CYEwjyjN.mjs → plugin-DALd9dcF.mjs} +1269 -346
- package/dist/plugins/index.d.mts +17 -14
- package/dist/plugins/index.mjs +44 -22
- package/dist/plugins/response-cache.d.mts +5 -6
- package/dist/plugins/response-cache.mjs +8 -14
- package/dist/plugins/tracing-entry.mjs +2 -2
- package/dist/{pluralize-CXWZIzTv.mjs → pluralize-COUNYo3d.mjs} +1 -1
- package/dist/presets/filesUpload.d.mts +8 -8
- package/dist/presets/filesUpload.mjs +5 -5
- package/dist/presets/index.d.mts +35 -40
- package/dist/presets/index.mjs +4 -4
- package/dist/presets/multiTenant.d.mts +2 -107
- package/dist/presets/multiTenant.mjs +22 -162
- package/dist/presets/search.d.mts +9 -10
- package/dist/presets/search.mjs +2 -2
- package/dist/{presets-ZJSPgmT2.mjs → presets-CONf2Qem.mjs} +99 -107
- package/dist/{projection-BzIgzoKZ.mjs → projection-wFoLqdss.mjs} +2 -2
- package/dist/{pushref-registry-Dov9l4qE.d.mts → pushref-registry-UxCkoA4C.d.mts} +1 -1
- package/dist/{queryCachePlugin-DZHPOm9p.mjs → queryCachePlugin-BATECpyh.mjs} +12 -14
- package/dist/{queryCachePlugin-BzqxconG.d.mts → queryCachePlugin-C2lZjTxk.d.mts} +1 -1
- package/dist/{rateLimitKey-BvOvcBDi.mjs → rateLimitKey-DVEZ_UpV.mjs} +1 -1
- package/dist/{realtime-8tIQWZz4.mjs → realtime-xyubMKSB.mjs} +25 -21
- package/dist/{redis-Bzi1y3F9.d.mts → redis-BDgv9Glw.d.mts} +17 -24
- package/dist/redis-stream-BMk-bpQS.d.mts +219 -0
- package/dist/redisShapes-CQksY67q.d.mts +55 -0
- package/dist/registry/index.d.mts +15 -10
- package/dist/registry/index.mjs +4 -4
- package/dist/{registry-DNkgGQcK.mjs → registry-Bdzg-hdm.mjs} +13 -10
- package/dist/{renewingLease-yF8BdW4b.mjs → renewingLease-BFJxGPuh.mjs} +1 -1
- package/dist/{replyHelpers-CNdvMfM4.mjs → replyHelpers-Bnc6lJyy.mjs} +2 -2
- package/dist/{requestContext-cDkAUr-P.mjs → requestContext-C10UeFe5.mjs} +1 -1
- package/dist/requirement-Bu50QALH.mjs +35 -0
- package/dist/requirement-CbiLdQ1n.d.mts +22 -0
- package/dist/resourceRateLimit-Wf6d6FL9.d.mts +30 -0
- package/dist/resourceRateLimit-urWPJxrt.mjs +180 -0
- package/dist/rolldown-runtime-MYrLNGnq.mjs +45 -0
- package/dist/routeValidator-DHtpzrzk.mjs +70 -0
- package/dist/{runtimeCapabilities-CkhS6jn6.mjs → runtimeCapabilities-DIMKMV2G.mjs} +1 -1
- package/dist/{schedules-j6uXXAeJ.mjs → schedules-CKTs5ys8.mjs} +46 -37
- package/dist/{schemaConverter-BVA7cFRG.mjs → schemaConverter-BVjkQ5DD.mjs} +2 -2
- package/dist/{schemaIR-CTvPDoPB.mjs → schemaIR-BA0Hb21Y.mjs} +2 -2
- package/dist/schemas/index.d.mts +20 -10
- package/dist/schemas/index.mjs +8 -3
- package/dist/scim/index.d.mts +13 -13
- package/dist/scim/index.mjs +2 -2
- package/dist/scope/index.d.mts +4 -4
- package/dist/scope/index.mjs +6 -6
- package/dist/{scope-BUi1xV1I.mjs → scope-DINaj7Ax.mjs} +4 -4
- package/dist/shutdown-LpLMH8T1.mjs +59 -0
- package/dist/{simpleEqualityMatcher-C9bzq2gO.mjs → simpleEqualityMatcher-DbwIM1f1.mjs} +1 -1
- package/dist/{sse-BeqVKQKu.mjs → sse-BzJFPX_1.mjs} +11 -15
- package/dist/{sseStream-Ppzo-WUH.mjs → sseStream-DQChzGTs.mjs} +2 -2
- package/dist/{store-helpers-dW71XVWL.mjs → store-helpers-Coj9RhOZ.mjs} +1 -1
- package/dist/{streaming-IcRFjWQU.mjs → streaming-JzB5CAga.mjs} +1 -1
- package/dist/subscriberIdentity-DeyppIif.mjs +28 -0
- package/dist/tenancy-DxV8OuX2.mjs +43 -0
- package/dist/tenantPreparation-CBvvAcAj.mjs +67 -0
- package/dist/testing/cleanupStoreContract.d.mts +4 -5
- package/dist/testing/cleanupStoreContract.mjs +1 -1
- package/dist/testing/index.d.mts +215 -197
- package/dist/testing/index.mjs +289 -214
- package/dist/testing/outboxStoreContract.d.mts +4 -5
- package/dist/testing/outboxStoreContract.mjs +137 -2
- package/dist/testing/requiredPorts.d.mts +16 -0
- package/dist/testing/requiredPorts.mjs +65 -0
- package/dist/testing/storageContract.d.mts +4 -5
- package/dist/testing/storageContract.mjs +1 -1
- package/dist/timing-CntavTlR.mjs +46 -0
- package/dist/{transactionContext-CPbdlnVw.mjs → transactionContext-orvnGu4F.mjs} +1 -1
- package/dist/{typeGuards-BLjPgVBm.mjs → typeGuards-kEaP_WmO.mjs} +1 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/types/index.mjs +1 -1
- package/dist/types/storage.mjs +1 -1
- package/dist/{types-DfVDvkdP.d.mts → types-BJ-2XqVF.d.mts} +189 -204
- package/dist/{types-CWQn9-IC.d.mts → types-D3Ixsh00.d.mts} +22 -9
- package/dist/{types-CgenB1gv.mjs → types-fvO6Ovzx.mjs} +4 -4
- package/dist/usage/index.d.mts +5 -6
- package/dist/usage/index.mjs +5 -5
- package/dist/{userHelpers-ChRvkuSZ.mjs → userHelpers-C76zD5pa.mjs} +1 -1
- package/dist/utils/index.d.mts +125 -264
- package/dist/utils/index.mjs +13 -12
- package/dist/{utils-CxcctrAh.mjs → utils-BpkVZ8rB.mjs} +315 -404
- package/dist/{validate-DrYWnOzI.mjs → validate-CWp-lsrm.mjs} +6 -14
- package/dist/{versioning-D6JIK8Tk.d.mts → versioning-Bsb51gGT.d.mts} +28 -13
- package/dist/{versioning-DKkT4hNJ.mjs → versioning-CHhL9P3o.mjs} +4 -4
- package/dist/{websocket-BOXVggMf.d.mts → websocket-Cs4awVyD.d.mts} +1 -1
- package/dist/{workScope-CxKqoIFn.mjs → workScope-n9a7d_lZ.mjs} +2 -2
- package/package.json +57 -59
- package/skills/arc/SKILL.md +13 -4
- package/skills/arc/references/auth.md +8 -5
- package/skills/arc/references/integrations.md +1 -1
- package/skills/arc/references/mcp.md +8 -6
- package/skills/arc/references/multi-tenancy.md +19 -14
- package/skills/arc/references/production.md +27 -10
- package/dist/actionPermissions-BoPGQ5-4.mjs +0 -350
- package/dist/index-CFfLKMH4.d.mts +0 -290
- package/dist/interface-YzIbF7Ii.mjs +0 -17
- package/dist/redis-stream-BPKscsTB.d.mts +0 -260
- package/dist/registerRoute-Bsnk6NiZ.mjs +0 -364
- package/dist/rolldown-runtime-eysyzFAF.mjs +0 -15
- package/dist/sync/changelog.d.mts +0 -3
- package/dist/sync/changelog.mjs +0 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { n as DomainEvent, r as EventHandler } from "./EventTransport-
|
|
2
|
+
import { n as DomainEvent, r as EventHandler } from "./EventTransport-CiicKz2Z.mjs";
|
|
3
3
|
import { n as ErrorMapper } from "./errorHandler--4rSMMvq.mjs";
|
|
4
4
|
import { FastifyInstance, FastifyPluginAsync } from "fastify";
|
|
5
5
|
import { LockAdapter } from "@classytic/repo-core/lock";
|
|
@@ -36,7 +36,6 @@ interface HealthOptions {
|
|
|
36
36
|
/** Collect HTTP request metrics (default: true if metrics enabled) */
|
|
37
37
|
collectHttpMetrics?: boolean;
|
|
38
38
|
}
|
|
39
|
-
declare const healthPlugin: FastifyPluginAsync<HealthOptions>;
|
|
40
39
|
declare const _default$1: FastifyPluginAsync<HealthOptions>;
|
|
41
40
|
//#endregion
|
|
42
41
|
//#region src/plugins/schedules.d.ts
|
|
@@ -132,7 +131,6 @@ declare module "fastify" {
|
|
|
132
131
|
getScheduleStats?: () => ScheduleStats[];
|
|
133
132
|
}
|
|
134
133
|
}
|
|
135
|
-
declare const schedulesPlugin: FastifyPluginAsync<SchedulesPluginOptions>;
|
|
136
134
|
declare const _default: FastifyPluginAsync<SchedulesPluginOptions>;
|
|
137
135
|
//#endregion
|
|
138
136
|
//#region src/factory/loadResources.d.ts
|
|
@@ -360,25 +358,26 @@ type ModuleDisposer = () => void | Promise<void>;
|
|
|
360
358
|
* Second argument to a module's setup phases (`plugins`, `bootstrap`,
|
|
361
359
|
* `afterResources`).
|
|
362
360
|
*/
|
|
363
|
-
interface ModuleSetupContext {
|
|
361
|
+
interface ModuleSetupContext<TPorts extends PortName = PortName, TOptionalPorts extends PortName = PortName> {
|
|
364
362
|
/**
|
|
365
|
-
* Register a teardown callback for the resource just acquired
|
|
366
|
-
* IMMEDIATELY after acquisition
|
|
367
|
-
*
|
|
368
|
-
*
|
|
369
|
-
* Disposers run LIFO, after this module's `onClose`, on both the rollback
|
|
370
|
-
* and shutdown paths, and exactly once. A throwing disposer is logged and
|
|
371
|
-
* never blocks the ones behind it.
|
|
363
|
+
* Register a teardown callback for the resource just acquired — call it
|
|
364
|
+
* IMMEDIATELY after acquisition. Runs LIFO, after this module's `onClose`,
|
|
365
|
+
* exactly once on rollback or shutdown. A throwing disposer is logged and
|
|
366
|
+
* never blocks the rest.
|
|
372
367
|
*/
|
|
373
368
|
defer(disposer: ModuleDisposer): void;
|
|
369
|
+
/**
|
|
370
|
+
* The ports THIS module declared in `requires`, frozen: each `ports` entry is present (boot
|
|
371
|
+
* fails otherwise), each `optionalPorts` entry is the value or `undefined`. Nothing else.
|
|
372
|
+
*/
|
|
373
|
+
readonly ports: ModulePorts<TPorts, TOptionalPorts>;
|
|
374
374
|
}
|
|
375
375
|
//#endregion
|
|
376
376
|
//#region src/factory/module/types.d.ts
|
|
377
377
|
/**
|
|
378
378
|
* A module's contribution of some arm (event handlers, scheduled jobs, …).
|
|
379
379
|
* Either a static array or a factory resolved AFTER all module bootstraps, so a
|
|
380
|
-
* contribution can close over booted engines
|
|
381
|
-
* reaching for a global getter (the coupling the module contract removes).
|
|
380
|
+
* contribution can close over booted engines instead of a global getter.
|
|
382
381
|
*/
|
|
383
382
|
type ModuleContribution<T> = readonly T[] | ((fastify: FastifyInstance) => readonly T[] | Promise<readonly T[]>);
|
|
384
383
|
/**
|
|
@@ -398,22 +397,13 @@ interface EventHandlerDefinition {
|
|
|
398
397
|
*/
|
|
399
398
|
name?: string;
|
|
400
399
|
/**
|
|
401
|
-
* Contain handler failures
|
|
402
|
-
*
|
|
403
|
-
* `{ err, event, eventId, handler }`) and swallowed instead of reaching the
|
|
404
|
-
* transport.
|
|
405
|
-
*
|
|
406
|
-
* **Off by default, deliberately.** Reaching the transport is what makes the
|
|
407
|
-
* durable path work: `RedisStreamTransport` leaves the message unacked, so it
|
|
408
|
-
* is redelivered and eventually DLQ'd. Silently swallowing by default would
|
|
409
|
-
* turn every module handler into best-effort delivery.
|
|
400
|
+
* Contain handler failures: a throw is logged via `fastify.log` and swallowed
|
|
401
|
+
* instead of reaching the transport.
|
|
410
402
|
*
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
* `subscribeWithBoundary` call in `afterResources` and lose arc's
|
|
416
|
-
* teardown-before-`onClose` guarantee.
|
|
403
|
+
* **Off by default, deliberately** — reaching the transport is what makes the
|
|
404
|
+
* durable path work (unacked → redelivered → DLQ). Turn it ON for
|
|
405
|
+
* fire-and-forget work (projections, cache invalidation, fan-out) where a
|
|
406
|
+
* failure must not block the ack.
|
|
417
407
|
*
|
|
418
408
|
* ```ts
|
|
419
409
|
* defineModule({ name: "search", eventHandlers: [
|
|
@@ -421,57 +411,77 @@ interface EventHandlerDefinition {
|
|
|
421
411
|
* ] })
|
|
422
412
|
* ```
|
|
423
413
|
*
|
|
424
|
-
* The object form
|
|
425
|
-
*
|
|
426
|
-
* caught and logged rather than escaping.
|
|
414
|
+
* The object form's `onError` replaces the default log; it runs INSIDE the
|
|
415
|
+
* boundary, so a throwing `onError` is caught and logged too.
|
|
427
416
|
*/
|
|
428
417
|
boundary?: boolean | {
|
|
429
418
|
onError?: (error: Error, event: DomainEvent) => void | Promise<void>;
|
|
430
419
|
};
|
|
420
|
+
/**
|
|
421
|
+
* What a failure means for a DURABLE event: `'retry'` rethrows to the relay (pair with
|
|
422
|
+
* `withInbox` so a redelivery re-runs only this handler); `'boundary'` may swallow and is
|
|
423
|
+
* the same as `boundary: true`. The module graph reports a durable event's handler without it.
|
|
424
|
+
*/
|
|
425
|
+
durability?: "retry" | "boundary";
|
|
431
426
|
}
|
|
432
|
-
interface ArcModule<TExports = unknown> {
|
|
427
|
+
interface ArcModule<TExports = unknown, TPorts extends PortName = PortName, TOptionalPorts extends PortName = PortName> {
|
|
433
428
|
/** Stable identifier — appears in boot logs and duplicate-module detection. */
|
|
434
429
|
readonly name: string;
|
|
435
430
|
/**
|
|
436
|
-
* Names of modules this one must be composed AFTER.
|
|
437
|
-
*
|
|
438
|
-
*
|
|
439
|
-
* is always live before this module's bootstrap, resources, or
|
|
440
|
-
* afterResources. Teardown (`onClose`) runs in the reverse of that order.
|
|
441
|
-
*
|
|
442
|
-
* Use this instead of relying on list position when a module reads another's
|
|
443
|
-
* public export — e.g. `@classytic/arc-reservation` wiring off
|
|
444
|
-
* `arc.modules.order`:
|
|
431
|
+
* Names of modules this one must be composed AFTER. A dependency's
|
|
432
|
+
* `bootstrap` (and its `fastify.arc.modules[dep]` export) is always live
|
|
433
|
+
* before this module's phases run; teardown runs in reverse.
|
|
445
434
|
*
|
|
446
435
|
* ```ts
|
|
447
436
|
* defineModule({ name: "reservation", dependsOn: ["order"], bootstrap: (f) => {
|
|
448
437
|
* const order = getModuleExports<OrderEngine>(f, "order"); // guaranteed live
|
|
449
|
-
* …
|
|
450
438
|
* }});
|
|
451
439
|
* ```
|
|
452
440
|
*
|
|
453
|
-
*
|
|
454
|
-
*
|
|
455
|
-
*
|
|
456
|
-
*
|
|
457
|
-
*
|
|
458
|
-
*
|
|
459
|
-
* **`dependsOn` is COMPOSITION order, not lazy loading.** Every module input
|
|
460
|
-
* (including dynamic-import thunks) is resolved — imported — up front via
|
|
461
|
-
* `Promise.all` BEFORE the sort; `dependsOn` then orders the *composition*
|
|
462
|
-
* (which module's `plugins`/`bootstrap` runs first), it does NOT delay
|
|
463
|
-
* *importing* a dependent until its dependency is ready. Use a thunk to gate
|
|
464
|
-
* whether a module is imported at all (region/tier packs); use `dependsOn`
|
|
465
|
-
* to order modules that are already selected.
|
|
466
|
-
*
|
|
467
|
-
* **Convention: every HARD sibling dependency belongs here** — including
|
|
468
|
-
* ones read lazily. `lazyRequiredModuleExports` defers the export READ to
|
|
469
|
-
* first use (and eagerly validates the module is composed), but only
|
|
470
|
-
* `dependsOn` orders composition so the sibling's engine exists before
|
|
471
|
-
* yours initializes. Omit the edge only for genuinely optional
|
|
441
|
+
* STABLE topological sort: modules with no edge between them keep list
|
|
442
|
+
* order. Unknown names, self-references and cycles fail at boot.
|
|
443
|
+
*
|
|
444
|
+
* Orders COMPOSITION, not importing — every input (thunks included) is
|
|
445
|
+
* imported up front. Every HARD sibling dependency belongs here, even one
|
|
446
|
+
* read via `lazyRequiredModuleExports`; omit it only for optional
|
|
472
447
|
* integrations (`lazyModuleExports` / `getOptionalModuleExports`).
|
|
473
448
|
*/
|
|
474
|
-
readonly dependsOn?: readonly
|
|
449
|
+
readonly dependsOn?: readonly ModuleName[];
|
|
450
|
+
/**
|
|
451
|
+
* - `'domain'` (default).
|
|
452
|
+
* - `'bridge'` joins two or more domains (order ↔ accounting): ACTIVE only when every
|
|
453
|
+
* `dependsOn` module is composed, dropped otherwise — no gate code.
|
|
454
|
+
* - `'platform'` — infrastructure (auth, outbox, notifications): orders ahead of every other
|
|
455
|
+
* ready module, and `resolveModuleClosure` includes it in every closure.
|
|
456
|
+
* - `'aggregator'` reads across the whole composed fleet (data cleanup, period close): it
|
|
457
|
+
* orders AFTER every non-aggregator module, as if it `dependsOn` all of them. A module that
|
|
458
|
+
* `dependsOn` an aggregator is therefore a cycle.
|
|
459
|
+
*/
|
|
460
|
+
readonly kind?: "domain" | "bridge" | "platform" | "aggregator";
|
|
461
|
+
/**
|
|
462
|
+
* The events this module OWNS — the facts it publishes, one owner per event, each named inside
|
|
463
|
+
* `eventNamespace`. What it consumes is derived from `eventHandlers`. Checked at boot by
|
|
464
|
+
* `createApp({ moduleGraph: { events } })`; rendered by `renderModuleGraph`.
|
|
465
|
+
*/
|
|
466
|
+
readonly publishes?: readonly (string | {
|
|
467
|
+
readonly name: string;
|
|
468
|
+
})[];
|
|
469
|
+
/**
|
|
470
|
+
* Owner prefix(es) of every event in `publishes` — `order` owns `order:placed` and
|
|
471
|
+
* `order.placed`. A list when one module owns several aggregates (`['order', 'rma']`).
|
|
472
|
+
* Default: the module name.
|
|
473
|
+
*/
|
|
474
|
+
readonly eventNamespace?: string | readonly string[];
|
|
475
|
+
/**
|
|
476
|
+
* What must be SUPPLIED or COMPOSED for this module to boot — checked before any module boots,
|
|
477
|
+
* every gap in one error. Ordering stays `dependsOn`'s job; nothing here adds an edge.
|
|
478
|
+
*
|
|
479
|
+
* ```ts
|
|
480
|
+
* defineModule({ name: "order", requires: { ports: ["outbox"], optionalPorts: ["calendar"], modules: ["invoice"] },
|
|
481
|
+
* bootstrap: (f, { ports }) => createOrderEngine(ports.outbox, ports.calendar) })
|
|
482
|
+
* ```
|
|
483
|
+
*/
|
|
484
|
+
readonly requires?: ModuleRequirements<TPorts, TOptionalPorts>;
|
|
475
485
|
/**
|
|
476
486
|
* Infra SETUP — the module analog of the app's `plugins()`. Runs after the
|
|
477
487
|
* app's own `plugins()`, in `dependsOn` order, before any module `bootstrap`.
|
|
@@ -483,7 +493,6 @@ interface ArcModule<TExports = unknown> {
|
|
|
483
493
|
* plugin throws; a bare multi-arg function warns.
|
|
484
494
|
*
|
|
485
495
|
* Receives `{ defer }` for teardown, or return one disposer as shorthand.
|
|
486
|
-
* v3 renames this slot to `setup` with no alias (v3.md).
|
|
487
496
|
*
|
|
488
497
|
* ```ts
|
|
489
498
|
* plugins: async (fastify) => {
|
|
@@ -493,48 +502,22 @@ interface ArcModule<TExports = unknown> {
|
|
|
493
502
|
* },
|
|
494
503
|
* ```
|
|
495
504
|
*/
|
|
496
|
-
plugins?: (fastify: FastifyInstance, context: ModuleSetupContext) => ModuleDisposer | undefined | Promise<ModuleDisposer | undefined>;
|
|
505
|
+
plugins?: (fastify: FastifyInstance, context: ModuleSetupContext<TPorts, TOptionalPorts>) => ModuleDisposer | undefined | Promise<ModuleDisposer | undefined>;
|
|
497
506
|
/**
|
|
498
507
|
* Domain error mappers this module ships (see `defineErrorMapper`). Merged
|
|
499
508
|
* into the app's error handler at boot, AFTER any host-declared mappers —
|
|
500
509
|
* host config keeps priority; module mappers follow in composition order.
|
|
501
|
-
*
|
|
502
|
-
* Closes the "composition root must know every domain's error classes"
|
|
503
|
-
* coupling: before this slot, adding `@classytic/arc-shipping` meant
|
|
504
|
-
* remembering to also register its `ShippingError` mapper in the host's
|
|
505
|
-
* `errorHandler.errorMappers` — forget it and the domain error crossed the
|
|
506
|
-
* wire as an opaque 500. Now the module carries its own mapper:
|
|
507
|
-
*
|
|
508
|
-
* ```ts
|
|
509
|
-
* defineModule({
|
|
510
|
-
* name: 'shipping',
|
|
511
|
-
* errorMappers: [shippingErrorMapper],
|
|
512
|
-
* ...
|
|
513
|
-
* })
|
|
514
|
-
* ```
|
|
510
|
+
* The host no longer has to know every domain's error classes.
|
|
515
511
|
*/
|
|
516
512
|
readonly errorMappers?: readonly ErrorMapper[];
|
|
517
513
|
/**
|
|
518
|
-
* Domain init — runs
|
|
519
|
-
*
|
|
520
|
-
* they are live when this module's `resources` factory runs.
|
|
514
|
+
* Domain init — runs after all `plugins`, before resources, so engines are
|
|
515
|
+
* live when this module's `resources` factory runs.
|
|
521
516
|
*
|
|
522
|
-
*
|
|
523
|
-
* `fastify.arc.modules[name]
|
|
524
|
-
*
|
|
525
|
-
*
|
|
526
|
-
* export shape via `defineModule<TExports>` and read it back with the typed
|
|
527
|
-
* accessor — no cast at the consuming end:
|
|
528
|
-
*
|
|
529
|
-
* ```ts
|
|
530
|
-
* // arc-invoice bootstrap, composed AFTER arc-accounting:
|
|
531
|
-
* const acct = getModuleExports<AccountingEngine>(fastify, "accounting");
|
|
532
|
-
* ```
|
|
533
|
-
*
|
|
534
|
-
* The return value is the module's export, so teardown here goes through
|
|
535
|
-
* `defer` (the second argument) rather than a returned disposer — register
|
|
536
|
-
* each resource the moment it exists and partial-init cleanup becomes exact
|
|
537
|
-
* instead of a chain of `?.` guards:
|
|
517
|
+
* The returned value is the module's PUBLIC EXPORT at
|
|
518
|
+
* `fastify.arc.modules[name]`; later modules read it with
|
|
519
|
+
* `getModuleExports<T>(fastify, name)`. Because the return slot is taken,
|
|
520
|
+
* teardown goes through `defer`, registered the moment each resource exists:
|
|
538
521
|
*
|
|
539
522
|
* ```ts
|
|
540
523
|
* bootstrap: async (fastify, { defer }) => {
|
|
@@ -546,27 +529,18 @@ interface ArcModule<TExports = unknown> {
|
|
|
546
529
|
* },
|
|
547
530
|
* ```
|
|
548
531
|
*/
|
|
549
|
-
bootstrap?: (fastify: FastifyInstance, context: ModuleSetupContext) => TExports | Promise<TExports>;
|
|
532
|
+
bootstrap?: (fastify: FastifyInstance, context: ModuleSetupContext<TPorts, TOptionalPorts>) => TExports | Promise<TExports>;
|
|
550
533
|
/**
|
|
551
|
-
* App-level resource NAMES this module SUPERSEDES
|
|
552
|
-
*
|
|
553
|
-
* registers this module's — so the host maintains no "which resources did
|
|
554
|
-
* modules take over" filter set.
|
|
534
|
+
* App-level resource NAMES this module SUPERSEDES: an app resource of the
|
|
535
|
+
* same name is dropped and this module's registered instead.
|
|
555
536
|
*
|
|
556
|
-
* PREFER `owns: "provided"
|
|
557
|
-
*
|
|
558
|
-
*
|
|
559
|
-
*
|
|
537
|
+
* PREFER `owns: "provided"` — derived from the resources the module actually
|
|
538
|
+
* returned, so the claim cannot disagree with reality. An explicit array is
|
|
539
|
+
* ENFORCED at boot: each name must appear in THIS module's own `resources`
|
|
540
|
+
* (a sibling's does not count), else a typo would silently remove the app's
|
|
541
|
+
* route with nothing serving it.
|
|
560
542
|
*
|
|
561
|
-
*
|
|
562
|
-
* module's own `resources`, or boot fails naming the unmet names. Without
|
|
563
|
-
* that, a typo or a deleted resource booted "successfully" with the app's
|
|
564
|
-
* route removed and nothing serving it. A sibling module providing the name
|
|
565
|
-
* does NOT satisfy the claim — ownership is local to its declarer.
|
|
566
|
-
*
|
|
567
|
-
* It only filters the APP list, never the module's own resources; an entry
|
|
568
|
-
* matching no app resource is a silent no-op (a module may pre-declare a
|
|
569
|
-
* name before any fork exists). Collected across modules as a union.
|
|
543
|
+
* Filters only the APP list; a name matching no app resource is a no-op.
|
|
570
544
|
*/
|
|
571
545
|
readonly owns?: readonly string[] | "provided";
|
|
572
546
|
/**
|
|
@@ -577,27 +551,17 @@ interface ArcModule<TExports = unknown> {
|
|
|
577
551
|
*/
|
|
578
552
|
resources?: ReadonlyArray<ResourceLike> | ((fastify: FastifyInstance) => ReadonlyArray<ResourceLike> | Promise<ReadonlyArray<ResourceLike>>);
|
|
579
553
|
/**
|
|
580
|
-
* Post-registration wiring — runs
|
|
581
|
-
*
|
|
582
|
-
* module owns.
|
|
583
|
-
*
|
|
584
|
-
* Receives `{ defer }`, and may return a disposer, on the same terms as
|
|
585
|
-
* `plugins` — handy for wiring that must be unwound (a subscription, a
|
|
586
|
-
* listener) without hoisting a handle into module scope.
|
|
554
|
+
* Post-registration wiring — runs once this module's routes are mounted.
|
|
555
|
+
* Receives `{ defer }` and may return a disposer, same as `plugins`.
|
|
587
556
|
*/
|
|
588
|
-
afterResources?: (fastify: FastifyInstance, context: ModuleSetupContext) => ModuleDisposer | undefined | Promise<ModuleDisposer | undefined>;
|
|
557
|
+
afterResources?: (fastify: FastifyInstance, context: ModuleSetupContext<TPorts, TOptionalPorts>) => ModuleDisposer | undefined | Promise<ModuleDisposer | undefined>;
|
|
589
558
|
/**
|
|
590
|
-
* Readiness checks
|
|
591
|
-
* `
|
|
592
|
-
*
|
|
593
|
-
* checks (modules-first, host-last) — the same additive convention arc uses
|
|
594
|
-
* for resources and error mappers. Check `name`s must be unique across the
|
|
595
|
-
* module graph (arc fails at boot on a collision, attributing both owners).
|
|
559
|
+
* Readiness checks for `/_health/ready`, merged BEFORE the host's
|
|
560
|
+
* `arcPlugins.health` checks. Names must be unique across the module graph
|
|
561
|
+
* (boot fails on a collision).
|
|
596
562
|
*
|
|
597
|
-
* STATIC by design (not a factory):
|
|
598
|
-
* `check()`
|
|
599
|
-
* can happen before the health plugin registers and the worker probe
|
|
600
|
-
* (`createWorker`) receives the identical union without a second registration.
|
|
563
|
+
* STATIC by design (not a factory): collection happens before the health
|
|
564
|
+
* plugin registers, so `check()` should resolve dependencies LAZILY.
|
|
601
565
|
*
|
|
602
566
|
* ```ts
|
|
603
567
|
* defineModule({ name: "inventory", healthChecks: [
|
|
@@ -607,15 +571,10 @@ interface ArcModule<TExports = unknown> {
|
|
|
607
571
|
*/
|
|
608
572
|
readonly healthChecks?: readonly HealthCheck[];
|
|
609
573
|
/**
|
|
610
|
-
* Domain-event subscriptions this module owns
|
|
611
|
-
*
|
|
612
|
-
*
|
|
613
|
-
*
|
|
614
|
-
* every unsubscribe and invokes it at shutdown BEFORE module `onClose` (while
|
|
615
|
-
* module deps are still alive). Named handlers must be unique across the
|
|
616
|
-
* module graph; a module that declares handlers while the event subsystem is
|
|
617
|
-
* disabled (`arcPlugins.events: false`) fails at boot. Array or factory (the
|
|
618
|
-
* factory runs after bootstraps, so it can close over booted engines).
|
|
574
|
+
* Domain-event subscriptions this module owns. Subscribed in dependency order
|
|
575
|
+
* during `afterResources`; unsubscribed at shutdown BEFORE module `onClose`
|
|
576
|
+
* (deps still alive). Named handlers must be unique across the graph;
|
|
577
|
+
* declaring handlers with `arcPlugins.events: false` fails at boot.
|
|
619
578
|
*
|
|
620
579
|
* ```ts
|
|
621
580
|
* defineModule({ name: "party", eventHandlers: [
|
|
@@ -625,13 +584,9 @@ interface ArcModule<TExports = unknown> {
|
|
|
625
584
|
*/
|
|
626
585
|
readonly eventHandlers?: ModuleContribution<EventHandlerDefinition>;
|
|
627
586
|
/**
|
|
628
|
-
* Durable workflows this module owns. OPAQUE to arc core —
|
|
629
|
-
* `@classytic/streamline
|
|
630
|
-
*
|
|
631
|
-
* gives it meaning (name/shape validation, registration). Collected via
|
|
632
|
-
* `collectModuleWorkflows` at integration-init time (after module bootstraps),
|
|
633
|
-
* so a factory can close over the shared workflow container the integration
|
|
634
|
-
* decorates on the instance.
|
|
587
|
+
* Durable workflows this module owns. OPAQUE to arc core — the streamline
|
|
588
|
+
* integration (`@classytic/arc/integrations/streamline`) validates and
|
|
589
|
+
* registers them after module bootstraps.
|
|
635
590
|
*
|
|
636
591
|
* ```ts
|
|
637
592
|
* defineModule({ name: "invoice",
|
|
@@ -640,12 +595,10 @@ interface ArcModule<TExports = unknown> {
|
|
|
640
595
|
*/
|
|
641
596
|
readonly workflows?: ModuleContribution<unknown>;
|
|
642
597
|
/**
|
|
643
|
-
* Recurring interval schedules
|
|
644
|
-
*
|
|
645
|
-
*
|
|
646
|
-
*
|
|
647
|
-
* declares schedules fails boot instead of silently dropping work. Array or
|
|
648
|
-
* factory (the factory runs once after bootstraps and may close over engines).
|
|
598
|
+
* Recurring interval schedules, composed into `schedulesPlugin` after
|
|
599
|
+
* bootstraps. Names must be unique across the graph; locking is configured
|
|
600
|
+
* via `arcPlugins.schedules`, and disabling that runner fails boot rather
|
|
601
|
+
* than silently dropping work.
|
|
649
602
|
*
|
|
650
603
|
* ```ts
|
|
651
604
|
* defineModule({ name: "loyalty", scheduledJobs: [
|
|
@@ -655,42 +608,18 @@ interface ArcModule<TExports = unknown> {
|
|
|
655
608
|
*/
|
|
656
609
|
readonly scheduledJobs?: ModuleContribution<ScheduleDefinition>;
|
|
657
610
|
/**
|
|
658
|
-
* Teardown — destroy engines, stop timers, flush the
|
|
659
|
-
*
|
|
660
|
-
*
|
|
661
|
-
*
|
|
662
|
-
*
|
|
663
|
-
*
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
*
|
|
667
|
-
*
|
|
668
|
-
*
|
|
669
|
-
*
|
|
670
|
-
* Because rollback fires after a PARTIAL init — your `bootstrap` opened a
|
|
671
|
-
* client and threw on the next line, or your `plugins` ran but `bootstrap`
|
|
672
|
-
* never did — write closers defensively. Guard everything init may not have
|
|
673
|
-
* reached: `client?.close()`, not `client.close()`.
|
|
674
|
-
*
|
|
675
|
-
* ```ts
|
|
676
|
-
* let client: Client | undefined;
|
|
677
|
-
* defineModule({
|
|
678
|
-
* name: "billing",
|
|
679
|
-
* bootstrap: async () => {
|
|
680
|
-
* client = await openClient(); // allocated…
|
|
681
|
-
* await migrate(client); // …and this may throw
|
|
682
|
-
* },
|
|
683
|
-
* onClose: async () => { await client?.close(); }, // still runs
|
|
684
|
-
* });
|
|
685
|
-
* ```
|
|
686
|
-
*
|
|
687
|
-
* Prefer `defer` (the setup phases' second argument) for anything acquired
|
|
688
|
-
* step-by-step: it registers each teardown at the point of acquisition, so
|
|
689
|
-
* the runtime knows exactly what was reached and the `?.` guards above
|
|
690
|
-
* disappear. `onClose` remains the right slot for tearing down what
|
|
691
|
-
* `bootstrap` RETURNED — the module's engine — and runs FIRST, ahead of the
|
|
692
|
-
* module's deferred disposers (see `disposers.ts` for the ordering rule).
|
|
693
|
-
* The two compose; either alone is complete.
|
|
611
|
+
* Teardown — destroy engines, stop timers, flush the outbox. Modules close in
|
|
612
|
+
* REVERSE composition order, BEFORE the app-level `onClose` and infra
|
|
613
|
+
* plugins' close hooks (so teardown still sees a live DB/Redis).
|
|
614
|
+
*
|
|
615
|
+
* Boot is transactional: if any phase fails, every module that entered an
|
|
616
|
+
* init phase (this one included) is closed in reverse, then the original
|
|
617
|
+
* error is rethrown. A closer runs AT MOST ONCE; a throwing one never blocks
|
|
618
|
+
* the rest.
|
|
619
|
+
*
|
|
620
|
+
* Rollback can follow a PARTIAL init, so guard what init may not have
|
|
621
|
+
* reached (`client?.close()`), or prefer `defer` for step-by-step
|
|
622
|
+
* acquisition. `onClose` runs FIRST, ahead of deferred disposers.
|
|
694
623
|
*/
|
|
695
624
|
onClose?: (fastify: FastifyInstance) => void | Promise<void>;
|
|
696
625
|
}
|
|
@@ -701,11 +630,8 @@ interface ArcModule<TExports = unknown> {
|
|
|
701
630
|
* - `Promise<ArcModule>` — an in-flight import
|
|
702
631
|
* - `() => ArcModule | Promise<…>` — a thunk, resolved at boot
|
|
703
632
|
*
|
|
704
|
-
*
|
|
705
|
-
*
|
|
706
|
-
* `next/dynamic` idea applied to backend domains. The module's code (and its
|
|
707
|
-
* heavy deps) is only pulled in when the thunk runs, so region- or tier-gated
|
|
708
|
-
* packs never enter the bundle path they aren't selected for:
|
|
633
|
+
* A thunk of a dynamic import loads a module only when selected (region- or
|
|
634
|
+
* tier-gated packs):
|
|
709
635
|
*
|
|
710
636
|
* ```ts
|
|
711
637
|
* const taxPack =
|
|
@@ -717,11 +643,59 @@ interface ArcModule<TExports = unknown> {
|
|
|
717
643
|
* // only the selected tax package is imported + composed
|
|
718
644
|
* ```
|
|
719
645
|
*/
|
|
720
|
-
type ArcModuleInput<TExports = unknown> = ArcModule<TExports> | Promise<ArcModule<TExports>> | (() => ArcModule<TExports> | Promise<ArcModule<TExports>>)
|
|
646
|
+
type ArcModuleInput<TExports = unknown> = ArcModule<TExports> | Promise<ArcModule<TExports>> | (() => ArcModule<TExports> | Promise<ArcModule<TExports>>) | LazyBridge<TExports>;
|
|
647
|
+
/**
|
|
648
|
+
* A bridge whose graph identity is declared up front, so arc decides activation
|
|
649
|
+
* BEFORE importing it — a bridge to a domain that is not composed is never
|
|
650
|
+
* loaded, not merely never activated. (A plain thunk must run before its
|
|
651
|
+
* `dependsOn` is known.) The loaded module must match the declaration.
|
|
652
|
+
*
|
|
653
|
+
* ```ts
|
|
654
|
+
* modules: [order, {
|
|
655
|
+
* kind: "bridge", name: "order-accounting", dependsOn: ["order", "accounting"],
|
|
656
|
+
* load: () => import("./bridges/order-accounting.js").then((m) => m.create(deps)),
|
|
657
|
+
* }]
|
|
658
|
+
* ```
|
|
659
|
+
*/
|
|
660
|
+
interface LazyBridge<TExports = unknown> {
|
|
661
|
+
readonly kind: "bridge";
|
|
662
|
+
readonly name: string;
|
|
663
|
+
readonly dependsOn: readonly ModuleName[];
|
|
664
|
+
/** Must equal the loaded module's `requires` — `planModules` checks ports without loading it. */
|
|
665
|
+
readonly requires?: ModuleRequirements;
|
|
666
|
+
readonly load: () => ArcModule<TExports> | Promise<ArcModule<TExports>>;
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Host collaborators by name — augment it so ports are typed and a misspelt name is a compile error:
|
|
670
|
+
*
|
|
671
|
+
* ```ts
|
|
672
|
+
* declare module "@classytic/arc/factory" {
|
|
673
|
+
* interface ArcPortRegistry { outbox: OutboxStore; calendar: BusinessCalendar }
|
|
674
|
+
* }
|
|
675
|
+
* ```
|
|
676
|
+
*/
|
|
677
|
+
interface ArcPortRegistry {}
|
|
678
|
+
/** A registered port name. */
|
|
679
|
+
type PortName = keyof ArcPortRegistry & string;
|
|
680
|
+
/** What `createApp({ ports })` accepts — any registered port, typed by the registry. */
|
|
681
|
+
type ArcPorts = { readonly [K in PortName]?: ArcPortRegistry[K]; };
|
|
682
|
+
/** The ports one module's setup phases see: required ones typed present, optional ones `| undefined`. */
|
|
683
|
+
type ModulePorts<TPorts extends PortName, TOptionalPorts extends PortName> = { readonly [K in TPorts]: ArcPortRegistry[K]; } & { readonly [K in TOptionalPorts]?: ArcPortRegistry[K]; };
|
|
684
|
+
/** What a module needs from its host. See `ArcModule.requires`. */
|
|
685
|
+
interface ModuleRequirements<TPorts extends PortName = PortName, TOptionalPorts extends PortName = PortName> {
|
|
686
|
+
/** Ports that must be supplied to `createApp({ ports })`. */
|
|
687
|
+
readonly ports?: readonly TPorts[];
|
|
688
|
+
/** Ports handed over when supplied, `undefined` otherwise. */
|
|
689
|
+
readonly optionalPorts?: readonly TOptionalPorts[];
|
|
690
|
+
/**
|
|
691
|
+
* Modules that must be COMPOSED, with no ordering edge — a mutual request-time need
|
|
692
|
+
* (accounting ⇄ invoice) a two-way `dependsOn` would make a cycle. Read the peer lazily.
|
|
693
|
+
*/
|
|
694
|
+
readonly modules?: readonly ModuleName[];
|
|
695
|
+
}
|
|
721
696
|
/**
|
|
722
|
-
* Typed module registry —
|
|
723
|
-
* `getModuleExports(f, "order")` infers the export type
|
|
724
|
-
* argument (the fastify / awilix pattern):
|
|
697
|
+
* Typed module registry — augment via declaration merging so
|
|
698
|
+
* `getModuleExports(f, "order")` infers the export type:
|
|
725
699
|
*
|
|
726
700
|
* ```ts
|
|
727
701
|
* declare module "@classytic/arc/factory" {
|
|
@@ -731,10 +705,21 @@ type ArcModuleInput<TExports = unknown> = ArcModule<TExports> | Promise<ArcModul
|
|
|
731
705
|
* }
|
|
732
706
|
* }
|
|
733
707
|
* ```
|
|
734
|
-
*
|
|
735
|
-
* Left empty here so the fallback `getModuleExports<T>(f, name: string)` stays
|
|
736
|
-
* available for apps that don't augment it.
|
|
737
708
|
*/
|
|
738
709
|
interface ArcModuleRegistry {}
|
|
710
|
+
/**
|
|
711
|
+
* Host-level composition switches. A HOST (never a package) sets `strictModuleNames: true` once
|
|
712
|
+
* every module it composes is in `ArcModuleRegistry`; then a misspelt `dependsOn` /
|
|
713
|
+
* `requires.modules` name is a compile error.
|
|
714
|
+
*
|
|
715
|
+
* ```ts
|
|
716
|
+
* declare module "@classytic/arc/factory" { interface ArcCompositionConfig { strictModuleNames: true } }
|
|
717
|
+
* ```
|
|
718
|
+
*/
|
|
719
|
+
interface ArcCompositionConfig {}
|
|
720
|
+
/** A module name as a reference: a registry key under `strictModuleNames`, else any string. */
|
|
721
|
+
type ModuleName = ArcCompositionConfig extends {
|
|
722
|
+
readonly strictModuleNames: true;
|
|
723
|
+
} ? keyof ArcModuleRegistry & string : string;
|
|
739
724
|
//#endregion
|
|
740
|
-
export {
|
|
725
|
+
export { _default as C, _default$1 as E, SchedulesPluginOptions as S, HealthOptions as T, ResourceLike as _, ArcPortRegistry as a, ScheduleDefinition as b, LazyBridge as c, ModulePorts as d, ModuleRequirements as f, LoadResourcesOptions as g, ModuleSetupContext as h, ArcModuleRegistry as i, ModuleContribution as l, ModuleDisposer as m, ArcModule as n, ArcPorts as o, PortName as p, ArcModuleInput as r, EventHandlerDefinition as s, ArcCompositionConfig as t, ModuleName as u, ResourceModule as v, HealthCheck as w, ScheduleStats as x, loadResources as y };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
2
|
+
import { F as ResourceDefinition } from "./index-WH7xgvxS.mjs";
|
|
3
|
+
import { i as ResourceRateLimiter } from "./resourceRateLimit-Wf6d6FL9.mjs";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
//#region src/integrations/mcp/types.d.ts
|
|
5
6
|
/** Behavioral hints for MCP clients (tool annotations per MCP spec) */
|
|
@@ -87,8 +88,12 @@ interface ToolDefinition<TSession = McpAuthResult> {
|
|
|
87
88
|
name: string;
|
|
88
89
|
description: string;
|
|
89
90
|
title?: string;
|
|
90
|
-
/**
|
|
91
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Flat Zod shape `{ field: z.string() }` (the SDK wraps it in a STRIPPING
|
|
93
|
+
* `z.object()`), or a whole Zod schema registered as-is — use the whole form
|
|
94
|
+
* when unknown keys must be refused or the input is a union of objects.
|
|
95
|
+
*/
|
|
96
|
+
inputSchema?: ToolInputSchema;
|
|
92
97
|
/** Flat Zod shape for structured output validation */
|
|
93
98
|
outputSchema?: Record<string, z.ZodTypeAny>;
|
|
94
99
|
annotations?: ToolAnnotations;
|
|
@@ -105,6 +110,8 @@ interface ToolDefinition<TSession = McpAuthResult> {
|
|
|
105
110
|
*/
|
|
106
111
|
source?: string;
|
|
107
112
|
}
|
|
113
|
+
/** A tool's input contract: a flat Zod shape, or a whole Zod schema validated as-is. */
|
|
114
|
+
type ToolInputSchema = Record<string, z.ZodTypeAny> | z.ZodType;
|
|
108
115
|
/** Output of definePrompt() — plain data, not yet registered */
|
|
109
116
|
interface PromptDefinition {
|
|
110
117
|
name: string;
|
|
@@ -178,6 +185,8 @@ type CrudDescriptionOverride = string | ((meta: CrudDescriptionMeta) => string);
|
|
|
178
185
|
* omit it to keep the legacy dispatch-only behavior.
|
|
179
186
|
*/
|
|
180
187
|
interface McpExecutionWiring {
|
|
188
|
+
/** Same resource budget and backend used by REST routes. */
|
|
189
|
+
readonly rateLimiter?: ResourceRateLimiter;
|
|
181
190
|
/** Shared `HookSystem` — `fastify.arc.hooks`. */
|
|
182
191
|
readonly hooks?: unknown;
|
|
183
192
|
/** Event bus decorator — `fastify.events`. */
|
|
@@ -192,6 +201,12 @@ interface McpExecutionWiring {
|
|
|
192
201
|
* on mutating CRUD tools and enables executor-level check/lock/replay.
|
|
193
202
|
*/
|
|
194
203
|
readonly idempotencyStore?: unknown;
|
|
204
|
+
/** Explicit migration escape matching the HTTP idempotency plugin. */
|
|
205
|
+
readonly allowUnfencedCompletion?: boolean;
|
|
206
|
+
/** Cached result lifetime shared with the HTTP plugin; defaults to 24 hours. */
|
|
207
|
+
readonly idempotencyTtlMs?: number;
|
|
208
|
+
/** Completion lease shared with the HTTP plugin; defaults to 30 seconds. */
|
|
209
|
+
readonly idempotencyLockTimeoutMs?: number;
|
|
195
210
|
}
|
|
196
211
|
/** Per-resource MCP configuration overrides */
|
|
197
212
|
interface McpResourceConfig {
|
|
@@ -328,7 +343,7 @@ interface McpPluginOptions {
|
|
|
328
343
|
/** Instructions for the LLM — guidance on tool usage, constraints */
|
|
329
344
|
instructions?: string;
|
|
330
345
|
/**
|
|
331
|
-
* Resources to exclude by name
|
|
346
|
+
* Resources to exclude by name. Mutually exclusive with `expose`.
|
|
332
347
|
*
|
|
333
348
|
* Drift-prone for LLM-facing surfaces: a new `defineResource()` is exposed
|
|
334
349
|
* by default and you have to remember to add it here. Prefer `expose` when
|
|
@@ -341,10 +356,8 @@ interface McpPluginOptions {
|
|
|
341
356
|
* inverse of `exclude`), matching the principle-of-least-authority that
|
|
342
357
|
* LLM-driven tool surfaces want.
|
|
343
358
|
*
|
|
344
|
-
* Mutually exclusive with `
|
|
345
|
-
* throws
|
|
346
|
-
* default would render the exclude list redundant; passing both throws
|
|
347
|
-
* with a hint to drop `exclude`.
|
|
359
|
+
* Mutually exclusive with `exclude` (the deny default makes it redundant);
|
|
360
|
+
* passing both throws with a hint to drop `exclude`.
|
|
348
361
|
*
|
|
349
362
|
* @example
|
|
350
363
|
* ```ts
|
|
@@ -482,4 +495,4 @@ interface CreateMcpServerConfig {
|
|
|
482
495
|
/** CRUD operation type */
|
|
483
496
|
type CrudOperation = "list" | "get" | "create" | "update" | "delete";
|
|
484
497
|
//#endregion
|
|
485
|
-
export { ToolDefinition as _, CrudDescriptionOverride as a, McpAuthResult as c, McpResourceConfig as d, PromptDefinition as f, ToolContext as g, ToolAnnotations as h, CrudDescriptionMeta as i, McpExecutionWiring as l, SessionEntry as m, CallToolResult as n, CrudOperation as o, PromptResult as p, CreateMcpServerConfig as r, McpAuthResolver as s, BetterAuthHandler as t, McpPluginOptions as u };
|
|
498
|
+
export { ToolDefinition as _, CrudDescriptionOverride as a, McpAuthResult as c, McpResourceConfig as d, PromptDefinition as f, ToolContext as g, ToolAnnotations as h, CrudDescriptionMeta as i, McpExecutionWiring as l, SessionEntry as m, CallToolResult as n, CrudOperation as o, PromptResult as p, CreateMcpServerConfig as r, McpAuthResolver as s, BetterAuthHandler as t, McpPluginOptions as u, ToolInputSchema as v };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { l as UnauthorizedError, o as OrgRequiredError } from "./errors-
|
|
3
|
-
import { n as requireSingleHeaderValue } from "./headers-
|
|
4
|
-
import { t as getUserId$1 } from "./userHelpers-
|
|
1
|
+
/*! @classytic/arc v2.44.0 | MIT | https://classytic.com */
|
|
2
|
+
import { l as UnauthorizedError, o as OrgRequiredError } from "./errors-CW4anJBy.mjs";
|
|
3
|
+
import { n as requireSingleHeaderValue } from "./headers-DKZQKL-Z.mjs";
|
|
4
|
+
import { t as getUserId$1 } from "./userHelpers-C76zD5pa.mjs";
|
|
5
5
|
//#region src/scope/types.ts
|
|
6
6
|
/**
|
|
7
7
|
* Request Scope — The One Standard
|