@camstack/system 1.2.135 → 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.
|
@@ -1315,7 +1315,10 @@ async function listAll(pctx, input) {
|
|
|
1315
1315
|
const idFilter = input.deviceIds === void 0 ? null : new Set(input.deviceIds);
|
|
1316
1316
|
const results = [];
|
|
1317
1317
|
const seen = /* @__PURE__ */ new Set();
|
|
1318
|
-
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
|
+
});
|
|
1319
1322
|
const rowById = /* @__PURE__ */ new Map();
|
|
1320
1323
|
for (const row of fleet) rowById.set(row.meta.id, row);
|
|
1321
1324
|
if (pctx.registry) {
|
|
@@ -4051,6 +4054,36 @@ var DEVICE_ROWS_COLUMNS = [
|
|
|
4051
4054
|
type: "JSON"
|
|
4052
4055
|
}
|
|
4053
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");
|
|
4054
4087
|
var DEVICE_ROWS_INDEXES = [
|
|
4055
4088
|
{
|
|
4056
4089
|
name: "idx_dm_devices_addon_stable",
|
|
@@ -4269,6 +4302,33 @@ var DeviceRowStore = class {
|
|
|
4269
4302
|
});
|
|
4270
4303
|
}
|
|
4271
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
|
+
/**
|
|
4272
4332
|
* The device an addon knows as `stableId`, or `null`.
|
|
4273
4333
|
*
|
|
4274
4334
|
* `(addonId, stableId)` is the addon-facing identity — unique by
|
|
@@ -4339,11 +4399,12 @@ var DeviceRowStore = class {
|
|
|
4339
4399
|
await this.declare();
|
|
4340
4400
|
return this.backend.count({ collection: DEVICE_ROWS_COLLECTION });
|
|
4341
4401
|
}
|
|
4342
|
-
async list(filter) {
|
|
4402
|
+
async list(filter, columns) {
|
|
4343
4403
|
await this.declare();
|
|
4344
4404
|
const records = await this.backend.query({
|
|
4345
4405
|
collection: DEVICE_ROWS_COLLECTION,
|
|
4346
|
-
filter
|
|
4406
|
+
filter,
|
|
4407
|
+
...columns === void 0 ? {} : { columns }
|
|
4347
4408
|
});
|
|
4348
4409
|
const out = [];
|
|
4349
4410
|
for (const record of records) {
|
|
@@ -1310,7 +1310,10 @@ async function listAll(pctx, input) {
|
|
|
1310
1310
|
const idFilter = input.deviceIds === void 0 ? null : new Set(input.deviceIds);
|
|
1311
1311
|
const results = [];
|
|
1312
1312
|
const seen = /* @__PURE__ */ new Set();
|
|
1313
|
-
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
|
+
});
|
|
1314
1317
|
const rowById = /* @__PURE__ */ new Map();
|
|
1315
1318
|
for (const row of fleet) rowById.set(row.meta.id, row);
|
|
1316
1319
|
if (pctx.registry) {
|
|
@@ -4046,6 +4049,36 @@ var DEVICE_ROWS_COLUMNS = [
|
|
|
4046
4049
|
type: "JSON"
|
|
4047
4050
|
}
|
|
4048
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");
|
|
4049
4082
|
var DEVICE_ROWS_INDEXES = [
|
|
4050
4083
|
{
|
|
4051
4084
|
name: "idx_dm_devices_addon_stable",
|
|
@@ -4264,6 +4297,33 @@ var DeviceRowStore = class {
|
|
|
4264
4297
|
});
|
|
4265
4298
|
}
|
|
4266
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
|
+
/**
|
|
4267
4327
|
* The device an addon knows as `stableId`, or `null`.
|
|
4268
4328
|
*
|
|
4269
4329
|
* `(addonId, stableId)` is the addon-facing identity — unique by
|
|
@@ -4334,11 +4394,12 @@ var DeviceRowStore = class {
|
|
|
4334
4394
|
await this.declare();
|
|
4335
4395
|
return this.backend.count({ collection: DEVICE_ROWS_COLLECTION });
|
|
4336
4396
|
}
|
|
4337
|
-
async list(filter) {
|
|
4397
|
+
async list(filter, columns) {
|
|
4338
4398
|
await this.declare();
|
|
4339
4399
|
const records = await this.backend.query({
|
|
4340
4400
|
collection: DEVICE_ROWS_COLLECTION,
|
|
4341
|
-
filter
|
|
4401
|
+
filter,
|
|
4402
|
+
...columns === void 0 ? {} : { columns }
|
|
4342
4403
|
});
|
|
4343
4404
|
const out = [];
|
|
4344
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
|
*
|