71 lines
2.2 KiB
TypeScript
71 lines
2.2 KiB
TypeScript
import { readFileSync, writeFileSync } from "node:fs";
|
|
import { deflateRawSync, inflateRawSync } from "node:zlib";
|
|
import type { BackupData, DeviceInventory } from "./types";
|
|
|
|
export const BACKUP_HEADER = new Uint8Array([0x98, 0x80, 0x01, 0x00]);
|
|
|
|
export interface BackupStats {
|
|
version: number;
|
|
ruleCount: number;
|
|
globalVariableCount: number;
|
|
nodeCount: number;
|
|
}
|
|
|
|
export function unpackBackup(buffer: Uint8Array): BackupData {
|
|
assertBackupHeader(buffer);
|
|
const inflated = inflateRawSync(buffer.subarray(BACKUP_HEADER.length));
|
|
const json = JSON.parse(inflated.toString("utf8")) as BackupData;
|
|
return normalizeBackup(json);
|
|
}
|
|
|
|
export function packBackup(data: BackupData): Uint8Array {
|
|
const json = JSON.stringify(normalizeBackup(data));
|
|
const compressed = deflateRawSync(Buffer.from(json, "utf8"));
|
|
const output = new Uint8Array(BACKUP_HEADER.length + compressed.length);
|
|
output.set(BACKUP_HEADER, 0);
|
|
output.set(compressed, BACKUP_HEADER.length);
|
|
return output;
|
|
}
|
|
|
|
export function readBackupFile(path: string): BackupData {
|
|
return unpackBackup(readFileSync(path));
|
|
}
|
|
|
|
export function writeBackupFile(path: string, data: BackupData): void {
|
|
writeFileSync(path, packBackup(data));
|
|
}
|
|
|
|
export function readDeviceInventoryFile(path: string): DeviceInventory {
|
|
return JSON.parse(readFileSync(path, "utf8")) as DeviceInventory;
|
|
}
|
|
|
|
export function backupStats(data: BackupData): BackupStats {
|
|
return {
|
|
version: data.version,
|
|
ruleCount: data.rules.length,
|
|
globalVariableCount: Object.keys(data.variables.global).length,
|
|
nodeCount: data.rules.reduce((sum, rule) => sum + rule.nodes.length, 0),
|
|
};
|
|
}
|
|
|
|
function assertBackupHeader(buffer: Uint8Array): void {
|
|
if (buffer.length < BACKUP_HEADER.length) {
|
|
throw new Error("备份文件过短,缺少固定头");
|
|
}
|
|
for (let index = 0; index < BACKUP_HEADER.length; index += 1) {
|
|
if (buffer[index] !== BACKUP_HEADER[index]) {
|
|
throw new Error("备份文件头不匹配,期望 0x98 0x80 0x01 0x00");
|
|
}
|
|
}
|
|
}
|
|
|
|
function normalizeBackup(data: BackupData): BackupData {
|
|
return {
|
|
version: 2,
|
|
rules: Array.isArray(data.rules) ? data.rules : [],
|
|
variables: {
|
|
global: data.variables?.global ?? {},
|
|
},
|
|
};
|
|
}
|