camstack 1.2.76 → 1.2.77

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/cli.js CHANGED
@@ -38,7 +38,7 @@ async function runServe(args) {
38
38
  ...typeof values.data === "string" ? { data: values.data } : {}
39
39
  };
40
40
  Object.assign(process.env, buildServeEnv(opts));
41
- await import("./launcher-WOTGVQN3.js");
41
+ await import("./launcher-JYQ4AMYP.js");
42
42
  }
43
43
 
44
44
  // src/commands/agent.ts
@@ -83,7 +83,7 @@ async function runAgent(args) {
83
83
  ...typeof values.port === "string" ? { port: values.port } : {}
84
84
  };
85
85
  Object.assign(process.env, buildAgentEnv(opts));
86
- await import("./launcher-WOTGVQN3.js");
86
+ await import("./launcher-JYQ4AMYP.js");
87
87
  }
88
88
 
89
89
  // src/commands/setup.ts
@@ -67743,6 +67743,86 @@ var require_device_manager_addon = __commonJS({
67743
67743
  });
67744
67744
  }
67745
67745
  /** Drop the device's row. Idempotent. */
67746
+ /**
67747
+ * Exchange the ids of two devices, carrying their children with them.
67748
+ *
67749
+ * ## Why this exists as a primitive
67750
+ *
67751
+ * Replacing a camera means the new hardware has to become the device the rest
67752
+ * of the system already knows. Everything general about a camera is keyed on
67753
+ * the NUMERIC id and on nothing else — the recording path on disk is
67754
+ * `<deviceId>/profile/…`, the hour ledger, the media store and zone ownership
67755
+ * carry `deviceId` and not one `stableId` between them, and all four
67756
+ * ecosystem exports (Home Assistant, Alexa, HomeKit, Google) key on it too.
67757
+ * Moving that work is the expensive, lossy operation. Moving the NUMBER is
67758
+ * two rows.
67759
+ *
67760
+ * ## Children are re-pointed, not renumbered
67761
+ *
67762
+ * A child keeps its own id and follows its parent: every row whose
67763
+ * `parentDeviceId` was `a` now names `b`, and the reverse. Renumbering the
67764
+ * children as well would move THEIR general work for no reason — the
67765
+ * accessory's own recordings and rules are keyed on the child id, which is
67766
+ * not the id being inherited.
67767
+ *
67768
+ * ## There are no transactions here, so the ORDER is the safety
67769
+ *
67770
+ * The backing store is a collection API (`set` / `delete` / `updateWhere`);
67771
+ * there is no rollback to lean on. So the sequence is chosen to make every
67772
+ * crash point LOUD rather than plausible: `a` first moves to a freshly
67773
+ * allocated id, which the monotonic counter guarantees was never used and
67774
+ * will never be reused. A crash before the end therefore leaves a device
67775
+ * missing from its number and a stray at an unfamiliar one — visible in the
67776
+ * device list at a glance. What it can never leave is two rows on one number,
67777
+ * or a row that looks correct while its children point elsewhere.
67778
+ *
67779
+ * The caller holds {@link DeviceMetaStore.withMetaWriteLock}. This method does
67780
+ * not take it: taking it here would deadlock the migration that has to disable
67781
+ * functions on both devices in the same critical section.
67782
+ */
67783
+ async swapIds(a, b, tempId) {
67784
+ if (a === b) throw new Error(`[device-manager] swapIds: ${a} and ${b} are the same device`);
67785
+ await this.declare();
67786
+ const rowA = await this.get(a);
67787
+ const rowB = await this.get(b);
67788
+ if (rowA === null) throw new Error(`[device-manager] swapIds: device ${a} does not exist`);
67789
+ if (rowB === null) throw new Error(`[device-manager] swapIds: device ${b} does not exist`);
67790
+ if (await this.get(tempId) !== null) throw new Error(`[device-manager] swapIds: temp id ${tempId} is taken`);
67791
+ const childrenOfA = (await this.listByParent(a)).map((r) => r.meta.id);
67792
+ const childrenOfB = (await this.listByParent(b)).map((r) => r.meta.id);
67793
+ await this.moveRow(rowA, tempId);
67794
+ await this.moveRow(rowB, a);
67795
+ await this.moveRow({
67796
+ ...rowA,
67797
+ meta: {
67798
+ ...rowA.meta,
67799
+ id: tempId
67800
+ }
67801
+ }, b);
67802
+ for (const childId of childrenOfA) await this.patch(childId, { parentDeviceId: b });
67803
+ for (const childId of childrenOfB) await this.patch(childId, { parentDeviceId: a });
67804
+ this.logger.info("device ids swapped", {
67805
+ tags: { deviceId: a },
67806
+ meta: {
67807
+ a,
67808
+ b,
67809
+ childrenOfA,
67810
+ childrenOfB
67811
+ }
67812
+ });
67813
+ }
67814
+ /** Rewrite a row under a new id and drop the old key. Not exported: the only
67815
+ * legitimate reason to move a row is {@link swapIds}. */
67816
+ async moveRow(row, toId) {
67817
+ await this.upsert({
67818
+ ...row.meta,
67819
+ id: toId
67820
+ }, {
67821
+ registered: row.registered,
67822
+ metadata: row.metadata
67823
+ });
67824
+ await this.remove(row.meta.id);
67825
+ }
67746
67826
  async remove(deviceId) {
67747
67827
  await this.declare();
67748
67828
  await this.backend.delete({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.2.76",
3
+ "version": "1.2.77",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",