All files / packages/adapters/home-assistant/src pairings.ts

100% Statements 15/15
100% Branches 9/9
100% Functions 2/2
100% Lines 15/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89                                                            2x                                       45x   45x 45x 1x   44x 1x         43x 43x 1x   42x 1x         41x                       7x 28x      
// SPDX-License-Identifier: MIT
/**
 * Auto-theme vendor pairings for the Home Assistant adapter.
 *
 * Home Assistant supports "auto" themes that switch between a dark and light
 * variant based on the user's system color scheme, via a `modes:` block. Each
 * pairing couples a Turbo dark flavor with its light counterpart.
 */
 
import type { ThemeTokens } from '@lgtm-hq/turbo-themes-core/themes/types';
import { getTheme } from '@lgtm-hq/turbo-themes-core';
 
/** A dark/light pairing that becomes a single Home Assistant auto theme. */
export interface AutoThemePairing {
  /** Human-readable Home Assistant theme name, e.g. `"Catppuccin (Auto)"`. */
  readonly name: string;
  /** Registry id of the dark flavor (also used for the flat top-level keys). */
  readonly dark: string;
  /** Registry id of the light flavor. */
  readonly light: string;
}
 
/** A pairing whose dark/light flavors have been resolved to concrete tokens. */
export interface ResolvedAutoTheme {
  readonly name: string;
  readonly darkTokens: ThemeTokens;
  readonly lightTokens: ThemeTokens;
}
 
/** Dark/light flavor pairings, one per vendor family, emitted as auto themes. */
export const AUTO_THEME_PAIRINGS: readonly AutoThemePairing[] = [
  { name: 'Bulma (Auto)', dark: 'bulma-dark', light: 'bulma-light' },
  { name: 'Catppuccin (Auto)', dark: 'catppuccin-mocha', light: 'catppuccin-latte' },
  { name: 'GitHub (Auto)', dark: 'github-dark', light: 'github-light' },
  { name: 'Gruvbox (Auto)', dark: 'gruvbox-dark', light: 'gruvbox-light' },
  { name: 'One (Auto)', dark: 'one-dark', light: 'one-light' },
  { name: 'Rosé Pine (Auto)', dark: 'rose-pine', light: 'rose-pine-dawn' },
  { name: 'Solarized (Auto)', dark: 'solarized-dark', light: 'solarized-light' },
  { name: 'Tokyo Night (Auto)', dark: 'tokyo-night-dark', light: 'tokyo-night-light' },
] as const;
 
/**
 * Resolve a pairing to its concrete dark/light tokens, validating as it goes.
 *
 * @param pairing - The pairing to resolve.
 * @returns The pairing name plus the resolved dark and light token sets.
 * @throws If either id is missing from the registry, or an id's appearance does
 *   not match the slot it occupies (dark slot must be dark, light slot light).
 */
export function resolveAutoTheme(pairing: AutoThemePairing): ResolvedAutoTheme {
  const { name, dark, light } = pairing;
 
  const darkTheme = getTheme(dark);
  if (!darkTheme) {
    throw new Error(`Auto theme "${name}" references unknown dark theme id "${dark}"`);
  }
  if (darkTheme.appearance !== 'dark') {
    throw new Error(
      `Auto theme "${name}" dark slot "${dark}" has appearance "${darkTheme.appearance}", expected "dark"`,
    );
  }
 
  const lightTheme = getTheme(light);
  if (!lightTheme) {
    throw new Error(`Auto theme "${name}" references unknown light theme id "${light}"`);
  }
  if (lightTheme.appearance !== 'light') {
    throw new Error(
      `Auto theme "${name}" light slot "${light}" has appearance "${lightTheme.appearance}", expected "light"`,
    );
  }
 
  return { name, darkTokens: darkTheme.tokens, lightTokens: lightTheme.tokens };
}
 
/**
 * Validate every pairing, throwing on the first problem.
 *
 * @param pairings - Pairings to validate (defaults to {@link AUTO_THEME_PAIRINGS}).
 * @throws If any pairing is invalid; see {@link resolveAutoTheme}.
 */
export function assertPairingsValid(
  pairings: readonly AutoThemePairing[] = AUTO_THEME_PAIRINGS,
): void {
  for (const pairing of pairings) {
    resolveAutoTheme(pairing);
  }
}