Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@wxn0brp/database.js

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@wxn0brp/database.js - npm Package Compare versions

Comparing version 0.0.1 to 0.0.2

CollectionManager.js

138

action.js

@@ -1,6 +0,5 @@

const fs = require("fs");
const gen = require("./gen");
const format = require("./format");
const fileM = require("./file");
const CacheManager = require("./cacheManager");
import { existsSync, mkdirSync, readdirSync, appendFileSync, rmSync, writeFileSync, statSync } from "fs";
import gen from "./gen.js";
import { stringify } from "./format.js";
import { find as _find, findOne as _findOne, update as _update, remove as _remove } from "./file/index.js";

@@ -18,10 +17,9 @@ const maxFileSize = 2 * 1024 * 1024; //2 MB

* @param {string} folder - The folder where database files are stored.
* @param {number} cacheThreshold - The cache threshold for query results.
* @param {number} ttl - The time-to-live (TTL) for cached data.
* @param {object} options - The options object.
*/
constructor(folder, cacheThreshold, ttl){
constructor(folder, options){
this.folder = folder;
this.cacheManager = new CacheManager(cacheThreshold, ttl);
// this.cacheManager = new CacheManager(options.cacheThreshold, options.cacheTTL);
if(!fs.existsSync(folder)) fs.mkdirSync(folder, { recursive: true });
if(!existsSync(folder)) mkdirSync(folder, { recursive: true });
}

@@ -33,4 +31,11 @@

*/
getDBs(){
return fs.readdirSync(this.folder);
getCollections(){
const collections = readdirSync(this.folder, { recursive: true, withFileTypes: true })
.filter(dirent => dirent.isDirectory())
.map(dirent => {
if(dirent.parentPath === this.folder) return dirent.name;
return dirent.parentPath.replace(this.folder + "/", "") + "/" + dirent.name
});
return collections;
}

@@ -45,6 +50,17 @@

const path = this.folder + "/" + collection;
if(!fs.existsSync(path)) fs.mkdirSync(path, { recursive: true });
if(!existsSync(path)) mkdirSync(path, { recursive: true });
}
/**
* Check if a collection exists.
* @function
* @param {string} collection - The name of the collection.
* @returns {boolean} True if the collection exists, false otherwise.
*/
issetCollection(collection){
const path = this.folder + "/" + collection;
return existsSync(path);
}
/**
* Add a new entry to the specified database.

@@ -58,8 +74,8 @@ * @async

async add(collection, arg, id_gen=true){
this.checkCollection(collection);
await this.checkCollection(collection);
const file = this.folder + "/" + collection + "/" + getLastFile(this.folder + "/" + collection);
if(id_gen) arg._id = arg._id || gen();
const data = format.stringify(arg);
fs.appendFileSync(file, data+"\n");
const data = stringify(arg);
appendFileSync(file, data+"\n");
return arg;

@@ -73,13 +89,15 @@ }

* @param {function|Object} arg - The search criteria. It can be a function or an object.
* @param {Object} context - The context object (for functions).
* @param {Object} options - The options for the search.
* @param {number} options.max - The maximum number of entries to return. Default is -1, meaning no limit.
* @param {boolean} options.reverse - Whether to reverse the order of returned entries. Default is false.
* @param {Object} findOpts - Update result object with findOpts options.
* @returns {Promise<Object[]>} A Promise that resolves to an array of matching entries.
*/
async find(collection, arg, options={}){
async find(collection, arg, context={}, options={}, findOpts={}){
options.reverse = options.reverse || false;
options.max = options.max || -1;
this.checkCollection(collection);
let files = fs.readdirSync(this.folder + "/" + collection).filter(file => !/\.tmp$/.test(file));
await this.checkCollection(collection);
const files = getSortedFiles(this.folder + "/" + collection).map(f => f.f);
if(options.reverse) files.reverse();

@@ -91,3 +109,3 @@ let datas = [];

for(let f of files){
let data = await fileM.find(this.folder + "/" + collection + "/" + f, arg, options);
let data = await _find(this.folder + "/" + collection + "/" + f, arg, context, findOpts);
if(options.reverse) data.reverse();

@@ -117,11 +135,13 @@

* @param {function|Object} arg - The search criteria. It can be a function or an object.
* @param {Object} context - The context object (for functions).
* @param {Object} findOpts - Update result object with findOpts options.
* @returns {Promise<Object|null>} A Promise that resolves to the first matching entry or null if not found.
*/
async findOne(collection, arg){
this.checkCollection(collection);
let files = fs.readdirSync(this.folder + "/" + collection).filter(file => !/\.tmp$/.test(file));
async findOne(collection, arg, context={}, findOpts={}){
await this.checkCollection(collection);
const files = getSortedFiles(this.folder + "/" + collection).map(f => f.f);
files.reverse();
for(let f of files){
let data = await fileM.findOne(this.folder + "/" + collection + "/" + f, arg);
let data = await _findOne(this.folder + "/" + collection + "/" + f, arg, context, findOpts);
if(data){

@@ -140,7 +160,8 @@ return data;

* @param {function|Object} obj - The updater function or object.
* @param {Object} context - The context object (for functions).
* @returns {Promise<boolean>} A Promise that resolves to `true` if entries were updated, or `false` otherwise.
*/
async update(collection, arg, obj){
this.checkCollection(collection);
return await fileM.update(this.folder, collection, arg, obj);
async update(collection, arg, obj, context={}){
await this.checkCollection(collection);
return await _update(this.folder, collection, arg, obj, context);
}

@@ -154,7 +175,8 @@

* @param {function|Object} obj - The updater function or object.
* @param {Object} context - The context object (for functions).
* @returns {Promise<boolean>} A Promise that resolves to `true` if one entry was updated, or `false` otherwise.
*/
async updateOne(collection, arg, obj){
this.checkCollection(collection);
return await fileM.update(this.folder, collection, arg, obj, true);
async updateOne(collection, arg, obj, context={}){
await this.checkCollection(collection);
return await _update(this.folder, collection, arg, obj, context, true);
}

@@ -167,7 +189,8 @@

* @param {function|Object} arg - The search criteria. It can be a function or an object.
* @param {Object} context - The context object (for functions).
* @returns {Promise<boolean>} A Promise that resolves to `true` if entries were removed, or `false` otherwise.
*/
async remove(collection, arg){
this.checkCollection(collection);
return await fileM.remove(this.folder, collection, arg);
async remove(collection, arg, context={}){
await this.checkCollection(collection);
return await _remove(this.folder, collection, arg, context);
}

@@ -180,7 +203,8 @@

* @param {function|Object} arg - The search criteria. It can be a function or an object.
* @param {Object} context - The context object (for functions).
* @returns {Promise<boolean>} A Promise that resolves to `true` if one entry was removed, or `false` otherwise.
*/
async removeOne(collection, arg){
this.checkCollection(collection);
return await fileM.remove(this.folder, collection, arg, true);
async removeOne(collection, arg, context={}){
await this.checkCollection(collection);
return await _remove(this.folder, collection, arg, context, true);
}

@@ -195,3 +219,3 @@

removeDb(collection){
fs.rmSync(this.folder + "/" + collection, { recursive: true, force: true });
rmSync(this.folder + "/" + collection, { recursive: true, force: true });
}

@@ -206,22 +230,34 @@ }

function getLastFile(path){
if(!fs.existsSync(path)) fs.mkdirSync(path, { recursive: true });
let files = fs.readdirSync(path).filter(file => !/\.tmp$/.test(file));
if(!existsSync(path)) mkdirSync(path, { recursive: true });
const files = getSortedFiles(path);
if(files.length == 0){
fs.writeFileSync(path+"/1.db", "");
writeFileSync(path+"/1.db", "");
return "1.db";
}
files = files.sort();
const last = files[files.length-1];
const info = path + "/" + last;
if(fs.statSync(info).size > maxFileSize){
const temName = last.replace(".db", "");
const int = parseInt(temName) + 1;
fs.writeFileSync(path + "/" + int + ".db", "");
return int+".db";
}else{
return last;
}
const info = path + "/" + last.f;
if(statSync(info).size < maxFileSize) return last.f;
const num = last.i + 1;
writeFileSync(path + "/" + num + ".db", "");
return num+".db";
}
module.exports = dbActionC;
/**
* Get all files in a directory sorted by name.
* @param {string} path - The path to the directory.
* @return {string[]} An array of file names sorted by name.
*/
function getSortedFiles(path){
let files = readdirSync(path).filter(file => file.endsWith(".db"));
if(files.length == 0) return [];
files = files.map(file => parseInt(file.replace(".db", "")))
files = files.sort();
files = files.map(file => { return { i: file, f: file+".db" } });
return files;
}
export default dbActionC;

@@ -83,2 +83,2 @@ /**

module.exports = CacheManager;
export default CacheManager;

@@ -1,3 +0,4 @@

const dbActionC = require("./action");
const executorC = require("./executor");
import dbActionC from "./action.js";
import executorC from "./executor.js";
import CollectionManager from "./CollectionManager.js";

@@ -13,7 +14,13 @@ /**

* @param {string} folder - The folder path where the database files are stored.
* @param {number} [cacheThreshold=3] - The cache threshold for database entries (default: 3).
* @param {number} [ttl=300000] - The time-to-live (TTL) for cached entries in milliseconds (default: 300,000 milliseconds or 5 minutes).
* @param {object} [options] - The options object.
* @param {number} [options.cacheThreshold=3] - The cache threshold for database entries (default: 3).
* @param {number} [options.cacheTTL=300000] - The time-to-live (TTL) for cached entries in milliseconds (default: 300,000 milliseconds or 5 minutes).
*/
constructor(folder, cacheThreshold=3, ttl=300_000){
this.dbAction = new dbActionC(folder, cacheThreshold, ttl);
constructor(folder, options={}){
options = {
cacheThreshold: 3,
cacheTTL: 300_000,
...options
}
this.dbAction = new dbActionC(folder, options);
this.executor = new executorC();

@@ -23,2 +30,12 @@ }

/**
* Create a new instance of a CollectionManager class.
* @function
* @param {string} collection - The name of the collection.
* @returns {CollectionManager} A new instance of CollectionManager.
*/
c(collection){
return new CollectionManager(this, collection);
}
/**
* Get the names of all available databases.

@@ -29,4 +46,4 @@ *

*/
getDBs(){
return this.dbAction.getDBs();
async getCollections(){
return await this.dbAction.getCollections();
}

@@ -40,7 +57,18 @@

*/
checkCollection(collection){
this.dbAction.checkCollection(collection);
async checkCollection(collection){
await this.dbAction.checkCollection(collection);
}
/**
* Check if a collection exists.
*
* @function
* @param {string} collection - The name of the collection.
* @returns {boolean} True if the collection exists, false otherwise.
*/
async issetCollection(collection){
return await this.dbAction.issetCollection(collection);
}
/**
* Add data to a database.

@@ -66,9 +94,11 @@ *

* @param {function|Object} search - The query. It can be an object or a function.
* @param {Object} context - The context object (for functions).
* @param {Object} options - The options for the search.
* @param {number} options.max - The maximum number of entries to return. Default is -1, meaning no limit.
* @param {boolean} options.reverse - Whether to reverse the order of returned entries. Default is false.
* @param {Object} findOpts - Update result object with findOpts options.
* @returns {Promise<Array<Object>>} A Promise that resolves with the matching data.
*/
async find(collection, search, options={}){
return await this.executor.addOp(this.dbAction.find.bind(this.dbAction), collection, search, options);
async find(collection, search, context={}, options={}, findOpts={}){
return await this.executor.addOp(this.dbAction.find.bind(this.dbAction), collection, search, context, options, findOpts);
}

@@ -83,6 +113,8 @@

* @param {function|Object} search - The query. It can be an object or a function.
* @param {Object} context - The context object (for functions).
* @param {Object} findOpts - Update result object with findOpts options.
* @returns {Promise<Object|null>} A Promise that resolves with the first matching data entry.
*/
async findOne(collection, search){
return await this.executor.addOp(this.dbAction.findOne.bind(this.dbAction), collection, search);
async findOne(collection, search, context={}, findOpts={}){
return await this.executor.addOp(this.dbAction.findOne.bind(this.dbAction), collection, search, context, findOpts);
}

@@ -98,6 +130,7 @@

* @param {function|Object} arg - Update arguments.
* @param {Object} context - The context object (for functions).
* @returns {Promise<boolean>} A Promise that resolves when the data is updated.
*/
async update(collection, search, arg){
return await this.executor.addOp(this.dbAction.update.bind(this.dbAction), collection, search, arg);
async update(collection, search, arg, context={}){
return await this.executor.addOp(this.dbAction.update.bind(this.dbAction), collection, search, arg, context);
}

@@ -113,6 +146,7 @@

* @param {function|Object} arg - The query.
* @param {Object} context - The context object (for functions).
* @returns {Promise<boolean>} A Promise that resolves when the data entry is updated.
*/
async updateOne(collection, search, arg){
return await this.executor.addOp(this.dbAction.updateOne.bind(this.dbAction), collection, search, arg);
async updateOne(collection, search, arg, context={}){
return await this.executor.addOp(this.dbAction.updateOne.bind(this.dbAction), collection, search, arg, context);
}

@@ -127,6 +161,7 @@

* @param {function|Object} search - The query. It can be an object or a function.
* @param {Object} context - The context object (for functions).
* @returns {Promise<boolean>} A Promise that resolves when the data is removed.
*/
async remove(collection, search){
return await this.executor.addOp(this.dbAction.remove.bind(this.dbAction), collection, search);
async remove(collection, search, context={}){
return await this.executor.addOp(this.dbAction.remove.bind(this.dbAction), collection, search, context);
}

@@ -141,6 +176,7 @@

* @param {function|Object} search - The query. It can be an object or a function.
* @param {Object} context - The context object (for functions).
* @returns {Promise<boolean>} A Promise that resolves when the data entry is removed.
*/
async removeOne(collection, search){
return await this.executor.addOp(this.dbAction.removeOne.bind(this.dbAction), collection, search);
async removeOne(collection, search, context={}){
return await this.executor.addOp(this.dbAction.removeOne.bind(this.dbAction), collection, search, context);
}

@@ -155,7 +191,15 @@

* @param {function|Object} add_arg - The arguments to be added to the new entry.
* @param {Object} context - The context object (for functions).
* @param {boolean} id_gen - Whether to generate an ID for the entry. Default is true.
* @return {Promise<boolean>} A Promise that resolves to `true` if the entry was updated, or `false` if it was added.
*/
async updateOneOrAdd(collection, search, arg, add_arg={}){
const res = await this.updateOne(collection, search, arg);
if(!res) await this.add(collection, Object.assign(search, arg, add_arg));
async updateOneOrAdd(collection, search, arg, add_arg={}, context={}, id_gen=true){
const res = await this.updateOne(collection, search, arg, context);
if(!res){
const assignData = [];
if(typeof search === "object" && !Array.isArray(search)) assignData.push(search);
if(typeof arg === "object" && !Array.isArray(arg)) assignData.push(arg);
if(typeof add_arg === "object" && !Array.isArray(add_arg)) assignData.push(add_arg);
await this.add(collection, Object.assign({}, ...assignData), id_gen);
}
return res;

@@ -175,2 +219,2 @@ }

module.exports = DataBase;
export default DataBase;

@@ -54,2 +54,2 @@ /**

module.exports = executorC;
export default executorC;

@@ -1,5 +0,5 @@

const fs = require("fs");
const { pathRepair, createRL } = require("./utils");
const format = require("../format");
const more = require("../more");
import { existsSync, promises } from "fs";
import { pathRepair, createRL } from "./utils.js";
import { parse } from "../format.js";
import { hasFieldsAdvanced, updateFindObject } from "../more.js";

@@ -11,15 +11,18 @@ /**

* @param {string} line - The line of text from the file.
* @param {Object} context - The context object (for functions).
* @param {Object} findOpts - Update result object with findOpts options.
* @returns {Promise<Object|null>} A Promise that resolves to the matching object or null.
*/
async function findProcesLine(arg, line){
const ob = format.parse(line);
async function findProcesLine(arg, line, context={}, findOpts={}){
const ob = parse(line);
let res = false;
if(typeof arg === "function"){
if(arg(ob)) res = true;
if(arg(ob, context)) res = true;
}else if(typeof arg === "object" && !Array.isArray(arg)){
if(more.hasFieldsAdvanced(ob, arg)) res = true;
if(hasFieldsAdvanced(ob, arg)) res = true;
}
return res ? ob : null;
if(res) return updateFindObject(ob, findOpts);
return null;
}

@@ -32,9 +35,11 @@

* @param {function|Object} arg - The search criteria. It can be a function or an object.
* @param {Object} context - The context object (for functions).
* @param {Object} findOpts - Update result object with findOpts options.
* @returns {Promise<Object[]>} A Promise that resolves to an array of matching objects.
*/
async function find(file, arg){
export async function find(file, arg, context={}, findOpts={}){
file = pathRepair(file);
return await new Promise(async (resolve) => {
if(!fs.existsSync(file)){
await fs.promises.writeFile(file, "");
if(!existsSync(file)){
await promises.writeFile(file, "");
resolve(false);

@@ -48,6 +53,7 @@ return;

const res = await findProcesLine(arg, line);
const res = await findProcesLine(arg, line, context, findOpts);
if(res) resF.push(res);
};
resolve(resF);
rl.close();
})

@@ -61,9 +67,11 @@ }

* @param {function|Object} arg - The search criteria. It can be a function or an object.
* @param {Object} context - The context object (for functions).
* @param {Object} findOpts - Update result object with findOpts options.
* @returns {Promise<Object>} A Promise that resolves to the first matching object found or an empty array.
*/
async function findOne(file, arg){
export async function findOne(file, arg, context={}, findOpts={}){
file = pathRepair(file);
return await new Promise(async (resolve) => {
if(!fs.existsSync(file)){
await fs.promises.writeFile(file, "");
if(!existsSync(file)){
await promises.writeFile(file, "");
resolve(false);

@@ -76,3 +84,3 @@ return;

const res = await findProcesLine(arg, line);
const res = await findProcesLine(arg, line, context, findOpts);
if(res){

@@ -85,7 +93,2 @@ resolve(res);

});
}
module.exports = {
find,
findOne
};
}

@@ -1,10 +0,3 @@

const update = require("./update");
const remove = require("./remove");
const { find, findOne } = require("./find");
module.exports = {
update,
remove,
find,
findOne
}
export { default as update } from "./update.js";
export { default as remove } from "./remove.js";
export * from "./find.js";

@@ -1,5 +0,5 @@

const fs = require("fs");
const { pathRepair, createRL } = require("./utils");
const format = require("../format");
const more = require("../more");
import { existsSync, promises, appendFileSync, readdirSync } from "fs";
import { pathRepair, createRL } from "./utils.js";
import { parse } from "../format.js";
import { hasFieldsAdvanced } from "../more.js";

@@ -11,13 +11,14 @@ /**

* @param {function|Object} search - The search criteria. It can be a function or an object.
* @param {Object} context - The context object (for functions).
* @param {boolean} [one=false] - Indicates whether to remove only one matching entry (default: false).
* @returns {Promise<boolean>} A Promise that resolves to `true` if entries were removed, or `false` otherwise.
*/
async function removeWorker(file, search, one=false){
async function removeWorker(file, search, context={}, one=false){
file = pathRepair(file);
if(!fs.existsSync(file)){
await fs.promises.writeFile(file, "");
if(!existsSync(file)){
await promises.writeFile(file, "");
return false;
}
await fs.promises.copyFile(file, file+".tmp");
await fs.promises.writeFile(file, "");
await promises.copyFile(file, file+".tmp");
await promises.writeFile(file, "");

@@ -29,10 +30,10 @@ const rl = createRL(file+".tmp");

if(one && removed){
fs.appendFileSync(file, line+"\n");
appendFileSync(file, line+"\n");
continue;
}
const data = format.parse(line);
const data = parse(line);
if(typeof search === "function"){
if(search(data)){
if(search(data, context)){
removed = true;

@@ -42,3 +43,3 @@ continue;

}else if(typeof search === "object" && !Array.isArray(search)){
if(more.hasFieldsAdvanced(data, search)){
if(hasFieldsAdvanced(data, search)){
removed = true;

@@ -49,5 +50,5 @@ continue;

fs.appendFileSync(file, line+"\n");
appendFileSync(file, line+"\n");
}
await fs.promises.writeFile(file+".tmp", "");
await promises.writeFile(file+".tmp", "");
return removed;

@@ -62,11 +63,12 @@ }

* @param {function|Object} arg - The search criteria. It can be a function or an object.
* @param {Object} context - The context object (for functions).
* @param {boolean} one - Indicates whether to remove only one matching entry (default: false).
* @returns {Promise<boolean>} A Promise that resolves to `true` if entries were removed, or `false` otherwise.
*/
async function remove(folder, name, arg, one){
let files = fs.readdirSync(folder + "/" + name).filter(file => !/\.tmp$/.test(file));
async function remove(folder, name, arg, context={}, one){
let files = readdirSync(folder + "/" + name).filter(file => !/\.tmp$/.test(file));
files.reverse();
let remove = false;
for(const file of files){
const removed = await removeWorker(folder + "/" + name + "/" + file, arg, one);
const removed = await removeWorker(folder + "/" + name + "/" + file, arg, context, one);
if(one && removed) break;

@@ -78,2 +80,2 @@ remove = remove || removed;

module.exports = remove;
export default remove;

@@ -1,5 +0,5 @@

const fs = require("fs");
const { pathRepair, createRL } = require("./utils");
const format = require("../format");
const more = require("../more");
import { existsSync, promises, appendFileSync, readdirSync } from "fs";
import { pathRepair, createRL } from "./utils.js";
import { parse, stringify } from "../format.js";
import { hasFieldsAdvanced, updateObject } from "../more.js";

@@ -12,13 +12,14 @@ /**

* @param {function|Object} updater - The updater function or object.
* @param {Object} context - The context object (for functions).
* @param {boolean} [one=false] - Indicates whether to update only one matching entry (default: false).
* @returns {Promise<boolean>} A Promise that resolves to `true` if the file was updated, or `false` otherwise.
*/
async function updateWorker(file, search, updater, one=false){
async function updateWorker(file, search, updater, context={}, one=false){
file = pathRepair(file);
if(!fs.existsSync(file)){
await fs.promises.writeFile(file, "");
if(!existsSync(file)){
await promises.writeFile(file, "");
return false;
}
await fs.promises.copyFile(file, file+".tmp");
await fs.promises.writeFile(file, "");
await promises.copyFile(file, file+".tmp");
await promises.writeFile(file, "");

@@ -30,13 +31,13 @@ const rl = createRL(file+".tmp");

if(one && updated){
fs.appendFileSync(file, line+"\n");
appendFileSync(file, line+"\n");
continue;
}
const data = format.parse(line);
const data = parse(line);
let ob = false;
if(typeof search === "function"){
ob = search(data) || false;
ob = search(data, context) || false;
}else if(typeof search === "object" && !Array.isArray(search)){
ob = more.hasFieldsAdvanced(data, search);
ob = hasFieldsAdvanced(data, search);
}

@@ -47,13 +48,13 @@

if(typeof updater === "function"){
updateObj = updater(data);
updateObj = updater(data, context);
}else if(typeof updater === "object" && !Array.isArray(updater)){
updateObj = more.updateObject(data, updater);
updateObj = updateObject(data, updater);
}
line = await format.stringify(updateObj);
line = await stringify(updateObj);
updated = true;
}
fs.appendFileSync(file, line+"\n");
appendFileSync(file, line+"\n");
}
await fs.promises.writeFile(file+".tmp", "");
await promises.writeFile(file+".tmp", "");
return updated;

@@ -69,11 +70,12 @@ }

* @param {function|Object} obj - The updater function or object.
* @param {Object} context - The context object (for functions).
* @param {boolean} one - Indicates whether to update only one matching entry (default: false).
* @returns {Promise<boolean>} A Promise that resolves to `true` if entries were updated, or `false` otherwise.
*/
async function update(folder, name, arg, obj, one){
let files = fs.readdirSync(folder + "/" + name).filter(file => !/\.tmp$/.test(file));
async function update(folder, name, arg, obj, context={}, one){
let files = readdirSync(folder + "/" + name).filter(file => !/\.tmp$/.test(file));
files.reverse();
let update = false;
for(const file of files){
const updated = await updateWorker(folder + "/" + name + "/" + file, arg, obj, one);
const updated = await updateWorker(folder + "/" + name + "/" + file, arg, obj, context, one);
if(one && updated) return true;

@@ -85,2 +87,2 @@ update = update || updated;

module.exports = update;
export default update;

@@ -1,3 +0,3 @@

const fs = require("fs");
const readline = require("readline");
import { createReadStream } from "fs";
import { createInterface } from "readline";

@@ -10,3 +10,3 @@ /**

*/
function pathRepair(path){
export function pathRepair(path){
return path.replaceAll("//", "/");

@@ -21,5 +21,5 @@ }

*/
function createRL(file){
const read_stream = fs.createReadStream(file, { highWaterMark: 10 * 1024 * 1024 }); //10MB
const rl = readline.createInterface({
export function createRL(file){
const read_stream = createReadStream(file, { highWaterMark: 10 * 1024 * 1024 }); //10MB
const rl = createInterface({
input: read_stream,

@@ -29,4 +29,2 @@ crlfDelay: Infinity

return rl;
}
module.exports = { pathRepair, createRL };
}

@@ -1,27 +0,29 @@

const json5 = require("json5");
import json5 from "json5";
module.exports = {
/**
* Parse JSON5 data.
* @function
* @param {string} data - The JSON5 data to parse.
* @returns {Object} The parsed JavaScript object.
*/
parse: (data) => {
if(!data.startsWith("{")) data = "{"+data+"}";
return json5.parse(data);
},
/**
* Stringify data into JSON5 format.
* @function
* @param {Object} data - The JavaScript object to stringify.
* @returns {string} The JSON5 formatted string.
*/
stringify: (data) => {
data = json5.stringify(data);
if(data.startsWith("{")){
data = data.slice(1, -1);
}
return data;
},
};
/**
* Parses given string into a JSON object. If the string does not start with
* a {, it is wrapped in one. This allows for a shorthand when
* storing/reading data from a file.
*
* @param {string} data
* @returns {Object}
*/
export function parse(data){
if(!data.startsWith("{")) data = "{" + data + "}";
return json5.parse(data);
}
/**
* Converts given object to a string. If the string is a valid json5, it is
* returned as is. If it is a valid json5 wrapped in {}, the curly brackets
* are removed. Otherwise the string is wrapped in {}.
*
* @param {Object} data
* @return {String}
*/
export function stringify(data){
data = json5.stringify(data);
if(data.startsWith("{")){
data = data.slice(1, -1);
}
return data;
}

@@ -10,3 +10,3 @@ const usedIdsMap = new Map();

*/
function genId(parts, fill=1){
export default function genId(parts, fill=1){
parts = changeInputToPartsArray(parts, fill);

@@ -98,4 +98,2 @@ const time = getTime();

return [1, 1];
}
module.exports = genId;
}

@@ -1,36 +0,130 @@

const DataBase = require("./database");
import DataBase from "./database.js";
/**
* A class representing a graph database.
* @class
*/
class Graph{
constructor(folder){
this.db = new DataBase(folder);
/**
* Initializes the graph database.
* @constructor
* @param {string} databaseFolder - The folder where the database is stored.
*/
constructor(databaseFolder){
this.db = new DataBase(databaseFolder);
}
async add(collection, a, b){
[a, b] = [a, b].sort();
return await this.db.add(collection, { a, b }, false);
/**
* Adds an edge between two nodes.
* @async
* @function
* @param {string} collection - The name of the collection.
* @param {string} nodeA - The first node.
* @param {string} nodeB - The second node.
* @returns {Promise<Object>} A promise that resolves with the added edge.
*/
async add(collection, nodeA, nodeB){
const sortedNodes = [nodeA, nodeB].sort();
return await this.db.add(collection, {
a: sortedNodes[0],
b: sortedNodes[1]
}, false);
}
async remove(collection, a, b){
[a, b] = [a, b].sort();
return await this.db.removeOne(collection, { a, b });
/**
* Removes an edge between two nodes.
* @async
* @function
* @param {string} collection - The name of the collection.
* @param {string} nodeA - The first node.
* @param {string} nodeB - The second node.
* @returns {Promise<boolean>} A promise that resolves when the edge is removed.
*/
async remove(collection, nodeA, nodeB){
const sortedNodes = [nodeA, nodeB].sort();
const query = { a: sortedNodes[0], b: sortedNodes[1] };
return await this.db.removeOne(collection, query);
}
async find(collection, d){
const buffor = [];
const a = await this.db.find(collection, { a: d });
const b = await this.db.find(collection, { b: d });
if(a) buffor.push(...a);
if(b) buffor.push(...b);
return buffor;
/**
* Finds all edges with either node equal to `node`.
* @async
* @function
* @param {string} collection - The name of the collection.
* @param {string} node - The node to search for.
* @returns {Promise<Object[]>} A promise that resolves with the found edges.
*/
async find(collection, node){
const edges = [];
const edgesByANode = await this.db.find(collection, { a: node });
const edgesByBNode = await this.db.find(collection, { b: node });
if(edgesByANode) edges.push(...edgesByANode);
if(edgesByBNode) edges.push(...edgesByBNode);
return edges;
}
async findOne(collection, d, e){
const a = await this.db.findOne(collection, { a: d, b: e });
if(a) return a;
const b = await this.db.findOne(collection, { a: e, b: d });
if(b) return b;
/**
* Finds one edge with either node equal to `nodeA` and the other equal to `nodeB`.
* @async
* @function
* @param {string} collection - The name of the collection.
* @param {string} nodeA - The first node.
* @param {string} nodeB - The second node.
* @returns {Promise<Object|null>} A promise that resolves with the found edge or null if not found.
*/
async findOne(collection, nodeA, nodeB){
const edgeAB = await this.db.findOne(collection, { a: nodeA, b: nodeB });
if(edgeAB) return edgeAB;
const edgeBA = await this.db.findOne(collection, { a: nodeB, b: nodeA });
if(edgeBA) return edgeBA;
return null;
}
/**
* Gets all edges in the database.
* @async
* @function
* @param {string} collection - The name of the collection.
* @returns {Promise<Object[]>} A promise that resolves with all edges in the database.
*/
async getAll(collection){
return await this.db.find(collection, {});
}
/**
* Get the names of all available databases.
*
* @function
* @returns {string[]} An array of database names.
*/
async getCollections(){
return await this.db.getCollections();
}
/**
* Check and create the specified collection if it doesn't exist.
*
* @function
* @param {string} collection - The collection to check.
*/
async checkCollection(collection){
await this.dbAction.checkCollection(collection);
}
/**
* Check if a collection exists.
*
* @function
* @param {string} collection - The name of the collection.
* @returns {boolean} True if the collection exists, false otherwise.
*/
async issetCollection(collection){
return await this.dbAction.issetCollection(collection);
}
}
module.exports = Graph;
export default Graph;

@@ -9,22 +9,22 @@ /**

*/
function hasFieldsAdvanced(obj, fields){
if(typeof fields !== 'object' || fields === null){
export function hasFieldsAdvanced(obj, fields){
if(typeof fields !== "object" || fields === null){
throw new Error("Fields must be an object");
}
if('$and' in fields){
return fields['$and'].every(subFields => hasFieldsAdvanced(obj, subFields));
if("$and" in fields){
return fields["$and"].every(subFields => hasFieldsAdvanced(obj, subFields));
}
if('$or' in fields){
return fields['$or'].some(subFields => hasFieldsAdvanced(obj, subFields));
if("$or" in fields){
return fields["$or"].some(subFields => hasFieldsAdvanced(obj, subFields));
}
if('$set' in fields){
const setFields = fields['$set'];
if("$set" in fields){
const setFields = fields["$set"];
return hasFields(obj, setFields);
}
if('$not' in fields){
return !hasFieldsAdvanced(obj, fields['$not']);
if("$not" in fields){
return !hasFieldsAdvanced(obj, fields["$not"]);
}

@@ -42,7 +42,7 @@

*/
function hasFields(obj, fields){
export function hasFields(obj, fields){
const keys = Object.keys(fields);
return keys.every(key => {
if(obj[key]){
if(typeof fields[key] === 'object' && fields[key] !== null){
if(typeof fields[key] === "object" && fields[key] !== null){
return hasFields(obj[key], fields[key]);

@@ -63,3 +63,3 @@ }

*/
function updateObject(obj, newVal){
export function updateObject(obj, newVal){
for(let key in newVal){

@@ -73,6 +73,35 @@ if(newVal.hasOwnProperty(key)){

module.exports = {
hasFieldsAdvanced,
hasFields,
updateObject
/**
* Updates an object with new values from a findOpts object.
* @function
* @param {Object} obj - The object to update.
* @param {Object} findOpts - An object containing options to update the target object.
* @param {function} [findOpts.transform] - A function to transform the object before applying the other options.
* @param {string[]} [findOpts.select] - An array of fields to select from the target object.
* @param {string[]} [findOpts.exclude] - An array of fields to exclude from the target object.
* @returns {Object} The updated object.
*/
export function updateFindObject(obj, findOpts){
const {
transform,
select,
exclude,
} = findOpts;
if(typeof transform === "function") obj = transform(obj);
if(Array.isArray(exclude)){
exclude.forEach(field => {
if(obj.hasOwnProperty(field)) delete obj[field];
});
}
if(Array.isArray(select)){
obj = select.reduce((acc, field) => {
if(obj.hasOwnProperty(field)) acc[field] = obj[field];
return acc;
}, {});
}
return obj;
}
{
"name": "@wxn0brp/database.js",
"version": "0.0.1",
"version": "0.0.2",
"main": "index.js",
"description": "A simple file-based database management system with support for CRUD operations, custom queries, and graph structures.",
"homepage": "https://github.com/wxn0brP/fusion-chat/blob/master/back/db/README.md",
"homepage": "https://github.com/wxn0brP/database.js",
"repository": {
"type": "git",
"url": "https://github.com/wxn0brP/fusion-chat.git",
"directory": "back/db"
"url": "https://github.com/wxn0brP/database.js.git"
},
"keywords": ["database", "file-based", "CRUD", "graph", "query"],
"keywords": [
"database",
"file-based",
"CRUD",
"graph",
"query"
],
"author": "wxn0brP",
"license": "MIT",
"private": false,
"type": "module",
"dependencies": {
"body-parser": "^1.20.3",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.21.1",
"got": "^14.4.2",
"json5": "^2.2.3",
"jwt-simple": "^0.5.6",
"node-cache": "^5.1.2",
"readline": "^1.3.0"
}
}
}

@@ -16,5 +16,5 @@ # DataBase Class

```javascript
const DataBase = require('@wxn0brp/database');
import DataBase from '@wxn0brp/database/database.js';
async function main() {
async function main(){
// Initialize the database with a folder path and optional cache settings

@@ -24,3 +24,3 @@ const db = new DataBase('./data');

// Create or check a collection
db.checkCollection('users');
await db.checkCollection('users');

@@ -49,13 +49,14 @@ // Add a new user to the collection

| ----------- | ----------- | ---------- | ------- |
| `getDBs()` | Retrieves the names of all available databases. | None | `string[]` |
| `checkCollection()` | Ensures that a collection exists, creating it if necessary. | `collection` (string): Name of the collection | `void` |
| `add()` | Adds data to a collection, optionally generating an ID. | `collection` (string), `data` (Object), `id_gen` (boolean) | `Promise<Object>` |
| `find()` | Finds data entries matching a query. | `collection` (string), `search` (function/Object), `options` (Object) - { max, reverse } | `Promise<Array<Object>>` |
| `findOne()` | Finds the first data entry matching a query. | `collection` (string), `search` (function/Object) | `Promise<Object\|null>` |
| `update()` | Updates data entries matching a query. | `collection` (string), `search` (function/Object), `arg` (function/Object) | `Promise<boolean>` |
| `updateOne()` | Updates the first data entry matching a query. | `collection` (string), `search` (function/Object), `arg` (function/Object) | `Promise<boolean>` |
| `remove()` | Removes data entries matching a query. | `collection` (string), `search` (function/Object) | `Promise<boolean>` |
| `removeOne()` | Removes the first data entry matching a query. | `collection` (string), `search` (function/Object) | `Promise<boolean>` |
| `updateOneOrAdd()` | Updates one entry or adds a new one if no match is found. | `collection` (string), `search` (function/Object), `arg` (function/Object), `add_arg` (function/Object) | `Promise<boolean>` |
| `removeDb()` | Removes an entire database collection from the file system. | `collection` (string) | `void` |
| `getCollections` | Retrieves the names of all available collections. | None | `string[]` |
| `checkCollection` | Ensures that a collection exists, creating it if necessary. | `collection` (string): Name of the collection | `Promise<void>` |
| `issetCollection` | Checks if a collection exists. | `collection` (string): Name of the collection | `Promise<boolean>` |
| `add` | Adds data to a collection, optionally generating an ID. | `collection` (string), `data` (Object), `id_gen` (boolean) | `Promise<Object>` |
| `find` | Finds data entries matching a query. | `collection` (string), `search` (function/Object), `context` (Object), `options` (Object) - { max, reverse } | `Promise<Array<Object>>` |
| `findOne` | Finds the first data entry matching a query. | `collection` (string), `search` (function/Object), `context` (Object) | `Promise<Object\|null>` |
| `update` | Updates data entries matching a query. | `collection` (string), `search` (function/Object), `arg` (function/Object), `context` (Object) | `Promise<boolean>` |
| `updateOne` | Updates the first data entry matching a query. | `collection` (string), `search` (function/Object), `arg` (function/Object), `context` (Object) | `Promise<boolean>` |
| `remove` | Removes data entries matching a query. | `collection` (string), `search` (function/Object), `context` (Object) | `Promise<boolean>` |
| `removeOne` | Removes the first data entry matching a query. | `collection` (string), `search` (function/Object), `context` (Object) | `Promise<boolean>` |
| `updateOneOrAdd` | Updates one entry or adds a new one if no match is found. | `collection` (string), `search` (function/Object), `arg` (function/Object), `add_arg` (function/Object), `context` (Object), `id_gen` (boolean) | `Promise<boolean>` |
| `removeDb` | Removes an entire database collection from the file system. | `collection` (string) | `void` |

@@ -62,0 +63,0 @@ ---

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc