UNPKG

rashi-discord-bot-lib

Version:

🚀 Powerful Discord bot framework with built-in database, event handling, and utilities

249 lines 9.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.VerseDB = void 0; // src/database/VerseDB.ts const fs = __importStar(require("fs")); const path = __importStar(require("path")); const JsonAdapter_1 = require("./adapters/JsonAdapter"); const YamlAdapter_1 = require("./adapters/YamlAdapter"); const MongoAdapter_1 = require("./adapters/MongoAdapter"); const SQLAdapter_1 = require("./adapters/SQLAdapter"); const Crypto_1 = require("../utils/Crypto"); const Logger_1 = require("../utils/Logger"); class VerseDB { adapter; config; logger; data = {}; isInitialized = false; constructor(config, logger) { this.config = config; this.logger = logger || new Logger_1.Logger(); this.adapter = this.createAdapter(); } /** Initialize the database */ async initialize() { try { if (typeof this.adapter.connect === 'function') { await this.adapter.connect(); } if (this.isFileBased() && this.config.path) { if (!fs.existsSync(this.config.path)) { fs.mkdirSync(this.config.path, { recursive: true }); } } let exists = false; try { exists = this.adapter.exists(); } catch { exists = false; } if (exists) { const raw = await this.adapter.read(); this.data = this.config.secure?.enable && this.config.secure.secret ? this.decryptData(raw) : (raw ?? {}); } else { this.data = {}; await this.save(); } this.isInitialized = true; } catch (error) { this.logger.error('Failed to initialize VerseDB:', error); throw error; } } get(key) { this.checkInitialized(); const keys = key.split('.'); let current = this.data; for (const k of keys) { if (current && typeof current === 'object' && k in current) current = current[k]; else return undefined; } return current; } async set(key, value) { this.checkInitialized(); const keys = key.split('.'); let current = this.data; for (let i = 0; i < keys.length - 1; i++) { const k = keys[i]; if (!current[k] || typeof current[k] !== 'object') current[k] = {}; current = current[k]; } current[keys[keys.length - 1]] = value; await this.save(); } async delete(key) { this.checkInitialized(); const keys = key.split('.'); let current = this.data; for (let i = 0; i < keys.length - 1; i++) { const k = keys[i]; if (!current[k] || typeof current[k] !== 'object') return; current = current[k]; } delete current[keys[keys.length - 1]]; await this.save(); } has(key) { return this.get(key) !== undefined; } all() { this.checkInitialized(); return Object.entries(this.data).map(([key, value]) => ({ key, value })); } async clear() { this.checkInitialized(); this.data = {}; await this.save(); } async backup(backupPath) { this.checkInitialized(); const baseDir = this.config.path ?? process.cwd(); const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const backupFile = backupPath || path.join(baseDir, `backup-${timestamp}.json`); await this.adapter.backup(backupFile); this.logger.info(`📦 Database backed up to: ${backupFile}`); } async restore(backupPath) { this.checkInitialized(); await this.adapter.restore(backupPath); const raw = await this.adapter.read(); this.data = this.config.secure?.enable && this.config.secure.secret ? this.decryptData(raw) : (raw ?? {}); this.logger.info(`📥 Database restored from: ${backupPath}`); } async getStats() { this.checkInitialized(); const dataString = JSON.stringify(this.data); return { size: Buffer.byteLength(dataString, 'utf8'), keys: Object.keys(this.data).length, adapter: this.config.adapterType }; } async healthCheck() { try { return this.isInitialized && this.adapter.exists(); } catch { return false; } } async close() { if (!this.isInitialized) return; await this.save(); if (typeof this.adapter.disconnect === 'function') { await this.adapter.disconnect(); } this.isInitialized = false; this.logger.info('🗃️ VerseDB connection closed'); } async save() { let toSave = this.data; if (this.config.secure?.enable && this.config.secure.secret) { toSave = this.encryptData(this.data); } await this.adapter.write(toSave); } createAdapter() { switch (this.config.adapterType) { case 'json': { if (!this.config.path) throw new Error('VerseConfig.path is required for JSON adapter'); const filePath = path.join(this.config.path, `database.json`); return new JsonAdapter_1.JsonAdapter(filePath); } case 'yaml': { if (!this.config.path) throw new Error('VerseConfig.path is required for YAML adapter'); const filePath = path.join(this.config.path, `database.yaml`); return new YamlAdapter_1.YamlAdapter(filePath); } case 'mongo': { const uri = this.config.mongoURI; if (!uri) throw new Error('VerseConfig.mongoURI is required for Mongo adapter'); const dbName = this.config.dbName ?? 'verse'; const collection = this.config.collection ?? 'versedb'; const documentId = this.config.documentId ?? 'versedb_data'; return new MongoAdapter_1.MongoAdapter(uri, dbName, collection, documentId); } case 'sqlite': { if (!this.config.path) throw new Error('VerseConfig.path is required for SQLite adapter'); const filePath = path.join(this.config.path, `database.sqlite`); return new SQLAdapter_1.SQLAdapter(filePath); } default: throw new Error(`Unsupported adapter type: ${this.config.adapterType}`); } } isFileBased() { return ['json', 'yaml', 'sqlite'].includes(this.config.adapterType); } encryptData(data) { if (!this.config.secure?.secret) return data; const dataString = JSON.stringify(data); const encrypted = Crypto_1.Crypto.encrypt(dataString, this.config.secure.secret); return { __encrypted: encrypted }; } decryptData(data) { if (!this.config.secure?.secret || !data?.__encrypted) return data; const decrypted = Crypto_1.Crypto.decrypt(data.__encrypted, this.config.secure.secret); return JSON.parse(decrypted); } checkInitialized() { if (!this.isInitialized) { throw new Error('VerseDB not initialized. Call initialize() first.'); } } } exports.VerseDB = VerseDB; //# sourceMappingURL=VerseDB.js.map