51 lines
1.7 KiB
TypeScript
51 lines
1.7 KiB
TypeScript
import { existsSync, promises as fs, readFileSync, writeFileSync } from "fs";
|
|
import { validate } from "jsonschema";
|
|
|
|
export class ConfigManager<T> {
|
|
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);
|
|
}
|
|
}
|