beyond
Version:
The Full Stack Universal Typescript Framework
101 lines (83 loc) • 2.86 kB
JavaScript
const DynamicProcessor = global.utils.DynamicProcessor();
const fs = (require('../../fs'));
const chokidar = require('chokidar');
module.exports = class extends DynamicProcessor {
get dp() {
return 'utils.config.property.file';
}
#watcher;
// The path of the parent property, or the specified path when the property is the root
#root;
get root() {
return this.#root;
}
// The relative path of the configuration file specified from the data of the property when the data is a string
#relative;
get relative() {
return this.#relative;
}
// The full path of the file (root + relative)
#file;
get file() {
return this.#file;
}
#dirname;
get dirname() {
if (this.#dirname !== void 0) return this.#dirname;
return this.#dirname = require('path').dirname(this.#file);
}
#errors = [];
get errors() {
return this.#errors;
}
get valid() {
return !this.errors.length;
}
#value;
get value() {
return this.#value;
}
/**
* File constructor
*
* @param root {string} The path of the parent property, or the specified path when the property is the root
* @param relative {string} The data of the property when the data is a string
*/
constructor(root, relative) {
super();
this.#root = root;
this.#relative = relative;
this.#file = require('path').join(root, relative);
}
async _begin() {
// Watch for file changes
this.#watcher = chokidar.watch(this.#file, {'ignoreInitial': true});
this.#watcher.on('all', this._invalidate);
}
async _process(request) {
this.#value = undefined;
const done = ({value, errors}) => {
errors = typeof errors === 'string' ? [errors] : errors;
this.#errors = errors ? errors : [];
this.#value = value;
}
const exists = (await fs.exists(this.#file)) && (await fs.stat(this.#file)).isFile();
if (this._request !== request) return;
if (!exists) return done({errors: `Configuration file "${this.#file}" not found`});
const content = await fs.readFile(this.#file, {'encoding': 'UTF8'});
if (this._request !== request) return;
let value;
try {
value = JSON.parse(content);
return done({value});
}
catch (exc) {
return done({errors: `Configuration file "${this.#file}" cannot be parsed - ${exc.message}`});
}
}
destroy() {
super.destroy();
this.#watcher?.close().catch(exc => console.error(exc.stack));
this.#watcher?.removeAllListeners();
}
}