@camstack/addon-pipeline 1.2.196 → 1.2.197
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/audio-analyzer/index.js +2 -2
- package/dist/audio-analyzer/index.mjs +2 -2
- package/dist/{default-detection-model-CJdc8j83.js → default-detection-model-CM-8U0Bb.js} +1 -1
- package/dist/{default-detection-model-BGBAmtEp.mjs → default-detection-model-CplzzTmN.mjs} +1 -1
- package/dist/detection-pipeline/index.js +5 -5
- package/dist/detection-pipeline/index.mjs +4 -4
- package/dist/{dist-HG5geL9t.js → dist-CBa1j3On.js} +141 -35
- package/dist/{dist-mYDK58Jp.mjs → dist-Y4BsF_EC.mjs} +130 -36
- package/dist/{lazy-sharp-DmAwZ0s9.js → lazy-sharp-CS5WE9mI.js} +1 -1
- package/dist/motion-wasm/index.js +2 -2
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-xRsaPwBa.mjs → node-B5ouEQYN.mjs} +1 -1
- package/dist/{node--my8JTOW.js → node-C-B8VuGi.js} +1 -1
- package/dist/pipeline-runner/index.js +363 -6
- package/dist/pipeline-runner/index.mjs +362 -5
- package/dist/{process-memory-CoCSce63.js → process-memory-CmeKr_MZ.js} +1 -1
- package/dist/{process-memory-BDHR3lxe.mjs → process-memory-DeO2OZ3-.mjs} +1 -1
- package/dist/recorder/index.js +131 -18
- package/dist/recorder/index.mjs +131 -18
- package/dist/{retire-root-keys-KE6D6Xh_.js → retire-root-keys-Csb8z2f3.js} +19 -0
- package/dist/{retire-root-keys-DMolfhsP.mjs → retire-root-keys-DZvlso2l.mjs} +19 -0
- package/dist/{segment-demux-js-CXvgKfsn.mjs → segment-demux-js-DXPgq2cf.mjs} +1 -1
- package/dist/{segment-demux-js-CBynn9Gh.js → segment-demux-js-DiIsywGz.js} +1 -1
- package/dist/session-decode/decode-worker-child.js +2 -2
- package/dist/session-decode/decode-worker-child.mjs +1 -1
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BMsB2MVD.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-Q-6HzWJ0.mjs} +3 -3
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-B_NVJXAy.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Cv5McbTI.mjs} +1 -1
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CBxobiZW.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Dj_qoc1e.mjs} +1 -1
- package/dist/stream-broker/demux-worker-child.js +1 -1
- package/dist/stream-broker/demux-worker-child.mjs +1 -1
- package/dist/stream-broker/{hostInit-CZig_taJ.mjs → hostInit-C-2Eo_nr.mjs} +3 -3
- package/dist/stream-broker/index.js +4 -4
- package/dist/stream-broker/index.mjs +4 -4
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/{worker-protocol-DCsi4YS1.js → worker-protocol-CXsdriRX.js} +1 -1
- package/dist/{worker-protocol-C0R1DDC0.mjs → worker-protocol-_7zrToTo.mjs} +1 -1
- package/package.json +1 -1
package/dist/recorder/index.js
CHANGED
|
@@ -2,12 +2,12 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
6
|
-
const require_node = require("../node
|
|
5
|
+
const require_dist = require("../dist-CBa1j3On.js");
|
|
6
|
+
const require_node = require("../node-C-B8VuGi.js");
|
|
7
7
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
8
8
|
const require_restream_intent = require("../restream-intent-Cv9x3jmu.js");
|
|
9
9
|
const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-DaUBcb13.js");
|
|
10
|
-
const require_retire_root_keys = require("../retire-root-keys-
|
|
10
|
+
const require_retire_root_keys = require("../retire-root-keys-Csb8z2f3.js");
|
|
11
11
|
let node_crypto = require("node:crypto");
|
|
12
12
|
let node_fs = require("node:fs");
|
|
13
13
|
let node_path = require("node:path");
|
|
@@ -3884,6 +3884,31 @@ var CalendarIndex = class {
|
|
|
3884
3884
|
//#endregion
|
|
3885
3885
|
//#region src/recorder/addon/config-store.ts
|
|
3886
3886
|
/**
|
|
3887
|
+
* Per-device recording-config persistence for the recorder addon.
|
|
3888
|
+
*
|
|
3889
|
+
* ONE ROW PER CAMERA in `recorder:recording-configs`, through
|
|
3890
|
+
* {@link RowMapStore}. Asking what camera 617 records is a primary-key lookup;
|
|
3891
|
+
* saving its config writes that row and touches no other.
|
|
3892
|
+
*
|
|
3893
|
+
* ## What this replaced, and why
|
|
3894
|
+
*
|
|
3895
|
+
* Until the 2026-08-19 flatten every camera's `RecordingConfig` lived in ONE
|
|
3896
|
+
* key of the recorder's `addon-settings` / `root` blob — a row that was 201 833
|
|
3897
|
+
* bytes on the reference hub, because the ops-log and the export history shared
|
|
3898
|
+
* it. So `loadDeviceConfig(617)` read and `JSON.parse`d 201 KB, and
|
|
3899
|
+
* `saveDeviceConfig` read that, merged, and rewrote it. The staging walk did it
|
|
3900
|
+
* once per device and lost 45–267 s of a boot to it (2026-08-18); teaching the
|
|
3901
|
+
* walk to read the map once capped the symptom, and this removes the cause.
|
|
3902
|
+
*
|
|
3903
|
+
* ## Failure direction
|
|
3904
|
+
*
|
|
3905
|
+
* `RecordingConfigSchema` rejects unknown keys so a stale caller fails loudly,
|
|
3906
|
+
* but a row written by an older build may still carry retired ones — `.strip()`
|
|
3907
|
+
* drops them. And validation is now PER ROW: one unparseable camera costs that
|
|
3908
|
+
* camera, where the blob's single `safeParse` took every camera down to the
|
|
3909
|
+
* empty fallback (= the whole fleet silently unconfigured).
|
|
3910
|
+
*/
|
|
3911
|
+
/**
|
|
3887
3912
|
* @durable class=config owner=recorder
|
|
3888
3913
|
* write="one row per camera, written by `saveDeviceConfig` (the `recording` cap's
|
|
3889
3914
|
* setConfig / band authoring) — the only writer"
|
|
@@ -3893,7 +3918,7 @@ var CalendarIndex = class {
|
|
|
3893
3918
|
var RECORDING_CONFIGS_COLLECTION = "recorder:recording-configs";
|
|
3894
3919
|
var RECORDING_CONFIGS_SPEC = {
|
|
3895
3920
|
collection: RECORDING_CONFIGS_COLLECTION,
|
|
3896
|
-
schema: require_dist.RecordingConfigSchema.strip(),
|
|
3921
|
+
schema: require_dist.preprocess((raw) => require_dist.migrateLegacyDeviceSignalConfig(raw).value, require_dist.RecordingConfigSchema.strip()),
|
|
3897
3922
|
columns: [
|
|
3898
3923
|
{
|
|
3899
3924
|
name: "deviceId",
|
|
@@ -3959,7 +3984,10 @@ async function loadDeviceConfig(state, deviceId) {
|
|
|
3959
3984
|
*/
|
|
3960
3985
|
function deviceIdsWithLostBands(configs) {
|
|
3961
3986
|
const lost = [];
|
|
3962
|
-
for (const [deviceId, config] of configs)
|
|
3987
|
+
for (const [deviceId, config] of configs) {
|
|
3988
|
+
if (config.deviceDecision === true) continue;
|
|
3989
|
+
if (config.enabled && config.bands.length === 0 && config.mode && config.mode !== "off") lost.push(deviceId);
|
|
3990
|
+
}
|
|
3963
3991
|
return lost.toSorted((a, b) => a - b);
|
|
3964
3992
|
}
|
|
3965
3993
|
/** Boot-time check: log the {@link deviceIdsWithLostBands} once, if any. */
|
|
@@ -3969,6 +3997,48 @@ async function warnLostBands(state, logger) {
|
|
|
3969
3997
|
logger.warn(`recording config: device(s) ${lost.join(", ")} claim a recording mode but have NO bands — a pre-retirement config that lost its legacy authoring fields. Nothing is recorded for them until their bands are re-authored.`);
|
|
3970
3998
|
}
|
|
3971
3999
|
/**
|
|
4000
|
+
* Persist the D371→D380 shape for every stored row — the migration, in code,
|
|
4001
|
+
* run once per boot and IDEMPOTENT: a second run finds no legacy key and
|
|
4002
|
+
* writes nothing.
|
|
4003
|
+
*
|
|
4004
|
+
* It reads the rows RAW ({@link RowMapStore.readAllRaw}) on purpose. The read
|
|
4005
|
+
* schema already migrates in memory, so by the time `readAll` answers there is
|
|
4006
|
+
* nothing left to recognise — and the retired key is stripped by a non-strict
|
|
4007
|
+
* `z.object`, so the migration would look like it had nothing to do on exactly
|
|
4008
|
+
* the row it exists for.
|
|
4009
|
+
*
|
|
4010
|
+
* Both outcomes are logged, because both change what a camera records and
|
|
4011
|
+
* silence would read as "nothing happened" — which is what a stripped key
|
|
4012
|
+
* looks like from the outside.
|
|
4013
|
+
*/
|
|
4014
|
+
async function migrateLegacyDeviceSignalRows(state, logger) {
|
|
4015
|
+
const migrated = [];
|
|
4016
|
+
const stripped = [];
|
|
4017
|
+
for (const [key, raw] of await state.readAllRaw()) {
|
|
4018
|
+
const outcome = require_dist.migrateLegacyDeviceSignalConfig(raw);
|
|
4019
|
+
if (!outcome.migrated && !outcome.strippedOnly) continue;
|
|
4020
|
+
const deviceId = Number(key);
|
|
4021
|
+
if (!Number.isInteger(deviceId)) continue;
|
|
4022
|
+
const parsed = require_dist.RecordingConfigSchema.strip().safeParse(outcome.value);
|
|
4023
|
+
if (!parsed.success) {
|
|
4024
|
+
logger.warn("recording config: legacy device-signal row could not be migrated", {
|
|
4025
|
+
tags: { deviceId },
|
|
4026
|
+
meta: { error: parsed.error.message }
|
|
4027
|
+
});
|
|
4028
|
+
continue;
|
|
4029
|
+
}
|
|
4030
|
+
await saveDeviceConfig(state, deviceId, parsed.data);
|
|
4031
|
+
if (outcome.migrated) migrated.push(deviceId);
|
|
4032
|
+
else stripped.push(deviceId);
|
|
4033
|
+
}
|
|
4034
|
+
if (migrated.length > 0) logger.info("recording config: migrated to the on-device-decision mode (the retired band trigger)", { meta: { deviceIds: migrated } });
|
|
4035
|
+
if (stripped.length > 0) logger.warn("recording config: a band mixed the retired device-signal trigger with others — the key was dropped and the band kept. These cameras no longer follow their own signal until the on-device-decision mode is selected for them.", { meta: { deviceIds: stripped } });
|
|
4036
|
+
return {
|
|
4037
|
+
migrated,
|
|
4038
|
+
stripped
|
|
4039
|
+
};
|
|
4040
|
+
}
|
|
4041
|
+
/**
|
|
3972
4042
|
* Persist (insert or replace) a device's config — ONE row. Validates against
|
|
3973
4043
|
* `RecordingConfigSchema` at the boundary (untrusted cap input). Returns the
|
|
3974
4044
|
* validated config that was persisted.
|
|
@@ -12462,6 +12532,13 @@ function bandActiveAt(band, date) {
|
|
|
12462
12532
|
if (s > e) return applies(wd) && t >= s || applies(prevWd) && t < e;
|
|
12463
12533
|
return applies(wd);
|
|
12464
12534
|
}
|
|
12535
|
+
/**
|
|
12536
|
+
* The band covering `date`, or null. GENERIC over the band type so the caller
|
|
12537
|
+
* gets back exactly what it put in: the recorder decides on `EffectiveBand`s
|
|
12538
|
+
* (`band-decision.ts`), which carry the one non-authored fact — that the DEVICE
|
|
12539
|
+
* decides — and a return type widened to `RecordingBand` would erase it right
|
|
12540
|
+
* where the gates read it.
|
|
12541
|
+
*/
|
|
12465
12542
|
function activeBandAt(config, date) {
|
|
12466
12543
|
return config.bands.find((b) => bandActiveAt(b, date)) ?? null;
|
|
12467
12544
|
}
|
|
@@ -12486,6 +12563,37 @@ function activeBandAt(config, date) {
|
|
|
12486
12563
|
* unit-testable without ffmpeg, the broker, the event bus, or a real wall clock.
|
|
12487
12564
|
*/
|
|
12488
12565
|
/**
|
|
12566
|
+
* THE band a `deviceDecision` config decides through: always on (every day,
|
|
12567
|
+
* `start === end` — the band engine's always-on shape), `events`, and listening
|
|
12568
|
+
* to exactly one source, the camera's own level.
|
|
12569
|
+
*
|
|
12570
|
+
* Its buffers are the canonical pad ({@link DEFAULT_EVENTS_BAND_BUFFER_SEC}),
|
|
12571
|
+
* not per-camera knobs: this mode's whole contract with the operator is ONE
|
|
12572
|
+
* flag. The pad only ever retains footage around an episode the device itself
|
|
12573
|
+
* delimited, so there is nothing here for an operator to tune.
|
|
12574
|
+
*/
|
|
12575
|
+
var DEVICE_DECISION_BAND = Object.freeze({
|
|
12576
|
+
days: [],
|
|
12577
|
+
start: "00:00",
|
|
12578
|
+
end: "00:00",
|
|
12579
|
+
mode: "events",
|
|
12580
|
+
deviceSignal: true,
|
|
12581
|
+
preBufferSec: require_dist.DEFAULT_EVENTS_BAND_BUFFER_SEC.preBufferSec,
|
|
12582
|
+
postBufferSec: require_dist.DEFAULT_EVENTS_BAND_BUFFER_SEC.postBufferSec
|
|
12583
|
+
});
|
|
12584
|
+
/**
|
|
12585
|
+
* THE bands the recorder decides on for a config — the ONE place
|
|
12586
|
+
* `config.bands` is turned into what the gates read.
|
|
12587
|
+
*
|
|
12588
|
+
* `deviceDecision` resolves to {@link DEVICE_DECISION_BAND} and to nothing
|
|
12589
|
+
* else; every other config is its own authored bands, byte for byte. Because
|
|
12590
|
+
* the schema makes the two exclusive, this is a choice and never a merge.
|
|
12591
|
+
*/
|
|
12592
|
+
function effectiveBands(config) {
|
|
12593
|
+
if (config.deviceDecision === true) return [DEVICE_DECISION_BAND];
|
|
12594
|
+
return config.bands ?? [];
|
|
12595
|
+
}
|
|
12596
|
+
/**
|
|
12489
12597
|
* THE one place a band's pre/post buffers are read. An ABSENT field takes
|
|
12490
12598
|
* {@link DEFAULT_EVENTS_BAND_BUFFER_SEC}; an explicit value — including `0` —
|
|
12491
12599
|
* is honoured verbatim.
|
|
@@ -12526,6 +12634,9 @@ function triggerKey(source) {
|
|
|
12526
12634
|
case "signal": return "signal";
|
|
12527
12635
|
}
|
|
12528
12636
|
}
|
|
12637
|
+
/** The single source {@link DEVICE_DECISION_BAND} listens to, shared so the
|
|
12638
|
+
* band never allocates a new one per call. */
|
|
12639
|
+
var SIGNAL_SOURCES = Object.freeze([{ kind: "signal" }]);
|
|
12529
12640
|
/**
|
|
12530
12641
|
* LE sorgenti che questa banda ascolta — l'unico posto dove i `triggers` di
|
|
12531
12642
|
* una banda diventano `TriggerSource[]`.
|
|
@@ -12541,6 +12652,7 @@ function triggerKey(source) {
|
|
|
12541
12652
|
* denuncia invece di restare zitto.
|
|
12542
12653
|
*/
|
|
12543
12654
|
function bandTriggerSources(band) {
|
|
12655
|
+
if (band.deviceSignal === true) return SIGNAL_SOURCES;
|
|
12544
12656
|
const t = band.triggers;
|
|
12545
12657
|
if (t === void 0) return [];
|
|
12546
12658
|
const sources = [];
|
|
@@ -12554,7 +12666,6 @@ function bandTriggerSources(band) {
|
|
|
12554
12666
|
kind: "sensor",
|
|
12555
12667
|
sourceDeviceId
|
|
12556
12668
|
});
|
|
12557
|
-
if (t.deviceSignal === true) sources.push({ kind: "signal" });
|
|
12558
12669
|
return sources;
|
|
12559
12670
|
}
|
|
12560
12671
|
/**
|
|
@@ -12740,8 +12851,8 @@ function eventsBandDemanded(band, triggers, atMs) {
|
|
|
12740
12851
|
*/
|
|
12741
12852
|
function shouldRecordAt(config, triggers, at) {
|
|
12742
12853
|
if (!config.enabled) return false;
|
|
12743
|
-
const bands = config
|
|
12744
|
-
if (
|
|
12854
|
+
const bands = effectiveBands(config);
|
|
12855
|
+
if (bands.length === 0) return false;
|
|
12745
12856
|
const band = activeBandAt({ bands }, at);
|
|
12746
12857
|
if (!band) return false;
|
|
12747
12858
|
if (band.mode === "continuous") return true;
|
|
@@ -12996,8 +13107,8 @@ function candidateEdgesMs(bands, nowMs) {
|
|
|
12996
13107
|
* costs one wasted wake-up and never costs footage.
|
|
12997
13108
|
*/
|
|
12998
13109
|
function nextBandEdgeMs(config, nowMs) {
|
|
12999
|
-
const bands = config
|
|
13000
|
-
if (
|
|
13110
|
+
const bands = effectiveBands(config);
|
|
13111
|
+
if (bands.length === 0) return null;
|
|
13001
13112
|
const current = activeBandAt({ bands }, new Date(nowMs));
|
|
13002
13113
|
const candidates = [...new Set(candidateEdgesMs(bands, nowMs))].filter((ms) => ms > nowMs).toSorted((a, b) => a - b);
|
|
13003
13114
|
for (const ms of candidates) if (activeBandAt({ bands }, new Date(ms)) !== current) return ms;
|
|
@@ -13032,8 +13143,8 @@ function eventsWindowCloseMs(band, triggers, nowMs) {
|
|
|
13032
13143
|
function nextDecisionChangeAt(input) {
|
|
13033
13144
|
const { config, triggers, nowMs } = input;
|
|
13034
13145
|
if (!config.enabled) return null;
|
|
13035
|
-
const bands = config
|
|
13036
|
-
if (
|
|
13146
|
+
const bands = effectiveBands(config);
|
|
13147
|
+
if (bands.length === 0) return null;
|
|
13037
13148
|
const band = activeBandAt({ bands }, new Date(nowMs));
|
|
13038
13149
|
const edgeMs = nextBandEdgeMs(config, nowMs);
|
|
13039
13150
|
const closeMs = band === null ? null : eventsWindowCloseMs(band, triggers, nowMs);
|
|
@@ -14503,7 +14614,7 @@ var RecordingController = class {
|
|
|
14503
14614
|
const config = await this.deps.loadConfig(deviceId);
|
|
14504
14615
|
if (config.enabled !== true) return;
|
|
14505
14616
|
const nowMs = this.now();
|
|
14506
|
-
const band = activeBandAt({ bands: config
|
|
14617
|
+
const band = activeBandAt({ bands: effectiveBands(config) }, new Date(nowMs));
|
|
14507
14618
|
if (!band || band.mode !== "events") return;
|
|
14508
14619
|
const { postMs } = resolveBandBufferMs(band);
|
|
14509
14620
|
const sinceMs = nowMs - postMs - TRIGGER_HISTORY_MARGIN_MS;
|
|
@@ -14910,7 +15021,7 @@ var RecordingController = class {
|
|
|
14910
15021
|
if (this.stopped) return;
|
|
14911
15022
|
let band;
|
|
14912
15023
|
try {
|
|
14913
|
-
band = activeBandAt({ bands: (await this.deps.loadConfig(deviceId))
|
|
15024
|
+
band = activeBandAt({ bands: effectiveBands(await this.deps.loadConfig(deviceId)) }, new Date(atMs));
|
|
14914
15025
|
} catch (err) {
|
|
14915
15026
|
this.deps.logger.warn("recorder: audio trigger qualification skipped — config read failed", {
|
|
14916
15027
|
tags: { deviceId },
|
|
@@ -14935,7 +15046,7 @@ var RecordingController = class {
|
|
|
14935
15046
|
*/
|
|
14936
15047
|
async postBufferMsFor(deviceId, atMs) {
|
|
14937
15048
|
try {
|
|
14938
|
-
const band = activeBandAt({ bands: (await this.deps.loadConfig(deviceId))
|
|
15049
|
+
const band = activeBandAt({ bands: effectiveBands(await this.deps.loadConfig(deviceId)) }, new Date(atMs));
|
|
14939
15050
|
if (band) return resolveBandBufferMs(band).postMs;
|
|
14940
15051
|
} catch (err) {
|
|
14941
15052
|
this.deps.logger.warn("recorder: trigger history using the DEFAULT post-buffer — config read failed", {
|
|
@@ -15026,7 +15137,7 @@ var RecordingController = class {
|
|
|
15026
15137
|
reportUnrecordable(deviceId, config) {
|
|
15027
15138
|
if (!config.enabled) return;
|
|
15028
15139
|
if (this.unrecordableReported.has(deviceId)) return;
|
|
15029
|
-
const bands = config
|
|
15140
|
+
const bands = effectiveBands(config);
|
|
15030
15141
|
if (bands.length === 0) {
|
|
15031
15142
|
this.unrecordableReported.add(deviceId);
|
|
15032
15143
|
this.deps.logger.warn("recorder: device is enabled but has no recording bands — nothing will ever be recorded", { tags: { deviceId } });
|
|
@@ -15363,7 +15474,7 @@ var RecordingController = class {
|
|
|
15363
15474
|
*/
|
|
15364
15475
|
async handleFinalizedSegment(deviceId, profile, placement, attach, startMs, durMs, flatAbsPath) {
|
|
15365
15476
|
try {
|
|
15366
|
-
const band = activeBandAt({ bands: (await this.deps.loadConfig(deviceId))
|
|
15477
|
+
const band = activeBandAt({ bands: effectiveBands(await this.deps.loadConfig(deviceId)) }, new Date(startMs + durMs));
|
|
15367
15478
|
const triggers = this.triggersFor(deviceId);
|
|
15368
15479
|
if (band?.mode === "events" && !segmentRetainedForEvents(startMs, startMs + durMs, band, triggers, attach)) {
|
|
15369
15480
|
this.reportDiscardedSegment(deviceId, profile, attach, band, triggers, startMs, durMs);
|
|
@@ -17367,7 +17478,9 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
17367
17478
|
watchIntervalMs: this.config.watchIntervalMs
|
|
17368
17479
|
}
|
|
17369
17480
|
});
|
|
17370
|
-
|
|
17481
|
+
migrateLegacyDeviceSignalRows(this.configStore(), this.ctx.logger).catch((err) => {
|
|
17482
|
+
this.ctx.logger.warn("recorder: device-signal config migration failed", { meta: { error: require_dist.errMsg(err) } });
|
|
17483
|
+
}).then(() => warnLostBands(this.configStore(), this.ctx.logger));
|
|
17371
17484
|
const providers = [
|
|
17372
17485
|
{
|
|
17373
17486
|
capability: require_dist.recordingCapability,
|
package/dist/recorder/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-
|
|
1
|
+
import { Ct as storageEvictableCapability, D as RecordingSignalStatusSchema, Dt as errMsg, E as RecordingConfigSchema, H as deriveBatteryPresence, It as DeviceFeature, Jt as _enum, Kt as selectAssignedProfileSlots, Lt as DeviceType, P as batteryCapability, Pt as BaseAddon, R as customAction, T as RECORDING_EXPORT_MAX_READ_BYTES, Ut as nodePin, V as defineCustomActions, W as deriveRecordingMode, Xt as boolean, Y as evaluateSensorEdge, Yt as array, _t as recordingSignalCapability, at as migrateLegacyDeviceSignalConfig, d as DEFAULT_EVENTS_BAND_BUFFER_SEC, en as number, et as isFirstLevelMacroClass, g as ExportRecordSchema, gt as recordingExportCapability, ht as recordingCapability, i as BatteryStatusSchema, in as string, nn as preprocess, on as EventCategory, qt as sleep$1, rn as record, tn as object, tt as loadContributionCapability, x as OpsLogEntrySchema, xt as resolveRecordingProfiles, zt as hydrateSchema } from "../dist-Y4BsF_EC.mjs";
|
|
2
|
+
import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-B5ouEQYN.mjs";
|
|
3
3
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
4
4
|
import { r as withRecordingIntent } from "../restream-intent-B4BXZra7.mjs";
|
|
5
5
|
import { n as startEventLoopStallMonitor } from "../event-loop-stall-monitor-DXLNBMkY.mjs";
|
|
6
|
-
import { n as RowMapStore, t as retireRootKeys } from "../retire-root-keys-
|
|
6
|
+
import { n as RowMapStore, t as retireRootKeys } from "../retire-root-keys-DZvlso2l.mjs";
|
|
7
7
|
import { randomUUID } from "node:crypto";
|
|
8
8
|
import { createReadStream, promises, realpathSync } from "node:fs";
|
|
9
9
|
import path from "node:path";
|
|
@@ -3879,6 +3879,31 @@ var CalendarIndex = class {
|
|
|
3879
3879
|
//#endregion
|
|
3880
3880
|
//#region src/recorder/addon/config-store.ts
|
|
3881
3881
|
/**
|
|
3882
|
+
* Per-device recording-config persistence for the recorder addon.
|
|
3883
|
+
*
|
|
3884
|
+
* ONE ROW PER CAMERA in `recorder:recording-configs`, through
|
|
3885
|
+
* {@link RowMapStore}. Asking what camera 617 records is a primary-key lookup;
|
|
3886
|
+
* saving its config writes that row and touches no other.
|
|
3887
|
+
*
|
|
3888
|
+
* ## What this replaced, and why
|
|
3889
|
+
*
|
|
3890
|
+
* Until the 2026-08-19 flatten every camera's `RecordingConfig` lived in ONE
|
|
3891
|
+
* key of the recorder's `addon-settings` / `root` blob — a row that was 201 833
|
|
3892
|
+
* bytes on the reference hub, because the ops-log and the export history shared
|
|
3893
|
+
* it. So `loadDeviceConfig(617)` read and `JSON.parse`d 201 KB, and
|
|
3894
|
+
* `saveDeviceConfig` read that, merged, and rewrote it. The staging walk did it
|
|
3895
|
+
* once per device and lost 45–267 s of a boot to it (2026-08-18); teaching the
|
|
3896
|
+
* walk to read the map once capped the symptom, and this removes the cause.
|
|
3897
|
+
*
|
|
3898
|
+
* ## Failure direction
|
|
3899
|
+
*
|
|
3900
|
+
* `RecordingConfigSchema` rejects unknown keys so a stale caller fails loudly,
|
|
3901
|
+
* but a row written by an older build may still carry retired ones — `.strip()`
|
|
3902
|
+
* drops them. And validation is now PER ROW: one unparseable camera costs that
|
|
3903
|
+
* camera, where the blob's single `safeParse` took every camera down to the
|
|
3904
|
+
* empty fallback (= the whole fleet silently unconfigured).
|
|
3905
|
+
*/
|
|
3906
|
+
/**
|
|
3882
3907
|
* @durable class=config owner=recorder
|
|
3883
3908
|
* write="one row per camera, written by `saveDeviceConfig` (the `recording` cap's
|
|
3884
3909
|
* setConfig / band authoring) — the only writer"
|
|
@@ -3888,7 +3913,7 @@ var CalendarIndex = class {
|
|
|
3888
3913
|
var RECORDING_CONFIGS_COLLECTION = "recorder:recording-configs";
|
|
3889
3914
|
var RECORDING_CONFIGS_SPEC = {
|
|
3890
3915
|
collection: RECORDING_CONFIGS_COLLECTION,
|
|
3891
|
-
schema: RecordingConfigSchema.strip(),
|
|
3916
|
+
schema: preprocess((raw) => migrateLegacyDeviceSignalConfig(raw).value, RecordingConfigSchema.strip()),
|
|
3892
3917
|
columns: [
|
|
3893
3918
|
{
|
|
3894
3919
|
name: "deviceId",
|
|
@@ -3954,7 +3979,10 @@ async function loadDeviceConfig(state, deviceId) {
|
|
|
3954
3979
|
*/
|
|
3955
3980
|
function deviceIdsWithLostBands(configs) {
|
|
3956
3981
|
const lost = [];
|
|
3957
|
-
for (const [deviceId, config] of configs)
|
|
3982
|
+
for (const [deviceId, config] of configs) {
|
|
3983
|
+
if (config.deviceDecision === true) continue;
|
|
3984
|
+
if (config.enabled && config.bands.length === 0 && config.mode && config.mode !== "off") lost.push(deviceId);
|
|
3985
|
+
}
|
|
3958
3986
|
return lost.toSorted((a, b) => a - b);
|
|
3959
3987
|
}
|
|
3960
3988
|
/** Boot-time check: log the {@link deviceIdsWithLostBands} once, if any. */
|
|
@@ -3964,6 +3992,48 @@ async function warnLostBands(state, logger) {
|
|
|
3964
3992
|
logger.warn(`recording config: device(s) ${lost.join(", ")} claim a recording mode but have NO bands — a pre-retirement config that lost its legacy authoring fields. Nothing is recorded for them until their bands are re-authored.`);
|
|
3965
3993
|
}
|
|
3966
3994
|
/**
|
|
3995
|
+
* Persist the D371→D380 shape for every stored row — the migration, in code,
|
|
3996
|
+
* run once per boot and IDEMPOTENT: a second run finds no legacy key and
|
|
3997
|
+
* writes nothing.
|
|
3998
|
+
*
|
|
3999
|
+
* It reads the rows RAW ({@link RowMapStore.readAllRaw}) on purpose. The read
|
|
4000
|
+
* schema already migrates in memory, so by the time `readAll` answers there is
|
|
4001
|
+
* nothing left to recognise — and the retired key is stripped by a non-strict
|
|
4002
|
+
* `z.object`, so the migration would look like it had nothing to do on exactly
|
|
4003
|
+
* the row it exists for.
|
|
4004
|
+
*
|
|
4005
|
+
* Both outcomes are logged, because both change what a camera records and
|
|
4006
|
+
* silence would read as "nothing happened" — which is what a stripped key
|
|
4007
|
+
* looks like from the outside.
|
|
4008
|
+
*/
|
|
4009
|
+
async function migrateLegacyDeviceSignalRows(state, logger) {
|
|
4010
|
+
const migrated = [];
|
|
4011
|
+
const stripped = [];
|
|
4012
|
+
for (const [key, raw] of await state.readAllRaw()) {
|
|
4013
|
+
const outcome = migrateLegacyDeviceSignalConfig(raw);
|
|
4014
|
+
if (!outcome.migrated && !outcome.strippedOnly) continue;
|
|
4015
|
+
const deviceId = Number(key);
|
|
4016
|
+
if (!Number.isInteger(deviceId)) continue;
|
|
4017
|
+
const parsed = RecordingConfigSchema.strip().safeParse(outcome.value);
|
|
4018
|
+
if (!parsed.success) {
|
|
4019
|
+
logger.warn("recording config: legacy device-signal row could not be migrated", {
|
|
4020
|
+
tags: { deviceId },
|
|
4021
|
+
meta: { error: parsed.error.message }
|
|
4022
|
+
});
|
|
4023
|
+
continue;
|
|
4024
|
+
}
|
|
4025
|
+
await saveDeviceConfig(state, deviceId, parsed.data);
|
|
4026
|
+
if (outcome.migrated) migrated.push(deviceId);
|
|
4027
|
+
else stripped.push(deviceId);
|
|
4028
|
+
}
|
|
4029
|
+
if (migrated.length > 0) logger.info("recording config: migrated to the on-device-decision mode (the retired band trigger)", { meta: { deviceIds: migrated } });
|
|
4030
|
+
if (stripped.length > 0) logger.warn("recording config: a band mixed the retired device-signal trigger with others — the key was dropped and the band kept. These cameras no longer follow their own signal until the on-device-decision mode is selected for them.", { meta: { deviceIds: stripped } });
|
|
4031
|
+
return {
|
|
4032
|
+
migrated,
|
|
4033
|
+
stripped
|
|
4034
|
+
};
|
|
4035
|
+
}
|
|
4036
|
+
/**
|
|
3967
4037
|
* Persist (insert or replace) a device's config — ONE row. Validates against
|
|
3968
4038
|
* `RecordingConfigSchema` at the boundary (untrusted cap input). Returns the
|
|
3969
4039
|
* validated config that was persisted.
|
|
@@ -12456,6 +12526,13 @@ function bandActiveAt(band, date) {
|
|
|
12456
12526
|
if (s > e) return applies(wd) && t >= s || applies(prevWd) && t < e;
|
|
12457
12527
|
return applies(wd);
|
|
12458
12528
|
}
|
|
12529
|
+
/**
|
|
12530
|
+
* The band covering `date`, or null. GENERIC over the band type so the caller
|
|
12531
|
+
* gets back exactly what it put in: the recorder decides on `EffectiveBand`s
|
|
12532
|
+
* (`band-decision.ts`), which carry the one non-authored fact — that the DEVICE
|
|
12533
|
+
* decides — and a return type widened to `RecordingBand` would erase it right
|
|
12534
|
+
* where the gates read it.
|
|
12535
|
+
*/
|
|
12459
12536
|
function activeBandAt(config, date) {
|
|
12460
12537
|
return config.bands.find((b) => bandActiveAt(b, date)) ?? null;
|
|
12461
12538
|
}
|
|
@@ -12480,6 +12557,37 @@ function activeBandAt(config, date) {
|
|
|
12480
12557
|
* unit-testable without ffmpeg, the broker, the event bus, or a real wall clock.
|
|
12481
12558
|
*/
|
|
12482
12559
|
/**
|
|
12560
|
+
* THE band a `deviceDecision` config decides through: always on (every day,
|
|
12561
|
+
* `start === end` — the band engine's always-on shape), `events`, and listening
|
|
12562
|
+
* to exactly one source, the camera's own level.
|
|
12563
|
+
*
|
|
12564
|
+
* Its buffers are the canonical pad ({@link DEFAULT_EVENTS_BAND_BUFFER_SEC}),
|
|
12565
|
+
* not per-camera knobs: this mode's whole contract with the operator is ONE
|
|
12566
|
+
* flag. The pad only ever retains footage around an episode the device itself
|
|
12567
|
+
* delimited, so there is nothing here for an operator to tune.
|
|
12568
|
+
*/
|
|
12569
|
+
var DEVICE_DECISION_BAND = Object.freeze({
|
|
12570
|
+
days: [],
|
|
12571
|
+
start: "00:00",
|
|
12572
|
+
end: "00:00",
|
|
12573
|
+
mode: "events",
|
|
12574
|
+
deviceSignal: true,
|
|
12575
|
+
preBufferSec: DEFAULT_EVENTS_BAND_BUFFER_SEC.preBufferSec,
|
|
12576
|
+
postBufferSec: DEFAULT_EVENTS_BAND_BUFFER_SEC.postBufferSec
|
|
12577
|
+
});
|
|
12578
|
+
/**
|
|
12579
|
+
* THE bands the recorder decides on for a config — the ONE place
|
|
12580
|
+
* `config.bands` is turned into what the gates read.
|
|
12581
|
+
*
|
|
12582
|
+
* `deviceDecision` resolves to {@link DEVICE_DECISION_BAND} and to nothing
|
|
12583
|
+
* else; every other config is its own authored bands, byte for byte. Because
|
|
12584
|
+
* the schema makes the two exclusive, this is a choice and never a merge.
|
|
12585
|
+
*/
|
|
12586
|
+
function effectiveBands(config) {
|
|
12587
|
+
if (config.deviceDecision === true) return [DEVICE_DECISION_BAND];
|
|
12588
|
+
return config.bands ?? [];
|
|
12589
|
+
}
|
|
12590
|
+
/**
|
|
12483
12591
|
* THE one place a band's pre/post buffers are read. An ABSENT field takes
|
|
12484
12592
|
* {@link DEFAULT_EVENTS_BAND_BUFFER_SEC}; an explicit value — including `0` —
|
|
12485
12593
|
* is honoured verbatim.
|
|
@@ -12520,6 +12628,9 @@ function triggerKey(source) {
|
|
|
12520
12628
|
case "signal": return "signal";
|
|
12521
12629
|
}
|
|
12522
12630
|
}
|
|
12631
|
+
/** The single source {@link DEVICE_DECISION_BAND} listens to, shared so the
|
|
12632
|
+
* band never allocates a new one per call. */
|
|
12633
|
+
var SIGNAL_SOURCES = Object.freeze([{ kind: "signal" }]);
|
|
12523
12634
|
/**
|
|
12524
12635
|
* LE sorgenti che questa banda ascolta — l'unico posto dove i `triggers` di
|
|
12525
12636
|
* una banda diventano `TriggerSource[]`.
|
|
@@ -12535,6 +12646,7 @@ function triggerKey(source) {
|
|
|
12535
12646
|
* denuncia invece di restare zitto.
|
|
12536
12647
|
*/
|
|
12537
12648
|
function bandTriggerSources(band) {
|
|
12649
|
+
if (band.deviceSignal === true) return SIGNAL_SOURCES;
|
|
12538
12650
|
const t = band.triggers;
|
|
12539
12651
|
if (t === void 0) return [];
|
|
12540
12652
|
const sources = [];
|
|
@@ -12548,7 +12660,6 @@ function bandTriggerSources(band) {
|
|
|
12548
12660
|
kind: "sensor",
|
|
12549
12661
|
sourceDeviceId
|
|
12550
12662
|
});
|
|
12551
|
-
if (t.deviceSignal === true) sources.push({ kind: "signal" });
|
|
12552
12663
|
return sources;
|
|
12553
12664
|
}
|
|
12554
12665
|
/**
|
|
@@ -12734,8 +12845,8 @@ function eventsBandDemanded(band, triggers, atMs) {
|
|
|
12734
12845
|
*/
|
|
12735
12846
|
function shouldRecordAt(config, triggers, at) {
|
|
12736
12847
|
if (!config.enabled) return false;
|
|
12737
|
-
const bands = config
|
|
12738
|
-
if (
|
|
12848
|
+
const bands = effectiveBands(config);
|
|
12849
|
+
if (bands.length === 0) return false;
|
|
12739
12850
|
const band = activeBandAt({ bands }, at);
|
|
12740
12851
|
if (!band) return false;
|
|
12741
12852
|
if (band.mode === "continuous") return true;
|
|
@@ -12990,8 +13101,8 @@ function candidateEdgesMs(bands, nowMs) {
|
|
|
12990
13101
|
* costs one wasted wake-up and never costs footage.
|
|
12991
13102
|
*/
|
|
12992
13103
|
function nextBandEdgeMs(config, nowMs) {
|
|
12993
|
-
const bands = config
|
|
12994
|
-
if (
|
|
13104
|
+
const bands = effectiveBands(config);
|
|
13105
|
+
if (bands.length === 0) return null;
|
|
12995
13106
|
const current = activeBandAt({ bands }, new Date(nowMs));
|
|
12996
13107
|
const candidates = [...new Set(candidateEdgesMs(bands, nowMs))].filter((ms) => ms > nowMs).toSorted((a, b) => a - b);
|
|
12997
13108
|
for (const ms of candidates) if (activeBandAt({ bands }, new Date(ms)) !== current) return ms;
|
|
@@ -13026,8 +13137,8 @@ function eventsWindowCloseMs(band, triggers, nowMs) {
|
|
|
13026
13137
|
function nextDecisionChangeAt(input) {
|
|
13027
13138
|
const { config, triggers, nowMs } = input;
|
|
13028
13139
|
if (!config.enabled) return null;
|
|
13029
|
-
const bands = config
|
|
13030
|
-
if (
|
|
13140
|
+
const bands = effectiveBands(config);
|
|
13141
|
+
if (bands.length === 0) return null;
|
|
13031
13142
|
const band = activeBandAt({ bands }, new Date(nowMs));
|
|
13032
13143
|
const edgeMs = nextBandEdgeMs(config, nowMs);
|
|
13033
13144
|
const closeMs = band === null ? null : eventsWindowCloseMs(band, triggers, nowMs);
|
|
@@ -14497,7 +14608,7 @@ var RecordingController = class {
|
|
|
14497
14608
|
const config = await this.deps.loadConfig(deviceId);
|
|
14498
14609
|
if (config.enabled !== true) return;
|
|
14499
14610
|
const nowMs = this.now();
|
|
14500
|
-
const band = activeBandAt({ bands: config
|
|
14611
|
+
const band = activeBandAt({ bands: effectiveBands(config) }, new Date(nowMs));
|
|
14501
14612
|
if (!band || band.mode !== "events") return;
|
|
14502
14613
|
const { postMs } = resolveBandBufferMs(band);
|
|
14503
14614
|
const sinceMs = nowMs - postMs - TRIGGER_HISTORY_MARGIN_MS;
|
|
@@ -14904,7 +15015,7 @@ var RecordingController = class {
|
|
|
14904
15015
|
if (this.stopped) return;
|
|
14905
15016
|
let band;
|
|
14906
15017
|
try {
|
|
14907
|
-
band = activeBandAt({ bands: (await this.deps.loadConfig(deviceId))
|
|
15018
|
+
band = activeBandAt({ bands: effectiveBands(await this.deps.loadConfig(deviceId)) }, new Date(atMs));
|
|
14908
15019
|
} catch (err) {
|
|
14909
15020
|
this.deps.logger.warn("recorder: audio trigger qualification skipped — config read failed", {
|
|
14910
15021
|
tags: { deviceId },
|
|
@@ -14929,7 +15040,7 @@ var RecordingController = class {
|
|
|
14929
15040
|
*/
|
|
14930
15041
|
async postBufferMsFor(deviceId, atMs) {
|
|
14931
15042
|
try {
|
|
14932
|
-
const band = activeBandAt({ bands: (await this.deps.loadConfig(deviceId))
|
|
15043
|
+
const band = activeBandAt({ bands: effectiveBands(await this.deps.loadConfig(deviceId)) }, new Date(atMs));
|
|
14933
15044
|
if (band) return resolveBandBufferMs(band).postMs;
|
|
14934
15045
|
} catch (err) {
|
|
14935
15046
|
this.deps.logger.warn("recorder: trigger history using the DEFAULT post-buffer — config read failed", {
|
|
@@ -15020,7 +15131,7 @@ var RecordingController = class {
|
|
|
15020
15131
|
reportUnrecordable(deviceId, config) {
|
|
15021
15132
|
if (!config.enabled) return;
|
|
15022
15133
|
if (this.unrecordableReported.has(deviceId)) return;
|
|
15023
|
-
const bands = config
|
|
15134
|
+
const bands = effectiveBands(config);
|
|
15024
15135
|
if (bands.length === 0) {
|
|
15025
15136
|
this.unrecordableReported.add(deviceId);
|
|
15026
15137
|
this.deps.logger.warn("recorder: device is enabled but has no recording bands — nothing will ever be recorded", { tags: { deviceId } });
|
|
@@ -15357,7 +15468,7 @@ var RecordingController = class {
|
|
|
15357
15468
|
*/
|
|
15358
15469
|
async handleFinalizedSegment(deviceId, profile, placement, attach, startMs, durMs, flatAbsPath) {
|
|
15359
15470
|
try {
|
|
15360
|
-
const band = activeBandAt({ bands: (await this.deps.loadConfig(deviceId))
|
|
15471
|
+
const band = activeBandAt({ bands: effectiveBands(await this.deps.loadConfig(deviceId)) }, new Date(startMs + durMs));
|
|
15361
15472
|
const triggers = this.triggersFor(deviceId);
|
|
15362
15473
|
if (band?.mode === "events" && !segmentRetainedForEvents(startMs, startMs + durMs, band, triggers, attach)) {
|
|
15363
15474
|
this.reportDiscardedSegment(deviceId, profile, attach, band, triggers, startMs, durMs);
|
|
@@ -17361,7 +17472,9 @@ var RecorderV2Addon = class extends BaseAddon {
|
|
|
17361
17472
|
watchIntervalMs: this.config.watchIntervalMs
|
|
17362
17473
|
}
|
|
17363
17474
|
});
|
|
17364
|
-
|
|
17475
|
+
migrateLegacyDeviceSignalRows(this.configStore(), this.ctx.logger).catch((err) => {
|
|
17476
|
+
this.ctx.logger.warn("recorder: device-signal config migration failed", { meta: { error: errMsg(err) } });
|
|
17477
|
+
}).then(() => warnLostBands(this.configStore(), this.ctx.logger));
|
|
17365
17478
|
const providers = [
|
|
17366
17479
|
{
|
|
17367
17480
|
capability: recordingCapability,
|
|
@@ -91,6 +91,25 @@ var RowMapStore = class RowMapStore {
|
|
|
91
91
|
} });
|
|
92
92
|
return out;
|
|
93
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Every entry as it was WRITTEN, unvalidated and unparsed — the read a
|
|
96
|
+
* MIGRATION needs.
|
|
97
|
+
*
|
|
98
|
+
* {@link readAll} answers through the CURRENT schema, which is exactly what a
|
|
99
|
+
* migration must not do: a retired key is stripped by a non-strict `z.object`
|
|
100
|
+
* before the migration could see it, so the row it is there to rescue looks
|
|
101
|
+
* like a row that never needed rescuing. Only a migration should call this;
|
|
102
|
+
* everything else wants the validated read.
|
|
103
|
+
*/
|
|
104
|
+
async readAllRaw() {
|
|
105
|
+
const records = await this.store.query.query({
|
|
106
|
+
collection: this.spec.collection,
|
|
107
|
+
filter: { limit: this.spec.loadLimit }
|
|
108
|
+
});
|
|
109
|
+
const out = /* @__PURE__ */ new Map();
|
|
110
|
+
for (const record of records) out.set(record.id, record.data[ROW_MAP_VALUE_COLUMN]);
|
|
111
|
+
return out;
|
|
112
|
+
}
|
|
94
113
|
/** Insert or replace ONE entry. Validates at the boundary. */
|
|
95
114
|
async write(key, value) {
|
|
96
115
|
const validated = this.spec.schema.parse(value);
|
|
@@ -91,6 +91,25 @@ var RowMapStore = class RowMapStore {
|
|
|
91
91
|
} });
|
|
92
92
|
return out;
|
|
93
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Every entry as it was WRITTEN, unvalidated and unparsed — the read a
|
|
96
|
+
* MIGRATION needs.
|
|
97
|
+
*
|
|
98
|
+
* {@link readAll} answers through the CURRENT schema, which is exactly what a
|
|
99
|
+
* migration must not do: a retired key is stripped by a non-strict `z.object`
|
|
100
|
+
* before the migration could see it, so the row it is there to rescue looks
|
|
101
|
+
* like a row that never needed rescuing. Only a migration should call this;
|
|
102
|
+
* everything else wants the validated read.
|
|
103
|
+
*/
|
|
104
|
+
async readAllRaw() {
|
|
105
|
+
const records = await this.store.query.query({
|
|
106
|
+
collection: this.spec.collection,
|
|
107
|
+
filter: { limit: this.spec.loadLimit }
|
|
108
|
+
});
|
|
109
|
+
const out = /* @__PURE__ */ new Map();
|
|
110
|
+
for (const record of records) out.set(record.id, record.data[ROW_MAP_VALUE_COLUMN]);
|
|
111
|
+
return out;
|
|
112
|
+
}
|
|
94
113
|
/** Insert or replace ONE entry. Validates at the boundary. */
|
|
95
114
|
async write(key, value) {
|
|
96
115
|
const validated = this.spec.schema.parse(value);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as __toESM, t as __commonJSMin } from "./chunk-DnnnRqeS.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { Dt as errMsg } from "./dist-Y4BsF_EC.mjs";
|
|
3
3
|
import { spawn } from "node:child_process";
|
|
4
4
|
//#region ../../node_modules/mp4box/dist/mp4box.all.js
|
|
5
5
|
var require_mp4box_all = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_dist = require("./dist-
|
|
1
|
+
const require_dist = require("./dist-CBa1j3On.js");
|
|
2
2
|
let node_child_process = require("node:child_process");
|
|
3
3
|
//#region ../../node_modules/mp4box/dist/mp4box.all.js
|
|
4
4
|
var require_mp4box_all = /* @__PURE__ */ require_dist.__commonJSMin(((exports) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_worker_protocol = require("../worker-protocol-
|
|
3
|
-
const require_lazy_sharp = require("../lazy-sharp-
|
|
2
|
+
const require_worker_protocol = require("../worker-protocol-CXsdriRX.js");
|
|
3
|
+
const require_lazy_sharp = require("../lazy-sharp-CS5WE9mI.js");
|
|
4
4
|
//#region src/session-decode/color-conversion.ts
|
|
5
5
|
/**
|
|
6
6
|
* Explicit YUV→RGB colorspace/range resolution for the session-decode worker.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as formatNativeLeaseKnobs, n as isWorkerRequest, o as resolveNativeLeaseKnobs, r as logLevelForLine } from "../worker-protocol-
|
|
1
|
+
import { i as formatNativeLeaseKnobs, n as isWorkerRequest, o as resolveNativeLeaseKnobs, r as logLevelForLine } from "../worker-protocol-_7zrToTo.mjs";
|
|
2
2
|
import { n as setSharpWarnSink, r as hostExternalEntryUrls, t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
|
|
3
3
|
//#region src/session-decode/color-conversion.ts
|
|
4
4
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as e, c as t, d as n, f as r, i, l as a, n as o, o as s, p as c, r as l, s as u, t as d, u as f } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-
|
|
1
|
+
import { a as e, c as t, d as n, f as r, i, l as a, n as o, o as s, p as c, r as l, s as u, t as d, u as f } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Dj_qoc1e.mjs";
|
|
2
2
|
import { a as p, i as m, n as h, o as g, r as _, t as v } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.js-C9j-2lBe.mjs";
|
|
3
3
|
import { n as y, r as b, t as x } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-XO0-Pyu6.mjs";
|
|
4
|
-
import { t as S } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-
|
|
4
|
+
import { t as S } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Cv5McbTI.mjs";
|
|
5
5
|
import { n as C, t as w } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-BO7TIbJV.mjs";
|
|
6
6
|
//#region ../../node_modules/lucide-react/dist/esm/shared/src/utils.js
|
|
7
7
|
var T = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), E = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), D = (e) => {
|