core/src/types/config.ts

141 lines
3.3 KiB
TypeScript
Raw Normal View History

2020-11-21 15:41:08 +00:00
import * as fs from 'fs-extra';
import { IEnvironment } from './environment';
2021-10-02 08:07:01 +00:00
/**
* Configuration object
*/
2020-11-21 15:41:08 +00:00
export class Configuration {
2020-11-28 19:08:23 +00:00
public config: any = {};
2021-10-02 08:07:01 +00:00
public loaded = false;
2020-11-21 15:41:08 +00:00
2021-10-02 08:07:01 +00:00
constructor(
private env: IEnvironment,
private file: string,
private defaults: any = {}
) {}
2020-11-21 15:41:08 +00:00
2021-10-02 08:07:01 +00:00
/**
* Load the configuration from its file.
*/
2020-11-21 15:41:08 +00:00
public async load(): Promise<void> {
2020-11-28 13:34:34 +00:00
this.loaded = true;
2020-11-21 15:41:08 +00:00
if (!await fs.pathExists(this.file)) {
this.saveDefaults();
return;
}
const json = await fs.readJson(this.file);
this.config = json;
// Assign default values to existing configuration and resave.
// Eliminates the need for plugins to overwrite the configuration file
// when exiting.
2020-11-21 15:41:08 +00:00
if (this.defaults) {
this.config = Object.assign({}, this.defaults, json);
await this.save();
2020-11-21 15:41:08 +00:00
}
}
2021-10-02 08:07:01 +00:00
/**
* Save configuration to its file.
*/
2020-11-28 13:34:34 +00:00
public async save(): Promise<void> {
return fs.writeJson(this.file, this.config);
}
2021-10-02 08:07:01 +00:00
/**
* Get a configuration value by key.
* @param key JSON traverse key (foo.bar.one)
* @param defval Default value
* @param from Internal use only
* @returns Configuration value or default or null
*/
2020-11-28 13:34:34 +00:00
public get(key: string, defval?: any, from?: any): any {
if (!from) {
from = this.config;
2020-11-21 15:41:08 +00:00
}
2020-11-28 13:34:34 +00:00
// Recursive object traversal
if (key.indexOf('.') !== -1) {
const split = key.split('.');
const first = this.get(split[0], null, from);
2020-12-03 17:20:15 +00:00
if (first != null) {
2020-11-28 13:34:34 +00:00
return this.get(split.slice(1).join('.'), defval, first);
}
return defval;
}
2020-11-21 15:41:08 +00:00
2020-11-28 13:34:34 +00:00
// Array indexing
if (key.indexOf('[') !== -1 && key.indexOf(']') !== -1) {
const match = key.match(/\[(\d+)\]/i);
const realKey = key.substr(0, key.indexOf('['));
if (match != null) {
const index = parseInt(match[1], 10);
if (from[realKey]) {
return from[realKey][index];
}
}
2020-11-21 15:41:08 +00:00
return defval;
}
2020-12-03 17:20:15 +00:00
if (from[key] == null) {
2020-11-28 13:34:34 +00:00
return defval;
}
return from[key];
2020-11-21 15:41:08 +00:00
}
2021-10-02 08:07:01 +00:00
/**
* Set a configuration value by key.
* @returns true on success
*/
2020-11-28 19:08:23 +00:00
public set(key: string, value?: any, from?: any): boolean {
if (!from) {
from = this.config;
}
// Recursive object traversal
if (key.indexOf('.') !== -1) {
const split = key.split('.');
const first = this.get(split[0], null, from);
2020-12-03 17:20:15 +00:00
if (first != null) {
2020-11-28 19:08:23 +00:00
return this.set(split.slice(1).join('.'), value, first);
}
return false;
}
// Array indexing
if (key.indexOf('[') !== -1 && key.indexOf(']') !== -1) {
const match = key.match(/\[(\d+)\]/i);
const realKey = key.substr(0, key.indexOf('['));
if (match != null) {
const index = parseInt(match[1], 10);
if (from[realKey]) {
from[realKey][index] = value;
}
}
return false;
}
from[key] = value;
return true;
}
2021-10-02 08:07:01 +00:00
/**
* Set the default configuration before loading.
* @param defconf Default configuration
*/
2020-11-28 13:34:34 +00:00
public setDefaults(defconf: any): void {
this.defaults = defconf;
2020-11-21 15:41:08 +00:00
}
2021-10-02 08:07:01 +00:00
/**
* Save default values to configuration file
*/
public async saveDefaults(): Promise<void> {
2020-11-28 13:34:34 +00:00
this.config = this.defaults || {};
2021-10-02 08:07:01 +00:00
await this.save();
2020-11-28 13:34:34 +00:00
}
2020-11-21 15:41:08 +00:00
}