123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.JsonDB = void 0;
- const Utils_1 = require("./lib/Utils");
- const FS = require("fs");
- const path = require("path");
- const mkdirp = require("mkdirp");
- const Errors_1 = require("./lib/Errors");
- const DBParentData_1 = require("./lib/DBParentData");
- const ArrayInfo_1 = require("./lib/ArrayInfo");
- const JsonDBConfig_1 = require("./lib/JsonDBConfig");
- class JsonDB {
- loaded = false;
- data = {};
- config;
- /**
- * JSONDB Constructor
- * @param filename where to save the "DB". Can also be used to give the whole configuration
- * @param saveOnPush save the database at each push command into the json file
- * @param humanReadable the JSON file will be readable easily by a human
- * @param separator what to use as separator
- */
- constructor(filename, saveOnPush = true, humanReadable = false, separator = '/') {
- if (filename instanceof JsonDBConfig_1.Config) {
- this.config = filename;
- }
- else {
- this.config = new JsonDBConfig_1.Config(filename, saveOnPush, humanReadable, separator);
- }
- if (!FS.existsSync(this.config.filename)) {
- const dirname = path.dirname(this.config.filename);
- mkdirp.sync(dirname);
- this.save(true);
- this.loaded = true;
- }
- }
- /**
- * Process datapath into different parts
- * @param dataPath
- */
- processDataPath(dataPath) {
- if (dataPath === undefined || !dataPath.trim()) {
- throw new Errors_1.DataError("The Data Path can't be empty", 6);
- }
- if (dataPath == this.config.separator) {
- return [];
- }
- dataPath = (0, Utils_1.removeTrailingChar)(dataPath, this.config.separator);
- const path = dataPath.split(this.config.separator);
- path.shift();
- return path;
- }
- retrieveData(dataPath, create = false) {
- this.load();
- const thisDb = this;
- const recursiveProcessDataPath = (data, index) => {
- let property = dataPath[index];
- /**
- * Find the wanted Data or create it.
- */
- function findData(isArray = false) {
- if (data.hasOwnProperty(property)) {
- data = data[property];
- }
- else if (create) {
- if (isArray) {
- data[property] = [];
- }
- else {
- data[property] = {};
- }
- data = data[property];
- }
- else {
- throw new Errors_1.DataError(`Can't find dataPath: ${thisDb.config.separator}${dataPath.join(thisDb.config.separator)}. Stopped at ${property}`, 5);
- }
- }
- const arrayInfo = ArrayInfo_1.ArrayInfo.processArray(property);
- if (arrayInfo) {
- property = arrayInfo.property;
- findData(true);
- if (!Array.isArray(data)) {
- throw new Errors_1.DataError(`DataPath: ${thisDb.config.separator}${dataPath.join(thisDb.config.separator)}. ${property} is not an array.`, 11);
- }
- const arrayIndex = arrayInfo.getIndex(data, true);
- if (!arrayInfo.append && data.hasOwnProperty(arrayIndex)) {
- data = data[arrayIndex];
- }
- else if (create) {
- if (arrayInfo.append) {
- data.push({});
- data = data[data.length - 1];
- }
- else {
- data[arrayIndex] = {};
- data = data[arrayIndex];
- }
- }
- else {
- throw new Errors_1.DataError(`DataPath: ${thisDb.config.separator}${dataPath.join(thisDb.config.separator)}. . Can't find index ${arrayInfo.index} in array ${property}`, 10);
- }
- }
- else {
- findData();
- }
- if (dataPath.length == ++index) {
- return data;
- }
- return recursiveProcessDataPath(data, index);
- };
- if (dataPath.length === 0) {
- return this.data;
- }
- return recursiveProcessDataPath(this.data, 0);
- }
- getParentData(dataPath, create) {
- const path = this.processDataPath(dataPath);
- const last = path.pop();
- return new DBParentData_1.DBParentData(this.retrieveData(path, create), this, dataPath, last);
- }
- /**
- * Get the wanted data
- * @param dataPath path of the data to retrieve
- */
- getData(dataPath) {
- const path = this.processDataPath(dataPath);
- return this.retrieveData(path, false);
- }
- /**
- * Same as getData only here it's directly typed to your object
- * @param dataPath path of the data to retrieve
- */
- getObject(dataPath) {
- return this.getData(dataPath);
- }
- /**
- * Check for existing datapath
- * @param dataPath
- */
- exists(dataPath) {
- try {
- this.getData(dataPath);
- return true;
- }
- catch (e) {
- if (e instanceof Errors_1.DataError) {
- return false;
- }
- throw e;
- }
- }
- /**
- * Returns the number of element which constitutes the array
- * @param dataPath
- */
- count(dataPath) {
- const result = this.getData(dataPath);
- if (!Array.isArray(result)) {
- throw new Errors_1.DataError(`DataPath: ${dataPath} is not an array.`, 11);
- }
- const path = this.processDataPath(dataPath);
- const data = this.retrieveData(path, false);
- return data.length;
- }
- /**
- * Returns the index of the object that meets the criteria submitted. Returns -1, if no match is found.
- * @param dataPath base dataPath from where to start searching
- * @param searchValue value to look for in the dataPath
- * @param propertyName name of the property to look for searchValue
- */
- getIndex(dataPath, searchValue, propertyName = 'id') {
- const data = this.getArrayData(dataPath);
- return data.map(function (element) { return element[propertyName]; }).indexOf(searchValue);
- }
- /**
- * Return the index of the value inside the array. Returns -1, if no match is found.
- * @param dataPath base dataPath from where to start searching
- * @param searchValue value to look for in the dataPath
- */
- getIndexValue(dataPath, searchValue) {
- return this.getArrayData(dataPath).indexOf(searchValue);
- }
- getArrayData(dataPath) {
- const result = this.getData(dataPath);
- if (!Array.isArray(result)) {
- throw new Errors_1.DataError(`DataPath: ${dataPath} is not an array.`, 11);
- }
- const path = this.processDataPath(dataPath);
- return this.retrieveData(path, false);
- }
- /**
- * Find all specific entry in an array/object
- * @param rootPath base dataPath from where to start searching
- * @param callback method to filter the result and find the wanted entry. Receive the entry and it's index.
- */
- filter(rootPath, callback) {
- const result = this.getData(rootPath);
- if (Array.isArray(result)) {
- return result.filter(callback);
- }
- if (result instanceof Object) {
- const entries = Object.entries(result);
- const found = entries.filter((entry) => {
- return callback(entry[1], entry[0]);
- });
- if (!found || found.length < 1) {
- return undefined;
- }
- return found.map((entry) => {
- return entry[1];
- });
- }
- throw new Errors_1.DataError("The entry at the path (" + rootPath + ") needs to be either an Object or an Array", 12);
- }
- /**
- * Find a specific entry in an array/object
- * @param rootPath base dataPath from where to start searching
- * @param callback method to filter the result and find the wanted entry. Receive the entry and it's index.
- */
- find(rootPath, callback) {
- const result = this.getData(rootPath);
- if (Array.isArray(result)) {
- return result.find(callback);
- }
- if (result instanceof Object) {
- const entries = Object.entries(result);
- const found = entries.find((entry) => {
- return callback(entry[1], entry[0]);
- });
- if (!found || found.length < 2) {
- return undefined;
- }
- return found[1];
- }
- throw new Errors_1.DataError("The entry at the path (" + rootPath + ") needs to be either an Object or an Array", 12);
- }
- /**
- * Pushing data into the database
- * @param dataPath path leading to the data
- * @param data data to push
- * @param override overriding or not the data, if not, it will merge them
- */
- push(dataPath, data, override = true) {
- const dbData = this.getParentData(dataPath, true);
- if (!dbData) {
- throw new Error("Data not found");
- }
- let toSet = data;
- if (!override) {
- if (Array.isArray(data)) {
- let storedData = dbData.getData();
- if (storedData === undefined) {
- storedData = [];
- }
- else if (!Array.isArray(storedData)) {
- throw new Errors_1.DataError("Can't merge another type of data with an Array", 3);
- }
- toSet = storedData.concat(data);
- }
- else if (data === Object(data)) {
- if (Array.isArray(dbData.getData())) {
- throw new Errors_1.DataError("Can't merge an Array with an Object", 4);
- }
- toSet = (0, Utils_1.merge)(dbData.getData(), data);
- }
- }
- dbData.setData(toSet);
- if (this.config.saveOnPush) {
- this.save();
- }
- }
- /**
- * Delete the data
- * @param dataPath path leading to the data
- */
- delete(dataPath) {
- const dbData = this.getParentData(dataPath, true);
- if (!dbData) {
- return;
- }
- dbData.delete();
- if (this.config.saveOnPush) {
- this.save();
- }
- }
- /**
- * Only use this if you know what you're doing.
- * It reset the full data of the database.
- * @param data
- */
- resetData(data) {
- this.data = data;
- }
- /**
- * Reload the database from the file
- */
- reload() {
- this.loaded = false;
- this.load();
- }
- ;
- /**
- * Manually load the database
- * It is automatically called when the first getData is done
- */
- load() {
- if (this.loaded) {
- return;
- }
- try {
- const data = FS.readFileSync(this.config.filename, 'utf8');
- this.data = JSON.parse(data);
- this.loaded = true;
- }
- catch (err) {
- const error = new Errors_1.DatabaseError("Can't Load Database", 1, err);
- throw error;
- }
- }
- /**
- * Manually save the database
- * By default you can't save the database if it's not loaded
- * @param force force the save of the database
- */
- save(force) {
- force = force || false;
- if (!force && !this.loaded) {
- throw new Errors_1.DatabaseError("DataBase not loaded. Can't write", 7);
- }
- let data = "";
- try {
- if (this.config.humanReadable) {
- data = JSON.stringify(this.data, null, 4);
- }
- else {
- data = JSON.stringify(this.data);
- }
- FS.writeFileSync(this.config.filename, data, 'utf8');
- }
- catch (err) {
- const error = new Errors_1.DatabaseError("Can't save the database", 2, err);
- throw error;
- }
- }
- }
- exports.JsonDB = JsonDB;
- //# sourceMappingURL=JsonDB.js.map
|