Files
healthchat-web/apps/web/scripts/healthchat-sync-theme.mjs
T
joel.poyet f33708c705 refactor(theme): single-source the HealthChat Light theme
Author the theme once in apps/web/element.io/healthchat/HealthChat-Light-Theme.json
and sync it into the web (apps/web/config.json) and desktop
(apps/desktop/element.io/healthchat/config.json) configs via
scripts/healthchat-sync-theme.mjs, removing the drifted duplicate.
`pnpm healthchat:theme` writes it; `pnpm lint` runs healthchat:theme:check to
fail on drift.

The canonical palette is the reviewed desktop theme, which reverts the web-only
contrast tweak (f64923ea1a) so web and desktop match.
2026-07-14 14:02:39 +02:00

71 lines
2.7 KiB
JavaScript

#!/usr/bin/env node
/*
* HealthChat theme sync.
*
* Single source of truth for the "HealthChat Light" theme lives in
* apps/web/element.io/healthchat/HealthChat-Light-Theme.json
* This script injects it into every element-web config that ships the theme, so the palette
* is authored once and never drifts between the dev and desktop configs.
*
* The production web deployment (matrix-docker-ansible-deploy) renders its config.json from
* host_vars and carries an inline copy of this theme; re-copy this file there when it changes.
*
* Usage:
* node apps/web/scripts/healthchat-sync-theme.mjs # write the theme into all configs
* node apps/web/scripts/healthchat-sync-theme.mjs --check # exit 1 if any config is out of sync
*
* Run `pnpm --filter element-web healthchat:theme` after editing the canonical theme;
* the --check variant runs in lint/CI to catch an un-synced edit.
*/
import { readFileSync, writeFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { dirname, resolve } from "node:path";
import prettier from "prettier";
const scriptDir = dirname(fileURLToPath(import.meta.url));
const repoRoot = resolve(scriptDir, "../../..");
const CANONICAL = resolve(repoRoot, "apps/web/element.io/healthchat/HealthChat-Light-Theme.json");
// Configs that must carry the theme in setting_defaults.custom_themes.
const TARGETS = [
"apps/web/config.json", // dev server config (also served by the web Docker image)
"apps/desktop/element.io/healthchat/config.json", // desktop variant config bundled into the app
];
const check = process.argv.includes("--check");
const theme = JSON.parse(readFileSync(CANONICAL, "utf8"));
let changed = 0;
for (const rel of TARGETS) {
const path = resolve(repoRoot, rel);
const raw = readFileSync(path, "utf8");
const config = JSON.parse(raw);
config.setting_defaults ??= {};
config.setting_defaults.custom_themes = [theme];
// Format identically to `prettier --write` so the output is byte-for-byte what the
// repo's formatting lint expects, keeping --check stable.
const options = await prettier.resolveConfig(path);
const next = await prettier.format(JSON.stringify(config), { ...options, filepath: path });
if (next === raw) {
continue;
}
changed++;
if (check) {
console.error(`out of sync: ${rel} (run: pnpm --filter element-web healthchat:theme)`);
} else {
writeFileSync(path, next);
console.log(`synced theme -> ${rel}`);
}
}
if (check) {
if (changed > 0) process.exit(1);
console.log("all configs in sync with the canonical HealthChat theme");
} else if (changed === 0) {
console.log("all configs already in sync");
}