repositories / pi-ext
pi-ext
bugabingas pi extensions
owned by admin
extensions/horst/settings.ts
Raw// horst — settings.
//
// Parses the `horst` block from Pi settings.
export interface HorstToolDelta {
add?: string[];
remove?: string[];
}
export interface HorstSettings {
os: Record<string, HorstToolDelta>;
hosts: Record<string, HorstToolDelta>;
preferredShell?: string;
}
export const EMPTY_HORST_SETTINGS: HorstSettings = { os: {}, hosts: {} };
export function horstOsKey(platform: string): string | undefined {
if (platform === "linux") return "lnx";
if (platform === "darwin") return "mac";
if (platform === "win32") return "win32";
return undefined;
}
function isObject(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
function toolNames(value: unknown, at: string): string[] | undefined {
if (value === undefined) return undefined;
if (
!Array.isArray(value) ||
!value.every((name) => typeof name === "string" && name.trim())
)
throw new Error(`${at} must be an array of non-empty strings`);
return value.length > 0 ? value : undefined;
}
function pickMap(value: unknown, at: string): Record<string, HorstToolDelta> {
if (value === undefined) return {};
if (!isObject(value)) throw new Error(`${at} must be an object`);
const map: Record<string, HorstToolDelta> = {};
for (const [key, entry] of Object.entries(value)) {
const tools = isObject(entry) ? entry.tools : undefined;
if (!isObject(tools))
throw new Error(`${at}.${key}.tools must be an object`);
const delta: HorstToolDelta = {};
const add = toolNames(tools.add, `${at}.${key}.tools.add`);
const remove = toolNames(tools.remove, `${at}.${key}.tools.remove`);
if (add) delta.add = add;
if (remove) delta.remove = remove;
if (delta.add || delta.remove) map[key.toLowerCase()] = delta;
}
return map;
}
/** Validate the `horst` block; throws on malformed values. */
export function parseHorst(raw: unknown): HorstSettings {
if (!isObject(raw)) throw new Error("expected an object");
const { preferredShell } = raw;
if (
preferredShell !== undefined &&
(typeof preferredShell !== "string" || !preferredShell.trim())
)
throw new Error("preferredShell must be a non-empty string");
return {
os: pickMap(raw.os, "os"),
hosts: pickMap(raw.hosts, "hosts"),
...(preferredShell ? { preferredShell: preferredShell.trim() } : {}),
};
}
/**
* Resolve the tool delta for this machine.
* `os` deltas apply first, a matching `hosts` entry wins per field.
*/
export function resolveHorstTools(
settings: HorstSettings,
platform: string,
hostname: string,
): HorstToolDelta | undefined {
const osDelta = settings.os[horstOsKey(platform) ?? ""];
const hostDelta = settings.hosts[hostname.toLowerCase()];
if (!osDelta && !hostDelta) return undefined;
return {
add: hostDelta?.add ?? osDelta?.add,
remove: hostDelta?.remove ?? osDelta?.remove,
};
}