import { existsSync, promises as fs, readFileSync, writeFileSync } from "fs"; import { validate } from "jsonschema"; export class ConfigManager { path: string; default_config: T; config: T | null; schema: object; constructor(path: string, default_config: T, schema: object) { this.path = path; this.default_config = default_config; this.config = null; this.schema = schema; } get_config_file(): T { if (this.config !== null) return this.config; this.config = { ...this.read_config_file() }; return this.config; } private emptyToDefault(target: T) { let occur = false; for (const key in this.default_config) { if (key === undefined || key in target) { continue; } target[key] = this.default_config[key]; occur = true; } return occur; } read_config_file(): T { if (!existsSync(this.path)) { writeFileSync(this.path, JSON.stringify(this.default_config)); return this.default_config; } const ret = JSON.parse(readFileSync(this.path, { encoding: "utf8" })); if (this.emptyToDefault(ret)) { writeFileSync(this.path, JSON.stringify(ret)); } const result = validate(ret, this.schema); if (!result.valid) { throw new Error(result.toString()); } return ret; } async write_config_file(new_config: T) { this.config = new_config; await fs.writeFile(`${this.path}.temp`, JSON.stringify(new_config)); await fs.rename(`${this.path}.temp`, this.path); } }