upgrade.db
Version:
Banco de dados simples e leve em JSON para bots Node.js com suporte a tabelas e métodos modernos.
221 lines (185 loc) • 5.96 kB
JavaScript
const fs = require('fs');
const path = require('path');
class Table {
constructor(name, dir = './db') {
this.name = name;
this.dir = dir;
this.filePath = path.join(this.dir, `${name}.json`);
this.data = {};
if (!fs.existsSync(this.dir)) fs.mkdirSync(this.dir, { recursive: true });
if (fs.existsSync(this.filePath)) {
try {
this.data = JSON.parse(fs.readFileSync(this.filePath, 'utf8'));
} catch {
this.data = {};
}
} else {
this.save();
}
}
save() {
try {
fs.writeFileSync(this.filePath, JSON.stringify(this.data, null, 2));
} catch (err) {
console.error(`Erro ao salvar o arquivo ${this.filePath}:`, err);
}
}
set(key, value) {
const keys = key.split('.');
let obj = this.data;
for (let i = 0; i < keys.length - 1; i++) {
if (!obj[keys[i]]) obj[keys[i]] = {};
obj = obj[keys[i]];
}
obj[keys[keys.length - 1]] = value;
this.save();
return true;
}
get(key) {
const keys = key.split('.');
let obj = this.data;
for (const k of keys) {
if (!obj || !(k in obj)) return undefined;
obj = obj[k];
}
return obj;
}
delete(key) {
const keys = key.split('.');
let obj = this.data;
for (let i = 0; i < keys.length - 1; i++) {
if (!obj[keys[i]]) return false;
obj = obj[keys[i]];
}
const deleted = delete obj[keys[keys.length - 1]];
if (deleted) this.save();
return deleted;
}
has(key) {
const val = this.get(key);
return val !== undefined && val !== null;
}
push(key, value) {
const current = this.get(key) || [];
if (!Array.isArray(current)) throw new Error(`"${key}" não é um array`);
if (!current.includes(value)) {
current.push(value);
this.set(key, current);
}
return true;
}
add(key, number) {
if (typeof number !== 'number') throw new TypeError('Valor precisa ser número');
let current = this.get(key) || 0;
if (typeof current !== 'number') throw new Error(`"${key}" não é um número`);
this.set(key, current + number);
return true;
}
subtract(key, number) {
if (typeof number !== 'number') throw new TypeError('Valor precisa ser número');
let current = this.get(key) || 0;
if (typeof current !== 'number') throw new Error(`"${key}" não é um número`);
this.set(key, current - number);
return true;
}
includes(key, value) {
const arr = this.get(key);
if (!Array.isArray(arr)) return false;
return arr.includes(value);
}
filter(callback) {
const results = {};
for (const key in this.data) {
if (!Object.prototype.hasOwnProperty.call(this.data, key)) continue;
if (callback(this.data[key], key)) {
results[key] = this.data[key];
}
}
return results;
}
math(key, operator, value) {
let current = this.get(key);
if (typeof current !== 'number') current = 0;
if (typeof value !== 'number') throw new TypeError('Valor precisa ser número');
switch (operator) {
case '+':
current += value;
break;
case '-':
current -= value;
break;
case '*':
current *= value;
break;
case '/':
if (value === 0) throw new Error('Divisão por zero');
current /= value;
break;
default:
throw new Error(`Operador inválido: ${operator}`);
}
this.set(key, current);
return current;
}
// Novos métodos adicionados e seguros — só funcionam se métodos base existem
max(key, value, maxValue) {
if (typeof value !== 'number') throw new TypeError('Valor precisa ser número');
if (typeof maxValue !== 'number') throw new TypeError('maxValue precisa ser número');
let current = typeof this.get === 'function' ? this.get(key) : 0;
if (typeof current !== 'number') current = 0;
let newValue = current + value;
if (newValue > maxValue) newValue = maxValue;
if (typeof this.set === 'function') this.set(key, newValue);
return newValue;
}
min(key, value, minValue) {
if (typeof value !== 'number') throw new TypeError('Valor precisa ser número');
if (typeof minValue !== 'number') throw new TypeError('minValue precisa ser número');
let current = typeof this.get === 'function' ? this.get(key) : 0;
if (typeof current !== 'number') current = 0;
let newValue = current - value;
if (newValue < minValue) newValue = minValue;
if (typeof this.set === 'function') this.set(key, newValue);
return newValue;
}
reset(key, defaultValue = null) {
if (defaultValue === null) {
if (typeof this.delete === 'function') return this.delete(key);
} else {
if (typeof this.set === 'function') return this.set(key, defaultValue);
}
return false;
}
clamp(key, minValue, maxValue) {
if (typeof minValue !== 'number' || typeof maxValue !== 'number') {
throw new TypeError('minValue e maxValue precisam ser números');
}
if (minValue > maxValue) {
throw new Error('minValue não pode ser maior que maxValue');
}
let current = typeof this.get === 'function' ? this.get(key) : minValue;
if (typeof current !== 'number') current = minValue;
if (current < minValue) current = minValue;
if (current > maxValue) current = maxValue;
if (typeof this.set === 'function') this.set(key, current);
return current;
}
incrementBy(key, value = 1) {
if (typeof this.add === 'function') return this.add(key, value);
return false;
}
decrementBy(key, value = 1) {
if (typeof this.subtract === 'function') return this.subtract(key, value);
return false;
}
}
class UpgradeDB {
constructor(dir = './db') {
this.dir = dir;
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
}
table(name) {
return new Table(name, this.dir);
}
}
module.exports = UpgradeDB;