@camstack/addon-provider-homeassistant 1.2.12 → 1.2.13

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/addon.js CHANGED
@@ -18843,6 +18843,20 @@ var GetInputSchema = object({ id: string() });
18843
18843
  var AddInputSchema = object({
18844
18844
  kind: string().min(1),
18845
18845
  name: string().min(1),
18846
+ /**
18847
+ * ADOPT an existing id instead of minting a new one.
18848
+ *
18849
+ * Written the day this cost an outage. A broker's id is not a detail: HA
18850
+ * devices carry it inside their `stableId` (`ha:ha_004:dev:…`), so a broker
18851
+ * lost from config and re-added as `ha_001` leaves every one of its devices
18852
+ * bound to a broker that no longer exists. Re-entering the password under the
18853
+ * ORIGINAL id turns a multi-step device migration back into re-entering a
18854
+ * password.
18855
+ *
18856
+ * A provider MUST refuse an id that is already in use — adopting a live
18857
+ * broker's id would silently take it over.
18858
+ */
18859
+ id: string().min(1).optional(),
18846
18860
  /** Kind-specific settings (e.g. MQTT `{url,username,password}` or HA
18847
18861
  * `{baseUrl,accessToken}`). Validated by the kind-specific provider
18848
18862
  * branch on receipt — invalid shape rejects the add. */
@@ -36117,6 +36131,27 @@ var HaBrokerRegistry = class {
36117
36131
  this.nextIdCounter += 1;
36118
36132
  return id;
36119
36133
  }
36134
+ /**
36135
+ * Take a caller-supplied id, or refuse.
36136
+ *
36137
+ * Two refusals, and both matter more than they look:
36138
+ *
36139
+ * - **An id already in use** would SILENTLY take over a live broker: the new
36140
+ * entry replaces it in config while its devices keep pointing at the id,
36141
+ * now serving someone else's Home Assistant. Recovery is re-creating a
36142
+ * broker that is GONE, never overwriting one that is here.
36143
+ * - **The progressive counter is advanced past an adopted id.** Adopting
36144
+ * `ha_004` while the counter sits at 2 would let the next automatic
36145
+ * allocation mint `ha_004` a second time — two brokers, one id, and every
36146
+ * device bound to whichever won. The counter is only seeded from stored
36147
+ * entries at load, so it cannot discover this on its own.
36148
+ */
36149
+ adoptId(id) {
36150
+ if (this.managers.has(id)) throw new Error(`broker id "${id}" is already in use — adopt an id only to restore a broker that is gone`);
36151
+ const match = id.match(/^ha_(\d+)$/);
36152
+ if (match) this.nextIdCounter = Math.max(this.nextIdCounter, Number.parseInt(match[1], 10) + 1);
36153
+ return id;
36154
+ }
36120
36155
  seedCounterFromEntries(entries) {
36121
36156
  let maxSeen = 0;
36122
36157
  for (const e of entries) {
@@ -36136,7 +36171,7 @@ var HaBrokerRegistry = class {
36136
36171
  async createEntry(name, settings, options = {}) {
36137
36172
  const auth = settingsToAuth(settings);
36138
36173
  const entry = {
36139
- id: this.allocateId(),
36174
+ id: options.id !== void 0 ? this.adoptId(options.id) : this.allocateId(),
36140
36175
  name,
36141
36176
  auth,
36142
36177
  ...options.integrationId !== void 0 ? { integrationId: options.integrationId } : {}
@@ -38500,9 +38535,13 @@ var HaProviderAddon = class HaProviderAddon extends BaseDeviceProvider {
38500
38535
  label: "Home Assistant"
38501
38536
  }]
38502
38537
  }],
38503
- add: async ({ kind, name, settings }) => {
38538
+ add: async ({ kind, name, settings, id }) => {
38504
38539
  if (kind !== HA_KIND) throw new Error(`provider-homeassistant: only kind '${HA_KIND}' is handled here (got '${kind}')`);
38505
- const entry = await this.requireRegistry().createEntry(name, settings);
38540
+ const entry = await this.requireRegistry().createEntry(name, settings, { ...id !== void 0 ? { id } : {} });
38541
+ if (id !== void 0) this.ctx.logger.info("broker restored under an adopted id", { meta: {
38542
+ brokerId: entry.id,
38543
+ name
38544
+ } });
38506
38545
  await this.updateGlobalSettings({ brokers: [...this.config.brokers, entry] });
38507
38546
  return { id: entry.id };
38508
38547
  },
package/dist/addon.mjs CHANGED
@@ -18842,6 +18842,20 @@ var GetInputSchema = object({ id: string() });
18842
18842
  var AddInputSchema = object({
18843
18843
  kind: string().min(1),
18844
18844
  name: string().min(1),
18845
+ /**
18846
+ * ADOPT an existing id instead of minting a new one.
18847
+ *
18848
+ * Written the day this cost an outage. A broker's id is not a detail: HA
18849
+ * devices carry it inside their `stableId` (`ha:ha_004:dev:…`), so a broker
18850
+ * lost from config and re-added as `ha_001` leaves every one of its devices
18851
+ * bound to a broker that no longer exists. Re-entering the password under the
18852
+ * ORIGINAL id turns a multi-step device migration back into re-entering a
18853
+ * password.
18854
+ *
18855
+ * A provider MUST refuse an id that is already in use — adopting a live
18856
+ * broker's id would silently take it over.
18857
+ */
18858
+ id: string().min(1).optional(),
18845
18859
  /** Kind-specific settings (e.g. MQTT `{url,username,password}` or HA
18846
18860
  * `{baseUrl,accessToken}`). Validated by the kind-specific provider
18847
18861
  * branch on receipt — invalid shape rejects the add. */
@@ -36116,6 +36130,27 @@ var HaBrokerRegistry = class {
36116
36130
  this.nextIdCounter += 1;
36117
36131
  return id;
36118
36132
  }
36133
+ /**
36134
+ * Take a caller-supplied id, or refuse.
36135
+ *
36136
+ * Two refusals, and both matter more than they look:
36137
+ *
36138
+ * - **An id already in use** would SILENTLY take over a live broker: the new
36139
+ * entry replaces it in config while its devices keep pointing at the id,
36140
+ * now serving someone else's Home Assistant. Recovery is re-creating a
36141
+ * broker that is GONE, never overwriting one that is here.
36142
+ * - **The progressive counter is advanced past an adopted id.** Adopting
36143
+ * `ha_004` while the counter sits at 2 would let the next automatic
36144
+ * allocation mint `ha_004` a second time — two brokers, one id, and every
36145
+ * device bound to whichever won. The counter is only seeded from stored
36146
+ * entries at load, so it cannot discover this on its own.
36147
+ */
36148
+ adoptId(id) {
36149
+ if (this.managers.has(id)) throw new Error(`broker id "${id}" is already in use — adopt an id only to restore a broker that is gone`);
36150
+ const match = id.match(/^ha_(\d+)$/);
36151
+ if (match) this.nextIdCounter = Math.max(this.nextIdCounter, Number.parseInt(match[1], 10) + 1);
36152
+ return id;
36153
+ }
36119
36154
  seedCounterFromEntries(entries) {
36120
36155
  let maxSeen = 0;
36121
36156
  for (const e of entries) {
@@ -36135,7 +36170,7 @@ var HaBrokerRegistry = class {
36135
36170
  async createEntry(name, settings, options = {}) {
36136
36171
  const auth = settingsToAuth(settings);
36137
36172
  const entry = {
36138
- id: this.allocateId(),
36173
+ id: options.id !== void 0 ? this.adoptId(options.id) : this.allocateId(),
36139
36174
  name,
36140
36175
  auth,
36141
36176
  ...options.integrationId !== void 0 ? { integrationId: options.integrationId } : {}
@@ -38499,9 +38534,13 @@ var HaProviderAddon = class HaProviderAddon extends BaseDeviceProvider {
38499
38534
  label: "Home Assistant"
38500
38535
  }]
38501
38536
  }],
38502
- add: async ({ kind, name, settings }) => {
38537
+ add: async ({ kind, name, settings, id }) => {
38503
38538
  if (kind !== HA_KIND) throw new Error(`provider-homeassistant: only kind '${HA_KIND}' is handled here (got '${kind}')`);
38504
- const entry = await this.requireRegistry().createEntry(name, settings);
38539
+ const entry = await this.requireRegistry().createEntry(name, settings, { ...id !== void 0 ? { id } : {} });
38540
+ if (id !== void 0) this.ctx.logger.info("broker restored under an adopted id", { meta: {
38541
+ brokerId: entry.id,
38542
+ name
38543
+ } });
38505
38544
  await this.updateGlobalSettings({ brokers: [...this.config.brokers, entry] });
38506
38545
  return { id: entry.id };
38507
38546
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-homeassistant",
3
- "version": "1.2.12",
3
+ "version": "1.2.13",
4
4
  "description": "Home Assistant device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",