Files
Void-Homelab/lib/actions/registry.js
2026-06-04 21:40:20 +10:00

30 lines
1.2 KiB
JavaScript

import { readFileSync } from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const DEFAULT = path.join(path.dirname(fileURLToPath(import.meta.url)), '../../config/actions.json');
const ID_RE = /^[a-z0-9-]+$/;
const KINDS = new Set(['service_restart', 'guest_power']);
const OPS = new Set(['start', 'stop', 'shutdown', 'reboot']);
const TIERS = new Set(['safe', 'risky']);
// Loads + validates the action whitelist. `raw` overrides file read (tests).
export function loadActions(file = DEFAULT, raw) {
const cfg = raw || JSON.parse(readFileSync(file, 'utf8'));
const hosts = cfg.hosts || {};
const byId = new Map();
for (const a of (cfg.actions || [])) {
if (!ID_RE.test(a.id || '')) throw new Error(`invalid action id: ${a.id}`);
if (!KINDS.has(a.kind)) throw new Error(`unknown kind: ${a.kind}`);
if (!TIERS.has(a.tier)) throw new Error(`invalid tier: ${a.tier}`);
if (a.kind === 'guest_power' && !OPS.has(a.op)) throw new Error(`invalid op: ${a.op}`);
if (byId.has(a.id)) throw new Error(`duplicate action id: ${a.id}`);
byId.set(a.id, a);
}
return {
list: () => [...byId.values()],
get: (id) => byId.get(id),
hostIp: (h) => hosts[h]
};
}