@camstack/addon-osd-manager 0.1.239 → 0.1.241
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/{MotionZonesSettings-BU-acK9Z.mjs → MotionZonesSettings-G8UCebu1.mjs} +2 -2
- package/dist/{PrivacyMaskSettings-DMXiC1dM.mjs → PrivacyMaskSettings-2NTC9B3W.mjs} +4 -4
- package/dist/{SceneMonitorEditor-ePI2t_wT.mjs → SceneMonitorEditor-ByMmaROK.mjs} +3 -3
- package/dist/_stub.js +2763 -2729
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-CNlBultD.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-BBDNfcPI.mjs} +3 -3
- package/dist/{_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DkfPNoLU.mjs → _virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BFkoKPX3.mjs} +1 -1
- package/dist/{hostInit-CTiW6F1s.mjs → hostInit-DCTyM4Bh.mjs} +2 -2
- package/dist/index.js +189 -26
- package/dist/index.mjs +189 -26
- package/dist/{player-overlays-B4efNR1A.mjs → player-overlays-B9Leo3bK.mjs} +1 -1
- package/dist/remoteEntry.js +1 -1
- package/dist/{responsive-CvSyX7h3.mjs → responsive-DCFnF6WM.mjs} +1 -1
- package/dist/{scene-monitor-copy-QAemI7ef.mjs → scene-monitor-copy-B3PBzmS-.mjs} +1 -1
- package/dist/{square-BG-oZkZc.mjs → square-CvNDzXRw.mjs} +1 -1
- package/dist/{trash-2-DvemWMy7.mjs → trash-2-DHcGMoei.mjs} +1 -1
- package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-CbjSvUsn.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-qRoXJuGX.mjs} +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5390,7 +5390,7 @@ var ZodIssueCode = {
|
|
|
5390
5390
|
var ZodFirstPartyTypeKind;
|
|
5391
5391
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5392
5392
|
//#endregion
|
|
5393
|
-
//#region ../types/dist/sleep-
|
|
5393
|
+
//#region ../types/dist/sleep-bwsTj221.mjs
|
|
5394
5394
|
/**
|
|
5395
5395
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5396
5396
|
* window to float samples (D455).
|
|
@@ -6641,7 +6641,6 @@ function createHandle(raw, opts) {
|
|
|
6641
6641
|
const writeAddon = (patch) => write("addon", opts.addonTree(), void 0, patch, () => readStoredAddonBlob(raw), (p) => raw.writeAddonStore(p));
|
|
6642
6642
|
const readAddonStoreResult = raw.readAddonStoreResult;
|
|
6643
6643
|
const readAddonStoreKeyResult = raw.readAddonStoreKeyResult;
|
|
6644
|
-
const readDeviceStoreBatch = raw.readDeviceStoreBatch;
|
|
6645
6644
|
const overrides = {
|
|
6646
6645
|
readAddonStore: async () => resolveRead("addon", await raw.readAddonStore()),
|
|
6647
6646
|
...readAddonStoreResult !== void 0 ? { readAddonStoreResult: async () => {
|
|
@@ -6665,12 +6664,12 @@ function createHandle(raw, opts) {
|
|
|
6665
6664
|
};
|
|
6666
6665
|
} } : {},
|
|
6667
6666
|
readDeviceStore: async (deviceId) => resolveRead(`device:${deviceId}`, await raw.readDeviceStore(deviceId)),
|
|
6668
|
-
|
|
6669
|
-
const rows = await readDeviceStoreBatch
|
|
6667
|
+
readDeviceStoreBatch: async (deviceIds) => {
|
|
6668
|
+
const rows = await raw.readDeviceStoreBatch(deviceIds);
|
|
6670
6669
|
const out = /* @__PURE__ */ new Map();
|
|
6671
6670
|
for (const [deviceId, blob] of rows) out.set(deviceId, await resolveRead(`device:${deviceId}`, blob));
|
|
6672
6671
|
return out;
|
|
6673
|
-
}
|
|
6672
|
+
},
|
|
6674
6673
|
writeAddonStore: async (patch) => {
|
|
6675
6674
|
await writeAddon(patch);
|
|
6676
6675
|
},
|
|
@@ -7497,7 +7496,7 @@ var BaseAddon = class {
|
|
|
7497
7496
|
return this._addonSecretTree;
|
|
7498
7497
|
}
|
|
7499
7498
|
deviceSecretTree() {
|
|
7500
|
-
this._deviceSecretTree ??= secretTreeFromSchema(this.deviceSettingsSchema());
|
|
7499
|
+
this._deviceSecretTree ??= mergeSecretStatePaths(secretTreeFromSchema(this.deviceSettingsSchema()), this.secretStatePaths);
|
|
7501
7500
|
return this._deviceSecretTree;
|
|
7502
7501
|
}
|
|
7503
7502
|
/**
|
|
@@ -7573,42 +7572,135 @@ var BaseAddon = class {
|
|
|
7573
7572
|
this[timerOf] = timer;
|
|
7574
7573
|
}
|
|
7575
7574
|
/**
|
|
7576
|
-
* Wrap `ctx.settings.readAddonStore()` with a
|
|
7577
|
-
*
|
|
7578
|
-
* swap, or any race where the SqliteSettingsBackend is between shutdown and
|
|
7579
|
-
* re-initialize) doesn't propagate up into `initialize()` and leave the
|
|
7575
|
+
* Wrap `ctx.settings.readAddonStore()` with a retry budget so a transient
|
|
7576
|
+
* settings-store outage doesn't propagate up into `initialize()` and leave the
|
|
7580
7577
|
* addon permanently broken.
|
|
7581
7578
|
*
|
|
7582
|
-
*
|
|
7583
|
-
*
|
|
7584
|
-
* `
|
|
7579
|
+
* Two kinds of outage, two budgets:
|
|
7580
|
+
* - the store's own restart fingerprints (`SqliteSettingsBackend not
|
|
7581
|
+
* initialized`, `provider not available`): a short budget, then the addon
|
|
7582
|
+
* falls back to `{}` (defaults) - its first successful patch rehydrates;
|
|
7583
|
+
* - a TRANSPORT failure (the hub is restarting while this runner boots:
|
|
7584
|
+
* `discovery deadline exceeded`, `parent could not route`, a refused or
|
|
7585
|
+
* timed-out connection). Since D870 a runner's settings read THROWS instead
|
|
7586
|
+
* of answering `{}`, so without a budget a hub restart ends in a respawn
|
|
7587
|
+
* loop. A long, bounded budget; only after it the error propagates - the
|
|
7588
|
+
* addon never runs on defaults for a store it could not ask.
|
|
7589
|
+
* Anything else propagates immediately so real bugs surface.
|
|
7585
7590
|
*/
|
|
7586
7591
|
async readAddonStoreWithRetry() {
|
|
7587
7592
|
const settings = this.rawSettings();
|
|
7588
7593
|
if (!settings) return {};
|
|
7589
|
-
const delaysMs = [
|
|
7590
|
-
150,
|
|
7591
|
-
350,
|
|
7592
|
-
600,
|
|
7593
|
-
900
|
|
7594
|
-
];
|
|
7595
7594
|
let lastErr;
|
|
7596
|
-
for (let attempt = 0
|
|
7595
|
+
for (let attempt = 0;; attempt++) try {
|
|
7597
7596
|
const stored = await settings.readAddonStore() ?? {};
|
|
7598
7597
|
this.settingsStoreReady = true;
|
|
7599
7598
|
return stored;
|
|
7600
7599
|
} catch (err) {
|
|
7601
7600
|
lastErr = err;
|
|
7602
|
-
const
|
|
7603
|
-
if (
|
|
7604
|
-
|
|
7605
|
-
|
|
7601
|
+
const kind = classifyStoreError(err);
|
|
7602
|
+
if (kind === "permanent") throw err;
|
|
7603
|
+
const delay = (kind === "transport" ? TRANSPORT_RETRY_DELAYS_MS : RESTART_RETRY_DELAYS_MS)[attempt];
|
|
7604
|
+
if (delay === void 0) {
|
|
7605
|
+
if (kind === "transport") throw err;
|
|
7606
|
+
break;
|
|
7607
|
+
}
|
|
7608
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
7606
7609
|
}
|
|
7607
7610
|
this.settingsStoreReady = false;
|
|
7608
7611
|
this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
|
|
7609
7612
|
return {};
|
|
7610
7613
|
}
|
|
7611
7614
|
};
|
|
7615
|
+
/** The settings store's own restart fingerprints. */
|
|
7616
|
+
var RESTART_RETRY_DELAYS_MS = [
|
|
7617
|
+
150,
|
|
7618
|
+
350,
|
|
7619
|
+
600,
|
|
7620
|
+
900
|
|
7621
|
+
];
|
|
7622
|
+
/** A hub restarting under a booting runner: ~100 s in total. */
|
|
7623
|
+
var TRANSPORT_RETRY_DELAYS_MS = [
|
|
7624
|
+
150,
|
|
7625
|
+
350,
|
|
7626
|
+
600,
|
|
7627
|
+
900,
|
|
7628
|
+
2e3,
|
|
7629
|
+
5e3,
|
|
7630
|
+
1e4,
|
|
7631
|
+
2e4,
|
|
7632
|
+
3e4,
|
|
7633
|
+
3e4
|
|
7634
|
+
];
|
|
7635
|
+
var RESTART_FINGERPRINTS = ["SqliteSettingsBackend not initialized", "provider not available"];
|
|
7636
|
+
/** Node / socket error codes of a connection that did not happen or broke. */
|
|
7637
|
+
var TRANSPORT_CODES = new Set([
|
|
7638
|
+
"ECONNREFUSED",
|
|
7639
|
+
"ECONNRESET",
|
|
7640
|
+
"ETIMEDOUT",
|
|
7641
|
+
"EPIPE",
|
|
7642
|
+
"EHOSTUNREACH",
|
|
7643
|
+
"ENETUNREACH"
|
|
7644
|
+
]);
|
|
7645
|
+
/** tRPC error codes that mean "the other side is not answering now", not "your call is wrong". */
|
|
7646
|
+
var UNAVAILABLE_TRPC_CODES = new Set([
|
|
7647
|
+
"TIMEOUT",
|
|
7648
|
+
"SERVICE_UNAVAILABLE",
|
|
7649
|
+
"BAD_GATEWAY",
|
|
7650
|
+
"GATEWAY_TIMEOUT"
|
|
7651
|
+
]);
|
|
7652
|
+
/** The exact phrases OUR transport raises when it cannot reach the hub. */
|
|
7653
|
+
var TRANSPORT_PHRASES = [
|
|
7654
|
+
"discovery deadline exceeded",
|
|
7655
|
+
"parent could not route child unowned cap call",
|
|
7656
|
+
"UDS request timed out after",
|
|
7657
|
+
"channel closed"
|
|
7658
|
+
];
|
|
7659
|
+
/** Moleculer error `type`s of a call that could not be served right now. */
|
|
7660
|
+
var MOLECULER_TRANSIENT_TYPES = new Set([
|
|
7661
|
+
"REQUEST_TIMEOUT",
|
|
7662
|
+
"SERVICE_NOT_FOUND",
|
|
7663
|
+
"SERVICE_NOT_AVAILABLE",
|
|
7664
|
+
"REQUEST_REJECTED",
|
|
7665
|
+
"BROKER_DISCONNECTED"
|
|
7666
|
+
]);
|
|
7667
|
+
function stringProp(value, key) {
|
|
7668
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
7669
|
+
const found = Reflect.get(value, key);
|
|
7670
|
+
return typeof found === "string" ? found : void 0;
|
|
7671
|
+
}
|
|
7672
|
+
/** The code an error carries: its own, its cause's, or a tRPC `data.code`. */
|
|
7673
|
+
function errorCode(err) {
|
|
7674
|
+
const out = {};
|
|
7675
|
+
const cause = typeof err === "object" && err !== null ? Reflect.get(err, "cause") : void 0;
|
|
7676
|
+
const data = typeof err === "object" && err !== null ? Reflect.get(err, "data") : void 0;
|
|
7677
|
+
const node = stringProp(err, "code") ?? stringProp(cause, "code");
|
|
7678
|
+
if (node !== void 0) out.node = node;
|
|
7679
|
+
const trpc = stringProp(data, "code");
|
|
7680
|
+
if (trpc !== void 0) out.trpc = trpc;
|
|
7681
|
+
return out;
|
|
7682
|
+
}
|
|
7683
|
+
/**
|
|
7684
|
+
* Is a settings read failure worth retrying, and with which budget? Only
|
|
7685
|
+
* EXPLICIT signals count: a socket error code, a tRPC "unavailable" code, or
|
|
7686
|
+
* one of the exact phrases our own transport raises. A message that merely
|
|
7687
|
+
* contains "timed out" or "unreachable" is not evidence of anything, and
|
|
7688
|
+
* `settings store not wired` is a wiring bug that retrying cannot fix.
|
|
7689
|
+
*/
|
|
7690
|
+
function classifyStoreError(err) {
|
|
7691
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
7692
|
+
if (RESTART_FINGERPRINTS.some((f) => message.includes(f))) return "restart";
|
|
7693
|
+
const code = errorCode(err);
|
|
7694
|
+
if (code.node !== void 0 && TRANSPORT_CODES.has(code.node)) return "transport";
|
|
7695
|
+
if (code.trpc !== void 0 && UNAVAILABLE_TRPC_CODES.has(code.trpc)) return "transport";
|
|
7696
|
+
if (typeof err === "object" && err !== null) {
|
|
7697
|
+
if (Reflect.get(err, "retryable") === true) return "transport";
|
|
7698
|
+
const type = stringProp(err, "type");
|
|
7699
|
+
if (type !== void 0 && MOLECULER_TRANSIENT_TYPES.has(type)) return "transport";
|
|
7700
|
+
}
|
|
7701
|
+
if (TRANSPORT_PHRASES.some((f) => message.includes(f))) return "transport";
|
|
7702
|
+
return "permanent";
|
|
7703
|
+
}
|
|
7612
7704
|
/**
|
|
7613
7705
|
* Collect the keys of every field marked `perNode: true`, recursing into
|
|
7614
7706
|
* layout containers (`group` fields and `sub-tabs` tabs) the same way
|
|
@@ -8163,7 +8255,7 @@ object({
|
|
|
8163
8255
|
params: record(string(), union([string(), number()])).optional()
|
|
8164
8256
|
});
|
|
8165
8257
|
//#endregion
|
|
8166
|
-
//#region ../types/dist/err-msg
|
|
8258
|
+
//#region ../types/dist/err-msg--2RrYiLO.mjs
|
|
8167
8259
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
8168
8260
|
DeviceType["Camera"] = "camera";
|
|
8169
8261
|
DeviceType["Hub"] = "hub";
|
|
@@ -8432,6 +8524,9 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
8432
8524
|
/** Virtual HA toggle (input_boolean.*) — distinguishable from a
|
|
8433
8525
|
* real Switch device for UI rendering / export adapters. */
|
|
8434
8526
|
DeviceRole["BinaryHelper"] = "binary-helper";
|
|
8527
|
+
/** A smart plug: a `switch` whose source says it is an outlet (HA
|
|
8528
|
+
* `device_class: outlet`). The Alexa export shows it as a SMARTPLUG. */
|
|
8529
|
+
DeviceRole["Outlet"] = "outlet";
|
|
8435
8530
|
/** Generic motion / occupancy / moving event source. Distinct from
|
|
8436
8531
|
* the camera accessory PirSensor role: that one is a camera child;
|
|
8437
8532
|
* this is a standalone HA / 3rd-party motion sensor. */
|
|
@@ -8499,7 +8594,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
8499
8594
|
return DeviceRole;
|
|
8500
8595
|
}({});
|
|
8501
8596
|
//#endregion
|
|
8502
|
-
//#region ../types/dist/composition-
|
|
8597
|
+
//#region ../types/dist/composition-DOwQB_Ua.mjs
|
|
8503
8598
|
/**
|
|
8504
8599
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
8505
8600
|
*
|
|
@@ -15838,6 +15933,28 @@ id: union([string(), number()]) }), {
|
|
|
15838
15933
|
kind: "mutation",
|
|
15839
15934
|
auth: "admin"
|
|
15840
15935
|
});
|
|
15936
|
+
/** One table of the settings database. */
|
|
15937
|
+
var StorageTableSchema = object({
|
|
15938
|
+
/** The table's full name, e.g. `recorder:addon-settings` or `addon-device-settings`. */
|
|
15939
|
+
name: string(),
|
|
15940
|
+
/** The owner prefix of a scoped name (`recorder` for `recorder:addon-settings`), else null. */
|
|
15941
|
+
owner: string().nullable(),
|
|
15942
|
+
rows: number().int().nonnegative(),
|
|
15943
|
+
/** Bytes the table's pages occupy (`dbstat`); null when the engine cannot measure. */
|
|
15944
|
+
bytes: number().int().nonnegative().nullable(),
|
|
15945
|
+
/** Declared by an addon since this engine process started (a running addon claims it). */
|
|
15946
|
+
declaredThisBoot: boolean()
|
|
15947
|
+
});
|
|
15948
|
+
method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: array(StorageTableSchema) }), { auth: "admin" }), method(object({
|
|
15949
|
+
collection: string().min(1),
|
|
15950
|
+
expectRows: number().int().nonnegative()
|
|
15951
|
+
}), object({
|
|
15952
|
+
dropped: literal(true),
|
|
15953
|
+
rows: number().int().nonnegative()
|
|
15954
|
+
}), {
|
|
15955
|
+
kind: "mutation",
|
|
15956
|
+
auth: "admin"
|
|
15957
|
+
});
|
|
15841
15958
|
/**
|
|
15842
15959
|
* `keychain` — the hub's encrypted store of secret values (D787).
|
|
15843
15960
|
*
|
|
@@ -16379,6 +16496,16 @@ method(object({}), KeychainStatusSchema, { auth: "admin" }), method(object({}),
|
|
|
16379
16496
|
kind: "mutation",
|
|
16380
16497
|
auth: "admin",
|
|
16381
16498
|
caller: "required"
|
|
16499
|
+
}), method(object({
|
|
16500
|
+
ref: string().min(1),
|
|
16501
|
+
value: string().min(1)
|
|
16502
|
+
}), object({
|
|
16503
|
+
ref: string(),
|
|
16504
|
+
version: number().int()
|
|
16505
|
+
}), {
|
|
16506
|
+
kind: "mutation",
|
|
16507
|
+
auth: "admin",
|
|
16508
|
+
caller: "required"
|
|
16382
16509
|
}), method(object({ refs: array(string().min(1)).max(1e3) }), object({
|
|
16383
16510
|
deleted: array(string()).readonly(),
|
|
16384
16511
|
kept: array(object({
|
|
@@ -53437,6 +53564,12 @@ object({
|
|
|
53437
53564
|
/** Horizontal louver swing on/off. Null when the device has no
|
|
53438
53565
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
53439
53566
|
swingHorizontal: boolean().nullable(),
|
|
53567
|
+
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
53568
|
+
minTemp: number().nullable().optional(),
|
|
53569
|
+
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
53570
|
+
maxTemp: number().nullable().optional(),
|
|
53571
|
+
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
53572
|
+
tempStep: number().positive().nullable().optional(),
|
|
53440
53573
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
53441
53574
|
lastFetchedAt: number()
|
|
53442
53575
|
});
|
|
@@ -64722,6 +64855,12 @@ Object.freeze({
|
|
|
64722
64855
|
addonId: null,
|
|
64723
64856
|
access: "create"
|
|
64724
64857
|
},
|
|
64858
|
+
"keychainAdmin.importSecret": {
|
|
64859
|
+
capName: "keychain-admin",
|
|
64860
|
+
capScope: "system",
|
|
64861
|
+
addonId: null,
|
|
64862
|
+
access: "create"
|
|
64863
|
+
},
|
|
64725
64864
|
"keychainAdmin.listAudit": {
|
|
64726
64865
|
capName: "keychain-admin",
|
|
64727
64866
|
capScope: "system",
|
|
@@ -68508,6 +68647,18 @@ Object.freeze({
|
|
|
68508
68647
|
addonId: null,
|
|
68509
68648
|
access: "create"
|
|
68510
68649
|
},
|
|
68650
|
+
"storageAdmin.dropCollection": {
|
|
68651
|
+
capName: "storage-admin",
|
|
68652
|
+
capScope: "system",
|
|
68653
|
+
addonId: null,
|
|
68654
|
+
access: "delete"
|
|
68655
|
+
},
|
|
68656
|
+
"storageAdmin.listTables": {
|
|
68657
|
+
capName: "storage-admin",
|
|
68658
|
+
capScope: "system",
|
|
68659
|
+
addonId: null,
|
|
68660
|
+
access: "view"
|
|
68661
|
+
},
|
|
68511
68662
|
"storageEvictable.evict": {
|
|
68512
68663
|
capName: "storage-evictable",
|
|
68513
68664
|
capScope: "system",
|
|
@@ -75073,6 +75224,18 @@ var CAP_STATE_LEAVES = Object.freeze({
|
|
|
75073
75224
|
{
|
|
75074
75225
|
"path": "swingHorizontal",
|
|
75075
75226
|
"valueType": "boolean"
|
|
75227
|
+
},
|
|
75228
|
+
{
|
|
75229
|
+
"path": "minTemp",
|
|
75230
|
+
"valueType": "number"
|
|
75231
|
+
},
|
|
75232
|
+
{
|
|
75233
|
+
"path": "maxTemp",
|
|
75234
|
+
"valueType": "number"
|
|
75235
|
+
},
|
|
75236
|
+
{
|
|
75237
|
+
"path": "tempStep",
|
|
75238
|
+
"valueType": "number"
|
|
75076
75239
|
}
|
|
75077
75240
|
],
|
|
75078
75241
|
"color": [
|
package/dist/index.mjs
CHANGED
|
@@ -5386,7 +5386,7 @@ var ZodIssueCode = {
|
|
|
5386
5386
|
var ZodFirstPartyTypeKind;
|
|
5387
5387
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5388
5388
|
//#endregion
|
|
5389
|
-
//#region ../types/dist/sleep-
|
|
5389
|
+
//#region ../types/dist/sleep-bwsTj221.mjs
|
|
5390
5390
|
/**
|
|
5391
5391
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5392
5392
|
* window to float samples (D455).
|
|
@@ -6637,7 +6637,6 @@ function createHandle(raw, opts) {
|
|
|
6637
6637
|
const writeAddon = (patch) => write("addon", opts.addonTree(), void 0, patch, () => readStoredAddonBlob(raw), (p) => raw.writeAddonStore(p));
|
|
6638
6638
|
const readAddonStoreResult = raw.readAddonStoreResult;
|
|
6639
6639
|
const readAddonStoreKeyResult = raw.readAddonStoreKeyResult;
|
|
6640
|
-
const readDeviceStoreBatch = raw.readDeviceStoreBatch;
|
|
6641
6640
|
const overrides = {
|
|
6642
6641
|
readAddonStore: async () => resolveRead("addon", await raw.readAddonStore()),
|
|
6643
6642
|
...readAddonStoreResult !== void 0 ? { readAddonStoreResult: async () => {
|
|
@@ -6661,12 +6660,12 @@ function createHandle(raw, opts) {
|
|
|
6661
6660
|
};
|
|
6662
6661
|
} } : {},
|
|
6663
6662
|
readDeviceStore: async (deviceId) => resolveRead(`device:${deviceId}`, await raw.readDeviceStore(deviceId)),
|
|
6664
|
-
|
|
6665
|
-
const rows = await readDeviceStoreBatch
|
|
6663
|
+
readDeviceStoreBatch: async (deviceIds) => {
|
|
6664
|
+
const rows = await raw.readDeviceStoreBatch(deviceIds);
|
|
6666
6665
|
const out = /* @__PURE__ */ new Map();
|
|
6667
6666
|
for (const [deviceId, blob] of rows) out.set(deviceId, await resolveRead(`device:${deviceId}`, blob));
|
|
6668
6667
|
return out;
|
|
6669
|
-
}
|
|
6668
|
+
},
|
|
6670
6669
|
writeAddonStore: async (patch) => {
|
|
6671
6670
|
await writeAddon(patch);
|
|
6672
6671
|
},
|
|
@@ -7493,7 +7492,7 @@ var BaseAddon = class {
|
|
|
7493
7492
|
return this._addonSecretTree;
|
|
7494
7493
|
}
|
|
7495
7494
|
deviceSecretTree() {
|
|
7496
|
-
this._deviceSecretTree ??= secretTreeFromSchema(this.deviceSettingsSchema());
|
|
7495
|
+
this._deviceSecretTree ??= mergeSecretStatePaths(secretTreeFromSchema(this.deviceSettingsSchema()), this.secretStatePaths);
|
|
7497
7496
|
return this._deviceSecretTree;
|
|
7498
7497
|
}
|
|
7499
7498
|
/**
|
|
@@ -7569,42 +7568,135 @@ var BaseAddon = class {
|
|
|
7569
7568
|
this[timerOf] = timer;
|
|
7570
7569
|
}
|
|
7571
7570
|
/**
|
|
7572
|
-
* Wrap `ctx.settings.readAddonStore()` with a
|
|
7573
|
-
*
|
|
7574
|
-
* swap, or any race where the SqliteSettingsBackend is between shutdown and
|
|
7575
|
-
* re-initialize) doesn't propagate up into `initialize()` and leave the
|
|
7571
|
+
* Wrap `ctx.settings.readAddonStore()` with a retry budget so a transient
|
|
7572
|
+
* settings-store outage doesn't propagate up into `initialize()` and leave the
|
|
7576
7573
|
* addon permanently broken.
|
|
7577
7574
|
*
|
|
7578
|
-
*
|
|
7579
|
-
*
|
|
7580
|
-
* `
|
|
7575
|
+
* Two kinds of outage, two budgets:
|
|
7576
|
+
* - the store's own restart fingerprints (`SqliteSettingsBackend not
|
|
7577
|
+
* initialized`, `provider not available`): a short budget, then the addon
|
|
7578
|
+
* falls back to `{}` (defaults) - its first successful patch rehydrates;
|
|
7579
|
+
* - a TRANSPORT failure (the hub is restarting while this runner boots:
|
|
7580
|
+
* `discovery deadline exceeded`, `parent could not route`, a refused or
|
|
7581
|
+
* timed-out connection). Since D870 a runner's settings read THROWS instead
|
|
7582
|
+
* of answering `{}`, so without a budget a hub restart ends in a respawn
|
|
7583
|
+
* loop. A long, bounded budget; only after it the error propagates - the
|
|
7584
|
+
* addon never runs on defaults for a store it could not ask.
|
|
7585
|
+
* Anything else propagates immediately so real bugs surface.
|
|
7581
7586
|
*/
|
|
7582
7587
|
async readAddonStoreWithRetry() {
|
|
7583
7588
|
const settings = this.rawSettings();
|
|
7584
7589
|
if (!settings) return {};
|
|
7585
|
-
const delaysMs = [
|
|
7586
|
-
150,
|
|
7587
|
-
350,
|
|
7588
|
-
600,
|
|
7589
|
-
900
|
|
7590
|
-
];
|
|
7591
7590
|
let lastErr;
|
|
7592
|
-
for (let attempt = 0
|
|
7591
|
+
for (let attempt = 0;; attempt++) try {
|
|
7593
7592
|
const stored = await settings.readAddonStore() ?? {};
|
|
7594
7593
|
this.settingsStoreReady = true;
|
|
7595
7594
|
return stored;
|
|
7596
7595
|
} catch (err) {
|
|
7597
7596
|
lastErr = err;
|
|
7598
|
-
const
|
|
7599
|
-
if (
|
|
7600
|
-
|
|
7601
|
-
|
|
7597
|
+
const kind = classifyStoreError(err);
|
|
7598
|
+
if (kind === "permanent") throw err;
|
|
7599
|
+
const delay = (kind === "transport" ? TRANSPORT_RETRY_DELAYS_MS : RESTART_RETRY_DELAYS_MS)[attempt];
|
|
7600
|
+
if (delay === void 0) {
|
|
7601
|
+
if (kind === "transport") throw err;
|
|
7602
|
+
break;
|
|
7603
|
+
}
|
|
7604
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
7602
7605
|
}
|
|
7603
7606
|
this.settingsStoreReady = false;
|
|
7604
7607
|
this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
|
|
7605
7608
|
return {};
|
|
7606
7609
|
}
|
|
7607
7610
|
};
|
|
7611
|
+
/** The settings store's own restart fingerprints. */
|
|
7612
|
+
var RESTART_RETRY_DELAYS_MS = [
|
|
7613
|
+
150,
|
|
7614
|
+
350,
|
|
7615
|
+
600,
|
|
7616
|
+
900
|
|
7617
|
+
];
|
|
7618
|
+
/** A hub restarting under a booting runner: ~100 s in total. */
|
|
7619
|
+
var TRANSPORT_RETRY_DELAYS_MS = [
|
|
7620
|
+
150,
|
|
7621
|
+
350,
|
|
7622
|
+
600,
|
|
7623
|
+
900,
|
|
7624
|
+
2e3,
|
|
7625
|
+
5e3,
|
|
7626
|
+
1e4,
|
|
7627
|
+
2e4,
|
|
7628
|
+
3e4,
|
|
7629
|
+
3e4
|
|
7630
|
+
];
|
|
7631
|
+
var RESTART_FINGERPRINTS = ["SqliteSettingsBackend not initialized", "provider not available"];
|
|
7632
|
+
/** Node / socket error codes of a connection that did not happen or broke. */
|
|
7633
|
+
var TRANSPORT_CODES = new Set([
|
|
7634
|
+
"ECONNREFUSED",
|
|
7635
|
+
"ECONNRESET",
|
|
7636
|
+
"ETIMEDOUT",
|
|
7637
|
+
"EPIPE",
|
|
7638
|
+
"EHOSTUNREACH",
|
|
7639
|
+
"ENETUNREACH"
|
|
7640
|
+
]);
|
|
7641
|
+
/** tRPC error codes that mean "the other side is not answering now", not "your call is wrong". */
|
|
7642
|
+
var UNAVAILABLE_TRPC_CODES = new Set([
|
|
7643
|
+
"TIMEOUT",
|
|
7644
|
+
"SERVICE_UNAVAILABLE",
|
|
7645
|
+
"BAD_GATEWAY",
|
|
7646
|
+
"GATEWAY_TIMEOUT"
|
|
7647
|
+
]);
|
|
7648
|
+
/** The exact phrases OUR transport raises when it cannot reach the hub. */
|
|
7649
|
+
var TRANSPORT_PHRASES = [
|
|
7650
|
+
"discovery deadline exceeded",
|
|
7651
|
+
"parent could not route child unowned cap call",
|
|
7652
|
+
"UDS request timed out after",
|
|
7653
|
+
"channel closed"
|
|
7654
|
+
];
|
|
7655
|
+
/** Moleculer error `type`s of a call that could not be served right now. */
|
|
7656
|
+
var MOLECULER_TRANSIENT_TYPES = new Set([
|
|
7657
|
+
"REQUEST_TIMEOUT",
|
|
7658
|
+
"SERVICE_NOT_FOUND",
|
|
7659
|
+
"SERVICE_NOT_AVAILABLE",
|
|
7660
|
+
"REQUEST_REJECTED",
|
|
7661
|
+
"BROKER_DISCONNECTED"
|
|
7662
|
+
]);
|
|
7663
|
+
function stringProp(value, key) {
|
|
7664
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
7665
|
+
const found = Reflect.get(value, key);
|
|
7666
|
+
return typeof found === "string" ? found : void 0;
|
|
7667
|
+
}
|
|
7668
|
+
/** The code an error carries: its own, its cause's, or a tRPC `data.code`. */
|
|
7669
|
+
function errorCode(err) {
|
|
7670
|
+
const out = {};
|
|
7671
|
+
const cause = typeof err === "object" && err !== null ? Reflect.get(err, "cause") : void 0;
|
|
7672
|
+
const data = typeof err === "object" && err !== null ? Reflect.get(err, "data") : void 0;
|
|
7673
|
+
const node = stringProp(err, "code") ?? stringProp(cause, "code");
|
|
7674
|
+
if (node !== void 0) out.node = node;
|
|
7675
|
+
const trpc = stringProp(data, "code");
|
|
7676
|
+
if (trpc !== void 0) out.trpc = trpc;
|
|
7677
|
+
return out;
|
|
7678
|
+
}
|
|
7679
|
+
/**
|
|
7680
|
+
* Is a settings read failure worth retrying, and with which budget? Only
|
|
7681
|
+
* EXPLICIT signals count: a socket error code, a tRPC "unavailable" code, or
|
|
7682
|
+
* one of the exact phrases our own transport raises. A message that merely
|
|
7683
|
+
* contains "timed out" or "unreachable" is not evidence of anything, and
|
|
7684
|
+
* `settings store not wired` is a wiring bug that retrying cannot fix.
|
|
7685
|
+
*/
|
|
7686
|
+
function classifyStoreError(err) {
|
|
7687
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
7688
|
+
if (RESTART_FINGERPRINTS.some((f) => message.includes(f))) return "restart";
|
|
7689
|
+
const code = errorCode(err);
|
|
7690
|
+
if (code.node !== void 0 && TRANSPORT_CODES.has(code.node)) return "transport";
|
|
7691
|
+
if (code.trpc !== void 0 && UNAVAILABLE_TRPC_CODES.has(code.trpc)) return "transport";
|
|
7692
|
+
if (typeof err === "object" && err !== null) {
|
|
7693
|
+
if (Reflect.get(err, "retryable") === true) return "transport";
|
|
7694
|
+
const type = stringProp(err, "type");
|
|
7695
|
+
if (type !== void 0 && MOLECULER_TRANSIENT_TYPES.has(type)) return "transport";
|
|
7696
|
+
}
|
|
7697
|
+
if (TRANSPORT_PHRASES.some((f) => message.includes(f))) return "transport";
|
|
7698
|
+
return "permanent";
|
|
7699
|
+
}
|
|
7608
7700
|
/**
|
|
7609
7701
|
* Collect the keys of every field marked `perNode: true`, recursing into
|
|
7610
7702
|
* layout containers (`group` fields and `sub-tabs` tabs) the same way
|
|
@@ -8159,7 +8251,7 @@ object({
|
|
|
8159
8251
|
params: record(string(), union([string(), number()])).optional()
|
|
8160
8252
|
});
|
|
8161
8253
|
//#endregion
|
|
8162
|
-
//#region ../types/dist/err-msg
|
|
8254
|
+
//#region ../types/dist/err-msg--2RrYiLO.mjs
|
|
8163
8255
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
8164
8256
|
DeviceType["Camera"] = "camera";
|
|
8165
8257
|
DeviceType["Hub"] = "hub";
|
|
@@ -8428,6 +8520,9 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
8428
8520
|
/** Virtual HA toggle (input_boolean.*) — distinguishable from a
|
|
8429
8521
|
* real Switch device for UI rendering / export adapters. */
|
|
8430
8522
|
DeviceRole["BinaryHelper"] = "binary-helper";
|
|
8523
|
+
/** A smart plug: a `switch` whose source says it is an outlet (HA
|
|
8524
|
+
* `device_class: outlet`). The Alexa export shows it as a SMARTPLUG. */
|
|
8525
|
+
DeviceRole["Outlet"] = "outlet";
|
|
8431
8526
|
/** Generic motion / occupancy / moving event source. Distinct from
|
|
8432
8527
|
* the camera accessory PirSensor role: that one is a camera child;
|
|
8433
8528
|
* this is a standalone HA / 3rd-party motion sensor. */
|
|
@@ -8495,7 +8590,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
8495
8590
|
return DeviceRole;
|
|
8496
8591
|
}({});
|
|
8497
8592
|
//#endregion
|
|
8498
|
-
//#region ../types/dist/composition-
|
|
8593
|
+
//#region ../types/dist/composition-DOwQB_Ua.mjs
|
|
8499
8594
|
/**
|
|
8500
8595
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
8501
8596
|
*
|
|
@@ -15834,6 +15929,28 @@ id: union([string(), number()]) }), {
|
|
|
15834
15929
|
kind: "mutation",
|
|
15835
15930
|
auth: "admin"
|
|
15836
15931
|
});
|
|
15932
|
+
/** One table of the settings database. */
|
|
15933
|
+
var StorageTableSchema = object({
|
|
15934
|
+
/** The table's full name, e.g. `recorder:addon-settings` or `addon-device-settings`. */
|
|
15935
|
+
name: string(),
|
|
15936
|
+
/** The owner prefix of a scoped name (`recorder` for `recorder:addon-settings`), else null. */
|
|
15937
|
+
owner: string().nullable(),
|
|
15938
|
+
rows: number().int().nonnegative(),
|
|
15939
|
+
/** Bytes the table's pages occupy (`dbstat`); null when the engine cannot measure. */
|
|
15940
|
+
bytes: number().int().nonnegative().nullable(),
|
|
15941
|
+
/** Declared by an addon since this engine process started (a running addon claims it). */
|
|
15942
|
+
declaredThisBoot: boolean()
|
|
15943
|
+
});
|
|
15944
|
+
method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: array(StorageTableSchema) }), { auth: "admin" }), method(object({
|
|
15945
|
+
collection: string().min(1),
|
|
15946
|
+
expectRows: number().int().nonnegative()
|
|
15947
|
+
}), object({
|
|
15948
|
+
dropped: literal(true),
|
|
15949
|
+
rows: number().int().nonnegative()
|
|
15950
|
+
}), {
|
|
15951
|
+
kind: "mutation",
|
|
15952
|
+
auth: "admin"
|
|
15953
|
+
});
|
|
15837
15954
|
/**
|
|
15838
15955
|
* `keychain` — the hub's encrypted store of secret values (D787).
|
|
15839
15956
|
*
|
|
@@ -16375,6 +16492,16 @@ method(object({}), KeychainStatusSchema, { auth: "admin" }), method(object({}),
|
|
|
16375
16492
|
kind: "mutation",
|
|
16376
16493
|
auth: "admin",
|
|
16377
16494
|
caller: "required"
|
|
16495
|
+
}), method(object({
|
|
16496
|
+
ref: string().min(1),
|
|
16497
|
+
value: string().min(1)
|
|
16498
|
+
}), object({
|
|
16499
|
+
ref: string(),
|
|
16500
|
+
version: number().int()
|
|
16501
|
+
}), {
|
|
16502
|
+
kind: "mutation",
|
|
16503
|
+
auth: "admin",
|
|
16504
|
+
caller: "required"
|
|
16378
16505
|
}), method(object({ refs: array(string().min(1)).max(1e3) }), object({
|
|
16379
16506
|
deleted: array(string()).readonly(),
|
|
16380
16507
|
kept: array(object({
|
|
@@ -53433,6 +53560,12 @@ object({
|
|
|
53433
53560
|
/** Horizontal louver swing on/off. Null when the device has no
|
|
53434
53561
|
* horizontal swing surface (gate with `DeviceFeature.ClimateSwingHorizontal`). */
|
|
53435
53562
|
swingHorizontal: boolean().nullable(),
|
|
53563
|
+
/** Lowest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
53564
|
+
minTemp: number().nullable().optional(),
|
|
53565
|
+
/** Highest setpoint the device accepts, Celsius. Absent / null = not reported. */
|
|
53566
|
+
maxTemp: number().nullable().optional(),
|
|
53567
|
+
/** Setpoint granularity, Celsius (0.5, 1). Absent / null = not reported. */
|
|
53568
|
+
tempStep: number().positive().nullable().optional(),
|
|
53436
53569
|
/** Ms epoch when the slice was last updated (push or command). */
|
|
53437
53570
|
lastFetchedAt: number()
|
|
53438
53571
|
});
|
|
@@ -64718,6 +64851,12 @@ Object.freeze({
|
|
|
64718
64851
|
addonId: null,
|
|
64719
64852
|
access: "create"
|
|
64720
64853
|
},
|
|
64854
|
+
"keychainAdmin.importSecret": {
|
|
64855
|
+
capName: "keychain-admin",
|
|
64856
|
+
capScope: "system",
|
|
64857
|
+
addonId: null,
|
|
64858
|
+
access: "create"
|
|
64859
|
+
},
|
|
64721
64860
|
"keychainAdmin.listAudit": {
|
|
64722
64861
|
capName: "keychain-admin",
|
|
64723
64862
|
capScope: "system",
|
|
@@ -68504,6 +68643,18 @@ Object.freeze({
|
|
|
68504
68643
|
addonId: null,
|
|
68505
68644
|
access: "create"
|
|
68506
68645
|
},
|
|
68646
|
+
"storageAdmin.dropCollection": {
|
|
68647
|
+
capName: "storage-admin",
|
|
68648
|
+
capScope: "system",
|
|
68649
|
+
addonId: null,
|
|
68650
|
+
access: "delete"
|
|
68651
|
+
},
|
|
68652
|
+
"storageAdmin.listTables": {
|
|
68653
|
+
capName: "storage-admin",
|
|
68654
|
+
capScope: "system",
|
|
68655
|
+
addonId: null,
|
|
68656
|
+
access: "view"
|
|
68657
|
+
},
|
|
68507
68658
|
"storageEvictable.evict": {
|
|
68508
68659
|
capName: "storage-evictable",
|
|
68509
68660
|
capScope: "system",
|
|
@@ -75069,6 +75220,18 @@ var CAP_STATE_LEAVES = Object.freeze({
|
|
|
75069
75220
|
{
|
|
75070
75221
|
"path": "swingHorizontal",
|
|
75071
75222
|
"valueType": "boolean"
|
|
75223
|
+
},
|
|
75224
|
+
{
|
|
75225
|
+
"path": "minTemp",
|
|
75226
|
+
"valueType": "number"
|
|
75227
|
+
},
|
|
75228
|
+
{
|
|
75229
|
+
"path": "maxTemp",
|
|
75230
|
+
"valueType": "number"
|
|
75231
|
+
},
|
|
75232
|
+
{
|
|
75233
|
+
"path": "tempStep",
|
|
75234
|
+
"valueType": "number"
|
|
75072
75235
|
}
|
|
75073
75236
|
],
|
|
75074
75237
|
"color": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { S as e, d as t, u as n, v as r } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react__loadShare__.js-C-pbjC7c.mjs";
|
|
2
2
|
import { n as i, r as a, t as o } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-DalfdIDw.mjs";
|
|
3
|
-
import { c as s, l as c } from "./responsive-
|
|
3
|
+
import { c as s, l as c } from "./responsive-DCFnF6WM.mjs";
|
|
4
4
|
var l = c("chevron-down", [["path", {
|
|
5
5
|
d: "m6 9 6 6 6-6",
|
|
6
6
|
key: "qrunsl"
|
package/dist/remoteEntry.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as e, t } from "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-
|
|
1
|
+
import { n as e, t } from "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-qRoXJuGX.mjs";
|
|
2
2
|
export { t as get, e as init };
|