@classytic/arc 2.20.0 → 2.21.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-D-MHZ27_.mjs → BaseController-BnLYgE9A.mjs} +2 -2
- package/dist/{EventTransport-IEn7Tn-Q.d.mts → EventTransport-QmY7A258.d.mts} +0 -1
- package/dist/{QueryCache-TRfXau3W.d.mts → QueryCache-Z1B38koh.d.mts} +0 -1
- package/dist/{actionPermissions-C9RMiIpc.mjs → actionPermissions-ze70xXJi.mjs} +1 -1
- package/dist/audit/index.d.mts +9 -5
- package/dist/auth/audit.d.mts +7 -4
- package/dist/auth/audit.mjs +5 -0
- package/dist/auth/index.d.mts +7 -14
- package/dist/auth/index.mjs +1 -1
- package/dist/auth/redis-session.d.mts +1 -2
- package/dist/cache/index.d.mts +2 -3
- package/dist/cli/commands/describe.d.mts +1 -2
- package/dist/cli/commands/docs.mjs +1 -1
- package/dist/cli/commands/init.mjs +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/context/index.d.mts +2 -2
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +4 -4
- package/dist/{core-CWhyGkiM.mjs → core-DZ6Xe1jR.mjs} +65 -10
- package/dist/{createActionRouter-HlQso0jO.mjs → createActionRouter-BWMDW-dL.mjs} +2 -2
- package/dist/{createAggregationRouter-5LzPzgw1.mjs → createAggregationRouter-l5mNdYrZ.mjs} +1 -1
- package/dist/{createApp-D6uwzCKu.mjs → createApp-Bi61XxqU.mjs} +149 -137
- package/dist/discovery/index.d.mts +0 -1
- package/dist/docs/index.d.mts +1 -2
- package/dist/docs/index.mjs +1 -1
- package/dist/{elevation-xGUBq6p_.d.mts → elevation-C9s5hFP_.d.mts} +0 -1
- package/dist/encryption/index.d.mts +2 -144
- package/dist/{errorHandler-BtUUDPEa.d.mts → errorHandler-B0e-bq-O.d.mts} +0 -1
- package/dist/{errors-DOHkjQlD.d.mts → errors-DHcHVAgk.d.mts} +0 -1
- package/dist/{eventPlugin-DbBFd3x_.d.mts → eventPlugin-A6EbthXR.d.mts} +10 -6
- package/dist/events/index.d.mts +9 -6
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis.d.mts +1 -2
- package/dist/factory/index.d.mts +4 -4
- package/dist/factory/index.mjs +2 -2
- package/dist/{fastify-augmentation-CCQJEDgh.d.mts → fastify-augmentation-DafigGQp.d.mts} +2 -3
- package/dist/{fields-C7ahdGYf.d.mts → fields-BGqrAa_u.d.mts} +1 -2
- package/dist/hooks/index.d.mts +1 -1
- package/dist/idempotency/index.d.mts +4 -3
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/{index-DUa8WHz3.d.mts → index-B5N-NaHs.d.mts} +88 -7
- package/dist/{index-CdFkIMEd.d.mts → index-B5PoNbfu.d.mts} +36 -7
- package/dist/{index-_--GyzcO.d.mts → index-Dtrj6XZk.d.mts} +62 -28
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +6 -6
- package/dist/{init-YH_nslQR.mjs → init-0YhHkXGk.mjs} +154 -137
- package/dist/integrations/event-gateway.d.mts +2 -3
- package/dist/integrations/index.d.mts +2 -2
- package/dist/integrations/jobs.d.mts +0 -1
- package/dist/integrations/mcp/index.d.mts +6 -7
- package/dist/integrations/mcp/index.mjs +1 -1
- package/dist/integrations/mcp/testing.d.mts +1 -2
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/integrations/streamline.d.mts +2 -2
- package/dist/integrations/webhooks.d.mts +0 -1
- package/dist/integrations/websocket-pushref-redis.d.mts +1 -2
- package/dist/integrations/websocket-redis.d.mts +1 -2
- package/dist/integrations/websocket.d.mts +2 -2
- package/dist/{loadResources-B8UmpITt.mjs → loadResources-DpU8pfjV.mjs} +4 -3
- package/dist/{mcpPlugin-CuW6L_uD.mjs → mcpPlugin-B9XjjNVG.mjs} +3 -3
- package/dist/middleware/index.d.mts +1 -2
- package/dist/{module-JYH9V0I8.d.mts → module-WeuU5jfd.d.mts} +46 -1
- package/dist/{openapi-Dq6RbEGK.mjs → openapi-Kyod_di6.mjs} +2 -2
- package/dist/permissions/index.d.mts +3 -3
- package/dist/permissions/index.mjs +2 -2
- package/dist/{permissions-CgbOLJZG.mjs → permissions-BJMuKMl7.mjs} +33 -1
- package/dist/pipeline/index.d.mts +1 -2
- package/dist/plugins/index.d.mts +79 -7
- package/dist/plugins/index.mjs +88 -1
- package/dist/plugins/response-cache.d.mts +5 -3
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/presets/filesUpload.d.mts +4 -5
- package/dist/presets/filesUpload.mjs +1 -1
- package/dist/presets/index.d.mts +1 -2
- package/dist/presets/index.mjs +1 -1
- package/dist/presets/multiTenant.d.mts +1 -2
- package/dist/presets/search.d.mts +2 -3
- package/dist/presets/search.mjs +1 -1
- package/dist/{presets-DWsYQdbV.mjs → presets-gw0ciIUD.mjs} +1 -1
- package/dist/{pushref-registry-DnCqL3aa.d.mts → pushref-registry-BbcnpNTm.d.mts} +4 -2
- package/dist/{queryCachePlugin-xzFyKAjT.d.mts → queryCachePlugin-CfYWq-Ak.d.mts} +1 -2
- package/dist/{redis-C3W0qbz8.d.mts → redis-UDtLaNj6.d.mts} +0 -1
- package/dist/{redis-stream-DsP1vqZB.d.mts → redis-stream-iVR2l7aS.d.mts} +1 -2
- package/dist/{registerRoute-DGSREwPw.mjs → registerRoute-oGAl0oA8.mjs} +1 -1
- package/dist/registry/index.d.mts +2 -2
- package/dist/schemas/index.d.mts +0 -1
- package/dist/scim/index.d.mts +0 -1
- package/dist/scope/index.d.mts +2 -3
- package/dist/{sessionManager-BXG-HGwG.d.mts → sessionManager-BHOM3N_0.d.mts} +10 -6
- package/dist/{storage-Co_PQpeQ.d.mts → storage-DLUZ04kK.d.mts} +8 -4
- package/dist/testing/index.d.mts +2 -3
- package/dist/testing/index.mjs +5 -2
- package/dist/testing/storageContract.d.mts +1 -2
- package/dist/{tracing-D8jlGXP7.d.mts → tracing-CsGKQJGg.d.mts} +0 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/types/storage.d.mts +1 -1
- package/dist/types-Cc91nXuA.d.mts +132 -0
- package/dist/{types-LNebCoJx.d.mts → types-DH0GupI7.d.mts} +8 -4
- package/dist/{types-C9b2HR5W.d.mts → types-DRj-Ut4n.d.mts} +1 -2
- package/dist/{types-BHMKlMBU.d.mts → types-DpxoNX5v.d.mts} +61 -21
- package/dist/utils/index.d.mts +182 -128
- package/dist/utils/index.mjs +2 -2
- package/dist/{utils-ChjYQpjn.mjs → utils-CO8a3B_1.mjs} +70 -26
- package/dist/{versioning-D_eBCfNr.d.mts → versioning-DQ4mCvg0.d.mts} +1 -2
- package/dist/{websocket-MlYlrYq0.d.mts → websocket-uuWqM6UY.d.mts} +5 -4
- package/package.json +7 -7
- package/skills/arc-module-publishing/SKILL.md +242 -0
- package/skills/arc-module-publishing/references/authoring-modules.md +272 -0
- package/skills/arc-module-publishing/references/package-manifest.md +155 -0
- package/skills/arc-module-publishing/references/publishing-workflow.md +182 -0
|
@@ -3,6 +3,134 @@ import { arcLog } from "./logger/index.mjs";
|
|
|
3
3
|
import { n as PUBLIC_SCOPE } from "./types-bHblZ9YN.mjs";
|
|
4
4
|
import Fastify from "fastify";
|
|
5
5
|
import qs from "qs";
|
|
6
|
+
//#region src/factory/module.ts
|
|
7
|
+
/**
|
|
8
|
+
* Resolve any module-input form to a concrete `ArcModule`. A thunk is invoked
|
|
9
|
+
* (this is where a dynamic `import()` fires); a promise (or plain module) is
|
|
10
|
+
* awaited. Called once per module at the start of the bootstrap phase.
|
|
11
|
+
*/
|
|
12
|
+
async function resolveModule(input) {
|
|
13
|
+
const resolved = typeof input === "function" ? await input() : await input;
|
|
14
|
+
if (!resolved || typeof resolved !== "object" || typeof resolved.name !== "string") throw new Error("[arc] a `modules` entry resolved to something that is not an ArcModule (expected an object with a string `name`). Check dynamic-import thunks return `createXModule(deps)` (or the module object), not the namespace.");
|
|
15
|
+
return resolved;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Order modules for composition by their `dependsOn` edges — a STABLE
|
|
19
|
+
* topological sort. Called once at the start of the bootstrap phase; every
|
|
20
|
+
* subsequent phase (bootstrap, resources, afterResources, and reverse-order
|
|
21
|
+
* onClose) iterates the returned list, so a module's declared dependencies are
|
|
22
|
+
* always composed before it.
|
|
23
|
+
*
|
|
24
|
+
* "Stable" = modules with no edge between them keep their original list order,
|
|
25
|
+
* so declaring `dependsOn` on one module never silently reorders an unrelated
|
|
26
|
+
* one. Backward compatible: a `modules` array with NO `dependsOn` anywhere is
|
|
27
|
+
* returned unchanged.
|
|
28
|
+
*
|
|
29
|
+
* Fail-fast — throws (never reorders past a broken contract) on:
|
|
30
|
+
* - duplicate module names (the name is the graph key)
|
|
31
|
+
* - a `dependsOn` name not present in the composed set
|
|
32
|
+
* - a self-reference (`dependsOn` includes the module's own name)
|
|
33
|
+
* - a dependency cycle (reports the concrete `a → b → … → a` path)
|
|
34
|
+
*/
|
|
35
|
+
function orderModules(modules) {
|
|
36
|
+
const byName = /* @__PURE__ */ new Map();
|
|
37
|
+
for (const m of modules) {
|
|
38
|
+
if (byName.has(m.name)) throw new Error(`[arc] Duplicate module name "${m.name}" — composed twice; check your modules array.`);
|
|
39
|
+
byName.set(m.name, m);
|
|
40
|
+
}
|
|
41
|
+
for (const m of modules) for (const dep of m.dependsOn ?? []) {
|
|
42
|
+
if (dep === m.name) throw new Error(`[arc] module "${m.name}" dependsOn itself — remove the self-reference.`);
|
|
43
|
+
if (!byName.has(dep)) throw new Error(`[arc] module "${m.name}" dependsOn "${dep}", which is not composed. Add the "${dep}" module to createApp({ modules }) (before this one is fine — arc orders them), or drop the dependency. Composed modules: ${[...byName.keys()].join(", ") || "(none)"}.`);
|
|
44
|
+
}
|
|
45
|
+
if (modules.every((m) => !m.dependsOn || m.dependsOn.length === 0)) return [...modules];
|
|
46
|
+
const originalIndex = /* @__PURE__ */ new Map();
|
|
47
|
+
let nextIndex = 0;
|
|
48
|
+
for (const m of modules) originalIndex.set(m.name, nextIndex++);
|
|
49
|
+
const pendingDeps = new Map(modules.map((m) => [m.name, (m.dependsOn ?? []).length]));
|
|
50
|
+
const dependents = /* @__PURE__ */ new Map();
|
|
51
|
+
for (const m of modules) for (const dep of m.dependsOn ?? []) {
|
|
52
|
+
const list = dependents.get(dep);
|
|
53
|
+
if (list) list.push(m.name);
|
|
54
|
+
else dependents.set(dep, [m.name]);
|
|
55
|
+
}
|
|
56
|
+
const ordered = [];
|
|
57
|
+
const remaining = new Set(modules.map((m) => m.name));
|
|
58
|
+
while (remaining.size > 0) {
|
|
59
|
+
let pick;
|
|
60
|
+
let pickIndex = Number.POSITIVE_INFINITY;
|
|
61
|
+
for (const name of remaining) {
|
|
62
|
+
if (pendingDeps.get(name) !== 0) continue;
|
|
63
|
+
const index = originalIndex.get(name) ?? Number.POSITIVE_INFINITY;
|
|
64
|
+
if (index < pickIndex) {
|
|
65
|
+
pick = name;
|
|
66
|
+
pickIndex = index;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (pick === void 0) throw new Error(describeModuleCycle(remaining, byName));
|
|
70
|
+
const picked = byName.get(pick);
|
|
71
|
+
if (!picked) throw new Error(`[arc] internal: ordered module "${pick}" is missing from the index`);
|
|
72
|
+
ordered.push(picked);
|
|
73
|
+
remaining.delete(pick);
|
|
74
|
+
for (const dependent of dependents.get(pick) ?? []) pendingDeps.set(dependent, (pendingDeps.get(dependent) ?? 1) - 1);
|
|
75
|
+
}
|
|
76
|
+
return ordered;
|
|
77
|
+
}
|
|
78
|
+
/** Walk the still-unordered subgraph for one concrete cycle path. */
|
|
79
|
+
function describeModuleCycle(remaining, byName) {
|
|
80
|
+
const stack = [];
|
|
81
|
+
const onStack = /* @__PURE__ */ new Set();
|
|
82
|
+
const done = /* @__PURE__ */ new Set();
|
|
83
|
+
let cycle = null;
|
|
84
|
+
const walk = (name) => {
|
|
85
|
+
if (cycle) return;
|
|
86
|
+
stack.push(name);
|
|
87
|
+
onStack.add(name);
|
|
88
|
+
for (const dep of byName.get(name)?.dependsOn ?? []) {
|
|
89
|
+
if (!remaining.has(dep)) continue;
|
|
90
|
+
if (onStack.has(dep)) {
|
|
91
|
+
cycle = [...stack.slice(stack.indexOf(dep)), dep];
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (!done.has(dep)) walk(dep);
|
|
95
|
+
if (cycle) return;
|
|
96
|
+
}
|
|
97
|
+
onStack.delete(name);
|
|
98
|
+
stack.pop();
|
|
99
|
+
done.add(name);
|
|
100
|
+
};
|
|
101
|
+
for (const name of remaining) {
|
|
102
|
+
if (!done.has(name)) walk(name);
|
|
103
|
+
if (cycle) break;
|
|
104
|
+
}
|
|
105
|
+
return `[arc] module dependency cycle: ${cycle ? cycle.join(" → ") : [...remaining].join(", ")}. Modules cannot dependsOn each other circularly — break it with a shared module both point at, or wire the softer direction through an event/port instead of a hard dependsOn.`;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Identity helper for authoring a typed module — mirrors `defineResource`.
|
|
109
|
+
* Gives inference + a single obvious construction site; does no work.
|
|
110
|
+
*
|
|
111
|
+
* `TExports` is inferred from the `bootstrap` return value, so a module
|
|
112
|
+
* author gets a typed public export for free:
|
|
113
|
+
*
|
|
114
|
+
* ```ts
|
|
115
|
+
* export const accountingModule = (deps: Deps) =>
|
|
116
|
+
* defineModule({
|
|
117
|
+
* name: "accounting",
|
|
118
|
+
* bootstrap: async () => createAccountingEngine(deps), // TExports inferred
|
|
119
|
+
* });
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
function defineModule(module) {
|
|
123
|
+
return module;
|
|
124
|
+
}
|
|
125
|
+
function getModuleExports(fastify, name) {
|
|
126
|
+
const modules = fastify.arc?.modules;
|
|
127
|
+
if (!modules || !Object.hasOwn(modules, name)) {
|
|
128
|
+
const available = modules ? Object.keys(modules) : [];
|
|
129
|
+
throw new Error(`[arc] no public export recorded for module "${name}".\nA module's export is its bootstrap() return value; it is readable only AFTER that module's bootstrap ran (dependsOn / list order = init order).\nModules with recorded exports: ${available.length ? available.join(", ") : "(none)"}.`);
|
|
130
|
+
}
|
|
131
|
+
return modules[name];
|
|
132
|
+
}
|
|
133
|
+
//#endregion
|
|
6
134
|
//#region src/factory/presets.ts
|
|
7
135
|
/**
|
|
8
136
|
* Production preset - strict security, performance optimized
|
|
@@ -344,11 +472,20 @@ async function registerElevation(fastify, config, trackPlugin) {
|
|
|
344
472
|
}
|
|
345
473
|
/**
|
|
346
474
|
* Register error handler plugin (opt-out).
|
|
475
|
+
*
|
|
476
|
+
* `moduleErrorMappers` — mappers shipped by composed arc modules
|
|
477
|
+
* (`defineModule({ errorMappers })`), appended AFTER host-declared mappers
|
|
478
|
+
* so host config keeps priority. Collected by `createApp` from the
|
|
479
|
+
* pre-resolved module graph.
|
|
347
480
|
*/
|
|
348
|
-
async function registerErrorHandler(fastify, config, trackPlugin) {
|
|
481
|
+
async function registerErrorHandler(fastify, config, trackPlugin, moduleErrorMappers) {
|
|
349
482
|
if (config.errorHandler === false) return;
|
|
350
483
|
const { errorHandlerPlugin } = await import("./errorHandler-Dxf6P_kV.mjs").then((n) => n.r);
|
|
351
|
-
|
|
484
|
+
let errorOpts = typeof config.errorHandler === "object" ? config.errorHandler : { includeStack: config.preset !== "production" };
|
|
485
|
+
if (moduleErrorMappers && moduleErrorMappers.length > 0) errorOpts = {
|
|
486
|
+
...errorOpts,
|
|
487
|
+
errorMappers: [...errorOpts.errorMappers ?? [], ...moduleErrorMappers]
|
|
488
|
+
};
|
|
352
489
|
await fastify.register(errorHandlerPlugin, errorOpts);
|
|
353
490
|
trackPlugin("arc-error-handler", errorOpts);
|
|
354
491
|
fastify.log.debug("Arc error handler enabled");
|
|
@@ -384,134 +521,6 @@ function createOptionalAuthenticate(authenticate) {
|
|
|
384
521
|
};
|
|
385
522
|
}
|
|
386
523
|
//#endregion
|
|
387
|
-
//#region src/factory/module.ts
|
|
388
|
-
/**
|
|
389
|
-
* Resolve any module-input form to a concrete `ArcModule`. A thunk is invoked
|
|
390
|
-
* (this is where a dynamic `import()` fires); a promise (or plain module) is
|
|
391
|
-
* awaited. Called once per module at the start of the bootstrap phase.
|
|
392
|
-
*/
|
|
393
|
-
async function resolveModule(input) {
|
|
394
|
-
const resolved = typeof input === "function" ? await input() : await input;
|
|
395
|
-
if (!resolved || typeof resolved !== "object" || typeof resolved.name !== "string") throw new Error("[arc] a `modules` entry resolved to something that is not an ArcModule (expected an object with a string `name`). Check dynamic-import thunks return `createXModule(deps)` (or the module object), not the namespace.");
|
|
396
|
-
return resolved;
|
|
397
|
-
}
|
|
398
|
-
/**
|
|
399
|
-
* Order modules for composition by their `dependsOn` edges — a STABLE
|
|
400
|
-
* topological sort. Called once at the start of the bootstrap phase; every
|
|
401
|
-
* subsequent phase (bootstrap, resources, afterResources, and reverse-order
|
|
402
|
-
* onClose) iterates the returned list, so a module's declared dependencies are
|
|
403
|
-
* always composed before it.
|
|
404
|
-
*
|
|
405
|
-
* "Stable" = modules with no edge between them keep their original list order,
|
|
406
|
-
* so declaring `dependsOn` on one module never silently reorders an unrelated
|
|
407
|
-
* one. Backward compatible: a `modules` array with NO `dependsOn` anywhere is
|
|
408
|
-
* returned unchanged.
|
|
409
|
-
*
|
|
410
|
-
* Fail-fast — throws (never reorders past a broken contract) on:
|
|
411
|
-
* - duplicate module names (the name is the graph key)
|
|
412
|
-
* - a `dependsOn` name not present in the composed set
|
|
413
|
-
* - a self-reference (`dependsOn` includes the module's own name)
|
|
414
|
-
* - a dependency cycle (reports the concrete `a → b → … → a` path)
|
|
415
|
-
*/
|
|
416
|
-
function orderModules(modules) {
|
|
417
|
-
const byName = /* @__PURE__ */ new Map();
|
|
418
|
-
for (const m of modules) {
|
|
419
|
-
if (byName.has(m.name)) throw new Error(`[arc] Duplicate module name "${m.name}" — composed twice; check your modules array.`);
|
|
420
|
-
byName.set(m.name, m);
|
|
421
|
-
}
|
|
422
|
-
for (const m of modules) for (const dep of m.dependsOn ?? []) {
|
|
423
|
-
if (dep === m.name) throw new Error(`[arc] module "${m.name}" dependsOn itself — remove the self-reference.`);
|
|
424
|
-
if (!byName.has(dep)) throw new Error(`[arc] module "${m.name}" dependsOn "${dep}", which is not composed. Add the "${dep}" module to createApp({ modules }) (before this one is fine — arc orders them), or drop the dependency. Composed modules: ${[...byName.keys()].join(", ") || "(none)"}.`);
|
|
425
|
-
}
|
|
426
|
-
if (modules.every((m) => !m.dependsOn || m.dependsOn.length === 0)) return [...modules];
|
|
427
|
-
const originalIndex = /* @__PURE__ */ new Map();
|
|
428
|
-
let nextIndex = 0;
|
|
429
|
-
for (const m of modules) originalIndex.set(m.name, nextIndex++);
|
|
430
|
-
const pendingDeps = new Map(modules.map((m) => [m.name, (m.dependsOn ?? []).length]));
|
|
431
|
-
const dependents = /* @__PURE__ */ new Map();
|
|
432
|
-
for (const m of modules) for (const dep of m.dependsOn ?? []) {
|
|
433
|
-
const list = dependents.get(dep);
|
|
434
|
-
if (list) list.push(m.name);
|
|
435
|
-
else dependents.set(dep, [m.name]);
|
|
436
|
-
}
|
|
437
|
-
const ordered = [];
|
|
438
|
-
const remaining = new Set(modules.map((m) => m.name));
|
|
439
|
-
while (remaining.size > 0) {
|
|
440
|
-
let pick;
|
|
441
|
-
let pickIndex = Number.POSITIVE_INFINITY;
|
|
442
|
-
for (const name of remaining) {
|
|
443
|
-
if (pendingDeps.get(name) !== 0) continue;
|
|
444
|
-
const index = originalIndex.get(name) ?? Number.POSITIVE_INFINITY;
|
|
445
|
-
if (index < pickIndex) {
|
|
446
|
-
pick = name;
|
|
447
|
-
pickIndex = index;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
if (pick === void 0) throw new Error(describeModuleCycle(remaining, byName));
|
|
451
|
-
const picked = byName.get(pick);
|
|
452
|
-
if (!picked) throw new Error(`[arc] internal: ordered module "${pick}" is missing from the index`);
|
|
453
|
-
ordered.push(picked);
|
|
454
|
-
remaining.delete(pick);
|
|
455
|
-
for (const dependent of dependents.get(pick) ?? []) pendingDeps.set(dependent, (pendingDeps.get(dependent) ?? 1) - 1);
|
|
456
|
-
}
|
|
457
|
-
return ordered;
|
|
458
|
-
}
|
|
459
|
-
/** Walk the still-unordered subgraph for one concrete cycle path. */
|
|
460
|
-
function describeModuleCycle(remaining, byName) {
|
|
461
|
-
const stack = [];
|
|
462
|
-
const onStack = /* @__PURE__ */ new Set();
|
|
463
|
-
const done = /* @__PURE__ */ new Set();
|
|
464
|
-
let cycle = null;
|
|
465
|
-
const walk = (name) => {
|
|
466
|
-
if (cycle) return;
|
|
467
|
-
stack.push(name);
|
|
468
|
-
onStack.add(name);
|
|
469
|
-
for (const dep of byName.get(name)?.dependsOn ?? []) {
|
|
470
|
-
if (!remaining.has(dep)) continue;
|
|
471
|
-
if (onStack.has(dep)) {
|
|
472
|
-
cycle = [...stack.slice(stack.indexOf(dep)), dep];
|
|
473
|
-
return;
|
|
474
|
-
}
|
|
475
|
-
if (!done.has(dep)) walk(dep);
|
|
476
|
-
if (cycle) return;
|
|
477
|
-
}
|
|
478
|
-
onStack.delete(name);
|
|
479
|
-
stack.pop();
|
|
480
|
-
done.add(name);
|
|
481
|
-
};
|
|
482
|
-
for (const name of remaining) {
|
|
483
|
-
if (!done.has(name)) walk(name);
|
|
484
|
-
if (cycle) break;
|
|
485
|
-
}
|
|
486
|
-
return `[arc] module dependency cycle: ${cycle ? cycle.join(" → ") : [...remaining].join(", ")}. Modules cannot dependsOn each other circularly — break it with a shared module both point at, or wire the softer direction through an event/port instead of a hard dependsOn.`;
|
|
487
|
-
}
|
|
488
|
-
/**
|
|
489
|
-
* Identity helper for authoring a typed module — mirrors `defineResource`.
|
|
490
|
-
* Gives inference + a single obvious construction site; does no work.
|
|
491
|
-
*
|
|
492
|
-
* `TExports` is inferred from the `bootstrap` return value, so a module
|
|
493
|
-
* author gets a typed public export for free:
|
|
494
|
-
*
|
|
495
|
-
* ```ts
|
|
496
|
-
* export const accountingModule = (deps: Deps) =>
|
|
497
|
-
* defineModule({
|
|
498
|
-
* name: "accounting",
|
|
499
|
-
* bootstrap: async () => createAccountingEngine(deps), // TExports inferred
|
|
500
|
-
* });
|
|
501
|
-
* ```
|
|
502
|
-
*/
|
|
503
|
-
function defineModule(module) {
|
|
504
|
-
return module;
|
|
505
|
-
}
|
|
506
|
-
function getModuleExports(fastify, name) {
|
|
507
|
-
const modules = fastify.arc?.modules;
|
|
508
|
-
if (!modules || !Object.hasOwn(modules, name)) {
|
|
509
|
-
const available = modules ? Object.keys(modules) : [];
|
|
510
|
-
throw new Error(`[arc] no public export recorded for module "${name}".\nA module's export is its bootstrap() return value; it is readable only AFTER that module's bootstrap ran (dependsOn / list order = init order).\nModules with recorded exports: ${available.length ? available.join(", ") : "(none)"}.`);
|
|
511
|
-
}
|
|
512
|
-
return modules[name];
|
|
513
|
-
}
|
|
514
|
-
//#endregion
|
|
515
524
|
//#region src/factory/registerResources.ts
|
|
516
525
|
function isResourcesFactory(value) {
|
|
517
526
|
return typeof value === "function";
|
|
@@ -553,7 +562,7 @@ async function registerOne(parent, resource) {
|
|
|
553
562
|
* THEN app onClose, in ONE hook so module
|
|
554
563
|
* teardown runs before shared infra closes.
|
|
555
564
|
*/
|
|
556
|
-
async function registerResources(fastify, config) {
|
|
565
|
+
async function registerResources(fastify, config, preResolvedModules) {
|
|
557
566
|
if (config.preset === "production") {
|
|
558
567
|
if (config.strictResources === void 0) config = {
|
|
559
568
|
...config,
|
|
@@ -564,7 +573,7 @@ async function registerResources(fastify, config) {
|
|
|
564
573
|
strictResourceDir: true
|
|
565
574
|
};
|
|
566
575
|
}
|
|
567
|
-
const modules = orderModules(await Promise.all((config.modules ?? []).map((m) => resolveModule(m))));
|
|
576
|
+
const modules = preResolvedModules ?? orderModules(await Promise.all((config.modules ?? []).map((m) => resolveModule(m))));
|
|
568
577
|
if (config.plugins) {
|
|
569
578
|
await config.plugins(fastify);
|
|
570
579
|
fastify.log.debug("Custom plugins registered");
|
|
@@ -617,7 +626,7 @@ async function registerResources(fastify, config) {
|
|
|
617
626
|
let discoveryPath;
|
|
618
627
|
let discoveryYieldedZero = false;
|
|
619
628
|
if (resolvedResources === void 0 && config.resourceDir) {
|
|
620
|
-
const { loadResources } = await import("./loadResources-
|
|
629
|
+
const { loadResources } = await import("./loadResources-DpU8pfjV.mjs").then((n) => n.n);
|
|
621
630
|
const { resolve, dirname } = await import("node:path");
|
|
622
631
|
const { fileURLToPath } = await import("node:url");
|
|
623
632
|
const rawDir = config.resourceDir;
|
|
@@ -1006,7 +1015,7 @@ Missing:\n${lines}\n\nFix: pass durable adapters under \`stores\`, or use runtim
|
|
|
1006
1015
|
*
|
|
1007
1016
|
* Boot order:
|
|
1008
1017
|
* ```
|
|
1009
|
-
* 0. Logger, validation, preset merge
|
|
1018
|
+
* 0. Logger, validation → beforeBoot() (DB connect etc.), preset merge
|
|
1010
1019
|
* 1. Create Fastify instance
|
|
1011
1020
|
* 2. Security plugins (Helmet, CORS, Rate Limit) — opt-out
|
|
1012
1021
|
* 3. Utility plugins (Under Pressure, Sensible, Multipart, Raw Body)
|
|
@@ -1027,10 +1036,13 @@ async function createApp(options) {
|
|
|
1027
1036
|
}
|
|
1028
1037
|
validateAuthOptions(options);
|
|
1029
1038
|
const deferredWarnings = validateDistributedRuntime(options);
|
|
1039
|
+
if (options.beforeBoot) await options.beforeBoot();
|
|
1030
1040
|
const config = {
|
|
1031
1041
|
...options.preset ? getPreset(options.preset) : {},
|
|
1032
1042
|
...options
|
|
1033
1043
|
};
|
|
1044
|
+
const resolvedModules = orderModules(await Promise.all((config.modules ?? []).map((m) => resolveModule(m))));
|
|
1045
|
+
const moduleErrorMappers = resolvedModules.flatMap((m) => m.errorMappers ?? []);
|
|
1034
1046
|
const fastify = Fastify({
|
|
1035
1047
|
logger: resolveLoggerConfig(config.logger),
|
|
1036
1048
|
trustProxy: config.trustProxy ?? false,
|
|
@@ -1086,8 +1098,8 @@ async function createApp(options) {
|
|
|
1086
1098
|
decorateRequestScope(fastify);
|
|
1087
1099
|
await registerAuth(fastify, config, trackPlugin);
|
|
1088
1100
|
await registerElevation(fastify, config, trackPlugin);
|
|
1089
|
-
await registerErrorHandler(fastify, config, trackPlugin);
|
|
1090
|
-
await registerResources(fastify, config);
|
|
1101
|
+
await registerErrorHandler(fastify, config, trackPlugin, moduleErrorMappers);
|
|
1102
|
+
await registerResources(fastify, config, resolvedModules);
|
|
1091
1103
|
if (config.replyHelpers) {
|
|
1092
1104
|
const { replyHelpersPlugin } = await import("./replyHelpers-67tRawQZ.mjs").then((n) => n.n);
|
|
1093
1105
|
await fastify.register(replyHelpersPlugin);
|
|
@@ -1140,4 +1152,4 @@ const ArcFactory = {
|
|
|
1140
1152
|
}
|
|
1141
1153
|
};
|
|
1142
1154
|
//#endregion
|
|
1143
|
-
export {
|
|
1155
|
+
export { edgePreset as a, testingPreset as c, orderModules as d, resolveModule as f, developmentPreset as i, defineModule as l, createApp as n, getPreset as o, createApp_exports as r, productionPreset as s, ArcFactory as t, getModuleExports as u };
|
package/dist/docs/index.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { p as RegistryEntry } from "../index-
|
|
1
|
+
import { p as RegistryEntry } from "../index-Dtrj6XZk.mjs";
|
|
2
2
|
import { t as ExternalOpenApiPaths } from "../externalPaths-BE6wFpYv.mjs";
|
|
3
3
|
import { FastifyPluginAsync } from "fastify";
|
|
4
|
-
|
|
5
4
|
//#region src/docs/openapi/types.d.ts
|
|
6
5
|
/**
|
|
7
6
|
* OpenAPI 3.0 type primitives used by arc's spec emitter.
|
package/dist/docs/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as getUserRoles } from "../types-XTApa8b6.mjs";
|
|
2
|
-
import { n as openApiPlugin, r as openapi_default, t as buildOpenApiSpec } from "../openapi-
|
|
2
|
+
import { n as openApiPlugin, r as openapi_default, t as buildOpenApiSpec } from "../openapi-Kyod_di6.mjs";
|
|
3
3
|
import fp from "fastify-plugin";
|
|
4
4
|
//#region src/docs/scalar.ts
|
|
5
5
|
const scalarPlugin = async (fastify, opts = {}) => {
|
|
@@ -1,135 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
//#region src/encryption/types.d.ts
|
|
4
|
-
/** JWE key-management algorithm — the protected-header `alg`. */
|
|
5
|
-
type JweAlg = "RSA-OAEP-256" | "RSA-OAEP-384" | "RSA-OAEP-512" | "ECDH-ES" | "ECDH-ES+A256KW" | "A256GCMKW" | "dir";
|
|
6
|
-
/** JWE content-encryption algorithm — the protected-header `enc`. AEAD only. */
|
|
7
|
-
type JweEnc = "A128GCM" | "A192GCM" | "A256GCM";
|
|
8
|
-
/** Encryption strategy for a route's response. */
|
|
9
|
-
type EncryptionMode = "jwe" | "fields";
|
|
10
|
-
/**
|
|
11
|
-
* Opaque key material. For `jwe` mode this is a `jose` `KeyLike` /
|
|
12
|
-
* `CryptoKey` / `Uint8Array`; for `fields` mode a 32-byte secret
|
|
13
|
-
* (`Buffer` / `Uint8Array`). Kept `unknown` at the contract layer so the
|
|
14
|
-
* `KeyProvider` interface carries no hard `jose` type dependency — hosts
|
|
15
|
-
* without `jose` installed can still implement field-mode providers.
|
|
16
|
-
*/
|
|
17
|
-
type KeyMaterial = unknown;
|
|
18
|
-
/** A key paired with its identifier — what encrypt operations consume. */
|
|
19
|
-
interface ActiveKey {
|
|
20
|
-
/** Key id, stamped into the JWE `kid` header / field envelope for rotation. */
|
|
21
|
-
readonly kid: string;
|
|
22
|
-
/** The key material (public key for JWE, 32-byte secret for fields). */
|
|
23
|
-
readonly key: KeyMaterial;
|
|
24
|
-
/** Optional per-key `alg` override (else the plugin default applies). */
|
|
25
|
-
readonly alg?: JweAlg;
|
|
26
|
-
}
|
|
27
|
-
/** Context handed to the key provider so resolution can be request-scoped. */
|
|
28
|
-
interface KeyContext {
|
|
29
|
-
readonly request: FastifyRequest;
|
|
30
|
-
}
|
|
31
|
-
type MaybePromise<T> = T | Promise<T>;
|
|
32
|
-
/**
|
|
33
|
-
* Pluggable key resolution. Arc owns the request-time plumbing — `kid` →
|
|
34
|
-
* key, algorithm allowlist enforcement; the host owns the trust store —
|
|
35
|
-
* which keys are valid and where they live (file / env / AWS KMS / GCP KMS
|
|
36
|
-
* / Vault). Encryption and decryption are deliberately separate operations
|
|
37
|
-
* because they often use DIFFERENT keys (JWE: a public key encrypts the
|
|
38
|
-
* outbound response, a private key by `kid` decrypts the inbound request —
|
|
39
|
-
* exactly Visa's two-key-pair model).
|
|
40
|
-
*
|
|
41
|
-
* Rotation mirrors `@fastify/secure-session`: the active key encrypts; any
|
|
42
|
-
* key resolvable by `kid` can decrypt, so you can roll keys without dropping
|
|
43
|
-
* in-flight traffic.
|
|
44
|
-
*/
|
|
45
|
-
interface KeyProvider {
|
|
46
|
-
/** Active key for encrypting OUTBOUND responses. */
|
|
47
|
-
encryptionKey(ctx: KeyContext): MaybePromise<ActiveKey>;
|
|
48
|
-
/** Resolve a DECRYPTION key by the inbound message's `kid`. */
|
|
49
|
-
decryptionKey(kid: string, ctx: KeyContext): MaybePromise<KeyMaterial | undefined>;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Per-resource encryption directive — the typed slice plugins register on
|
|
53
|
-
* `ResourceExtensions`. Declared on a resource via
|
|
54
|
-
* `defineResource({ extensions: { encryption: { … } } })`; arc threads it
|
|
55
|
-
* to request time on `request.routeOptions.config.arcExtensions.encryption`.
|
|
56
|
-
*/
|
|
57
|
-
interface EncryptionDirective {
|
|
58
|
-
/** Strategy. Defaults to the plugin-level `mode` (default `'jwe'`). */
|
|
59
|
-
readonly mode?: EncryptionMode;
|
|
60
|
-
/**
|
|
61
|
-
* For `mode: 'fields'` — dot-paths of fields to encrypt, resolved against
|
|
62
|
-
* the serialized response body (e.g. `'cardNumber'`, `'account.iban'`).
|
|
63
|
-
* Ignored for `mode: 'jwe'` (the whole body is encrypted).
|
|
64
|
-
*/
|
|
65
|
-
readonly fields?: readonly string[];
|
|
66
|
-
/**
|
|
67
|
-
* Explicit opt-out — set `false` to disable encryption for this resource
|
|
68
|
-
* even when a plugin-level default (`routes`) would otherwise apply.
|
|
69
|
-
*/
|
|
70
|
-
readonly enabled?: boolean;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Plugin-level options. `keyProvider` is the only required field; everything
|
|
74
|
-
* else has a secure default.
|
|
75
|
-
*/
|
|
76
|
-
interface EncryptionOptions {
|
|
77
|
-
/**
|
|
78
|
-
* Master on/off. Default `true`. Set `false` to register the plugin as a
|
|
79
|
-
* typed no-op (config-gated environments) — same pattern as
|
|
80
|
-
* `idempotencyPlugin`.
|
|
81
|
-
*/
|
|
82
|
-
readonly enabled?: boolean;
|
|
83
|
-
/** Key provider — resolves `kid` → key for encrypt/decrypt. Required. */
|
|
84
|
-
readonly keyProvider: KeyProvider;
|
|
85
|
-
/** Default mode when a route opts in without naming one. Default `'jwe'`. */
|
|
86
|
-
readonly mode?: EncryptionMode;
|
|
87
|
-
/** JWE key-management algorithm. Default `'RSA-OAEP-256'`. */
|
|
88
|
-
readonly alg?: JweAlg;
|
|
89
|
-
/** JWE content-encryption algorithm. Default `'A256GCM'`. */
|
|
90
|
-
readonly enc?: JweEnc;
|
|
91
|
-
/**
|
|
92
|
-
* Inbound-decryption algorithm allowlists — block algorithm-substitution
|
|
93
|
-
* downgrade attacks. Default `[alg]` / `[enc]`. Set explicitly only when a
|
|
94
|
-
* client legitimately uses more than one algorithm.
|
|
95
|
-
*/
|
|
96
|
-
readonly allowedAlgs?: readonly JweAlg[];
|
|
97
|
-
readonly allowedEncs?: readonly JweEnc[];
|
|
98
|
-
/**
|
|
99
|
-
* Fallback opt-in for routes that don't declare
|
|
100
|
-
* `extensions.encryption`. Return a directive (or `true` for the default
|
|
101
|
-
* mode) to encrypt, `false`/`undefined` to skip. The per-resource
|
|
102
|
-
* `extensions.encryption` ALWAYS wins when present. Use this to scope ALE
|
|
103
|
-
* to sensitive prefixes without touching every resource.
|
|
104
|
-
*
|
|
105
|
-
* @example confine ALE to `/payments` and `/accounts`
|
|
106
|
-
* ```ts
|
|
107
|
-
* routes: (req) => /^\/(payments|accounts)\b/.test(req.url)
|
|
108
|
-
* ```
|
|
109
|
-
*/
|
|
110
|
-
readonly routes?: (request: FastifyRequest) => EncryptionDirective | boolean | undefined;
|
|
111
|
-
/** Decrypt inbound `application/jose` request bodies. Default `true`. */
|
|
112
|
-
readonly decryptRequests?: boolean;
|
|
113
|
-
/** Media type that signals an encrypted REQUEST body. Default `'application/jose'`. */
|
|
114
|
-
readonly contentType?: string;
|
|
115
|
-
/** Content-Type set on full-body JWE RESPONSES. Default `'application/jose'`. */
|
|
116
|
-
readonly responseContentType?: string;
|
|
117
|
-
/**
|
|
118
|
-
* Response header advertising that the body is encrypted, so generic
|
|
119
|
-
* client SDKs know to decrypt. Default `'x-encrypted'`; set `false` to omit.
|
|
120
|
-
*/
|
|
121
|
-
readonly flagHeader?: string | false;
|
|
122
|
-
}
|
|
123
|
-
/** Request decorations added by the plugin. */
|
|
124
|
-
declare module "fastify" {
|
|
125
|
-
interface FastifyRequest {
|
|
126
|
-
/** `true` when the inbound body was decrypted from a JWE by this plugin. */
|
|
127
|
-
requestDecrypted?: boolean;
|
|
128
|
-
/** `true` when the outbound body was encrypted by this plugin. */
|
|
129
|
-
responseEncrypted?: boolean;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
//#endregion
|
|
1
|
+
import { a as JweAlg, c as KeyMaterial, i as EncryptionOptions, l as KeyProvider, n as EncryptionDirective, o as JweEnc, r as EncryptionMode, s as KeyContext, t as ActiveKey } from "../types-Cc91nXuA.mjs";
|
|
2
|
+
import { FastifyPluginAsync } from "fastify";
|
|
133
3
|
//#region src/encryption/encryptionPlugin.d.ts
|
|
134
4
|
declare const encryptionPlugin: FastifyPluginAsync<EncryptionOptions>;
|
|
135
5
|
declare const _default: FastifyPluginAsync<EncryptionOptions>;
|
|
@@ -207,16 +77,4 @@ interface StaticKeyProviderOptions {
|
|
|
207
77
|
*/
|
|
208
78
|
declare function createStaticKeyProvider(options: StaticKeyProviderOptions): KeyProvider;
|
|
209
79
|
//#endregion
|
|
210
|
-
//#region src/encryption/index.d.ts
|
|
211
|
-
declare module "../types/resource.js" {
|
|
212
|
-
interface ResourceExtensions {
|
|
213
|
-
/**
|
|
214
|
-
* Encrypt this resource's responses — full-body JWE or specific fields.
|
|
215
|
-
* Threaded to request time on
|
|
216
|
-
* `request.routeOptions.config.arcExtensions.encryption`.
|
|
217
|
-
*/
|
|
218
|
-
encryption?: EncryptionDirective;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
//#endregion
|
|
222
80
|
export { type ActiveKey, type EncryptionDirective, type EncryptionMode, type EncryptionOptions, type JweAlg, type JweEnc, type KeyContext, type KeyMaterial, type KeyProvider, type ParsedFieldEnvelope, type StaticKeyProviderOptions, createStaticKeyProvider, decryptField, _default as default, encryptField, encryptionPlugin, parseFieldEnvelope };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "./EventTransport-
|
|
1
|
+
import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "./EventTransport-QmY7A258.mjs";
|
|
2
2
|
import { FastifyPluginAsync } from "fastify";
|
|
3
|
-
|
|
4
3
|
//#region src/events/defineEvent.d.ts
|
|
5
4
|
interface EventSchema {
|
|
6
5
|
type: "object";
|
|
@@ -249,7 +248,8 @@ interface EventPluginOptions {
|
|
|
249
248
|
* failed events are published to the `$deadLetter` event type by default.
|
|
250
249
|
*/
|
|
251
250
|
deadLetterQueue?: {
|
|
252
|
-
/** Custom store function. If omitted, publishes to '$deadLetter' event type. */
|
|
251
|
+
/** Custom store function. If omitted, publishes to '$deadLetter' event type. */
|
|
252
|
+
store?: (event: DomainEvent, errors: Error[]) => void | Promise<void>;
|
|
253
253
|
};
|
|
254
254
|
/** Callback after successful publish (for metrics/tracking) */
|
|
255
255
|
onPublish?: (event: DomainEvent) => void;
|
|
@@ -302,9 +302,13 @@ interface EventPluginOptions {
|
|
|
302
302
|
declare module "fastify" {
|
|
303
303
|
interface FastifyInstance {
|
|
304
304
|
events: {
|
|
305
|
-
/** Publish an event */
|
|
306
|
-
|
|
307
|
-
|
|
305
|
+
/** Publish an event */
|
|
306
|
+
publish: <T>(type: string, payload: T, meta?: Partial<DomainEvent["meta"]>) => Promise<void>;
|
|
307
|
+
/** Subscribe to events */
|
|
308
|
+
subscribe: (pattern: string, handler: EventHandler) => Promise<() => void>;
|
|
309
|
+
/** Get transport name */
|
|
310
|
+
transportName: string;
|
|
311
|
+
/** Event registry for introspection (undefined when no registry configured) */
|
|
308
312
|
registry?: EventRegistry;
|
|
309
313
|
};
|
|
310
314
|
}
|
package/dist/events/index.d.mts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { a as EventTransport, i as EventLogger, n as DomainEvent, o as MemoryEventTransport, r as EventHandler, s as MemoryEventTransportOptions, t as DeadLetteredEvent } from "../EventTransport-
|
|
2
|
-
import { a as withRetry, c as EventDefinitionOutput, d as EventSchema, f as ValidationResult, i as createDeadLetterPublisher, l as EventRegistry, m as defineEvent, n as eventPlugin, o as CustomValidator, p as createEventRegistry, r as RetryOptions, s as EventDefinitionInput, t as EventPluginOptions, u as EventRegistryOptions } from "../eventPlugin-
|
|
1
|
+
import { a as EventTransport, i as EventLogger, n as DomainEvent, o as MemoryEventTransport, r as EventHandler, s as MemoryEventTransportOptions, t as DeadLetteredEvent } from "../EventTransport-QmY7A258.mjs";
|
|
2
|
+
import { a as withRetry, c as EventDefinitionOutput, d as EventSchema, f as ValidationResult, i as createDeadLetterPublisher, l as EventRegistry, m as defineEvent, n as eventPlugin, o as CustomValidator, p as createEventRegistry, r as RetryOptions, s as EventDefinitionInput, t as EventPluginOptions, u as EventRegistryOptions } from "../eventPlugin-A6EbthXR.mjs";
|
|
3
3
|
import { RedisEventTransportOptions, RedisLike } from "./transports/redis.mjs";
|
|
4
|
-
import { r as RedisStreamTransportOptions, t as RedisStreamLike } from "../redis-stream-
|
|
4
|
+
import { r as RedisStreamTransportOptions, t as RedisStreamLike } from "../redis-stream-iVR2l7aS.mjs";
|
|
5
5
|
import { RepositoryLike } from "@classytic/repo-core/adapter";
|
|
6
|
-
|
|
7
6
|
//#region src/events/eventTypes.d.ts
|
|
8
7
|
/**
|
|
9
8
|
* Event Type Constants and Helpers
|
|
@@ -38,14 +37,18 @@ type CrudEventSuffix = (typeof CRUD_EVENT_SUFFIXES)[number];
|
|
|
38
37
|
declare function crudEventType(resource: string, suffix: CrudEventSuffix): string;
|
|
39
38
|
/** Arc framework lifecycle events — emitted automatically by the framework */
|
|
40
39
|
declare const ARC_LIFECYCLE_EVENTS: Readonly<{
|
|
41
|
-
/** Emitted when a resource plugin is registered */
|
|
40
|
+
/** Emitted when a resource plugin is registered */
|
|
41
|
+
readonly RESOURCE_REGISTERED: "arc.resource.registered";
|
|
42
|
+
/** Emitted when Arc is fully ready (all resources registered, onReady fired) */
|
|
42
43
|
readonly READY: "arc.ready";
|
|
43
44
|
}>;
|
|
44
45
|
/** Type for Arc lifecycle event names */
|
|
45
46
|
type ArcLifecycleEvent = (typeof ARC_LIFECYCLE_EVENTS)[keyof typeof ARC_LIFECYCLE_EVENTS];
|
|
46
47
|
/** Cache-specific event types for observability and external triggers */
|
|
47
48
|
declare const CACHE_EVENTS: Readonly<{
|
|
48
|
-
/** Emitted when a resource's cache version is bumped */
|
|
49
|
+
/** Emitted when a resource's cache version is bumped */
|
|
50
|
+
readonly VERSION_BUMPED: "arc.cache.version.bumped";
|
|
51
|
+
/** Emitted when a tag version is bumped */
|
|
49
52
|
readonly TAG_VERSION_BUMPED: "arc.cache.tag.bumped";
|
|
50
53
|
}>;
|
|
51
54
|
/** Type for cache event names */
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as RedisStreamTransport, r as RedisStreamTransportOptions, t as RedisStreamLike } from "../../redis-stream-
|
|
1
|
+
import { n as RedisStreamTransport, r as RedisStreamTransportOptions, t as RedisStreamLike } from "../../redis-stream-iVR2l7aS.mjs";
|
|
2
2
|
export { type RedisStreamLike, RedisStreamTransport, type RedisStreamTransportOptions };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "../../EventTransport-
|
|
2
|
-
|
|
1
|
+
import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "../../EventTransport-QmY7A258.mjs";
|
|
3
2
|
//#region src/events/transports/redis.d.ts
|
|
4
3
|
interface RedisLike {
|
|
5
4
|
publish(channel: string, message: string): Promise<number>;
|
package/dist/factory/index.d.mts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { a as getModuleExports, c as LoadResourcesOptions, d as loadResources, i as defineModule, l as ResourceLike, n as ArcModuleInput, o as orderModules, r as ArcModuleRegistry, s as resolveModule, t as ArcModule, u as ResourceModule } from "../module-
|
|
2
|
-
import
|
|
1
|
+
import { a as getModuleExports, c as LoadResourcesOptions, d as loadResources, i as defineModule, l as ResourceLike, n as ArcModuleInput, o as orderModules, r as ArcModuleRegistry, s as resolveModule, t as ArcModule, u as ResourceModule } from "../module-WeuU5jfd.mjs";
|
|
2
|
+
import "../fastify-augmentation-DafigGQp.mjs";
|
|
3
|
+
import { a as CustomPluginAuthOption, c as RawBodyOptions, d as preloadResourcesAsync, i as CustomAuthenticatorOption, l as UnderPressureOptions, n as BetterAuthOption, o as JwtAuthOption, r as CreateAppOptions, s as MultipartOptions, t as AuthOption, u as preloadResources } from "../types-DpxoNX5v.mjs";
|
|
3
4
|
import { FastifyInstance, FastifyServerOptions } from "fastify";
|
|
4
|
-
|
|
5
5
|
//#region src/factory/createApp.d.ts
|
|
6
6
|
/**
|
|
7
7
|
* Create a production-ready Fastify application with Arc framework.
|
|
8
8
|
*
|
|
9
9
|
* Boot order:
|
|
10
10
|
* ```
|
|
11
|
-
* 0. Logger, validation, preset merge
|
|
11
|
+
* 0. Logger, validation → beforeBoot() (DB connect etc.), preset merge
|
|
12
12
|
* 1. Create Fastify instance
|
|
13
13
|
* 2. Security plugins (Helmet, CORS, Rate Limit) — opt-out
|
|
14
14
|
* 3. Utility plugins (Under Pressure, Sensible, Multipart, Raw Body)
|