88 lines
3.9 KiB
TypeScript
88 lines
3.9 KiB
TypeScript
import { existsSync, readFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { repoRoot } from "./config";
|
|
|
|
export const transHostProxyConfigPath = "config/platform-infra/host-proxy.yaml";
|
|
|
|
export type TransHostProxyEnvApplyTo = "host-posix-commands";
|
|
|
|
export interface TransHostProxyEnvRule {
|
|
targetId: string;
|
|
enabled: boolean;
|
|
envFile: string;
|
|
envFileRef: "files.envFile";
|
|
applyTo: TransHostProxyEnvApplyTo;
|
|
configPath: string;
|
|
configPathLabel: string;
|
|
}
|
|
|
|
export function readTransHostProxyEnvRule(targetId: string): TransHostProxyEnvRule | null {
|
|
const absolutePath = join(repoRoot, transHostProxyConfigPath);
|
|
if (!existsSync(absolutePath)) return null;
|
|
const root = record(Bun.YAML.parse(readFileSync(absolutePath, "utf8")), transHostProxyConfigPath);
|
|
if (root.kind !== "platform-infra-host-proxy") throw new Error(`${transHostProxyConfigPath}.kind must be platform-infra-host-proxy`);
|
|
const targets = record(root.targets, `${transHostProxyConfigPath}.targets`);
|
|
const targetRaw = targets[targetId];
|
|
if (targetRaw === undefined) return null;
|
|
const target = record(targetRaw, `${transHostProxyConfigPath}.targets.${targetId}`);
|
|
if (target.trans === undefined) return null;
|
|
const targetEnabled = booleanField(target, "enabled", `${transHostProxyConfigPath}.targets.${targetId}`);
|
|
if (!targetEnabled) return null;
|
|
const trans = record(target.trans, `${transHostProxyConfigPath}#targets.${targetId}.trans`);
|
|
if (trans.hostProxyEnv === undefined) return null;
|
|
const raw = record(trans.hostProxyEnv, `${transHostProxyConfigPath}#targets.${targetId}.trans.hostProxyEnv`);
|
|
const enabled = booleanField(raw, "enabled", `${transHostProxyConfigPath}#targets.${targetId}.trans.hostProxyEnv`);
|
|
if (!enabled) return null;
|
|
const envFileRef = enumField(raw, "envFileRef", `${transHostProxyConfigPath}.targets.${targetId}.trans.hostProxyEnv`, ["files.envFile"] as const);
|
|
const files = record(target.files, `${transHostProxyConfigPath}.targets.${targetId}.files`);
|
|
return {
|
|
targetId,
|
|
enabled,
|
|
envFile: absolutePathField(files, "envFile", `${transHostProxyConfigPath}.targets.${targetId}.files`),
|
|
envFileRef,
|
|
applyTo: enumField(raw, "applyTo", `${transHostProxyConfigPath}#targets.${targetId}.trans.hostProxyEnv`, ["host-posix-commands"] as const),
|
|
configPath: transHostProxyConfigPath,
|
|
configPathLabel: `${transHostProxyConfigPath}#targets.${targetId}.trans.hostProxyEnv`,
|
|
};
|
|
}
|
|
|
|
export function transHostProxyEnvSummary(targetId: string): Record<string, unknown> | null {
|
|
const rule = readTransHostProxyEnvRule(targetId);
|
|
if (rule === null) return null;
|
|
return {
|
|
enabled: rule.enabled,
|
|
envFileRef: rule.envFileRef,
|
|
envFile: rule.envFile,
|
|
applyTo: rule.applyTo,
|
|
source: rule.configPathLabel,
|
|
};
|
|
}
|
|
|
|
function record(value: unknown, label: string): Record<string, unknown> {
|
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
throw new Error(`${label} must be an object`);
|
|
}
|
|
return value as Record<string, unknown>;
|
|
}
|
|
|
|
function booleanField(raw: Record<string, unknown>, key: string, label: string): boolean {
|
|
const value = raw[key];
|
|
if (typeof value !== "boolean") throw new Error(`${label}.${key} must be a boolean`);
|
|
return value;
|
|
}
|
|
|
|
function enumField<const T extends readonly string[]>(raw: Record<string, unknown>, key: string, label: string, allowed: T): T[number] {
|
|
const value = raw[key];
|
|
if (typeof value !== "string" || !(allowed as readonly string[]).includes(value)) {
|
|
throw new Error(`${label}.${key} must be one of: ${allowed.join(", ")}`);
|
|
}
|
|
return value as T[number];
|
|
}
|
|
|
|
function absolutePathField(raw: Record<string, unknown>, key: string, label: string): string {
|
|
const value = raw[key];
|
|
if (typeof value !== "string" || !value.startsWith("/")) throw new Error(`${label}.${key} must be an absolute path`);
|
|
if (value.includes("\0") || value.includes("\n")) throw new Error(`${label}.${key} must not contain control characters`);
|
|
return value;
|
|
}
|