@heliomarpm/kvs
Version:
A simple and robust KeyValues Storage's library
231 lines (230 loc) • 8.43 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.JsonFileHelper = void 0;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const write_file_atomic_1 = __importDefault(require("write-file-atomic"));
const constants_1 = require("./constants");
/**
* This module provides a helper class for managing JSON files in a key-value store.
* It includes methods for loading, saving, and ensuring the existence of JSON files and directories.
* It is designed to work with a customizable directory and file name for storing key-value pairs.
*
* @module JsonFileHelper
* @author Heliomar Marques
* @internal
* @ignore
*/
class JsonFileHelper {
/**
* Creates an instance of JsonFileHelper.
*
* @param {@link Options} options - The options for the JsonFileHelper.
*/
constructor(options) {
/**
* The options for the JsonFileHelper.
* @type {@link Options}
* @private
*/
Object.defineProperty(this, "options", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.options = options;
}
/**
* Returns the path to the keyvalues directory. The path
* may be customized by the developer by using
* `configure()`.
*
* @returns The path to the keyvalues directory.
*/
getJsonDirPath() {
var _a;
const dir = ((_a = this.options.dir) !== null && _a !== void 0 ? _a : node_path_1.default.resolve(constants_1.DEFAULT_DIR_NAME)).trim();
return dir === "" ? "./" : dir;
}
/**
* Returns the path to the keyvalues file. The file name
* may be customized by the developer using `configure()`.
*
* @returns The path to the keyvalues file.
*/
getJsonFilePath() {
const dir = this.getJsonDirPath();
let fileName = this.options.fileName.trim();
fileName = fileName === "" ? constants_1.DEFAULT_FILE_NAME : fileName;
return node_path_1.default.join(dir, fileName);
}
/**
* Ensures that the keyvalues file exists. If it does not
* exist, then it is created.
*
* @returns A promise which resolves when the keyvalues file exists.
*/
ensureJsonFile() {
return __awaiter(this, void 0, void 0, function* () {
const filePath = this.getJsonFilePath();
try {
yield node_fs_1.default.promises.stat(filePath);
}
catch (error) {
const ex = error;
if ((ex === null || ex === void 0 ? void 0 : ex.code) === "ENOENT") {
yield this.saveKeyValues({});
}
else {
throw error;
}
}
});
}
/**
* Ensures that the keyvalues file exists. If it does not
* exist, then it is created.
*
* @returns {void}
*/
ensureJsonFileSync() {
const filePath = this.getJsonFilePath();
try {
node_fs_1.default.statSync(filePath);
}
catch (error) {
const ex = error;
if ((ex === null || ex === void 0 ? void 0 : ex.code) === "ENOENT") {
this.saveKeyValuesSync({});
}
else {
throw error;
}
}
}
/**
* Ensures that the KeyValues directory exists. If it does
* not exist, then it is created.
*
* @returns A promise which resolves when the keyvalues dir exists.
*/
ensureJsonDir() {
return __awaiter(this, void 0, void 0, function* () {
const dirPath = this.getJsonDirPath();
try {
yield node_fs_1.default.promises.stat(dirPath);
}
catch (error) {
const ex = error;
if ((ex === null || ex === void 0 ? void 0 : ex.code) === "ENOENT") {
yield node_fs_1.default.promises.mkdir(dirPath, { recursive: true });
}
else {
throw error;
}
}
});
}
/**
* Ensures that the KeyValues directory exists synchronously. If it does not exist,
* then it is created.
*
* @returns {void}
*/
ensureJsonDirSync() {
const dirPath = this.getJsonDirPath();
try {
node_fs_1.default.statSync(dirPath);
}
catch (error) {
const ex = error;
if ((ex === null || ex === void 0 ? void 0 : ex.code) === "ENOENT") {
node_fs_1.default.mkdirSync(dirPath, { recursive: true });
}
else {
throw error;
}
}
}
/**
* Asynchronously loads key-value pairs from a JSON file. First ensures that the file exists,
* then reads the file and parses its contents into a JavaScript object.
*
* @template T - The type of the key-value pairs.
* @return {Promise<T>} A promise that resolves with the key-value pairs.
*/
loadKeyValues() {
return __awaiter(this, void 0, void 0, function* () {
yield this.ensureJsonFile();
const filePath = this.getJsonFilePath();
const data = yield node_fs_1.default.promises.readFile(filePath, "utf-8");
// fs.promises.readFile com 'utf-8' sempre retorna uma string, então a verificação de array é desnecessária.
const jsonData = data || "{}";
return JSON.parse(jsonData);
});
}
/**
* Loads the key-value pairs synchronously from the JSON file.
*
* @template T - The type of the key-value pairs.
* @returns {T} - The loaded key-value pairs.
*/
loadKeyValuesSync() {
this.ensureJsonFileSync();
const filePath = this.getJsonFilePath();
const data = node_fs_1.default.readFileSync(filePath, "utf-8");
return JSON.parse(data.length ? data : "{}");
}
/**
* Saves the keyvalues to the disk.
*
* @param {T} obj - The keyvalues object to save.
* @return {Promise<void>} A promise that resolves when the keyvalues have been saved.
*/
saveKeyValues(obj) {
return __awaiter(this, void 0, void 0, function* () {
const filePath = this.getJsonFilePath();
const numSpaces = this.options.prettify ? this.options.numSpaces : 0;
const content = JSON.stringify(obj, null, numSpaces);
yield this.ensureJsonDir();
if (this.options.atomicSave) {
yield (0, write_file_atomic_1.default)(filePath, content);
}
else {
yield node_fs_1.default.promises.writeFile(filePath, content);
}
});
}
/**
* Saves the keyvalues to the disk synchronously.
*
* @param {T} obj - The keyvalues object to save.
* @return {void} This function does not return anything.
*/
saveKeyValuesSync(obj) {
const filePath = this.getJsonFilePath();
const numSpaces = this.options.prettify ? this.options.numSpaces : 0;
const data = JSON.stringify(obj, null, numSpaces);
this.ensureJsonDirSync();
if (this.options.atomicSave) {
write_file_atomic_1.default.sync(filePath, data);
}
else {
node_fs_1.default.writeFileSync(filePath, data);
}
}
}
exports.JsonFileHelper = JsonFileHelper;