const fs = require('fs');
const path = require('path');
const process = require('process');
/**
* Utilities to write and load json data to disk
*
* @author Maksim Sandybekov
* @date 7.5.20
* @version 1.0
*/
class FsUtil {
/**
*
* @param {string} dirPath Path to directory where to write data to, defaults to /data (from project root).
*/
constructor(dirPath = path.join(process.cwd(), 'data')) {
this.workingDir = dirPath;
this.dirExists = this._setupDirectory();
this._initQueue();
this._initAdminCache();
this._initConfig();
}
/**
* Read all data file from the storage directory and build an object.
*
* Example:
* /data
* users.json
* storage.json
*
* results in following object: {"users": {}, "storage": {}}
*/
readData() {
let storage = {};
// Build the storage object
const storageFiles = fs.readdirSync(this.workingDir).filter(file => file.endsWith('.json'))
for (const file of storageFiles) {
let fileName = file.split('.')[0];
storage[fileName] = require(path.join(this.workingDir, file));
}
return storage;
}
/**
* Write new data to the storage directory.
*
* @param {string} filename The name of the file to be written.
* @param {Object} data Write data to the files in the
*/
writeData(filename, data) {
// Add json ending if non-existent
if (!filename.endsWith('.json')) {
filename = filename+'.json';
}
// Setup directory if it does not exist
if (!fs.existsSync(this.workingDir)) {
this._setupDirectory();
}
let content = JSON.stringify(data);
let filePath = path.join(this.workingDir, filename);
fs.writeFileSync(filePath, content);
}
/**
* Set a default configuration file if non exists, only for unit tests.
* - prefix: /
* - token needs to be set
* - default admin Role "Bot Admin"
* - allow communication on channels
*
*/
static createDefaultConfig() {
let content = {
"prefix": "/",
"token": "",
"adminRole": "Bot Admin",
"channels":{
"category": "bot",
"member": "member",
"admin": "admin"
}
};
let configPath = path.join(process.cwd(), "config.json");
if (!fs.existsSync(configPath)) {
content = JSON.stringify(content);
fs.writeFileSync(configPath, content);
}
}
// ---------------------
// Private functions
// -------------------------
/**
* Setup a data storage in form of a directory, loading already existing files.
*
* @private
* @return {boolean} - wether the directory was created successfully or not
*/
_setupDirectory() {
if (!fs.existsSync(this.workingDir)) {
fs.mkdirSync(this.workingDir, {recursive: true});
}
return fs.existsSync(this.workingDir);
}
/**
* Creates a default file to store the members of the queue.
*
* @private
* @param {string} fileName The name of the file to be created in the working directory
*/
_initQueue(fileName = "queue") {
let content = {
};
this._writeDefaultConfig(fileName, content);
}
/**
* Creates a file to keep track of admin member calls to the bot.
*
* @private
* @param {*} fileName
*/
_initAdminCache(fileName = "admin") {
let content = {
};
this._writeDefaultConfig(fileName, content);
}
/**
* Create a configuration
*
* @private
* @param {string} fileName The name of the file to be created in the working directory
*/
_initConfig(fileName = "config") {
let content = {
}
this._writeDefaultConfig(fileName, content);
}
/**
* Creates a file in the working directory if it not already exists.
*
* @private
* @param {string} fileName The name of the file to be created
* @param {object} initialConent The initial content of the file
*/
_writeDefaultConfig(fileName, initialContent = {}) {
let filePath = path.join(this.workingDir, fileName + ".json");
if (!fs.existsSync(filePath)) {
this.writeData(fileName, initialContent);
}
}
}
module.exports = FsUtil;