@camstack/addon-provider-homeassistant 1.2.656 → 1.2.657

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/CHANGELOG.md CHANGED
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.657] - 2026-11-04
11
+
12
+ ### Changed
13
+
14
+ - Home Assistant broker migrations no longer read as 'skipped-newer' (and no false 'Database is newer' alert) after the addon boots
15
+
10
16
  ## [1.2.656] - 2026-11-04
11
17
 
12
18
  ### Changed
package/dist/addon.js CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_ha_instance_settings = require("./ha-instance-settings-Dm0tU8iv.js");
2
+ const require_ha_instance_settings = require("./ha-instance-settings-DJXP_6Rg.js");
3
3
  let node_crypto = require("node:crypto");
4
4
  let node_zlib = require("node:zlib");
5
5
  //#region src/ha-admin-link.ts
@@ -8966,7 +8966,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
8966
8966
  onChanged: (id) => this.syncBrokerRuntime(id),
8967
8967
  probe: (settings) => this.requireRegistry().testSettings(settings)
8968
8968
  });
8969
- await this.runMigrations(require_ha_instance_settings.defineAddonMigrations(ADDON_MIGRATIONS.filter((m) => m.meta.id === FLATTEN_BROKER_RECORDS_ID), this.flattenPorts(records)));
8969
+ await this.runMigrations(require_ha_instance_settings.defineAddonMigrations(ADDON_MIGRATIONS, this.flattenPorts(records)), { only: [FLATTEN_BROKER_RECORDS_ID] });
8970
8970
  this.activeBrokers = await this.loadPersistedBrokers();
8971
8971
  this.registry = new HaBrokerRegistry(this.ctx.logger, this.ctx.eventBus);
8972
8972
  this.registry.setOnBrokerConnected((brokerId) => {
@@ -8983,7 +8983,7 @@ var HaProviderAddon = class HaProviderAddon extends require_ha_instance_settings
8983
8983
  this.reconcileAllConnectedBrokers();
8984
8984
  }, HaProviderAddon.RESYNC_INTERVAL_MS);
8985
8985
  this.ctx.logger.info("ha provider initialised", { meta: { brokerCount: this.activeBrokers.length } });
8986
- await this.runMigrations(require_ha_instance_settings.defineAddonMigrations(ADDON_MIGRATIONS.filter((m) => m.meta.id !== FLATTEN_BROKER_RECORDS_ID), this.flattenPorts(records)));
8986
+ await this.runMigrations(require_ha_instance_settings.defineAddonMigrations(ADDON_MIGRATIONS, this.flattenPorts(records)), { only: ADDON_MIGRATIONS.map((m) => m.meta.id).filter((id) => id !== FLATTEN_BROKER_RECORDS_ID) });
8987
8987
  await this.reconcileIntegrationsToBrokers();
8988
8988
  this.subscribeIntegrationLifecycle();
8989
8989
  return [
package/dist/addon.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as fanControlCapability, $t as createEvent, A as bestLocationMatch, At as runningFromMediaPlayer, B as climateControlCapability, Bt as tryConvertDelta, C as accessoriesCapability, Ct as pressureSensorCapability, D as ambientLightSensorCapability, Dt as resolveAttachmentUrls, E as alarmPanelCapability, Et as quantityFromUnit, F as buildAddonRouteProvider, Ft as smokeCapability, G as contactCapability, Gt as vibrationCapability, H as connectivityCapability, Ht as updateCapability, I as buildDeviceAdminUrl, J as deviceAdminLinkCapability, K as controlCapability, Kt as waterHeaterCapability, L as buttonCapability, Lt as switchCapability, M as boardKeySourceCapability, Mt as runningStateCapability, N as brightnessCapability, Nt as scriptRunnerCapability, O as automationControlCapability, P as brokerCapability, Q as eventEmitterCapability, Qt as baseUnitOf, R as calendarSourceCapability, Rt as tamperCapability, S as TargetSchema, Sn as EventCategory, St as presenceCapability, T as airQualitySensorCapability, Tt as publicEndpointReaderFrom, Ut as vacuumControlCapability, V as colorCapability, Vt as tryConvertUnit, Wt as valveCapability, Xt as RecordSecretUnavailableError, Y as deviceAdoptionCapability, Z as enumSensorCapability, _n as url, at as humiditySensorCapability, b as RUNNING_STATE_COLD, bn as DeviceType, bt as preconditionOf, cn as boolean, ct as integrationInstancesCapability, dn as number, dt as mediaPlayerCapability, en as defineAddonMigrations, et as flattenNestedRecords, fn as object, ft as motionCapability, gn as unknown, gt as numericSensorCapability, hn as union, ht as notifierCapability, it as humidifierCapability, j as binaryCapability, jt as runningFromVacuumState, k as batteryCapability, kt as runningFromLawnMower, ln as discriminatedUnion, lt as lawnMowerControlCapability, m as EnumSensorDateTimeFormatSchema, mn as string, mt as notificationOutputCapability, n as HA_BROKER_KIND, nn as defineRecordKinds, nt as floodCapability, o as BaseDevice, on as _enum, ot as imageCapability, pn as record, pt as normalizeUnit, q as coverCapability, qt as weatherCapability, rn as entryBody, rt as gasCapability, s as BaseDeviceProvider, sn as array, st as ingestReading, t as haInstanceSettingsPortsOver, tn as defineEntryKind, tt as flattenPortsOver, un as literal, ut as lockControlCapability, vn as DeviceFeature, vt as parseAdminBase, w as addonRoutesCapability, x as RecordIntegrationInstances, xn as errMsg, xt as prepareNotification, yn as DeviceRole, yt as powerMeterCapability, z as carbonMonoxideCapability, zt as temperatureSensorCapability } from "./ha-instance-settings-EQ5Ey3Q-.mjs";
1
+ import { $ as fanControlCapability, $t as createEvent, A as bestLocationMatch, At as runningFromMediaPlayer, B as climateControlCapability, Bt as tryConvertDelta, C as accessoriesCapability, Ct as pressureSensorCapability, D as ambientLightSensorCapability, Dt as resolveAttachmentUrls, E as alarmPanelCapability, Et as quantityFromUnit, F as buildAddonRouteProvider, Ft as smokeCapability, G as contactCapability, Gt as vibrationCapability, H as connectivityCapability, Ht as updateCapability, I as buildDeviceAdminUrl, J as deviceAdminLinkCapability, K as controlCapability, Kt as waterHeaterCapability, L as buttonCapability, Lt as switchCapability, M as boardKeySourceCapability, Mt as runningStateCapability, N as brightnessCapability, Nt as scriptRunnerCapability, O as automationControlCapability, P as brokerCapability, Q as eventEmitterCapability, Qt as baseUnitOf, R as calendarSourceCapability, Rt as tamperCapability, S as TargetSchema, Sn as EventCategory, St as presenceCapability, T as airQualitySensorCapability, Tt as publicEndpointReaderFrom, Ut as vacuumControlCapability, V as colorCapability, Vt as tryConvertUnit, Wt as valveCapability, Xt as RecordSecretUnavailableError, Y as deviceAdoptionCapability, Z as enumSensorCapability, _n as url, at as humiditySensorCapability, b as RUNNING_STATE_COLD, bn as DeviceType, bt as preconditionOf, cn as boolean, ct as integrationInstancesCapability, dn as number, dt as mediaPlayerCapability, en as defineAddonMigrations, et as flattenNestedRecords, fn as object, ft as motionCapability, gn as unknown, gt as numericSensorCapability, hn as union, ht as notifierCapability, it as humidifierCapability, j as binaryCapability, jt as runningFromVacuumState, k as batteryCapability, kt as runningFromLawnMower, ln as discriminatedUnion, lt as lawnMowerControlCapability, m as EnumSensorDateTimeFormatSchema, mn as string, mt as notificationOutputCapability, n as HA_BROKER_KIND, nn as defineRecordKinds, nt as floodCapability, o as BaseDevice, on as _enum, ot as imageCapability, pn as record, pt as normalizeUnit, q as coverCapability, qt as weatherCapability, rn as entryBody, rt as gasCapability, s as BaseDeviceProvider, sn as array, st as ingestReading, t as haInstanceSettingsPortsOver, tn as defineEntryKind, tt as flattenPortsOver, un as literal, ut as lockControlCapability, vn as DeviceFeature, vt as parseAdminBase, w as addonRoutesCapability, x as RecordIntegrationInstances, xn as errMsg, xt as prepareNotification, yn as DeviceRole, yt as powerMeterCapability, z as carbonMonoxideCapability, zt as temperatureSensorCapability } from "./ha-instance-settings-CxalgfRa.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
4
4
  //#region src/ha-admin-link.ts
@@ -8945,7 +8945,7 @@ var HaProviderAddon = class HaProviderAddon extends BaseDeviceProvider {
8945
8945
  onChanged: (id) => this.syncBrokerRuntime(id),
8946
8946
  probe: (settings) => this.requireRegistry().testSettings(settings)
8947
8947
  });
8948
- await this.runMigrations(defineAddonMigrations(ADDON_MIGRATIONS.filter((m) => m.meta.id === FLATTEN_BROKER_RECORDS_ID), this.flattenPorts(records)));
8948
+ await this.runMigrations(defineAddonMigrations(ADDON_MIGRATIONS, this.flattenPorts(records)), { only: [FLATTEN_BROKER_RECORDS_ID] });
8949
8949
  this.activeBrokers = await this.loadPersistedBrokers();
8950
8950
  this.registry = new HaBrokerRegistry(this.ctx.logger, this.ctx.eventBus);
8951
8951
  this.registry.setOnBrokerConnected((brokerId) => {
@@ -8962,7 +8962,7 @@ var HaProviderAddon = class HaProviderAddon extends BaseDeviceProvider {
8962
8962
  this.reconcileAllConnectedBrokers();
8963
8963
  }, HaProviderAddon.RESYNC_INTERVAL_MS);
8964
8964
  this.ctx.logger.info("ha provider initialised", { meta: { brokerCount: this.activeBrokers.length } });
8965
- await this.runMigrations(defineAddonMigrations(ADDON_MIGRATIONS.filter((m) => m.meta.id !== FLATTEN_BROKER_RECORDS_ID), this.flattenPorts(records)));
8965
+ await this.runMigrations(defineAddonMigrations(ADDON_MIGRATIONS, this.flattenPorts(records)), { only: ADDON_MIGRATIONS.map((m) => m.meta.id).filter((id) => id !== FLATTEN_BROKER_RECORDS_ID) });
8966
8966
  await this.reconcileIntegrationsToBrokers();
8967
8967
  this.subscribeIntegrationLifecycle();
8968
8968
  return [
@@ -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-Dm0tU8iv.js");
27
+ const require_ha_instance_settings = require("../ha-instance-settings-DJXP_6Rg.js");
28
28
  let node_crypto = require("node:crypto");
29
29
  require("node:zlib");
30
30
  let node_fs = require("node:fs");
@@ -1,4 +1,4 @@
1
- import { F as buildAddonRouteProvider, It as statusInstanceOf, Jt as BaseAddon, Ot as runExportedAction, Pt as sendToExportedTarget, Qt as baseUnitOf, Sn as EventCategory, U as consumableFormOf, W as consumableKindOf, X as deviceExportCapability, Zt as RevConflictError, _ as HvacModeSchema, _t as oauthIntegrationCapability, a as AlarmArmModeSchema, an as nodePin, bt as preconditionOf, c as CAMERA_SWITCH_ORDER, cn as boolean, d as ConsumableFormSchema, en as defineAddonMigrations, f as ConsumableItemSchema, fn as object, g as FanDirectionSchema, gn as unknown, h as ExportInstanceUnknownError, i as listHomeAssistantBrokers, in as isReadingQuantity, l as COCO_TO_MACRO, mn as string, on as _enum, p as ConsumableStatusSchema, sn as array, t as haInstanceSettingsPortsOver, tn as defineEntryKind, u as CameraSwitchIdSchema, v as MediaPlayerRepeatSchema, w as addonRoutesCapability, wt as pruneDeletedEntities, y as PLUG_APPLIANCE_TYPES } from "../ha-instance-settings-EQ5Ey3Q-.mjs";
1
+ import { F as buildAddonRouteProvider, It as statusInstanceOf, Jt as BaseAddon, Ot as runExportedAction, Pt as sendToExportedTarget, Qt as baseUnitOf, Sn as EventCategory, U as consumableFormOf, W as consumableKindOf, X as deviceExportCapability, Zt as RevConflictError, _ as HvacModeSchema, _t as oauthIntegrationCapability, a as AlarmArmModeSchema, an as nodePin, bt as preconditionOf, c as CAMERA_SWITCH_ORDER, cn as boolean, d as ConsumableFormSchema, en as defineAddonMigrations, f as ConsumableItemSchema, fn as object, g as FanDirectionSchema, gn as unknown, h as ExportInstanceUnknownError, i as listHomeAssistantBrokers, in as isReadingQuantity, l as COCO_TO_MACRO, mn as string, on as _enum, p as ConsumableStatusSchema, sn as array, t as haInstanceSettingsPortsOver, tn as defineEntryKind, u as CameraSwitchIdSchema, v as MediaPlayerRepeatSchema, w as addonRoutesCapability, wt as pruneDeletedEntities, y as PLUG_APPLIANCE_TYPES } from "../ha-instance-settings-CxalgfRa.mjs";
2
2
  import { createHmac, timingSafeEqual } from "node:crypto";
3
3
  import "node:zlib";
4
4
  import "node:fs";
@@ -5980,7 +5980,7 @@ var ZodIssueCode = {
5980
5980
  var ZodFirstPartyTypeKind;
5981
5981
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5982
5982
  //#endregion
5983
- //#region ../types/dist/sleep-BaWhXZFm.mjs
5983
+ //#region ../types/dist/sleep-Cv4Zmie9.mjs
5984
5984
  /**
5985
5985
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5986
5986
  * window to float samples (D455).
@@ -6590,7 +6590,7 @@ var NOT_RUN = {
6590
6590
  * throws: an unreachable or refusing engine is logged and reported `declared: false`,
6591
6591
  * because the hub (and this addon's boot) must not hang on a migration.
6592
6592
  */
6593
- async function runAddonMigrations(host, migrations, logger) {
6593
+ async function runAddonMigrations(host, migrations, logger, options = {}) {
6594
6594
  const first = migrations[0];
6595
6595
  if (first === void 0) return NOT_RUN;
6596
6596
  const owner = first.meta.owner;
@@ -6619,7 +6619,9 @@ async function runAddonMigrations(host, migrations, logger) {
6619
6619
  else if (status === "blocked") blocked.push(id);
6620
6620
  else skipped.push(id);
6621
6621
  };
6622
+ const selected = options.only === void 0 ? null : new Set(options.only);
6622
6623
  for (const step of declaration.steps) {
6624
+ if (selected !== null && !selected.has(step.id)) continue;
6623
6625
  const bound = byId.get(step.id);
6624
6626
  if (bound === void 0 || step.action === "skip") {
6625
6627
  skipped.push(step.id);
@@ -7779,14 +7781,18 @@ var BaseAddon = class {
7779
7781
  * nothing; the boot continues. A migration that FAILED (or was blocked by one)
7780
7782
  * and declares `onFailure: 'block-owner'` makes this throw, so the addon does not
7781
7783
  * serve data whose shape it cannot trust; `tolerate` migrations never do.
7784
+ *
7785
+ * ALWAYS pass the whole catalogue; a phase that must run only some of it passes
7786
+ * `{ only: [ids] }` — never a filtered catalogue (the engine would judge the
7787
+ * omitted applied ids "newer").
7782
7788
  */
7783
- async runMigrations(migrations) {
7789
+ async runMigrations(migrations, options) {
7784
7790
  const api = this.ctx.api.migrations;
7785
7791
  const report = await runAddonMigrations({
7786
7792
  declareOwner: (input) => api.declareOwner.mutate(input),
7787
7793
  startMigration: (input) => api.startMigration.mutate(input),
7788
7794
  finishMigration: (input) => api.finishMigration.mutate(input)
7789
- }, migrations, this.ctx.logger);
7795
+ }, migrations, this.ctx.logger, options);
7790
7796
  if (report.blockOwner.length > 0) throw new AddonMigrationsBlockedError(report.blockOwner);
7791
7797
  return report;
7792
7798
  }
@@ -14724,7 +14730,13 @@ var MigrationLedgerEntrySchema = object({
14724
14730
  * joined by the engine from the catalogues it knows this boot. Absent when no
14725
14731
  * catalogue lists the id (a newer database).
14726
14732
  */
14727
- meta: MigrationMetaSchema.optional()
14733
+ meta: MigrationMetaSchema.optional(),
14734
+ /**
14735
+ * Set when this is an applied row of an addon owner whose catalogue the answering
14736
+ * process has not loaded (the owner has not declared yet): the row is applied, the
14737
+ * process just cannot judge it. Never `skipped-newer` — that needs the owner loaded.
14738
+ */
14739
+ ownerNotLoaded: boolean().optional()
14728
14740
  });
14729
14741
  /** A catalogued migration that is not applied, with where it stands. */
14730
14742
  var MigrationPendingEntrySchema = object({
@@ -5981,7 +5981,7 @@ var ZodIssueCode = {
5981
5981
  var ZodFirstPartyTypeKind;
5982
5982
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5983
5983
  //#endregion
5984
- //#region ../types/dist/sleep-BaWhXZFm.mjs
5984
+ //#region ../types/dist/sleep-Cv4Zmie9.mjs
5985
5985
  /**
5986
5986
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5987
5987
  * window to float samples (D455).
@@ -6591,7 +6591,7 @@ var NOT_RUN = {
6591
6591
  * throws: an unreachable or refusing engine is logged and reported `declared: false`,
6592
6592
  * because the hub (and this addon's boot) must not hang on a migration.
6593
6593
  */
6594
- async function runAddonMigrations(host, migrations, logger) {
6594
+ async function runAddonMigrations(host, migrations, logger, options = {}) {
6595
6595
  const first = migrations[0];
6596
6596
  if (first === void 0) return NOT_RUN;
6597
6597
  const owner = first.meta.owner;
@@ -6620,7 +6620,9 @@ async function runAddonMigrations(host, migrations, logger) {
6620
6620
  else if (status === "blocked") blocked.push(id);
6621
6621
  else skipped.push(id);
6622
6622
  };
6623
+ const selected = options.only === void 0 ? null : new Set(options.only);
6623
6624
  for (const step of declaration.steps) {
6625
+ if (selected !== null && !selected.has(step.id)) continue;
6624
6626
  const bound = byId.get(step.id);
6625
6627
  if (bound === void 0 || step.action === "skip") {
6626
6628
  skipped.push(step.id);
@@ -7780,14 +7782,18 @@ var BaseAddon = class {
7780
7782
  * nothing; the boot continues. A migration that FAILED (or was blocked by one)
7781
7783
  * and declares `onFailure: 'block-owner'` makes this throw, so the addon does not
7782
7784
  * serve data whose shape it cannot trust; `tolerate` migrations never do.
7785
+ *
7786
+ * ALWAYS pass the whole catalogue; a phase that must run only some of it passes
7787
+ * `{ only: [ids] }` — never a filtered catalogue (the engine would judge the
7788
+ * omitted applied ids "newer").
7783
7789
  */
7784
- async runMigrations(migrations) {
7790
+ async runMigrations(migrations, options) {
7785
7791
  const api = this.ctx.api.migrations;
7786
7792
  const report = await runAddonMigrations({
7787
7793
  declareOwner: (input) => api.declareOwner.mutate(input),
7788
7794
  startMigration: (input) => api.startMigration.mutate(input),
7789
7795
  finishMigration: (input) => api.finishMigration.mutate(input)
7790
- }, migrations, this.ctx.logger);
7796
+ }, migrations, this.ctx.logger, options);
7791
7797
  if (report.blockOwner.length > 0) throw new AddonMigrationsBlockedError(report.blockOwner);
7792
7798
  return report;
7793
7799
  }
@@ -14725,7 +14731,13 @@ var MigrationLedgerEntrySchema = object({
14725
14731
  * joined by the engine from the catalogues it knows this boot. Absent when no
14726
14732
  * catalogue lists the id (a newer database).
14727
14733
  */
14728
- meta: MigrationMetaSchema.optional()
14734
+ meta: MigrationMetaSchema.optional(),
14735
+ /**
14736
+ * Set when this is an applied row of an addon owner whose catalogue the answering
14737
+ * process has not loaded (the owner has not declared yet): the row is applied, the
14738
+ * process just cannot judge it. Never `skipped-newer` — that needs the owner loaded.
14739
+ */
14740
+ ownerNotLoaded: boolean().optional()
14729
14741
  });
14730
14742
  /** A catalogued migration that is not applied, with where it stands. */
14731
14743
  var MigrationPendingEntrySchema = object({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-homeassistant",
3
- "version": "1.2.656",
3
+ "version": "1.2.657",
4
4
  "description": "Home Assistant device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",
@@ -134,7 +134,7 @@
134
134
  "description": "Device provider (import) + native entity export (push). Two addons, one bundle, separate processes."
135
135
  },
136
136
  "requires": {
137
- "server": ">=1.2.762"
137
+ "server": ">=1.2.763"
138
138
  }
139
139
  },
140
140
  "files": [