Add Registry class.

The class is an optimized version of the Helper class.

- Sanitization of the HASS registries after import according to the
  configuration options.
- Improved error handling and logging.
- Removed generic utility functions.
This commit is contained in:
DigiLive
2025-04-23 07:39:28 +02:00
parent d224fc353c
commit 3725b89f9e

View File

@@ -1,8 +1,11 @@
import deepmerge from 'deepmerge'; import deepmerge from "deepmerge";
import { HassEntities } from 'home-assistant-js-websocket'; import {HassEntities} from "home-assistant-js-websocket";
import { AreaRegistryEntry } from './types/homeassistant/data/area_registry'; import {ConfigurationDefaults} from "./configurationDefaults";
import { DeviceRegistryEntry } from './types/homeassistant/data/device_registry'; import {AreaRegistryEntry} from "./types/homeassistant/data/area_registry";
import { EntityRegistryEntry } from './types/homeassistant/data/entity_registry'; import {DeviceRegistryEntry} from "./types/homeassistant/data/device_registry";
import {EntityRegistryEntry} from "./types/homeassistant/data/entity_registry";
import {LovelaceCardConfig} from "./types/homeassistant/data/lovelace/config/card";
import {StackCardConfig} from "./types/homeassistant/panels/lovelace/cards/types";
import { import {
AllDomainsConfig, AllDomainsConfig,
DashboardInfo, DashboardInfo,
@@ -13,10 +16,10 @@ import {
StrategyViewConfig, StrategyViewConfig,
SupportedDomains, SupportedDomains,
SupportedViews, SupportedViews,
} from './types/strategy/strategy-generics'; } from "./types/strategy/strategy-generics";
import { logMessage, lvlFatal, lvlOff, lvlWarn, setDebugLevel } from './utilities/debug'; import {logMessage, lvlDebug, lvlFatal, lvlOff, lvlWarn, setDebugLevel} from "./utilities/debug";
import setupCustomLocalize from './utilities/localize'; import setupCustomLocalize from "./utilities/localize";
import RegistryFilter from './utilities/RegistryFilter'; import RegistryFilter from "./utilities/RegistryFilter";
/** /**
* Registry Class * Registry Class
@@ -104,11 +107,11 @@ class Registry {
* @param {DashboardInfo} info Strategy information object. * @param {DashboardInfo} info Strategy information object.
*/ */
static async initialize(info: DashboardInfo): Promise<void> { static async initialize(info: DashboardInfo): Promise<void> {
setDebugLevel(lvlFatal);
setupCustomLocalize(info.hass); setupCustomLocalize(info.hass);
// Import the Hass States and strategy options. // Import the Hass States and strategy options.
Registry._hassStates = info.hass.states; Registry._hassStates = info.hass.states;
const { ConfigurationDefaults } = await import('./configurationDefaults');
try { try {
Registry._strategyOptions = deepmerge(ConfigurationDefaults, info.config?.strategy?.options ?? {}); Registry._strategyOptions = deepmerge(ConfigurationDefaults, info.config?.strategy?.options ?? {});
@@ -116,7 +119,7 @@ class Registry {
logMessage(lvlFatal, 'Error importing strategy options!', e); logMessage(lvlFatal, 'Error importing strategy options!', e);
} }
setDebugLevel(Registry.strategyOptions.debug ? lvlFatal : lvlOff); setDebugLevel(Registry.strategyOptions.debug ? lvlDebug : lvlOff);
// Import the registries of Home Assistant. // Import the registries of Home Assistant.
try { try {
@@ -130,12 +133,6 @@ class Registry {
logMessage(lvlFatal, 'Error importing Home Assistant registries!', e); logMessage(lvlFatal, 'Error importing Home Assistant registries!', e);
} }
// Process the entries of the Strategy Options.
Registry._strategyOptions.extra_views.map((view) => ({
...view,
subview: false,
}));
// Process entries of the HASS entity registry. // Process entries of the HASS entity registry.
Registry._entities = new RegistryFilter(Registry.entities) Registry._entities = new RegistryFilter(Registry.entities)
.not() .not()
@@ -165,9 +162,7 @@ class Registry {
})); }));
// Process entries of the HASS area registry. // Process entries of the HASS area registry.
if (Registry.strategyOptions.areas._?.hidden) { if (!Registry.strategyOptions.areas._?.hidden) {
Registry._areas = [];
} else {
// Create and add the undisclosed area if not hidden in the strategy options. // Create and add the undisclosed area if not hidden in the strategy options.
if (!Registry.strategyOptions.areas.undisclosed?.hidden) { if (!Registry.strategyOptions.areas.undisclosed?.hidden) {
Registry.areas.push(ConfigurationDefaults.areas.undisclosed); Registry.areas.push(ConfigurationDefaults.areas.undisclosed);
@@ -185,14 +180,16 @@ class Registry {
// Remove hidden areas if configured as so and sort them by name. // Remove hidden areas if configured as so and sort them by name.
Registry._areas = new RegistryFilter(Registry.areas).isNotHidden().orderBy(['order', 'name'], 'asc').toList(); Registry._areas = new RegistryFilter(Registry.areas).isNotHidden().orderBy(['order', 'name'], 'asc').toList();
} else {
Registry._areas = [];
} }
// Sort views by order first and then by title. // Sort views by order first and then by title.
const sortViews = () => { const sortViews = () => {
const entries = Object.entries(Registry.strategyOptions.views); const viewEntries = Object.entries(Registry.strategyOptions.views);
Registry.strategyOptions.views = Object.fromEntries( Registry.strategyOptions.views = Object.fromEntries(
entries.sort(([_, a], [__, b]) => { viewEntries.sort(([_, a], [__, b]) => {
return (a.order ?? Infinity) - (b.order ?? Infinity) || (a.title ?? '').localeCompare(b.title ?? ''); return (a.order ?? Infinity) - (b.order ?? Infinity) || (a.title ?? '').localeCompare(b.title ?? '');
}), }),
) as Record<SupportedViews, StrategyViewConfig>; ) as Record<SupportedViews, StrategyViewConfig>;
@@ -202,9 +199,9 @@ class Registry {
// Sort domains by order first and then by title. // Sort domains by order first and then by title.
const sortDomains = () => { const sortDomains = () => {
const entries = Object.entries(Registry.strategyOptions.domains); const domainEntries = Object.entries(Registry.strategyOptions.domains);
Registry.strategyOptions.domains = Object.fromEntries( Registry.strategyOptions.domains = Object.fromEntries(
entries.sort(([, a], [, b]) => { domainEntries.sort(([, a], [, b]) => {
if (isSortable(a) && isSortable(b)) { if (isSortable(a) && isSortable(b)) {
return (a.order ?? Infinity) - (b.order ?? Infinity) || (a.title ?? '').localeCompare(b.title ?? ''); return (a.order ?? Infinity) - (b.order ?? Infinity) || (a.title ?? '').localeCompare(b.title ?? '');
} }
@@ -216,16 +213,6 @@ class Registry {
sortDomains(); sortDomains();
// Sort extra views by order first and then by title.
// TODO: Add sorting to the wiki.
const sortExtraViews = () => {
Registry.strategyOptions.extra_views.sort((a, b) => {
return (a.order ?? Infinity) - (b.order ?? Infinity) || (a.title ?? '').localeCompare(b.title ?? '');
});
};
sortExtraViews();
Registry._initialized = true; Registry._initialized = true;
} }
@@ -258,7 +245,6 @@ class Registry {
states.push( states.push(
...new RegistryFilter(Registry.entities) ...new RegistryFilter(Registry.entities)
.whereDomain(domain) .whereDomain(domain)
.where((entity) => !entity.entity_id.endsWith('_stateful_scene'))
.toList() .toList()
.map((entity) => `states['${entity.entity_id}']`), .map((entity) => `states['${entity.entity_id}']`),
); );
@@ -273,6 +259,27 @@ class Registry {
}}`; }}`;
} }
/**
* Splits an array of card configurations into horizontal stack card configurations.
*
* Each horizontal stack contains a specified number of cards.
*
* @param {LovelaceCardConfig[]} cardConfigurations - Array of card configurations to be stacked.
* @param {number} columnCount - Number of cards per horizontal stack.
*/
static stackHorizontal(cardConfigurations: LovelaceCardConfig[], columnCount: number): StackCardConfig[] {
const stackedCardConfigurations: StackCardConfig[] = [];
for (let i = 0; i < cardConfigurations.length; i += columnCount) {
stackedCardConfigurations.push({
type: 'horizontal-stack',
cards: cardConfigurations.slice(i, i + columnCount),
} as StackCardConfig);
}
return stackedCardConfigurations;
}
/** /**
* Get the names of the specified type which aren't set to hidden in the strategy options. * Get the names of the specified type which aren't set to hidden in the strategy options.
* *