UNPKG

pallas-db

Version:
176 lines (175 loc) 6.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SteganographyStorage = void 0; const path = require("node:path"); const node_fs_1 = require("node:fs"); const steggy = require("steggy-noencrypt"); class SteganographyStorage { filePath; templatePath; data = {}; constructor(filePath, options = {}) { this.filePath = filePath; this.templatePath = options.templatePath || path.join(process.cwd(), 'assets', 'default_database_image.png'); this.loadFromFile(); } loadFromFile() { try { if ((0, node_fs_1.existsSync)(this.filePath)) { // Decode data from PNG file const image = (0, node_fs_1.readFileSync)(this.filePath); const encodedData = steggy.reveal(image); if (encodedData) { const rawData = JSON.parse(encodedData); // Handle migration from old format to new format this.data = {}; for (const [tableName, tableData] of Object.entries(rawData)) { if (Array.isArray(tableData)) { // New format: array of { id, value } this.data[tableName] = tableData; } else if (typeof tableData === 'object' && tableData !== null) { // Old format: object with keys as properties - convert to new format this.data[tableName] = Object.entries(tableData).map(([id, value]) => ({ id, value: value })); } else { this.data[tableName] = []; } } } else { this.data = {}; } } else { // If file doesn't exist, create it from template this.createFromTemplate(); } } catch (error) { console.warn('Failed to load steganography file, starting with empty data:', error); this.data = {}; this.createFromTemplate(); } } createFromTemplate() { try { if ((0, node_fs_1.existsSync)(this.templatePath)) { // Copy template to target location const dir = path.dirname(this.filePath); if (!(0, node_fs_1.existsSync)(dir)) { (0, node_fs_1.mkdirSync)(dir, { recursive: true }); } (0, node_fs_1.copyFileSync)(this.templatePath, this.filePath); } else { console.warn(`Template PNG not found at ${this.templatePath}, please provide a valid template PNG file`); } } catch (error) { console.error('Failed to create steganography file from template:', error); } } saveToFile() { try { const dir = path.dirname(this.filePath); if (!(0, node_fs_1.existsSync)(dir)) { (0, node_fs_1.mkdirSync)(dir, { recursive: true }); } // Ensure we have a valid PNG file to work with if (!(0, node_fs_1.existsSync)(this.filePath)) { this.createFromTemplate(); } // Encode data into PNG file const original = (0, node_fs_1.readFileSync)(this.filePath); const concealed = steggy.conceal(original, JSON.stringify(this.data)); (0, node_fs_1.writeFileSync)(this.filePath, concealed); } catch (error) { console.error('Failed to save steganography file:', error); } } getTable(tableName) { if (!this.data[tableName]) { this.data[tableName] = []; } return this.data[tableName]; } findRecord(tableName, id) { const table = this.getTable(tableName); const index = table.findIndex((record) => record.id === id); return { record: index !== -1 ? table[index] : null, index }; } getRecord(tableName, id) { const { record } = this.findRecord(tableName, id); return record?.value; } setTableData(tableName, key, value) { const table = this.getTable(tableName); const { record, index } = this.findRecord(tableName, key); if (record) { // Update existing record table[index] = { id: key, value }; } else { // Add new record table.push({ id: key, value }); } this.saveToFile(); } deleteTableKey(tableName, key) { if (this.data[tableName]) { const { index } = this.findRecord(tableName, key); if (index !== -1) { this.data[tableName].splice(index, 1); this.saveToFile(); } } } clearTable(tableName) { this.data[tableName] = []; this.saveToFile(); } hasKey(tableName, key) { const { record } = this.findRecord(tableName, key); return record !== null; } getAllFromTable(tableName) { return this.getTable(tableName); } getStats() { const stats = {}; for (const [tableName, table] of Object.entries(this.data)) { stats[tableName] = table.length; } return stats; } repair(tables, validateKey, validateValue) { const deletedKeys = []; for (const tableName of tables) { if (this.data[tableName]) { const validRecords = []; for (const record of this.data[tableName]) { if (validateKey(record.id) && validateValue(record.value)) { validRecords.push(record); } else { deletedKeys.push(`${tableName}.${record.id}`); } } this.data[tableName] = validRecords; } } if (deletedKeys.length > 0) { this.saveToFile(); } return deletedKeys; } } exports.SteganographyStorage = SteganographyStorage;