@classytic/arc 2.30.0 → 2.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +7 -0
- package/TRADEMARK.md +22 -0
- package/dist/{BaseController-B5DwufbB.mjs → BaseController-Dk34dxhI.mjs} +21 -19
- package/dist/{EventTransport-QmY7A258.d.mts → EventTransport-2uVV34WU.d.mts} +1 -0
- package/dist/{EventTransport-C6YA8xY9.mjs → EventTransport-BV10D0oG.mjs} +1 -0
- package/dist/{HookSystem-WkIougo6.mjs → HookSystem-vimw5D7Z.mjs} +2 -1
- package/dist/{QueryCache-DOMT_iq7.d.mts → QueryCache-DFA-QrU9.d.mts} +2 -1
- package/dist/{ResourceRegistry-y9Hnypus.mjs → ResourceRegistry-BVr7PgA0.mjs} +18 -15
- package/dist/{actionPermissions-CAphcmUG.mjs → actionPermissions-Dti7ebyv.mjs} +1 -0
- package/dist/audit/index.d.mts +3 -2
- package/dist/audit/index.mjs +2 -1
- package/dist/auth/audit.d.mts +1 -0
- package/dist/auth/audit.mjs +1 -0
- package/dist/auth/index.d.mts +5 -4
- package/dist/auth/index.mjs +11 -9
- package/dist/auth/redis-session.d.mts +2 -1
- package/dist/auth/redis-session.mjs +1 -0
- package/dist/{applyPermissionResult-Cf6zUCvb.mjs → authorizationDecision-__T3EJDA.mjs} +19 -10
- package/dist/{buildHandler-BYS3Vkfz.mjs → buildHandler-Dn7rzUJo.mjs} +6 -4
- package/dist/cache/index.d.mts +4 -3
- package/dist/cache/index.mjs +4 -3
- package/dist/{caching-_NJeDd1_.mjs → caching-DFJqHyFs.mjs} +2 -1
- package/dist/cleanup/index.d.mts +39 -16
- package/dist/cleanup/index.mjs +50 -38
- package/dist/cli/commands/describe.d.mts +2 -1
- package/dist/cli/commands/describe.mjs +4 -5
- package/dist/cli/commands/docs.d.mts +1 -0
- package/dist/cli/commands/docs.mjs +3 -2
- package/dist/cli/commands/doctor.d.mts +1 -0
- package/dist/cli/commands/doctor.mjs +1 -0
- package/dist/cli/commands/generate.d.mts +2 -1
- package/dist/cli/commands/generate.mjs +2 -1
- package/dist/cli/commands/init.d.mts +2 -1
- package/dist/cli/commands/init.mjs +2 -1
- package/dist/cli/commands/introspect.d.mts +1 -0
- package/dist/cli/commands/introspect.mjs +2 -1
- package/dist/cli/index.d.mts +3 -2
- package/dist/cli/index.mjs +3 -2
- package/dist/{constants-DNre0wRg.mjs → constants-J99LGTJI.mjs} +1 -0
- package/dist/context/index.d.mts +1 -0
- package/dist/context/index.mjs +3 -2
- package/dist/core/index.d.mts +3 -2
- package/dist/core/index.mjs +7 -6
- package/dist/{core-poalJLvp.mjs → core-BwwmNSp7.mjs} +3 -2
- package/dist/{createActionRouter-BxuywVRB.mjs → createActionRouter-DkJZWo0m.mjs} +14 -10
- package/dist/{createAggregationRouter-BiY-lGdY.mjs → createAggregationRouter-B1exOVD8.mjs} +10 -7
- package/dist/{createApp-CXrKFciH.mjs → createApp-Bv0m-Q6_.mjs} +625 -229
- package/dist/{defineAggregation-ufWjUwml.mjs → defineAggregation-gX4No1gt.mjs} +1 -0
- package/dist/{defineResource-CxWqDCAy.mjs → defineResource-XFPPUu2c.mjs} +84 -50
- package/dist/discovery/index.d.mts +1 -0
- package/dist/discovery/index.mjs +1 -0
- package/dist/docs/index.d.mts +3 -2
- package/dist/docs/index.mjs +3 -2
- package/dist/{elevation-C9s5hFP_.d.mts → elevation-BXCfVcNG.d.mts} +1 -0
- package/dist/{elevation-CIz1GjGm.mjs → elevation-DNXXxgjl.mjs} +4 -3
- package/dist/encryption/index.d.mts +2 -1
- package/dist/encryption/index.mjs +5 -3
- package/dist/{errorHandler-Bq2OeEQL.mjs → errorHandler-B2AZUJUj.mjs} +3 -2
- package/dist/{errorHandler-C6yv4ZTW.d.mts → errorHandler-CpYUJmPA.d.mts} +1 -0
- package/dist/{errors-DHcHVAgk.d.mts → errors-BGdVwP25.d.mts} +1 -0
- package/dist/{errors-DkO8Nk6-.mjs → errors-Bh1KK5ps.mjs} +1 -0
- package/dist/{eventPlugin-D2NNR4py.mjs → eventPlugin-Dk_TyXeE.mjs} +8 -6
- package/dist/{eventPlugin-Bg3cP2_u.d.mts → eventPlugin-GF5nnBIq.d.mts} +2 -1
- package/dist/events/index.d.mts +112 -44
- package/dist/events/index.mjs +177 -141
- package/dist/events/transports/redis-stream-entry.d.mts +2 -1
- package/dist/events/transports/redis-stream-entry.mjs +14 -9
- package/dist/events/transports/redis.d.mts +2 -1
- package/dist/events/transports/redis.mjs +1 -0
- package/dist/{externalPaths-BE6wFpYv.d.mts → externalPaths-CmGOxOtD.d.mts} +1 -0
- package/dist/factory/index.d.mts +9 -5
- package/dist/factory/index.mjs +131 -7
- package/dist/fastify-augmentation-BppG5bMT.d.mts +179 -0
- package/dist/{fields-CQ_7KQWw.mjs → fields-DEi65pGj.mjs} +6 -10
- package/dist/{fields-D3lhgzhD.d.mts → fields-I_EeRWND.d.mts} +1 -0
- package/dist/{generate-D0wZupBg.mjs → generate-CRSG0jTv.mjs} +2 -1
- package/dist/{generate-BnsL9GBm.d.mts → generate-DCGuEbqI.d.mts} +1 -0
- package/dist/{headers-BvlQSDMB.mjs → headers-BXjQYbeC.mjs} +2 -1
- package/dist/{health-CB_m4S32.mjs → health-5XnTa2uo.mjs} +1 -0
- package/dist/hooks/index.d.mts +2 -1
- package/dist/hooks/index.mjs +2 -1
- package/dist/idempotency/index.d.mts +3 -2
- package/dist/idempotency/index.mjs +8 -5
- package/dist/idempotency/redis.d.mts +2 -1
- package/dist/idempotency/redis.mjs +1 -0
- package/dist/{index-CG4yqMDB.d.mts → index-C-481Zf2.d.mts} +74 -18
- package/dist/{index-Q5gzEIWY.d.mts → index-CpzxqePp.d.mts} +107 -32
- package/dist/{index-Cx7bro4R.d.mts → index-DXlHwvuE.d.mts} +5 -4
- package/dist/index-ZWhLTp_s.d.mts +290 -0
- package/dist/{index-Ch16aAah.d.mts → index-zq6VrjaB.d.mts} +122 -15
- package/dist/index.d.mts +9 -8
- package/dist/index.mjs +11 -10
- package/dist/{init-tlRSt667.mjs → init-BbfP8aky.mjs} +25 -27
- package/dist/{init-BPEu8cs-.d.mts → init-Cscs4lab.d.mts} +1 -0
- package/dist/integrations/event-gateway.d.mts +3 -2
- package/dist/integrations/event-gateway.mjs +2 -1
- package/dist/integrations/index.d.mts +4 -3
- package/dist/integrations/index.mjs +1 -0
- package/dist/integrations/jobs/index.d.mts +2 -1
- package/dist/integrations/jobs/index.mjs +109 -33
- package/dist/integrations/mcp/index.d.mts +6 -6
- package/dist/integrations/mcp/index.mjs +2 -1
- package/dist/integrations/mcp/testing.d.mts +3 -2
- package/dist/integrations/mcp/testing.mjs +2 -2
- package/dist/integrations/streamline.d.mts +1 -0
- package/dist/integrations/streamline.mjs +3 -2
- package/dist/integrations/webhooks.d.mts +1 -0
- package/dist/integrations/webhooks.mjs +1 -0
- package/dist/integrations/websocket-pushref-redis.d.mts +2 -1
- package/dist/integrations/websocket-pushref-redis.mjs +1 -0
- package/dist/integrations/websocket-redis.d.mts +2 -1
- package/dist/integrations/websocket-redis.mjs +1 -0
- package/dist/integrations/websocket.d.mts +3 -2
- package/dist/integrations/websocket.mjs +38 -34
- package/dist/{interface-BGZCzOGL.d.mts → interface-BOk3YnTz.d.mts} +1 -0
- package/dist/{interface-n5hpKg1d.mjs → interface-BP4IJCBO.mjs} +1 -0
- package/dist/{interface-Uk8ONJv7.d.mts → interface-DEWNOMza.d.mts} +1 -0
- package/dist/{jsonBody-BlzAoGCe.mjs → jsonBody-DDSR2HFl.mjs} +2 -1
- package/dist/{keys-Cd316u_y.mjs → keys-B-HBTGXl.mjs} +1 -0
- package/dist/{loadResources-DpU8pfjV.mjs → loadResources-DisEAmkm.mjs} +4 -2
- package/dist/{loadResourcesFromEntry-kvGT6EcO.mjs → loadResourcesFromEntry-D1MJp13f.mjs} +2 -1
- package/dist/logger/index.d.mts +1 -0
- package/dist/logger/index.mjs +1 -0
- package/dist/{mcpPlugin-nRzm5g2s.mjs → mcpPlugin-CpfVpKHE.mjs} +38 -38
- package/dist/{memory-CmnzXE5Z.mjs → memory-DsuWnj4T.mjs} +5 -4
- package/dist/{metrics-fdxI5mn_.mjs → metrics-DdQL8syd.mjs} +2 -1
- package/dist/middleware/index.d.mts +2 -1
- package/dist/middleware/index.mjs +3 -2
- package/dist/migrations/index.d.mts +1 -0
- package/dist/migrations/index.mjs +3 -2
- package/dist/module-Br81am6m.mjs +78 -0
- package/dist/{multipartBody-D0eBvkeq.mjs → multipartBody-BnkBLN7v.mjs} +3 -2
- package/dist/{openapi-B8Vkbxbn.mjs → openapi-DIRzvxC0.mjs} +6 -5
- package/dist/outbox-admin/index.d.mts +85 -0
- package/dist/outbox-admin/index.mjs +115 -0
- package/dist/permissions/index.d.mts +5 -4
- package/dist/permissions/index.mjs +6 -5
- package/dist/{permissions-Bfu_8y1U.mjs → permissions-Dl_m0NCe.mjs} +308 -42
- package/dist/{pipe-BOLmGIxa.mjs → pipe-ELHCP3zj.mjs} +3 -4
- package/dist/pipeline/index.d.mts +2 -1
- package/dist/pipeline/index.mjs +2 -1
- package/dist/{pipeline-BJnpkY9i.mjs → pipeline-CPA-jx0M.mjs} +17 -14
- package/dist/plugins/index.d.mts +8 -7
- package/dist/plugins/index.mjs +16 -15
- package/dist/plugins/response-cache.d.mts +1 -0
- package/dist/plugins/response-cache.mjs +2 -1
- package/dist/plugins/tracing-entry.d.mts +2 -1
- package/dist/plugins/tracing-entry.mjs +2 -1
- package/dist/{pluralize-BhrgwZb9.mjs → pluralize-C2ZkKbsn.mjs} +1 -0
- package/dist/{preloadResources-DSY5HGpS.mjs → preloadResources-CDs87fTw.mjs} +1 -0
- package/dist/{preloadResources-DCfa2egz.d.mts → preloadResources-T1hmlTEZ.d.mts} +117 -12
- package/dist/presets/filesUpload.d.mts +6 -5
- package/dist/presets/filesUpload.mjs +10 -12
- package/dist/presets/index.d.mts +3 -2
- package/dist/presets/index.mjs +2 -1
- package/dist/presets/multiTenant.d.mts +2 -1
- package/dist/presets/multiTenant.mjs +3 -2
- package/dist/presets/search.d.mts +3 -2
- package/dist/presets/search.mjs +2 -1
- package/dist/{presets-CJOEXLuk.mjs → presets-Dntd_pUO.mjs} +6 -4
- package/dist/{projection-UBDgfMwu.mjs → projection-CjHhM5W1.mjs} +2 -1
- package/dist/{pushref-registry-BbcnpNTm.d.mts → pushref-registry-Dov9l4qE.d.mts} +1 -0
- package/dist/{queryCachePlugin-br4otiqF.d.mts → queryCachePlugin-BzqxconG.d.mts} +3 -2
- package/dist/{queryCachePlugin-DSGuSVLW.mjs → queryCachePlugin-Dhps-Ldt.mjs} +6 -5
- package/dist/{rateLimit-DrED-C4v.mjs → rateLimit-C7mmAGs3.mjs} +7 -3
- package/dist/{rateLimitKey-BoWRH3e7.mjs → rateLimitKey-CccEFBfk.mjs} +1 -0
- package/dist/{realtime-B9nmIY5V.mjs → realtime-DVvVZZFz.mjs} +20 -9
- package/dist/{redis-UDtLaNj6.d.mts → redis-CduhKsJi.d.mts} +2 -1
- package/dist/{redis-stream-uIaauNpZ.d.mts → redis-stream-qN6A-RFv.d.mts} +2 -1
- package/dist/{registerRoute-JkxIEBJq.mjs → registerRoute-B_QrjYZS.mjs} +10 -7
- package/dist/registry/index.d.mts +3 -2
- package/dist/registry/index.mjs +3 -2
- package/dist/{registry-BYXUUg21.mjs → registry-DqUmzA9W.mjs} +2 -1
- package/dist/{renewingLease-3cuQH7h8.mjs → renewingLease-BpP9wwj7.mjs} +1 -0
- package/dist/{replyHelpers-67tRawQZ.mjs → replyHelpers-DS-P0b32.mjs} +2 -1
- package/dist/{repositoryFilter-Dz8k3S4P.mjs → repositoryFilter-DotlxG3L.mjs} +1 -0
- package/dist/{requestContext-MrlJwECf.mjs → requestContext-B6vQF-sy.mjs} +1 -0
- package/dist/{rolldown-runtime-8H4AJuhK.mjs → rolldown-runtime-BhflRrBs.mjs} +1 -0
- package/dist/{schedules-CjOd2MG9.mjs → schedules-C2Q3uv2d.mjs} +3 -2
- package/dist/{schemaConverter-DJvodiHj.mjs → schemaConverter-Crjvczi_.mjs} +70 -17
- package/dist/{schemaIR-Ca7ySNPx.mjs → schemaIR-CnyKK_1j.mjs} +2 -1
- package/dist/schemas/index.d.mts +1 -0
- package/dist/schemas/index.mjs +1 -0
- package/dist/scim/index.d.mts +1 -0
- package/dist/scim/index.mjs +2 -1
- package/dist/scope/index.d.mts +3 -2
- package/dist/scope/index.mjs +5 -4
- package/dist/{scope-DfaPntpo.mjs → scope-afz_Ieek.mjs} +4 -3
- package/dist/{sessionManager-BHOM3N_0.d.mts → sessionManager-qimlKV0P.d.mts} +1 -0
- package/dist/{simpleEqualityMatcher-Cg05HPsn.mjs → simpleEqualityMatcher-C4KiMWUa.mjs} +1 -0
- package/dist/{sse-BQ1w0dfl.mjs → sse-B9P4Y-UI.mjs} +7 -5
- package/dist/{sseStream-BQ7Qaynp.mjs → sseStream-B3zb_d1h.mjs} +2 -1
- package/dist/{storage-DLUZ04kK.d.mts → storage-Cx9Sz3Ou.d.mts} +1 -0
- package/dist/{store-helpers-DY6xq4sM.mjs → store-helpers-DmEMHlPQ.mjs} +1 -0
- package/dist/{streaming-BQcW6_Kq.mjs → streaming-DPZdQmDz.mjs} +1 -0
- package/dist/{subscribe-helpers-DfzsivM6.mjs → subscribe-helpers-sp5xTDVA.mjs} +2 -1
- package/dist/sync/changelog.d.mts +1 -0
- package/dist/sync/changelog.mjs +1 -0
- package/dist/testing/cleanupStoreContract.d.mts +2 -1
- package/dist/testing/cleanupStoreContract.mjs +10 -5
- package/dist/testing/index.d.mts +166 -12
- package/dist/testing/index.mjs +315 -43
- package/dist/testing/outboxStoreContract.d.mts +12 -2
- package/dist/testing/outboxStoreContract.mjs +110 -20
- package/dist/testing/storageContract.d.mts +2 -1
- package/dist/testing/storageContract.mjs +11 -5
- package/dist/{tracing-CsGKQJGg.d.mts → tracing-Dro5eH6j.d.mts} +1 -0
- package/dist/{transactionContext-PNdoyLLm.mjs → transactionContext-BvLKvOIL.mjs} +1 -0
- package/dist/{typeGuards-C9KXUly6.mjs → typeGuards-B_5-hKjJ.mjs} +1 -0
- package/dist/types/index.d.mts +6 -5
- package/dist/types/index.mjs +1 -0
- package/dist/types/storage.d.mts +2 -1
- package/dist/types/storage.mjs +1 -0
- package/dist/{types-ChvvVNP8.d.mts → types-B7XeLEgK.d.mts} +34 -2
- package/dist/{types-Cc91nXuA.d.mts → types-ByHn9rEO.d.mts} +1 -0
- package/dist/{types-C_ZZRcD6.d.mts → types-C4QE8qnm.d.mts} +1 -0
- package/dist/{types-D_n8L6VY.d.mts → types-CT5vu6M0.d.mts} +132 -17
- package/dist/{types-DjC-KUCz.d.mts → types-ChuShpCP.d.mts} +1 -0
- package/dist/{types-Bmmn-fO0.d.mts → types-CwcUQ610.d.mts} +2 -6
- package/dist/{types-CSyCxl2V.mjs → types-DXYX7dIR.mjs} +4 -3
- package/dist/usage/index.d.mts +3 -2
- package/dist/usage/index.mjs +0 -0
- package/dist/{userHelpers-Cg_y3fBz.mjs → userHelpers-BNsOXzOd.mjs} +1 -0
- package/dist/utils/index.d.mts +16 -7
- package/dist/utils/index.mjs +10 -9
- package/dist/{utils-taUVD4p3.mjs → utils-BtOha_Sp.mjs} +3 -2
- package/dist/{validate-Bk44F2yT.mjs → validate-PMCPR9El.mjs} +2 -1
- package/dist/{versioning-gKWyryT3.mjs → versioning-CKv2jz_U.mjs} +4 -3
- package/dist/{versioning-DXgY5BUm.d.mts → versioning-D_rhHfZm.d.mts} +5 -2
- package/dist/{websocket-_Pd0CgR0.d.mts → websocket-BOXVggMf.d.mts} +2 -1
- package/package.json +557 -539
- package/skills/arc/SKILL.md +22 -8
- package/skills/arc/references/api-reference.md +4 -0
- package/skills/arc/references/auth.md +3 -0
- package/skills/arc/references/integrations.md +33 -0
- package/skills/arc/references/mcp.md +6 -7
- package/skills/arc/references/production.md +24 -25
- package/skills/arc-code-review/references/anti-patterns.md +3 -3
- package/dist/fastify-augmentation-0WhPnUH7.d.mts +0 -76
- package/dist/index-CCzVR-N3.d.mts +0 -107
- package/dist/module-_-M7C5ES.mjs +0 -29
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import "./
|
|
5
|
-
import
|
|
6
|
-
import { n as
|
|
7
|
-
import { n as
|
|
1
|
+
|
|
2
|
+
import { a as QueryCacheConfig } from "./QueryCache-DFA-QrU9.mjs";
|
|
3
|
+
import { P as ArcHeaders, i as RequestScope } from "./types-ChuShpCP.mjs";
|
|
4
|
+
import { a as UserBase, l as AnyRecord, r as PermissionCheck } from "./types-B7XeLEgK.mjs";
|
|
5
|
+
import "./elevation-BXCfVcNG.mjs";
|
|
6
|
+
import { n as FieldPermissionMap } from "./fields-I_EeRWND.mjs";
|
|
7
|
+
import { n as EncryptionDirective } from "./types-ByHn9rEO.mjs";
|
|
8
|
+
import { n as DomainEvent } from "./EventTransport-2uVV34WU.mjs";
|
|
8
9
|
import { Filter } from "@classytic/repo-core/filter";
|
|
9
10
|
import { KeysetPaginationResult, OffsetPaginationResult } from "@classytic/repo-core/pagination";
|
|
10
11
|
import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest, RouteHandlerMethod, RouteHandlerMethod as RouteHandlerMethod$1 } from "fastify";
|
|
@@ -1238,11 +1239,27 @@ interface AuthPluginOptions {
|
|
|
1238
1239
|
strictTokenType?: boolean;
|
|
1239
1240
|
}
|
|
1240
1241
|
//#endregion
|
|
1242
|
+
//#region src/core/middlewares/rateLimit.d.ts
|
|
1243
|
+
/**
|
|
1244
|
+
* Per-route CORS override, read by `@fastify/cors` off `routeOptions.config.cors`.
|
|
1245
|
+
*
|
|
1246
|
+
* The app-wide policy cannot serve both an API and public assets: an API wants
|
|
1247
|
+
* `credentials: true` with a pinned origin list, while a public asset wants
|
|
1248
|
+
* `origin: "*"` — and `*` with credentials is forbidden by the CORS spec (arc
|
|
1249
|
+
* throws at boot on that combination). Per-route is the granularity that
|
|
1250
|
+
* resolves it. `false` disables CORS for the route entirely.
|
|
1251
|
+
*
|
|
1252
|
+
* Arc does not interpret the value; `@fastify/cors` owns the semantics. Typed
|
|
1253
|
+
* loosely on purpose so a host is never blocked by arc lagging the plugin's
|
|
1254
|
+
* option surface.
|
|
1255
|
+
*/
|
|
1256
|
+
type RouteCorsConfig = Record<string, unknown> | false;
|
|
1257
|
+
//#endregion
|
|
1241
1258
|
//#region src/types/handlers.d.ts
|
|
1242
1259
|
/**
|
|
1243
1260
|
* Minimal server accessor — exposes safe, read-only server decorators.
|
|
1244
1261
|
* Allows controller handlers to publish events, log, and audit
|
|
1245
|
-
* without switching to `
|
|
1262
|
+
* without switching to `rawHandler`.
|
|
1246
1263
|
*/
|
|
1247
1264
|
interface ServerAccessor {
|
|
1248
1265
|
/** Event bus — publish domain events from any handler */
|
|
@@ -1396,7 +1413,7 @@ interface IRequestContext<TBody = unknown, TParams extends Record<string, string
|
|
|
1396
1413
|
metadata?: TMetadata;
|
|
1397
1414
|
/**
|
|
1398
1415
|
* Fastify server accessor — publish events, log, and audit
|
|
1399
|
-
* from any handler without switching to `
|
|
1416
|
+
* from any handler without switching to `rawHandler`.
|
|
1400
1417
|
*
|
|
1401
1418
|
* @example
|
|
1402
1419
|
* ```typescript
|
|
@@ -1431,7 +1448,7 @@ interface IControllerResponse<T = unknown> {
|
|
|
1431
1448
|
* Controller handler — Arc's standard pattern.
|
|
1432
1449
|
*
|
|
1433
1450
|
* Receives a request context object, returns IControllerResponse.
|
|
1434
|
-
* Use with `
|
|
1451
|
+
* Use with `handler` in routes.
|
|
1435
1452
|
*
|
|
1436
1453
|
* **Generic parameters:**
|
|
1437
1454
|
* - `TResponse` — shape of `IControllerResponse.data` (default: `unknown`)
|
|
@@ -1468,7 +1485,6 @@ interface IControllerResponse<T = unknown> {
|
|
|
1468
1485
|
* path: '/products',
|
|
1469
1486
|
* handler: createProduct,
|
|
1470
1487
|
* permissions: requireAuth(),
|
|
1471
|
-
* raw: false, // Arc wraps this into Fastify handler
|
|
1472
1488
|
* }]
|
|
1473
1489
|
* ```
|
|
1474
1490
|
*/
|
|
@@ -1477,7 +1493,7 @@ type ControllerHandler<TResponse = unknown, TBody = unknown, TParams extends Rec
|
|
|
1477
1493
|
* Fastify native handler
|
|
1478
1494
|
*
|
|
1479
1495
|
* Standard Fastify request/reply pattern.
|
|
1480
|
-
* Use with `
|
|
1496
|
+
* Use with `rawHandler` in routes.
|
|
1481
1497
|
*
|
|
1482
1498
|
* @example
|
|
1483
1499
|
* ```typescript
|
|
@@ -1490,12 +1506,31 @@ type ControllerHandler<TResponse = unknown, TBody = unknown, TParams extends Rec
|
|
|
1490
1506
|
* routes: [{
|
|
1491
1507
|
* method: 'GET',
|
|
1492
1508
|
* path: '/files/:id/download',
|
|
1493
|
-
*
|
|
1509
|
+
* rawHandler: downloadFile,
|
|
1494
1510
|
* permissions: requireAuth(),
|
|
1495
|
-
* raw: true, // Use as-is, no wrapping
|
|
1496
1511
|
* }]
|
|
1497
1512
|
* ```
|
|
1498
1513
|
*/
|
|
1514
|
+
type RawRouteHandler = {
|
|
1515
|
+
/**
|
|
1516
|
+
* Fastify-native route handler — the type behind `RouteDefinition.rawHandler`.
|
|
1517
|
+
*
|
|
1518
|
+
* Declared with METHOD syntax and read back through an indexed access, which
|
|
1519
|
+
* buys two properties a plain arrow alias can't have at once:
|
|
1520
|
+
*
|
|
1521
|
+
* - **Bivariant parameters.** `strictFunctionTypes` exempts method
|
|
1522
|
+
* declarations, so a handler annotated `FastifyRequest<{ Body: CreateBody }>`
|
|
1523
|
+
* assigns without a cast. Fastify's own `RouteHandlerMethod` is an arrow
|
|
1524
|
+
* alias, so it rejects those — hosts used to write `as any`.
|
|
1525
|
+
* - **One call signature.** TypeScript contextually types parameters only
|
|
1526
|
+
* when a single constituent is callable, so inline
|
|
1527
|
+
* `rawHandler: async (request, reply) => …` infers instead of reporting
|
|
1528
|
+
* TS7006.
|
|
1529
|
+
*
|
|
1530
|
+
* The runtime always passes the real `(request, reply)` pair.
|
|
1531
|
+
*/
|
|
1532
|
+
handler(this: FastifyInstance, request: FastifyRequest, reply: FastifyReply): unknown;
|
|
1533
|
+
}["handler"];
|
|
1499
1534
|
type FastifyHandler<RouteGeneric extends Record<string, unknown> = Record<string, unknown>> = (request: FastifyRequest<RouteGeneric>, reply: FastifyReply) => Promise<unknown> | unknown;
|
|
1500
1535
|
/**
|
|
1501
1536
|
* Union type for route handlers
|
|
@@ -1574,7 +1609,7 @@ interface RouteMcpConfig {
|
|
|
1574
1609
|
*
|
|
1575
1610
|
* - `handler: 'string'` → controller method → full Arc pipeline + MCP tool
|
|
1576
1611
|
* - `handler: function` → inline handler → full Arc pipeline + MCP tool
|
|
1577
|
-
* - `
|
|
1612
|
+
* - `rawHandler` → raw Fastify handler → no pipeline, no MCP by default
|
|
1578
1613
|
*/
|
|
1579
1614
|
interface RouteDefinition {
|
|
1580
1615
|
readonly method: RouteMethod;
|
|
@@ -1583,14 +1618,14 @@ interface RouteDefinition {
|
|
|
1583
1618
|
/**
|
|
1584
1619
|
* Route handler.
|
|
1585
1620
|
* - String: controller method name (Arc pipeline) — runtime lookup, no TS coverage on typos.
|
|
1586
|
-
* - Function
|
|
1587
|
-
* -
|
|
1621
|
+
* - Function: receives IRequestContext, returns IControllerResponse (Arc pipeline)
|
|
1622
|
+
* - For a raw Fastify handler `(request, reply)`, use {@link rawHandler}
|
|
1588
1623
|
*
|
|
1589
1624
|
* Prefer `controllerMethod` (2.16) over the string form when you want the
|
|
1590
1625
|
* compiler to catch typos. `handler` stays optional when `controllerMethod`
|
|
1591
1626
|
* is set — exactly one of the two must be declared.
|
|
1592
1627
|
*/
|
|
1593
|
-
readonly handler?: string | ControllerHandler
|
|
1628
|
+
readonly handler?: string | ControllerHandler;
|
|
1594
1629
|
/**
|
|
1595
1630
|
* Typed function-reference handler (2.16). Receives the live controller
|
|
1596
1631
|
* instance and returns the method to invoke — TypeScript catches typos
|
|
@@ -1602,11 +1637,15 @@ interface RouteDefinition {
|
|
|
1602
1637
|
* handlers go through), so there's no per-request lookup overhead.
|
|
1603
1638
|
* The returned method is bound to the controller before dispatch.
|
|
1604
1639
|
*
|
|
1640
|
+
* PIPELINE-ONLY: the referenced method is invoked as a `ControllerHandler`
|
|
1641
|
+
* (one `IRequestContext`), because the router derives "is this raw?" from
|
|
1642
|
+
* {@link rawHandler} alone and this field is mutually exclusive with it.
|
|
1643
|
+
* There is no flag that could make a `controllerMethod` route raw. For a
|
|
1644
|
+
* Fastify-native controller method, put its NAME in `rawHandler` — the
|
|
1645
|
+
* lookup is the same, and the field states the calling convention.
|
|
1646
|
+
*
|
|
1605
1647
|
* Mutually exclusive with `handler` — passing both throws at boot
|
|
1606
|
-
* with a clear "pick one" message.
|
|
1607
|
-
* returned function accepts mirrors the `handler` rules: a plain
|
|
1608
|
-
* `ControllerHandler` for pipeline routes, a raw Fastify handler when
|
|
1609
|
-
* the route is `raw: true`.
|
|
1648
|
+
* with a clear "pick one" message.
|
|
1610
1649
|
*
|
|
1611
1650
|
* Typed loosely (`(controller: unknown) => …`) at the type-system
|
|
1612
1651
|
* boundary because `RouteDefinition` is not generic over the
|
|
@@ -1630,14 +1669,33 @@ interface RouteDefinition {
|
|
|
1630
1669
|
* });
|
|
1631
1670
|
* ```
|
|
1632
1671
|
*/
|
|
1633
|
-
readonly controllerMethod?: (controller: unknown) => ControllerHandler
|
|
1672
|
+
readonly controllerMethod?: (controller: unknown) => ControllerHandler;
|
|
1634
1673
|
/** Permission check — REQUIRED */
|
|
1635
1674
|
readonly permissions: PermissionCheck;
|
|
1636
1675
|
/**
|
|
1637
|
-
*
|
|
1638
|
-
*
|
|
1639
|
-
|
|
1640
|
-
|
|
1676
|
+
* Fastify-native handler — receives `(request, reply)` and owns the response.
|
|
1677
|
+
* Bypasses arc's pipeline entirely: no `IControllerResponse` shaping, no
|
|
1678
|
+
* field-write sanitization.
|
|
1679
|
+
*
|
|
1680
|
+
* Mutually exclusive with {@link handler}. The FIELD carries the intent, so
|
|
1681
|
+
* there is no flag to forget: the previous `raw: boolean` let a Fastify-shaped
|
|
1682
|
+
* function sit in `handler` without it (silently run through the pipeline) or
|
|
1683
|
+
* a pipeline handler sit there with it (silently unwrapped), and neither
|
|
1684
|
+
* mismatch was a type error.
|
|
1685
|
+
*
|
|
1686
|
+
* Splitting the two also restores inference. One field carrying both shapes
|
|
1687
|
+
* meant a union of several function types, which has no single contextual
|
|
1688
|
+
* signature — so an inline `handler: async (req) => …` reported TS7006 and
|
|
1689
|
+
* every author annotated `req` by hand. Fastify types its own
|
|
1690
|
+
* `RouteOptions.handler` as ONE function type for exactly this reason; see
|
|
1691
|
+
* {@link RawRouteHandler} for why arc declares its own rather than reusing
|
|
1692
|
+
* `RouteHandlerMethod` directly.
|
|
1693
|
+
*
|
|
1694
|
+
* Accepts a controller-method NAME as well, same as {@link handler} — the
|
|
1695
|
+
* lookup is identical and only the calling convention differs, so a
|
|
1696
|
+
* Fastify-native controller method stays reachable by name.
|
|
1697
|
+
*/
|
|
1698
|
+
readonly rawHandler?: string | RawRouteHandler;
|
|
1641
1699
|
/** Logical operation name (pipeline keys, MCP tool naming). */
|
|
1642
1700
|
readonly operation?: string;
|
|
1643
1701
|
/** OpenAPI summary */
|
|
@@ -1669,7 +1727,8 @@ interface RouteDefinition {
|
|
|
1669
1727
|
*/
|
|
1670
1728
|
readonly tenantScope?: boolean;
|
|
1671
1729
|
/**
|
|
1672
|
-
* SSE streaming mode.
|
|
1730
|
+
* SSE streaming mode. Requires {@link rawHandler} — the handler is invoked
|
|
1731
|
+
* with `(request, reply)` and owns the response. Two shapes work:
|
|
1673
1732
|
*
|
|
1674
1733
|
* - Write to `reply.raw` directly (NDJSON, custom SSE — historical contract).
|
|
1675
1734
|
* - Return a Web `ReadableStream` (Vercel AI SDK's `result.toUIMessageStream()`,
|
|
@@ -1700,7 +1759,7 @@ interface RouteDefinition {
|
|
|
1700
1759
|
* `onFieldWriteDenied: 'reject' | 'strip'` setting governs how denials
|
|
1701
1760
|
* are surfaced.
|
|
1702
1761
|
*
|
|
1703
|
-
* `
|
|
1762
|
+
* `rawHandler` routes ALWAYS bypass this — they've opted out of the
|
|
1704
1763
|
* pipeline entirely.
|
|
1705
1764
|
*/
|
|
1706
1765
|
readonly fieldWrite?: boolean;
|
|
@@ -1723,6 +1782,22 @@ interface RouteDefinition {
|
|
|
1723
1782
|
* it to a dedicated `routes:` entry, or rely on the resource-level limit.
|
|
1724
1783
|
*/
|
|
1725
1784
|
readonly rateLimit?: RateLimitConfig | false;
|
|
1785
|
+
/**
|
|
1786
|
+
* Per-route CORS override, forwarded to `@fastify/cors` as
|
|
1787
|
+
* `routeOptions.config.cors`. `undefined` inherits the app policy; `false`
|
|
1788
|
+
* disables CORS for this route; an object replaces the app policy for it.
|
|
1789
|
+
*
|
|
1790
|
+
* Needed because one app-wide policy cannot serve both an API and a public
|
|
1791
|
+
* asset: an API wants `credentials: true` with a pinned origin list, a public
|
|
1792
|
+
* asset wants `origin: "*"`, and `*` + credentials is forbidden by the spec
|
|
1793
|
+
* (arc throws at boot on that pair).
|
|
1794
|
+
*
|
|
1795
|
+
* ```ts
|
|
1796
|
+
* { method: "GET", path: "/manifest.json", permissions: allowPublic(),
|
|
1797
|
+
* cors: { origin: "*", credentials: false }, handler }
|
|
1798
|
+
* ```
|
|
1799
|
+
*/
|
|
1800
|
+
readonly cors?: RouteCorsConfig;
|
|
1726
1801
|
/**
|
|
1727
1802
|
* Fastify route schema. Each slot (`body`, `querystring`, `params`,
|
|
1728
1803
|
* `headers`, `response[status]`) accepts a plain JSON Schema object
|
|
@@ -2829,7 +2904,7 @@ interface ResourceConfig<TDoc = AnyRecord> {
|
|
|
2829
2904
|
* object, primitive) is supported via auto-envelope (2.17+) but the
|
|
2830
2905
|
* explicit envelope is the canonical contract — declared `fields:`
|
|
2831
2906
|
* permissions, custom `status`, `meta`, and `headers` only work when
|
|
2832
|
-
* you return the envelope.
|
|
2907
|
+
* you return the envelope. Declare a route's function via `rawHandler` to opt out of
|
|
2833
2908
|
* arc's pipeline entirely (custom streaming, SSE, manual `reply.send()`).
|
|
2834
2909
|
*
|
|
2835
2910
|
* **Path collisions with auto-CRUD are detected at `defineResource()` time.**
|
|
@@ -2844,7 +2919,7 @@ interface ResourceConfig<TDoc = AnyRecord> {
|
|
|
2844
2919
|
* ```typescript
|
|
2845
2920
|
* routes: [
|
|
2846
2921
|
* { method: 'GET', path: '/stats', handler: 'getStats', permissions: auth() },
|
|
2847
|
-
* { method: 'POST', path: '/webhook',
|
|
2922
|
+
* { method: 'POST', path: '/webhook', rawHandler: webhookFn, permissions: auth() },
|
|
2848
2923
|
* ]
|
|
2849
2924
|
* ```
|
|
2850
2925
|
*
|
|
@@ -4220,4 +4295,4 @@ interface ValidateOptions {
|
|
|
4220
4295
|
strict?: boolean;
|
|
4221
4296
|
}
|
|
4222
4297
|
//#endregion
|
|
4223
|
-
export { OpenApiSchemas as $,
|
|
4298
|
+
export { OpenApiSchemas as $, TreeMixin as $t, RequestIdOptions as A, BaseControllerOptions as An, RouteDefinition as At, defineResource as B, RawRouteHandler as Bt, RequestContext as C, createHookSystem as Cn, PipelineStep as Ct, HealthCheck as D, ArcGetResult as Dn, ActionEntry as Dt, GracefulShutdownOptions as E, ArcDeleteResult as En, ActionDefinition as Et, FastifyWithDecorators as F, BodySanitizerConfig as Fn, ControllerLike as Ft, OnTenantDeleteConfig as G, Authenticator as Gt, CrudController as H, ServerAccessor as Ht, MiddlewareHandler as I, FastifyHandler as It, PresetHook as J, TokenPair as Jt, ResolvedTenantPurge as K, AuthenticatorContext as Kt, RequestWithExtras as L, IController as Lt, EventsDecorator as M, ControllerConstructionOptions as Mn, RouteMethod as Mt, FastifyRequestExtras as N, ListResult as Nn, RateLimitConfig as Nt, HealthOptions as O, ArcListResult as On, ActionHandlerFn as Ot, FastifyWithAuth as P, BodySanitizer as Pn, ControllerHandler as Pt, MiddlewareConfig as Q, TreeExt as Qt, RegisterOptions as R, IControllerResponse as Rt, QueryParserInterface as S, beforeUpdate as Sn, PipelineContext as St, CrudRouterOptions as T, ArcCreateResult as Tn, ResourceCacheConfig as Tt, ResourceConfig as U, AuthHelpers as Ut, ResourceDefinition as V, RouteHandler as Vt, ResourcePermissions as W, AuthPluginOptions as Wt, CrudRouteKey as X, SoftDeleteExt as Xt, PresetResult as Y, BaseController as Yt, CrudSchemas as Z, SoftDeleteMixin as Zt, ControllerQueryOptions as _, afterCreate as _n, Guard as _t, InferAdapterDoc as a, QueryResolver as an, ResourceExtensions as at, ParsedQuery as b, beforeCreate as bn, OperationFilter as bt, TypedController as c, AccessControlConfig as cn, AggMeasureShorthand as ct, PaginationResult as d, HookHandler as dn, AggregationDateRangeRequirement as dt, SlugExt as en, RouteSchemaOptions as et, IntrospectionData as f, HookOperation as fn, AggregationIndexHint as ft, ArcInternalMetadata as g, HookSystemOptions as gn, AggregationsMap as gt, ResourceMetadata as h, HookSystem as hn, AggregationRateLimit as ht, ValidationResult as i, BaseCrudController as in, ResourceHooks as it, ArcDecorator as j, ControllerConfigurableOptions as jn, RouteMcpConfig as jt, IntrospectionPluginOptions as k, ArcUpdateResult as kn, ActionsMap as kt, TypedRepository as l, DefineHookOptions as ln, AggregationCacheConfig as lt, RegistryStats as m, HookRegistration as mn, AggregationMaterializedResult as mt, ConfigError as n, BulkExt as nn, FieldRule$1 as nt, InferDocType as o, QueryResolverConfig as on, EventDefinition as ot, RegistryEntry as p, HookPhase as pn, AggregationMaterializedContext as pt, PresetFunction as q, JwtContext as qt, ValidateOptions as r, BulkMixin as rn, ResourceHookContext as rt, InferResourceDoc as s, AccessControl as sn, AggMeasureInput as st, RouteHandlerMethod$1 as t, SlugMixin as tn, ArcFieldRule as tt, TypedResourceConfig as u, HookContext as un, AggregationConfig as ut, LookupOption as v, afterDelete as vn, Interceptor as vt, ServiceContext as w, defineHook as wn, Transform as wt, PopulateOption as x, beforeDelete as xn, PipelineConfig as xt, OwnershipCheck as y, afterUpdate as yn, NextFunction as yt, ResourceRegistry as z, IRequestContext as zt };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import "./
|
|
1
|
+
|
|
2
|
+
import { C as RequestContext, Et as ActionDefinition, F as FastifyWithDecorators, H as CrudController, L as RequestWithExtras, Lt as IController, Rt as IControllerResponse, T as CrudRouterOptions, U as ResourceConfig, V as ResourceDefinition, et as RouteSchemaOptions, jt as RouteMcpConfig, tt as ArcFieldRule, ut as AggregationConfig, zt as IRequestContext } from "./index-CpzxqePp.mjs";
|
|
3
|
+
import { i as RequestScope } from "./types-ChuShpCP.mjs";
|
|
4
|
+
import { l as AnyRecord, r as PermissionCheck } from "./types-B7XeLEgK.mjs";
|
|
5
|
+
import "./fastify-augmentation-BppG5bMT.mjs";
|
|
5
6
|
import { FastifyReply, FastifyRequest, RouteHandlerMethod } from "fastify";
|
|
6
7
|
import { z } from "zod";
|
|
7
8
|
import { DataAdapter } from "@classytic/repo-core/adapter";
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
|
|
2
|
+
import { _ as HealthCheck, a as ModuleContribution, f as ScheduleDefinition, n as ArcModuleInput, r as ArcModuleRegistry, s as ModuleSetupContext, t as ArcModule } from "./types-CT5vu6M0.mjs";
|
|
3
|
+
import { FastifyInstance } from "fastify";
|
|
4
|
+
//#region src/factory/module/contributions.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Collect every module's `healthChecks` in the caller's order. Fails at boot
|
|
7
|
+
* on a duplicate check `name` across modules, naming BOTH owning modules.
|
|
8
|
+
* The host's app-level checks are appended AFTER this (modules-first,
|
|
9
|
+
* host-last) by the caller.
|
|
10
|
+
*/
|
|
11
|
+
declare function collectModuleHealthChecks(modules: readonly ArcModule[]): HealthCheck[];
|
|
12
|
+
/**
|
|
13
|
+
* Collect every module's `workflows`. Resolves factory contributions (so a
|
|
14
|
+
* factory can close over a container the caller has already decorated on
|
|
15
|
+
* `fastify`) and flattens to a single opaque array. Arc core deliberately
|
|
16
|
+
* does NOT validate or interpret the values — the streamline integration
|
|
17
|
+
* owns name/shape checks and registration. Called by the integration at init
|
|
18
|
+
* time, not by arc's boot pipeline (workflows depend on the integration's
|
|
19
|
+
* container).
|
|
20
|
+
*/
|
|
21
|
+
declare function collectModuleWorkflows(fastify: FastifyInstance, modules: readonly ArcModule[]): Promise<unknown[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Collect every module's `scheduledJobs`. Resolves factory contributions
|
|
24
|
+
* (after bootstraps) and fails at boot on a duplicate job `name` across
|
|
25
|
+
* modules. The caller passes the returned definitions to the canonical
|
|
26
|
+
* schedules plugin; factories must therefore be resolved only once.
|
|
27
|
+
*/
|
|
28
|
+
declare function collectModuleScheduledJobs(fastify: FastifyInstance, modules: readonly ArcModule[],
|
|
29
|
+
/**
|
|
30
|
+
* Optional sink for per-module counts, filled as each arm resolves.
|
|
31
|
+
*
|
|
32
|
+
* Exists so `arc.moduleDescriptors` can report real numbers without
|
|
33
|
+
* resolving the factories a SECOND time — a contribution factory closes over
|
|
34
|
+
* booted engines and may register or allocate, so running it twice is not a
|
|
35
|
+
* free read. One resolution feeds both activation and introspection.
|
|
36
|
+
*/
|
|
37
|
+
countsByModule?: Map<string, number>): Promise<ScheduleDefinition[]>;
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/factory/module/extend.d.ts
|
|
40
|
+
/**
|
|
41
|
+
* What a caller may add. Every mergeable arm of `ArcModule`, plus `bootstrap`
|
|
42
|
+
* in wrapper form only.
|
|
43
|
+
*
|
|
44
|
+
* `name` is absent on purpose: renaming a module mid-composition breaks the
|
|
45
|
+
* `dependsOn` graph and the registry key its consumers read, and it is the one
|
|
46
|
+
* "extension" that is never additive.
|
|
47
|
+
*/
|
|
48
|
+
interface ModuleExtension<TExports = unknown> {
|
|
49
|
+
dependsOn?: readonly string[];
|
|
50
|
+
owns?: readonly string[] | "provided";
|
|
51
|
+
resources?: ArcModule<TExports>["resources"];
|
|
52
|
+
eventHandlers?: ArcModule<TExports>["eventHandlers"];
|
|
53
|
+
scheduledJobs?: ArcModule<TExports>["scheduledJobs"];
|
|
54
|
+
workflows?: ArcModule<TExports>["workflows"];
|
|
55
|
+
healthChecks?: ArcModule<TExports>["healthChecks"];
|
|
56
|
+
errorMappers?: ArcModule<TExports>["errorMappers"];
|
|
57
|
+
plugins?: ArcModule<TExports>["plugins"];
|
|
58
|
+
afterResources?: ArcModule<TExports>["afterResources"];
|
|
59
|
+
onClose?: ArcModule<TExports>["onClose"];
|
|
60
|
+
/**
|
|
61
|
+
* WRAP the module's bootstrap — it is never replaced.
|
|
62
|
+
*
|
|
63
|
+
* Bootstrap returns the module's exports, so two of them cannot be
|
|
64
|
+
* concatenated: one value has to win, and a host silently winning is the gym
|
|
65
|
+
* failure (`{ ...mod, bootstrap }` overwrote the factory's own, so the engine
|
|
66
|
+
* the module published was never created). The wrapper form makes the
|
|
67
|
+
* relationship explicit — call `inner` and decorate its result, or
|
|
68
|
+
* deliberately do not.
|
|
69
|
+
*
|
|
70
|
+
* `inner` is `undefined` when the module has no bootstrap of its own.
|
|
71
|
+
*/
|
|
72
|
+
bootstrap?: (inner: ((f: FastifyInstance, c: ModuleSetupContext) => TExports | Promise<TExports>) | undefined) => (f: FastifyInstance, c: ModuleSetupContext) => TExports | Promise<TExports>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Merge a host's additions onto a module. Nothing the module declared is lost.
|
|
76
|
+
*
|
|
77
|
+
* ```ts
|
|
78
|
+
* return extendModule(createOrderModule({ … }), {
|
|
79
|
+
* eventHandlers: () => hostHandlers(), // appended after the module's
|
|
80
|
+
* dependsOn: ["outbox"], // unioned
|
|
81
|
+
* bootstrap: (inner) => async (f, c) => { // wraps, never replaces
|
|
82
|
+
* const exports = await inner?.(f, c);
|
|
83
|
+
* return decorate(exports);
|
|
84
|
+
* },
|
|
85
|
+
* });
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
declare function extendModule<TExports = unknown>(mod: ArcModule<TExports>, extension: ModuleExtension<TExports>): ArcModule<TExports>;
|
|
89
|
+
//#endregion
|
|
90
|
+
//#region src/factory/module/lifecycle.d.ts
|
|
91
|
+
/**
|
|
92
|
+
* Subscribe every module's `eventHandlers` in dependency order (pass the
|
|
93
|
+
* `orderModules`-sorted list). Returns the ordered list of unsubscribe
|
|
94
|
+
* functions so the caller can tear them down at shutdown BEFORE module
|
|
95
|
+
* `onClose` (while module deps are still alive). Fails at boot on:
|
|
96
|
+
* - a duplicate NAMED handler across modules (attributing both owners);
|
|
97
|
+
* - a module declaring handlers while the event subsystem is unavailable.
|
|
98
|
+
* Resolves factory contributions (after bootstraps) so a handler can close over
|
|
99
|
+
* booted engines rather than a global getter.
|
|
100
|
+
*/
|
|
101
|
+
declare function subscribeModuleEventHandlers(fastify: FastifyInstance, modules: readonly ArcModule[],
|
|
102
|
+
/**
|
|
103
|
+
* Optional sink for per-module handler counts, filled as each arm resolves.
|
|
104
|
+
* Lets `arc.moduleDescriptors` report real numbers without resolving the
|
|
105
|
+
* factories a SECOND time — see the note on `collectModuleScheduledJobs`.
|
|
106
|
+
*/
|
|
107
|
+
countsByModule?: Map<string, number>): Promise<Array<() => void | Promise<void>>>;
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region src/factory/module/order.d.ts
|
|
110
|
+
/**
|
|
111
|
+
* Order modules for composition by their `dependsOn` edges — a STABLE
|
|
112
|
+
* topological sort. Called once at the start of the bootstrap phase; every
|
|
113
|
+
* subsequent phase (bootstrap, resources, afterResources, and reverse-order
|
|
114
|
+
* onClose) iterates the returned list, so a module's declared dependencies are
|
|
115
|
+
* always composed before it.
|
|
116
|
+
*
|
|
117
|
+
* "Stable" = modules with no edge between them keep their original list order,
|
|
118
|
+
* so declaring `dependsOn` on one module never silently reorders an unrelated
|
|
119
|
+
* one. Backward compatible: a `modules` array with NO `dependsOn` anywhere is
|
|
120
|
+
* returned unchanged.
|
|
121
|
+
*
|
|
122
|
+
* Fail-fast — throws (never reorders past a broken contract) on:
|
|
123
|
+
* - duplicate module names (the name is the graph key)
|
|
124
|
+
* - a `dependsOn` name not present in the composed set
|
|
125
|
+
* - a self-reference (`dependsOn` includes the module's own name)
|
|
126
|
+
* - a dependency cycle (reports the concrete `a → b → … → a` path)
|
|
127
|
+
*/
|
|
128
|
+
declare function orderModules(modules: readonly ArcModule[]): ArcModule[];
|
|
129
|
+
//#endregion
|
|
130
|
+
//#region src/factory/module/resolve.d.ts
|
|
131
|
+
/**
|
|
132
|
+
* Resolve any module-input form to a concrete `ArcModule`. A thunk is invoked
|
|
133
|
+
* (this is where a dynamic `import()` fires); a promise (or plain module) is
|
|
134
|
+
* awaited. Called once per module at the start of the bootstrap phase.
|
|
135
|
+
*/
|
|
136
|
+
declare function resolveModule(input: ArcModuleInput): Promise<ArcModule>;
|
|
137
|
+
/** Resolve a `ModuleContribution` to a concrete array (array passthrough or factory call). */
|
|
138
|
+
declare function resolveContribution<T>(contribution: ModuleContribution<T> | undefined, fastify: FastifyInstance): Promise<readonly T[]>;
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/factory/module/state.d.ts
|
|
141
|
+
type ModuleState = "resolved" | "bootstrapping" | "ready" | "closing" | "closed" | "failed";
|
|
142
|
+
/**
|
|
143
|
+
* Is `name` in the composed module graph? TRUE for resource-only modules and
|
|
144
|
+
* modules that exported nothing — the question `hasModuleExports()` cannot
|
|
145
|
+
* answer. FALSE before registerResources runs (no graph yet) and for
|
|
146
|
+
* uncomposed names.
|
|
147
|
+
*/
|
|
148
|
+
declare function hasModule(fastify: FastifyInstance, name: string): boolean;
|
|
149
|
+
/**
|
|
150
|
+
* The module's current lifecycle state, or `undefined` when the module is not
|
|
151
|
+
* composed (or no graph has been composed on this instance). See the state
|
|
152
|
+
* machine in the file header.
|
|
153
|
+
*/
|
|
154
|
+
declare function getModuleState(fastify: FastifyInstance, name: string): ModuleState | undefined;
|
|
155
|
+
//#endregion
|
|
156
|
+
//#region src/factory/module/index.d.ts
|
|
157
|
+
/**
|
|
158
|
+
* Identity helper for authoring a typed module — mirrors `defineResource`.
|
|
159
|
+
* Gives inference + a single obvious construction site; does no work.
|
|
160
|
+
*
|
|
161
|
+
* `TExports` is inferred from the `bootstrap` return value, so a module
|
|
162
|
+
* author gets a typed public export for free:
|
|
163
|
+
*
|
|
164
|
+
* ```ts
|
|
165
|
+
* export const accountingModule = (deps: Deps) =>
|
|
166
|
+
* defineModule({
|
|
167
|
+
* name: "accounting",
|
|
168
|
+
* bootstrap: async () => createAccountingEngine(deps), // TExports inferred
|
|
169
|
+
* });
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
declare function defineModule<TExports = unknown>(module: ArcModule<TExports>): ArcModule<TExports>;
|
|
173
|
+
/**
|
|
174
|
+
* Typed accessor for a module's public export (its `bootstrap` return value),
|
|
175
|
+
* recorded at `fastify.arc.modules[name]`.
|
|
176
|
+
*
|
|
177
|
+
* Throwing, in line with the fail-fast contract (and `requireOrgId`-style
|
|
178
|
+
* accessors): a missing entry means the module either isn't composed, is
|
|
179
|
+
* composed AFTER the caller (list order = init order), or returned nothing —
|
|
180
|
+
* all wiring bugs that must surface at boot, not as `undefined` downstream.
|
|
181
|
+
*
|
|
182
|
+
* The type parameter is an assertion, not a proof. Two ways to type it:
|
|
183
|
+
* - augment `ArcModuleRegistry` once — then the name alone infers the type:
|
|
184
|
+
* `getModuleExports(f, "accounting")` → `AccountingEngine`.
|
|
185
|
+
* - or pass it inline: `getModuleExports<AccountingEngine>(f, "accounting")`.
|
|
186
|
+
*
|
|
187
|
+
* Siblings, for the two shapes this one is wrong for:
|
|
188
|
+
* - `getOptionalModuleExports` — the module is genuinely OPTIONAL.
|
|
189
|
+
* - `lazyModuleExports` / `lazyRequiredModuleExports` — the read happens at
|
|
190
|
+
* composition time, where boot order decides the answer.
|
|
191
|
+
*/
|
|
192
|
+
declare function getModuleExports<K extends keyof ArcModuleRegistry>(fastify: FastifyInstance, name: K): ArcModuleRegistry[K];
|
|
193
|
+
declare function getModuleExports<TExports = unknown>(fastify: FastifyInstance, name: string): TExports;
|
|
194
|
+
/**
|
|
195
|
+
* Non-throwing sibling of `getModuleExports`: `undefined` when the module is
|
|
196
|
+
* not composed (or has not bootstrapped yet).
|
|
197
|
+
*
|
|
198
|
+
* Exists because OPTIONAL sibling modules are a first-class composition shape —
|
|
199
|
+
* a deployment that turns `inventory` off still sells services, so its POS
|
|
200
|
+
* module must ask "is inventory here?" rather than fail-fast. Hosts were
|
|
201
|
+
* spelling that question as
|
|
202
|
+
*
|
|
203
|
+
* ```ts
|
|
204
|
+
* (fastify as unknown as { arc?: { modules?: Record<string, unknown> } })
|
|
205
|
+
* .arc?.modules?.inventory;
|
|
206
|
+
* ```
|
|
207
|
+
*
|
|
208
|
+
* — a double cast that (a) defeats `ArcModuleRegistry` inference, (b) silently
|
|
209
|
+
* survives a typo in the module name, and (c) is impossible to grep for. Use
|
|
210
|
+
* `getModuleExports` when the dependency is REQUIRED (boot must fail), this
|
|
211
|
+
* when it is genuinely optional.
|
|
212
|
+
*
|
|
213
|
+
* Prefer `lazyModuleExports` whenever the read happens at COMPOSITION time —
|
|
214
|
+
* see its doc for why a value read once can latch `undefined` forever.
|
|
215
|
+
*/
|
|
216
|
+
declare function getOptionalModuleExports<K extends keyof ArcModuleRegistry>(fastify: FastifyInstance, name: K): ArcModuleRegistry[K] | undefined;
|
|
217
|
+
declare function getOptionalModuleExports<TExports = unknown>(fastify: FastifyInstance, name: string): TExports | undefined;
|
|
218
|
+
/**
|
|
219
|
+
* Is a module's public export recorded yet? The predicate form of
|
|
220
|
+
* `getOptionalModuleExports`, for readiness gates (`ready: () => ...`) that
|
|
221
|
+
* should not have to reason about falsy-but-present exports.
|
|
222
|
+
*/
|
|
223
|
+
declare function hasModuleExports(fastify: FastifyInstance, name: string): boolean;
|
|
224
|
+
/**
|
|
225
|
+
* A DEFERRED reader of a sibling module's export: returns a getter that reads
|
|
226
|
+
* the registry at CALL time, not now.
|
|
227
|
+
*
|
|
228
|
+
* ── Why this exists (the bug it removes) ─────────────────────────────────────
|
|
229
|
+
*
|
|
230
|
+
* Module composition runs bootstraps in dependency/list order, but a lot of
|
|
231
|
+
* wiring is *registered* earlier than it *runs*: an `eventHandlers` factory, a
|
|
232
|
+
* bridge accessor handed to another module, a hook added during bootstrap and
|
|
233
|
+
* fired per request. Such a factory can execute BEFORE the sibling it needs has
|
|
234
|
+
* bootstrapped — so a sibling engine captured into a local at that moment is
|
|
235
|
+
* `undefined`, and stays `undefined` for the life of the process even though the
|
|
236
|
+
* sibling came up milliseconds later.
|
|
237
|
+
*
|
|
238
|
+
* That failure is SILENT by construction: the consumer sees a null bridge and
|
|
239
|
+
* treats it as "this deployment has no inventory / no revenue engine", which is
|
|
240
|
+
* a legitimate configuration. Real cost in this codebase: orders were created
|
|
241
|
+
* and never payment-confirmed (no entitlement, no card, no door) and nothing
|
|
242
|
+
* errored anywhere.
|
|
243
|
+
*
|
|
244
|
+
* The getter therefore:
|
|
245
|
+
* - re-reads while the module is ABSENT, so boot order cannot matter;
|
|
246
|
+
* - memoizes the FIRST resolved value, so the steady-state read is a closure
|
|
247
|
+
* variable rather than a registry lookup per request;
|
|
248
|
+
* - never memoizes absence — that is precisely the latch this replaces.
|
|
249
|
+
*
|
|
250
|
+
* ```ts
|
|
251
|
+
* const inventory = lazyModuleExports<FlowEngine>(fastify, "inventory");
|
|
252
|
+
* return {
|
|
253
|
+
* flowBridge: () => (inventory() ? createFlowEngineBridge({ getFlowEngine: () => inventory()! }) : null),
|
|
254
|
+
* ready: () => inventory() !== undefined,
|
|
255
|
+
* };
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
declare function lazyModuleExports<K extends keyof ArcModuleRegistry>(fastify: FastifyInstance, name: K): () => ArcModuleRegistry[K] | undefined;
|
|
259
|
+
declare function lazyModuleExports<TExports = unknown>(fastify: FastifyInstance, name: string): () => TExports | undefined;
|
|
260
|
+
/**
|
|
261
|
+
* Required counterpart of `lazyModuleExports`: defers the read, then throws
|
|
262
|
+
* `getModuleExports`' error if the module is still absent at first use.
|
|
263
|
+
*
|
|
264
|
+
* The pair matters because "required" and "readable now" are different
|
|
265
|
+
* questions. A hook registered at bootstrap that needs the `order` engine at
|
|
266
|
+
* REQUEST time is a hard dependency, but reading it eagerly turns a correct
|
|
267
|
+
* composition into a boot crash purely because of list order. Deferring keeps
|
|
268
|
+
* the fail-fast guarantee and moves it to the first moment the answer is
|
|
269
|
+
* actually needed.
|
|
270
|
+
*
|
|
271
|
+
* Deferred does NOT mean unvalidated: a lazily-required module is still a
|
|
272
|
+
* HARD dependency, so PRESENCE is checked eagerly. When the composed module
|
|
273
|
+
* graph is known (any `createApp`/`registerResources` boot — the normal
|
|
274
|
+
* case), a name that is not in the graph throws HERE, at composition time,
|
|
275
|
+
* instead of surviving startup and failing on the first request or event.
|
|
276
|
+
* Only the EXPORT read (does bootstrap's return value exist yet?) is
|
|
277
|
+
* deferred to first call.
|
|
278
|
+
*
|
|
279
|
+
* Convention for hard sibling access: also declare the target in the
|
|
280
|
+
* consumer's `dependsOn`. That orders composition (the sibling's bootstrap
|
|
281
|
+
* runs first), while this accessor merely defers the read — the two are
|
|
282
|
+
* complementary, not alternatives:
|
|
283
|
+
* - hard dependency, read during bootstrap → `dependsOn` + `getModuleExports`
|
|
284
|
+
* - hard dependency, read at request/event time → `dependsOn` + this
|
|
285
|
+
* - optional integration → `lazyModuleExports` (no `dependsOn` needed)
|
|
286
|
+
*/
|
|
287
|
+
declare function lazyRequiredModuleExports<K extends keyof ArcModuleRegistry>(fastify: FastifyInstance, name: K): () => ArcModuleRegistry[K];
|
|
288
|
+
declare function lazyRequiredModuleExports<TExports = unknown>(fastify: FastifyInstance, name: string): () => TExports;
|
|
289
|
+
//#endregion
|
|
290
|
+
export { collectModuleScheduledJobs as _, lazyModuleExports as a, getModuleState as c, resolveModule as d, orderModules as f, collectModuleHealthChecks as g, extendModule as h, hasModuleExports as i, hasModule as l, ModuleExtension as m, getModuleExports as n, lazyRequiredModuleExports as o, subscribeModuleEventHandlers as p, getOptionalModuleExports as r, ModuleState as s, defineModule as t, resolveContribution as u, collectModuleWorkflows as v };
|