// server/templates/render.ts import Mustache from "mustache"; import { readFileSync, existsSync } from "node:fs"; import { resolve } from "node:path"; const TEMPLATES_ROOT = resolve(process.cwd(), "templates"); export interface TemplateVars { aptProxy?: string | null; } export function renderTemplate(relPath: string, vars: TemplateVars): string { const tpl = readFileSync(resolve(TEMPLATES_ROOT, relPath), "utf8"); // Mustache échappe le HTML par défaut; on désactive (ce sont des scripts shell). return Mustache.render(tpl, vars, {}, { escape: (s) => s }); } /** Existence par défaut d'un template relatif à templates/. */ function defaultExists(rel: string): boolean { return existsSync(resolve(TEMPLATES_ROOT, rel)); } /** * Résout le chemin de template le plus spécifique pour (action, OS) : * `/.sh.tpl` s'il existe, sinon fallback base `apt/.sh.tpl`. * `exists` est injectable pour les tests. */ export function resolveTemplate( action: string, osFamily: string, exists: (rel: string) => boolean = defaultExists, ): string { const specific = `${osFamily}/${action}.sh.tpl`; if (osFamily !== "unknown" && osFamily !== "apt" && exists(specific)) return specific; return `apt/${action}.sh.tpl`; }