chore: Enforce a few house rules via eslint (#2539)

This commit is contained in:
Dermot Duffy
2026-06-30 17:45:13 -07:00
committed by dermotduffy
parent 5572ec728e
commit 921d45e577
100 changed files with 479 additions and 295 deletions
+3 -5
View File
@@ -29,7 +29,7 @@ export class IssueManager {
private _suspended = false;
// Reentrancy guard: evaluate() calls setState() on the condition state
// manager, which fires listeners synchronously — including the one
// manager, which fires listeners synchronously -- including the one
// registered in this constructor. Without this guard, detectDynamic()
// and presence computation would run twice per evaluation.
private _evaluating = false;
@@ -165,16 +165,14 @@ export class IssueManager {
// normal re-evaluation (on any condition-state change).
//
// `initialized: true` in the change payload means mandatory initialization
// just finished — see InitializationManager._initializeMandatory. That's
// just finished -- see InitializationManager._initializeMandatory. That's
// also the earliest point at which the full HASS object is guaranteed
// ready for websocket calls (e.g. LegacyResourceIssue's lovelace/resources
// fetch). Because `initialized` is latched (its comment notes it never
// changes again), this block fires exactly once per IssueManager life.
private _onStateChange(change: ConditionStateChange): void {
if (change.change.initialized === true && change.new.hass) {
/* async */ this._stateManager
.detectStatic(change.new.hass)
.then(() => this.evaluate());
void this._stateManager.detectStatic(change.new.hass).then(() => this.evaluate());
}
this.evaluate();
}
@@ -19,7 +19,7 @@ export class ConnectionIssue implements Issue {
private _state: ConnectionState = 'ready';
public detectDynamic(state: ConditionState): void {
// Before HASS is ever provided, leave state untouched — undefined hass is
// Before HASS is ever provided, leave state untouched -- undefined hass is
// not a disconnection, just "not yet initialized".
if (state.hass === undefined) {
return;
@@ -44,7 +44,7 @@ export class InitializationIssue extends AbstractErrorIssue {
// resources (WebSocket subscriptions, listeners) before the CAMERAS
// init aspect replaces the instance via createCameraManager().
this._api.getInitializationManager().uninitializeMandatory();
this._api.getCameraManager().destroy();
void this._api.getCameraManager().destroy();
return false;
}
@@ -37,7 +37,7 @@ export class MediaLoadIssue implements Issue {
}
// =========================================================================
// Explicit trigger — called when a component fires an issue:trigger event.
// Explicit trigger -- called when a component fires an issue:trigger event.
// =========================================================================
public trigger(context: IssueTriggerContext['media_load']): void {
@@ -45,7 +45,7 @@ export class MediaLoadIssue implements Issue {
}
// =========================================================================
// Detection — called by the manager on every state change.
// Detection -- called by the manager on every state change.
// =========================================================================
public detectDynamic(state: ConditionState): void {
@@ -62,7 +62,7 @@ export class MediaLoadIssue implements Issue {
}
// =========================================================================
// State queries — called by the manager to read current state.
// State queries -- called by the manager to read current state.
// =========================================================================
public hasIssue(): boolean {
@@ -113,7 +113,7 @@ export class MediaLoadIssue implements Issue {
}
// =========================================================================
// Retry — called by the manager to schedule a media reload.
// Retry -- called by the manager to schedule a media reload.
// =========================================================================
public needsRetry(): boolean {
@@ -144,7 +144,7 @@ export class MediaLoadIssue implements Issue {
// re-attempts loading underneath. If the retry succeeds,
// _handleMediaLoaded will clear everything when media:loaded fires. If
// it fails silently (e.g. bogus stream name), the error stays visible
// immediately — no new 10s grace period.
// immediately -- no new 10s grace period.
this._api.getViewManager().setViewWithMergedContext({ mediaEpoch });
return false;
}
@@ -212,7 +212,7 @@ export class MediaLoadIssue implements Issue {
this._timerTargetID = targetID;
this._timer.start(MEDIA_LOADING_TIMEOUT_SECONDS, () => {
// Record the error on timeout so retry() knows which epoch to bump.
// targetID is guaranteed non-null here — the null case bails at the
// targetID is guaranteed non-null here -- the null case bails at the
// top of _handleMediaNotLoaded.
this._erroredTargetIDs.add(targetID);
this._activate();
@@ -31,7 +31,7 @@ export class MediaQueryIssue extends AbstractErrorIssue {
return false;
}
this._error = null;
this._api.getViewManager().setViewByParametersWithNewQuery();
void this._api.getViewManager().setViewByParametersWithNewQuery();
// Exclusive retry. No other issue should attempt to retry until the next
// evaluation cycle, when we'll know if this was successful.
+10 -4
View File
@@ -3,7 +3,7 @@ import { summarizeNotification } from '../../components-lib/notification/summari
import { ConditionState } from '../../condition-trigger/conditions/types';
import { Notification } from '../../config/schema/actions/types';
import { HomeAssistant } from '../../ha/types';
import { isTruthy } from '../../utils/basic';
import { errorToConsole, isTruthy } from '../../utils/basic';
import {
Issue,
IssueDescription,
@@ -27,12 +27,18 @@ export class IssueStateManager implements IssueReadOnlyState {
}
// =========================================================================
// Detection — static (one-shot on init) and dynamic (on every state change).
// Detection -- static (one-shot on init) and dynamic (on every state change).
// =========================================================================
public async detectStatic(hass: HomeAssistant): Promise<void> {
for (const issue of this._issues.values()) {
await issue.detectStatic?.(hass);
try {
await issue.detectStatic?.(hass);
} catch (e) {
// Isolate one issue's detection failure so it cannot abort detection
// for the rest; log so the cause is visible.
errorToConsole(e as Error);
}
this._logIfNew(issue);
}
}
@@ -57,7 +63,7 @@ export class IssueStateManager implements IssueReadOnlyState {
}
// =========================================================================
// Queries — read active issue state.
// Queries -- read active issue state.
// =========================================================================
public getFullCardIssue(): IssueDescription | null {
+11 -11
View File
@@ -28,11 +28,11 @@ export interface KeyedIssueDescription {
}
// Map of currently active issues keyed by IssueKey, with each entry's value
// being the issue's current rendered description. Stored as a Map (not just
// a Set of keys) so that sub-state changes within an issue — e.g.
// ConnectionIssue swapping between 'lost' and 'starting' — are reflected as
// real value-level diffs to the condition state, triggering re-renders and
// any user-defined conditions that depend on issue state.
// being the issue's current rendered description. Stored as a Map (not just a
// Set of keys) so that sub-state changes within an issue -- e.g.
// ConnectionIssue swapping between 'lost' and 'starting' -- are reflected as
// real value-level diffs to the condition state, triggering re-renders and any
// user-defined conditions that depend on issue state.
export type IssuePresence = Map<IssueKey, IssueDescription>;
export interface IssueReadOnlyState {
hasFullCardIssue(): boolean;
@@ -80,7 +80,7 @@ export interface Issue {
// loop (exclusive), false to allow subsequent issues to also retry.
retry?(): boolean;
// Optional user-initiated fix. Not called by the issue infrastructure —
// Optional user-initiated fix. Not called by the issue infrastructure --
// callers (e.g. notification control actions) invoke this directly.
fix?(hass: HomeAssistant): Promise<boolean>;
@@ -92,11 +92,11 @@ export interface Issue {
// Called when the card is detached. Issues with age-based timers (e.g.
// loading-timeout timers) must stop them here so that time spent offscreen
// doesn't count against the user. Must preserve already-active issue state
// — a full-card issue visible at detach should still be visible on
// reattach. No `resume` hook: IssueManager.resume() triggers a normal
// evaluate(), so any timer that should restart is re-armed via
// detectDynamic against the current condition state.
// doesn't count against the user. Must preserve already-active issue state --
// a full-card issue visible at detach should still be visible on reattach. No
// `resume` hook: IssueManager.resume() triggers a normal evaluate(), so any
// timer that should restart is re-armed via detectDynamic against the current
// condition state.
suspend?(): void;
// Release external resources (e.g. a listener registered on another manager)