@camstack/system 1.1.11 → 1.1.12
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-runner.mjs +1 -1
- package/dist/builtins/device-manager/device-aggregation-merge.d.ts +22 -0
- package/dist/builtins/device-manager/device-aggregation.d.ts +220 -0
- package/dist/builtins/device-manager/device-bindings-store.d.ts +100 -0
- package/dist/builtins/device-manager/device-manager.addon.d.ts +41 -332
- package/dist/builtins/device-manager/device-manager.addon.js +3293 -2871
- package/dist/builtins/device-manager/device-manager.addon.mjs +3293 -2871
- package/dist/builtins/device-manager/device-meta-actions.d.ts +159 -0
- package/dist/builtins/device-manager/device-meta-store.d.ts +72 -0
- package/dist/builtins/device-manager/device-meta-types.d.ts +169 -0
- package/dist/builtins/device-manager/device-projection.d.ts +74 -0
- package/dist/builtins/device-manager/device-provider-context.d.ts +65 -0
- package/dist/builtins/device-manager/device-queries.d.ts +38 -0
- package/dist/builtins/device-manager/device-state-mirror.d.ts +137 -0
- package/dist/builtins/device-manager/device-sync-resolvers.d.ts +41 -0
- package/dist/index.js +215 -0
- package/dist/index.mjs +216 -3
- package/dist/kernel/cap-router-builder.d.ts +78 -0
- package/dist/kernel/index.d.ts +2 -0
- package/dist/{manifest-python-deps-1zTy3vXe.mjs → manifest-python-deps-BfJEdXhi.mjs} +2 -2
- package/package.json +1 -1
package/dist/addon-runner.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as setWorkerNativeCapsChangeListener, A as createUdsLoggerWithControl, X as getWorkerNativeCapProvider, Z as getWorkerNativeCapSnapshot, i as createUdsAddonContext, j as LocalChildClient, mt as resolveAddonClass, pt as installManifestNativeDeps, t as installManifestPythonDeps, tt as validateProviderRegistrations } from "./manifest-python-deps-
|
|
1
|
+
import { $ as setWorkerNativeCapsChangeListener, A as createUdsLoggerWithControl, X as getWorkerNativeCapProvider, Z as getWorkerNativeCapSnapshot, i as createUdsAddonContext, j as LocalChildClient, mt as resolveAddonClass, pt as installManifestNativeDeps, t as installManifestPythonDeps, tt as validateProviderRegistrations } from "./manifest-python-deps-BfJEdXhi.mjs";
|
|
2
2
|
import { t as CustomActionRegistry } from "./custom-action-registry-BEXwC-oo.mjs";
|
|
3
3
|
import { register } from "node:module";
|
|
4
4
|
import * as fs from "node:fs";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ConfigUISchemaWithValues } from '@camstack/types';
|
|
2
|
+
import { ContributionShape } from './device-meta-types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Walk the sections/fields of a contribution and inject `writerCapName` +
|
|
5
|
+
* `writerAddonId` + `source` on each editable field. Readonly fields and
|
|
6
|
+
* structural fields (separator/info/button) pass through untouched. The
|
|
7
|
+
* aggregator is the single place that knows provenance — provider schemas
|
|
8
|
+
* stay clean, UI-bound metadata is attached once at the boundary.
|
|
9
|
+
*/
|
|
10
|
+
export declare function tagContribution(contribution: ContributionShape, capName: string, addonId: string, kind: 'settings' | 'live'): ContributionShape;
|
|
11
|
+
export declare function isFieldRecord(value: unknown): value is Record<string, unknown>;
|
|
12
|
+
/**
|
|
13
|
+
* Convert a strict `ConfigUISchemaWithValues` (readonly arrays, typed
|
|
14
|
+
* field union) into the cap wire shape `ContributionShape` (mutable
|
|
15
|
+
* arrays, opaque field records). Required because the cap method z.infer
|
|
16
|
+
* uses mutable arrays — readonly arrays are not assignable to mutable
|
|
17
|
+
* even when structurally identical, so a structural copy bridges the gap
|
|
18
|
+
* without disabling the type checker.
|
|
19
|
+
*/
|
|
20
|
+
export declare function toWireShape(input: ConfigUISchemaWithValues): ContributionShape;
|
|
21
|
+
export declare function tagField(field: unknown, capName: string, addonId: string, source: 'settings' | 'live', kind: 'settings' | 'live'): unknown;
|
|
22
|
+
export declare function mergeAggregates(parts: readonly ContributionShape[]): ContributionShape;
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { deviceManagerCapability, InferProvider, AddonContext, CapabilityDefinition, DeviceBindingEntry, DeviceConfigSpec, DeviceSettingsContribution, ICapabilityRegistry, IDevice } from '@camstack/types';
|
|
2
|
+
import { ContributionShape, DriverConfigSchemaResult } from './device-meta-types.js';
|
|
3
|
+
import { BindingsDeps, RemoteNativeCaps } from './device-bindings-store.js';
|
|
4
|
+
/**
|
|
5
|
+
* Dependencies the aggregation + update routing functions consume. Assembled
|
|
6
|
+
* by the addon from its own state and passed in explicitly — no hidden `this`
|
|
7
|
+
* capture. `bindingsDeps` carries the lower-level context the bindings-store
|
|
8
|
+
* resolvers need so this module can call them directly.
|
|
9
|
+
*/
|
|
10
|
+
export interface AggregationDeps {
|
|
11
|
+
readonly ctx: AddonContext;
|
|
12
|
+
readonly capabilityRegistry: ICapabilityRegistry | undefined;
|
|
13
|
+
readonly remoteNativeCaps: RemoteNativeCaps;
|
|
14
|
+
readonly bindingsDeps: BindingsDeps;
|
|
15
|
+
}
|
|
16
|
+
type IDeviceManagerProvider = InferProvider<typeof deviceManagerCapability>;
|
|
17
|
+
export declare function getDeviceAggregate(deps: AggregationDeps, deviceId: number, kind: 'settings' | 'live'): Promise<ContributionShape | null>;
|
|
18
|
+
/**
|
|
19
|
+
* System-scoped per-device contributions — the deliberate exception to
|
|
20
|
+
* binding-driven aggregation (D12).
|
|
21
|
+
*
|
|
22
|
+
* A `scope: 'system'` cap with `exposesDeviceSettings: true` holds per-device
|
|
23
|
+
* state but is NOT bound per-device: it is a system addon, not a BaseDevice,
|
|
24
|
+
* so it never calls `registerNativeCap` and never appears in
|
|
25
|
+
* `getBindings(deviceId)`. The binding-driven loop therefore skips it and its
|
|
26
|
+
* per-device panel never renders. Two such caps ship today:
|
|
27
|
+
* - `stream-broker` (singleton) — the RTSP-restream / pre-buffer settings
|
|
28
|
+
* tab, scoped to the cameras whose streams it serves.
|
|
29
|
+
* - `device-export` (collection) — the "Export" panel; a device can be
|
|
30
|
+
* exposed to MULTIPLE exporters at once (Alexa + HomeKit + HA-MQTT).
|
|
31
|
+
*
|
|
32
|
+
* D12 bans fanning a per-device call out to every same-named provider of a
|
|
33
|
+
* `scope: 'device'` cap, because vendor providers SHARE cap names
|
|
34
|
+
* (`stream-params`/`ptz` from reolink AND hikvision). System caps are NOT
|
|
35
|
+
* vendor-shared — a system cap name maps to one active provider (singleton)
|
|
36
|
+
* or one declared collection — so consulting the cap's own provider(s)
|
|
37
|
+
* directly is safe. Each provider gates internally by deviceId and returns
|
|
38
|
+
* null for devices it does not own.
|
|
39
|
+
*
|
|
40
|
+
* `seenCaps` skips any system cap that already contributed via a binding so
|
|
41
|
+
* its section is never duplicated.
|
|
42
|
+
*/
|
|
43
|
+
export declare function collectSystemDeviceContributions(deps: AggregationDeps, deviceId: number, kind: 'settings' | 'live', seenCaps: ReadonlySet<string>): Promise<ContributionShape[]>;
|
|
44
|
+
/**
|
|
45
|
+
* D14: framework-derived device-config contribution.
|
|
46
|
+
*
|
|
47
|
+
* `kind === 'live'` — device-config caps contribute nothing to the live
|
|
48
|
+
* aggregate (they hold editable config, not live observables).
|
|
49
|
+
*
|
|
50
|
+
* `ui.kind === 'widget'` — emits a single structural `type:'widget'`
|
|
51
|
+
* section; the widget self-persists via the cap's own mutations.
|
|
52
|
+
*
|
|
53
|
+
* `ui.kind === 'derived-form'` — calls `getOptions`/`getStatus` on the
|
|
54
|
+
* bound provider, runs the registered pure builder, and returns the
|
|
55
|
+
* derived form sections. Returns null when the camera exposes nothing
|
|
56
|
+
* configurable or the provider is not yet registered.
|
|
57
|
+
*/
|
|
58
|
+
export declare function deriveDeviceConfigContribution(deps: AggregationDeps, registry: ICapabilityRegistry, def: CapabilityDefinition & {
|
|
59
|
+
deviceConfig: DeviceConfigSpec;
|
|
60
|
+
}, entry: DeviceBindingEntry, deviceId: number, kind: 'settings' | 'live'): Promise<ContributionShape | null>;
|
|
61
|
+
/**
|
|
62
|
+
* Build the device-manager's own contribution to the aggregator — the
|
|
63
|
+
* device identity (id, stableId, addonId, type, online) + the
|
|
64
|
+
* driver-specific config exposed by the device class via
|
|
65
|
+
* `zodEntriesToConfigUI`.
|
|
66
|
+
*
|
|
67
|
+
* Two paths, deliberately symmetric with `getSettingsSchema`:
|
|
68
|
+
*
|
|
69
|
+
* - Hub-local: device's IDevice instance lives in this process'
|
|
70
|
+
* DeviceRegistry, we read config + schema directly by reference.
|
|
71
|
+
* - Cross-process: device lives in a forked worker (RtspCamera on
|
|
72
|
+
* provider-rtsp, ONVIF on provider-onvif, …). We ask the worker's
|
|
73
|
+
* `device-ops.getSettingsSchema` native provider for a wire-
|
|
74
|
+
* serializable ConfigUISchema and merge it in under the same
|
|
75
|
+
* "Driver Config" section, so the UI sees the same shape regardless
|
|
76
|
+
* of where the IDevice physically runs.
|
|
77
|
+
*
|
|
78
|
+
* Returns `null` only when the device genuinely doesn't exist anywhere
|
|
79
|
+
* (no hub-local, no persisted ownership, no device-ops native). The
|
|
80
|
+
* aggregator falls back to contributor sections only in that case.
|
|
81
|
+
*/
|
|
82
|
+
export declare function buildBaseDeviceSection(deps: AggregationDeps, deviceId: number): Promise<ContributionShape | null>;
|
|
83
|
+
/**
|
|
84
|
+
* Lookup the native owner for `device-ops` on `deviceId` — the native-cap
|
|
85
|
+
* registry (hub-local and remote) is keyed by numeric id.
|
|
86
|
+
*/
|
|
87
|
+
export declare function resolveNativeDeviceOwner(deps: AggregationDeps, deviceId: number): {
|
|
88
|
+
addonId: string;
|
|
89
|
+
nodeId: string;
|
|
90
|
+
} | null;
|
|
91
|
+
/**
|
|
92
|
+
* Aggregate `status` across every registered cap for a device.
|
|
93
|
+
*
|
|
94
|
+
* Walks the supplied cap list (or `CAP_NAMES_WITH_STATUS` when
|
|
95
|
+
* omitted), looks up a native provider per cap via the capability
|
|
96
|
+
* registry, calls `provider.getStatus({ deviceId })`, and validates
|
|
97
|
+
* the return against the cap's own `status.schema`. Validation
|
|
98
|
+
* failures log a warning and yield `null` for that cap so the
|
|
99
|
+
* overall aggregate stays usable — a single misbehaving provider
|
|
100
|
+
* must not blank out a device's entire status view.
|
|
101
|
+
*
|
|
102
|
+
* Returned shape is `Record<capName, unknown | null>`; the client-
|
|
103
|
+
* side hook tightens this to `CapStatusTypeMap` via the generated
|
|
104
|
+
* `cap-status-types.ts`.
|
|
105
|
+
*/
|
|
106
|
+
export declare function getDeviceStatusAggregate(deps: AggregationDeps, input: {
|
|
107
|
+
readonly deviceId: number;
|
|
108
|
+
readonly caps?: readonly string[];
|
|
109
|
+
}): Promise<Record<string, unknown | null>>;
|
|
110
|
+
/**
|
|
111
|
+
* Return the driver-specific device-settings contribution. Hub-local
|
|
112
|
+
* devices call `getSettingsUISchema()` directly; forked-worker devices
|
|
113
|
+
* go through the `device-ops.getSettingsSchema` cap method on the
|
|
114
|
+
* numeric-id-keyed native registry.
|
|
115
|
+
*
|
|
116
|
+
* Returns a discriminated result so callers can distinguish three states:
|
|
117
|
+
* 'ok' – schema obtained successfully
|
|
118
|
+
* 'none' – driver genuinely has no settings schema
|
|
119
|
+
* 'unavailable' – worker was unreachable after retries (transient)
|
|
120
|
+
*/
|
|
121
|
+
export declare function resolveDriverConfigSchema(deps: AggregationDeps, deviceId: number, hubLocal: {
|
|
122
|
+
addonId: string;
|
|
123
|
+
device: IDevice;
|
|
124
|
+
} | null): Promise<DriverConfigSchemaResult>;
|
|
125
|
+
export declare function updateDeviceField(deps: AggregationDeps, input: {
|
|
126
|
+
deviceId: number;
|
|
127
|
+
writerCapName: string;
|
|
128
|
+
writerAddonId: string;
|
|
129
|
+
key: string;
|
|
130
|
+
value: unknown;
|
|
131
|
+
}): Promise<{
|
|
132
|
+
success: true;
|
|
133
|
+
}>;
|
|
134
|
+
/**
|
|
135
|
+
* Dispatch a device custom action. Hub-local devices run it directly;
|
|
136
|
+
* forked/remote devices route through the `device-ops` native cap
|
|
137
|
+
* (`runAction`) — the same hub-local-then-device-ops fan-out that
|
|
138
|
+
* `updateDeviceField` uses for `applySettingsPatch`.
|
|
139
|
+
*/
|
|
140
|
+
export declare function dispatchDeviceAction(deps: AggregationDeps, deviceId: number, action: string, input: unknown): Promise<unknown>;
|
|
141
|
+
/**
|
|
142
|
+
* Resolve the `DeviceSettingsContribution` provider that owns a tagged
|
|
143
|
+
* field. The `writerAddonId` on a tagged field equals `entry.providerAddonId`
|
|
144
|
+
* from the binding that produced it — for `kind:'wrapped'` entries, that is
|
|
145
|
+
* the wrapper addon id (e.g. 'snapshot-addon'); for native-only entries,
|
|
146
|
+
* the system addon id.
|
|
147
|
+
*
|
|
148
|
+
* Resolution order (Bug-3 fix):
|
|
149
|
+
* 1. `getProviderByAddon(capName, writerAddonId)` — resolves the
|
|
150
|
+
* system-registered provider by the addon id from the tagged field.
|
|
151
|
+
* For wrapper bindings (snapshot, motion-detection, etc.) this directly
|
|
152
|
+
* returns the wrapper provider, bypassing the native-first resolution
|
|
153
|
+
* order of `getProviderForDevice` that caused "method not found".
|
|
154
|
+
* 2. `getSingleton(capName)` — fallback for stale/mismatched writerAddonIds.
|
|
155
|
+
* The active singleton handles the contribution even if the addonId
|
|
156
|
+
* stored in the field is out of date (e.g. after an addon rename).
|
|
157
|
+
*
|
|
158
|
+
* `getProviderForDevice` is intentionally NOT used here: it returns the
|
|
159
|
+
* per-device native first when present (e.g. Reolink/ONVIF), and the native
|
|
160
|
+
* does NOT implement contribution methods — the root cause of Bug-3.
|
|
161
|
+
*/
|
|
162
|
+
export declare function resolveContributionProvider(registry: ICapabilityRegistry, _def: CapabilityDefinition, writerCapName: string, writerAddonId: string, deviceId: number): DeviceSettingsContribution;
|
|
163
|
+
/**
|
|
164
|
+
* Batched counterpart of `updateDeviceField`. Groups changes by
|
|
165
|
+
* `(writerCapName, writerAddonId)` so each contributor receives a
|
|
166
|
+
* single `applyDeviceSettingsPatch` with all of its updates merged —
|
|
167
|
+
* avoids N round-trips for simultaneous edits in the same save.
|
|
168
|
+
*
|
|
169
|
+
* Per-provider failures are captured in the `failures[]` output so the
|
|
170
|
+
* admin UI can highlight which sections didn't persist; a failure on
|
|
171
|
+
* one provider does NOT abort the others.
|
|
172
|
+
*/
|
|
173
|
+
export declare function updateDeviceFieldsBatch(deps: AggregationDeps, input: {
|
|
174
|
+
deviceId: number;
|
|
175
|
+
changes: ReadonlyArray<{
|
|
176
|
+
writerCapName: string;
|
|
177
|
+
writerAddonId: string;
|
|
178
|
+
key: string;
|
|
179
|
+
value: unknown;
|
|
180
|
+
}>;
|
|
181
|
+
}): Promise<{
|
|
182
|
+
success: true;
|
|
183
|
+
failures: {
|
|
184
|
+
writerCapName: string;
|
|
185
|
+
writerAddonId: string;
|
|
186
|
+
error: string;
|
|
187
|
+
}[];
|
|
188
|
+
}>;
|
|
189
|
+
/** Apply a single grouped patch to the appropriate provider. Mirrors
|
|
190
|
+
* `updateDeviceField` routing (special-case device-manager, else
|
|
191
|
+
* registry lookup). Used by `updateDeviceFieldsBatch`. */
|
|
192
|
+
export declare function applyGroupPatch(deps: AggregationDeps, deviceId: number, group: {
|
|
193
|
+
writerCapName: string;
|
|
194
|
+
writerAddonId: string;
|
|
195
|
+
patch: Record<string, unknown>;
|
|
196
|
+
}): Promise<void>;
|
|
197
|
+
export declare function listWrappersForCap(deps: AggregationDeps, input: {
|
|
198
|
+
capName: string;
|
|
199
|
+
}): Promise<string[]>;
|
|
200
|
+
export declare function listBindableCapsForDeviceType(deps: AggregationDeps, input: {
|
|
201
|
+
deviceType: string;
|
|
202
|
+
}): Promise<Array<{
|
|
203
|
+
capName: string;
|
|
204
|
+
wrappers: string[];
|
|
205
|
+
}>>;
|
|
206
|
+
export declare function setWrapperActive(deps: AggregationDeps, input: {
|
|
207
|
+
deviceId: number;
|
|
208
|
+
capName: string;
|
|
209
|
+
wrapperAddonId: string;
|
|
210
|
+
active: boolean;
|
|
211
|
+
}): Promise<void>;
|
|
212
|
+
/**
|
|
213
|
+
* Per-device wireable-field catalog — the domain status fields a device's
|
|
214
|
+
* bound caps expose, for the operator's cross-device wiring UI. Binding-driven:
|
|
215
|
+
* walks `getBindings(deviceId)`, skips wrapper caps (their status schemas are
|
|
216
|
+
* internal book-keeping, not wireable domain data), and enumerates each cap's
|
|
217
|
+
* status schema leaf fields. Behavior unchanged from the inline provider method.
|
|
218
|
+
*/
|
|
219
|
+
export declare function getWireableFields(deps: AggregationDeps, input: Parameters<IDeviceManagerProvider['getWireableFields']>[0]): ReturnType<IDeviceManagerProvider['getWireableFields']>;
|
|
220
|
+
export {};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { AddonContext, DeviceBindingEntry, ICapabilityRegistry } from '@camstack/types';
|
|
2
|
+
import { DeviceBindingsStore } from './device-meta-types.js';
|
|
3
|
+
/** Push-fed remote native-cap cache shape (numeric deviceId → capName → owner). */
|
|
4
|
+
export type RemoteNativeCaps = Map<number, Map<string, {
|
|
5
|
+
addonId: string;
|
|
6
|
+
nodeId: string;
|
|
7
|
+
}>>;
|
|
8
|
+
/**
|
|
9
|
+
* Low-level dependencies the binding resolver needs. Assembled by the addon
|
|
10
|
+
* from its own (mostly private) state and passed in explicitly — no hidden
|
|
11
|
+
* `this` capture.
|
|
12
|
+
*/
|
|
13
|
+
export interface BindingsDeps {
|
|
14
|
+
readonly ctx: AddonContext;
|
|
15
|
+
readonly capabilityRegistry: ICapabilityRegistry | undefined;
|
|
16
|
+
readonly remoteNativeCaps: RemoteNativeCaps;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Wire the push-fed cross-process native-cap cache (`remoteNativeCaps`).
|
|
20
|
+
* Workers emit `DeviceBindingsChanged` on `ctx.registerNativeCap` / device
|
|
21
|
+
* removal; we mirror those into `remoteNativeCaps` so `getBindings` returns the
|
|
22
|
+
* full cluster view. Events from the local node are ignored: hub-local natives
|
|
23
|
+
* live in `capabilityRegistry` and are folded in directly by getBindings.
|
|
24
|
+
*
|
|
25
|
+
* Push events are accurate in the steady state but can be lost during the
|
|
26
|
+
* Moleculer transport handshake window (hub restart, crash-respawn,
|
|
27
|
+
* restartAddon). The reliable replacement for lost events is the D3 re-handshake
|
|
28
|
+
* (`listClusterNativeCaps()`), which `resolveNativeCapOwnerSync` /
|
|
29
|
+
* `getBindings` step 4 fall through to on a push miss. The `$node.disconnected`
|
|
30
|
+
* handler purges a gone node's entries; the worker re-handshakes (and re-emits
|
|
31
|
+
* `native-registered`) on its next boot.
|
|
32
|
+
*/
|
|
33
|
+
export declare function wireRemoteNativeCapSync(ctx: AddonContext, remoteNativeCaps: RemoteNativeCaps): void;
|
|
34
|
+
export declare function readBindingsStore(deps: BindingsDeps): Promise<DeviceBindingsStore>;
|
|
35
|
+
export declare function writeBindingsStore(deps: BindingsDeps, next: DeviceBindingsStore): Promise<void>;
|
|
36
|
+
export declare function resolveWrapperNodeId(_wrapperAddonId: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Reduce a provider node id to the routable form `DeviceProxy` can pin.
|
|
39
|
+
*
|
|
40
|
+
* Every addon runs in its own `addon-runner` with the composite node id
|
|
41
|
+
* `${parentNodeId}/${runnerId}` (see `addon-runner.ts`) — e.g.
|
|
42
|
+
* `hub/provider-reolink` or `dev-agent-0/provider-reolink`. That composite is
|
|
43
|
+
* an IDENTITY, not a routable target: the `CapRouteResolver` reaches a child
|
|
44
|
+
* only THROUGH its parent (the hub resolves a hub-local-uds child by
|
|
45
|
+
* cap+device; an agent forwards to its own child). `DeviceProxy` pins
|
|
46
|
+
* `entry.providerNodeId` on every cap call, so a binding entry must expose the
|
|
47
|
+
* parent node id — otherwise the explicit pin classifies as `remote-moleculer`
|
|
48
|
+
* to an unknown node → `no-provider`, which surfaces as
|
|
49
|
+
* "this camera doesn't expose …" for client-proxy-driven widget caps
|
|
50
|
+
* (motion-zones, privacy-mask). Wrappers already report the parent via
|
|
51
|
+
* `resolveWrapperNodeId`; this aligns natives with the same contract.
|
|
52
|
+
*
|
|
53
|
+
* A flat node id (a genuine standalone node with no `/`) is returned
|
|
54
|
+
* unchanged.
|
|
55
|
+
*/
|
|
56
|
+
export declare function toRoutableProviderNodeId(nodeId: string): string;
|
|
57
|
+
/**
|
|
58
|
+
* Resolve a remote native cap entry for a given `(capName, deviceId)` by
|
|
59
|
+
* consulting the handshake-fed `HubNodeRegistry` via
|
|
60
|
+
* `ctx.kernel.listClusterNativeCaps()`. Called when the push-based
|
|
61
|
+
* `remoteNativeCaps` cache misses — covers the Moleculer transport
|
|
62
|
+
* handshake window where `DeviceBindingsChanged` events were lost but the
|
|
63
|
+
* D3 re-handshake (post device restore) has already populated the registry.
|
|
64
|
+
*
|
|
65
|
+
* Returns `null` when the entry is genuinely not present in the cluster
|
|
66
|
+
* view (cap not registered on any worker for that device).
|
|
67
|
+
*/
|
|
68
|
+
export declare function resolveRemoteNativeCapFromRegistry(deps: BindingsDeps, capName: string, deviceId: number): {
|
|
69
|
+
addonId: string;
|
|
70
|
+
nodeId: string;
|
|
71
|
+
} | null;
|
|
72
|
+
export declare function getBindings(deps: BindingsDeps, input: {
|
|
73
|
+
deviceId: number;
|
|
74
|
+
}): Promise<{
|
|
75
|
+
deviceId: number;
|
|
76
|
+
entries: DeviceBindingEntry[];
|
|
77
|
+
}>;
|
|
78
|
+
/**
|
|
79
|
+
* Whole-fleet binding dump. Iterates every device known to the
|
|
80
|
+
* deviceRegistry and reuses the per-device `getBindings` resolver
|
|
81
|
+
* for each — same routing rules, single round-trip. Used by
|
|
82
|
+
* `SystemManager.init()` for warm-boot.
|
|
83
|
+
*
|
|
84
|
+
* Bindings change rarely (wrapper toggle, device add/remove) so
|
|
85
|
+
* clients invalidate via the existing
|
|
86
|
+
* `capability.binding-changed` event rather than re-fetching this
|
|
87
|
+
* payload periodically.
|
|
88
|
+
*/
|
|
89
|
+
export declare function getAllBindings(deps: BindingsDeps): Promise<Array<{
|
|
90
|
+
deviceId: number;
|
|
91
|
+
entries: DeviceBindingEntry[];
|
|
92
|
+
}>>;
|
|
93
|
+
/**
|
|
94
|
+
* Resolve a numeric deviceId to a stableId via persisted meta.
|
|
95
|
+
* Used only by the device-identity section of the device-details
|
|
96
|
+
* aggregator (see `buildBaseDeviceSection`) to surface the stableId as
|
|
97
|
+
* a readonly display field. All runtime/registry lookups are keyed by
|
|
98
|
+
* numeric deviceId; this helper is display-only.
|
|
99
|
+
*/
|
|
100
|
+
export declare function lookupPersistedStableId(deps: BindingsDeps, deviceId: number): Promise<string | undefined>;
|