Files
efibootmgr-mqtt/src/efibootmgr.service.ts

93 lines
1.9 KiB
TypeScript

import { $ } from "bun";
import type z from "zod";
import type { BootEntries } from "./efibootmgr.schema";
import { logger } from "./logger";
export class EfiBootMgrService {
async reboot() {
await $`reboot`;
}
async setNextBoot(bootNum: number) {
await $`efibootmgr -n ${bootNum}`;
}
parseEfiBootMgrOutput(output: string): z.output<typeof BootEntries> {
const lines = output.split("\n");
const isBootNextSet = output.includes("BootNext:");
if (lines.length < 4) {
throw new Error("Invalid output!");
}
let outputValues: {
bootNext?: string;
bootCurrent: string;
timeout: string;
bootOrder: string;
entries: Array<string>;
};
if (isBootNextSet) {
const [bootNext, bootCurrent, timeout, bootOrder, ...entries] = lines;
if (!bootNext || !bootCurrent || !timeout || !bootOrder) {
throw new Error("Invalid output!");
}
outputValues = {
bootNext,
bootCurrent,
timeout,
bootOrder,
entries,
};
} else {
const [bootCurrent, timeout, bootOrder, ...entries] = lines;
if (!bootCurrent || !timeout || !bootOrder) {
throw new Error("Invalid output!");
}
outputValues = {
bootCurrent,
timeout,
bootOrder,
entries,
};
}
return outputValues.entries
.filter((e) => !![e].join(""))
.map((v) => {
logger.debug(`Processing boot entry: ${v}`);
const [bootStr, labelStr] = v.split("* ");
if (!bootStr || !labelStr) throw new Error("Invalid output!");
const digits = bootStr.match(/\d/g);
if (digits === null) throw new Error("invalid output!");
const [osName] = labelStr.split("\t");
if (!osName) throw new Error("Invalid output!");
return {
label: osName,
number: Number.parseInt(digits.join(""), 10),
};
});
}
async listBootEntries(): Promise<z.output<typeof BootEntries>> {
const output = await $`efibootmgr`.text();
logger.info(output);
return this.parseEfiBootMgrOutput(output);
}
}