@camstack/addon-provider-homeassistant 1.2.654 → 1.2.655

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.
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  enumerable: true
25
25
  }) : target, mod));
26
26
  //#endregion
27
- const require_ha_instance_settings = require("../ha-instance-settings-Bn_Trz6p.js");
27
+ const require_ha_instance_settings = require("../ha-instance-settings-5Ms7yRju.js");
28
28
  let node_crypto = require("node:crypto");
29
29
  require("node:zlib");
30
30
  let node_fs = require("node:fs");
@@ -7672,31 +7672,46 @@ var HaExportAddon = class extends require_ha_instance_settings.BaseAddon {
7672
7672
  {
7673
7673
  capability: require_ha_instance_settings.deviceExportCapability,
7674
7674
  provider: {
7675
- getStatus: async () => this.buildStatus(),
7676
- listSupportedDeviceKinds: async () => [...SUPPORTED_DEVICE_KINDS],
7677
- listExposedDevices: async () => exposedDeviceIds(this.config.membership, this.enabledBrokerIds()).map((deviceId) => ({
7678
- deviceId,
7679
- exposedAs: brokersExposing(this.config.membership, deviceId).map((brokerId) => this.brokerName(brokerId)).join(", ")
7675
+ getStatus: async (input) => this.buildStatus(this.brokerScope(require_ha_instance_settings.statusInstanceOf(input))),
7676
+ listInstances: async () => this.config.knownBrokers.map((broker) => ({
7677
+ instanceId: broker.id,
7678
+ name: broker.name,
7679
+ enabled: this.enabledBrokerIds().includes(broker.id),
7680
+ kind: "home-assistant"
7680
7681
  })),
7681
- exposeDevice: async ({ deviceId }) => this.setMembershipEverywhere(deviceId, true),
7682
- unexposeDevice: async ({ deviceId }) => this.setMembershipEverywhere(deviceId, false),
7682
+ listSupportedDeviceKinds: async ({ instanceId }) => {
7683
+ this.brokerScope(instanceId);
7684
+ return [...SUPPORTED_DEVICE_KINDS];
7685
+ },
7686
+ listExposedDevices: async ({ instanceId }) => this.exposedDeviceRows(this.brokerScope(instanceId)),
7687
+ exposeDevice: async ({ instanceId, deviceId }) => this.setBrokerMembership(instanceId, deviceId, true),
7688
+ unexposeDevice: async ({ instanceId, deviceId }) => this.setBrokerMembership(instanceId, deviceId, false),
7683
7689
  listSupportedEntityKinds: async () => [
7684
7690
  "device",
7685
7691
  "action",
7686
7692
  "notifier"
7687
7693
  ],
7688
- listExposedEntities: async () => {
7694
+ listExposedEntities: async ({ instanceId }) => {
7695
+ const scope = this.brokerScope(instanceId);
7689
7696
  await exportedEntities.pruneDeleted();
7690
- return [...exposedDeviceIds(this.config.membership, this.enabledBrokerIds()).map((deviceId) => ({
7697
+ return [...this.exposedDeviceRows(scope).map((row) => ({
7691
7698
  entity: {
7692
7699
  kind: "device",
7693
- deviceId
7700
+ deviceId: row.deviceId
7694
7701
  },
7695
- exposedAs: brokersExposing(this.config.membership, deviceId).map((brokerId) => this.brokerName(brokerId)).join(", ")
7702
+ exposedAs: row.exposedAs
7696
7703
  })), ...exportedEntities.list()];
7697
7704
  },
7698
- exposeEntity: async ({ entity }) => entity.kind === "device" ? this.setMembershipEverywhere(entity.deviceId, true) : exportedEntities.expose(entity),
7699
- unexposeEntity: async ({ entity }) => entity.kind === "device" ? this.setMembershipEverywhere(entity.deviceId, false) : exportedEntities.unexpose(entity),
7705
+ exposeEntity: async ({ instanceId, entity }) => {
7706
+ if (entity.kind === "device") return this.setBrokerMembership(instanceId, entity.deviceId, true);
7707
+ this.brokerScope(instanceId);
7708
+ return exportedEntities.expose(entity);
7709
+ },
7710
+ unexposeEntity: async ({ instanceId, entity }) => {
7711
+ if (entity.kind === "device") return this.setBrokerMembership(instanceId, entity.deviceId, false);
7712
+ this.brokerScope(instanceId);
7713
+ return exportedEntities.unexpose(entity);
7714
+ },
7700
7715
  getDeviceSettingsContribution: async ({ deviceId }) => this.buildContribution(deviceId),
7701
7716
  getDeviceLiveContribution: async () => null,
7702
7717
  applyDeviceSettingsPatch: async ({ deviceId, patch }) => this.applyDeviceSettingsPatch(deviceId, patch)
@@ -9820,20 +9835,44 @@ var HaExportAddon = class extends require_ha_instance_settings.BaseAddon {
9820
9835
  return bases;
9821
9836
  }
9822
9837
  /**
9823
- * The cap-level expose/unexpose applies to EVERY enabled broker.
9824
- *
9825
- * The `device-export` cap is the COMMON surface across export targets
9826
- * and has no notion of a broker; per-broker granularity lives in the
9827
- * derived Export panel, over the same store. There is exactly one
9828
- * authority either way.
9838
+ * Every broker this addon knows, enabled or not: a membership write may
9839
+ * target a broker that is switched off (its devices resume when it is turned
9840
+ * back on). A cold `knownBrokers` still counts the enabled ids.
9829
9841
  */
9830
- async setMembershipEverywhere(deviceId, exposed) {
9831
- let next = this.config.membership;
9832
- for (const brokerId of this.enabledBrokerIds()) next = setExposed(next, brokerId, deviceId, exposed);
9842
+ knownBrokerIds() {
9843
+ return new Set([...this.config.knownBrokers.map((b) => b.id), ...this.enabledBrokerIds()]);
9844
+ }
9845
+ /**
9846
+ * The brokers a `device-export` read answers over: the named instance, or
9847
+ * (absent) every enabled broker. A broker this addon does not know is
9848
+ * refused, never answered empty.
9849
+ */
9850
+ brokerScope(instanceId) {
9851
+ if (instanceId === void 0) return this.enabledBrokerIds();
9852
+ if (!this.knownBrokerIds().has(instanceId)) throw new require_ha_instance_settings.ExportInstanceUnknownError("provider-homeassistant", instanceId);
9853
+ return [instanceId];
9854
+ }
9855
+ exposedDeviceRows(scope) {
9856
+ return exposedDeviceIds(this.config.membership, scope).map((deviceId) => ({
9857
+ deviceId,
9858
+ exposedAs: brokersExposing(this.config.membership, deviceId).map((brokerId) => this.brokerName(brokerId)).join(", ")
9859
+ }));
9860
+ }
9861
+ /**
9862
+ * A cap-level expose/unexpose changes ONE broker's membership — the named
9863
+ * instance. There is no write without a target and no "everywhere": the
9864
+ * other brokers' membership is not touched.
9865
+ */
9866
+ async setBrokerMembership(instanceId, deviceId, exposed) {
9867
+ this.brokerScope(instanceId);
9868
+ const next = setExposed(this.config.membership, instanceId, deviceId, exposed);
9833
9869
  if (next === this.config.membership) {
9834
9870
  this.ctx.logger.debug("ha-export: membership already in that state, nothing to do", {
9835
9871
  tags: { deviceId: Number(deviceId) },
9836
- meta: { exposed }
9872
+ meta: {
9873
+ exposed,
9874
+ brokerId: instanceId
9875
+ }
9837
9876
  });
9838
9877
  return;
9839
9878
  }
@@ -9842,7 +9881,7 @@ var HaExportAddon = class extends require_ha_instance_settings.BaseAddon {
9842
9881
  tags: { deviceId: Number(deviceId) },
9843
9882
  meta: {
9844
9883
  exposed,
9845
- brokers: this.enabledBrokerIds()
9884
+ brokerId: instanceId
9846
9885
  }
9847
9886
  });
9848
9887
  await this.reconcile(exposed ? "expose" : "unexpose");
@@ -9996,19 +10035,20 @@ var HaExportAddon = class extends require_ha_instance_settings.BaseAddon {
9996
10035
  await this.reconcile("device-panel");
9997
10036
  return { success: true };
9998
10037
  }
9999
- buildStatus() {
10000
- const enabled = this.enabledBrokerIds();
10001
- const healthy = [...this.links.values()].filter((link) => link.client.healthy).length;
10002
- const linkFailure = [...this.links.values()].map((link) => link.client.failure).filter((failure) => failure !== null)[0]?.text;
10038
+ buildStatus(scope) {
10039
+ const enabled = scope;
10040
+ const links = [...this.links.entries()].filter(([brokerId]) => scope.includes(brokerId)).map(([, link]) => link);
10041
+ const healthy = links.filter((link) => link.client.healthy).length;
10042
+ const linkFailure = links.map((link) => link.client.failure).filter((failure) => failure !== null)[0]?.text;
10003
10043
  return {
10004
- linkState: enabled.length === 0 ? "unlinked" : healthy === this.links.size ? "linked" : "error",
10044
+ linkState: enabled.length === 0 ? "unlinked" : healthy === links.length ? "linked" : "error",
10005
10045
  exposedDeviceCount: exposedDeviceIds(this.config.membership, enabled).length,
10006
10046
  ...linkFailure !== void 0 ? { error: linkFailure } : this.lastError !== void 0 ? { error: this.lastError } : {},
10007
10047
  setup: {
10008
10048
  fields: [
10009
10049
  {
10010
10050
  label: "Home Assistant instances",
10011
- value: `${healthy} / ${this.links.size} reachable`
10051
+ value: `${healthy} / ${links.length} reachable`
10012
10052
  },
10013
10053
  {
10014
10054
  label: "Last push failure",
@@ -1,4 +1,4 @@
1
- import { $t as nodePin, F as buildAddonRouteProvider, Jt as defineAddonMigrations, Kt as baseUnitOf, Qt as isReadingQuantity, Tt as runExportedAction, U as consumableFormOf, W as consumableKindOf, Wt as BaseAddon, X as deviceExportCapability, _ as FanDirectionSchema, _t as preconditionOf, b as PLUG_APPLIANCE_TYPES, cn as string, d as COCO_TO_MACRO, f as CameraSwitchIdSchema, gn as EventCategory, h as ConsumableStatusSchema, jt as sendToExportedTarget, m as ConsumableItemSchema, mt as oauthIntegrationCapability, n as listInstancesOrNothing, o as listHomeAssistantBrokers, on as object, p as ConsumableFormSchema, r as settingsByBroker, s as AlarmArmModeSchema, t as haInstanceSettingsPortsOver, tn as array, u as CAMERA_SWITCH_ORDER, un as unknown, v as HvacModeSchema, w as addonRoutesCapability, xt as pruneDeletedEntities, y as MediaPlayerRepeatSchema } from "../ha-instance-settings-g5pwb3Fi.mjs";
1
+ import { $t as baseUnitOf, At as runExportedAction, Cn as EventCategory, E as addonRoutesCapability, Et as pruneDeletedEntities, G as consumableFormOf, It as sendToExportedTarget, K as consumableKindOf, L as buildAddonRouteProvider, Q as deviceExportCapability, Rt as statusInstanceOf, St as preconditionOf, Xt as BaseAddon, _ as ExportInstanceUnknownError, _n as unknown, an as isReadingQuantity, b as MediaPlayerRepeatSchema, cn as array, d as COCO_TO_MACRO, f as CameraSwitchIdSchema, h as ConsumableStatusSchema, hn as string, m as ConsumableItemSchema, n as listInstancesOrNothing, o as listHomeAssistantBrokers, on as nodePin, p as ConsumableFormSchema, pn as object, r as settingsByBroker, s as AlarmArmModeSchema, t as haInstanceSettingsPortsOver, tn as defineAddonMigrations, u as CAMERA_SWITCH_ORDER, v as FanDirectionSchema, x as PLUG_APPLIANCE_TYPES, y as HvacModeSchema, yt as oauthIntegrationCapability } from "../ha-instance-settings-DLDNOmgL.mjs";
2
2
  import { createHmac, timingSafeEqual } from "node:crypto";
3
3
  import "node:zlib";
4
4
  import "node:fs";
@@ -7637,31 +7637,46 @@ var HaExportAddon = class extends BaseAddon {
7637
7637
  {
7638
7638
  capability: deviceExportCapability,
7639
7639
  provider: {
7640
- getStatus: async () => this.buildStatus(),
7641
- listSupportedDeviceKinds: async () => [...SUPPORTED_DEVICE_KINDS],
7642
- listExposedDevices: async () => exposedDeviceIds(this.config.membership, this.enabledBrokerIds()).map((deviceId) => ({
7643
- deviceId,
7644
- exposedAs: brokersExposing(this.config.membership, deviceId).map((brokerId) => this.brokerName(brokerId)).join(", ")
7640
+ getStatus: async (input) => this.buildStatus(this.brokerScope(statusInstanceOf(input))),
7641
+ listInstances: async () => this.config.knownBrokers.map((broker) => ({
7642
+ instanceId: broker.id,
7643
+ name: broker.name,
7644
+ enabled: this.enabledBrokerIds().includes(broker.id),
7645
+ kind: "home-assistant"
7645
7646
  })),
7646
- exposeDevice: async ({ deviceId }) => this.setMembershipEverywhere(deviceId, true),
7647
- unexposeDevice: async ({ deviceId }) => this.setMembershipEverywhere(deviceId, false),
7647
+ listSupportedDeviceKinds: async ({ instanceId }) => {
7648
+ this.brokerScope(instanceId);
7649
+ return [...SUPPORTED_DEVICE_KINDS];
7650
+ },
7651
+ listExposedDevices: async ({ instanceId }) => this.exposedDeviceRows(this.brokerScope(instanceId)),
7652
+ exposeDevice: async ({ instanceId, deviceId }) => this.setBrokerMembership(instanceId, deviceId, true),
7653
+ unexposeDevice: async ({ instanceId, deviceId }) => this.setBrokerMembership(instanceId, deviceId, false),
7648
7654
  listSupportedEntityKinds: async () => [
7649
7655
  "device",
7650
7656
  "action",
7651
7657
  "notifier"
7652
7658
  ],
7653
- listExposedEntities: async () => {
7659
+ listExposedEntities: async ({ instanceId }) => {
7660
+ const scope = this.brokerScope(instanceId);
7654
7661
  await exportedEntities.pruneDeleted();
7655
- return [...exposedDeviceIds(this.config.membership, this.enabledBrokerIds()).map((deviceId) => ({
7662
+ return [...this.exposedDeviceRows(scope).map((row) => ({
7656
7663
  entity: {
7657
7664
  kind: "device",
7658
- deviceId
7665
+ deviceId: row.deviceId
7659
7666
  },
7660
- exposedAs: brokersExposing(this.config.membership, deviceId).map((brokerId) => this.brokerName(brokerId)).join(", ")
7667
+ exposedAs: row.exposedAs
7661
7668
  })), ...exportedEntities.list()];
7662
7669
  },
7663
- exposeEntity: async ({ entity }) => entity.kind === "device" ? this.setMembershipEverywhere(entity.deviceId, true) : exportedEntities.expose(entity),
7664
- unexposeEntity: async ({ entity }) => entity.kind === "device" ? this.setMembershipEverywhere(entity.deviceId, false) : exportedEntities.unexpose(entity),
7670
+ exposeEntity: async ({ instanceId, entity }) => {
7671
+ if (entity.kind === "device") return this.setBrokerMembership(instanceId, entity.deviceId, true);
7672
+ this.brokerScope(instanceId);
7673
+ return exportedEntities.expose(entity);
7674
+ },
7675
+ unexposeEntity: async ({ instanceId, entity }) => {
7676
+ if (entity.kind === "device") return this.setBrokerMembership(instanceId, entity.deviceId, false);
7677
+ this.brokerScope(instanceId);
7678
+ return exportedEntities.unexpose(entity);
7679
+ },
7665
7680
  getDeviceSettingsContribution: async ({ deviceId }) => this.buildContribution(deviceId),
7666
7681
  getDeviceLiveContribution: async () => null,
7667
7682
  applyDeviceSettingsPatch: async ({ deviceId, patch }) => this.applyDeviceSettingsPatch(deviceId, patch)
@@ -9785,20 +9800,44 @@ var HaExportAddon = class extends BaseAddon {
9785
9800
  return bases;
9786
9801
  }
9787
9802
  /**
9788
- * The cap-level expose/unexpose applies to EVERY enabled broker.
9789
- *
9790
- * The `device-export` cap is the COMMON surface across export targets
9791
- * and has no notion of a broker; per-broker granularity lives in the
9792
- * derived Export panel, over the same store. There is exactly one
9793
- * authority either way.
9803
+ * Every broker this addon knows, enabled or not: a membership write may
9804
+ * target a broker that is switched off (its devices resume when it is turned
9805
+ * back on). A cold `knownBrokers` still counts the enabled ids.
9794
9806
  */
9795
- async setMembershipEverywhere(deviceId, exposed) {
9796
- let next = this.config.membership;
9797
- for (const brokerId of this.enabledBrokerIds()) next = setExposed(next, brokerId, deviceId, exposed);
9807
+ knownBrokerIds() {
9808
+ return new Set([...this.config.knownBrokers.map((b) => b.id), ...this.enabledBrokerIds()]);
9809
+ }
9810
+ /**
9811
+ * The brokers a `device-export` read answers over: the named instance, or
9812
+ * (absent) every enabled broker. A broker this addon does not know is
9813
+ * refused, never answered empty.
9814
+ */
9815
+ brokerScope(instanceId) {
9816
+ if (instanceId === void 0) return this.enabledBrokerIds();
9817
+ if (!this.knownBrokerIds().has(instanceId)) throw new ExportInstanceUnknownError("provider-homeassistant", instanceId);
9818
+ return [instanceId];
9819
+ }
9820
+ exposedDeviceRows(scope) {
9821
+ return exposedDeviceIds(this.config.membership, scope).map((deviceId) => ({
9822
+ deviceId,
9823
+ exposedAs: brokersExposing(this.config.membership, deviceId).map((brokerId) => this.brokerName(brokerId)).join(", ")
9824
+ }));
9825
+ }
9826
+ /**
9827
+ * A cap-level expose/unexpose changes ONE broker's membership — the named
9828
+ * instance. There is no write without a target and no "everywhere": the
9829
+ * other brokers' membership is not touched.
9830
+ */
9831
+ async setBrokerMembership(instanceId, deviceId, exposed) {
9832
+ this.brokerScope(instanceId);
9833
+ const next = setExposed(this.config.membership, instanceId, deviceId, exposed);
9798
9834
  if (next === this.config.membership) {
9799
9835
  this.ctx.logger.debug("ha-export: membership already in that state, nothing to do", {
9800
9836
  tags: { deviceId: Number(deviceId) },
9801
- meta: { exposed }
9837
+ meta: {
9838
+ exposed,
9839
+ brokerId: instanceId
9840
+ }
9802
9841
  });
9803
9842
  return;
9804
9843
  }
@@ -9807,7 +9846,7 @@ var HaExportAddon = class extends BaseAddon {
9807
9846
  tags: { deviceId: Number(deviceId) },
9808
9847
  meta: {
9809
9848
  exposed,
9810
- brokers: this.enabledBrokerIds()
9849
+ brokerId: instanceId
9811
9850
  }
9812
9851
  });
9813
9852
  await this.reconcile(exposed ? "expose" : "unexpose");
@@ -9961,19 +10000,20 @@ var HaExportAddon = class extends BaseAddon {
9961
10000
  await this.reconcile("device-panel");
9962
10001
  return { success: true };
9963
10002
  }
9964
- buildStatus() {
9965
- const enabled = this.enabledBrokerIds();
9966
- const healthy = [...this.links.values()].filter((link) => link.client.healthy).length;
9967
- const linkFailure = [...this.links.values()].map((link) => link.client.failure).filter((failure) => failure !== null)[0]?.text;
10003
+ buildStatus(scope) {
10004
+ const enabled = scope;
10005
+ const links = [...this.links.entries()].filter(([brokerId]) => scope.includes(brokerId)).map(([, link]) => link);
10006
+ const healthy = links.filter((link) => link.client.healthy).length;
10007
+ const linkFailure = links.map((link) => link.client.failure).filter((failure) => failure !== null)[0]?.text;
9968
10008
  return {
9969
- linkState: enabled.length === 0 ? "unlinked" : healthy === this.links.size ? "linked" : "error",
10009
+ linkState: enabled.length === 0 ? "unlinked" : healthy === links.length ? "linked" : "error",
9970
10010
  exposedDeviceCount: exposedDeviceIds(this.config.membership, enabled).length,
9971
10011
  ...linkFailure !== void 0 ? { error: linkFailure } : this.lastError !== void 0 ? { error: this.lastError } : {},
9972
10012
  setup: {
9973
10013
  fields: [
9974
10014
  {
9975
10015
  label: "Home Assistant instances",
9976
- value: `${healthy} / ${this.links.size} reachable`
10016
+ value: `${healthy} / ${links.length} reachable`
9977
10017
  },
9978
10018
  {
9979
10019
  label: "Last push failure",