@camstack/system 1.2.276 → 1.2.278
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/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
- package/dist/builtins/device-manager/device-bindings-store.d.ts +10 -0
- package/dist/builtins/device-manager/device-manager.addon.d.ts +0 -2
- package/dist/builtins/device-manager/device-manager.addon.js +63 -118
- package/dist/builtins/device-manager/device-manager.addon.mjs +64 -116
- package/dist/builtins/device-manager/device-meta-types.d.ts +15 -27
- package/dist/builtins/device-manager/device-source-activation.d.ts +9 -43
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-D_OlSf31.js → dist-BWz_gZ5l.js} +145 -85
- package/dist/{dist-AHdiIdJH.mjs → dist-D1atncyi.mjs} +145 -85
- package/dist/index.d.ts +1 -1
- package/dist/index.js +14 -67
- package/dist/index.mjs +16 -66
- package/dist/kernel/capability-registry.d.ts +12 -42
- package/dist/kernel/index.d.ts +0 -1
- package/dist/{retired-settings-keys-LwFyTKun.js → retired-settings-keys-Ek9MPzCi.js} +1 -1
- package/dist/{retired-settings-keys-Cp3oG_aH.mjs → retired-settings-keys-rG_QVMT3.mjs} +1 -1
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-BWz_gZ5l.js");
|
|
7
7
|
const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
|
|
8
8
|
let node_crypto = require("node:crypto");
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Fn as EventCategory, P as addonPagesCapability, cn as BaseAddon, on as errMsg } from "../../dist-
|
|
1
|
+
import { Fn as EventCategory, P as addonPagesCapability, cn as BaseAddon, on as errMsg } from "../../dist-D1atncyi.mjs";
|
|
2
2
|
import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-BWz_gZ5l.js");
|
|
7
7
|
const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
|
|
8
8
|
let node_crypto = require("node:crypto");
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Fn as EventCategory, I as addonWidgetsCapability, cn as BaseAddon, on as errMsg } from "../../dist-
|
|
1
|
+
import { Fn as EventCategory, I as addonWidgetsCapability, cn as BaseAddon, on as errMsg } from "../../dist-D1atncyi.mjs";
|
|
2
2
|
import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-BWz_gZ5l.js");
|
|
7
7
|
//#region src/builtins/alerts/prune-policy.ts
|
|
8
8
|
/**
|
|
9
9
|
* Ids older than `cutoffMs`, oldest first.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Fn as EventCategory, L as alertsCapability, cn as BaseAddon, n as AlertSchema, on as errMsg, xn as createEvent } from "../../dist-
|
|
1
|
+
import { Fn as EventCategory, L as alertsCapability, cn as BaseAddon, n as AlertSchema, on as errMsg, xn as createEvent } from "../../dist-D1atncyi.mjs";
|
|
2
2
|
//#region src/builtins/alerts/prune-policy.ts
|
|
3
3
|
/**
|
|
4
4
|
* Ids older than `cutoffMs`, oldest first.
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-BWz_gZ5l.js");
|
|
7
7
|
//#region src/builtins/autotrack/autotrack-config.ts
|
|
8
8
|
var DEFAULT_AUTOTRACK_LOOP_CONFIG = {
|
|
9
9
|
deadZoneFraction: .5,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as bareAddonId, Dn as isEvent, Fn as EventCategory, Lt as ptzAutotrackCapability, cn as BaseAddon, h as FIRST_LEVEL_MACRO_CLASSES, on as errMsg } from "../../dist-
|
|
1
|
+
import { B as bareAddonId, Dn as isEvent, Fn as EventCategory, Lt as ptzAutotrackCapability, cn as BaseAddon, h as FIRST_LEVEL_MACRO_CLASSES, on as errMsg } from "../../dist-D1atncyi.mjs";
|
|
2
2
|
//#region src/builtins/autotrack/autotrack-config.ts
|
|
3
3
|
var DEFAULT_AUTOTRACK_LOOP_CONFIG = {
|
|
4
4
|
deadZoneFraction: .5,
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-BWz_gZ5l.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
let buffer = require("buffer");
|
|
9
9
|
let node_fs_promises = require("node:fs/promises");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Dt as mayWriteToLocation, Fn as EventCategory, Qt as storageOccupancyCapability, cn as BaseAddon, z as backupCapability } from "../../dist-
|
|
1
|
+
import { Dt as mayWriteToLocation, Fn as EventCategory, Qt as storageOccupancyCapability, cn as BaseAddon, z as backupCapability } from "../../dist-D1atncyi.mjs";
|
|
2
2
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
3
3
|
import { Buffer as Buffer$1 } from "buffer";
|
|
4
4
|
import * as fsp from "node:fs/promises";
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-BWz_gZ5l.js");
|
|
7
7
|
let zod = require("zod");
|
|
8
8
|
let _camstack_types_node = require("@camstack/types/node");
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { At as motionCapability, Fn as EventCategory, Tn as hydrateSchema, U as cameraGridLayoutCapability, Y as declarationOwnerNodeId, Yt as snapshotCapability, b as MOTION_CLOSE_AFTER_MS, cn as BaseAddon, en as streamCatalogCapability, f as DERIVED_CAMERA_SILENCED_CAP_NAMES, fn as DeviceFeature, i as BaseDevice, mn as DeviceType, on as errMsg, p as DeclaredDevices, sn as buildFfmpegArgs, xn as createEvent } from "../../dist-
|
|
1
|
+
import { At as motionCapability, Fn as EventCategory, Tn as hydrateSchema, U as cameraGridLayoutCapability, Y as declarationOwnerNodeId, Yt as snapshotCapability, b as MOTION_CLOSE_AFTER_MS, cn as BaseAddon, en as streamCatalogCapability, f as DERIVED_CAMERA_SILENCED_CAP_NAMES, fn as DeviceFeature, i as BaseDevice, mn as DeviceType, on as errMsg, p as DeclaredDevices, sn as buildFfmpegArgs, xn as createEvent } from "../../dist-D1atncyi.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { FfmpegProcess } from "@camstack/types/node";
|
|
4
4
|
import { join } from "node:path";
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-BWz_gZ5l.js");
|
|
7
7
|
const require_formatter = require("../../formatter-DqAKDlvN.js");
|
|
8
8
|
//#region src/builtins/console-logging/console-destination.ts
|
|
9
9
|
var LEVEL_RANK = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Ct as logDestinationCapability, cn as BaseAddon } from "../../dist-
|
|
1
|
+
import { Ct as logDestinationCapability, cn as BaseAddon } from "../../dist-D1atncyi.mjs";
|
|
2
2
|
import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
|
|
3
3
|
//#region src/builtins/console-logging/console-destination.ts
|
|
4
4
|
var LEVEL_RANK = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("../../dist-
|
|
3
|
+
const require_dist = require("../../dist-BWz_gZ5l.js");
|
|
4
4
|
let node_crypto = require("node:crypto");
|
|
5
5
|
let node_fs_promises = require("node:fs/promises");
|
|
6
6
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as coreBlockAddonId, K as coreBlockIdFromAddonId, c as CORE_BLOCKS_ADDON_ID, cn as BaseAddon, l as CORE_BLOCK_ADDON_PREFIX, on as errMsg, p as DeclaredDevices, q as coreBlocksCapability, u as CoreBlockSchema } from "../../dist-
|
|
1
|
+
import { G as coreBlockAddonId, K as coreBlockIdFromAddonId, c as CORE_BLOCKS_ADDON_ID, cn as BaseAddon, l as CORE_BLOCK_ADDON_PREFIX, on as errMsg, p as DeclaredDevices, q as coreBlocksCapability, u as CoreBlockSchema } from "../../dist-D1atncyi.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import * as fs from "node:fs/promises";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
@@ -161,6 +161,16 @@ export type LedgerNonEmpty = () => Promise<boolean>;
|
|
|
161
161
|
* changes nothing (D49: a read that fails must not destroy work).
|
|
162
162
|
*/
|
|
163
163
|
export declare function capAppliesToDeviceType(def: CapabilityDefinition | undefined, deviceType: string | undefined): boolean;
|
|
164
|
+
/**
|
|
165
|
+
* An addon's identity, with the node it happens to run on stripped.
|
|
166
|
+
*
|
|
167
|
+
* A capability registered on an agent arrives under `<addonId>@<nodeId>` —
|
|
168
|
+
* `pipeline-analytics@little-unraid`. That is the same ADDON as the hub-local
|
|
169
|
+
* `pipeline-analytics`, and treating the two as different providers is what
|
|
170
|
+
* put `analytics` in device 592's clip picker three times (D554 amended).
|
|
171
|
+
* Where a provider RUNS is a routing fact; it is not part of who it is.
|
|
172
|
+
*/
|
|
173
|
+
export declare function addonIdentityOf(addonId: string): string;
|
|
164
174
|
export declare function getBindings(deps: BindingsDeps, input: {
|
|
165
175
|
deviceId: number;
|
|
166
176
|
}): Promise<{
|
|
@@ -166,8 +166,6 @@ export declare class DeviceManagerAddon extends BaseAddon {
|
|
|
166
166
|
deviceId: number;
|
|
167
167
|
capName: string;
|
|
168
168
|
wrapperAddonId: string;
|
|
169
|
-
/** The source to toggle on a collection cap. Absent = all of the addon's. */
|
|
170
|
-
sourceId?: string;
|
|
171
169
|
active: boolean;
|
|
172
170
|
}): Promise<void>;
|
|
173
171
|
/** The narrow dependency bag the activation verb needs (D556). */
|
|
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
7
|
-
const require_retired_settings_keys = require("../../retired-settings-keys-
|
|
6
|
+
const require_dist = require("../../dist-BWz_gZ5l.js");
|
|
7
|
+
const require_retired_settings_keys = require("../../retired-settings-keys-Ek9MPzCi.js");
|
|
8
8
|
let node_crypto = require("node:crypto");
|
|
9
9
|
let _camstack_types_node = require("@camstack/types/node");
|
|
10
10
|
//#region src/builtins/device-manager/adoption-job-engine.ts
|
|
@@ -722,6 +722,52 @@ function capAppliesToDeviceType(def, deviceType) {
|
|
|
722
722
|
if (!declared || declared.length === 0) return true;
|
|
723
723
|
return declared.some((t) => t === deviceType);
|
|
724
724
|
}
|
|
725
|
+
/**
|
|
726
|
+
* An addon's identity, with the node it happens to run on stripped.
|
|
727
|
+
*
|
|
728
|
+
* A capability registered on an agent arrives under `<addonId>@<nodeId>` —
|
|
729
|
+
* `pipeline-analytics@little-unraid`. That is the same ADDON as the hub-local
|
|
730
|
+
* `pipeline-analytics`, and treating the two as different providers is what
|
|
731
|
+
* put `analytics` in device 592's clip picker three times (D554 amended).
|
|
732
|
+
* Where a provider RUNS is a routing fact; it is not part of who it is.
|
|
733
|
+
*/
|
|
734
|
+
function addonIdentityOf(addonId) {
|
|
735
|
+
const at = addonId.indexOf("@");
|
|
736
|
+
return at === -1 ? addonId : addonId.slice(0, at);
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Every provider addon of every COLLECTION capability that applies to this
|
|
740
|
+
* device, one entry each.
|
|
741
|
+
*
|
|
742
|
+
* Deduped by {@link addonIdentityOf}, so the hub-local registration, the
|
|
743
|
+
* agent's `<addon>@<node>` one and the device's native registration of the same
|
|
744
|
+
* addon are ONE provider — the defect this exists to make unrepresentable.
|
|
745
|
+
* Gated only by the cap's declared `deviceTypes` (D4), like step 2's auto-bind.
|
|
746
|
+
*/
|
|
747
|
+
function collectionBindings(deps, deviceId, deviceType) {
|
|
748
|
+
const registry = deps.capabilityRegistry;
|
|
749
|
+
if (!registry) return [];
|
|
750
|
+
const out = [];
|
|
751
|
+
for (const declared of registry.listCapabilities()) {
|
|
752
|
+
if (declared.mode !== "collection") continue;
|
|
753
|
+
if (!capAppliesToDeviceType(registry.getDefinition(declared.name), deviceType)) continue;
|
|
754
|
+
const nativeAddonId = registry.getNativeAddonId(declared.name, deviceId);
|
|
755
|
+
const seen = /* @__PURE__ */ new Set();
|
|
756
|
+
for (const addonId of [...declared.providers, ...nativeAddonId ? [nativeAddonId] : []]) {
|
|
757
|
+
const identity = addonIdentityOf(addonId);
|
|
758
|
+
if (identity.length === 0 || seen.has(identity)) continue;
|
|
759
|
+
seen.add(identity);
|
|
760
|
+
out.push({
|
|
761
|
+
capName: declared.name,
|
|
762
|
+
kind: "wrapped",
|
|
763
|
+
providerAddonId: identity,
|
|
764
|
+
providerNodeId: resolveWrapperNodeId(identity),
|
|
765
|
+
nativeAddonId: nativeAddonId === null ? "" : addonIdentityOf(nativeAddonId)
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
return out;
|
|
770
|
+
}
|
|
725
771
|
async function getBindings(deps, input) {
|
|
726
772
|
const [row, store] = await Promise.all([deps.rows.get(input.deviceId), readBindingsStore(deps)]);
|
|
727
773
|
return resolveBindingsForDevice(deps, input.deviceId, row, {
|
|
@@ -760,6 +806,11 @@ async function resolveBindingsForDevice(deps, deviceId, row, pass) {
|
|
|
760
806
|
const presence = await resolveDevicePresence(deps, row, deviceId, pass.ledgerNonEmpty);
|
|
761
807
|
const entries = [];
|
|
762
808
|
const seenCaps = /* @__PURE__ */ new Set();
|
|
809
|
+
const collectionEntries = collectionBindings(deps, deviceId, deviceType);
|
|
810
|
+
for (const entry of collectionEntries) {
|
|
811
|
+
entries.push(entry);
|
|
812
|
+
seenCaps.add(entry.capName);
|
|
813
|
+
}
|
|
763
814
|
const resolveRemote = (capName) => deps.remoteNativeCaps.get(deviceId)?.get(capName) ?? resolveRemoteNativeCapFromRegistry(deps, capName, deviceId);
|
|
764
815
|
for (const [capName, { wrapperAddonId }] of Object.entries(perDevice)) {
|
|
765
816
|
if (wrapperAddonId === void 0) continue;
|
|
@@ -3303,114 +3354,30 @@ async function getWireableFields(deps, input) {
|
|
|
3303
3354
|
}
|
|
3304
3355
|
//#endregion
|
|
3305
3356
|
//#region src/builtins/device-manager/device-source-activation.ts
|
|
3306
|
-
/**
|
|
3307
|
-
* Is `source` denied for a device, given the persisted deny set?
|
|
3308
|
-
*
|
|
3309
|
-
* The ONE place the migration rule lives: an entry matches either the source's
|
|
3310
|
-
* own id or the id of the addon that serves it. New writes are always source
|
|
3311
|
-
* ids; an addon id can only be a pre-re-key entry, and it still means "every
|
|
3312
|
-
* source this addon serves here".
|
|
3313
|
-
*/
|
|
3314
|
-
function isSourceDenied(denied, source) {
|
|
3315
|
-
if (denied.includes(source.addonId)) return true;
|
|
3316
|
-
return source.sourceId !== void 0 && denied.includes(source.sourceId);
|
|
3317
|
-
}
|
|
3318
|
-
/**
|
|
3319
|
-
* The deny list after one toggle. Pure, order-preserving, idempotent — a
|
|
3320
|
-
* second "off" on an addon already off changes nothing.
|
|
3321
|
-
*/
|
|
3322
|
-
function nextDisabledSources(current, key, active) {
|
|
3323
|
-
if (active) return current.filter((id) => id !== key);
|
|
3324
|
-
return current.includes(key) ? current : [...current, key];
|
|
3325
|
-
}
|
|
3326
3357
|
/** Is `capName` a COLLECTION cap — a cap whose device has several SOURCES? */
|
|
3327
3358
|
function isCollectionCap(registry, capName) {
|
|
3328
3359
|
return registry?.getDefinition(capName)?.mode === "collection";
|
|
3329
3360
|
}
|
|
3330
3361
|
/**
|
|
3331
|
-
* The persisted deny list for one `(device, cap)`, empty when never written.
|
|
3332
|
-
*
|
|
3333
|
-
* Reads the current field AND the pre-re-key one, unioned: a legacy addon id
|
|
3334
|
-
* is still an entry and still denies every source that addon serves here. The
|
|
3335
|
-
* union is what makes the migration a read rule rather than a data rewrite —
|
|
3336
|
-
* nothing has to walk a thousand cameras to keep an operator's decision.
|
|
3337
|
-
*/
|
|
3338
|
-
function disabledSourcesOf(record) {
|
|
3339
|
-
const current = record?.disabledSourceIds ?? [];
|
|
3340
|
-
const legacy = record?.disabledSourceAddonIds ?? [];
|
|
3341
|
-
const out = [...current];
|
|
3342
|
-
for (const id of legacy) if (!out.includes(id)) out.push(id);
|
|
3343
|
-
return out;
|
|
3344
|
-
}
|
|
3345
|
-
/**
|
|
3346
|
-
* Push ONE device's persisted source deactivations onto the resolution path.
|
|
3347
|
-
* The only writer of the registry's per-device source set.
|
|
3348
|
-
*/
|
|
3349
|
-
function mirrorDeviceSources(registry, deviceId, capName, disabledAddonIds) {
|
|
3350
|
-
registry?.setDeviceDisabledSources(String(deviceId), capName, disabledAddonIds);
|
|
3351
|
-
}
|
|
3352
|
-
/**
|
|
3353
|
-
* Replay the whole persisted store onto a fresh registry.
|
|
3354
|
-
*
|
|
3355
|
-
* The projection is in-memory, so a hub restart starts it empty — and an empty
|
|
3356
|
-
* deny list means "every source", which would silently switch every source the
|
|
3357
|
-
* operator turned off back ON. That is precisely the D62 failure (an off switch
|
|
3358
|
-
* that reports on), so the replay is not an optimisation: it is what makes the
|
|
3359
|
-
* authority durable. Called from the device-manager's `onInitialize`, before
|
|
3360
|
-
* any camera can be asked for its clips, and safe to call again.
|
|
3361
|
-
*/
|
|
3362
|
-
function restoreDeviceSourceActivations(registry, store, logger) {
|
|
3363
|
-
const deviceBindings = store.deviceBindings;
|
|
3364
|
-
if (deviceBindings === void 0) return 0;
|
|
3365
|
-
let restored = 0;
|
|
3366
|
-
for (const [deviceKey, perDevice] of Object.entries(deviceBindings)) {
|
|
3367
|
-
const deviceId = Number(deviceKey);
|
|
3368
|
-
for (const [capName, record] of Object.entries(perDevice)) {
|
|
3369
|
-
const disabled = disabledSourcesOf(record);
|
|
3370
|
-
if (disabled.length === 0) continue;
|
|
3371
|
-
registry.setDeviceDisabledSources(deviceKey, capName, disabled);
|
|
3372
|
-
restored += 1;
|
|
3373
|
-
logger.info("restored per-device source deactivations", {
|
|
3374
|
-
tags: { deviceId },
|
|
3375
|
-
meta: {
|
|
3376
|
-
capability: capName,
|
|
3377
|
-
disabledSourceIds: disabled
|
|
3378
|
-
}
|
|
3379
|
-
});
|
|
3380
|
-
}
|
|
3381
|
-
}
|
|
3382
|
-
return restored;
|
|
3383
|
-
}
|
|
3384
|
-
/**
|
|
3385
3362
|
* Activate or deactivate a wrapper for one device.
|
|
3386
3363
|
*
|
|
3387
|
-
*
|
|
3388
|
-
*
|
|
3389
|
-
* `
|
|
3390
|
-
*
|
|
3391
|
-
*
|
|
3392
|
-
*
|
|
3393
|
-
*
|
|
3364
|
+
* SINGLETON caps only, and that is now enforced rather than assumed: one
|
|
3365
|
+
* `wrapperAddonId`, or the explicit `null` "operator disabled" marker that
|
|
3366
|
+
* stops `getBindings` step 2 re-binding a `defaultActive` wrapper.
|
|
3367
|
+
*
|
|
3368
|
+
* A COLLECTION cap is REFUSED by name. Its providers are a derived SET
|
|
3369
|
+
* (`device-bindings-store.ts` step 0) — there is nothing to activate, and a
|
|
3370
|
+
* verb that accepted the call and wrote a store nobody reads is exactly what
|
|
3371
|
+
* this module shipped until 2026-09-20.
|
|
3394
3372
|
*/
|
|
3395
3373
|
async function setWrapperActive(deps, input) {
|
|
3396
3374
|
const storeKey = String(input.deviceId);
|
|
3397
|
-
|
|
3398
|
-
let mirrored = [];
|
|
3375
|
+
if (isCollectionCap(deps.capabilityRegistry, input.capName)) throw new Error(`setWrapperActive: "${input.capName}" is a COLLECTION capability — its providers are a derived set, not an operator choice, so there is nothing to activate. Every provider that serves this device is already one of its sources.`);
|
|
3399
3376
|
await deps.withAddonStoreWriteLock(async () => {
|
|
3400
3377
|
const store = await readBindingsStore(deps);
|
|
3401
3378
|
const perDevice = { ...store.deviceBindings[storeKey] };
|
|
3402
3379
|
const existing = perDevice[input.capName];
|
|
3403
|
-
if (
|
|
3404
|
-
const key = input.sourceId ?? input.wrapperAddonId;
|
|
3405
|
-
const disabled = nextDisabledSources(disabledSourcesOf(existing), key, input.active);
|
|
3406
|
-
mirrored = disabled;
|
|
3407
|
-
const wrapperAddonId = existing?.wrapperAddonId;
|
|
3408
|
-
perDevice[input.capName] = {
|
|
3409
|
-
...wrapperAddonId === void 0 ? {} : { wrapperAddonId },
|
|
3410
|
-
...disabled.length === 0 ? {} : { disabledSourceIds: disabled }
|
|
3411
|
-
};
|
|
3412
|
-
if (Object.keys(perDevice[input.capName] ?? {}).length === 0) delete perDevice[input.capName];
|
|
3413
|
-
} else if (input.active) perDevice[input.capName] = {
|
|
3380
|
+
if (input.active) perDevice[input.capName] = {
|
|
3414
3381
|
...existing,
|
|
3415
3382
|
wrapperAddonId: input.wrapperAddonId
|
|
3416
3383
|
};
|
|
@@ -3426,20 +3393,6 @@ async function setWrapperActive(deps, input) {
|
|
|
3426
3393
|
return rest;
|
|
3427
3394
|
})() });
|
|
3428
3395
|
});
|
|
3429
|
-
if (collection) {
|
|
3430
|
-
mirrorDeviceSources(deps.capabilityRegistry, input.deviceId, input.capName, mirrored);
|
|
3431
|
-
deps.ctx.logger.info(input.active ? "source activated for device" : "source deactivated for device", {
|
|
3432
|
-
tags: {
|
|
3433
|
-
deviceId: input.deviceId,
|
|
3434
|
-
addonId: input.wrapperAddonId
|
|
3435
|
-
},
|
|
3436
|
-
meta: {
|
|
3437
|
-
capability: input.capName,
|
|
3438
|
-
sourceId: input.sourceId ?? null,
|
|
3439
|
-
disabledSourceIds: [...mirrored]
|
|
3440
|
-
}
|
|
3441
|
-
});
|
|
3442
|
-
}
|
|
3443
3396
|
deps.ctx.eventBus.emit({
|
|
3444
3397
|
id: (0, node_crypto.randomUUID)(),
|
|
3445
3398
|
timestamp: /* @__PURE__ */ new Date(),
|
|
@@ -7458,11 +7411,6 @@ var DeviceManagerAddon = class extends require_dist.BaseAddon {
|
|
|
7458
7411
|
const deviceRows = new DeviceRowStore(deviceRowBackendOf(settingsStoreApi), this.ctx.logger.child("rows"));
|
|
7459
7412
|
await deviceRows.declare();
|
|
7460
7413
|
this.deviceRows = deviceRows;
|
|
7461
|
-
const capRegistryForRestore = this.capabilityRegistry;
|
|
7462
|
-
if (capRegistryForRestore) {
|
|
7463
|
-
const restored = restoreDeviceSourceActivations(capRegistryForRestore, await readBindingsStore({ ctx: this.ctx }), this.ctx.logger);
|
|
7464
|
-
if (restored > 0) this.ctx.logger.info("per-device source deactivations restored", { meta: { rows: restored } });
|
|
7465
|
-
}
|
|
7466
7414
|
try {
|
|
7467
7415
|
await require_retired_settings_keys.purgeRetiredSettingsRows(deviceRows.retiredRowStore(), this.ctx.logger.child("RetiredRows"));
|
|
7468
7416
|
} catch (err) {
|
|
@@ -7717,8 +7665,5 @@ var DeviceManagerAddon = class extends require_dist.BaseAddon {
|
|
|
7717
7665
|
//#endregion
|
|
7718
7666
|
exports.DeviceManagerAddon = DeviceManagerAddon;
|
|
7719
7667
|
exports.default = DeviceManagerAddon;
|
|
7720
|
-
exports.isSourceDenied = isSourceDenied;
|
|
7721
7668
|
exports.mergeAggregates = mergeAggregates;
|
|
7722
|
-
exports.nextDisabledSources = nextDisabledSources;
|
|
7723
|
-
exports.restoreDeviceSourceActivations = restoreDeviceSourceActivations;
|
|
7724
7669
|
exports.setWrapperActive = setWrapperActive;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $ as deviceStateCapability, Bt as resolveContainerPrimaryChild, D as STREAM_PROFILE_META, En as isDeviceConfigCap, Fn as EventCategory, H as buildStreamParamsConfigSchema, Jt as siteZoneKey, Pn as sleep$1, Pt as parseStreamParamsFormPatch, Q as deviceManagerCapability, St as locationIconKey, Ut as runtimeStatePolicyFor, _n as WELL_KNOWN_TAB_MAP, cn as BaseAddon, et as deviceStatusCapability, fn as DeviceFeature, it as enumerateSchemaFields, jt as normalizeUnit, m as DeviceStatusSchema, mn as DeviceType, o as CAMERA_SWITCH_ORDER, on as errMsg, pn as DeviceRole, rt as enumerateItemArrayFields, s as CAP_NAMES_WITH_STATUS, t as ALL_CAPABILITY_DEFINITIONS, v as LocationIconIdSchema } from "../../dist-
|
|
2
|
-
import { n as purgeRetiredSettingsRows } from "../../retired-settings-keys-
|
|
1
|
+
import { $ as deviceStateCapability, Bt as resolveContainerPrimaryChild, D as STREAM_PROFILE_META, En as isDeviceConfigCap, Fn as EventCategory, H as buildStreamParamsConfigSchema, Jt as siteZoneKey, Pn as sleep$1, Pt as parseStreamParamsFormPatch, Q as deviceManagerCapability, St as locationIconKey, Ut as runtimeStatePolicyFor, _n as WELL_KNOWN_TAB_MAP, cn as BaseAddon, et as deviceStatusCapability, fn as DeviceFeature, it as enumerateSchemaFields, jt as normalizeUnit, m as DeviceStatusSchema, mn as DeviceType, o as CAMERA_SWITCH_ORDER, on as errMsg, pn as DeviceRole, rt as enumerateItemArrayFields, s as CAP_NAMES_WITH_STATUS, t as ALL_CAPABILITY_DEFINITIONS, v as LocationIconIdSchema } from "../../dist-D1atncyi.mjs";
|
|
2
|
+
import { n as purgeRetiredSettingsRows } from "../../retired-settings-keys-rG_QVMT3.mjs";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import { canonicalDeviceFingerprint } from "@camstack/types/node";
|
|
5
5
|
//#region src/builtins/device-manager/adoption-job-engine.ts
|
|
@@ -717,6 +717,52 @@ function capAppliesToDeviceType(def, deviceType) {
|
|
|
717
717
|
if (!declared || declared.length === 0) return true;
|
|
718
718
|
return declared.some((t) => t === deviceType);
|
|
719
719
|
}
|
|
720
|
+
/**
|
|
721
|
+
* An addon's identity, with the node it happens to run on stripped.
|
|
722
|
+
*
|
|
723
|
+
* A capability registered on an agent arrives under `<addonId>@<nodeId>` —
|
|
724
|
+
* `pipeline-analytics@little-unraid`. That is the same ADDON as the hub-local
|
|
725
|
+
* `pipeline-analytics`, and treating the two as different providers is what
|
|
726
|
+
* put `analytics` in device 592's clip picker three times (D554 amended).
|
|
727
|
+
* Where a provider RUNS is a routing fact; it is not part of who it is.
|
|
728
|
+
*/
|
|
729
|
+
function addonIdentityOf(addonId) {
|
|
730
|
+
const at = addonId.indexOf("@");
|
|
731
|
+
return at === -1 ? addonId : addonId.slice(0, at);
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Every provider addon of every COLLECTION capability that applies to this
|
|
735
|
+
* device, one entry each.
|
|
736
|
+
*
|
|
737
|
+
* Deduped by {@link addonIdentityOf}, so the hub-local registration, the
|
|
738
|
+
* agent's `<addon>@<node>` one and the device's native registration of the same
|
|
739
|
+
* addon are ONE provider — the defect this exists to make unrepresentable.
|
|
740
|
+
* Gated only by the cap's declared `deviceTypes` (D4), like step 2's auto-bind.
|
|
741
|
+
*/
|
|
742
|
+
function collectionBindings(deps, deviceId, deviceType) {
|
|
743
|
+
const registry = deps.capabilityRegistry;
|
|
744
|
+
if (!registry) return [];
|
|
745
|
+
const out = [];
|
|
746
|
+
for (const declared of registry.listCapabilities()) {
|
|
747
|
+
if (declared.mode !== "collection") continue;
|
|
748
|
+
if (!capAppliesToDeviceType(registry.getDefinition(declared.name), deviceType)) continue;
|
|
749
|
+
const nativeAddonId = registry.getNativeAddonId(declared.name, deviceId);
|
|
750
|
+
const seen = /* @__PURE__ */ new Set();
|
|
751
|
+
for (const addonId of [...declared.providers, ...nativeAddonId ? [nativeAddonId] : []]) {
|
|
752
|
+
const identity = addonIdentityOf(addonId);
|
|
753
|
+
if (identity.length === 0 || seen.has(identity)) continue;
|
|
754
|
+
seen.add(identity);
|
|
755
|
+
out.push({
|
|
756
|
+
capName: declared.name,
|
|
757
|
+
kind: "wrapped",
|
|
758
|
+
providerAddonId: identity,
|
|
759
|
+
providerNodeId: resolveWrapperNodeId(identity),
|
|
760
|
+
nativeAddonId: nativeAddonId === null ? "" : addonIdentityOf(nativeAddonId)
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
return out;
|
|
765
|
+
}
|
|
720
766
|
async function getBindings(deps, input) {
|
|
721
767
|
const [row, store] = await Promise.all([deps.rows.get(input.deviceId), readBindingsStore(deps)]);
|
|
722
768
|
return resolveBindingsForDevice(deps, input.deviceId, row, {
|
|
@@ -755,6 +801,11 @@ async function resolveBindingsForDevice(deps, deviceId, row, pass) {
|
|
|
755
801
|
const presence = await resolveDevicePresence(deps, row, deviceId, pass.ledgerNonEmpty);
|
|
756
802
|
const entries = [];
|
|
757
803
|
const seenCaps = /* @__PURE__ */ new Set();
|
|
804
|
+
const collectionEntries = collectionBindings(deps, deviceId, deviceType);
|
|
805
|
+
for (const entry of collectionEntries) {
|
|
806
|
+
entries.push(entry);
|
|
807
|
+
seenCaps.add(entry.capName);
|
|
808
|
+
}
|
|
758
809
|
const resolveRemote = (capName) => deps.remoteNativeCaps.get(deviceId)?.get(capName) ?? resolveRemoteNativeCapFromRegistry(deps, capName, deviceId);
|
|
759
810
|
for (const [capName, { wrapperAddonId }] of Object.entries(perDevice)) {
|
|
760
811
|
if (wrapperAddonId === void 0) continue;
|
|
@@ -3298,114 +3349,30 @@ async function getWireableFields(deps, input) {
|
|
|
3298
3349
|
}
|
|
3299
3350
|
//#endregion
|
|
3300
3351
|
//#region src/builtins/device-manager/device-source-activation.ts
|
|
3301
|
-
/**
|
|
3302
|
-
* Is `source` denied for a device, given the persisted deny set?
|
|
3303
|
-
*
|
|
3304
|
-
* The ONE place the migration rule lives: an entry matches either the source's
|
|
3305
|
-
* own id or the id of the addon that serves it. New writes are always source
|
|
3306
|
-
* ids; an addon id can only be a pre-re-key entry, and it still means "every
|
|
3307
|
-
* source this addon serves here".
|
|
3308
|
-
*/
|
|
3309
|
-
function isSourceDenied(denied, source) {
|
|
3310
|
-
if (denied.includes(source.addonId)) return true;
|
|
3311
|
-
return source.sourceId !== void 0 && denied.includes(source.sourceId);
|
|
3312
|
-
}
|
|
3313
|
-
/**
|
|
3314
|
-
* The deny list after one toggle. Pure, order-preserving, idempotent — a
|
|
3315
|
-
* second "off" on an addon already off changes nothing.
|
|
3316
|
-
*/
|
|
3317
|
-
function nextDisabledSources(current, key, active) {
|
|
3318
|
-
if (active) return current.filter((id) => id !== key);
|
|
3319
|
-
return current.includes(key) ? current : [...current, key];
|
|
3320
|
-
}
|
|
3321
3352
|
/** Is `capName` a COLLECTION cap — a cap whose device has several SOURCES? */
|
|
3322
3353
|
function isCollectionCap(registry, capName) {
|
|
3323
3354
|
return registry?.getDefinition(capName)?.mode === "collection";
|
|
3324
3355
|
}
|
|
3325
3356
|
/**
|
|
3326
|
-
* The persisted deny list for one `(device, cap)`, empty when never written.
|
|
3327
|
-
*
|
|
3328
|
-
* Reads the current field AND the pre-re-key one, unioned: a legacy addon id
|
|
3329
|
-
* is still an entry and still denies every source that addon serves here. The
|
|
3330
|
-
* union is what makes the migration a read rule rather than a data rewrite —
|
|
3331
|
-
* nothing has to walk a thousand cameras to keep an operator's decision.
|
|
3332
|
-
*/
|
|
3333
|
-
function disabledSourcesOf(record) {
|
|
3334
|
-
const current = record?.disabledSourceIds ?? [];
|
|
3335
|
-
const legacy = record?.disabledSourceAddonIds ?? [];
|
|
3336
|
-
const out = [...current];
|
|
3337
|
-
for (const id of legacy) if (!out.includes(id)) out.push(id);
|
|
3338
|
-
return out;
|
|
3339
|
-
}
|
|
3340
|
-
/**
|
|
3341
|
-
* Push ONE device's persisted source deactivations onto the resolution path.
|
|
3342
|
-
* The only writer of the registry's per-device source set.
|
|
3343
|
-
*/
|
|
3344
|
-
function mirrorDeviceSources(registry, deviceId, capName, disabledAddonIds) {
|
|
3345
|
-
registry?.setDeviceDisabledSources(String(deviceId), capName, disabledAddonIds);
|
|
3346
|
-
}
|
|
3347
|
-
/**
|
|
3348
|
-
* Replay the whole persisted store onto a fresh registry.
|
|
3349
|
-
*
|
|
3350
|
-
* The projection is in-memory, so a hub restart starts it empty — and an empty
|
|
3351
|
-
* deny list means "every source", which would silently switch every source the
|
|
3352
|
-
* operator turned off back ON. That is precisely the D62 failure (an off switch
|
|
3353
|
-
* that reports on), so the replay is not an optimisation: it is what makes the
|
|
3354
|
-
* authority durable. Called from the device-manager's `onInitialize`, before
|
|
3355
|
-
* any camera can be asked for its clips, and safe to call again.
|
|
3356
|
-
*/
|
|
3357
|
-
function restoreDeviceSourceActivations(registry, store, logger) {
|
|
3358
|
-
const deviceBindings = store.deviceBindings;
|
|
3359
|
-
if (deviceBindings === void 0) return 0;
|
|
3360
|
-
let restored = 0;
|
|
3361
|
-
for (const [deviceKey, perDevice] of Object.entries(deviceBindings)) {
|
|
3362
|
-
const deviceId = Number(deviceKey);
|
|
3363
|
-
for (const [capName, record] of Object.entries(perDevice)) {
|
|
3364
|
-
const disabled = disabledSourcesOf(record);
|
|
3365
|
-
if (disabled.length === 0) continue;
|
|
3366
|
-
registry.setDeviceDisabledSources(deviceKey, capName, disabled);
|
|
3367
|
-
restored += 1;
|
|
3368
|
-
logger.info("restored per-device source deactivations", {
|
|
3369
|
-
tags: { deviceId },
|
|
3370
|
-
meta: {
|
|
3371
|
-
capability: capName,
|
|
3372
|
-
disabledSourceIds: disabled
|
|
3373
|
-
}
|
|
3374
|
-
});
|
|
3375
|
-
}
|
|
3376
|
-
}
|
|
3377
|
-
return restored;
|
|
3378
|
-
}
|
|
3379
|
-
/**
|
|
3380
3357
|
* Activate or deactivate a wrapper for one device.
|
|
3381
3358
|
*
|
|
3382
|
-
*
|
|
3383
|
-
*
|
|
3384
|
-
* `
|
|
3385
|
-
*
|
|
3386
|
-
*
|
|
3387
|
-
*
|
|
3388
|
-
*
|
|
3359
|
+
* SINGLETON caps only, and that is now enforced rather than assumed: one
|
|
3360
|
+
* `wrapperAddonId`, or the explicit `null` "operator disabled" marker that
|
|
3361
|
+
* stops `getBindings` step 2 re-binding a `defaultActive` wrapper.
|
|
3362
|
+
*
|
|
3363
|
+
* A COLLECTION cap is REFUSED by name. Its providers are a derived SET
|
|
3364
|
+
* (`device-bindings-store.ts` step 0) — there is nothing to activate, and a
|
|
3365
|
+
* verb that accepted the call and wrote a store nobody reads is exactly what
|
|
3366
|
+
* this module shipped until 2026-09-20.
|
|
3389
3367
|
*/
|
|
3390
3368
|
async function setWrapperActive(deps, input) {
|
|
3391
3369
|
const storeKey = String(input.deviceId);
|
|
3392
|
-
|
|
3393
|
-
let mirrored = [];
|
|
3370
|
+
if (isCollectionCap(deps.capabilityRegistry, input.capName)) throw new Error(`setWrapperActive: "${input.capName}" is a COLLECTION capability — its providers are a derived set, not an operator choice, so there is nothing to activate. Every provider that serves this device is already one of its sources.`);
|
|
3394
3371
|
await deps.withAddonStoreWriteLock(async () => {
|
|
3395
3372
|
const store = await readBindingsStore(deps);
|
|
3396
3373
|
const perDevice = { ...store.deviceBindings[storeKey] };
|
|
3397
3374
|
const existing = perDevice[input.capName];
|
|
3398
|
-
if (
|
|
3399
|
-
const key = input.sourceId ?? input.wrapperAddonId;
|
|
3400
|
-
const disabled = nextDisabledSources(disabledSourcesOf(existing), key, input.active);
|
|
3401
|
-
mirrored = disabled;
|
|
3402
|
-
const wrapperAddonId = existing?.wrapperAddonId;
|
|
3403
|
-
perDevice[input.capName] = {
|
|
3404
|
-
...wrapperAddonId === void 0 ? {} : { wrapperAddonId },
|
|
3405
|
-
...disabled.length === 0 ? {} : { disabledSourceIds: disabled }
|
|
3406
|
-
};
|
|
3407
|
-
if (Object.keys(perDevice[input.capName] ?? {}).length === 0) delete perDevice[input.capName];
|
|
3408
|
-
} else if (input.active) perDevice[input.capName] = {
|
|
3375
|
+
if (input.active) perDevice[input.capName] = {
|
|
3409
3376
|
...existing,
|
|
3410
3377
|
wrapperAddonId: input.wrapperAddonId
|
|
3411
3378
|
};
|
|
@@ -3421,20 +3388,6 @@ async function setWrapperActive(deps, input) {
|
|
|
3421
3388
|
return rest;
|
|
3422
3389
|
})() });
|
|
3423
3390
|
});
|
|
3424
|
-
if (collection) {
|
|
3425
|
-
mirrorDeviceSources(deps.capabilityRegistry, input.deviceId, input.capName, mirrored);
|
|
3426
|
-
deps.ctx.logger.info(input.active ? "source activated for device" : "source deactivated for device", {
|
|
3427
|
-
tags: {
|
|
3428
|
-
deviceId: input.deviceId,
|
|
3429
|
-
addonId: input.wrapperAddonId
|
|
3430
|
-
},
|
|
3431
|
-
meta: {
|
|
3432
|
-
capability: input.capName,
|
|
3433
|
-
sourceId: input.sourceId ?? null,
|
|
3434
|
-
disabledSourceIds: [...mirrored]
|
|
3435
|
-
}
|
|
3436
|
-
});
|
|
3437
|
-
}
|
|
3438
3391
|
deps.ctx.eventBus.emit({
|
|
3439
3392
|
id: randomUUID(),
|
|
3440
3393
|
timestamp: /* @__PURE__ */ new Date(),
|
|
@@ -7453,11 +7406,6 @@ var DeviceManagerAddon = class extends BaseAddon {
|
|
|
7453
7406
|
const deviceRows = new DeviceRowStore(deviceRowBackendOf(settingsStoreApi), this.ctx.logger.child("rows"));
|
|
7454
7407
|
await deviceRows.declare();
|
|
7455
7408
|
this.deviceRows = deviceRows;
|
|
7456
|
-
const capRegistryForRestore = this.capabilityRegistry;
|
|
7457
|
-
if (capRegistryForRestore) {
|
|
7458
|
-
const restored = restoreDeviceSourceActivations(capRegistryForRestore, await readBindingsStore({ ctx: this.ctx }), this.ctx.logger);
|
|
7459
|
-
if (restored > 0) this.ctx.logger.info("per-device source deactivations restored", { meta: { rows: restored } });
|
|
7460
|
-
}
|
|
7461
7409
|
try {
|
|
7462
7410
|
await purgeRetiredSettingsRows(deviceRows.retiredRowStore(), this.ctx.logger.child("RetiredRows"));
|
|
7463
7411
|
} catch (err) {
|
|
@@ -7710,4 +7658,4 @@ var DeviceManagerAddon = class extends BaseAddon {
|
|
|
7710
7658
|
}
|
|
7711
7659
|
};
|
|
7712
7660
|
//#endregion
|
|
7713
|
-
export { DeviceManagerAddon, DeviceManagerAddon as default,
|
|
7661
|
+
export { DeviceManagerAddon, DeviceManagerAddon as default, mergeAggregates, setWrapperActive as t };
|