@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
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
|
|
2
|
+
import { F as ResourceDefinition } from "./index-WH7xgvxS.mjs";
|
|
3
|
+
import { h as ModuleSetupContext, i as ArcModuleRegistry, l as ModuleContribution, n as ArcModule, o as ArcPorts, p as PortName, r as ArcModuleInput, u as ModuleName } from "./types-BJ-2XqVF.mjs";
|
|
4
|
+
import { FastifyInstance } from "fastify";
|
|
5
|
+
//#region src/factory/module/graph.d.ts
|
|
6
|
+
type ModuleKind = "domain" | "bridge" | "platform" | "aggregator";
|
|
7
|
+
/** How strictly the event graph is checked at boot. */
|
|
8
|
+
type ModuleGraphMode = "strict" | "warn" | "off";
|
|
9
|
+
interface ModuleGraphOptions {
|
|
10
|
+
/** Default `'off'`. `'strict'` fails boot on any issue; `'warn'` logs each one. */
|
|
11
|
+
readonly events?: ModuleGraphMode;
|
|
12
|
+
/**
|
|
13
|
+
* Event patterns published by something OUTSIDE the module graph (a plugin, a webhook
|
|
14
|
+
* bridge, another service) — a consumer of one of these is satisfied without a module owner.
|
|
15
|
+
*/
|
|
16
|
+
readonly externalEvents?: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
interface SkippedBridge {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
/** The `dependsOn` modules that are not active. */
|
|
21
|
+
readonly missing: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
interface ModuleGraphNode {
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly kind: ModuleKind;
|
|
26
|
+
/** Owner prefixes every owned event carries — `eventNamespace`, or the module name. */
|
|
27
|
+
readonly namespaces: readonly string[];
|
|
28
|
+
readonly dependsOn: readonly string[];
|
|
29
|
+
readonly publishes: readonly string[];
|
|
30
|
+
readonly consumes: readonly string[];
|
|
31
|
+
}
|
|
32
|
+
interface ModuleGraph {
|
|
33
|
+
readonly modules: readonly ModuleGraphNode[];
|
|
34
|
+
readonly skippedBridges: readonly SkippedBridge[];
|
|
35
|
+
readonly externalEvents: readonly string[];
|
|
36
|
+
}
|
|
37
|
+
interface ModuleGraphIssue {
|
|
38
|
+
readonly code: "duplicate-owner" | "outside-namespace" | "no-publisher" | "durable-without-outbox" | "durable-consumer-undeclared";
|
|
39
|
+
readonly module: string;
|
|
40
|
+
readonly event: string;
|
|
41
|
+
readonly message: string;
|
|
42
|
+
}
|
|
43
|
+
/** The resolved incidence: who owns each event, and what each consumed pattern reaches. */
|
|
44
|
+
interface ModuleGraphAnalysis {
|
|
45
|
+
/** Published event → owning modules (more than one is a `duplicate-owner` issue). */
|
|
46
|
+
readonly owners: ReadonlyMap<string, readonly string[]>;
|
|
47
|
+
/** Module → consumed pattern → the published events it matches. */
|
|
48
|
+
readonly reaches: ReadonlyMap<string, ReadonlyMap<string, readonly string[]>>;
|
|
49
|
+
/** D = C·Pᵀ: consumer → publisher → the events flowing between them. */
|
|
50
|
+
readonly coupling: ReadonlyMap<string, ReadonlyMap<string, readonly string[]>>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Drop every bridge whose `dependsOn` is not fully composed — to a fixpoint, so a bridge that
|
|
54
|
+
* depends on a dropped bridge is dropped too. Domain and platform modules are never dropped:
|
|
55
|
+
* their missing dependencies stay a hard error in `orderModules`.
|
|
56
|
+
*/
|
|
57
|
+
declare function activateBridges(modules: readonly ArcModule[]): {
|
|
58
|
+
active: ArcModule[];
|
|
59
|
+
skipped: SkippedBridge[];
|
|
60
|
+
};
|
|
61
|
+
/** The CRUD route shape the registry records — enough to know which mutations actually mounted. */
|
|
62
|
+
interface CrudSurface {
|
|
63
|
+
readonly name: string;
|
|
64
|
+
readonly adapter?: unknown;
|
|
65
|
+
readonly disableDefaultRoutes?: boolean | undefined;
|
|
66
|
+
readonly disabledRoutes?: readonly string[] | undefined;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The events arc auto-emits for a resource (`<name>.created|updated|deleted`) — only for
|
|
70
|
+
* mutations that actually MOUNTED. Overstating would satisfy a consumer that never receives one.
|
|
71
|
+
*/
|
|
72
|
+
declare function crudEventsOf(r: CrudSurface): string[];
|
|
73
|
+
/** What arc knows a module publishes without it declaring — its resources' CRUD events. */
|
|
74
|
+
interface DerivedPublishes {
|
|
75
|
+
readonly publishes: readonly string[];
|
|
76
|
+
/** Resource names — a module owns its resources' events. */
|
|
77
|
+
readonly namespaces: readonly string[];
|
|
78
|
+
}
|
|
79
|
+
declare function buildModuleGraph(modules: readonly ArcModule[], consumedByModule: ReadonlyMap<string, readonly string[]>, skippedBridges: readonly SkippedBridge[], externalEvents?: readonly string[], derived?: ReadonlyMap<string, DerivedPublishes>): ModuleGraph;
|
|
80
|
+
/** Resolve the graph's incidence once — every check and view reads this. */
|
|
81
|
+
declare function analyzeModuleGraph(graph: ModuleGraph): ModuleGraphAnalysis;
|
|
82
|
+
/** Every issue in the graph — empty when it is sound. */
|
|
83
|
+
declare function verifyModuleGraph(graph: ModuleGraph, analysis?: ModuleGraphAnalysis): ModuleGraphIssue[];
|
|
84
|
+
/** A subscribed handler as the durability check sees it. */
|
|
85
|
+
interface HandlerDurabilityFact {
|
|
86
|
+
readonly label: string;
|
|
87
|
+
readonly patterns: readonly string[];
|
|
88
|
+
readonly durability?: "retry" | "boundary";
|
|
89
|
+
}
|
|
90
|
+
interface DurabilityFacts {
|
|
91
|
+
/** Modules whose export is an outbox with `transactionalSave === true`. */
|
|
92
|
+
readonly outboxModules: ReadonlySet<string>;
|
|
93
|
+
/** Module → the handlers it subscribed. */
|
|
94
|
+
readonly handlers: ReadonlyMap<string, readonly HandlerDurabilityFact[]>;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* A durable event's publisher must `dependsOn` a transactional outbox, and each of its handlers
|
|
98
|
+
* must declare `durability` (`'retry'` rethrows to the relay; `'boundary'` may swallow).
|
|
99
|
+
*/
|
|
100
|
+
declare function verifyEventDurability(modules: readonly ArcModule[], facts: DurabilityFacts): ModuleGraphIssue[];
|
|
101
|
+
/**
|
|
102
|
+
* What stops working if `name` is switched off: modules consuming events only it publishes
|
|
103
|
+
* (a column of the coupling matrix), and bridges that `dependsOn` it — which arc drops.
|
|
104
|
+
*/
|
|
105
|
+
declare function dependentsOf(graph: ModuleGraph, name: string, analysis?: ModuleGraphAnalysis): {
|
|
106
|
+
starved: {
|
|
107
|
+
module: string;
|
|
108
|
+
events: string[];
|
|
109
|
+
}[];
|
|
110
|
+
droppedBridges: string[];
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* The graph as Markdown — modules, the coupling between them, then every event with its owner
|
|
114
|
+
* and consumers. Generate it into the repo so people and agents read the map instead of grepping.
|
|
115
|
+
*/
|
|
116
|
+
declare function renderModuleGraph(graph: ModuleGraph, analysis?: ModuleGraphAnalysis): string;
|
|
117
|
+
/**
|
|
118
|
+
* Divide the graph by its coupling: Tarjan's strongly connected components over D = C·Pᵀ.
|
|
119
|
+
* A component of more than one module is an EVENT CYCLE — modules that consume each other's
|
|
120
|
+
* facts and so can only be deployed, disabled or reasoned about together. `layers` is the
|
|
121
|
+
* condensation in dependency order: each layer consumes only from layers before it, so a layer's
|
|
122
|
+
* modules can be verified, tested or split out in parallel.
|
|
123
|
+
*/
|
|
124
|
+
declare function eventTopology(graph: ModuleGraph, analysis?: ModuleGraphAnalysis): {
|
|
125
|
+
cycles: string[][];
|
|
126
|
+
layers: string[][];
|
|
127
|
+
};
|
|
128
|
+
//#endregion
|
|
129
|
+
//#region src/factory/module/asyncapi.d.ts
|
|
130
|
+
/** The slice of an event registry's `catalog()` the export reads. */
|
|
131
|
+
interface AsyncApiCatalogEntry {
|
|
132
|
+
readonly name: string;
|
|
133
|
+
readonly version: number;
|
|
134
|
+
readonly description?: string | undefined;
|
|
135
|
+
readonly schema?: unknown;
|
|
136
|
+
}
|
|
137
|
+
interface AsyncApiInfo {
|
|
138
|
+
readonly title: string;
|
|
139
|
+
readonly version: string;
|
|
140
|
+
readonly description?: string;
|
|
141
|
+
}
|
|
142
|
+
declare function toAsyncApi(graph: ModuleGraph, catalog: readonly AsyncApiCatalogEntry[], info: AsyncApiInfo, analysis?: ModuleGraphAnalysis): Record<string, unknown>;
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/factory/module/contributions.d.ts
|
|
145
|
+
/**
|
|
146
|
+
* Collect every module's `workflows`. Resolves factory contributions (so a
|
|
147
|
+
* factory can close over a container the caller has already decorated on
|
|
148
|
+
* `fastify`) and flattens to a single opaque array. Arc core deliberately
|
|
149
|
+
* does NOT validate or interpret the values — the streamline integration
|
|
150
|
+
* owns name/shape checks and registration. Called by the integration at init
|
|
151
|
+
* time, not by arc's boot pipeline (workflows depend on the integration's
|
|
152
|
+
* container).
|
|
153
|
+
*/
|
|
154
|
+
declare function collectModuleWorkflows(fastify: FastifyInstance, modules: readonly ArcModule[]): Promise<unknown[]>;
|
|
155
|
+
//#endregion
|
|
156
|
+
//#region src/factory/module/extend.d.ts
|
|
157
|
+
/**
|
|
158
|
+
* What a caller may add. Every mergeable arm of `ArcModule`, plus `bootstrap`
|
|
159
|
+
* in wrapper form only.
|
|
160
|
+
*
|
|
161
|
+
* `name` is absent on purpose: renaming a module mid-composition breaks the
|
|
162
|
+
* `dependsOn` graph and the registry key its consumers read, and it is the one
|
|
163
|
+
* "extension" that is never additive.
|
|
164
|
+
*/
|
|
165
|
+
interface ModuleExtension<TExports = unknown> {
|
|
166
|
+
dependsOn?: ArcModule<TExports>["dependsOn"];
|
|
167
|
+
/**
|
|
168
|
+
* Classify a module the package left unclassified (`'platform'`, `'aggregator'`, …). Setting
|
|
169
|
+
* a kind that DIFFERS from one the module declared throws — a bridge is not silently relabelled.
|
|
170
|
+
*/
|
|
171
|
+
kind?: ArcModule<TExports>["kind"];
|
|
172
|
+
/** Unioned with the module's; a port either side marks `'required'` stays required. */
|
|
173
|
+
requires?: ArcModule<TExports>["requires"];
|
|
174
|
+
owns?: readonly string[] | "provided";
|
|
175
|
+
resources?: ArcModule<TExports>["resources"];
|
|
176
|
+
eventHandlers?: ArcModule<TExports>["eventHandlers"];
|
|
177
|
+
scheduledJobs?: ArcModule<TExports>["scheduledJobs"];
|
|
178
|
+
workflows?: ArcModule<TExports>["workflows"];
|
|
179
|
+
healthChecks?: ArcModule<TExports>["healthChecks"];
|
|
180
|
+
errorMappers?: ArcModule<TExports>["errorMappers"];
|
|
181
|
+
plugins?: ArcModule<TExports>["plugins"];
|
|
182
|
+
afterResources?: ArcModule<TExports>["afterResources"];
|
|
183
|
+
onClose?: ArcModule<TExports>["onClose"];
|
|
184
|
+
/** Host-emitted facts added to the module's owned events — concatenated. */
|
|
185
|
+
publishes?: ArcModule<TExports>["publishes"];
|
|
186
|
+
/** Extra owner prefixes for those facts — unioned with the module's. */
|
|
187
|
+
eventNamespace?: ArcModule<TExports>["eventNamespace"];
|
|
188
|
+
/**
|
|
189
|
+
* WRAP the module's bootstrap — it is never replaced.
|
|
190
|
+
*
|
|
191
|
+
* Bootstrap returns the module's exports, so two of them cannot be
|
|
192
|
+
* concatenated: one value has to win, and a host silently winning is the gym
|
|
193
|
+
* failure (`{ ...mod, bootstrap }` overwrote the factory's own, so the engine
|
|
194
|
+
* the module published was never created). The wrapper form makes the
|
|
195
|
+
* relationship explicit — call `inner` and decorate its result, or
|
|
196
|
+
* deliberately do not.
|
|
197
|
+
*
|
|
198
|
+
* `inner` is `undefined` when the module has no bootstrap of its own.
|
|
199
|
+
*/
|
|
200
|
+
bootstrap?: (inner: ((f: FastifyInstance, c: ModuleSetupContext) => TExports | Promise<TExports>) | undefined) => (f: FastifyInstance, c: ModuleSetupContext) => TExports | Promise<TExports>;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Merge a host's additions onto a module. Nothing the module declared is lost.
|
|
204
|
+
*
|
|
205
|
+
* ```ts
|
|
206
|
+
* return extendModule(createOrderModule({ … }), {
|
|
207
|
+
* eventHandlers: () => hostHandlers(), // appended after the module's
|
|
208
|
+
* dependsOn: ["outbox"], // unioned
|
|
209
|
+
* bootstrap: (inner) => async (f, c) => { // wraps, never replaces
|
|
210
|
+
* const exports = await inner?.(f, c);
|
|
211
|
+
* return decorate(exports);
|
|
212
|
+
* },
|
|
213
|
+
* });
|
|
214
|
+
* ```
|
|
215
|
+
*/
|
|
216
|
+
declare function extendModule<TExports = unknown>(mod: ArcModule<TExports>, extension: ModuleExtension<TExports>): ArcModule<TExports>;
|
|
217
|
+
//#endregion
|
|
218
|
+
//#region src/factory/module/lifecycle.d.ts
|
|
219
|
+
/**
|
|
220
|
+
* Subscribe every module's `eventHandlers` in dependency order (pass the
|
|
221
|
+
* `orderModules`-sorted list). Returns the ordered list of unsubscribe
|
|
222
|
+
* functions so the caller can tear them down at shutdown BEFORE module
|
|
223
|
+
* `onClose` (while module deps are still alive). Fails at boot on:
|
|
224
|
+
* - a duplicate NAMED handler across modules (attributing both owners);
|
|
225
|
+
* - a module declaring handlers while the event subsystem is unavailable.
|
|
226
|
+
* Resolves factory contributions (after bootstraps) so a handler can close over
|
|
227
|
+
* booted engines rather than a global getter.
|
|
228
|
+
*/
|
|
229
|
+
declare function subscribeModuleEventHandlers(fastify: FastifyInstance, modules: readonly ArcModule[],
|
|
230
|
+
/** Per-module handler counts, so descriptors never re-resolve the factories. */
|
|
231
|
+
countsByModule?: Map<string, number>, consumedByModule?: Map<string, string[]>,
|
|
232
|
+
/** Per-module handler facts for the durability check. */
|
|
233
|
+
handlersByModule?: Map<string, HandlerDurabilityFact[]>): Promise<Array<() => void | Promise<void>>>;
|
|
234
|
+
//#endregion
|
|
235
|
+
//#region src/factory/module/order.d.ts
|
|
236
|
+
/**
|
|
237
|
+
* Order modules for composition — a STABLE topological sort. Every later phase
|
|
238
|
+
* (bootstrap, resources, afterResources, reverse-order onClose) iterates the
|
|
239
|
+
* returned list, so a module's dependencies are always composed before it.
|
|
240
|
+
*
|
|
241
|
+
* Edges: each module's `dependsOn`, plus an implicit edge from every
|
|
242
|
+
* `kind: 'aggregator'` module to every non-aggregator one. Among READY modules a
|
|
243
|
+
* `kind: 'platform'` one is emitted first; otherwise list order breaks ties, so
|
|
244
|
+
* declaring an edge never reorders an unrelated module.
|
|
245
|
+
*
|
|
246
|
+
* Throws on a duplicate name, a `dependsOn` name not composed, a self-reference,
|
|
247
|
+
* or a cycle (reporting the concrete `a → b → … → a` path).
|
|
248
|
+
*/
|
|
249
|
+
declare function orderModules(modules: readonly ArcModule[]): ArcModule[];
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region src/factory/module/plan.d.ts
|
|
252
|
+
/** One reason a module list cannot boot. `message` names the module, what is missing, and the fix. */
|
|
253
|
+
interface CompositionProblem {
|
|
254
|
+
readonly code: "duplicate-module" | "self-dependency" | "missing-dependency" | "missing-module" | "missing-port";
|
|
255
|
+
readonly module: string;
|
|
256
|
+
/** The missing module or port, or the duplicated name. */
|
|
257
|
+
readonly target: string;
|
|
258
|
+
readonly message: string;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Every problem in an ACTIVE module list (bridges already activated): duplicate names,
|
|
262
|
+
* self/missing `dependsOn`, unmet `requires.modules`, unsupplied `requires.ports`. Cycles are
|
|
263
|
+
* `orderModules`' to report, with their path.
|
|
264
|
+
*/
|
|
265
|
+
declare function compositionProblems(modules: readonly Pick<ArcModule, "name" | "dependsOn" | "requires">[], ports?: ArcPorts): CompositionProblem[];
|
|
266
|
+
/** Throw ONE error listing every composition problem, or return. */
|
|
267
|
+
declare function assertComposable(modules: readonly Pick<ArcModule, "name" | "dependsOn" | "requires">[], ports?: ArcPorts): void;
|
|
268
|
+
/** What `createApp` would compose — without booting anything or loading a lazy bridge. */
|
|
269
|
+
interface ModulePlan {
|
|
270
|
+
/** Module names in boot order (bootstrap order; teardown is the reverse). */
|
|
271
|
+
readonly order: readonly string[];
|
|
272
|
+
/** Active `kind: 'bridge'` modules, in boot order. */
|
|
273
|
+
readonly activeBridges: readonly string[];
|
|
274
|
+
/** Bridges dropped because a module they join is not composed. */
|
|
275
|
+
readonly skippedBridges: readonly SkippedBridge[];
|
|
276
|
+
}
|
|
277
|
+
interface PlanModulesOptions {
|
|
278
|
+
/** The ports the app will receive — checked exactly as `createApp({ ports })` checks them. */
|
|
279
|
+
readonly ports?: ArcPorts;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Dry-run a composition: resolve inputs, activate bridges, order, check requirements — the same
|
|
283
|
+
* functions `createApp` calls, so the plan fails where boot would and orders as boot would.
|
|
284
|
+
*
|
|
285
|
+
* Thunks ARE invoked (their result is the module); a `LazyBridge` is decided on its declaration
|
|
286
|
+
* and never loaded.
|
|
287
|
+
*/
|
|
288
|
+
declare function planModules(inputs: readonly ArcModuleInput[], options?: PlanModulesOptions): Promise<ModulePlan>;
|
|
289
|
+
/** The graph identity `resolveModuleClosure` reads — an `ArcModule` or a `LazyBridge` both fit. */
|
|
290
|
+
interface ClosureNode {
|
|
291
|
+
readonly name: string;
|
|
292
|
+
readonly kind?: ArcModule["kind"];
|
|
293
|
+
readonly dependsOn?: readonly string[];
|
|
294
|
+
readonly requires?: ArcModule["requires"];
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* The modules `roots` need to boot: their `dependsOn` and `requires.modules` closure, plus every
|
|
298
|
+
* `kind: 'platform'` module (and its own closure). Returned in INPUT order, so ordering the result
|
|
299
|
+
* matches ordering the full list.
|
|
300
|
+
*
|
|
301
|
+
* Bridges are not pulled in — a bridge joins domains, it is not needed by them. An aggregator
|
|
302
|
+
* root brings only its declared edges: it reads whatever is composed.
|
|
303
|
+
*
|
|
304
|
+
* Throws on an unknown root, or an edge to a module that is not in `modules`.
|
|
305
|
+
*/
|
|
306
|
+
declare function resolveModuleClosure<T extends ClosureNode>(modules: readonly T[], roots: readonly ModuleName[]): T[];
|
|
307
|
+
//#endregion
|
|
308
|
+
//#region src/factory/module/relay-nudge.d.ts
|
|
309
|
+
/** What a module accepts as `relay`. */
|
|
310
|
+
type RelayOption = {
|
|
311
|
+
readonly requestDrain: () => void;
|
|
312
|
+
} | (() => {
|
|
313
|
+
readonly requestDrain: () => void;
|
|
314
|
+
}) |
|
|
315
|
+
/** Resolve the drain from an arc module's exports — `{ fromModule: 'outbox' }` is arc's outbox module. */
|
|
316
|
+
{
|
|
317
|
+
readonly fromModule: string;
|
|
318
|
+
} |
|
|
319
|
+
/** The relay runs in another process (`role: 'relay'`); nothing here to nudge. */
|
|
320
|
+
"external";
|
|
321
|
+
/**
|
|
322
|
+
* Merge an `afterCommit` nudge into a runtime whose `dispatch` is `'relay'`.
|
|
323
|
+
*
|
|
324
|
+
* - `'inline'` / no dispatch: returned untouched.
|
|
325
|
+
* - `'relay'` + a resolvable `relay`: `afterCommit` nudges; a host's own hook runs first.
|
|
326
|
+
* - `'relay'` + no `relay`: THROWS — a worker-drained deployment and a forgotten wire
|
|
327
|
+
* look identical, so the host has to say which.
|
|
328
|
+
*/
|
|
329
|
+
declare function withRelayNudge<T>(label: string, runtime: T, relay: RelayOption | undefined): T;
|
|
330
|
+
interface RelayNudge {
|
|
331
|
+
/** Wrap the engine runtime before `bind`; its type is preserved. */
|
|
332
|
+
apply<T>(runtime: T): T;
|
|
333
|
+
/**
|
|
334
|
+
* Present only for `{ fromModule }`: resolve the drain off the module registry. Spread
|
|
335
|
+
* into the module's `afterResources` — every bootstrap has run by then, and a missing
|
|
336
|
+
* module or drain fails at BOOT, not on the first write.
|
|
337
|
+
*/
|
|
338
|
+
afterResources?: (fastify: FastifyInstance) => Promise<undefined>;
|
|
339
|
+
}
|
|
340
|
+
/** The one way a module wires `relay` — `{ fromModule }` included. */
|
|
341
|
+
declare function createRelayNudge(label: string, relay: RelayOption | undefined): RelayNudge;
|
|
342
|
+
//#endregion
|
|
343
|
+
//#region src/factory/module/resolve.d.ts
|
|
344
|
+
/**
|
|
345
|
+
* Resolve any module-input form to a concrete `ArcModule`. A thunk is invoked
|
|
346
|
+
* (this is where a dynamic `import()` fires); a promise (or plain module) is
|
|
347
|
+
* awaited. Called once per module at the start of the bootstrap phase.
|
|
348
|
+
*/
|
|
349
|
+
declare function resolveModule(input: ArcModuleInput): Promise<ArcModule>;
|
|
350
|
+
/** Resolve a `ModuleContribution` to a concrete array (array passthrough or factory call). */
|
|
351
|
+
declare function resolveContribution<T>(contribution: ModuleContribution<T> | undefined, fastify: FastifyInstance): Promise<readonly T[]>;
|
|
352
|
+
//#endregion
|
|
353
|
+
//#region src/factory/module/state.d.ts
|
|
354
|
+
type ModuleState = "resolved" | "bootstrapping" | "ready" | "closing" | "closed" | "failed";
|
|
355
|
+
/**
|
|
356
|
+
* Is `name` in the composed module graph? TRUE for resource-only modules and
|
|
357
|
+
* modules that exported nothing — the question `hasModuleExports()` cannot
|
|
358
|
+
* answer. FALSE before registerResources runs (no graph yet) and for
|
|
359
|
+
* uncomposed names.
|
|
360
|
+
*/
|
|
361
|
+
declare function hasModule(fastify: FastifyInstance, name: string): boolean;
|
|
362
|
+
/**
|
|
363
|
+
* The module's current lifecycle state, or `undefined` when the module is not
|
|
364
|
+
* composed (or no graph has been composed on this instance). See the state
|
|
365
|
+
* machine in the file header.
|
|
366
|
+
*/
|
|
367
|
+
declare function getModuleState(fastify: FastifyInstance, name: string): ModuleState | undefined;
|
|
368
|
+
/**
|
|
369
|
+
* The `ResourceDefinition`s module `name` mounted, in its declared order — for building that
|
|
370
|
+
* module's MCP tools or docs after boot. Throws when `name` is not a composed module (a typo would
|
|
371
|
+
* otherwise read as "no resources"), and when called before `registerResources` has published the
|
|
372
|
+
* descriptors. A resource declaring `skipRegistry` is absent, as from every introspection surface.
|
|
373
|
+
*/
|
|
374
|
+
declare function getModuleResources(fastify: FastifyInstance, name: string): ResourceDefinition<unknown>[];
|
|
375
|
+
//#endregion
|
|
376
|
+
//#region src/factory/module/index.d.ts
|
|
377
|
+
/**
|
|
378
|
+
* Identity helper for authoring a typed module — mirrors `defineResource`.
|
|
379
|
+
* Gives inference + a single obvious construction site; does no work.
|
|
380
|
+
*
|
|
381
|
+
* Everything is inferred: the export from `bootstrap`'s return, the port types from
|
|
382
|
+
* `requires` (declare `requires` BEFORE the phases that read `ports`):
|
|
383
|
+
*
|
|
384
|
+
* ```ts
|
|
385
|
+
* defineModule({
|
|
386
|
+
* name: "accounting",
|
|
387
|
+
* requires: { ports: ["outbox"], optionalPorts: ["calendar"] },
|
|
388
|
+
* bootstrap: (f, { ports }) => createAccountingEngine(ports.outbox, ports.calendar),
|
|
389
|
+
* });
|
|
390
|
+
* ```
|
|
391
|
+
*/
|
|
392
|
+
declare function defineModule<TExports = unknown, const TPorts extends PortName = never, const TOptionalPorts extends PortName = never>(module: ArcModule<TExports, TPorts, TOptionalPorts>): ArcModule<TExports, TPorts, TOptionalPorts>;
|
|
393
|
+
/**
|
|
394
|
+
* Typed accessor for a module's public export (its `bootstrap` return value),
|
|
395
|
+
* recorded at `fastify.arc.modules[name]`.
|
|
396
|
+
*
|
|
397
|
+
* Throwing, in line with the fail-fast contract (and `requireOrgId`-style
|
|
398
|
+
* accessors): a missing entry means the module either isn't composed, is
|
|
399
|
+
* composed AFTER the caller (list order = init order), or returned nothing —
|
|
400
|
+
* all wiring bugs that must surface at boot, not as `undefined` downstream.
|
|
401
|
+
*
|
|
402
|
+
* The type parameter is an assertion, not a proof. Two ways to type it:
|
|
403
|
+
* - augment `ArcModuleRegistry` once — then the name alone infers the type:
|
|
404
|
+
* `getModuleExports(f, "accounting")` → `AccountingEngine`.
|
|
405
|
+
* - or pass it inline: `getModuleExports<AccountingEngine>(f, "accounting")`.
|
|
406
|
+
*
|
|
407
|
+
* Siblings, for the two shapes this one is wrong for:
|
|
408
|
+
* - `getOptionalModuleExports` — the module is genuinely OPTIONAL.
|
|
409
|
+
* - `lazyModuleExports` / `lazyRequiredModuleExports` — the read happens at
|
|
410
|
+
* composition time, where boot order decides the answer.
|
|
411
|
+
*/
|
|
412
|
+
declare function getModuleExports<K extends keyof ArcModuleRegistry>(fastify: FastifyInstance, name: K): ArcModuleRegistry[K];
|
|
413
|
+
declare function getModuleExports<TExports = unknown>(fastify: FastifyInstance, name: string): TExports;
|
|
414
|
+
/**
|
|
415
|
+
* Non-throwing sibling of `getModuleExports`: `undefined` when the module is
|
|
416
|
+
* not composed (or has not bootstrapped yet).
|
|
417
|
+
*
|
|
418
|
+
* Exists because OPTIONAL sibling modules are a first-class composition shape —
|
|
419
|
+
* a deployment that turns `inventory` off still sells services, so its POS
|
|
420
|
+
* module must ask "is inventory here?" rather than fail-fast. Hosts were
|
|
421
|
+
* spelling that question as
|
|
422
|
+
*
|
|
423
|
+
* ```ts
|
|
424
|
+
* (fastify as { arc?: { modules?: Record<string, unknown> } })
|
|
425
|
+
* .arc?.modules?.inventory;
|
|
426
|
+
* ```
|
|
427
|
+
*
|
|
428
|
+
* — a double cast that (a) defeats `ArcModuleRegistry` inference, (b) silently
|
|
429
|
+
* survives a typo in the module name, and (c) is impossible to grep for. Use
|
|
430
|
+
* `getModuleExports` when the dependency is REQUIRED (boot must fail), this
|
|
431
|
+
* when it is genuinely optional.
|
|
432
|
+
*
|
|
433
|
+
* Prefer `lazyModuleExports` whenever the read happens at COMPOSITION time —
|
|
434
|
+
* see its doc for why a value read once can latch `undefined` forever.
|
|
435
|
+
*/
|
|
436
|
+
declare function getOptionalModuleExports<K extends keyof ArcModuleRegistry>(fastify: FastifyInstance, name: K): ArcModuleRegistry[K] | undefined;
|
|
437
|
+
declare function getOptionalModuleExports<TExports = unknown>(fastify: FastifyInstance, name: string): TExports | undefined;
|
|
438
|
+
/**
|
|
439
|
+
* Is a module's public export recorded yet? The predicate form of
|
|
440
|
+
* `getOptionalModuleExports`, for readiness gates (`ready: () => ...`) that
|
|
441
|
+
* should not have to reason about falsy-but-present exports.
|
|
442
|
+
*/
|
|
443
|
+
declare function hasModuleExports(fastify: FastifyInstance, name: string): boolean;
|
|
444
|
+
/**
|
|
445
|
+
* A DEFERRED reader of a sibling module's export: returns a getter that reads
|
|
446
|
+
* the registry at CALL time, not now.
|
|
447
|
+
*
|
|
448
|
+
* ── Why this exists (the bug it removes) ─────────────────────────────────────
|
|
449
|
+
*
|
|
450
|
+
* Module composition runs bootstraps in dependency/list order, but a lot of
|
|
451
|
+
* wiring is *registered* earlier than it *runs*: an `eventHandlers` factory, a
|
|
452
|
+
* bridge accessor handed to another module, a hook added during bootstrap and
|
|
453
|
+
* fired per request. Such a factory can execute BEFORE the sibling it needs has
|
|
454
|
+
* bootstrapped — so a sibling engine captured into a local at that moment is
|
|
455
|
+
* `undefined`, and stays `undefined` for the life of the process even though the
|
|
456
|
+
* sibling came up milliseconds later.
|
|
457
|
+
*
|
|
458
|
+
* That failure is SILENT by construction: the consumer sees a null bridge and
|
|
459
|
+
* treats it as "this deployment has no inventory / no revenue engine", which is
|
|
460
|
+
* a legitimate configuration. Real cost in this codebase: orders were created
|
|
461
|
+
* and never payment-confirmed (no entitlement, no card, no door) and nothing
|
|
462
|
+
* errored anywhere.
|
|
463
|
+
*
|
|
464
|
+
* The getter therefore:
|
|
465
|
+
* - re-reads while the module is ABSENT, so boot order cannot matter;
|
|
466
|
+
* - memoizes the FIRST resolved value, so the steady-state read is a closure
|
|
467
|
+
* variable rather than a registry lookup per request;
|
|
468
|
+
* - never memoizes absence — that is precisely the latch this replaces.
|
|
469
|
+
*
|
|
470
|
+
* ```ts
|
|
471
|
+
* const inventory = lazyModuleExports<FlowEngine>(fastify, "inventory");
|
|
472
|
+
* return {
|
|
473
|
+
* flowBridge: () => (inventory() ? createFlowEngineBridge({ getFlowEngine: () => inventory()! }) : null),
|
|
474
|
+
* ready: () => inventory() !== undefined,
|
|
475
|
+
* };
|
|
476
|
+
* ```
|
|
477
|
+
*/
|
|
478
|
+
declare function lazyModuleExports<K extends keyof ArcModuleRegistry>(fastify: FastifyInstance, name: K): () => ArcModuleRegistry[K] | undefined;
|
|
479
|
+
declare function lazyModuleExports<TExports = unknown>(fastify: FastifyInstance, name: string): () => TExports | undefined;
|
|
480
|
+
/**
|
|
481
|
+
* Required counterpart of `lazyModuleExports`: defers the read, then throws
|
|
482
|
+
* `getModuleExports`' error if the module is still absent at first use.
|
|
483
|
+
*
|
|
484
|
+
* The pair matters because "required" and "readable now" are different
|
|
485
|
+
* questions. A hook registered at bootstrap that needs the `order` engine at
|
|
486
|
+
* REQUEST time is a hard dependency, but reading it eagerly turns a correct
|
|
487
|
+
* composition into a boot crash purely because of list order. Deferring keeps
|
|
488
|
+
* the fail-fast guarantee and moves it to the first moment the answer is
|
|
489
|
+
* actually needed.
|
|
490
|
+
*
|
|
491
|
+
* Deferred does NOT mean unvalidated: a lazily-required module is still a
|
|
492
|
+
* HARD dependency, so PRESENCE is checked eagerly. When the composed module
|
|
493
|
+
* graph is known (any `createApp`/`registerResources` boot — the normal
|
|
494
|
+
* case), a name that is not in the graph throws HERE, at composition time,
|
|
495
|
+
* instead of surviving startup and failing on the first request or event.
|
|
496
|
+
* Only the EXPORT read (does bootstrap's return value exist yet?) is
|
|
497
|
+
* deferred to first call.
|
|
498
|
+
*
|
|
499
|
+
* Convention for hard sibling access: also declare the target in the
|
|
500
|
+
* consumer's `dependsOn`. That orders composition (the sibling's bootstrap
|
|
501
|
+
* runs first), while this accessor merely defers the read — the two are
|
|
502
|
+
* complementary, not alternatives:
|
|
503
|
+
* - hard dependency, read during bootstrap → `dependsOn` + `getModuleExports`
|
|
504
|
+
* - hard dependency, read at request/event time → `dependsOn` + this
|
|
505
|
+
* - optional integration → `lazyModuleExports` (no `dependsOn` needed)
|
|
506
|
+
*/
|
|
507
|
+
declare function lazyRequiredModuleExports<K extends keyof ArcModuleRegistry>(fastify: FastifyInstance, name: K): () => ArcModuleRegistry[K];
|
|
508
|
+
declare function lazyRequiredModuleExports<TExports = unknown>(fastify: FastifyInstance, name: string): () => TExports;
|
|
509
|
+
//#endregion
|
|
510
|
+
export { verifyModuleGraph as $, AsyncApiCatalogEntry as A, ModuleGraphMode as B, planModules as C, ModuleExtension as D, subscribeModuleEventHandlers as E, DurabilityFacts as F, activateBridges as G, ModuleGraphOptions as H, HandlerDurabilityFact as I, crudEventsOf as J, analyzeModuleGraph as K, ModuleGraph as L, toAsyncApi as M, CrudSurface as N, extendModule as O, DerivedPublishes as P, verifyEventDurability as Q, ModuleGraphAnalysis as R, compositionProblems as S, orderModules as T, ModuleKind as U, ModuleGraphNode as V, SkippedBridge as W, eventTopology as X, dependentsOf as Y, renderModuleGraph as Z, ClosureNode as _, lazyModuleExports as a, PlanModulesOptions as b, getModuleResources as c, resolveContribution as d, resolveModule as f, withRelayNudge as g, createRelayNudge as h, hasModuleExports as i, AsyncApiInfo as j, collectModuleWorkflows as k, getModuleState as l, RelayOption as m, getModuleExports as n, lazyRequiredModuleExports as o, RelayNudge as p, buildModuleGraph as q, getOptionalModuleExports as r, ModuleState as s, defineModule as t, hasModule as u, CompositionProblem as v, resolveModuleClosure as w, assertComposable as x, ModulePlan as y, ModuleGraphIssue as z };
|