workwatch
Version:
A Linux terminal program for honest worktime tracking and billing.
136 lines (127 loc) • 4.47 kB
JavaScript
/**
* This file is part of the WorkWatch, a Linux terminal program for honest
* worktime tracking and billing.
*
* Copyright (C) 2020-2025 by Artur Rutkowski
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* WorkWatch is beeing developped and maintained by Artur (locust) Rutkwoski
* <locust@mailbox.org>
*/
/**
* This file defines the basic file-handling object which is beeing extended to
* the particular file-type objects with their methods and getters using
* prototype chaining as the natural JavaScript inheritance.
*/
const fs = require("node:fs");
// Constructor.
function WorkWatchFile(jsonContent, pathToJSONFile = null) {
let workWatchFileJSON = JSON.parse(jsonContent);
let workWatchFilePath = pathToJSONFile;
// The getter providing the instantiated file content.
Object.defineProperty(this, "fileContent", {
get() {
return workWatchFileJSON;
},
enumerable: false,
configurable: false
});
// The getter providing instantiated file path.
Object.defineProperty(this, "filePath", {
get() {
return workWatchFilePath;
},
enumerable: false,
configurable: false
});
Object.preventExtensions(this);
}
// The prototype method which creates new file or saves existing one.
Object.defineProperty(WorkWatchFile.prototype, "createOrSave", {
value: function createOrSave() {
return new Promise((resolve, reject) => {
// Validate file content before writing to disk.
this.verify()
.then(verifySuccess => {
const jsonFileWriteStream = fs.createWriteStream(this.filePath);
jsonFileWriteStream.on("error", (err) => {
reject(err);
});
jsonFileWriteStream.on("ready", () => {
jsonFileWriteStream.end(JSON.stringify(this.fileContent));
resolve(true);
});
})
.catch(verifyError => reject(verifyError));
});
},
writable: false,
enumerable: false,
configurable: false
});
// The prototype empty file content verification method designated to be
// overriden by derived objects' one.
Object.defineProperty(WorkWatchFile.prototype, "verify", {
value: function verify() {
return Promise.resolve(true);
},
writable: false,
enumerable: false,
configurable: false
});
// Reads and instantiates existing file. Used by derived objects which
// extend it by handling errors.
Object.defineProperty(WorkWatchFile, "load", {
value: function load(
pathToJSONFile,
validateContent = true,
fileObjectConstructor = WorkWatchFile
) {
return new Promise((resolve, reject) => {
// Each derived file object is singleton, so return existing instance
// of the object.
if (fileObjectConstructor.instance !== undefined) {
resolve(fileObjectConstructor.instance);
} else {
// Load file and create the instance property pointing to it.
let jsonContent = "";
const jsonFileReadStream = fs.createReadStream(pathToJSONFile);
jsonFileReadStream.on("error", (err) => {
reject(err);
});
jsonFileReadStream.on("data", (chunk) => jsonContent += chunk);
jsonFileReadStream.on("end", () => {
Object.defineProperty(fileObjectConstructor, "instance", {
value: new fileObjectConstructor(jsonContent, pathToJSONFile),
writable: false,
enumerable: false,
configurable: false
});
if (!validateContent) {
resolve(fileObjectConstructor.instance);
} else {
fileObjectConstructor.instance.verify()
.then(verifySuccess => resolve(fileObjectConstructor.instance))
.catch(verifyError => reject(verifyError));
}
});
}
});
},
writable: false,
enumerable: false,
configurable: false
});
module.exports = WorkWatchFile;