70 lines
3.1 KiB
TypeScript
70 lines
3.1 KiB
TypeScript
import { readFileSync } from "node:fs";
|
|
import { CliError } from "./errors.js";
|
|
|
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
}
|
|
|
|
export function readJsonFile(path: string, label: string): unknown {
|
|
try {
|
|
return JSON.parse(readFileSync(path, "utf8"));
|
|
} catch (error) {
|
|
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
|
|
throw new CliError("CLI 参数错误", "INPUT_NOT_FOUND", `${label} file not found: ${path}`, 2);
|
|
}
|
|
if (error instanceof SyntaxError) throw new CliError("CLI 参数错误", "INPUT_INVALID_JSON", `${label} file must be valid JSON: ${path}`, 2);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
export function parseBurstFile(path: string): [string[], number[]] {
|
|
let raw = readJsonFile(path, "burst");
|
|
if (isRecord(raw) && "bursts" in raw) raw = raw.bursts;
|
|
if (isRecord(raw) && "burst_ID" in raw && "burst_size" in raw && Array.isArray(raw.burst_ID) && Array.isArray(raw.burst_size)) {
|
|
const ids = raw.burst_ID.map(String);
|
|
const sizes = raw.burst_size.map(Number);
|
|
if (ids.length !== sizes.length) throw new CliError("CLI 参数错误", "BURST_FILE_INVALID", "burst file burst_ID and burst_size must have the same length", 2);
|
|
return [ids, sizes];
|
|
}
|
|
if (Array.isArray(raw)) {
|
|
return [
|
|
raw.map((item) => {
|
|
if (!isRecord(item) || !("id" in item) || !("size" in item)) throw new CliError("CLI 参数错误", "BURST_FILE_INVALID", "burst file items must contain id and size", 2);
|
|
return String(item.id);
|
|
}),
|
|
raw.map((item) => Number((item as Record<string, unknown>).size)),
|
|
];
|
|
}
|
|
throw new CliError("CLI 参数错误", "BURST_FILE_INVALID", "burst file must be a JSON array or object with burst_ID/burst_size", 2);
|
|
}
|
|
|
|
export function parseValveSettingFile(path: string): [string[], number[]] {
|
|
const raw = readJsonFile(path, "valve-setting");
|
|
if (isRecord(raw) && "valves" in raw && "valves_k" in raw && Array.isArray(raw.valves) && Array.isArray(raw.valves_k)) {
|
|
const valves = raw.valves.map(String);
|
|
const openings = raw.valves_k.map(Number);
|
|
if (valves.length !== openings.length) throw new CliError("CLI 参数错误", "VALVE_SETTING_INVALID", "valves and valves_k must have the same length", 2);
|
|
return [valves, openings];
|
|
}
|
|
if (Array.isArray(raw)) {
|
|
return [
|
|
raw.map((item) => {
|
|
if (!isRecord(item) || !("valve" in item) || !("opening" in item)) throw new CliError("CLI 参数错误", "VALVE_SETTING_INVALID", "valve-setting items must contain valve and opening", 2);
|
|
return String(item.valve);
|
|
}),
|
|
raw.map((item) => Number((item as Record<string, unknown>).opening)),
|
|
];
|
|
}
|
|
throw new CliError("CLI 参数错误", "VALVE_SETTING_INVALID", "valve-setting file must be a JSON array or object with valves/valves_k", 2);
|
|
}
|
|
|
|
export function assignDatasetKeys(target: Record<string, unknown>, path: string, keys: string[], label: string): void {
|
|
const payload = readJsonFile(path, label);
|
|
if (isRecord(payload)) {
|
|
for (const key of keys) {
|
|
if (key in payload) target[key] = payload[key];
|
|
}
|
|
}
|
|
}
|
|
|