@classytic/arc 2.31.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/dist/{BaseController-De7GqHck.mjs → BaseController-Dk34dxhI.mjs} +16 -13
- package/dist/{EventTransport-9mlTgqzE.mjs → EventTransport-BV10D0oG.mjs} +1 -1
- package/dist/{HookSystem-BcmPyq5I.mjs → HookSystem-vimw5D7Z.mjs} +2 -2
- package/dist/{ResourceRegistry-qq0mn2s9.mjs → ResourceRegistry-BVr7PgA0.mjs} +17 -15
- package/dist/{actionPermissions-BE5NwaQk.mjs → actionPermissions-Dti7ebyv.mjs} +1 -1
- package/dist/audit/index.mjs +2 -2
- package/dist/auth/audit.mjs +1 -1
- package/dist/auth/index.mjs +11 -10
- package/dist/auth/redis-session.mjs +1 -1
- package/dist/{authorizationDecision-ChvUQGG1.mjs → authorizationDecision-__T3EJDA.mjs} +2 -2
- package/dist/{buildHandler-CDrCJzmB.mjs → buildHandler-Dn7rzUJo.mjs} +6 -5
- package/dist/cache/index.mjs +4 -4
- package/dist/{caching-BFHA6Scf.mjs → caching-DFJqHyFs.mjs} +2 -2
- package/dist/cleanup/index.d.mts +36 -14
- package/dist/cleanup/index.mjs +45 -29
- package/dist/cli/commands/describe.mjs +4 -6
- package/dist/cli/commands/docs.mjs +3 -3
- package/dist/cli/commands/doctor.mjs +1 -1
- package/dist/cli/commands/generate.mjs +2 -2
- package/dist/cli/commands/init.mjs +2 -2
- package/dist/cli/commands/introspect.mjs +2 -2
- package/dist/cli/index.mjs +3 -3
- package/dist/{constants-D3Dv4LAV.mjs → constants-J99LGTJI.mjs} +1 -1
- package/dist/context/index.mjs +3 -3
- package/dist/core/index.d.mts +1 -1
- package/dist/core/index.mjs +7 -7
- package/dist/{core-BGpIxINN.mjs → core-BwwmNSp7.mjs} +3 -3
- package/dist/{createActionRouter-CDXEdasl.mjs → createActionRouter-DkJZWo0m.mjs} +14 -11
- package/dist/{createAggregationRouter-KrQDzx-k.mjs → createAggregationRouter-B1exOVD8.mjs} +10 -8
- package/dist/{createApp-Df89BEni.mjs → createApp-Bv0m-Q6_.mjs} +182 -61
- package/dist/{defineAggregation-DbPPS8RI.mjs → defineAggregation-gX4No1gt.mjs} +1 -1
- package/dist/{defineResource-Bv6EtN1x.mjs → defineResource-XFPPUu2c.mjs} +41 -32
- package/dist/discovery/index.mjs +1 -1
- package/dist/docs/index.mjs +3 -3
- package/dist/{elevation-D2l1mh4g.mjs → elevation-DNXXxgjl.mjs} +4 -4
- package/dist/encryption/index.mjs +5 -4
- package/dist/{errorHandler-C5NeD6bT.mjs → errorHandler-B2AZUJUj.mjs} +3 -3
- package/dist/{errors-Cj42AntO.mjs → errors-Bh1KK5ps.mjs} +1 -1
- package/dist/{eventPlugin-CkffEihm.mjs → eventPlugin-Dk_TyXeE.mjs} +8 -7
- package/dist/events/index.d.mts +108 -41
- package/dist/events/index.mjs +166 -142
- package/dist/events/transports/redis-stream-entry.mjs +14 -10
- package/dist/events/transports/redis.mjs +1 -1
- package/dist/factory/index.d.mts +5 -5
- package/dist/factory/index.mjs +131 -8
- package/dist/fastify-augmentation-BppG5bMT.d.mts +179 -0
- package/dist/{fields-CB5Cuzk9.mjs → fields-DEi65pGj.mjs} +6 -11
- package/dist/{generate-EcA6ui4i.mjs → generate-CRSG0jTv.mjs} +2 -2
- package/dist/{headers-3zvE0rM3.mjs → headers-BXjQYbeC.mjs} +2 -2
- package/dist/{health-DjZYjM7H.mjs → health-5XnTa2uo.mjs} +1 -1
- package/dist/hooks/index.mjs +2 -2
- package/dist/idempotency/index.mjs +8 -6
- package/dist/idempotency/redis.mjs +1 -1
- package/dist/{index-Bc2ox8_U.d.mts → index-DXlHwvuE.d.mts} +1 -1
- package/dist/{index-CFThn1K9.d.mts → index-ZWhLTp_s.d.mts} +70 -4
- package/dist/{index-CEJNZFtX.d.mts → index-zq6VrjaB.d.mts} +70 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +11 -11
- package/dist/{init-BEiNZBsJ.mjs → init-BbfP8aky.mjs} +7 -5
- package/dist/integrations/event-gateway.mjs +2 -2
- package/dist/integrations/index.mjs +1 -1
- package/dist/integrations/jobs/index.mjs +3 -3
- package/dist/integrations/mcp/index.mjs +2 -2
- package/dist/integrations/mcp/testing.mjs +2 -2
- package/dist/integrations/streamline.mjs +3 -3
- package/dist/integrations/webhooks.mjs +1 -1
- package/dist/integrations/websocket-pushref-redis.mjs +1 -1
- package/dist/integrations/websocket-redis.mjs +1 -1
- package/dist/integrations/websocket.mjs +38 -35
- package/dist/{interface-DYzM0q-u.mjs → interface-BP4IJCBO.mjs} +1 -1
- package/dist/{jsonBody-BYbLDi5D.mjs → jsonBody-DDSR2HFl.mjs} +2 -2
- package/dist/{keys-C0_pa1tY.mjs → keys-B-HBTGXl.mjs} +1 -1
- package/dist/{loadResources-yawi9tAE.mjs → loadResources-DisEAmkm.mjs} +4 -3
- package/dist/{loadResourcesFromEntry-BAjYZonx.mjs → loadResourcesFromEntry-D1MJp13f.mjs} +2 -2
- package/dist/logger/index.mjs +1 -1
- package/dist/{mcpPlugin-B_es0hiF.mjs → mcpPlugin-CpfVpKHE.mjs} +32 -31
- package/dist/{memory-DR6wpa9F.mjs → memory-DsuWnj4T.mjs} +5 -5
- package/dist/{metrics-CUdw_wLB.mjs → metrics-DdQL8syd.mjs} +2 -2
- package/dist/middleware/index.mjs +3 -3
- package/dist/migrations/index.mjs +3 -3
- package/dist/{module-0pFJA6YW.mjs → module-Br81am6m.mjs} +1 -1
- package/dist/{multipartBody-wOgj_fnj.mjs → multipartBody-BnkBLN7v.mjs} +3 -3
- package/dist/{openapi-B2L4js1v.mjs → openapi-DIRzvxC0.mjs} +6 -6
- package/dist/outbox-admin/index.d.mts +85 -0
- package/dist/outbox-admin/index.mjs +115 -0
- package/dist/permissions/index.d.mts +2 -2
- package/dist/permissions/index.mjs +6 -6
- package/dist/{permissions-L--QDAir.mjs → permissions-Dl_m0NCe.mjs} +101 -8
- package/dist/{pipe-DRDNsI2T.mjs → pipe-ELHCP3zj.mjs} +3 -5
- package/dist/pipeline/index.mjs +2 -2
- package/dist/{pipeline-UPQFatit.mjs → pipeline-CPA-jx0M.mjs} +17 -15
- package/dist/plugins/index.d.mts +2 -2
- package/dist/plugins/index.mjs +16 -16
- package/dist/plugins/response-cache.mjs +2 -2
- package/dist/plugins/tracing-entry.mjs +2 -2
- package/dist/{pluralize-O0FZgESl.mjs → pluralize-C2ZkKbsn.mjs} +1 -1
- package/dist/{preloadResources-Dz6BjzM6.mjs → preloadResources-CDs87fTw.mjs} +1 -1
- package/dist/{preloadResources-CyoJMSiO.d.mts → preloadResources-T1hmlTEZ.d.mts} +2 -2
- package/dist/presets/filesUpload.mjs +6 -6
- package/dist/presets/index.mjs +2 -2
- package/dist/presets/multiTenant.mjs +3 -3
- package/dist/presets/search.mjs +2 -2
- package/dist/{presets-C4-g4_4P.mjs → presets-Dntd_pUO.mjs} +6 -5
- package/dist/{projection-BHw6xlOQ.mjs → projection-CjHhM5W1.mjs} +2 -2
- package/dist/{queryCachePlugin-BZr8v46E.mjs → queryCachePlugin-Dhps-Ldt.mjs} +6 -6
- package/dist/{rateLimit-CMPY5Qms.mjs → rateLimit-C7mmAGs3.mjs} +2 -2
- package/dist/{rateLimitKey-Dn5JNmkj.mjs → rateLimitKey-CccEFBfk.mjs} +1 -1
- package/dist/{realtime-C5NoxWFY.mjs → realtime-DVvVZZFz.mjs} +10 -10
- package/dist/{registerRoute-CBN84fc7.mjs → registerRoute-B_QrjYZS.mjs} +10 -8
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +3 -3
- package/dist/{registry-4213U4zb.mjs → registry-DqUmzA9W.mjs} +2 -2
- package/dist/{renewingLease-Dll8mGgc.mjs → renewingLease-BpP9wwj7.mjs} +1 -1
- package/dist/{replyHelpers-DIiZKGUt.mjs → replyHelpers-DS-P0b32.mjs} +2 -2
- package/dist/{repositoryFilter-f9eAfq_l.mjs → repositoryFilter-DotlxG3L.mjs} +1 -1
- package/dist/{requestContext-2TxXOJ7T.mjs → requestContext-B6vQF-sy.mjs} +1 -1
- package/dist/{rolldown-runtime-CUsjNX9R.mjs → rolldown-runtime-BhflRrBs.mjs} +1 -1
- package/dist/{schedules-DdtlICTf.mjs → schedules-C2Q3uv2d.mjs} +3 -3
- package/dist/{schemaConverter-D--wdJM-.mjs → schemaConverter-Crjvczi_.mjs} +1 -1
- package/dist/{schemaIR-Bm2enbnh.mjs → schemaIR-CnyKK_1j.mjs} +2 -2
- package/dist/schemas/index.mjs +1 -1
- package/dist/scim/index.mjs +2 -2
- package/dist/scope/index.mjs +5 -5
- package/dist/{scope-DHx5Fous.mjs → scope-afz_Ieek.mjs} +4 -4
- package/dist/{simpleEqualityMatcher-DjQJ7FKA.mjs → simpleEqualityMatcher-C4KiMWUa.mjs} +1 -1
- package/dist/{sse-CUTo9y0X.mjs → sse-B9P4Y-UI.mjs} +7 -6
- package/dist/{sseStream-B_5XcVVd.mjs → sseStream-B3zb_d1h.mjs} +2 -2
- package/dist/{store-helpers-D1MP_gRG.mjs → store-helpers-DmEMHlPQ.mjs} +1 -1
- package/dist/{streaming-PSZwi8JV.mjs → streaming-DPZdQmDz.mjs} +1 -1
- package/dist/{subscribe-helpers-C0Tb2aUp.mjs → subscribe-helpers-sp5xTDVA.mjs} +2 -2
- package/dist/sync/changelog.mjs +1 -1
- package/dist/testing/cleanupStoreContract.mjs +10 -6
- package/dist/testing/index.d.mts +31 -4
- package/dist/testing/index.mjs +97 -39
- package/dist/testing/outboxStoreContract.d.mts +11 -2
- package/dist/testing/outboxStoreContract.mjs +110 -21
- package/dist/testing/storageContract.mjs +11 -6
- package/dist/{transactionContext-dAfBVUrk.mjs → transactionContext-BvLKvOIL.mjs} +1 -1
- package/dist/{typeGuards-B0ryPo3I.mjs → typeGuards-B_5-hKjJ.mjs} +1 -1
- package/dist/types/index.mjs +1 -1
- package/dist/types/storage.mjs +1 -1
- package/dist/{types-CBgvkp8O.d.mts → types-CT5vu6M0.d.mts} +87 -11
- package/dist/{types-Cys0ko9Z.mjs → types-DXYX7dIR.mjs} +4 -4
- package/dist/usage/index.mjs +0 -0
- package/dist/{userHelpers-ChYJ6CdK.mjs → userHelpers-BNsOXzOd.mjs} +1 -1
- package/dist/utils/index.mjs +10 -10
- package/dist/{utils-vL8BrDE2.mjs → utils-BtOha_Sp.mjs} +3 -3
- package/dist/{validate-_KbifpHF.mjs → validate-PMCPR9El.mjs} +2 -2
- package/dist/{versioning-CHDTor3P.mjs → versioning-CKv2jz_U.mjs} +4 -4
- package/package.json +23 -13
- package/dist/fastify-augmentation-zh0_AYHa.d.mts +0 -85
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { t as __exportAll } from "./rolldown-runtime-
|
|
3
|
-
import "./constants-
|
|
4
|
-
import { f as createError } from "./errors-
|
|
5
|
-
import { a as buildRouteHooks, i as selectPluginMw, l as buildAuthMiddlewareForPermissions, n as buildRouteConfig, r as resolveRouterPluginMw, s as routeHookOptions, t as buildRateLimitConfig, u as buildArcDecorator } from "./rateLimit-
|
|
6
|
-
import { n as buildActionPermissionMw, t as tryRegisterRoute } from "./registerRoute-
|
|
7
|
-
import { l as sendControllerResponse, r as resolvePipelineSteps, t as buildActionPipelineHandler } from "./pipeline-
|
|
8
|
-
import { n as schemaIRToJsonSchemaBranch, t as normalizeSchemaIR } from "./schemaIR-
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-BhflRrBs.mjs";
|
|
3
|
+
import "./constants-J99LGTJI.mjs";
|
|
4
|
+
import { f as createError } from "./errors-Bh1KK5ps.mjs";
|
|
5
|
+
import { a as buildRouteHooks, i as selectPluginMw, l as buildAuthMiddlewareForPermissions, n as buildRouteConfig, r as resolveRouterPluginMw, s as routeHookOptions, t as buildRateLimitConfig, u as buildArcDecorator } from "./rateLimit-C7mmAGs3.mjs";
|
|
6
|
+
import { n as buildActionPermissionMw, t as tryRegisterRoute } from "./registerRoute-B_QrjYZS.mjs";
|
|
7
|
+
import { l as sendControllerResponse, r as resolvePipelineSteps, t as buildActionPipelineHandler } from "./pipeline-CPA-jx0M.mjs";
|
|
8
|
+
import { n as schemaIRToJsonSchemaBranch, t as normalizeSchemaIR } from "./schemaIR-CnyKK_1j.mjs";
|
|
9
9
|
//#region src/core/createActionRouter.ts
|
|
10
10
|
var createActionRouter_exports = /* @__PURE__ */ __exportAll({
|
|
11
11
|
buildActionBodySchema: () => buildActionBodySchema,
|
|
@@ -58,7 +58,8 @@ function createActionRouter(fastify, config) {
|
|
|
58
58
|
const { urlPath, actionSubset, hasId } = mountOpts;
|
|
59
59
|
if (actionSubset.length === 0) return;
|
|
60
60
|
const subsetSet = new Set(actionSubset);
|
|
61
|
-
const
|
|
61
|
+
const perActionPermissions = actionSubset.map((name) => actionPermissions[name] ?? globalAuth);
|
|
62
|
+
const authMw = buildAuthMiddlewareForPermissions(fastify, perActionPermissions);
|
|
62
63
|
const subsetPermissions = {};
|
|
63
64
|
for (const name of actionSubset) {
|
|
64
65
|
const perm = actionPermissions[name];
|
|
@@ -90,7 +91,8 @@ function createActionRouter(fastify, config) {
|
|
|
90
91
|
if (!submitted || !subsetSet.has(submitted)) {
|
|
91
92
|
const wrongMount = submitted && allActionNames.includes(submitted) ? submitted : void 0;
|
|
92
93
|
const otherMount = hasId ? "/action" : "/:id/action";
|
|
93
|
-
|
|
94
|
+
const message = wrongMount ? `Action '${wrongMount}' on '${resourceName}' is mounted at 'POST ${otherMount}', not 'POST ${urlPath}'` : submitted ? `Unknown action '${submitted}' on '${resourceName}'. Valid at 'POST ${urlPath}': ${actionSubset.join(", ")}` : `Missing 'action' field on '${resourceName}'. Valid at 'POST ${urlPath}': ${actionSubset.join(", ")}`;
|
|
95
|
+
throw createError(400, message, {
|
|
94
96
|
code: "arc.invalid_action",
|
|
95
97
|
validActions: actionSubset,
|
|
96
98
|
mount: urlPath,
|
|
@@ -141,7 +143,8 @@ function createActionRouter(fastify, config) {
|
|
|
141
143
|
const handler = wrappedHandlers.get(action);
|
|
142
144
|
if (!handler) throw createError(400, `Invalid action '${action}'. Valid actions: ${actionSubset.join(", ")}`, { validActions: actionSubset });
|
|
143
145
|
try {
|
|
144
|
-
|
|
146
|
+
const response = await handler(id, data, req);
|
|
147
|
+
sendControllerResponse(reply, response, req);
|
|
145
148
|
return reply;
|
|
146
149
|
} catch (error) {
|
|
147
150
|
if (onError) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { n as evaluateAndApplyPermission } from "./authorizationDecision-
|
|
3
|
-
import { f as createError } from "./errors-
|
|
4
|
-
import { u as getRequestScope } from "./types-
|
|
5
|
-
import { a as buildRouteHooks, c as buildAuthMiddleware, i as selectPluginMw, r as resolveRouterPluginMw, s as routeHookOptions, t as buildRateLimitConfig, u as buildArcDecorator } from "./rateLimit-
|
|
6
|
-
import { n as validateAggregations } from "./validate-
|
|
7
|
-
import { t as buildAggregationHandler } from "./buildHandler-
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { n as evaluateAndApplyPermission } from "./authorizationDecision-__T3EJDA.mjs";
|
|
3
|
+
import { f as createError } from "./errors-Bh1KK5ps.mjs";
|
|
4
|
+
import { u as getRequestScope } from "./types-DXYX7dIR.mjs";
|
|
5
|
+
import { a as buildRouteHooks, c as buildAuthMiddleware, i as selectPluginMw, r as resolveRouterPluginMw, s as routeHookOptions, t as buildRateLimitConfig, u as buildArcDecorator } from "./rateLimit-C7mmAGs3.mjs";
|
|
6
|
+
import { n as validateAggregations } from "./validate-PMCPR9El.mjs";
|
|
7
|
+
import { t as buildAggregationHandler } from "./buildHandler-Dn7rzUJo.mjs";
|
|
8
8
|
//#region src/core/aggregation/createAggregationRouter.ts
|
|
9
9
|
/**
|
|
10
10
|
* Register one Fastify route per aggregation. No-op when the map is
|
|
@@ -45,11 +45,13 @@ function registerOne(fastify, normalized, ctx) {
|
|
|
45
45
|
const ctx = buildPermissionContextLite(req, normalized.name);
|
|
46
46
|
await evaluateAndApplyPermission(permissionFn, ctx, req, reply, { defaultDenialMessage: (user) => user ? "You do not have permission to access this aggregation." : "Authentication required to access this aggregation." });
|
|
47
47
|
};
|
|
48
|
+
const pluginMwAll = resolveRouterPluginMw(fastify, false);
|
|
49
|
+
const pluginMw = selectPluginMw("GET", pluginMwAll);
|
|
48
50
|
const hooks = buildRouteHooks({
|
|
49
51
|
arcDecorator,
|
|
50
52
|
authMw,
|
|
51
53
|
permissionMw,
|
|
52
|
-
pluginMw
|
|
54
|
+
pluginMw,
|
|
53
55
|
routeGuards,
|
|
54
56
|
customMws: middlewares
|
|
55
57
|
});
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { t as __exportAll } from "./rolldown-runtime-
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-BhflRrBs.mjs";
|
|
3
3
|
import { arcLog, configureArcLogger, createPinoWriter } from "./logger/index.mjs";
|
|
4
|
-
import { n as PUBLIC_SCOPE } from "./types-
|
|
5
|
-
import { t as createTenantKeyGenerator } from "./rateLimitKey-
|
|
6
|
-
import { i as createRequestIdGenerator, r as mergeHealthChecks } from "./health-
|
|
7
|
-
import { t as parseJsonBody } from "./jsonBody-
|
|
8
|
-
import { r as wrapWithBoundary } from "./subscribe-helpers-
|
|
4
|
+
import { n as PUBLIC_SCOPE } from "./types-DXYX7dIR.mjs";
|
|
5
|
+
import { t as createTenantKeyGenerator } from "./rateLimitKey-CccEFBfk.mjs";
|
|
6
|
+
import { i as createRequestIdGenerator, r as mergeHealthChecks } from "./health-5XnTa2uo.mjs";
|
|
7
|
+
import { t as parseJsonBody } from "./jsonBody-DDSR2HFl.mjs";
|
|
8
|
+
import { r as wrapWithBoundary } from "./subscribe-helpers-sp5xTDVA.mjs";
|
|
9
9
|
import Fastify from "fastify";
|
|
10
10
|
import qs from "qs";
|
|
11
11
|
//#region src/factory/security/pluginLoader.ts
|
|
@@ -183,12 +183,15 @@ async function resolveContribution(contribution, fastify) {
|
|
|
183
183
|
* them. The original error is preserved via `{ cause }`.
|
|
184
184
|
*/
|
|
185
185
|
async function resolveModuleArm(module, arm, contribution, fastify) {
|
|
186
|
+
let resolved;
|
|
186
187
|
try {
|
|
187
|
-
|
|
188
|
+
resolved = await resolveContribution(contribution, fastify);
|
|
188
189
|
} catch (err) {
|
|
189
190
|
const msg = err instanceof Error ? err.message : String(err);
|
|
190
191
|
throw new Error(`[arc] module "${module.name}" ${arm} factory threw: ${msg}`, { cause: err });
|
|
191
192
|
}
|
|
193
|
+
if (!Array.isArray(resolved)) throw new TypeError(`[arc] module "${module.name}" ${arm} factory must return an array — received ${resolved === null ? "null" : typeof resolved}.`);
|
|
194
|
+
return resolved;
|
|
192
195
|
}
|
|
193
196
|
//#endregion
|
|
194
197
|
//#region src/factory/module/contributions.ts
|
|
@@ -227,11 +230,12 @@ async function collectModuleWorkflows(fastify, modules) {
|
|
|
227
230
|
* modules. The caller passes the returned definitions to the canonical
|
|
228
231
|
* schedules plugin; factories must therefore be resolved only once.
|
|
229
232
|
*/
|
|
230
|
-
async function collectModuleScheduledJobs(fastify, modules) {
|
|
233
|
+
async function collectModuleScheduledJobs(fastify, modules, countsByModule) {
|
|
231
234
|
const owner = /* @__PURE__ */ new Map();
|
|
232
235
|
const out = [];
|
|
233
236
|
for (const m of modules) {
|
|
234
237
|
const jobs = await resolveModuleArm(m, "scheduledJobs", m.scheduledJobs, fastify);
|
|
238
|
+
countsByModule?.set(m.name, jobs.length);
|
|
235
239
|
for (const job of jobs) {
|
|
236
240
|
const prior = owner.get(job.name);
|
|
237
241
|
if (prior !== void 0) throw new Error(`[arc] duplicate scheduled-job name "${job.name}" — declared by module "${prior}" and module "${m.name}". Scheduled-job names must be unique across the module graph.`);
|
|
@@ -242,6 +246,69 @@ async function collectModuleScheduledJobs(fastify, modules) {
|
|
|
242
246
|
return out;
|
|
243
247
|
}
|
|
244
248
|
//#endregion
|
|
249
|
+
//#region src/factory/module/descriptor.ts
|
|
250
|
+
/**
|
|
251
|
+
* Build a descriptor. Called by `registerResources` once per module, after
|
|
252
|
+
* resources are resolved and `owns` is effective.
|
|
253
|
+
*
|
|
254
|
+
* Frozen at every level: a descriptor is a snapshot of a completed decision,
|
|
255
|
+
* and a consumer mutating it would silently disagree with the running app.
|
|
256
|
+
*/
|
|
257
|
+
function describeResolvedModule(input) {
|
|
258
|
+
return Object.freeze({
|
|
259
|
+
name: input.name,
|
|
260
|
+
dependsOn: Object.freeze([...input.dependsOn ?? []]),
|
|
261
|
+
resources: Object.freeze(input.resources.map((r) => Object.freeze({
|
|
262
|
+
...r.name !== void 0 ? { name: r.name } : {},
|
|
263
|
+
...r.prefix !== void 0 ? { prefix: r.prefix } : {},
|
|
264
|
+
skipGlobalPrefix: r.skipGlobalPrefix === true
|
|
265
|
+
}))),
|
|
266
|
+
owns: Object.freeze([...input.owns]),
|
|
267
|
+
lifecycle: Object.freeze({ ...input.lifecycle })
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
//#endregion
|
|
271
|
+
//#region src/factory/module/disposers.ts
|
|
272
|
+
function createDisposerRegistry(fastify) {
|
|
273
|
+
const stacks = /* @__PURE__ */ new Map();
|
|
274
|
+
const drained = /* @__PURE__ */ new Set();
|
|
275
|
+
const contexts = /* @__PURE__ */ new Map();
|
|
276
|
+
return {
|
|
277
|
+
contextFor(moduleName) {
|
|
278
|
+
const existing = contexts.get(moduleName);
|
|
279
|
+
if (existing) return existing;
|
|
280
|
+
const ctx = { defer(disposer) {
|
|
281
|
+
if (typeof disposer !== "function") throw new TypeError(`[arc] module "${moduleName}" called defer() with a ${typeof disposer} — expected a function.`);
|
|
282
|
+
if (drained.has(moduleName)) {
|
|
283
|
+
(async () => {
|
|
284
|
+
try {
|
|
285
|
+
await disposer();
|
|
286
|
+
} catch (err) {
|
|
287
|
+
fastify.log?.error({
|
|
288
|
+
err,
|
|
289
|
+
module: moduleName
|
|
290
|
+
}, `[arc] module "${moduleName}" deferred a disposer after teardown had already run; it was invoked immediately and threw.`);
|
|
291
|
+
}
|
|
292
|
+
})();
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
const stack = stacks.get(moduleName);
|
|
296
|
+
if (stack) stack.push(disposer);
|
|
297
|
+
else stacks.set(moduleName, [disposer]);
|
|
298
|
+
} };
|
|
299
|
+
contexts.set(moduleName, ctx);
|
|
300
|
+
return ctx;
|
|
301
|
+
},
|
|
302
|
+
take(moduleName) {
|
|
303
|
+
drained.add(moduleName);
|
|
304
|
+
const stack = stacks.get(moduleName);
|
|
305
|
+
if (!stack?.length) return [];
|
|
306
|
+
stacks.delete(moduleName);
|
|
307
|
+
return stack.reverse();
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
//#endregion
|
|
245
312
|
//#region src/factory/module/lifecycle.ts
|
|
246
313
|
/**
|
|
247
314
|
* Subscribe every module's `eventHandlers` in dependency order (pass the
|
|
@@ -253,12 +320,13 @@ async function collectModuleScheduledJobs(fastify, modules) {
|
|
|
253
320
|
* Resolves factory contributions (after bootstraps) so a handler can close over
|
|
254
321
|
* booted engines rather than a global getter.
|
|
255
322
|
*/
|
|
256
|
-
async function subscribeModuleEventHandlers(fastify, modules) {
|
|
323
|
+
async function subscribeModuleEventHandlers(fastify, modules, countsByModule) {
|
|
257
324
|
const unsubscribes = [];
|
|
258
325
|
const owner = /* @__PURE__ */ new Map();
|
|
259
326
|
try {
|
|
260
327
|
for (const m of modules) {
|
|
261
328
|
const handlers = await resolveModuleArm(m, "eventHandlers", m.eventHandlers, fastify);
|
|
329
|
+
countsByModule?.set(m.name, handlers.length);
|
|
262
330
|
if (handlers.length === 0) continue;
|
|
263
331
|
const bus = fastify.events;
|
|
264
332
|
if (!bus) throw new Error(`[arc] module "${m.name}" declares eventHandlers but the event subsystem is unavailable (fastify.events). Enable arcPlugins.events.`);
|
|
@@ -460,7 +528,7 @@ function getModuleState(fastify, name) {
|
|
|
460
528
|
}
|
|
461
529
|
//#endregion
|
|
462
530
|
//#region src/factory/module/teardown.ts
|
|
463
|
-
function createModuleTeardown(fastify, modules) {
|
|
531
|
+
function createModuleTeardown(fastify, modules, disposers) {
|
|
464
532
|
const initializedNames = /* @__PURE__ */ new Set();
|
|
465
533
|
const consumed = /* @__PURE__ */ new Set();
|
|
466
534
|
async function closeInitialized() {
|
|
@@ -469,18 +537,30 @@ function createModuleTeardown(fastify, modules) {
|
|
|
469
537
|
const m = modules[index];
|
|
470
538
|
if (!m || !initializedNames.has(m.name) || consumed.has(m.name)) continue;
|
|
471
539
|
consumed.add(m.name);
|
|
472
|
-
|
|
540
|
+
const stack = disposers?.take(m.name) ?? [];
|
|
541
|
+
if (!m.onClose && stack.length === 0) {
|
|
473
542
|
setModuleState(fastify, m.name, "closed");
|
|
474
543
|
continue;
|
|
475
544
|
}
|
|
476
545
|
setModuleState(fastify, m.name, "closing");
|
|
477
|
-
|
|
546
|
+
let teardownFailed = false;
|
|
547
|
+
if (m.onClose) try {
|
|
478
548
|
await m.onClose(fastify);
|
|
479
|
-
setModuleState(fastify, m.name, "closed");
|
|
480
549
|
} catch (err) {
|
|
481
|
-
|
|
550
|
+
teardownFailed = true;
|
|
482
551
|
errors.push(new Error(`[arc] module "${m.name}" onClose() threw during teardown: ${err instanceof Error ? err.message : String(err)}`, { cause: err }));
|
|
483
552
|
}
|
|
553
|
+
for (let d = 0; d < stack.length; d++) {
|
|
554
|
+
const dispose = stack[d];
|
|
555
|
+
if (!dispose) continue;
|
|
556
|
+
try {
|
|
557
|
+
await dispose();
|
|
558
|
+
} catch (err) {
|
|
559
|
+
teardownFailed = true;
|
|
560
|
+
errors.push(new Error(`[arc] module "${m.name}" deferred disposer #${stack.length - d} threw during teardown: ${err instanceof Error ? err.message : String(err)}`, { cause: err }));
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
setModuleState(fastify, m.name, teardownFailed ? "failed" : "closed");
|
|
484
564
|
}
|
|
485
565
|
return errors;
|
|
486
566
|
}
|
|
@@ -554,8 +634,8 @@ const productionPreset = {
|
|
|
554
634
|
exposeStatusRoute: true,
|
|
555
635
|
maxEventLoopDelay: 3e3,
|
|
556
636
|
maxEventLoopUtilization: .98,
|
|
557
|
-
maxHeapUsedBytes:
|
|
558
|
-
maxRssBytes:
|
|
637
|
+
maxHeapUsedBytes: 1073741824,
|
|
638
|
+
maxRssBytes: 1073741824
|
|
559
639
|
}
|
|
560
640
|
};
|
|
561
641
|
/**
|
|
@@ -625,7 +705,7 @@ const testingPreset = {
|
|
|
625
705
|
arcPlugins: { gracefulShutdown: false },
|
|
626
706
|
sensible: true,
|
|
627
707
|
multipart: { limits: {
|
|
628
|
-
fileSize:
|
|
708
|
+
fileSize: 1048576,
|
|
629
709
|
files: 5
|
|
630
710
|
} }
|
|
631
711
|
};
|
|
@@ -719,7 +799,7 @@ async function registerArcCore(fastify, config, trackPlugin) {
|
|
|
719
799
|
await fastify.register(arcCorePlugin, { emitEvents: config.arcPlugins?.emitEvents !== false });
|
|
720
800
|
trackPlugin("arc-core");
|
|
721
801
|
if (config.arcPlugins?.events !== false) {
|
|
722
|
-
const { default: eventPlugin } = await import("./eventPlugin-
|
|
802
|
+
const { default: eventPlugin } = await import("./eventPlugin-Dk_TyXeE.mjs").then((n) => n.n);
|
|
723
803
|
const eventOpts = typeof config.arcPlugins?.events === "object" ? config.arcPlugins.events : {};
|
|
724
804
|
await fastify.register(eventPlugin, {
|
|
725
805
|
...eventOpts,
|
|
@@ -767,43 +847,47 @@ async function registerArcPlugins(fastify, config, trackPlugin, modules, moduleH
|
|
|
767
847
|
trackPlugin("arc-graceful-shutdown");
|
|
768
848
|
}
|
|
769
849
|
if (config.arcPlugins?.caching) {
|
|
770
|
-
const { default: cachingPlugin } = await import("./caching-
|
|
850
|
+
const { default: cachingPlugin } = await import("./caching-DFJqHyFs.mjs").then((n) => n.r);
|
|
771
851
|
const opts = config.arcPlugins.caching === true ? {} : config.arcPlugins.caching;
|
|
772
852
|
await fastify.register(cachingPlugin, opts);
|
|
773
853
|
trackPlugin("arc-caching", opts);
|
|
774
854
|
}
|
|
775
855
|
if (config.arcPlugins?.queryCache) {
|
|
776
|
-
const { queryCachePlugin } = await import("./queryCachePlugin-
|
|
856
|
+
const { queryCachePlugin } = await import("./queryCachePlugin-Dhps-Ldt.mjs").then((n) => n.n);
|
|
777
857
|
const opts = config.arcPlugins.queryCache === true ? {} : config.arcPlugins.queryCache;
|
|
778
|
-
const store = config.stores?.queryCache ?? new (await (import("./memory-
|
|
858
|
+
const store = config.stores?.queryCache ?? new (await (import("./memory-DsuWnj4T.mjs").then((n) => n.n))).MemoryCacheStore();
|
|
779
859
|
await fastify.register(queryCachePlugin, {
|
|
780
860
|
store,
|
|
781
861
|
...opts
|
|
782
862
|
});
|
|
783
863
|
trackPlugin("arc-query-cache", opts);
|
|
784
864
|
}
|
|
785
|
-
if (config.arcPlugins?.sse)
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
865
|
+
if (config.arcPlugins?.sse) {
|
|
866
|
+
if (config.arcPlugins?.events === false) fastify.log.warn("SSE plugin requires events plugin (arcPlugins.events). SSE disabled.");
|
|
867
|
+
else {
|
|
868
|
+
const { default: ssePlugin } = await import("./sse-B9P4Y-UI.mjs").then((n) => n.r);
|
|
869
|
+
const opts = config.arcPlugins.sse === true ? {} : config.arcPlugins.sse;
|
|
870
|
+
await fastify.register(ssePlugin, opts);
|
|
871
|
+
trackPlugin("arc-sse", opts);
|
|
872
|
+
}
|
|
791
873
|
}
|
|
792
|
-
if (config.arcPlugins?.realtime)
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
874
|
+
if (config.arcPlugins?.realtime) {
|
|
875
|
+
if (config.arcPlugins?.events === false) fastify.log.warn("Realtime plugin requires events plugin (arcPlugins.events). Realtime disabled.");
|
|
876
|
+
else {
|
|
877
|
+
const { default: realtimePlugin } = await import("./realtime-DVvVZZFz.mjs").then((n) => n.r);
|
|
878
|
+
const opts = config.arcPlugins.realtime === true ? {} : config.arcPlugins.realtime;
|
|
879
|
+
await fastify.register(realtimePlugin, opts);
|
|
880
|
+
trackPlugin("arc-realtime", opts);
|
|
881
|
+
}
|
|
798
882
|
}
|
|
799
883
|
if (config.arcPlugins?.metrics) {
|
|
800
|
-
const { default: metricsPlugin } = await import("./metrics-
|
|
884
|
+
const { default: metricsPlugin } = await import("./metrics-DdQL8syd.mjs").then((n) => n.r);
|
|
801
885
|
const opts = config.arcPlugins.metrics === true ? {} : config.arcPlugins.metrics;
|
|
802
886
|
await fastify.register(metricsPlugin, opts);
|
|
803
887
|
trackPlugin("arc-metrics", opts);
|
|
804
888
|
}
|
|
805
889
|
if (config.arcPlugins?.versioning) {
|
|
806
|
-
const { default: versioningPlugin } = await import("./versioning-
|
|
890
|
+
const { default: versioningPlugin } = await import("./versioning-CKv2jz_U.mjs").then((n) => n.r);
|
|
807
891
|
await fastify.register(versioningPlugin, config.arcPlugins.versioning);
|
|
808
892
|
trackPlugin("arc-versioning", config.arcPlugins.versioning);
|
|
809
893
|
}
|
|
@@ -849,10 +933,12 @@ async function registerAuth(fastify, config, trackPlugin) {
|
|
|
849
933
|
fastify.decorate("authenticate", async (request, reply) => {
|
|
850
934
|
await authenticate(request, reply);
|
|
851
935
|
});
|
|
852
|
-
if (!fastify.hasDecorator("optionalAuthenticate"))
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
936
|
+
if (!fastify.hasDecorator("optionalAuthenticate")) {
|
|
937
|
+
if (optionalAuthenticate) fastify.decorate("optionalAuthenticate", async (request, reply) => {
|
|
938
|
+
await optionalAuthenticate(request, reply);
|
|
939
|
+
});
|
|
940
|
+
else fastify.decorate("optionalAuthenticate", createOptionalAuthenticate(authenticate));
|
|
941
|
+
}
|
|
856
942
|
trackPlugin("auth-authenticator");
|
|
857
943
|
fastify.log.debug("Custom authenticator enabled");
|
|
858
944
|
break;
|
|
@@ -872,7 +958,7 @@ async function registerAuth(fastify, config, trackPlugin) {
|
|
|
872
958
|
*/
|
|
873
959
|
async function registerElevation(fastify, config, trackPlugin) {
|
|
874
960
|
if (!config.elevation) return;
|
|
875
|
-
const { elevationPlugin } = await import("./elevation-
|
|
961
|
+
const { elevationPlugin } = await import("./elevation-DNXXxgjl.mjs").then((n) => n.r);
|
|
876
962
|
await fastify.register(elevationPlugin, config.elevation);
|
|
877
963
|
trackPlugin("arc-elevation", config.elevation);
|
|
878
964
|
fastify.log.debug("Elevation plugin enabled");
|
|
@@ -887,7 +973,7 @@ async function registerElevation(fastify, config, trackPlugin) {
|
|
|
887
973
|
*/
|
|
888
974
|
async function registerErrorHandler(fastify, config, trackPlugin, moduleErrorMappers) {
|
|
889
975
|
if (config.errorHandler === false) return;
|
|
890
|
-
const { errorHandlerPlugin } = await import("./errorHandler-
|
|
976
|
+
const { errorHandlerPlugin } = await import("./errorHandler-B2AZUJUj.mjs").then((n) => n.r);
|
|
891
977
|
let errorOpts = typeof config.errorHandler === "object" ? config.errorHandler : { includeStack: config.preset !== "production" };
|
|
892
978
|
if (moduleErrorMappers && moduleErrorMappers.length > 0) errorOpts = {
|
|
893
979
|
...errorOpts,
|
|
@@ -997,7 +1083,8 @@ async function registerResources(fastify, config, preResolvedModules) {
|
|
|
997
1083
|
}
|
|
998
1084
|
const modules = preResolvedModules ?? orderModules(await Promise.all((config.modules ?? []).map((m) => resolveModule(m))));
|
|
999
1085
|
initModuleStates(fastify, modules.map((m) => m.name));
|
|
1000
|
-
const
|
|
1086
|
+
const disposers = createDisposerRegistry(fastify);
|
|
1087
|
+
const teardown = createModuleTeardown(fastify, modules, disposers);
|
|
1001
1088
|
let eventUnsubscribes = [];
|
|
1002
1089
|
try {
|
|
1003
1090
|
if (config.plugins) {
|
|
@@ -1008,7 +1095,8 @@ async function registerResources(fastify, config, preResolvedModules) {
|
|
|
1008
1095
|
if (!m.plugins) continue;
|
|
1009
1096
|
teardown.markInitialized(m);
|
|
1010
1097
|
try {
|
|
1011
|
-
await m.plugins(fastify);
|
|
1098
|
+
const returned = await m.plugins(fastify, disposers.contextFor(m.name));
|
|
1099
|
+
if (typeof returned === "function") disposers.contextFor(m.name).defer(returned);
|
|
1012
1100
|
} catch (err) {
|
|
1013
1101
|
setModuleState(fastify, m.name, "failed");
|
|
1014
1102
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -1025,7 +1113,7 @@ async function registerResources(fastify, config, preResolvedModules) {
|
|
|
1025
1113
|
teardown.markInitialized(m);
|
|
1026
1114
|
setModuleState(fastify, m.name, "bootstrapping");
|
|
1027
1115
|
try {
|
|
1028
|
-
exported = await m.bootstrap(fastify);
|
|
1116
|
+
exported = await m.bootstrap(fastify, disposers.contextFor(m.name));
|
|
1029
1117
|
} catch (err) {
|
|
1030
1118
|
setModuleState(fastify, m.name, "failed");
|
|
1031
1119
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -1048,6 +1136,7 @@ async function registerResources(fastify, config, preResolvedModules) {
|
|
|
1048
1136
|
if (isResourcesFactory(config.resources)) {
|
|
1049
1137
|
try {
|
|
1050
1138
|
resolvedResources = await config.resources(fastify);
|
|
1139
|
+
if (!Array.isArray(resolvedResources)) throw new TypeError(`resources factory must return an array — received ${resolvedResources === null ? "null" : typeof resolvedResources}`);
|
|
1051
1140
|
} catch (err) {
|
|
1052
1141
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1053
1142
|
fastify.log.error(`Resources factory threw during boot: ${msg}`);
|
|
@@ -1062,7 +1151,7 @@ async function registerResources(fastify, config, preResolvedModules) {
|
|
|
1062
1151
|
let discoveryPath;
|
|
1063
1152
|
let discoveryYieldedZero = false;
|
|
1064
1153
|
if (resolvedResources === void 0 && config.resourceDir) {
|
|
1065
|
-
const { loadResources } = await import("./loadResources-
|
|
1154
|
+
const { loadResources } = await import("./loadResources-DisEAmkm.mjs").then((n) => n.n);
|
|
1066
1155
|
const { resolve, dirname } = await import("node:path");
|
|
1067
1156
|
const { fileURLToPath } = await import("node:url");
|
|
1068
1157
|
const rawDir = config.resourceDir;
|
|
@@ -1077,6 +1166,7 @@ async function registerResources(fastify, config, preResolvedModules) {
|
|
|
1077
1166
|
resolvedResources = discovered;
|
|
1078
1167
|
}
|
|
1079
1168
|
const moduleResourceNames = /* @__PURE__ */ new Map();
|
|
1169
|
+
const perModuleResources = /* @__PURE__ */ new Map();
|
|
1080
1170
|
const moduleResources = [];
|
|
1081
1171
|
for (const m of modules) {
|
|
1082
1172
|
if (!m.resources) continue;
|
|
@@ -1087,24 +1177,37 @@ async function registerResources(fastify, config, preResolvedModules) {
|
|
|
1087
1177
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1088
1178
|
throw new Error(`[arc] module "${m.name}" resources factory threw: ${msg}. Check the module's bootstrap ran and its adapters received booted engines.`, { cause: err });
|
|
1089
1179
|
}
|
|
1180
|
+
if (!Array.isArray(rs)) throw new TypeError(`[arc] module "${m.name}" resources factory must return an array — received ${rs === null ? "null" : typeof rs}.`);
|
|
1090
1181
|
const names = /* @__PURE__ */ new Set();
|
|
1091
|
-
for (const r of rs)
|
|
1182
|
+
for (const r of rs) {
|
|
1183
|
+
if (r.name == null) continue;
|
|
1184
|
+
if (names.has(r.name)) throw new Error(`[arc] module "${m.name}" provides two resources named "${r.name}". Resource names must be unique within a module — arc registers one route group per name, so the second would be dropped.`);
|
|
1185
|
+
names.add(r.name);
|
|
1186
|
+
}
|
|
1092
1187
|
moduleResourceNames.set(m.name, names);
|
|
1188
|
+
perModuleResources.set(m.name, rs);
|
|
1093
1189
|
moduleResources.push(...rs);
|
|
1094
1190
|
}
|
|
1191
|
+
const effectiveOwns = /* @__PURE__ */ new Map();
|
|
1095
1192
|
for (const m of modules) {
|
|
1096
|
-
if (!m.owns?.length) continue;
|
|
1097
1193
|
const supplied = moduleResourceNames.get(m.name);
|
|
1194
|
+
if (m.owns === "provided") {
|
|
1195
|
+
if (!supplied?.size) throw new Error(`[arc] module "${m.name}" declares \`owns: "provided"\` but supplies no named resources. Either give it resources to own, or drop the \`owns\` entry — an empty claim is almost always a resources factory that returned early.`);
|
|
1196
|
+
effectiveOwns.set(m.name, [...supplied]);
|
|
1197
|
+
continue;
|
|
1198
|
+
}
|
|
1199
|
+
if (!m.owns?.length) continue;
|
|
1098
1200
|
const missing = m.owns.filter((name) => !supplied?.has(name));
|
|
1099
1201
|
if (missing.length > 0) {
|
|
1100
1202
|
const provided = supplied?.size ? [...supplied].join(", ") : "(none)";
|
|
1101
|
-
throw new Error(`[arc] module "${m.name}" declares owns: [${missing.map((n) => `"${n}"`).join(", ")}] but its own \`resources\` do not supply ${missing.length === 1 ? "that name" : "those names"}. \`owns\` DROPS the app-level resource of that name, so an unmet claim removes the route entirely and nothing serves it. Provide it in this module's \`resources\`,
|
|
1203
|
+
throw new Error(`[arc] module "${m.name}" declares owns: [${missing.map((n) => `"${n}"`).join(", ")}] but its own \`resources\` do not supply ${missing.length === 1 ? "that name" : "those names"}. \`owns\` DROPS the app-level resource of that name, so an unmet claim removes the route entirely and nothing serves it. Provide it in this module's \`resources\`, drop the \`owns\` entry, or use \`owns: "provided"\` to derive it.
|
|
1102
1204
|
Resources supplied by "${m.name}": ${provided}.`);
|
|
1103
1205
|
}
|
|
1206
|
+
effectiveOwns.set(m.name, m.owns);
|
|
1104
1207
|
}
|
|
1105
1208
|
if (modules.length && resolvedResources && resolvedResources.length > 0) {
|
|
1106
1209
|
const owned = /* @__PURE__ */ new Set();
|
|
1107
|
-
for (const m of modules) for (const name of m.
|
|
1210
|
+
for (const m of modules) for (const name of effectiveOwns.get(m.name) ?? []) owned.add(name);
|
|
1108
1211
|
if (owned.size > 0) {
|
|
1109
1212
|
const before = resolvedResources.length;
|
|
1110
1213
|
resolvedResources = resolvedResources.filter((r) => !(r.name != null && owned.has(r.name)));
|
|
@@ -1128,10 +1231,12 @@ Resources supplied by "${m.name}": ${provided}.`);
|
|
|
1128
1231
|
for (const resource of resolvedResources) if (resource.skipGlobalPrefix) root.push(resource);
|
|
1129
1232
|
else prefixed.push(resource);
|
|
1130
1233
|
for (const resource of root) await registerOne(fastify, resource, config.mountRoutes);
|
|
1131
|
-
if (prefixed.length)
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1234
|
+
if (prefixed.length) {
|
|
1235
|
+
if (config.resourcePrefix) await fastify.register(async (scoped) => {
|
|
1236
|
+
for (const resource of prefixed) await registerOne(scoped, resource, config.mountRoutes);
|
|
1237
|
+
}, { prefix: config.resourcePrefix });
|
|
1238
|
+
else for (const resource of prefixed) await registerOne(fastify, resource, config.mountRoutes);
|
|
1239
|
+
}
|
|
1135
1240
|
const names = resolvedResources.map((r) => r.name ?? "?").join(", ");
|
|
1136
1241
|
const prefix = config.resourcePrefix ? ` (prefix: ${config.resourcePrefix})` : "";
|
|
1137
1242
|
fastify.log.info(`${resolvedResources.length} resource(s) registered${prefix}: ${names}`);
|
|
@@ -1144,19 +1249,21 @@ Resources supplied by "${m.name}": ${provided}.`);
|
|
|
1144
1249
|
for (const m of modules) {
|
|
1145
1250
|
if (!m.afterResources) continue;
|
|
1146
1251
|
try {
|
|
1147
|
-
await m.afterResources(fastify);
|
|
1252
|
+
const returned = await m.afterResources(fastify, disposers.contextFor(m.name));
|
|
1253
|
+
if (typeof returned === "function") disposers.contextFor(m.name).defer(returned);
|
|
1148
1254
|
} catch (err) {
|
|
1149
1255
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1150
1256
|
throw new Error(`[arc] module "${m.name}" afterResources() threw: ${msg}`, { cause: err });
|
|
1151
1257
|
}
|
|
1152
1258
|
}
|
|
1153
|
-
const
|
|
1259
|
+
const scheduleCounts = /* @__PURE__ */ new Map();
|
|
1260
|
+
const scheduledJobs = await collectModuleScheduledJobs(fastify, modules, scheduleCounts);
|
|
1154
1261
|
if (scheduledJobs.length > 0) {
|
|
1155
1262
|
if (config.arcPlugins?.schedules === false) throw new Error("[arc] modules declare scheduledJobs but arcPlugins.schedules is false. Enable the scheduler or remove the declarations.");
|
|
1156
1263
|
if (fastify.hasDecorator("getScheduleStats")) throw new Error("[arc] modules declare scheduledJobs but schedulesPlugin was already registered manually. Configure their runner through arcPlugins.schedules so Arc can compose one schedule table.");
|
|
1157
1264
|
const frozenJobs = Object.freeze(scheduledJobs.map((job) => Object.freeze({ ...job })));
|
|
1158
1265
|
const scheduleOptions = typeof config.arcPlugins?.schedules === "object" ? config.arcPlugins.schedules : {};
|
|
1159
|
-
const { default: schedulesPlugin } = await import("./schedules-
|
|
1266
|
+
const { default: schedulesPlugin } = await import("./schedules-C2Q3uv2d.mjs").then((n) => n.r);
|
|
1160
1267
|
await fastify.register(schedulesPlugin, {
|
|
1161
1268
|
...scheduleOptions,
|
|
1162
1269
|
schedules: frozenJobs
|
|
@@ -1170,7 +1277,21 @@ Resources supplied by "${m.name}": ${provided}.`);
|
|
|
1170
1277
|
});
|
|
1171
1278
|
}
|
|
1172
1279
|
}
|
|
1173
|
-
|
|
1280
|
+
const subscriptionCounts = /* @__PURE__ */ new Map();
|
|
1281
|
+
eventUnsubscribes = await subscribeModuleEventHandlers(fastify, modules, subscriptionCounts);
|
|
1282
|
+
if (fastify.arc) fastify.arc.moduleDescriptors = Object.freeze(modules.map((m) => describeResolvedModule({
|
|
1283
|
+
name: m.name,
|
|
1284
|
+
dependsOn: m.dependsOn,
|
|
1285
|
+
resources: perModuleResources.get(m.name) ?? [],
|
|
1286
|
+
owns: effectiveOwns.get(m.name) ?? [],
|
|
1287
|
+
lifecycle: {
|
|
1288
|
+
hasClose: typeof m.onClose === "function",
|
|
1289
|
+
subscriptions: subscriptionCounts.get(m.name) ?? 0,
|
|
1290
|
+
scheduledJobs: scheduleCounts.get(m.name) ?? 0,
|
|
1291
|
+
healthChecks: m.healthChecks?.length ?? 0,
|
|
1292
|
+
exports: typeof m.bootstrap === "function"
|
|
1293
|
+
}
|
|
1294
|
+
})));
|
|
1174
1295
|
if (config.afterResources) {
|
|
1175
1296
|
await config.afterResources(fastify);
|
|
1176
1297
|
fastify.log.debug("afterResources hook executed");
|
|
@@ -1399,7 +1520,7 @@ async function registerUtilityPlugins(fastify, config) {
|
|
|
1399
1520
|
throwFileSizeLimit: true,
|
|
1400
1521
|
...hostMultipart,
|
|
1401
1522
|
limits: {
|
|
1402
|
-
fileSize:
|
|
1523
|
+
fileSize: 10485760,
|
|
1403
1524
|
files: 10,
|
|
1404
1525
|
fields: 100,
|
|
1405
1526
|
parts: 120,
|
|
@@ -1683,7 +1804,7 @@ async function buildApp(options, onInstance) {
|
|
|
1683
1804
|
await registerErrorHandler(fastify, config, trackPlugin, moduleErrorMappers);
|
|
1684
1805
|
await registerResources(fastify, config, resolvedModules);
|
|
1685
1806
|
if (config.replyHelpers) {
|
|
1686
|
-
const { replyHelpersPlugin } = await import("./replyHelpers-
|
|
1807
|
+
const { replyHelpersPlugin } = await import("./replyHelpers-DS-P0b32.mjs").then((n) => n.n);
|
|
1687
1808
|
await fastify.register(replyHelpersPlugin);
|
|
1688
1809
|
}
|
|
1689
1810
|
if (config.serializeBigInt) {
|
|
@@ -1734,4 +1855,4 @@ const ArcFactory = {
|
|
|
1734
1855
|
}
|
|
1735
1856
|
};
|
|
1736
1857
|
//#endregion
|
|
1737
|
-
export {
|
|
1858
|
+
export { collectModuleWorkflows as _, edgePreset as a, testingPreset as c, hasModule as d, orderModules as f, collectModuleScheduledJobs as g, collectModuleHealthChecks as h, developmentPreset as i, workerPreset as l, describeResolvedModule as m, createApp as n, getPreset as o, subscribeModuleEventHandlers as p, createApp_exports as r, productionPreset as s, ArcFactory as t, getModuleState as u, resolveContribution as v, resolveModule as y };
|