Add homelab installer and services (allprox, authelia, lldap)

This commit is contained in:
Ezequiel C. 2026-09-01 18:32:56 +02:00
parent 68b23f1cbe
commit bb754cdd8c
32 changed files with 2356 additions and 1 deletions

52
installer/src/metadata.ts Normal file
View file

@ -0,0 +1,52 @@
import type { ServiceMetadata } from "./types.ts";
export interface ValidationIssue {
path: string;
message: string;
}
export function parseAndValidate(raw: string, fallbackId: string): ServiceMetadata {
let data: unknown;
try {
data = JSON.parse(raw);
} catch (e) {
throw new Error(`metadata.json is not valid JSON: ${(e as Error).message}`);
}
if (typeof data !== "object" || data === null || Array.isArray(data)) {
throw new Error("metadata.json must be a JSON object");
}
const meta = data as ServiceMetadata;
const issues = validateMetadata(meta, fallbackId);
if (issues.length > 0) {
const detail = issues.map((i) => `${i.path}: ${i.message}`).join("; ");
throw new Error(`invalid metadata.json (${detail})`);
}
meta.id = meta.id || fallbackId;
return meta;
}
export function validateMetadata(meta: ServiceMetadata, fallbackId: string): ValidationIssue[] {
const issues: ValidationIssue[] = [];
const id = meta.id || fallbackId;
if (!meta.name || typeof meta.name !== "string") {
issues.push({ path: "name", message: "required string" });
}
if (!meta.description || typeof meta.description !== "string") {
issues.push({ path: "description", message: "required string" });
}
if (!meta.version || typeof meta.version !== "string") {
issues.push({ path: "version", message: "required string" });
}
if (!meta.compose || typeof meta.compose !== "object" || Array.isArray(meta.compose)) {
issues.push({ path: "compose", message: "required object (docker-compose service spec)" });
}
if (!/^[a-z0-9][a-z0-9-]*$/.test(id)) {
issues.push({ path: "id", message: "must be kebab-case and match the folder name" });
}
return issues;
}