core/src/types/config.ts

141 lines
3.3 KiB
TypeScript

import * as fs from 'fs-extra';
import { IEnvironment } from './environment';
/**
* Configuration object
*/
export class Configuration {
public config: any = {};
public loaded = false;
constructor(
private env: IEnvironment,
private file: string,
private defaults: any = {}
) {}
/**
* Load the configuration from its file.
*/
public async load(): Promise<void> {
this.loaded = true;
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.
if (this.defaults) {
this.config = Object.assign({}, this.defaults, json);
await this.save();
}
}
/**
* Save configuration to its file.
*/
public async save(): Promise<void> {
return fs.writeJson(this.file, this.config);
}
/**
* 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
*/
public get(key: string, defval?: any, from?: any): any {
if (!from) {
from = this.config;
}
// Recursive object traversal
if (key.indexOf('.') !== -1) {
const split = key.split('.');
const first = this.get(split[0], null, from);
if (first != null) {
return this.get(split.slice(1).join('.'), defval, first);
}
return defval;
}
// 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];
}
}
return defval;
}
if (from[key] == null) {
return defval;
}
return from[key];
}
/**
* Set a configuration value by key.
* @returns true on success
*/
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);
if (first != null) {
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;
}
/**
* Set the default configuration before loading.
* @param defconf Default configuration
*/
public setDefaults(defconf: any): void {
this.defaults = defconf;
}
/**
* Save default values to configuration file
*/
public async saveDefaults(): Promise<void> {
this.config = this.defaults || {};
await this.save();
}
}