@camstack/system 1.2.134 → 1.2.136
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/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.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-manager.addon.js +117 -9
- package/dist/builtins/device-manager/device-manager.addon.mjs +117 -9
- package/dist/builtins/device-manager/device-row-store.d.ts +50 -0
- 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-backend.d.ts +39 -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-BUEU7B1V.mjs → dist-Bh25kEUH.mjs} +62 -32
- package/dist/{dist-DqcaE-k1.js → dist-D-R0SuP-.js} +62 -32
- package/dist/index.js +18 -1
- package/dist/index.mjs +18 -1
- package/dist/kernel/config-manager.d.ts +4 -0
- package/dist/{retired-settings-keys-BhPleRL7.mjs → retired-settings-keys-BZbOXqch.mjs} +1 -1
- package/dist/{retired-settings-keys-KZnmtfsh.js → retired-settings-keys-CqD6rSQx.js} +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-D-R0SuP-.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 { Gt as EventCategory, v as addonPagesCapability, vt as errMsg, yt as BaseAddon } from "../../dist-
|
|
1
|
+
import { Gt as EventCategory, v as addonPagesCapability, vt as errMsg, yt as BaseAddon } from "../../dist-Bh25kEUH.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-D-R0SuP-.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 { Gt as EventCategory, b as addonWidgetsCapability, vt as errMsg, yt as BaseAddon } from "../../dist-
|
|
1
|
+
import { Gt as EventCategory, b as addonWidgetsCapability, vt as errMsg, yt as BaseAddon } from "../../dist-Bh25kEUH.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-D-R0SuP-.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 { Gt as EventCategory, Mt as createEvent, n as AlertSchema, vt as errMsg, x as alertsCapability, yt as BaseAddon } from "../../dist-
|
|
1
|
+
import { Gt as EventCategory, Mt as createEvent, n as AlertSchema, vt as errMsg, x as alertsCapability, yt as BaseAddon } from "../../dist-Bh25kEUH.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
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-D-R0SuP-.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 { C as backupCapability, Gt as EventCategory, yt as BaseAddon } from "../../dist-
|
|
1
|
+
import { C as backupCapability, Gt as EventCategory, yt as BaseAddon } from "../../dist-Bh25kEUH.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-D-R0SuP-.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 { X as logDestinationCapability, yt as BaseAddon } from "../../dist-
|
|
1
|
+
import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-Bh25kEUH.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-D-R0SuP-.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 { D as coreBlockAddonId, O as coreBlockIdFromAddonId, c as CoreBlockSchema, k as coreBlocksCapability, l as DeclaredDevices, o as CORE_BLOCKS_ADDON_ID, s as CORE_BLOCK_ADDON_PREFIX, vt as errMsg, yt as BaseAddon } from "../../dist-
|
|
1
|
+
import { D as coreBlockAddonId, O as coreBlockIdFromAddonId, c as CoreBlockSchema, k as coreBlocksCapability, l as DeclaredDevices, o as CORE_BLOCKS_ADDON_ID, s as CORE_BLOCK_ADDON_PREFIX, vt as errMsg, yt as BaseAddon } from "../../dist-Bh25kEUH.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";
|
|
@@ -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-D-R0SuP-.js");
|
|
7
|
+
const require_retired_settings_keys = require("../../retired-settings-keys-CqD6rSQx.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
|
|
@@ -1280,6 +1280,32 @@ async function listPersistedByAddon(pctx, input) {
|
|
|
1280
1280
|
parentDeviceId: m.parentDeviceId
|
|
1281
1281
|
}));
|
|
1282
1282
|
}
|
|
1283
|
+
/**
|
|
1284
|
+
* Every requested device's persisted config, in as few store round trips as the
|
|
1285
|
+
* settings view allows.
|
|
1286
|
+
*
|
|
1287
|
+
* One call when the view can batch (the in-process door, which keys
|
|
1288
|
+
* `addon-device-settings` by `<addonId>:<deviceId>.` and answers a whole addon
|
|
1289
|
+
* with one indexed range scan). Otherwise the per-device form, unchanged — a
|
|
1290
|
+
* fallback and not a silent downgrade: `readDeviceStoreBatch` is optional
|
|
1291
|
+
* precisely because a forked addon's view has nothing to batch, and refusing
|
|
1292
|
+
* would break the only implementation that cannot comply.
|
|
1293
|
+
*
|
|
1294
|
+
* A read that THROWS yields `{}` for that device rather than failing the whole
|
|
1295
|
+
* listing: one unreadable settings row must not make the fleet unlistable.
|
|
1296
|
+
*/
|
|
1297
|
+
async function readDeviceConfigs(pctx, deviceIds) {
|
|
1298
|
+
if (deviceIds.length === 0) return /* @__PURE__ */ new Map();
|
|
1299
|
+
const batch = pctx.settings.readDeviceStoreBatch;
|
|
1300
|
+
if (batch !== void 0) return batch.call(pctx.settings, deviceIds);
|
|
1301
|
+
const out = /* @__PURE__ */ new Map();
|
|
1302
|
+
for (const id of deviceIds) try {
|
|
1303
|
+
out.set(id, await pctx.settings.readDeviceStore(id));
|
|
1304
|
+
} catch {
|
|
1305
|
+
out.set(id, {});
|
|
1306
|
+
}
|
|
1307
|
+
return out;
|
|
1308
|
+
}
|
|
1283
1309
|
async function listAll(pctx, input) {
|
|
1284
1310
|
const ownerFilter = Reflect.get(input, "addonId");
|
|
1285
1311
|
if (ownerFilter !== void 0 && (typeof ownerFilter !== "string" || ownerFilter.length === 0)) throw new Error(`deviceManager.listAll: addonId must be a non-empty string or be omitted — got ${JSON.stringify(ownerFilter)}. An owner filter that is present but empty is never widened to every device. On an addon context the id is \`ctx.id\`; there is no \`ctx.addonId\`.`);
|
|
@@ -1289,7 +1315,10 @@ async function listAll(pctx, input) {
|
|
|
1289
1315
|
const idFilter = input.deviceIds === void 0 ? null : new Set(input.deviceIds);
|
|
1290
1316
|
const results = [];
|
|
1291
1317
|
const seen = /* @__PURE__ */ new Set();
|
|
1292
|
-
const fleet = addonId ? await pctx.metaStore.rows.listByAddon(addonId) : await pctx.metaStore.rows.
|
|
1318
|
+
const fleet = addonId ? await pctx.metaStore.rows.listByAddon(addonId) : await pctx.metaStore.rows.listFleet({
|
|
1319
|
+
...input.deviceIds !== void 0 ? { deviceIds: input.deviceIds } : {},
|
|
1320
|
+
slim
|
|
1321
|
+
});
|
|
1293
1322
|
const rowById = /* @__PURE__ */ new Map();
|
|
1294
1323
|
for (const row of fleet) rowById.set(row.meta.id, row);
|
|
1295
1324
|
if (pctx.registry) {
|
|
@@ -1311,6 +1340,7 @@ async function listAll(pctx, input) {
|
|
|
1311
1340
|
} : info);
|
|
1312
1341
|
}
|
|
1313
1342
|
}
|
|
1343
|
+
const configs = await readDeviceConfigs(pctx, slim ? [] : fleet.filter((row) => !seen.has(String(row.meta.id))).filter((row) => idFilter === null || idFilter.has(row.meta.id)).filter((row) => !camerasOnly || row.meta.type === require_dist.DeviceType.Camera).map((row) => row.meta.id));
|
|
1314
1344
|
for (const row of fleet) {
|
|
1315
1345
|
const m = row.meta;
|
|
1316
1346
|
const aid = m.addonId;
|
|
@@ -1319,7 +1349,7 @@ async function listAll(pctx, input) {
|
|
|
1319
1349
|
if (idFilter !== null && !idFilter.has(m.id)) continue;
|
|
1320
1350
|
const persistedType = m.type;
|
|
1321
1351
|
if (camerasOnly && persistedType !== require_dist.DeviceType.Camera) continue;
|
|
1322
|
-
const persistedConfig =
|
|
1352
|
+
const persistedConfig = configs.get(m.id) ?? {};
|
|
1323
1353
|
const metadata = slim ? null : row.metadata;
|
|
1324
1354
|
results.push({
|
|
1325
1355
|
id: m.id,
|
|
@@ -1848,6 +1878,26 @@ function resolveTrackedEventDeviceIds(config, linkedIds) {
|
|
|
1848
1878
|
return linkedIds.filter((id) => picked.has(id));
|
|
1849
1879
|
}
|
|
1850
1880
|
/**
|
|
1881
|
+
* The fleet listing every function here needs, and the ONLY projection any of
|
|
1882
|
+
* them may ask for.
|
|
1883
|
+
*
|
|
1884
|
+
* Linked-device policy reads five fields off a candidate — `id`,
|
|
1885
|
+
* `parentDeviceId`, `location`, `name`, `features` — and `slim` carries all
|
|
1886
|
+
* five. What `slim` drops is `config`, and `config` is not a column: `listAll`
|
|
1887
|
+
* materialises it with ONE `readDeviceStore` per device, sequentially, on
|
|
1888
|
+
* device-manager's event loop. This module asked for the full projection three
|
|
1889
|
+
* times, so every linked-devices read swept the whole fleet's settings rows to
|
|
1890
|
+
* use none of them.
|
|
1891
|
+
*
|
|
1892
|
+
* Measured on the live hub 2026-08-25: `query addon-device-settings` ran
|
|
1893
|
+
* 36 814 times a minute against a 967-device fleet — ~38 full-fleet sweeps a
|
|
1894
|
+
* minute, ~31 of them the `pipeline-analytics` reverse index rebuilding itself
|
|
1895
|
+
* one camera at a time through `getLinkedDevices`. The per-camera `config`
|
|
1896
|
+
* this query DOES need is the separate `readDeviceStore(deviceId)` below, and
|
|
1897
|
+
* it is one row, not the fleet.
|
|
1898
|
+
*/
|
|
1899
|
+
var LINK_CANDIDATE_PROJECTION = { projection: "slim" };
|
|
1900
|
+
/**
|
|
1851
1901
|
* Resolve ONE camera's linked set against an ALREADY-FETCHED fleet.
|
|
1852
1902
|
*
|
|
1853
1903
|
* The fleet is a parameter, not a fetch, because it is the entire cost of this
|
|
@@ -1884,7 +1934,7 @@ function resolveFor(deviceId, all, byId, blob) {
|
|
|
1884
1934
|
/** Cap implementation of `getLinkedDevices`. */
|
|
1885
1935
|
async function getLinkedDevices(pctx, input) {
|
|
1886
1936
|
const { deviceId } = input;
|
|
1887
|
-
const [all, blob] = await Promise.all([listAll(pctx,
|
|
1937
|
+
const [all, blob] = await Promise.all([listAll(pctx, LINK_CANDIDATE_PROJECTION), pctx.settings.readDeviceStore(deviceId)]);
|
|
1888
1938
|
return resolveFor(deviceId, all, new Map(all.map((d) => [d.id, d])), blob);
|
|
1889
1939
|
}
|
|
1890
1940
|
/**
|
|
@@ -1903,7 +1953,7 @@ async function getLinkedDevices(pctx, input) {
|
|
|
1903
1953
|
async function getLinkedDevicesBatch(pctx, input) {
|
|
1904
1954
|
const deviceIds = [...new Set(input.deviceIds)];
|
|
1905
1955
|
if (deviceIds.length === 0) return [];
|
|
1906
|
-
const [all, blobs] = await Promise.all([listAll(pctx,
|
|
1956
|
+
const [all, blobs] = await Promise.all([listAll(pctx, LINK_CANDIDATE_PROJECTION), Promise.all(deviceIds.map((id) => pctx.settings.readDeviceStore(id).catch((err) => {
|
|
1907
1957
|
pctx.host.ctx.logger.warn("getLinkedDevicesBatch: settings read failed — children only", {
|
|
1908
1958
|
tags: { deviceId: id },
|
|
1909
1959
|
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
@@ -1925,7 +1975,7 @@ async function getLinkedDevicesBatch(pctx, input) {
|
|
|
1925
1975
|
async function buildLinkedDevicesContribution(pctx, deviceId) {
|
|
1926
1976
|
const persisted = await pctx.metaStore.resolvePersistedById(deviceId);
|
|
1927
1977
|
if (!persisted || persisted.meta.type !== require_dist.DeviceType.Camera) return null;
|
|
1928
|
-
const [all, blob] = await Promise.all([listAll(pctx,
|
|
1978
|
+
const [all, blob] = await Promise.all([listAll(pctx, LINK_CANDIDATE_PROJECTION), pctx.settings.readDeviceStore(deviceId)]);
|
|
1929
1979
|
const config = parseLinkedDevicesConfig(blob);
|
|
1930
1980
|
const options = all.filter((d) => d.id !== deviceId).map((d) => ({
|
|
1931
1981
|
value: String(d.id),
|
|
@@ -4004,6 +4054,36 @@ var DEVICE_ROWS_COLUMNS = [
|
|
|
4004
4054
|
type: "JSON"
|
|
4005
4055
|
}
|
|
4006
4056
|
];
|
|
4057
|
+
/**
|
|
4058
|
+
* The columns a SLIM fleet read selects: every declared column except the
|
|
4059
|
+
* primary key (always returned) and `metadata`.
|
|
4060
|
+
*
|
|
4061
|
+
* ## Why this is a DENYLIST and must stay one
|
|
4062
|
+
*
|
|
4063
|
+
* `decodeDeviceRow` returns `null` when `deviceId`, `addonId`, `stableId`,
|
|
4064
|
+
* `type` or `name` is missing, and `list()` then SKIPS the row with a warn. A
|
|
4065
|
+
* hand-written allowlist that forgot one of the five would not make the fleet
|
|
4066
|
+
* slower — it would make devices vanish from every listing, quietly, and the
|
|
4067
|
+
* only trace would be a log line nobody is reading at the time. Deriving the
|
|
4068
|
+
* list by subtraction means a column added tomorrow is carried by default and
|
|
4069
|
+
* the only way to lose one is to name it here.
|
|
4070
|
+
*
|
|
4071
|
+
* `metadata` is the one slim provably discards: `device-queries.ts#listAll`
|
|
4072
|
+
* sets `metadata: null` on every slim row. It is also the largest JSON column
|
|
4073
|
+
* on the row, which is why this is worth doing at all.
|
|
4074
|
+
*
|
|
4075
|
+
* ## What is NOT here, and will not be
|
|
4076
|
+
*
|
|
4077
|
+
* There is no `where: { type: 'camera' }` companion to this. `isCameraDevice`
|
|
4078
|
+
* is a method-presence check (`getStreamSources`), not the persisted `type`, so
|
|
4079
|
+
* a doorbell with a camera answers YES while its row says `doorbell`. Filtering
|
|
4080
|
+
* the rows by type would strip exactly those devices of their row — and
|
|
4081
|
+
* `toDeviceInfo` reads `name` / `location` / `disabled` from the ROW precisely
|
|
4082
|
+
* because the live device's copies are stale by construction. The fleet would
|
|
4083
|
+
* keep working and start reporting pre-rename names on doorbells. The
|
|
4084
|
+
* `isCamera` filter stays in JS.
|
|
4085
|
+
*/
|
|
4086
|
+
var DEVICE_ROWS_SLIM_COLUMNS = DEVICE_ROWS_COLUMNS.map((c) => c.name).filter((name) => name !== "id" && name !== "metadata");
|
|
4007
4087
|
var DEVICE_ROWS_INDEXES = [
|
|
4008
4088
|
{
|
|
4009
4089
|
name: "idx_dm_devices_addon_stable",
|
|
@@ -4222,6 +4302,33 @@ var DeviceRowStore = class {
|
|
|
4222
4302
|
});
|
|
4223
4303
|
}
|
|
4224
4304
|
/**
|
|
4305
|
+
* The fleet, read as narrowly as the question allows.
|
|
4306
|
+
*
|
|
4307
|
+
* `listAll` is a full-table `SELECT … ORDER BY "deviceId"` — ~1 017 rows a
|
|
4308
|
+
* call on the live hub, 14–54 calls a minute — and its callers then filtered
|
|
4309
|
+
* the result in JS. The two filters that CAN be pushed down are here:
|
|
4310
|
+
*
|
|
4311
|
+
* - `deviceIds` becomes a `whereIn`. The viewer's linked-devices panel asks
|
|
4312
|
+
* about ~8 named ids; it was answered by reading the whole ledger. An
|
|
4313
|
+
* EMPTY set reads nothing at all rather than degrading to "everything" —
|
|
4314
|
+
* a request for no devices is a request, not an omission.
|
|
4315
|
+
* - `slim` becomes a column projection, {@link DEVICE_ROWS_SLIM_COLUMNS}.
|
|
4316
|
+
*
|
|
4317
|
+
* `isCamera` is deliberately NOT one of them — see that constant's note and
|
|
4318
|
+
* `device-row-store-filtered.spec.ts`.
|
|
4319
|
+
*/
|
|
4320
|
+
async listFleet(opts) {
|
|
4321
|
+
if (opts.deviceIds !== void 0 && opts.deviceIds.length === 0) return [];
|
|
4322
|
+
return this.list({
|
|
4323
|
+
...opts.deviceIds !== void 0 ? { whereIn: { deviceId: [...new Set(opts.deviceIds)] } } : {},
|
|
4324
|
+
orderBy: {
|
|
4325
|
+
field: "deviceId",
|
|
4326
|
+
direction: "asc"
|
|
4327
|
+
},
|
|
4328
|
+
limit: DEVICE_ROWS_FLEET_LIMIT
|
|
4329
|
+
}, opts.slim === true ? DEVICE_ROWS_SLIM_COLUMNS : void 0);
|
|
4330
|
+
}
|
|
4331
|
+
/**
|
|
4225
4332
|
* The device an addon knows as `stableId`, or `null`.
|
|
4226
4333
|
*
|
|
4227
4334
|
* `(addonId, stableId)` is the addon-facing identity — unique by
|
|
@@ -4292,11 +4399,12 @@ var DeviceRowStore = class {
|
|
|
4292
4399
|
await this.declare();
|
|
4293
4400
|
return this.backend.count({ collection: DEVICE_ROWS_COLLECTION });
|
|
4294
4401
|
}
|
|
4295
|
-
async list(filter) {
|
|
4402
|
+
async list(filter, columns) {
|
|
4296
4403
|
await this.declare();
|
|
4297
4404
|
const records = await this.backend.query({
|
|
4298
4405
|
collection: DEVICE_ROWS_COLLECTION,
|
|
4299
|
-
filter
|
|
4406
|
+
filter,
|
|
4407
|
+
...columns === void 0 ? {} : { columns }
|
|
4300
4408
|
});
|
|
4301
4409
|
const out = [];
|
|
4302
4410
|
for (const record of records) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Ct as DeviceFeature, E as buildStreamParamsConfigSchema, F as deviceStatusCapability, Gt as EventCategory, Lt as isDeviceConfigCap, N as deviceManagerCapability, Ot as WELL_KNOWN_TAB_MAP, P as deviceStateCapability, R as enumerateItemArrayFields, Tt as DeviceType, Wt as sleep, a as CAP_NAMES_WITH_STATUS, at as runtimeStatePolicyFor, et as normalizeUnit, nt as parseStreamParamsFormPatch, p as STREAM_PROFILE_META, t as ALL_CAPABILITY_DEFINITIONS, u as DeviceStatusSchema, vt as errMsg, wt as DeviceRole, yt as BaseAddon, z as enumerateSchemaFields } from "../../dist-
|
|
2
|
-
import { n as purgeRetiredSettingsRows } from "../../retired-settings-keys-
|
|
1
|
+
import { Ct as DeviceFeature, E as buildStreamParamsConfigSchema, F as deviceStatusCapability, Gt as EventCategory, Lt as isDeviceConfigCap, N as deviceManagerCapability, Ot as WELL_KNOWN_TAB_MAP, P as deviceStateCapability, R as enumerateItemArrayFields, Tt as DeviceType, Wt as sleep, a as CAP_NAMES_WITH_STATUS, at as runtimeStatePolicyFor, et as normalizeUnit, nt as parseStreamParamsFormPatch, p as STREAM_PROFILE_META, t as ALL_CAPABILITY_DEFINITIONS, u as DeviceStatusSchema, vt as errMsg, wt as DeviceRole, yt as BaseAddon, z as enumerateSchemaFields } from "../../dist-Bh25kEUH.mjs";
|
|
2
|
+
import { n as purgeRetiredSettingsRows } from "../../retired-settings-keys-BZbOXqch.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
|
|
@@ -1275,6 +1275,32 @@ async function listPersistedByAddon(pctx, input) {
|
|
|
1275
1275
|
parentDeviceId: m.parentDeviceId
|
|
1276
1276
|
}));
|
|
1277
1277
|
}
|
|
1278
|
+
/**
|
|
1279
|
+
* Every requested device's persisted config, in as few store round trips as the
|
|
1280
|
+
* settings view allows.
|
|
1281
|
+
*
|
|
1282
|
+
* One call when the view can batch (the in-process door, which keys
|
|
1283
|
+
* `addon-device-settings` by `<addonId>:<deviceId>.` and answers a whole addon
|
|
1284
|
+
* with one indexed range scan). Otherwise the per-device form, unchanged — a
|
|
1285
|
+
* fallback and not a silent downgrade: `readDeviceStoreBatch` is optional
|
|
1286
|
+
* precisely because a forked addon's view has nothing to batch, and refusing
|
|
1287
|
+
* would break the only implementation that cannot comply.
|
|
1288
|
+
*
|
|
1289
|
+
* A read that THROWS yields `{}` for that device rather than failing the whole
|
|
1290
|
+
* listing: one unreadable settings row must not make the fleet unlistable.
|
|
1291
|
+
*/
|
|
1292
|
+
async function readDeviceConfigs(pctx, deviceIds) {
|
|
1293
|
+
if (deviceIds.length === 0) return /* @__PURE__ */ new Map();
|
|
1294
|
+
const batch = pctx.settings.readDeviceStoreBatch;
|
|
1295
|
+
if (batch !== void 0) return batch.call(pctx.settings, deviceIds);
|
|
1296
|
+
const out = /* @__PURE__ */ new Map();
|
|
1297
|
+
for (const id of deviceIds) try {
|
|
1298
|
+
out.set(id, await pctx.settings.readDeviceStore(id));
|
|
1299
|
+
} catch {
|
|
1300
|
+
out.set(id, {});
|
|
1301
|
+
}
|
|
1302
|
+
return out;
|
|
1303
|
+
}
|
|
1278
1304
|
async function listAll(pctx, input) {
|
|
1279
1305
|
const ownerFilter = Reflect.get(input, "addonId");
|
|
1280
1306
|
if (ownerFilter !== void 0 && (typeof ownerFilter !== "string" || ownerFilter.length === 0)) throw new Error(`deviceManager.listAll: addonId must be a non-empty string or be omitted — got ${JSON.stringify(ownerFilter)}. An owner filter that is present but empty is never widened to every device. On an addon context the id is \`ctx.id\`; there is no \`ctx.addonId\`.`);
|
|
@@ -1284,7 +1310,10 @@ async function listAll(pctx, input) {
|
|
|
1284
1310
|
const idFilter = input.deviceIds === void 0 ? null : new Set(input.deviceIds);
|
|
1285
1311
|
const results = [];
|
|
1286
1312
|
const seen = /* @__PURE__ */ new Set();
|
|
1287
|
-
const fleet = addonId ? await pctx.metaStore.rows.listByAddon(addonId) : await pctx.metaStore.rows.
|
|
1313
|
+
const fleet = addonId ? await pctx.metaStore.rows.listByAddon(addonId) : await pctx.metaStore.rows.listFleet({
|
|
1314
|
+
...input.deviceIds !== void 0 ? { deviceIds: input.deviceIds } : {},
|
|
1315
|
+
slim
|
|
1316
|
+
});
|
|
1288
1317
|
const rowById = /* @__PURE__ */ new Map();
|
|
1289
1318
|
for (const row of fleet) rowById.set(row.meta.id, row);
|
|
1290
1319
|
if (pctx.registry) {
|
|
@@ -1306,6 +1335,7 @@ async function listAll(pctx, input) {
|
|
|
1306
1335
|
} : info);
|
|
1307
1336
|
}
|
|
1308
1337
|
}
|
|
1338
|
+
const configs = await readDeviceConfigs(pctx, slim ? [] : fleet.filter((row) => !seen.has(String(row.meta.id))).filter((row) => idFilter === null || idFilter.has(row.meta.id)).filter((row) => !camerasOnly || row.meta.type === DeviceType.Camera).map((row) => row.meta.id));
|
|
1309
1339
|
for (const row of fleet) {
|
|
1310
1340
|
const m = row.meta;
|
|
1311
1341
|
const aid = m.addonId;
|
|
@@ -1314,7 +1344,7 @@ async function listAll(pctx, input) {
|
|
|
1314
1344
|
if (idFilter !== null && !idFilter.has(m.id)) continue;
|
|
1315
1345
|
const persistedType = m.type;
|
|
1316
1346
|
if (camerasOnly && persistedType !== DeviceType.Camera) continue;
|
|
1317
|
-
const persistedConfig =
|
|
1347
|
+
const persistedConfig = configs.get(m.id) ?? {};
|
|
1318
1348
|
const metadata = slim ? null : row.metadata;
|
|
1319
1349
|
results.push({
|
|
1320
1350
|
id: m.id,
|
|
@@ -1843,6 +1873,26 @@ function resolveTrackedEventDeviceIds(config, linkedIds) {
|
|
|
1843
1873
|
return linkedIds.filter((id) => picked.has(id));
|
|
1844
1874
|
}
|
|
1845
1875
|
/**
|
|
1876
|
+
* The fleet listing every function here needs, and the ONLY projection any of
|
|
1877
|
+
* them may ask for.
|
|
1878
|
+
*
|
|
1879
|
+
* Linked-device policy reads five fields off a candidate — `id`,
|
|
1880
|
+
* `parentDeviceId`, `location`, `name`, `features` — and `slim` carries all
|
|
1881
|
+
* five. What `slim` drops is `config`, and `config` is not a column: `listAll`
|
|
1882
|
+
* materialises it with ONE `readDeviceStore` per device, sequentially, on
|
|
1883
|
+
* device-manager's event loop. This module asked for the full projection three
|
|
1884
|
+
* times, so every linked-devices read swept the whole fleet's settings rows to
|
|
1885
|
+
* use none of them.
|
|
1886
|
+
*
|
|
1887
|
+
* Measured on the live hub 2026-08-25: `query addon-device-settings` ran
|
|
1888
|
+
* 36 814 times a minute against a 967-device fleet — ~38 full-fleet sweeps a
|
|
1889
|
+
* minute, ~31 of them the `pipeline-analytics` reverse index rebuilding itself
|
|
1890
|
+
* one camera at a time through `getLinkedDevices`. The per-camera `config`
|
|
1891
|
+
* this query DOES need is the separate `readDeviceStore(deviceId)` below, and
|
|
1892
|
+
* it is one row, not the fleet.
|
|
1893
|
+
*/
|
|
1894
|
+
var LINK_CANDIDATE_PROJECTION = { projection: "slim" };
|
|
1895
|
+
/**
|
|
1846
1896
|
* Resolve ONE camera's linked set against an ALREADY-FETCHED fleet.
|
|
1847
1897
|
*
|
|
1848
1898
|
* The fleet is a parameter, not a fetch, because it is the entire cost of this
|
|
@@ -1879,7 +1929,7 @@ function resolveFor(deviceId, all, byId, blob) {
|
|
|
1879
1929
|
/** Cap implementation of `getLinkedDevices`. */
|
|
1880
1930
|
async function getLinkedDevices(pctx, input) {
|
|
1881
1931
|
const { deviceId } = input;
|
|
1882
|
-
const [all, blob] = await Promise.all([listAll(pctx,
|
|
1932
|
+
const [all, blob] = await Promise.all([listAll(pctx, LINK_CANDIDATE_PROJECTION), pctx.settings.readDeviceStore(deviceId)]);
|
|
1883
1933
|
return resolveFor(deviceId, all, new Map(all.map((d) => [d.id, d])), blob);
|
|
1884
1934
|
}
|
|
1885
1935
|
/**
|
|
@@ -1898,7 +1948,7 @@ async function getLinkedDevices(pctx, input) {
|
|
|
1898
1948
|
async function getLinkedDevicesBatch(pctx, input) {
|
|
1899
1949
|
const deviceIds = [...new Set(input.deviceIds)];
|
|
1900
1950
|
if (deviceIds.length === 0) return [];
|
|
1901
|
-
const [all, blobs] = await Promise.all([listAll(pctx,
|
|
1951
|
+
const [all, blobs] = await Promise.all([listAll(pctx, LINK_CANDIDATE_PROJECTION), Promise.all(deviceIds.map((id) => pctx.settings.readDeviceStore(id).catch((err) => {
|
|
1902
1952
|
pctx.host.ctx.logger.warn("getLinkedDevicesBatch: settings read failed — children only", {
|
|
1903
1953
|
tags: { deviceId: id },
|
|
1904
1954
|
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
@@ -1920,7 +1970,7 @@ async function getLinkedDevicesBatch(pctx, input) {
|
|
|
1920
1970
|
async function buildLinkedDevicesContribution(pctx, deviceId) {
|
|
1921
1971
|
const persisted = await pctx.metaStore.resolvePersistedById(deviceId);
|
|
1922
1972
|
if (!persisted || persisted.meta.type !== DeviceType.Camera) return null;
|
|
1923
|
-
const [all, blob] = await Promise.all([listAll(pctx,
|
|
1973
|
+
const [all, blob] = await Promise.all([listAll(pctx, LINK_CANDIDATE_PROJECTION), pctx.settings.readDeviceStore(deviceId)]);
|
|
1924
1974
|
const config = parseLinkedDevicesConfig(blob);
|
|
1925
1975
|
const options = all.filter((d) => d.id !== deviceId).map((d) => ({
|
|
1926
1976
|
value: String(d.id),
|
|
@@ -3999,6 +4049,36 @@ var DEVICE_ROWS_COLUMNS = [
|
|
|
3999
4049
|
type: "JSON"
|
|
4000
4050
|
}
|
|
4001
4051
|
];
|
|
4052
|
+
/**
|
|
4053
|
+
* The columns a SLIM fleet read selects: every declared column except the
|
|
4054
|
+
* primary key (always returned) and `metadata`.
|
|
4055
|
+
*
|
|
4056
|
+
* ## Why this is a DENYLIST and must stay one
|
|
4057
|
+
*
|
|
4058
|
+
* `decodeDeviceRow` returns `null` when `deviceId`, `addonId`, `stableId`,
|
|
4059
|
+
* `type` or `name` is missing, and `list()` then SKIPS the row with a warn. A
|
|
4060
|
+
* hand-written allowlist that forgot one of the five would not make the fleet
|
|
4061
|
+
* slower — it would make devices vanish from every listing, quietly, and the
|
|
4062
|
+
* only trace would be a log line nobody is reading at the time. Deriving the
|
|
4063
|
+
* list by subtraction means a column added tomorrow is carried by default and
|
|
4064
|
+
* the only way to lose one is to name it here.
|
|
4065
|
+
*
|
|
4066
|
+
* `metadata` is the one slim provably discards: `device-queries.ts#listAll`
|
|
4067
|
+
* sets `metadata: null` on every slim row. It is also the largest JSON column
|
|
4068
|
+
* on the row, which is why this is worth doing at all.
|
|
4069
|
+
*
|
|
4070
|
+
* ## What is NOT here, and will not be
|
|
4071
|
+
*
|
|
4072
|
+
* There is no `where: { type: 'camera' }` companion to this. `isCameraDevice`
|
|
4073
|
+
* is a method-presence check (`getStreamSources`), not the persisted `type`, so
|
|
4074
|
+
* a doorbell with a camera answers YES while its row says `doorbell`. Filtering
|
|
4075
|
+
* the rows by type would strip exactly those devices of their row — and
|
|
4076
|
+
* `toDeviceInfo` reads `name` / `location` / `disabled` from the ROW precisely
|
|
4077
|
+
* because the live device's copies are stale by construction. The fleet would
|
|
4078
|
+
* keep working and start reporting pre-rename names on doorbells. The
|
|
4079
|
+
* `isCamera` filter stays in JS.
|
|
4080
|
+
*/
|
|
4081
|
+
var DEVICE_ROWS_SLIM_COLUMNS = DEVICE_ROWS_COLUMNS.map((c) => c.name).filter((name) => name !== "id" && name !== "metadata");
|
|
4002
4082
|
var DEVICE_ROWS_INDEXES = [
|
|
4003
4083
|
{
|
|
4004
4084
|
name: "idx_dm_devices_addon_stable",
|
|
@@ -4217,6 +4297,33 @@ var DeviceRowStore = class {
|
|
|
4217
4297
|
});
|
|
4218
4298
|
}
|
|
4219
4299
|
/**
|
|
4300
|
+
* The fleet, read as narrowly as the question allows.
|
|
4301
|
+
*
|
|
4302
|
+
* `listAll` is a full-table `SELECT … ORDER BY "deviceId"` — ~1 017 rows a
|
|
4303
|
+
* call on the live hub, 14–54 calls a minute — and its callers then filtered
|
|
4304
|
+
* the result in JS. The two filters that CAN be pushed down are here:
|
|
4305
|
+
*
|
|
4306
|
+
* - `deviceIds` becomes a `whereIn`. The viewer's linked-devices panel asks
|
|
4307
|
+
* about ~8 named ids; it was answered by reading the whole ledger. An
|
|
4308
|
+
* EMPTY set reads nothing at all rather than degrading to "everything" —
|
|
4309
|
+
* a request for no devices is a request, not an omission.
|
|
4310
|
+
* - `slim` becomes a column projection, {@link DEVICE_ROWS_SLIM_COLUMNS}.
|
|
4311
|
+
*
|
|
4312
|
+
* `isCamera` is deliberately NOT one of them — see that constant's note and
|
|
4313
|
+
* `device-row-store-filtered.spec.ts`.
|
|
4314
|
+
*/
|
|
4315
|
+
async listFleet(opts) {
|
|
4316
|
+
if (opts.deviceIds !== void 0 && opts.deviceIds.length === 0) return [];
|
|
4317
|
+
return this.list({
|
|
4318
|
+
...opts.deviceIds !== void 0 ? { whereIn: { deviceId: [...new Set(opts.deviceIds)] } } : {},
|
|
4319
|
+
orderBy: {
|
|
4320
|
+
field: "deviceId",
|
|
4321
|
+
direction: "asc"
|
|
4322
|
+
},
|
|
4323
|
+
limit: DEVICE_ROWS_FLEET_LIMIT
|
|
4324
|
+
}, opts.slim === true ? DEVICE_ROWS_SLIM_COLUMNS : void 0);
|
|
4325
|
+
}
|
|
4326
|
+
/**
|
|
4220
4327
|
* The device an addon knows as `stableId`, or `null`.
|
|
4221
4328
|
*
|
|
4222
4329
|
* `(addonId, stableId)` is the addon-facing identity — unique by
|
|
@@ -4287,11 +4394,12 @@ var DeviceRowStore = class {
|
|
|
4287
4394
|
await this.declare();
|
|
4288
4395
|
return this.backend.count({ collection: DEVICE_ROWS_COLLECTION });
|
|
4289
4396
|
}
|
|
4290
|
-
async list(filter) {
|
|
4397
|
+
async list(filter, columns) {
|
|
4291
4398
|
await this.declare();
|
|
4292
4399
|
const records = await this.backend.query({
|
|
4293
4400
|
collection: DEVICE_ROWS_COLLECTION,
|
|
4294
|
-
filter
|
|
4401
|
+
filter,
|
|
4402
|
+
...columns === void 0 ? {} : { columns }
|
|
4295
4403
|
});
|
|
4296
4404
|
const out = [];
|
|
4297
4405
|
for (const record of records) {
|
|
@@ -43,6 +43,36 @@ export declare const DEVICE_ROWS_COLLECTION = "device-manager:devices";
|
|
|
43
43
|
*/
|
|
44
44
|
export declare const DEVICE_ROWS_FLEET_LIMIT = 20000;
|
|
45
45
|
export declare const DEVICE_ROWS_COLUMNS: readonly CollectionColumn[];
|
|
46
|
+
/**
|
|
47
|
+
* The columns a SLIM fleet read selects: every declared column except the
|
|
48
|
+
* primary key (always returned) and `metadata`.
|
|
49
|
+
*
|
|
50
|
+
* ## Why this is a DENYLIST and must stay one
|
|
51
|
+
*
|
|
52
|
+
* `decodeDeviceRow` returns `null` when `deviceId`, `addonId`, `stableId`,
|
|
53
|
+
* `type` or `name` is missing, and `list()` then SKIPS the row with a warn. A
|
|
54
|
+
* hand-written allowlist that forgot one of the five would not make the fleet
|
|
55
|
+
* slower — it would make devices vanish from every listing, quietly, and the
|
|
56
|
+
* only trace would be a log line nobody is reading at the time. Deriving the
|
|
57
|
+
* list by subtraction means a column added tomorrow is carried by default and
|
|
58
|
+
* the only way to lose one is to name it here.
|
|
59
|
+
*
|
|
60
|
+
* `metadata` is the one slim provably discards: `device-queries.ts#listAll`
|
|
61
|
+
* sets `metadata: null` on every slim row. It is also the largest JSON column
|
|
62
|
+
* on the row, which is why this is worth doing at all.
|
|
63
|
+
*
|
|
64
|
+
* ## What is NOT here, and will not be
|
|
65
|
+
*
|
|
66
|
+
* There is no `where: { type: 'camera' }` companion to this. `isCameraDevice`
|
|
67
|
+
* is a method-presence check (`getStreamSources`), not the persisted `type`, so
|
|
68
|
+
* a doorbell with a camera answers YES while its row says `doorbell`. Filtering
|
|
69
|
+
* the rows by type would strip exactly those devices of their row — and
|
|
70
|
+
* `toDeviceInfo` reads `name` / `location` / `disabled` from the ROW precisely
|
|
71
|
+
* because the live device's copies are stale by construction. The fleet would
|
|
72
|
+
* keep working and start reporting pre-rename names on doorbells. The
|
|
73
|
+
* `isCamera` filter stays in JS.
|
|
74
|
+
*/
|
|
75
|
+
export declare const DEVICE_ROWS_SLIM_COLUMNS: readonly string[];
|
|
46
76
|
export declare const DEVICE_ROWS_INDEXES: readonly CollectionIndex[];
|
|
47
77
|
/**
|
|
48
78
|
* The settings-store door this store needs, as a plain object surface.
|
|
@@ -193,6 +223,26 @@ export declare class DeviceRowStore {
|
|
|
193
223
|
get(deviceId: number): Promise<DeviceRow | null>;
|
|
194
224
|
/** Every device, ordered by numeric id. */
|
|
195
225
|
listAll(): Promise<readonly DeviceRow[]>;
|
|
226
|
+
/**
|
|
227
|
+
* The fleet, read as narrowly as the question allows.
|
|
228
|
+
*
|
|
229
|
+
* `listAll` is a full-table `SELECT … ORDER BY "deviceId"` — ~1 017 rows a
|
|
230
|
+
* call on the live hub, 14–54 calls a minute — and its callers then filtered
|
|
231
|
+
* the result in JS. The two filters that CAN be pushed down are here:
|
|
232
|
+
*
|
|
233
|
+
* - `deviceIds` becomes a `whereIn`. The viewer's linked-devices panel asks
|
|
234
|
+
* about ~8 named ids; it was answered by reading the whole ledger. An
|
|
235
|
+
* EMPTY set reads nothing at all rather than degrading to "everything" —
|
|
236
|
+
* a request for no devices is a request, not an omission.
|
|
237
|
+
* - `slim` becomes a column projection, {@link DEVICE_ROWS_SLIM_COLUMNS}.
|
|
238
|
+
*
|
|
239
|
+
* `isCamera` is deliberately NOT one of them — see that constant's note and
|
|
240
|
+
* `device-row-store-filtered.spec.ts`.
|
|
241
|
+
*/
|
|
242
|
+
listFleet(opts: {
|
|
243
|
+
readonly deviceIds?: readonly number[];
|
|
244
|
+
readonly slim?: boolean;
|
|
245
|
+
}): Promise<readonly DeviceRow[]>;
|
|
196
246
|
/**
|
|
197
247
|
* The device an addon knows as `stableId`, or `null`.
|
|
198
248
|
*
|
|
@@ -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-D-R0SuP-.js");
|
|
7
7
|
//#region src/builtins/doorbell/trigger-engine.ts
|
|
8
8
|
/**
|
|
9
9
|
* Pure trigger logic for the virtual-doorbell builtin — edge detection over
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as isSameAddonId, Gt as EventCategory, I as doorbellCapability, Mt as createEvent, Tt as DeviceType, vt as errMsg, w as bareAddonId, yt as BaseAddon } from "../../dist-
|
|
1
|
+
import { G as isSameAddonId, Gt as EventCategory, I as doorbellCapability, Mt as createEvent, Tt as DeviceType, vt as errMsg, w as bareAddonId, yt as BaseAddon } from "../../dist-Bh25kEUH.mjs";
|
|
2
2
|
//#region src/builtins/doorbell/trigger-engine.ts
|
|
3
3
|
/**
|
|
4
4
|
* Pure trigger logic for the virtual-doorbell builtin — edge detection over
|
|
@@ -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-D-R0SuP-.js");
|
|
7
7
|
const require_formatter = require("../../formatter-DqAKDlvN.js");
|
|
8
8
|
//#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
|
|
9
9
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-
|
|
1
|
+
import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-Bh25kEUH.mjs";
|
|
2
2
|
import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
|
|
3
3
|
//#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
|
|
4
4
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("../../dist-
|
|
3
|
+
const require_dist = require("../../dist-D-R0SuP-.js");
|
|
4
4
|
//#region src/builtins/liveness-monitor/liveness-checks.ts
|
|
5
5
|
var NO_DEVICES = "liveness:no-devices";
|
|
6
6
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Gt as EventCategory, Mt as createEvent, vt as errMsg, yt as BaseAddon } from "../../dist-
|
|
1
|
+
import { Gt as EventCategory, Mt as createEvent, vt as errMsg, yt as BaseAddon } from "../../dist-Bh25kEUH.mjs";
|
|
2
2
|
//#region src/builtins/liveness-monitor/liveness-checks.ts
|
|
3
3
|
var NO_DEVICES = "liveness:no-devices";
|
|
4
4
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
@@ -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-D-R0SuP-.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
9
9
|
let crypto$1 = require("crypto");
|