@camstack/system 1.0.2
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/addon/addon-api-factory.d.ts +35 -0
- package/dist/addon-routes/addon-route-registry.d.ts +37 -0
- package/dist/addon-runner.js +599 -0
- package/dist/addon-runner.mjs +597 -0
- package/dist/auth/api-key-manager.d.ts +26 -0
- package/dist/auth/auth-manager.d.ts +109 -0
- package/dist/auth/parse-record.d.ts +18 -0
- package/dist/auth/scope-matcher.d.ts +7 -0
- package/dist/auth/scoped-token-manager.d.ts +40 -0
- package/dist/auth/totp-manager.d.ts +51 -0
- package/dist/auth/user-manager.d.ts +34 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.d.ts +53 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +259 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +251 -0
- package/dist/builtins/addon-pages-aggregator/dedupe-pages.d.ts +6 -0
- package/dist/builtins/addon-pages-aggregator/index.d.ts +1 -0
- package/dist/builtins/addon-pages-aggregator/index.js +8 -0
- package/dist/builtins/addon-pages-aggregator/index.mjs +2 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.d.ts +47 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +228 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +220 -0
- package/dist/builtins/addon-widgets-aggregator/index.d.ts +1 -0
- package/dist/builtins/addon-widgets-aggregator/index.js +8 -0
- package/dist/builtins/addon-widgets-aggregator/index.mjs +2 -0
- package/dist/builtins/alerts/alerts.addon.d.ts +81 -0
- package/dist/builtins/alerts/alerts.addon.js +601 -0
- package/dist/builtins/alerts/alerts.addon.mjs +595 -0
- package/dist/builtins/alerts/index.d.ts +1 -0
- package/dist/builtins/alerts/index.js +4 -0
- package/dist/builtins/alerts/index.mjs +2 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +147 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2229 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2220 -0
- package/dist/builtins/backup-orchestrator/cron-helpers.d.ts +23 -0
- package/dist/builtins/backup-orchestrator/destination-policy.d.ts +72 -0
- package/dist/builtins/backup-orchestrator/download-helpers.d.ts +12 -0
- package/dist/builtins/backup-orchestrator/index.d.ts +2 -0
- package/dist/builtins/backup-orchestrator/index.js +8 -0
- package/dist/builtins/backup-orchestrator/index.mjs +2 -0
- package/dist/builtins/backup-orchestrator/manifest-store.d.ts +77 -0
- package/dist/builtins/console-logging/console-destination.d.ts +13 -0
- package/dist/builtins/console-logging/console-logging.addon.d.ts +25 -0
- package/dist/builtins/console-logging/index.d.ts +3 -0
- package/dist/builtins/console-logging/index.js +104 -0
- package/dist/builtins/console-logging/index.mjs +95 -0
- package/dist/builtins/device-manager/device-config-contribution.d.ts +32 -0
- package/dist/builtins/device-manager/device-event-propagator.d.ts +26 -0
- package/dist/builtins/device-manager/device-link-overlay.d.ts +23 -0
- package/dist/builtins/device-manager/device-link-resolver.d.ts +15 -0
- package/dist/builtins/device-manager/device-manager.addon.d.ts +452 -0
- package/dist/builtins/device-manager/device-manager.addon.js +3299 -0
- package/dist/builtins/device-manager/device-manager.addon.mjs +3292 -0
- package/dist/builtins/device-manager/index.d.ts +2 -0
- package/dist/builtins/device-manager/index.js +8 -0
- package/dist/builtins/device-manager/index.mjs +2 -0
- package/dist/builtins/hub-forwarder/hub-forwarder-destination.d.ts +44 -0
- package/dist/builtins/hub-forwarder/hub-forwarder.addon.d.ts +15 -0
- package/dist/builtins/hub-forwarder/index.d.ts +3 -0
- package/dist/builtins/hub-forwarder/index.js +154 -0
- package/dist/builtins/hub-forwarder/index.mjs +145 -0
- package/dist/builtins/local-auth/auth-schema.d.ts +26 -0
- package/dist/builtins/local-auth/index.d.ts +1 -0
- package/dist/builtins/local-auth/index.js +4 -0
- package/dist/builtins/local-auth/index.mjs +2 -0
- package/dist/builtins/local-auth/local-auth.addon.d.ts +18 -0
- package/dist/builtins/local-auth/local-auth.addon.js +8094 -0
- package/dist/builtins/local-auth/local-auth.addon.mjs +8063 -0
- package/dist/builtins/local-auth/oauth-grants.d.ts +45 -0
- package/dist/builtins/local-auth/oauth-session-manager.d.ts +50 -0
- package/dist/builtins/local-network/index.d.ts +2 -0
- package/dist/builtins/local-network/index.js +10 -0
- package/dist/builtins/local-network/index.mjs +2 -0
- package/dist/builtins/local-network/local-network.addon.d.ts +150 -0
- package/dist/builtins/local-network/local-network.addon.js +489 -0
- package/dist/builtins/local-network/local-network.addon.mjs +477 -0
- package/dist/builtins/native-metrics/index.d.ts +2 -0
- package/dist/builtins/native-metrics/native-metrics-provider.d.ts +48 -0
- package/dist/builtins/native-metrics/native-metrics.addon.d.ts +73 -0
- package/dist/builtins/native-metrics/native-metrics.addon.js +922 -0
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +914 -0
- package/dist/builtins/platform-probe/hardware-decode-accel-probe.d.ts +37 -0
- package/dist/builtins/platform-probe/hardware-encoder-probe.d.ts +13 -0
- package/dist/builtins/platform-probe/index.d.ts +22 -0
- package/dist/builtins/platform-probe/index.js +834 -0
- package/dist/builtins/platform-probe/index.mjs +822 -0
- package/dist/builtins/platform-probe/inference-config-resolver.d.ts +29 -0
- package/dist/builtins/platform-probe/intel-accelerators.d.ts +11 -0
- package/dist/builtins/platform-probe/platform-scorer.d.ts +30 -0
- package/dist/builtins/platform-probe/runtime-packages.d.ts +6 -0
- package/dist/builtins/remote-access-orchestrator/enabled-providers-reconcile.d.ts +96 -0
- package/dist/builtins/remote-access-orchestrator/index.d.ts +1 -0
- package/dist/builtins/remote-access-orchestrator/index.js +8 -0
- package/dist/builtins/remote-access-orchestrator/index.mjs +2 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.d.ts +40 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +214 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +208 -0
- package/dist/builtins/shared/settle-sources.d.ts +22 -0
- package/dist/builtins/snapshot/index.d.ts +2 -0
- package/dist/builtins/snapshot/index.js +494 -0
- package/dist/builtins/snapshot/index.mjs +488 -0
- package/dist/builtins/snapshot/snapshot.addon.d.ts +120 -0
- package/dist/builtins/sqlite-storage/config-store.d.ts +8 -0
- package/dist/builtins/sqlite-storage/device-store.d.ts +23 -0
- package/dist/builtins/sqlite-storage/filesystem-browse-provider.d.ts +25 -0
- package/dist/builtins/sqlite-storage/filesystem-storage-provider.d.ts +83 -0
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.ts +32 -0
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +396 -0
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +388 -0
- package/dist/builtins/sqlite-storage/index.d.ts +8 -0
- package/dist/builtins/sqlite-storage/index.js +62 -0
- package/dist/builtins/sqlite-storage/index.mjs +49 -0
- package/dist/builtins/sqlite-storage/integration-registry.d.ts +27 -0
- package/dist/builtins/sqlite-storage/path-guard.d.ts +4 -0
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +102 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +14 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +644 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +636 -0
- package/dist/builtins/storage-orchestrator/index.d.ts +6 -0
- package/dist/builtins/storage-orchestrator/index.js +10 -0
- package/dist/builtins/storage-orchestrator/index.mjs +2 -0
- package/dist/builtins/storage-orchestrator/location-store.d.ts +49 -0
- package/dist/builtins/storage-orchestrator/provider-discovery.d.ts +10 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +103 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1138 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1128 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +236 -0
- package/dist/builtins/storage-orchestrator/storage-pressure-manager.d.ts +38 -0
- package/dist/builtins/system-backup/system-backup.service.d.ts +137 -0
- package/dist/builtins/system-config/index.d.ts +1 -0
- package/dist/builtins/system-config/index.js +8 -0
- package/dist/builtins/system-config/index.mjs +2 -0
- package/dist/builtins/system-config/system-config.addon.d.ts +10 -0
- package/dist/builtins/system-config/system-config.addon.js +232 -0
- package/dist/builtins/system-config/system-config.addon.mjs +226 -0
- package/dist/builtins/winston-logging/index.d.ts +3 -0
- package/dist/builtins/winston-logging/index.js +156 -0
- package/dist/builtins/winston-logging/index.mjs +144 -0
- package/dist/builtins/winston-logging/winston-destination.d.ts +21 -0
- package/dist/builtins/winston-logging/winston-logging.addon.d.ts +19 -0
- package/dist/chunk-CNf5ZN-e.mjs +37 -0
- package/dist/chunk-Cek0wNdY.js +64 -0
- package/dist/download/model-download-service.d.ts +41 -0
- package/dist/download/model-downloader.d.ts +31 -0
- package/dist/events/event-bus.d.ts +10 -0
- package/dist/events/system-event-bus.d.ts +14 -0
- package/dist/feature/feature-manager.d.ts +11 -0
- package/dist/formatter-B7qW8bPJ.mjs +162 -0
- package/dist/formatter-DqAKDlvN.js +167 -0
- package/dist/http/authenticated-file-server.d.ts +53 -0
- package/dist/http/data-plane-registry.d.ts +23 -0
- package/dist/http/file-data-plane.d.ts +10 -0
- package/dist/http/reverse-proxy.d.ts +15 -0
- package/dist/index.d.ts +82 -0
- package/dist/index.js +93485 -0
- package/dist/index.mjs +93179 -0
- package/dist/intel-accelerators-Gg0P5mnl.js +20 -0
- package/dist/intel-accelerators-hGgpZ0pX.mjs +19 -0
- package/dist/kernel/addon-class-resolver.d.ts +4 -0
- package/dist/kernel/addon-engine-manager.d.ts +22 -0
- package/dist/kernel/addon-health-monitor.d.ts +154 -0
- package/dist/kernel/addon-installer.d.ts +208 -0
- package/dist/kernel/addon-loader.d.ts +106 -0
- package/dist/kernel/addon-manifest.d.ts +77 -0
- package/dist/kernel/capability-handle.d.ts +46 -0
- package/dist/kernel/capability-registry.d.ts +412 -0
- package/dist/kernel/config-manager.d.ts +212 -0
- package/dist/kernel/config-schema.d.ts +93 -0
- package/dist/kernel/custom-action-registry.d.ts +23 -0
- package/dist/kernel/deps/addon-deps-manager.d.ts +19 -0
- package/dist/kernel/deps/manifest-native-deps.d.ts +25 -0
- package/dist/kernel/deps/manifest-python-deps.d.ts +20 -0
- package/dist/kernel/device-registry.d.ts +29 -0
- package/dist/kernel/fs-utils.d.ts +41 -0
- package/dist/kernel/hwaccel/hwaccel-resolver.d.ts +19 -0
- package/dist/kernel/hwaccel/hwaccel-service.d.ts +4 -0
- package/dist/kernel/index.d.ts +74 -0
- package/dist/kernel/infra-capabilities.d.ts +13 -0
- package/dist/kernel/moleculer/addon-context-factory.d.ts +91 -0
- package/dist/kernel/moleculer/addon-data-plane-facility.d.ts +19 -0
- package/dist/kernel/moleculer/addon-runner.d.ts +1 -0
- package/dist/kernel/moleculer/addon-service-factory.d.ts +50 -0
- package/dist/kernel/moleculer/broker-factory.d.ts +50 -0
- package/dist/kernel/moleculer/cap-usage-registry.d.ts +46 -0
- package/dist/kernel/moleculer/capabilities-access.d.ts +21 -0
- package/dist/kernel/moleculer/child-addon-call-dispatch.d.ts +46 -0
- package/dist/kernel/moleculer/child-cap-dispatch.d.ts +20 -0
- package/dist/kernel/moleculer/cluster-secret.d.ts +15 -0
- package/dist/kernel/moleculer/core-cap-service.d.ts +50 -0
- package/dist/kernel/moleculer/crash-supervisor.d.ts +50 -0
- package/dist/kernel/moleculer/device-cap-proxy.d.ts +79 -0
- package/dist/kernel/moleculer/event-bus-core.d.ts +53 -0
- package/dist/kernel/moleculer/event-bus.d.ts +53 -0
- package/dist/kernel/moleculer/hub-log-forwarder.d.ts +36 -0
- package/dist/kernel/moleculer/hub-service.d.ts +35 -0
- package/dist/kernel/moleculer/node-registry.d.ts +126 -0
- package/dist/kernel/moleculer/process-context.d.ts +4 -0
- package/dist/kernel/moleculer/process-service.d.ts +72 -0
- package/dist/kernel/moleculer/provider-registry.d.ts +28 -0
- package/dist/kernel/moleculer/readiness-context.d.ts +62 -0
- package/dist/kernel/moleculer/readiness-service.d.ts +7 -0
- package/dist/kernel/moleculer/register-node-client.d.ts +35 -0
- package/dist/kernel/moleculer/remote-logger.d.ts +43 -0
- package/dist/kernel/moleculer/resilient-cap-call.d.ts +28 -0
- package/dist/kernel/moleculer/stream-probe-service.d.ts +9 -0
- package/dist/kernel/moleculer/trpc-links.d.ts +189 -0
- package/dist/kernel/moleculer/typed-array-serde.d.ts +25 -0
- package/dist/kernel/moleculer/worker-device-restore.d.ts +10 -0
- package/dist/kernel/provider-kind-drift.d.ts +12 -0
- package/dist/kernel/restart-coordinator.d.ts +90 -0
- package/dist/kernel/storage-location-registry.d.ts +40 -0
- package/dist/kernel/transport/cap-action-name.d.ts +100 -0
- package/dist/kernel/transport/cap-route-resolver.d.ts +148 -0
- package/dist/kernel/transport/cap-route.d.ts +148 -0
- package/dist/kernel/transport/child-cap-protocol.d.ts +136 -0
- package/dist/kernel/transport/create-local-transport.d.ts +7 -0
- package/dist/kernel/transport/frame-codec.d.ts +7 -0
- package/dist/kernel/transport/index.d.ts +27 -0
- package/dist/kernel/transport/local-child-client.d.ts +136 -0
- package/dist/kernel/transport/local-child-registry.d.ts +179 -0
- package/dist/kernel/transport/local-endpoint-path.d.ts +6 -0
- package/dist/kernel/transport/local-transport.d.ts +46 -0
- package/dist/kernel/transport/parent-unowned-call.d.ts +75 -0
- package/dist/kernel/transport/socket-channel.d.ts +27 -0
- package/dist/kernel/transport/uds-event-bridge.d.ts +36 -0
- package/dist/kernel/transport/uds-event-bus.d.ts +22 -0
- package/dist/kernel/transport/uds-local-transport.d.ts +18 -0
- package/dist/kernel/transport/uds-log-ingest.d.ts +28 -0
- package/dist/kernel/transport/uds-logger.d.ts +44 -0
- package/dist/kernel/utils/ring-buffer.d.ts +15 -0
- package/dist/kernel/workspace-detect.d.ts +9 -0
- package/dist/lifecycle/lifecycle-state-machine.d.ts +28 -0
- package/dist/logging/formatter.d.ts +30 -0
- package/dist/logging/log-manager.d.ts +54 -0
- package/dist/logging/log-ring-buffer.d.ts +47 -0
- package/dist/logging/partitioned-log-buffer.d.ts +35 -0
- package/dist/logging/scoped-logger.d.ts +17 -0
- package/dist/main-DNnMW7Z2.js +9983 -0
- package/dist/main-rtjOwPBR.mjs +9976 -0
- package/dist/manifest-python-deps-D1DbAQEv.js +6724 -0
- package/dist/manifest-python-deps-DZsKTbs1.mjs +6315 -0
- package/dist/network/network-quality.d.ts +11 -0
- package/dist/notification/notification-service.d.ts +37 -0
- package/dist/notification/toast-service.d.ts +22 -0
- package/dist/pipeline/engine-manager-resolver.d.ts +15 -0
- package/dist/pipeline/pipeline-runner.d.ts +8 -0
- package/dist/pipeline/pipeline-validator.d.ts +13 -0
- package/dist/process/resource-monitor.d.ts +11 -0
- package/dist/python/python-env-manager.d.ts +12 -0
- package/dist/repl/interfaces.d.ts +31 -0
- package/dist/repl/repl-engine.d.ts +8 -0
- package/dist/resource-monitor-ClDGFyf6.mjs +57 -0
- package/dist/resource-monitor-IIEanuJt.js +74 -0
- package/dist/settle-sources-Bhsy57y-.js +38 -0
- package/dist/settle-sources-CDtNC8ub.mjs +33 -0
- package/dist/storage/fs-storage-backend.d.ts +40 -0
- package/dist/storage/storage-location-manager.d.ts +23 -0
- package/dist/storage/storage-manager.d.ts +83 -0
- package/dist/tar-BgAEMRBR.js +5434 -0
- package/dist/tar-ByMOPNM0.mjs +5429 -0
- package/dist/tls/cert-manager.d.ts +26 -0
- package/dist/tls/index.d.ts +1 -0
- package/package.json +343 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { ChildProcess, SpawnOptions } from 'node:child_process';
|
|
2
|
+
import { ServiceSchema } from 'moleculer';
|
|
3
|
+
/** One addon hosted inside a runner subprocess. */
|
|
4
|
+
interface RunnerAddonSpec {
|
|
5
|
+
readonly addonId: string;
|
|
6
|
+
readonly addonDir: string;
|
|
7
|
+
}
|
|
8
|
+
interface SpawnedProcess {
|
|
9
|
+
readonly pid: number;
|
|
10
|
+
readonly nodeId: string;
|
|
11
|
+
readonly name: string;
|
|
12
|
+
/**
|
|
13
|
+
* Synthetic supervisor label `runner:${runnerId}` — the real list of
|
|
14
|
+
* hosted addons lives on `runnerAddons`. The normal case is a size-1
|
|
15
|
+
* `runnerAddons` array (one addon, one process); the media-pipeline
|
|
16
|
+
* group is the sole multi-addon exception.
|
|
17
|
+
*/
|
|
18
|
+
readonly addonId: string;
|
|
19
|
+
readonly addonDir: string;
|
|
20
|
+
/** Every addon hosted by this runner subprocess (size 1 in the normal case). */
|
|
21
|
+
readonly runnerAddons: readonly RunnerAddonSpec[];
|
|
22
|
+
readonly startedAt: number;
|
|
23
|
+
restartCount: number;
|
|
24
|
+
/**
|
|
25
|
+
* Runner lifecycle state. `failed` is terminal — the D6 crash
|
|
26
|
+
* circuit-breaker tripped (too many crashes inside `CRASH_WINDOW_MS`)
|
|
27
|
+
* and the runner will NOT be respawned. `crashed` is transient — the
|
|
28
|
+
* window between an exit and the next backoff respawn.
|
|
29
|
+
*/
|
|
30
|
+
state: 'starting' | 'running' | 'stopping' | 'stopped' | 'crashed' | 'failed';
|
|
31
|
+
child: ChildProcess;
|
|
32
|
+
}
|
|
33
|
+
interface ProcessInfo {
|
|
34
|
+
readonly pid: number;
|
|
35
|
+
readonly nodeId: string;
|
|
36
|
+
readonly name: string;
|
|
37
|
+
readonly addonId: string;
|
|
38
|
+
/**
|
|
39
|
+
* The full list of addon ids inside this runner subprocess. Size 1 in
|
|
40
|
+
* the normal one-addon-one-process case; longer only for the media
|
|
41
|
+
* group. Cluster page UI expands this to render every addon under the
|
|
42
|
+
* same process card so operators see what's running where.
|
|
43
|
+
*/
|
|
44
|
+
readonly addonIds: readonly string[];
|
|
45
|
+
/** Runner label — the `runnerId` this subprocess was spawned with. */
|
|
46
|
+
readonly groupId: string;
|
|
47
|
+
readonly isolated: boolean;
|
|
48
|
+
readonly spawnedBy: string | null;
|
|
49
|
+
readonly startedAt: number;
|
|
50
|
+
readonly restartCount: number;
|
|
51
|
+
readonly state: string;
|
|
52
|
+
readonly cpuPercent: number;
|
|
53
|
+
readonly memoryRss: number;
|
|
54
|
+
readonly uptimeSeconds: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Subprocess spawner injected into `createProcessService`. Production
|
|
58
|
+
* code passes `child_process.spawn`; tests pass a fake that records
|
|
59
|
+
* the call shape and returns a stub `ChildProcess`. Centralising the
|
|
60
|
+
* dependency here is the only ESM-safe way to intercept spawn — the
|
|
61
|
+
* `node:child_process` module export is non-configurable so `vi.spyOn`
|
|
62
|
+
* fails. The injection point is private to this module: callers don't
|
|
63
|
+
* see it, so the public `createProcessService(parentNodeId, dataDir)`
|
|
64
|
+
* shape stays unchanged.
|
|
65
|
+
*/
|
|
66
|
+
type SpawnFn = (command: string, args: readonly string[], opts: SpawnOptions) => ChildProcess;
|
|
67
|
+
interface ProcessServiceDeps {
|
|
68
|
+
readonly spawnFn?: SpawnFn;
|
|
69
|
+
}
|
|
70
|
+
declare function createProcessService(parentNodeId: string, dataDir: string, deps?: ProcessServiceDeps, parentTcpPort?: number, parentUdsPath?: string): ServiceSchema;
|
|
71
|
+
export { createProcessService };
|
|
72
|
+
export type { ProcessInfo, SpawnedProcess };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ServiceBroker } from 'moleculer';
|
|
2
|
+
/**
|
|
3
|
+
* Per-broker provider registries. In production there is one broker per
|
|
4
|
+
* process, so these behave like module-scoped singletons. In tests that
|
|
5
|
+
* spin up multiple brokers in the same process, each broker gets its
|
|
6
|
+
* own isolated set of maps so providers don't leak across nodes.
|
|
7
|
+
*/
|
|
8
|
+
interface BrokerRegistries {
|
|
9
|
+
readonly providers: Map<string, unknown[]>;
|
|
10
|
+
readonly preferred: Map<string, string>;
|
|
11
|
+
readonly byAddonId: Map<string, Map<string, unknown>>;
|
|
12
|
+
}
|
|
13
|
+
declare function getRegistries(brokerNodeId: string): BrokerRegistries;
|
|
14
|
+
export { getRegistries };
|
|
15
|
+
export type { BrokerRegistries };
|
|
16
|
+
declare function withAddonScope<T>(addonId: string, fn: () => T): T;
|
|
17
|
+
/** Exported for test harnesses that drive the factory manually. */
|
|
18
|
+
export { withAddonScope };
|
|
19
|
+
/** The addon id currently in scope, used by `registerProvider` to tag providers. */
|
|
20
|
+
declare function getCurrentAddonId(): string | null;
|
|
21
|
+
export { getCurrentAddonId };
|
|
22
|
+
/** Update the preferred provider for a capability (called from binding-changed subscribers). */
|
|
23
|
+
declare function setPreferredProvider(capabilityName: string, addonId: string | null, brokerNodeId?: string): void;
|
|
24
|
+
export { setPreferredProvider };
|
|
25
|
+
declare function ensureBindingSubscription(broker: ServiceBroker): void;
|
|
26
|
+
export { ensureBindingSubscription };
|
|
27
|
+
declare function __resetBindingSubscriptionForTests(): void;
|
|
28
|
+
export { __resetBindingSubscriptionForTests };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ServiceBroker } from 'moleculer';
|
|
2
|
+
import { IEventBus, IScopedLogger, ReadinessRegistry } from '@camstack/types';
|
|
3
|
+
/**
|
|
4
|
+
* Minimal interface for the `LocalChildClient` surface used in UDS-mode
|
|
5
|
+
* readiness hydration. Declared here (rather than importing the concrete
|
|
6
|
+
* class) so this module stays free of a direct transport dependency and
|
|
7
|
+
* remains independently testable with a plain fake object.
|
|
8
|
+
*/
|
|
9
|
+
interface UdsReadinessClient {
|
|
10
|
+
/** True once `start()` has connected and registered with the parent. */
|
|
11
|
+
readonly isConnected: boolean;
|
|
12
|
+
/** Request the current readiness snapshot from the parent over UDS. */
|
|
13
|
+
requestReadinessSnapshot(): Promise<readonly import('@camstack/types').IReadinessRegistryRecord[]>;
|
|
14
|
+
/** Register a callback fired each time the client connects (including reconnects). */
|
|
15
|
+
onConnected(cb: () => void): void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Return the shared ReadinessRegistry for this broker — one per
|
|
19
|
+
* process is enough. Every addon context on the same broker gets the
|
|
20
|
+
* same instance via `ctx.kernel.readinessRegistry`.
|
|
21
|
+
*
|
|
22
|
+
* For non-hub brokers (forked workers + remote agents) the registry
|
|
23
|
+
* is hydrated from the hub's `$readiness.getSnapshot` Moleculer action
|
|
24
|
+
* on every `$node.connected` — this closes the boot-time race where
|
|
25
|
+
* `broker.broadcast` consumers on the hub fire before the worker is
|
|
26
|
+
* in the cluster, and makes hub reconnects refresh consumer state
|
|
27
|
+
* without forcing every producer to re-emit. Live deltas continue
|
|
28
|
+
* through the normal `system.ready-state` event bridge; hydrate skips
|
|
29
|
+
* entries already observed locally.
|
|
30
|
+
*/
|
|
31
|
+
declare function getOrInitReadinessRegistry(broker: ServiceBroker, eventBus: IEventBus, logger: IScopedLogger): ReadinessRegistry;
|
|
32
|
+
/**
|
|
33
|
+
* Return (or create) the shared `ReadinessRegistry` for a UDS-only child
|
|
34
|
+
* process — one per child node id. The registry is hydrated from the parent
|
|
35
|
+
* over UDS instead of via `$readiness.getSnapshot` Moleculer action.
|
|
36
|
+
*
|
|
37
|
+
* **Hydration strategy:**
|
|
38
|
+
* - Initial snapshot: `client.requestReadinessSnapshot()` is called once
|
|
39
|
+
* `client.isConnected` becomes true (the `onConnected` callback).
|
|
40
|
+
* - Reconnect: each time `onConnected` fires again (the client re-connected
|
|
41
|
+
* after a parent-side restart), a fresh snapshot is pulled so pending
|
|
42
|
+
* `awaitReady` callers can unblock.
|
|
43
|
+
* - Live deltas: `system.ready-state` events arrive via the UDS event bus
|
|
44
|
+
* (Phase C) — the registry ingests them through its own event-bus
|
|
45
|
+
* subscription, exactly as in broker mode.
|
|
46
|
+
*
|
|
47
|
+
* **No `$services.changed` reconcile signal needed:**
|
|
48
|
+
* The broker-mode `$services.changed` reconcile existed because Moleculer
|
|
49
|
+
* broadcasts can be dropped during the boot window. Over UDS the parent
|
|
50
|
+
* reliably forwards every `system.ready-state` delta to each child (via
|
|
51
|
+
* the event bridge wired in Phase C). Dropped deltas are not a concern;
|
|
52
|
+
* the initial snapshot + live event bus is sufficient. A new
|
|
53
|
+
* parent-to-child "topology changed, re-pull" signal is therefore NOT
|
|
54
|
+
* added — it would be redundant and would complicate the protocol.
|
|
55
|
+
*
|
|
56
|
+
* **`awaitReady`/`acquireCapability`/`onReadyState` semantics unchanged.**
|
|
57
|
+
*
|
|
58
|
+
* Keep `$readiness.getSnapshot` (broker path) intact — Phase F removes it.
|
|
59
|
+
*/
|
|
60
|
+
declare function getOrInitReadinessRegistryForClient(client: UdsReadinessClient, eventBus: IEventBus, logger: IScopedLogger, nodeId: string): ReadinessRegistry;
|
|
61
|
+
export { getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient };
|
|
62
|
+
export type { UdsReadinessClient };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ServiceSchema } from 'moleculer';
|
|
2
|
+
import { IReadinessRegistry, IReadinessRegistryRecord } from '@camstack/types';
|
|
3
|
+
export interface ReadinessServiceDeps {
|
|
4
|
+
readonly getSnapshot: () => readonly IReadinessRegistryRecord[];
|
|
5
|
+
}
|
|
6
|
+
export declare function createReadinessService(deps: ReadinessServiceDeps): ServiceSchema;
|
|
7
|
+
export declare function createReadinessServiceForRegistry(registry: IReadinessRegistry): ServiceSchema;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { RegisteredAddonManifest, RegisteredNativeCap, RegisterNodeParams } from './node-registry.js';
|
|
2
|
+
/** Minimal broker surface this client needs. */
|
|
3
|
+
interface RegisterNodeBroker {
|
|
4
|
+
call(action: string, params: unknown, opts?: {
|
|
5
|
+
nodeID?: string;
|
|
6
|
+
}): Promise<unknown>;
|
|
7
|
+
}
|
|
8
|
+
interface CallRegisterNodeOptions {
|
|
9
|
+
/** `'hub'` → `$hub.registerNode`; `'agent'` → `$agent.registerNode`. */
|
|
10
|
+
readonly target: 'hub' | 'agent';
|
|
11
|
+
/** Required when target is `'agent'` — the agent's nodeID to route to. */
|
|
12
|
+
readonly targetNodeId?: string;
|
|
13
|
+
/** First retry delay; doubles each attempt, capped at 5000ms. Default 250. */
|
|
14
|
+
readonly baseDelayMs?: number;
|
|
15
|
+
/** Abort the retry loop (e.g. on node shutdown). */
|
|
16
|
+
readonly signal?: AbortSignal;
|
|
17
|
+
/** Optional logger for retry diagnostics. */
|
|
18
|
+
readonly log?: (msg: string) => void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Build a `RegisterNodeParams` from a node id, its per-addon manifests,
|
|
22
|
+
* optionally its device-scoped native caps, and optionally the SHA-256 hash
|
|
23
|
+
* of the cluster secret. `nativeCaps` is omitted entirely on the first
|
|
24
|
+
* handshake; `clusterSecretHash` is omitted when no secret is configured.
|
|
25
|
+
*/
|
|
26
|
+
declare function buildNodeManifest(nodeId: string, addons: readonly RegisteredAddonManifest[], nativeCaps?: readonly RegisteredNativeCap[], clusterSecretHash?: string): RegisterNodeParams;
|
|
27
|
+
/**
|
|
28
|
+
* Call `<target>.registerNode` and retry until the parent acks. The loop
|
|
29
|
+
* terminates ONLY on a successful ack or an abort — there is no fixed
|
|
30
|
+
* attempt cap, because the real terminating condition is "the hub
|
|
31
|
+
* received it", not "we tried N times".
|
|
32
|
+
*/
|
|
33
|
+
declare function callRegisterNodeWithRetry(broker: RegisterNodeBroker, params: RegisterNodeParams, opts: CallRegisterNodeOptions): Promise<void>;
|
|
34
|
+
export { callRegisterNodeWithRetry, buildNodeManifest };
|
|
35
|
+
export type { RegisterNodeBroker, CallRegisterNodeOptions };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ServiceBroker } from 'moleculer';
|
|
2
|
+
import { IScopedLogger, LogTags } from '@camstack/types';
|
|
3
|
+
import { BrokerLike } from './event-bus.js';
|
|
4
|
+
/**
|
|
5
|
+
* Call after `broker.waitForServices('$hub')` to enable log forwarding.
|
|
6
|
+
*
|
|
7
|
+
* Marks the broker connected and flushes any log lines buffered during
|
|
8
|
+
* the pre-discovery window. With no argument (test harnesses), every
|
|
9
|
+
* known broker state is connected and flushed — the buffered entries
|
|
10
|
+
* carry their own dispatch closures so no broker reference is needed.
|
|
11
|
+
*/
|
|
12
|
+
declare function setHubConnected(broker?: ServiceBroker): void;
|
|
13
|
+
/**
|
|
14
|
+
* Test-only: clear all per-broker hub-connection state + buffers and the
|
|
15
|
+
* process-wide baseline so specs that create brokers in sequence start
|
|
16
|
+
* from a clean slate. Production never calls this.
|
|
17
|
+
*/
|
|
18
|
+
declare function __resetHubConnectedForTests(): void;
|
|
19
|
+
export { __resetHubConnectedForTests };
|
|
20
|
+
declare function createRemoteLogger(broker: ServiceBroker, addonId: string, scope?: string, tags?: LogTags): IScopedLogger;
|
|
21
|
+
export { createRemoteLogger };
|
|
22
|
+
/**
|
|
23
|
+
* Build a hub-forwarding logger for a forked-process runner (process-runner
|
|
24
|
+
* / group-runner). The runner has no `AddonContext` of its own — its own
|
|
25
|
+
* diagnostics ("started", "handshake failed", …) would otherwise be raw
|
|
26
|
+
* `console.*` that never reaches the hub `LogManager`. This routes them
|
|
27
|
+
* through the same `$hub.log` transport every addon logger uses, with the
|
|
28
|
+
* Part A pre-connect buffer so boot-time lines survive.
|
|
29
|
+
*
|
|
30
|
+
* `scope` lets the runner tag its own lines (e.g. `process-runner`) so the
|
|
31
|
+
* hub renderer distinguishes runner plumbing from the hosted addon's output.
|
|
32
|
+
*/
|
|
33
|
+
declare function createRunnerLogger(broker: ServiceBroker, addonId: string, scope: string): IScopedLogger;
|
|
34
|
+
export { createRunnerLogger };
|
|
35
|
+
/**
|
|
36
|
+
* Test-only: build a remote logger against a structural broker spy.
|
|
37
|
+
* `createRemoteLogger` only touches `broker.nodeID` + `broker.call`, so a
|
|
38
|
+
* minimal stand-in is enough — this avoids spinning a real `ServiceBroker`
|
|
39
|
+
* just to assert the pre-connect buffer behaviour.
|
|
40
|
+
*/
|
|
41
|
+
declare function __createRemoteLoggerForTests(broker: BrokerLike, addonId: string): IScopedLogger;
|
|
42
|
+
export { __createRemoteLoggerForTests };
|
|
43
|
+
export { setHubConnected };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D3 — resilient cross-process capability call.
|
|
3
|
+
*
|
|
4
|
+
* The `$hub.registerNode` handshake registers a cap proxy the moment the
|
|
5
|
+
* RPC lands — decoupled from Moleculer's service-discovery INFO packet,
|
|
6
|
+
* which propagates separately. A call through the proxy in that window
|
|
7
|
+
* fails with `ServiceNotFoundError`. This wraps a `broker.call` so that,
|
|
8
|
+
* on a discovery error, it waits for Moleculer to discover the service
|
|
9
|
+
* (the framework-native `waitForServices` primitive) and retries ONCE.
|
|
10
|
+
* Happy path (service already discovered) pays nothing. If the service
|
|
11
|
+
* genuinely never appears, `waitForServices` rejects → fail-fast.
|
|
12
|
+
*/
|
|
13
|
+
/** Minimal broker surface this helper needs. */
|
|
14
|
+
export interface ServiceDiscoveryBroker {
|
|
15
|
+
call(action: string, params: unknown, opts: {
|
|
16
|
+
nodeID?: string;
|
|
17
|
+
timeout?: number;
|
|
18
|
+
}): Promise<unknown>;
|
|
19
|
+
waitForServices(services: string[], timeout?: number): Promise<unknown>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Call a Moleculer action; on a service-discovery error, wait for the
|
|
23
|
+
* named service to be discovered and retry the call exactly once.
|
|
24
|
+
*/
|
|
25
|
+
export declare function callWithServiceDiscovery(broker: ServiceDiscoveryBroker, serviceName: string, action: string, params: unknown, opts: {
|
|
26
|
+
nodeID?: string;
|
|
27
|
+
timeout?: number;
|
|
28
|
+
}, discoveryTimeoutMs?: number): Promise<unknown>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ServiceSchema } from 'moleculer';
|
|
2
|
+
import { IKernelStreamProbe } from '@camstack/types';
|
|
3
|
+
/**
|
|
4
|
+
* Hub-side dependencies for the `$stream-probe` broker service.
|
|
5
|
+
* Matches `IKernelStreamProbe` exactly so the same function references
|
|
6
|
+
* are reused for hub-direct injection and worker broker routing.
|
|
7
|
+
*/
|
|
8
|
+
export type StreamProbeBrokerDeps = IKernelStreamProbe;
|
|
9
|
+
export declare function createStreamProbeBrokerService(deps: StreamProbeBrokerDeps): ServiceSchema;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { ServiceBroker } from 'moleculer';
|
|
2
|
+
import { TRPCLink } from '@trpc/client';
|
|
3
|
+
import { AnyRouter } from '@trpc/server';
|
|
4
|
+
import { LocalChildRegistry, CapCallInput } from '../transport/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Resolver for in-process capability providers.
|
|
7
|
+
*
|
|
8
|
+
* The localProviderLink calls this on every operation to check whether
|
|
9
|
+
* a provider exists in the local process. Implementations differ:
|
|
10
|
+
* - Worker: reads from `localProviderRegistry` + `preferredProviderRegistry`
|
|
11
|
+
* - Hub: reads from `CapabilityRegistry`
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Shared interface — also re-exported by `broker-api-proxy.ts`.
|
|
15
|
+
* Single method is sufficient: the link only needs to resolve the
|
|
16
|
+
* first matching provider. Singleton vs collection distinction is
|
|
17
|
+
* a registry concern, not a transport concern.
|
|
18
|
+
*/
|
|
19
|
+
export interface LocalProviderResolver {
|
|
20
|
+
/** First matching provider (active singleton or first collection member). */
|
|
21
|
+
getByName(capabilityName: string): unknown | null;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A single tRPC cap call observation. Recorded by `localProviderLink`
|
|
25
|
+
* / `brokerTransportLink` on every op, regardless of in-process vs
|
|
26
|
+
* cluster-bound routing, and fed to the hub's `CapUsageRegistry`.
|
|
27
|
+
*
|
|
28
|
+
* Observation is best-effort — observers MUST NOT throw. The link
|
|
29
|
+
* wraps the recorder in a try/catch so a broken observer never fails
|
|
30
|
+
* the caller's RPC.
|
|
31
|
+
*/
|
|
32
|
+
export interface CapUsageObservation {
|
|
33
|
+
readonly callerAddonId: string;
|
|
34
|
+
readonly providerAddonId: string;
|
|
35
|
+
readonly capName: string;
|
|
36
|
+
readonly methodName: string;
|
|
37
|
+
readonly atMs: number;
|
|
38
|
+
}
|
|
39
|
+
export type CapUsageObserver = (obs: CapUsageObservation) => void;
|
|
40
|
+
export interface CapUsageObserverOptions {
|
|
41
|
+
/** The addon whose `ctx.api` produced this link chain. */
|
|
42
|
+
readonly callerAddonId: string;
|
|
43
|
+
/** Resolve which addon hosts the provider for `capName`. Return `null` to skip recording. */
|
|
44
|
+
readonly providerAddonIdForCap: (capName: string) => string | null;
|
|
45
|
+
/** Sink for observations. MUST NOT throw — wrapper catches anyway. */
|
|
46
|
+
readonly observer: CapUsageObserver;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Non-terminating tRPC link that intercepts calls when the target
|
|
50
|
+
* capability has a provider registered in the local process.
|
|
51
|
+
*
|
|
52
|
+
* When a local provider is found and implements the requested method,
|
|
53
|
+
* the call is made directly (zero serialization). When no local
|
|
54
|
+
* provider exists, the call passes through to `next(op)`.
|
|
55
|
+
*
|
|
56
|
+
* This is the mechanism that makes `ctx.api.streamBroker.getBrokerStats.query()`
|
|
57
|
+
* resolve in-process on the hub without going through Moleculer, and
|
|
58
|
+
* makes `ctx.api.pipelineExecutor.runPipeline.mutate()` resolve locally
|
|
59
|
+
* on a forked worker that has a co-located pipeline-executor.
|
|
60
|
+
*/
|
|
61
|
+
export declare function localProviderLink<TRouter extends AnyRouter>(resolver: LocalProviderResolver, observerOpts?: CapUsageObserverOptions): TRPCLink<TRouter>;
|
|
62
|
+
/**
|
|
63
|
+
* Hard deadline for service discovery on a load-balanced cap call.
|
|
64
|
+
*
|
|
65
|
+
* Before this constant existed, `awaitServiceCandidates` polled forever
|
|
66
|
+
* if a service never (re-)appeared — every consumer of a wedged cap then
|
|
67
|
+
* hung indefinitely (observed live as `[brokerTransportLink] still
|
|
68
|
+
* awaiting … after 200s+` in dev logs, cascading through every chain
|
|
69
|
+
* that touched the affected cap). With the deadline in place, a missing
|
|
70
|
+
* provider surfaces as a Moleculer "service not found" rejection at the
|
|
71
|
+
* caller site after at most ~30s — within the cold-boot / respawn
|
|
72
|
+
* window for any well-behaved addon, while still bounding the failure
|
|
73
|
+
* mode of a genuinely-stuck cap.
|
|
74
|
+
*
|
|
75
|
+
* Callers that legitimately need to wait longer (e.g. boot ordering)
|
|
76
|
+
* use `ctx.acquireCapability(name, scope, { timeoutMs })` BEFORE issuing
|
|
77
|
+
* the RPC — see CLAUDE.md's "Do not re-implement Moleculer discovery /
|
|
78
|
+
* liveness / events" rule. Per-link override is exposed for tests +
|
|
79
|
+
* tuning via `BrokerTransportLinkOptions.discoveryTimeoutMs`.
|
|
80
|
+
*/
|
|
81
|
+
export declare const DEFAULT_DISCOVERY_TIMEOUT_MS = 30000;
|
|
82
|
+
/**
|
|
83
|
+
* Options for {@link brokerCallForCap} — the reusable broker-dispatch core
|
|
84
|
+
* shared by `brokerTransportLink` and the parent-side `onUnownedCall` fallback.
|
|
85
|
+
*/
|
|
86
|
+
export interface BrokerCapCallOpts {
|
|
87
|
+
/**
|
|
88
|
+
* Pins the call to a specific Moleculer node. When set, the call uses the
|
|
89
|
+
* bounded pinned-discovery retry (2s) and surfaces "service not found" fast,
|
|
90
|
+
* mirroring `brokerTransportLink`'s pinned path. When absent, the call uses
|
|
91
|
+
* the unbounded load-balanced discovery wait.
|
|
92
|
+
*/
|
|
93
|
+
readonly nodeId?: string;
|
|
94
|
+
/** Static service-name override for the cap (matches `brokerTransportLink`'s serviceMap entry). */
|
|
95
|
+
readonly forceServiceName?: string;
|
|
96
|
+
/**
|
|
97
|
+
* Abort flag — set `aborted = true` to tear down a pending discovery wait.
|
|
98
|
+
* Defaults to a never-aborted flag when omitted.
|
|
99
|
+
*/
|
|
100
|
+
readonly abort?: {
|
|
101
|
+
aborted: boolean;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Resolve and dispatch a cap method call over a Moleculer broker.
|
|
106
|
+
*
|
|
107
|
+
* Routing (service discovery + node resolution + `capActionName`) is delegated
|
|
108
|
+
* to the shared {@link resolveBrokerCapCall} core — the SAME core
|
|
109
|
+
* `brokerTransportLink` uses — so the two can never drift. This function is the
|
|
110
|
+
* thin "resolve then `broker.call`" wrapper.
|
|
111
|
+
*
|
|
112
|
+
* What this function IS used for:
|
|
113
|
+
* The hub / agent parent-side `onUnownedCall` fallback (F0 — when a forked
|
|
114
|
+
* child calls a cap no local sibling owns and the resolver returns `no-provider`,
|
|
115
|
+
* e.g. the hub's `$core-caps` / `$stream-probe` core services, which are
|
|
116
|
+
* Moleculer services NOT registered as CapabilityRegistry providers).
|
|
117
|
+
*
|
|
118
|
+
* A genuinely-absent service surfaces the broker's "service not found" error
|
|
119
|
+
* (bounded for pinned calls) rather than hanging.
|
|
120
|
+
*/
|
|
121
|
+
export declare function brokerCallForCap(broker: ServiceBroker, capName: string, method: string, args: unknown, opts?: BrokerCapCallOpts): Promise<unknown>;
|
|
122
|
+
/**
|
|
123
|
+
* Tunables for {@link brokerTransportLink}.
|
|
124
|
+
*
|
|
125
|
+
* `discoveryTimeoutMs` bounds the load-balanced service-discovery wait
|
|
126
|
+
* inside `awaitServiceCandidates`. Default {@link DEFAULT_DISCOVERY_TIMEOUT_MS}.
|
|
127
|
+
* Overriding is for tests + tuning — production callers that need a
|
|
128
|
+
* different deadline should use `ctx.acquireCapability` instead, since
|
|
129
|
+
* that's the documented liveness mechanism (CLAUDE.md).
|
|
130
|
+
*/
|
|
131
|
+
export interface BrokerTransportLinkOptions {
|
|
132
|
+
readonly discoveryTimeoutMs?: number;
|
|
133
|
+
}
|
|
134
|
+
export declare function brokerTransportLink<TRouter extends AnyRouter>(broker: ServiceBroker, serviceMap?: Readonly<Record<string, string>>, observerOpts?: CapUsageObserverOptions, linkOptions?: BrokerTransportLinkOptions): TRPCLink<TRouter>;
|
|
135
|
+
/**
|
|
136
|
+
* Middle link that routes a cap op to a LOCAL addon-runner over UDS via the
|
|
137
|
+
* `LocalChildRegistry`. If no local child owns `(capName, deviceId?)`, the op
|
|
138
|
+
* passes through to `next(op)` (e.g. `brokerTransportLink` for remote agents),
|
|
139
|
+
* so this link is transparent for everything it does not own.
|
|
140
|
+
*
|
|
141
|
+
* `deviceId` for device-scoped caps is read from `op.input` (the same place
|
|
142
|
+
* the codegen'd device-scoped routers carry it); the full `op.input` is
|
|
143
|
+
* forwarded as the child method's argument.
|
|
144
|
+
*/
|
|
145
|
+
export declare function ipcChildLink<TRouter extends AnyRouter>(registry: LocalChildRegistry): TRPCLink<TRouter>;
|
|
146
|
+
/**
|
|
147
|
+
* Middle link that routes a child addon's outbound `ctx.api` cap call to the
|
|
148
|
+
* parent hub over UDS via `callOut` (obtained at call-time so the child can
|
|
149
|
+
* reconnect without rebuilding its tRPC client).
|
|
150
|
+
*
|
|
151
|
+
* Delegation rules:
|
|
152
|
+
* - `getCallOut()` returns `null` → not connected, delegate via `next(op)`.
|
|
153
|
+
* - `parsePath(op.path)` returns `null` → unparseable path, delegate via `next(op)`.
|
|
154
|
+
* - `callOut` rejects with a no-route error (message starts with `UDS_NO_ROUTE_PREFIX`)
|
|
155
|
+
* → the parent could not route the call (no local sibling, no cluster fallback);
|
|
156
|
+
* delegate via `next(op)` (broker fallback) — safe because no provider ran.
|
|
157
|
+
* - `callOut` rejects with any other error → real provider error; propagate to
|
|
158
|
+
* the caller via `observer.error` — NEVER retry via broker to avoid
|
|
159
|
+
* double-executing side effects.
|
|
160
|
+
*/
|
|
161
|
+
export declare function ipcParentLink<TRouter extends AnyRouter>(getCallOut: () => ((input: CapCallInput) => Promise<unknown>) | null): TRPCLink<TRouter>;
|
|
162
|
+
export type LinkChainTarget = {
|
|
163
|
+
type: 'local-router';
|
|
164
|
+
terminatingLink: TRPCLink<AnyRouter>;
|
|
165
|
+
} | {
|
|
166
|
+
type: 'ws';
|
|
167
|
+
terminatingLink: TRPCLink<AnyRouter>;
|
|
168
|
+
} | {
|
|
169
|
+
type: 'broker';
|
|
170
|
+
broker: ServiceBroker;
|
|
171
|
+
serviceMap?: Readonly<Record<string, string>>;
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* Optional observer hookup for `buildLinkChain` — threads the same
|
|
175
|
+
* `CapUsageObserverOptions` through `localProviderLink` and
|
|
176
|
+
* `brokerTransportLink` so every op is recorded once regardless of
|
|
177
|
+
* whether it resolved locally or over the broker.
|
|
178
|
+
*/
|
|
179
|
+
export interface LinkChainObserverHookup {
|
|
180
|
+
readonly observerOpts?: CapUsageObserverOptions;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Build the tRPC link chain for an addon context.
|
|
184
|
+
*
|
|
185
|
+
* Always starts with `localProviderLink` (if a resolver is provided),
|
|
186
|
+
* then falls through to the appropriate terminating link based on the
|
|
187
|
+
* deployment context.
|
|
188
|
+
*/
|
|
189
|
+
export declare function buildLinkChain(target: LinkChainTarget, localResolver?: LocalProviderResolver, hookup?: LinkChainObserverHookup): TRPCLink<AnyRouter>[];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialize/deserialize non-Buffer TypedArrays for Moleculer MsgPack transport.
|
|
3
|
+
*
|
|
4
|
+
* MsgPack handles Buffer natively but serializes Float32Array, Int16Array etc.
|
|
5
|
+
* as plain objects with numeric keys. These helpers convert them to Buffer
|
|
6
|
+
* with a type tag for transport and reconstruct them on arrival.
|
|
7
|
+
*
|
|
8
|
+
* Used by:
|
|
9
|
+
* - capability-bridge.ts (hub → child proxy calls)
|
|
10
|
+
* - addon-service-factory.ts (child → provider param reconstruction)
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Convert non-Buffer TypedArrays → `{ __typedArray, type, data: Buffer }` recursively.
|
|
14
|
+
*
|
|
15
|
+
* A WeakSet tracks objects already visited on the current descent path so a
|
|
16
|
+
* cyclic input throws a precise error at the offending path instead of
|
|
17
|
+
* blowing the stack with "Maximum call stack size exceeded". tRPC inputs
|
|
18
|
+
* should never be cyclic in practice — this is a safety net for regressions
|
|
19
|
+
* that accidentally introduce shared-reference loops (e.g. a config object
|
|
20
|
+
* that holds a back-pointer into its own container).
|
|
21
|
+
*/
|
|
22
|
+
declare function serializeTypedArrays(value: unknown, seen?: WeakSet<object>, path?: string): unknown;
|
|
23
|
+
/** Reconstruct TypedArrays from tagged objects. */
|
|
24
|
+
declare function deserializeTypedArrays(value: unknown): unknown;
|
|
25
|
+
export { serializeTypedArrays, deserializeTypedArrays };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ICamstackAddon, IEventBus, IScopedLogger } from '@camstack/types';
|
|
2
|
+
export declare function runWorkerDeviceRestoreWithRetry(addon: ICamstackAddon, context: {
|
|
3
|
+
api?: unknown;
|
|
4
|
+
eventBus?: IEventBus;
|
|
5
|
+
logger?: IScopedLogger | {
|
|
6
|
+
info?: (m: string) => void;
|
|
7
|
+
warn?: (m: string) => void;
|
|
8
|
+
debug?: (m: string) => void;
|
|
9
|
+
};
|
|
10
|
+
}, addonId: string, sourceNodeId: string): Promise<void>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CapabilityDefinition } from '@camstack/types';
|
|
2
|
+
/** The deprecated runtime metadata hint carried on a `ProviderRegistration`. */
|
|
3
|
+
export type ProviderKindHint = {
|
|
4
|
+
readonly kind?: 'native' | 'wrapper';
|
|
5
|
+
readonly defaultActive?: boolean;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Compare a runtime registration hint against the authoritative cap
|
|
9
|
+
* definition. Returns a human-readable warning string when they disagree,
|
|
10
|
+
* or `null` when the hint is absent or consistent.
|
|
11
|
+
*/
|
|
12
|
+
export declare function describeProviderKindDrift(capName: string, capDef: Pick<CapabilityDefinition, 'kind' | 'defaultActive'>, hint: ProviderKindHint): string | null;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RestartCoordinator — shared primitives for the framework live-update flow.
|
|
3
|
+
*
|
|
4
|
+
* Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md (P2)
|
|
5
|
+
*
|
|
6
|
+
* Three responsibilities:
|
|
7
|
+
* 1) Marker schema + read/write/clear on `<dataDir>/.restart-pending`.
|
|
8
|
+
* 2) Boot-side handoff: `readPendingRestart()` returns the payload exactly
|
|
9
|
+
* once and atomically clears the marker so a crashed second boot
|
|
10
|
+
* doesn't re-fire the completion event.
|
|
11
|
+
* 3) Environment-agnostic `scheduleSelfRestart()` — Electron calls
|
|
12
|
+
* `app.relaunch()`+`app.exit(0)`, everything else `process.exit(0)`.
|
|
13
|
+
*
|
|
14
|
+
* The cap method that writes the marker lives in the addons cap (P3); this
|
|
15
|
+
* module is the zero-dep primitive both the cap (writer) and PostBootService
|
|
16
|
+
* (reader) call into.
|
|
17
|
+
*/
|
|
18
|
+
/** Filename of the restart marker, written under `<dataDir>`. */
|
|
19
|
+
export declare const RESTART_MARKER_FILE = ".restart-pending";
|
|
20
|
+
/** Discriminated union of reasons the hub can be asked to restart. */
|
|
21
|
+
export type RestartKind = 'framework-update' | 'framework-bulk-update' | 'manual' | 'system';
|
|
22
|
+
/**
|
|
23
|
+
* On-disk shape. All fields stable + load-bearing for the completion event.
|
|
24
|
+
* Future kinds add new optional fields; existing readers ignore them.
|
|
25
|
+
*/
|
|
26
|
+
export interface PendingRestartMarker {
|
|
27
|
+
readonly kind: RestartKind;
|
|
28
|
+
readonly packageName?: string;
|
|
29
|
+
readonly fromVersion?: string;
|
|
30
|
+
readonly toVersion?: string;
|
|
31
|
+
readonly requestedBy?: string;
|
|
32
|
+
readonly requestedAt: number;
|
|
33
|
+
}
|
|
34
|
+
/** Resolve the marker path inside a data directory. */
|
|
35
|
+
export declare function getRestartMarkerPath(dataDir: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Write the marker atomically. Existing marker is overwritten — the most
|
|
38
|
+
* recent restart request wins.
|
|
39
|
+
*
|
|
40
|
+
* Uses write-then-rename so a crash mid-write leaves either the old marker
|
|
41
|
+
* intact or no marker at all (never a half-written file).
|
|
42
|
+
*/
|
|
43
|
+
export declare function writePendingRestart(dataDir: string, marker: PendingRestartMarker): void;
|
|
44
|
+
/**
|
|
45
|
+
* Read + consume the marker. Returns the parsed payload on success and
|
|
46
|
+
* clears the file in the same tick (rename → unlink), so a crash between
|
|
47
|
+
* read and emit won't replay the completion event on the next boot.
|
|
48
|
+
*
|
|
49
|
+
* Failure modes:
|
|
50
|
+
* - no marker present → returns null
|
|
51
|
+
* - file unreadable / IO → logs to console, returns null, leaves marker
|
|
52
|
+
* - JSON malformed → logs, clears the marker, returns null
|
|
53
|
+
* - missing required `kind` / `requestedAt` → logs, clears, returns null
|
|
54
|
+
*
|
|
55
|
+
* "Clear on parse failure" is intentional: a stuck unparseable marker would
|
|
56
|
+
* otherwise block every subsequent restart's completion event.
|
|
57
|
+
*
|
|
58
|
+
* NOTE: the `console.error` calls below are deliberate, documented
|
|
59
|
+
* residuals. This is a stateless bootstrap utility invoked during hub
|
|
60
|
+
* startup before `LogManager` / the Moleculer broker exist — there is no
|
|
61
|
+
* `IScopedLogger` or `$hub.log` transport in scope. Threading a logger
|
|
62
|
+
* parameter through every caller is out of scope for the D8 log-forwarding
|
|
63
|
+
* work (which only touches `packages/kernel/src`).
|
|
64
|
+
*/
|
|
65
|
+
export declare function readPendingRestart(dataDir: string): PendingRestartMarker | null;
|
|
66
|
+
/** Remove the marker if present. No-op if missing. */
|
|
67
|
+
export declare function clearPendingRestart(dataDir: string): void;
|
|
68
|
+
/**
|
|
69
|
+
* Schedule a self-restart appropriate for the runtime:
|
|
70
|
+
* - Electron: `app.relaunch()` then `app.exit(0)` — the bundle handles the spawn.
|
|
71
|
+
* - Docker / standalone Node: `process.exit(0)` — the supervisor (compose
|
|
72
|
+
* `restart: unless-stopped`, systemd, pm2, …) brings the process back up.
|
|
73
|
+
*
|
|
74
|
+
* Caller is expected to have:
|
|
75
|
+
* 1) Written the marker via `writePendingRestart`.
|
|
76
|
+
* 2) Returned the cap-method response to the caller (so the WS doesn't
|
|
77
|
+
* drop mid-reply).
|
|
78
|
+
* 3) Closed the Fastify instance gracefully (`await fastify.close()`).
|
|
79
|
+
*
|
|
80
|
+
* The 500ms delay is the same beat used by P3's cap method — kept here as a
|
|
81
|
+
* default so non-cap callers (signal handlers, future flows) share the same
|
|
82
|
+
* shutdown pacing.
|
|
83
|
+
*/
|
|
84
|
+
export interface ScheduleSelfRestartOptions {
|
|
85
|
+
/** Delay before exit (ms). Default 500 — gives in-flight RPC time to drain. */
|
|
86
|
+
readonly delayMs?: number;
|
|
87
|
+
/** Override exit code. Default 0 (clean exit → supervisor restart). */
|
|
88
|
+
readonly exitCode?: number;
|
|
89
|
+
}
|
|
90
|
+
export declare function scheduleSelfRestart(options?: ScheduleSelfRestartOptions): void;
|