all.db
Version:
JSON Database
241 lines (197 loc) • 7.49 kB
text/typescript
import { writeFileSync, readFileSync, existsSync } from "fs";
class Database {
private readFile: () => any;
private writeFile: (data: any) => void;
constructor({ dataPath = "./data.json" } = {}) {
if (!existsSync(dataPath)) writeFileSync(dataPath, `{\n}`, { flag: 'wx' });
this.readFile = () => JSON.parse(readFileSync(dataPath, "utf-8"));
this.writeFile = (data) => writeFileSync(dataPath, JSON.stringify(data, null, 4));
}
set(key: string, value: any) {
const data = this.readFile();
if (!key) throw new Error("Please enter data name.");
const text = key.toString();
function setValue(obj: any, path: string, value: any) {
const name = path.split(".");
let current = obj;
for (let i = 0; i < name.length - 1; i++) {
const prop = name[i];
if (typeof current[prop] !== "object" || current[prop] === null) {
current[prop] = {};
}
current = current[prop];
}
const key = name[name.length - 1];
const index = parseInt(key);
if (value === undefined && Array.isArray(current) && !isNaN(index)) {
current.splice(index, 1);
} else {
current[key] = value;
}
}
setValue(data, text, value);
this.writeFile(data);
return this.get(key);
}
get(key: string) {
const data = this.readFile();
if (!key) throw new Error("Please enter key.");
const text = key.toString();
function getValue(obj: any, path: string) {
const name = path.split(".");
let current = obj;
for (const prop of name) {
if (typeof current !== "object" || !current.hasOwnProperty(prop)) {
return undefined;
}
current = current[prop];
}
return current;
}
return getValue(data, text);
}
delete(key: string) {
if (typeof key === "function") {
const filtered = this.filter(key);
Object.keys(filtered).forEach(i => {
this.set(i, undefined);
});
return filtered;
} else if (typeof key === "string") {
return this.set(key, undefined);
} else {
throw new Error("Key can only be string or function");
}
}
add(key: string, number: number) {
const data = this.get(key) || 0;
if (isNaN(data) || isNaN(number)) {
throw new Error("Both arguments must be numbers.");
}
return this.set(key, (data + number));
}
subtract(key: string, number: number) {
const data = this.get(key) || 0;
if (isNaN(data) || isNaN(number)) {
throw new Error("Both arguments must be numbers.");
}
return this.set(key, (data - number));
}
push(key: string, value: any, hardly: boolean = false) {
const data = this.get(key);
if (data == null) {
return this.set(key, [value]);
} else if (Array.isArray(data)) {
data.push(value);
return this.set(key, data);
} else {
if (hardly !== true) {
throw new Error("This is not an array");
}
return this.set(key, [value]);
}
}
pull(key: string, func: any) {
const data = this.get(key);
if (!Array.isArray(data)) throw new Error("This is not an array");
if (typeof func !== "function") throw new Error("This is not a function");
const filteredItems = Object.entries(data).filter(func);
filteredItems.forEach((value) => {
const index = data.indexOf(value[1]);
if (index != -1) data.splice(index, 1);
});
return this.set(key, data);
}
has(key: string) {
return this.get(key) !== undefined;
}
typeof(key: string, type = "string") {
const data = this.get(key);
if (!data) {
throw new Error("This is not a data");
}
const allowedTypes = ["undefined", "object", "boolean", "number", "bigint", "string", "symbol", "function"];
if (!allowedTypes.includes(type.toLowerCase())) {
throw new Error("This type is not included");
}
if (typeof data === type) {
return true;
}
return false;
}
math(key: string, symbol: string, number: number) {
const data = this.get(key);
if (isNaN(data) || isNaN(number)) throw new Error("This is not a number");
let dt;
switch (symbol) {
case "+":
dt = data + number;
break;
case "-":
dt = data - number;
break;
case "*":
dt = data * number;
break;
case "/":
dt = data / number;
break;
case "%":
dt = data % number;
break;
default:
throw new Error("Invalid symbol");
}
return this.set(key, dt);
}
find(text: string, tCase: boolean) {
const data = this.readFile();
const getKeys = (obj: any, path: string[] = []): string[] => {
if (Object(obj) !== obj) {
return [path.join(".")];
}
return Object.entries(obj).flatMap(([key, val]) =>
getKeys(val, [...path, key])
);
};
const result: any = [];
getKeys(data).forEach((key: string) => {
const getData = this.get(key);
if (!getData) {
return;
}
if (tCase && getData.toString().toLowerCase() === text.toString().toLowerCase()) {
result.push([key, getData]);
} else if (getData === text) {
result.push([key, getData]);
}
});
return result;
}
filter(func: any) {
const data = this.readFile();
if (typeof func !== "function") throw new Error("This is not a function");
const filteredEntries = Object.entries(data).filter(func);
return Object.fromEntries(filteredEntries);
}
getAll() {
const data = this.readFile();
const newData = JSON.parse(JSON.stringify(data));
Object.defineProperty(newData, 'save', {
enumerable: false,
value: function (path = './save.json') {
if (!existsSync(path)) {
writeFileSync(path, JSON.stringify(newData, null, 4), { flag: 'wx' });
} else {
writeFileSync(path, JSON.stringify(newData, null, 4));
}
}
});
return newData;
}
remove(key: string) { return this.delete(key) }
fetch(key: string) { return this.get(key) }
exists(key: string) { return this.has(key) }
substr(key: string, number: number) { return this.subtract(key, number) }
}
export { Database };