@camstack/server 1.2.113 → 1.2.115
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.
|
@@ -4171,6 +4171,14 @@ function createCapRouter_llm(getProvider, _createRemoteProxy) {
|
|
|
4171
4171
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
|
|
4172
4172
|
return p.listNodeModels(input);
|
|
4173
4173
|
}),
|
|
4174
|
+
resolveModelRef: trpc_middleware_js_1.adminProcedure
|
|
4175
|
+
.input(types_55.llmCapability.methods.resolveModelRef.input.loose())
|
|
4176
|
+
.output(types_55.llmCapability.methods.resolveModelRef.output)
|
|
4177
|
+
.mutation(async ({ input, ctx }) => {
|
|
4178
|
+
const p = requireCapProvider('llm', () => getProvider(ctx));
|
|
4179
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
|
|
4180
|
+
return p.resolveModelRef(input);
|
|
4181
|
+
}),
|
|
4174
4182
|
installModel: trpc_middleware_js_1.adminProcedure
|
|
4175
4183
|
.input(types_55.llmCapability.methods.installModel.input.loose())
|
|
4176
4184
|
.output(types_55.llmCapability.methods.installModel.output)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The hub's `onModuleInit` order, as one named, testable sequence.
|
|
4
|
+
*
|
|
5
|
+
* It was inline in `bootManual`. It is here because one seam in it is now
|
|
6
|
+
* load-bearing rather than incidental — {@link BootInitSequence.beforeAddonBoot}
|
|
7
|
+
* — and a seam nothing pins is a seam that moves.
|
|
8
|
+
*
|
|
9
|
+
* The order is derived from the dependency graph:
|
|
10
|
+
*
|
|
11
|
+
* 1. Moleculer — starts the broker and calls `EventBus.attachBroker()`.
|
|
12
|
+
* 2. AddonBridge — no cross-service deps.
|
|
13
|
+
* 3. AgentRegistry — subscribes to `broker.localBus.on('$node.connected')`.
|
|
14
|
+
* ── beforeAddonBoot ── the broker is live and NOTHING has booted yet.
|
|
15
|
+
* 4. AddonRegistry — boots EVERY addon. Minutes of work on a real hub.
|
|
16
|
+
* 5. …post-boot reconciles.
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.runBootInitSequence = runBootInitSequence;
|
|
20
|
+
/** Run the boot init steps in dependency order. */
|
|
21
|
+
async function runBootInitSequence(sequence) {
|
|
22
|
+
await sequence.moleculer();
|
|
23
|
+
await sequence.addonBridge();
|
|
24
|
+
await sequence.agentRegistry();
|
|
25
|
+
if (sequence.beforeAddonBoot !== undefined)
|
|
26
|
+
await sequence.beforeAddonBoot();
|
|
27
|
+
await sequence.addonBoot();
|
|
28
|
+
if (sequence.afterAddonBoot !== undefined)
|
|
29
|
+
await sequence.afterAddonBoot();
|
|
30
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access -- pre-existing lint debt across this 2200-line orchestration class. The flagged sites (StorageService.setLocationManager / setSettingsBackend, LoggingService.addDestination, RouteRegistry, etc.) are typed as `unknown` by their owning services to break circular construction-order dependencies; runtime contracts are validated structurally. Tracked separately; do not amend in unrelated edits. */
|
|
2
3
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
4
|
if (k2 === undefined) k2 = k;
|
|
4
5
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -36,29 +37,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
37
|
exports.AddonRegistryService = void 0;
|
|
37
38
|
exports.shouldEvictMissingOnDisk = shouldEvictMissingOnDisk;
|
|
38
39
|
exports.shouldEmitProviderRegisteredReady = shouldEmitProviderRegisteredReady;
|
|
39
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access -- pre-existing lint debt across this 2200-line orchestration class. The flagged sites (StorageService.setLocationManager / setSettingsBackend, LoggingService.addDestination, RouteRegistry, etc.) are typed as `unknown` by their owning services to break circular construction-order dependencies; runtime contracts are validated structurally. Tracked separately; do not amend in unrelated edits. */
|
|
40
|
-
const os = __importStar(require("node:os"));
|
|
41
|
-
const addon_row_manifest_1 = require("./addon-row-manifest");
|
|
42
|
-
const runner_convergence_1 = require("./runner-convergence");
|
|
43
|
-
const package_dir_utils_1 = require("./package-dir-utils");
|
|
44
|
-
const types_1 = require("@camstack/types");
|
|
45
|
-
const prune_misplaced_addons_js_1 = require("./prune-misplaced-addons.js");
|
|
46
|
-
const system_1 = require("@camstack/system");
|
|
47
|
-
const system_2 = require("@camstack/system");
|
|
48
|
-
const client_1 = require("@trpc/client");
|
|
49
|
-
const system_3 = require("@camstack/system");
|
|
50
|
-
const system_4 = require("@camstack/system");
|
|
51
|
-
const system_5 = require("@camstack/system");
|
|
52
40
|
const node_crypto_1 = require("node:crypto");
|
|
53
|
-
const path = __importStar(require("node:path"));
|
|
54
41
|
const fs = __importStar(require("node:fs"));
|
|
42
|
+
const os = __importStar(require("node:os"));
|
|
43
|
+
const path = __importStar(require("node:path"));
|
|
55
44
|
const node_url_1 = require("node:url");
|
|
56
|
-
const
|
|
45
|
+
const system_1 = require("@camstack/system");
|
|
46
|
+
const types_1 = require("@camstack/types");
|
|
47
|
+
const client_1 = require("@trpc/client");
|
|
48
|
+
const addon_call_gateway_js_1 = require("./addon-call-gateway.js");
|
|
49
|
+
const addon_row_manifest_1 = require("./addon-row-manifest");
|
|
57
50
|
const addon_settings_provider_js_1 = require("./addon-settings-provider.js");
|
|
58
51
|
const integration_visibility_js_1 = require("./integration-visibility.js");
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
const
|
|
52
|
+
const package_dir_utils_1 = require("./package-dir-utils");
|
|
53
|
+
const prune_misplaced_addons_js_1 = require("./prune-misplaced-addons.js");
|
|
54
|
+
const require_cache_js_1 = require("./require-cache.js");
|
|
55
|
+
const runner_convergence_1 = require("./runner-convergence");
|
|
56
|
+
const runner_spawn_fanout_js_1 = require("./runner-spawn-fanout.js");
|
|
62
57
|
/**
|
|
63
58
|
* Decide whether an in-memory addon entry should be evicted because it is no
|
|
64
59
|
* longer on disk (the uninstall path in `loadNewAddons`).
|
|
@@ -222,6 +217,11 @@ class AddonRegistryService {
|
|
|
222
217
|
// each addon's initialize() (in-process path); Task 7.2 will dispatch
|
|
223
218
|
// through this from the `api.addons.custom` tRPC procedure.
|
|
224
219
|
customActionRegistry = new system_1.CustomActionRegistry();
|
|
220
|
+
/**
|
|
221
|
+
* Keeps `purgeRequireCacheUnder` + `import()` atomic per addon directory now
|
|
222
|
+
* that the boot runner plan overlaps (D171). See `runner-spawn-fanout.ts`.
|
|
223
|
+
*/
|
|
224
|
+
moduleLoadSerializer = (0, runner_spawn_fanout_js_1.createKeyedSerializer)();
|
|
225
225
|
/**
|
|
226
226
|
* AddonIds whose group-runner disconnect is operator-initiated (update /
|
|
227
227
|
* restart / uninstall). The Moleculer `$node.disconnected` handler skips
|
|
@@ -267,7 +267,7 @@ class AddonRegistryService {
|
|
|
267
267
|
getByName: (capName) => reg.getSingleton(capName) ?? reg.getAllProviders(capName)[0] ?? null,
|
|
268
268
|
};
|
|
269
269
|
const client = (0, client_1.createTRPCClient)({
|
|
270
|
-
links: [(0,
|
|
270
|
+
links: [(0, system_1.localProviderLink)(resolver), (0, system_1.brokerTransportLink)(this.moleculer.broker)],
|
|
271
271
|
});
|
|
272
272
|
this.brokerApi = client;
|
|
273
273
|
}
|
|
@@ -399,7 +399,7 @@ class AddonRegistryService {
|
|
|
399
399
|
// Register the addon-settings singleton provider — replaces the
|
|
400
400
|
// former `$addonHost` Moleculer service. The provider resolves
|
|
401
401
|
// addonId → local addon instance (hub) or remote Moleculer call.
|
|
402
|
-
this.capabilityRegistry.declareCapability(
|
|
402
|
+
this.capabilityRegistry.declareCapability(system_1.addonSettingsCapability);
|
|
403
403
|
// The SINGLE router for addon-level calls (routes / custom / settings).
|
|
404
404
|
// It classifies in-process | hub-local-child (UDS) | remote-agent
|
|
405
405
|
// (Moleculer) in ONE place — `resolveNode` reports only the BASE node
|
|
@@ -681,8 +681,16 @@ class AddonRegistryService {
|
|
|
681
681
|
// `addon.error` — there is NO in-process-on-the-hub fallback (it
|
|
682
682
|
// would violate one-addon-one-process). Retry policy for a failed
|
|
683
683
|
// spawn is governed by the kernel circuit-breaker.
|
|
684
|
+
//
|
|
685
|
+
// BOUNDED-PARALLEL (D171). Entries within a plan are independent by
|
|
686
|
+
// construction — `buildAddonGroupPlan` keys by runner id and nothing reads
|
|
687
|
+
// the iteration order — while each one costs a fork plus a full addon
|
|
688
|
+
// bundle evaluated on the hub's event loop. Serially that was ~4 s of the
|
|
689
|
+
// measured 10 s kernel boot and grew with every addon shipped. The ordering
|
|
690
|
+
// that IS load-bearing is BETWEEN the plans (see the two call sites), not
|
|
691
|
+
// inside one.
|
|
684
692
|
const spawnRunnerPlan = async (plan) => {
|
|
685
|
-
|
|
693
|
+
await (0, runner_spawn_fanout_js_1.spawnPlanConcurrently)(plan, async (runnerId, runnerAddons) => {
|
|
686
694
|
try {
|
|
687
695
|
await this.initializeAddonGroup(runnerId, runnerAddons);
|
|
688
696
|
for (const { addonId } of runnerAddons) {
|
|
@@ -701,7 +709,7 @@ class AddonRegistryService {
|
|
|
701
709
|
meta: { runnerId, addonIds: runnerAddons.map((a) => a.addonId), error: msg },
|
|
702
710
|
});
|
|
703
711
|
}
|
|
704
|
-
}
|
|
712
|
+
});
|
|
705
713
|
};
|
|
706
714
|
// An ISOLATED builtin is a builtin: everything it stores lives behind
|
|
707
715
|
// `settings-store`, which is one of the in-process builtins booted below.
|
|
@@ -2420,7 +2428,7 @@ class AddonRegistryService {
|
|
|
2420
2428
|
const store = this.capabilityRegistry.getProviderByAddon('settings-store', addonId);
|
|
2421
2429
|
if (!store)
|
|
2422
2430
|
return;
|
|
2423
|
-
this.integrationRegistry = new
|
|
2431
|
+
this.integrationRegistry = new system_1.IntegrationRegistry(store);
|
|
2424
2432
|
void this.integrationRegistry.initialize().then(() => {
|
|
2425
2433
|
this.logger.info('IntegrationRegistry initialized', { meta: { phase: 'v2' } });
|
|
2426
2434
|
});
|
|
@@ -2822,7 +2830,7 @@ class AddonRegistryService {
|
|
|
2822
2830
|
registry.dataPlaneRegistry?.registerAddon(id, endpoints);
|
|
2823
2831
|
},
|
|
2824
2832
|
};
|
|
2825
|
-
const dataPlaneFacility = (0,
|
|
2833
|
+
const dataPlaneFacility = (0, system_1.createAddonDataPlaneFacility)({
|
|
2826
2834
|
addonId,
|
|
2827
2835
|
logger,
|
|
2828
2836
|
sink: dataPlaneSink,
|
|
@@ -2859,7 +2867,7 @@ class AddonRegistryService {
|
|
|
2859
2867
|
return registry.capabilityRegistry.getSingleton(capName) ?? undefined;
|
|
2860
2868
|
},
|
|
2861
2869
|
},
|
|
2862
|
-
deps: new
|
|
2870
|
+
deps: new system_1.AddonDepsManager(dataDir, logger),
|
|
2863
2871
|
kernel: {
|
|
2864
2872
|
localNodeId: this.broker.nodeID,
|
|
2865
2873
|
storage: storageProvider ?? undefined,
|
|
@@ -2936,7 +2944,7 @@ class AddonRegistryService {
|
|
|
2936
2944
|
let chain = this.disposerChains.get(addonId);
|
|
2937
2945
|
if (chain == null) {
|
|
2938
2946
|
const log = this.loggingService.createLogger().withTags({ addonId });
|
|
2939
|
-
chain = new
|
|
2947
|
+
chain = new types_1.DisposerChain({
|
|
2940
2948
|
onError: (err, index) => {
|
|
2941
2949
|
log.error(`Disposer #${index} threw during teardown`, {
|
|
2942
2950
|
meta: { error: (0, types_1.errMsg)(err) },
|
|
@@ -3248,17 +3256,26 @@ class AddonRegistryService {
|
|
|
3248
3256
|
// Dropping the addon's own modules from the require cache is what
|
|
3249
3257
|
// actually re-reads the bundle — see `require-cache.ts` for the scoping
|
|
3250
3258
|
// and the real-path match Node's cache keys demand.
|
|
3251
|
-
|
|
3252
|
-
//
|
|
3253
|
-
|
|
3254
|
-
//
|
|
3255
|
-
//
|
|
3256
|
-
//
|
|
3257
|
-
//
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3259
|
+
//
|
|
3260
|
+
// The purge mutates the PROCESS-GLOBAL require cache, so purge-then-import
|
|
3261
|
+
// must stay atomic per directory now that the boot plan overlaps (D171):
|
|
3262
|
+
// `@camstack/addon-remote-storage` ships three addon ids whose entries all
|
|
3263
|
+
// resolve into one `dist/`, and a sibling's purge landing mid-import would
|
|
3264
|
+
// evict a module graph while it is being evaluated. Different directories
|
|
3265
|
+
// still load concurrently.
|
|
3266
|
+
const modUnknown = await this.moduleLoadSerializer.run(path.dirname(entryPath), async () => {
|
|
3267
|
+
(0, require_cache_js_1.purgeRequireCacheUnder)(path.dirname(entryPath));
|
|
3268
|
+
// Kept for a genuinely ESM addon entry, where it IS the mechanism.
|
|
3269
|
+
const cacheBustedUrl = `${(0, node_url_1.pathToFileURL)(entryPath).href}?t=${Date.now()}`;
|
|
3270
|
+
// A plain `await import()` here is downleveled by tsc (the backend builds
|
|
3271
|
+
// with `module: CommonJS`) into a `require()`-based shim. `require()` then
|
|
3272
|
+
// treats the `?t=…` cache-bust query as part of the literal filename and
|
|
3273
|
+
// throws MODULE_NOT_FOUND for EVERY forked addon — so no forked addon's
|
|
3274
|
+
// custom-action catalog ever loaded. Use a native dynamic import the
|
|
3275
|
+
// compiler won't rewrite, so Node's ESM loader handles the query string.
|
|
3276
|
+
const nativeImport = new Function('specifier', 'return import(specifier)');
|
|
3277
|
+
return nativeImport(cacheBustedUrl);
|
|
3278
|
+
});
|
|
3262
3279
|
catalog =
|
|
3263
3280
|
modUnknown && typeof modUnknown === 'object'
|
|
3264
3281
|
? modUnknown['customActions']
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* What makes the boot runner plan safe to OVERLAP.
|
|
4
|
+
*
|
|
5
|
+
* `spawnRunnerPlan` used to be `for (…of plan) await initializeAddonGroup(…)`.
|
|
6
|
+
* The fork itself is cheap — `$process.spawnRunner` returns as soon as
|
|
7
|
+
* `child_process.spawn` hands back a pid, and the child's capabilities land
|
|
8
|
+
* later on its INFO heartbeat — but every iteration ALSO does a dynamic
|
|
9
|
+
* `import()` of the addon's built bundle inside the hub process, purely to read
|
|
10
|
+
* its `customActions` export. Forty runners' module graphs, evaluated one after
|
|
11
|
+
* another, were ~4 s of the measured 10 s kernel boot, and it grows linearly
|
|
12
|
+
* with the addon count (docs/design/boot-to-usable-camera.md, item B).
|
|
13
|
+
*
|
|
14
|
+
* Nothing in a plan is ordered: `buildAddonGroupPlan` keys by runner id and
|
|
15
|
+
* `resolveRunnerId` is `execution.group ?? addonId`, so entries are independent
|
|
16
|
+
* by construction. The ordering that IS load-bearing lives BETWEEN the plans
|
|
17
|
+
* (forked addons → in-process builtins → isolated builtins) and is untouched.
|
|
18
|
+
*
|
|
19
|
+
* Two primitives, because overlapping the loop exposes exactly one shared
|
|
20
|
+
* resource: Node's `require.cache`.
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.RUNNER_SPAWN_CONCURRENCY = void 0;
|
|
24
|
+
exports.spawnPlanConcurrently = spawnPlanConcurrently;
|
|
25
|
+
exports.createKeyedSerializer = createKeyedSerializer;
|
|
26
|
+
/**
|
|
27
|
+
* Concurrent runner spawns during boot.
|
|
28
|
+
*
|
|
29
|
+
* Each unit is a `child_process.spawn` (kernel work) plus a full CJS module
|
|
30
|
+
* graph evaluated ON the hub's event loop. The bound protects the hub, not the
|
|
31
|
+
* code: unbounded, forty simultaneous module evaluations would starve the very
|
|
32
|
+
* event loop that has to answer the children's UDS handshakes. Eight keeps the
|
|
33
|
+
* fork syscalls overlapped while never leaving more than eight bundles being
|
|
34
|
+
* parsed at once.
|
|
35
|
+
*/
|
|
36
|
+
exports.RUNNER_SPAWN_CONCURRENCY = 8;
|
|
37
|
+
/**
|
|
38
|
+
* Run `spawnOne` over every plan entry with at most `concurrency` in flight.
|
|
39
|
+
*
|
|
40
|
+
* Same lane-pool shape as `BaseDeviceProvider.onRestoreDevices` and
|
|
41
|
+
* `hydrateDevicesFromStorage` (D167) — one queue, N lanes, each lane pulling
|
|
42
|
+
* the next index until the queue is drained. `spawnOne` owns its own failure
|
|
43
|
+
* handling; a unit that settles (however it settles) frees its lane.
|
|
44
|
+
*/
|
|
45
|
+
async function spawnPlanConcurrently(plan, spawnOne, concurrency = exports.RUNNER_SPAWN_CONCURRENCY) {
|
|
46
|
+
const queue = [...plan.entries()];
|
|
47
|
+
if (queue.length === 0)
|
|
48
|
+
return;
|
|
49
|
+
let next = 0;
|
|
50
|
+
const lane = async () => {
|
|
51
|
+
for (;;) {
|
|
52
|
+
const unit = queue[next++];
|
|
53
|
+
if (unit === undefined)
|
|
54
|
+
return;
|
|
55
|
+
await spawnOne(unit[0], unit[1]);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const lanes = Math.min(Math.max(1, concurrency), queue.length);
|
|
59
|
+
await Promise.all(Array.from({ length: lanes }, lane));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Serialise work that shares a key, while different keys run freely.
|
|
63
|
+
*
|
|
64
|
+
* THE reason this exists: loading a forked addon's custom-action catalog first
|
|
65
|
+
* calls `purgeRequireCacheUnder(dirname(entryPath))`, which mutates the
|
|
66
|
+
* PROCESS-GLOBAL `require.cache`. Serially that is always purge-then-import.
|
|
67
|
+
* Overlapped, one addon's purge can fire while a sibling's `import()` of the
|
|
68
|
+
* same directory is still resolving, evicting half of a module graph that is
|
|
69
|
+
* being evaluated — duplicate module instances, or a partially-purged one.
|
|
70
|
+
*
|
|
71
|
+
* It is not hypothetical: `@camstack/addon-remote-storage` ships three addon
|
|
72
|
+
* ids (`sftp-storage`, `s3-storage`, `webdav-storage`) whose entries all
|
|
73
|
+
* resolve into the same `dist/` directory, each on its own runner, all in the
|
|
74
|
+
* same plan.
|
|
75
|
+
*
|
|
76
|
+
* Keyed by the purge scope, so the bound above still applies across packages
|
|
77
|
+
* and only true siblings queue behind each other.
|
|
78
|
+
*/
|
|
79
|
+
function createKeyedSerializer() {
|
|
80
|
+
const chains = new Map();
|
|
81
|
+
return {
|
|
82
|
+
run(key, work) {
|
|
83
|
+
const previous = chains.get(key) ?? Promise.resolve();
|
|
84
|
+
// `.then(work, work)` — a predecessor that REJECTED must not cancel its
|
|
85
|
+
// successors, and must not leave the chain permanently rejected.
|
|
86
|
+
const result = previous.then(work, work);
|
|
87
|
+
// The chain link swallows the outcome; only the caller sees it.
|
|
88
|
+
const link = result.then(() => undefined, () => undefined);
|
|
89
|
+
chains.set(key, link);
|
|
90
|
+
void link.then(() => {
|
|
91
|
+
// Drop the key once this link is the tail — keeps the map from growing
|
|
92
|
+
// one entry per addon directory for the life of the process.
|
|
93
|
+
if (chains.get(key) === link)
|
|
94
|
+
chains.delete(key);
|
|
95
|
+
});
|
|
96
|
+
return result;
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
package/dist/main.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument -- pre-existing lint debt across this 800+ line bootstrap module. The flagged sites cross typed boundaries (Fastify request typing, AddonRouteRegistry, AuthService inherited methods) where the projectService context can't trace inheritance chains. Tracked separately; do not amend in unrelated edits. */
|
|
2
3
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
4
|
if (k2 === undefined) k2 = k;
|
|
4
5
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -36,23 +37,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
37
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
38
|
};
|
|
38
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
|
|
40
|
-
const fastify_1 = require("@trpc/server/adapters/fastify");
|
|
41
|
-
const ws_1 = require("@trpc/server/adapters/ws");
|
|
42
|
-
const compress_1 = __importDefault(require("@fastify/compress"));
|
|
43
|
-
const cookie_1 = __importDefault(require("@fastify/cookie"));
|
|
44
|
-
const sse_no_compression_js_1 = require("./api/sse-no-compression.js");
|
|
45
|
-
const ws_2 = require("ws");
|
|
40
|
+
const node_child_process_1 = require("node:child_process");
|
|
46
41
|
const fs = __importStar(require("node:fs"));
|
|
47
42
|
const path = __importStar(require("node:path"));
|
|
48
|
-
const node_child_process_1 = require("node:child_process");
|
|
49
|
-
const single_copy_cleanup_runner_js_1 = require("./single-copy-cleanup-runner.js");
|
|
50
|
-
const logging_service_1 = require("./core/logging/logging.service");
|
|
51
|
-
const event_bus_service_1 = require("./core/events/event-bus.service");
|
|
52
|
-
const config_service_1 = require("./core/config/config.service");
|
|
53
|
-
const auth_service_1 = require("./core/auth/auth.service");
|
|
54
|
-
const share_token_service_1 = require("./core/auth/share-token.service");
|
|
55
|
-
const handoff_code_service_1 = require("./core/auth/handoff-code.service");
|
|
56
43
|
// Boot-time capability declaration runs over the auto-generated
|
|
57
44
|
// `ALL_CAPABILITY_DEFINITIONS` array — every `*.cap.ts` file that ships
|
|
58
45
|
// with `@camstack/types` is included automatically. Adding a new cap
|
|
@@ -64,39 +51,50 @@ const handoff_code_service_1 = require("./core/auth/handoff-code.service");
|
|
|
64
51
|
// capability surface refreshes on `camstack deploy packages/system` with no new
|
|
65
52
|
// server image. `@camstack/types` is never deployed to the hub.
|
|
66
53
|
const system_1 = require("@camstack/system");
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
const
|
|
54
|
+
const compress_1 = __importDefault(require("@fastify/compress"));
|
|
55
|
+
const cookie_1 = __importDefault(require("@fastify/cookie"));
|
|
56
|
+
const fastify_1 = require("@trpc/server/adapters/fastify");
|
|
57
|
+
const ws_1 = require("@trpc/server/adapters/ws");
|
|
58
|
+
const ws_2 = require("ws");
|
|
59
|
+
const addon_upload_1 = require("./api/addon-upload");
|
|
60
|
+
const auth_whoami_1 = require("./api/auth-whoami");
|
|
61
|
+
const health_routes_1 = require("./api/health/health.routes");
|
|
71
62
|
const model_distributor_js_1 = require("./api/model-distributor.js");
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
const addon_bridge_service_1 = require("./core/addon-bridge/addon-bridge.service");
|
|
78
|
-
const addon_pages_service_1 = require("./core/addon-pages/addon-pages.service");
|
|
79
|
-
const addon_widgets_service_1 = require("./core/addon-widgets/addon-widgets.service");
|
|
80
|
-
const trpc_router_1 = require("./api/trpc/trpc.router");
|
|
63
|
+
const oauth2_routes_js_1 = require("./api/oauth2/oauth2-routes.js");
|
|
64
|
+
const server_upload_1 = require("./api/server-upload");
|
|
65
|
+
const sse_no_compression_js_1 = require("./api/sse-no-compression.js");
|
|
66
|
+
const precompressed_asset_js_1 = require("./api/static/precompressed-asset.js");
|
|
67
|
+
const spa_static_1 = require("./api/static/spa-static");
|
|
81
68
|
const core_cap_bridge_1 = require("./api/trpc/core-cap-bridge");
|
|
82
69
|
const trpc_context_1 = require("./api/trpc/trpc.context");
|
|
70
|
+
const trpc_router_1 = require("./api/trpc/trpc.router");
|
|
83
71
|
const trpc_error_principal_1 = require("./api/trpc/trpc-error-principal");
|
|
84
|
-
const addon_upload_1 = require("./api/addon-upload");
|
|
85
|
-
const server_upload_1 = require("./api/server-upload");
|
|
86
|
-
const auth_whoami_1 = require("./api/auth-whoami");
|
|
87
|
-
const system_2 = require("@camstack/system");
|
|
88
|
-
const session_cookie_js_1 = require("./auth/session-cookie.js");
|
|
89
72
|
const addon_route_jwt_gate_js_1 = require("./auth/addon-route-jwt-gate.js");
|
|
90
|
-
const
|
|
91
|
-
const spa_static_1 = require("./api/static/spa-static");
|
|
92
|
-
const precompressed_asset_js_1 = require("./api/static/precompressed-asset.js");
|
|
93
|
-
const oauth2_routes_js_1 = require("./api/oauth2/oauth2-routes.js");
|
|
94
|
-
const system_3 = require("@camstack/system");
|
|
73
|
+
const session_cookie_js_1 = require("./auth/session-cookie.js");
|
|
95
74
|
const boot_config_1 = require("./boot/boot-config");
|
|
96
|
-
const
|
|
75
|
+
const integration_id_backfill_1 = require("./boot/integration-id-backfill");
|
|
97
76
|
const post_boot_service_1 = require("./boot/post-boot.service");
|
|
77
|
+
const addon_package_service_1 = require("./core/addon/addon-package.service");
|
|
78
|
+
const addon_registry_service_1 = require("./core/addon/addon-registry.service");
|
|
79
|
+
const addon_bridge_service_1 = require("./core/addon-bridge/addon-bridge.service");
|
|
80
|
+
const addon_pages_service_1 = require("./core/addon-pages/addon-pages.service");
|
|
81
|
+
const addon_widgets_service_1 = require("./core/addon-widgets/addon-widgets.service");
|
|
82
|
+
const agent_registry_service_1 = require("./core/agent/agent-registry.service");
|
|
83
|
+
const auth_service_1 = require("./core/auth/auth.service");
|
|
84
|
+
const handoff_code_service_1 = require("./core/auth/handoff-code.service");
|
|
85
|
+
const share_token_service_1 = require("./core/auth/share-token.service");
|
|
86
|
+
const config_service_1 = require("./core/config/config.service");
|
|
87
|
+
const event_bus_service_1 = require("./core/events/event-bus.service");
|
|
88
|
+
const feature_service_1 = require("./core/feature/feature.service");
|
|
89
|
+
const logging_service_1 = require("./core/logging/logging.service");
|
|
90
|
+
const moleculer_service_1 = require("./core/moleculer/moleculer.service");
|
|
91
|
+
const network_quality_service_1 = require("./core/network/network-quality.service");
|
|
92
|
+
const repl_engine_service_1 = require("./core/repl/repl-engine.service");
|
|
98
93
|
const server_update_service_1 = require("./core/server-update/server-update.service");
|
|
99
|
-
const
|
|
94
|
+
const storage_service_1 = require("./core/storage/storage.service");
|
|
95
|
+
const stream_probe_service_1 = require("./core/streaming/stream-probe.service");
|
|
96
|
+
const manual_boot_1 = require("./manual-boot");
|
|
97
|
+
const single_copy_cleanup_runner_js_1 = require("./single-copy-cleanup-runner.js");
|
|
100
98
|
// ---- Process-level error handlers ----
|
|
101
99
|
process.on('uncaughtException', (err) => {
|
|
102
100
|
console.error('[uncaughtException] Unhandled exception — server will continue:', err);
|
|
@@ -233,9 +231,9 @@ async function bootstrap() {
|
|
|
233
231
|
// 256KB pages it committed at a sawtooth peak, and an ordinary major GC does not
|
|
234
232
|
// return them. `createV8Reclaimer()` returns undefined if V8 declines, and the
|
|
235
233
|
// heartbeat then behaves exactly as it did before.
|
|
236
|
-
const heapReclaimer = (0,
|
|
234
|
+
const heapReclaimer = (0, system_1.createV8Reclaimer)();
|
|
237
235
|
const heapReclaim = heapReclaimer === undefined ? undefined : { reclaim: heapReclaimer };
|
|
238
|
-
(0,
|
|
236
|
+
(0, system_1.startHeapWatch)('hub-main', undefined, undefined, heapReclaim);
|
|
239
237
|
// Clean up orphaned processes from previous crashes before starting
|
|
240
238
|
cleanupOrphanProcesses();
|
|
241
239
|
// SPA fallback — set later when admin UI is resolved, used by addon route catch-all
|
|
@@ -323,8 +321,8 @@ async function bootstrap() {
|
|
|
323
321
|
// If registration fails, start in degraded mode: serve a health warning endpoint.
|
|
324
322
|
// Instantiate new core services
|
|
325
323
|
const loggingService = app.get(logging_service_1.LoggingService);
|
|
326
|
-
const addonRouteRegistry = new
|
|
327
|
-
const dataPlaneRegistry = new
|
|
324
|
+
const addonRouteRegistry = new system_1.AddonRouteRegistry();
|
|
325
|
+
const dataPlaneRegistry = new system_1.DataPlaneRegistry();
|
|
328
326
|
// Use Fastify-managed notification/toast wrappers (globally provided by NotificationModule)
|
|
329
327
|
const { NotificationServiceWrapper } = await Promise.resolve().then(() => __importStar(require('./core/notification/notification-wrapper.service')));
|
|
330
328
|
const { ToastServiceWrapper } = await Promise.resolve().then(() => __importStar(require('./core/notification/toast-wrapper.service')));
|
|
@@ -369,9 +367,68 @@ async function bootstrap() {
|
|
|
369
367
|
// and the distributed metrics-provider capability — no manual wiring needed.
|
|
370
368
|
let trpcRegistered = false;
|
|
371
369
|
let appRouter = null;
|
|
372
|
-
//
|
|
373
|
-
//
|
|
374
|
-
|
|
370
|
+
// Share-view (`csv_*`) tokens — hub-resident mint/verify/revoke over the
|
|
371
|
+
// settings backend (lazy getter: the backend lands after the sqlite-storage
|
|
372
|
+
// builtin registers; the service resolves it per call).
|
|
373
|
+
const shareTokenService = new share_token_service_1.ShareTokenService(() => addonRegistry.getSettingsBackend(), loggingService.createLogger('share-tokens'));
|
|
374
|
+
// One-time native-app login handoff codes (in-memory, 60s TTL, single-use) —
|
|
375
|
+
// minted by `auth.createHandoffCode`, redeemed by the viewer app via the
|
|
376
|
+
// public `auth.redeemHandoffCode`.
|
|
377
|
+
const handoffCodeService = new handoff_code_service_1.HandoffCodeService();
|
|
378
|
+
const buildRouter = () => (0, trpc_router_1.buildAppRouter)({
|
|
379
|
+
authService: app.get(auth_service_1.AuthService),
|
|
380
|
+
shareTokenService,
|
|
381
|
+
handoffCodeService,
|
|
382
|
+
configService: config,
|
|
383
|
+
featureService: app.get(feature_service_1.FeatureService),
|
|
384
|
+
loggingService,
|
|
385
|
+
eventBus: app.get(event_bus_service_1.EventBusService),
|
|
386
|
+
agentRegistry: app.get(agent_registry_service_1.AgentRegistryService),
|
|
387
|
+
moleculer: app.get(moleculer_service_1.MoleculerService),
|
|
388
|
+
addonRegistry,
|
|
389
|
+
replEngine: app.get(repl_engine_service_1.ReplEngineService),
|
|
390
|
+
networkQualityService: app.get(network_quality_service_1.NetworkQualityService),
|
|
391
|
+
addonBridge: app.get(addon_bridge_service_1.AddonBridgeService),
|
|
392
|
+
addonPackageService: app.get(addon_package_service_1.AddonPackageService),
|
|
393
|
+
notificationService,
|
|
394
|
+
toastService,
|
|
395
|
+
capabilityRegistry,
|
|
396
|
+
streamProbe: app.get(stream_probe_service_1.StreamProbeService),
|
|
397
|
+
serverUpdateService: app.get(server_update_service_1.ServerUpdateService),
|
|
398
|
+
});
|
|
399
|
+
// ── The core-cap mesh bridge, mounted BEFORE a single addon boots (D171) ──
|
|
400
|
+
//
|
|
401
|
+
// `$core-caps` exposes the hub's core (non-addon) tRPC routers on the mesh so
|
|
402
|
+
// a forked addon's `ctx.api.<coreCap>` resolves. It used to be registered
|
|
403
|
+
// after `app.init()` returned — and `app.init()` IS the addon boot, so for
|
|
404
|
+
// the whole of it every core-cap call was structurally unanswerable:
|
|
405
|
+
// `brokerTransportLink` polled the full 30 s discovery deadline and
|
|
406
|
+
// fast-failed, with no boot-window retry (core caps are excluded from it).
|
|
407
|
+
// One such await held `device-manager`, and with it every camera (D167).
|
|
408
|
+
//
|
|
409
|
+
// The router is safe to build here: `buildCapabilityRouters` is driven by
|
|
410
|
+
// `ALL_CAPABILITY_DEFINITIONS` (declared above, before init) and every
|
|
411
|
+
// provider — registry singleton or `server-provided` factory — is resolved
|
|
412
|
+
// PER REQUEST, not at build time. That is the two-phase shape: the route is
|
|
413
|
+
// on the mesh immediately, each provider completes on its own schedule, and
|
|
414
|
+
// a caller that is early gets an immediate, typed answer instead of 30 s of
|
|
415
|
+
// silence. The same router instance is handed to Fastify after init, so
|
|
416
|
+
// there is exactly one.
|
|
417
|
+
await app.init({
|
|
418
|
+
beforeAddonBoot: () => {
|
|
419
|
+
try {
|
|
420
|
+
appRouter = buildRouter();
|
|
421
|
+
app.get(moleculer_service_1.MoleculerService).registerCoreCapService((0, core_cap_bridge_1.buildCoreCapService)(appRouter));
|
|
422
|
+
console.log('[bootstrap] core-cap mesh bridge registered ($core-caps) — before addon boot');
|
|
423
|
+
}
|
|
424
|
+
catch (err) {
|
|
425
|
+
// Never abort boot for this: a hub without the bridge is degraded
|
|
426
|
+
// (core-cap calls fast-fail), a hub that refuses to start is down.
|
|
427
|
+
appRouter = null;
|
|
428
|
+
console.warn('[bootstrap] Failed to register core-cap mesh bridge early:', err);
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
});
|
|
375
432
|
console.log('[bootstrap] app.init() complete — all onModuleInit hooks have run');
|
|
376
433
|
// Mark registry as ready — providers from app.init() are now registered
|
|
377
434
|
capabilityRegistry.ready();
|
|
@@ -429,35 +486,19 @@ async function bootstrap() {
|
|
|
429
486
|
}
|
|
430
487
|
try {
|
|
431
488
|
const authService = app.get(auth_service_1.AuthService);
|
|
432
|
-
//
|
|
433
|
-
//
|
|
434
|
-
//
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
featureService: app.get(feature_service_1.FeatureService),
|
|
446
|
-
loggingService,
|
|
447
|
-
eventBus: app.get(event_bus_service_1.EventBusService),
|
|
448
|
-
agentRegistry: app.get(agent_registry_service_1.AgentRegistryService),
|
|
449
|
-
moleculer: app.get(moleculer_service_1.MoleculerService),
|
|
450
|
-
addonRegistry,
|
|
451
|
-
replEngine: app.get(repl_engine_service_1.ReplEngineService),
|
|
452
|
-
networkQualityService: app.get(network_quality_service_1.NetworkQualityService),
|
|
453
|
-
addonBridge: app.get(addon_bridge_service_1.AddonBridgeService),
|
|
454
|
-
addonPackageService: app.get(addon_package_service_1.AddonPackageService),
|
|
455
|
-
notificationService,
|
|
456
|
-
toastService,
|
|
457
|
-
capabilityRegistry,
|
|
458
|
-
streamProbe: app.get(stream_probe_service_1.StreamProbeService),
|
|
459
|
-
serverUpdateService: app.get(server_update_service_1.ServerUpdateService),
|
|
460
|
-
});
|
|
489
|
+
// Normally already built and bridged onto the mesh in `beforeAddonBoot`
|
|
490
|
+
// above — this is the fallback for the case where that failed, so a hub
|
|
491
|
+
// whose mesh bridge could not be mounted still serves HTTP.
|
|
492
|
+
if (appRouter === null) {
|
|
493
|
+
appRouter = buildRouter();
|
|
494
|
+
try {
|
|
495
|
+
app.get(moleculer_service_1.MoleculerService).registerCoreCapService((0, core_cap_bridge_1.buildCoreCapService)(appRouter));
|
|
496
|
+
console.log('[bootstrap] core-cap mesh bridge registered ($core-caps) — late fallback');
|
|
497
|
+
}
|
|
498
|
+
catch (err) {
|
|
499
|
+
console.warn('[bootstrap] Failed to register core-cap mesh bridge:', err);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
461
502
|
await fastify.register(fastify_1.fastifyTRPCPlugin, {
|
|
462
503
|
prefix: '/trpc',
|
|
463
504
|
trpcOptions: {
|
|
@@ -487,17 +528,6 @@ async function bootstrap() {
|
|
|
487
528
|
},
|
|
488
529
|
});
|
|
489
530
|
trpcRegistered = true;
|
|
490
|
-
// Mount the `$core-caps` Moleculer service so forked addons /
|
|
491
|
-
// remote agents can reach the hub's core (non-addon) tRPC routers
|
|
492
|
-
// through `ctx.api.<coreCap>`. Without it those calls hang in
|
|
493
|
-
// `brokerTransportLink`'s unbounded discovery wait.
|
|
494
|
-
try {
|
|
495
|
-
moleculer.registerCoreCapService((0, core_cap_bridge_1.buildCoreCapService)(appRouter));
|
|
496
|
-
console.log('[bootstrap] core-cap mesh bridge registered ($core-caps)');
|
|
497
|
-
}
|
|
498
|
-
catch (err) {
|
|
499
|
-
console.warn('[bootstrap] Failed to register core-cap mesh bridge:', err);
|
|
500
|
-
}
|
|
501
531
|
// Register addon-pages static file endpoint
|
|
502
532
|
const addonPagesService = app.get(addon_pages_service_1.AddonPagesService);
|
|
503
533
|
fastify.get('/api/addon-pages/:addonId/*', async (request, reply) => {
|
|
@@ -873,7 +903,7 @@ async function bootstrap() {
|
|
|
873
903
|
: Buffer.isBuffer(request.body)
|
|
874
904
|
? request.body
|
|
875
905
|
: Buffer.from(typeof request.body === 'string' ? request.body : JSON.stringify(request.body));
|
|
876
|
-
(0,
|
|
906
|
+
(0, system_1.proxyToUpstream)({
|
|
877
907
|
baseUrl: dpMatch.endpoint.baseUrl,
|
|
878
908
|
secret: dpMatch.endpoint.secret,
|
|
879
909
|
upstreamPath,
|
package/dist/manual-boot.js
CHANGED
|
@@ -46,10 +46,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
46
46
|
exports.bootManual = bootManual;
|
|
47
47
|
const node_crypto_1 = require("node:crypto");
|
|
48
48
|
const path = __importStar(require("node:path"));
|
|
49
|
+
const system_1 = require("@camstack/system");
|
|
49
50
|
const types_1 = require("@camstack/types");
|
|
50
51
|
const fastify_1 = __importDefault(require("fastify"));
|
|
51
52
|
const addon_upload_1 = require("./api/addon-upload");
|
|
52
53
|
const cap_providers_1 = require("./api/core/cap-providers");
|
|
54
|
+
const init_sequence_1 = require("./boot/init-sequence");
|
|
53
55
|
const post_boot_service_1 = require("./boot/post-boot.service");
|
|
54
56
|
const addon_package_service_1 = require("./core/addon/addon-package.service");
|
|
55
57
|
const addon_registry_service_1 = require("./core/addon/addon-registry.service");
|
|
@@ -109,6 +111,17 @@ async function bootManual(opts) {
|
|
|
109
111
|
const toastWrapper = new toast_wrapper_service_1.ToastServiceWrapper();
|
|
110
112
|
// ---- Layer 1: need ConfigService / LoggingService -----------------------
|
|
111
113
|
const loggingService = new logging_service_1.LoggingService(configService);
|
|
114
|
+
// Bootstrap stdout, attached at the FIRST moment a LogManager exists.
|
|
115
|
+
//
|
|
116
|
+
// The real console destination is a core builtin that boots in pass 3, after
|
|
117
|
+
// the entire runner plan: a measured boot produced no stdout at all for ~40 s
|
|
118
|
+
// and then flushed the whole backlog newest-first, so every boot
|
|
119
|
+
// investigation needed a parser (docs/design/boot-to-usable-camera.md, F).
|
|
120
|
+
// This sink carries the window and is detached — without a second flush —
|
|
121
|
+
// the moment `console-logging` registers.
|
|
122
|
+
const bootstrapConsole = new system_1.ConsoleDestination();
|
|
123
|
+
void bootstrapConsole.initialize();
|
|
124
|
+
loggingService.attachBootstrapConsole(bootstrapConsole);
|
|
112
125
|
const eventBusService = new event_bus_service_1.EventBusService(configService);
|
|
113
126
|
// Wire device-name cache for log formatter — subscribes here so the
|
|
114
127
|
// very first DeviceRegistered event populates the cache before any
|
|
@@ -325,27 +338,31 @@ async function bootManual(opts) {
|
|
|
325
338
|
process.once('SIGTERM', handler);
|
|
326
339
|
process.once('SIGINT', handler);
|
|
327
340
|
},
|
|
328
|
-
async init() {
|
|
329
|
-
//
|
|
330
|
-
//
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
341
|
+
async init(hooks = {}) {
|
|
342
|
+
// The order and the `beforeAddonBoot` seam live in `runBootInitSequence`
|
|
343
|
+
// — see `boot/init-sequence.ts` for why that seam is load-bearing.
|
|
344
|
+
await (0, init_sequence_1.runBootInitSequence)({
|
|
345
|
+
moleculer: () => moleculerService.onModuleInit(),
|
|
346
|
+
addonBridge: () => addonBridgeService.onModuleInit(),
|
|
347
|
+
agentRegistry: () => {
|
|
348
|
+
agentRegistryService.onModuleInit();
|
|
349
|
+
},
|
|
350
|
+
...(hooks.beforeAddonBoot !== undefined ? { beforeAddonBoot: hooks.beforeAddonBoot } : {}),
|
|
351
|
+
addonBoot: () => addonRegistryService.onModuleInit(),
|
|
352
|
+
afterAddonBoot: () => {
|
|
353
|
+
// Reconcile already-connected agents now that the hub's installed
|
|
354
|
+
// addon set is populated. Agents online before the hub started never
|
|
355
|
+
// fire a fresh `$node.connected` event, so the per-connect trigger
|
|
356
|
+
// alone would miss them — this catches the boot-time case (e.g. a
|
|
357
|
+
// long-running dev-agent with a now-stale addon). Fire-and-forget so
|
|
358
|
+
// an unreachable agent never delays boot.
|
|
359
|
+
void agentRegistryService.reconcileConnectedAgents();
|
|
360
|
+
// Topology emitter must boot AFTER AgentRegistry + AddonRegistry —
|
|
361
|
+
// its initial snapshot reads both. Subscribes to lifecycle events
|
|
362
|
+
// for incremental snapshots and emits a periodic safety net.
|
|
363
|
+
topologyEmitterService.onModuleInit();
|
|
364
|
+
},
|
|
365
|
+
});
|
|
349
366
|
},
|
|
350
367
|
async listen(port, host) {
|
|
351
368
|
await fastify.listen({ port, host });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/server",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.115",
|
|
4
4
|
"private": false,
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -33,19 +33,19 @@
|
|
|
33
33
|
]
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@camstack/addon-admin-ui": "1.2.
|
|
36
|
+
"@camstack/addon-admin-ui": "1.2.64",
|
|
37
37
|
"@camstack/addon-agent-ui": "1.2.17",
|
|
38
38
|
"@camstack/addon-auth": "1.2.19",
|
|
39
39
|
"@camstack/addon-decoder-nodeav": "1.2.16",
|
|
40
40
|
"@camstack/addon-notifiers": "1.2.21",
|
|
41
|
-
"@camstack/addon-pipeline": "1.2.
|
|
42
|
-
"@camstack/addon-pipeline-orchestrator": "1.2.
|
|
43
|
-
"@camstack/addon-post-analysis": "1.2.
|
|
41
|
+
"@camstack/addon-pipeline": "1.2.81",
|
|
42
|
+
"@camstack/addon-pipeline-orchestrator": "1.2.60",
|
|
43
|
+
"@camstack/addon-post-analysis": "1.2.79",
|
|
44
44
|
"@camstack/sdk": "1.2.19",
|
|
45
45
|
"@camstack/shm-ring": "1.1.16",
|
|
46
|
-
"@camstack/system": "1.2.
|
|
47
|
-
"@camstack/types": "1.2.
|
|
48
|
-
"@camstack/ui-library": "1.2.
|
|
46
|
+
"@camstack/system": "1.2.93",
|
|
47
|
+
"@camstack/types": "1.2.77",
|
|
48
|
+
"@camstack/ui-library": "1.2.54",
|
|
49
49
|
"@fastify/compress": "^9.0.0",
|
|
50
50
|
"@fastify/cookie": "^11.0.2",
|
|
51
51
|
"@fastify/cors": "^11.2.0",
|