Files
system_update/server/templates/render.ts
T
gilles 2af8e74079 feat(docker): scan/inspect passifs des stacks Compose (tâche 2 SJ-4)
- 4 tables Docker (settings/compose_roots/compose_stacks/stack_services)
  + migration 0004 (timestamps journal monotones)
- templates docker/scan-compose + inspect-compose ; renderTemplate bascule
  sur délimiteurs <% %> pour les templates docker/ afin de préserver les
  Go-templates {{.ID}} intacts
- dockerScan: parseDockerScan (TDD) + scanDockerStacks (persiste stacks
  candidats, complète la détection par labels)
- action docker_scan branchée dans execute (route dédiée, archivage report/log)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 20:54:52 +02:00

48 lines
1.7 KiB
TypeScript

// 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;
// Docker template vars
composeRoots?: string | number | null;
composeScanDepth?: string | number | null;
stackDir?: string | null;
}
export function renderTemplate(
relPath: string,
vars: TemplateVars,
opts?: { tags?: [string, string] },
): string {
const tpl = readFileSync(resolve(TEMPLATES_ROOT, relPath), "utf8");
// Les templates Docker contiennent des Go-templates {{...}} : on bascule les
// délimiteurs Mustache sur <% %> pour ne pas les interpréter.
const tags = opts?.tags ?? (relPath.startsWith("docker/") ? (["<%", "%>"] as [string, string]) : undefined);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return Mustache.render(tpl, vars, {}, { escape: (s: any) => s, ...(tags ? { tags } : {}) } as any);
}
/** 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) :
* `<osFamily>/<action>.sh.tpl` s'il existe, sinon fallback base `apt/<action>.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`;
}