/** * Storage Service - บริการสำหรับจัดเก็บข้อมูลใน localStorage */ (function(global) { 'use strict'; /** * คลาส StorageService * บริการสำหรับจัดเก็บข้อมูลใน localStorage */ class StorageService { constructor(editor) { this.editor = editor; this.prefix = 'editor_'; this.encryptionEnabled = false; this.encryptionKey = null; } /** * บันทึกข้อมูล * @param {string} key - คีย์ * @param {*} data - ข้อมูลที่จะบันทึก * @param {Object} options - ตัวเลือก (optional) */ save(key, data, options = {}) { try { const prefixedKey = this.prefix + key; // แปลงข้อมูลเป็น JSON let serializedData = JSON.stringify({ data, timestamp: Date.now(), version: options.version || '1.0.0' }); // เข้ารหัสถ้าเปิดใช้งาน if (this.encryptionEnabled) { serializedData = this.encrypt(serializedData); } // บันทึกใน localStorage localStorage.setItem(prefixedKey, serializedData); // ส่งเหตุการณ์ this.editor.emit('storage:saved', {key, data}); if (this.editor.config.debug) { console.log(`Data saved to storage: ${key}`); } return true; } catch (error) { console.error(`Failed to save data to storage: ${key}`, error); // ส่งเหตุการณ์ this.editor.emit('storage:save-error', {key, error}); return false; } } /** * โหลดข้อมูล * @param {string} key - คีย์ * @param {*} defaultValue - ค่าเริ่มต้น (optional) * @param {Object} options - ตัวเลือก (optional) * @returns {*} ข้อมูลที่โหลด */ load(key, defaultValue = null, options = {}) { try { const prefixedKey = this.prefix + key; // โหลดจาก localStorage let serializedData = localStorage.getItem(prefixedKey); if (!serializedData) { return defaultValue; } // ถอดรหัสถ้าเปิดใช้งาน if (this.encryptionEnabled) { serializedData = this.decrypt(serializedData); } // แปลงจาก JSON const parsedData = JSON.parse(serializedData); // ตรวจสอบเวอร์ชัน if (options.version && parsedData.version !== options.version) { console.warn(`Version mismatch for ${key}: expected ${options.version}, got ${parsedData.version}`); // ส่งเหตุการณ์ this.editor.emit('storage:version-mismatch', { key, expected: options.version, actual: parsedData.version }); return defaultValue; } // ส่งเหตุการณ์ this.editor.emit('storage:loaded', {key, data: parsedData.data}); if (this.editor.config.debug) { console.log(`Data loaded from storage: ${key}`); } return parsedData.data; } catch (error) { console.error(`Failed to load data from storage: ${key}`, error); // ส่งเหตุการณ์ this.editor.emit('storage:load-error', {key, error}); return defaultValue; } } /** * ลบข้อมูล * @param {string} key - คีย์ * @returns {boolean} สำเร็จหรือไม่ */ remove(key) { try { const prefixedKey = this.prefix + key; // ตรวจสอบว่ามีข้อมูลหรือไม่ if (!localStorage.getItem(prefixedKey)) { return false; } // ลบข้อมูล localStorage.removeItem(prefixedKey); // ส่งเหตุการณ์ this.editor.emit('storage:removed', {key}); if (this.editor.config.debug) { console.log(`Data removed from storage: ${key}`); } return true; } catch (error) { console.error(`Failed to remove data from storage: ${key}`, error); // ส่งเหตุการณ์ this.editor.emit('storage:remove-error', {key, error}); return false; } } /** * ตรวจสอบว่ามีข้อมูลหรือไม่ * @param {string} key - คีย์ * @returns {boolean} มีข้อมูลหรือไม่ */ exists(key) { const prefixedKey = this.prefix + key; return localStorage.getItem(prefixedKey) !== null; } /** * รับคีย์ทั้งหมด * @returns {Array} รายการคีย์ทั้งหมด */ getAllKeys() { const keys = []; for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); if (key && key.startsWith(this.prefix)) { // ลบ prefix keys.push(key.substring(this.prefix.length)); } } return keys; } /** * ล้างข้อมูลทั้งหมด */ clear() { const keys = this.getAllKeys(); keys.forEach(key => { this.remove(key); }); // ส่งเหตุการณ์ this.editor.emit('storage:cleared'); if (this.editor.config.debug) { console.log('All data cleared from storage'); } } /** * รับขนาดข้อมูลทั้งหมด * @returns {number} ขนาดข้อมูล (bytes) */ getSize() { let size = 0; for (let key in localStorage) { if (localStorage.hasOwnProperty(key) && key.startsWith(this.prefix)) { size += localStorage[key].length + key.length; } } return size; } /** * ตั้งค่าการเข้ารหัส * @param {boolean} enabled - เปิดใช้งานหรือไม่ * @param {string} key - คีย์เข้ารหัส (optional) */ setEncryption(enabled, key = null) { this.encryptionEnabled = enabled; if (enabled && key) { this.encryptionKey = key; } } /** * เข้ารหัสข้อมูล * @param {string} data - ข้อมูลที่จะเข้ารหัส * @returns {string} ข้อมูลที่เข้ารหัสแล้ว */ encrypt(data) { if (!this.encryptionEnabled || !this.encryptionKey) { return data; } try { // ใช้งานง่ายๆ ด้วย XOR let encrypted = ''; for (let i = 0; i < data.length; i++) { const charCode = data.charCodeAt(i); const keyChar = this.encryptionKey.charCodeAt(i % this.encryptionKey.length); encrypted += String.fromCharCode(charCode ^ keyChar); } // แปลงเป็น Base64 return btoa(encrypted); } catch (error) { console.error('Failed to encrypt data:', error); return data; } } /** * ถอดรหัสข้อมูล * @param {string} encryptedData - ข้อมูลที่เข้ารหัส * @returns {string} ข้อมูลที่ถอดรหัสแล้ว */ decrypt(encryptedData) { if (!this.encryptionEnabled || !this.encryptionKey) { return encryptedData; } try { // แปลงจาก Base64 const data = atob(encryptedData); // ใช้งานง่ายๆ ด้วย XOR let decrypted = ''; for (let i = 0; i < data.length; i++) { const charCode = data.charCodeAt(i); const keyChar = this.encryptionKey.charCodeAt(i % this.encryptionKey.length); decrypted += String.fromCharCode(charCode ^ keyChar); } return decrypted; } catch (error) { console.error('Failed to decrypt data:', error); return encryptedData; } } /** * ส่งออกข้อมูลเป็นไฟล์ * @param {string} key - คีย์ * @param {string} filename - ชื่อไฟล์ * @param {string} type - ประเภทไฟล์ (optional) */ exportToFile(key, filename, type = 'application/json') { try { const data = this.load(key); if (data === null) { throw new Error(`Data not found for key: ${key}`); } // สร้าง Blob const blob = new Blob([JSON.stringify(data, null, 2)], {type}); // สร้าง URL const url = URL.createObjectURL(blob); // สร้างลิงก์ดาวน์โหลด const a = document.createElement('a'); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); // ลบ URL URL.revokeObjectURL(url); // ส่งเหตุการณ์ this.editor.emit('storage:exported', {key, filename}); return true; } catch (error) { console.error(`Failed to export data to file: ${key}`, error); // ส่งเหตุการณ์ this.editor.emit('storage:export-error', {key, error}); return false; } } /** * นำเข้าข้อมูลจากไฟล์ * @param {string} key - คีย์ * @param {File} file - ไฟล์ที่จะนำเข้า * @returns {Promise} Promise ที่ส่งคืนผลการนำเข้า */ importFromFile(key, file) { return new Promise((resolve, reject) => { try { const reader = new FileReader(); reader.onload = (e) => { try { const data = JSON.parse(e.target.result); // บันทึกข้อมูล const success = this.save(key, data); if (success) { // ส่งเหตุการณ์ this.editor.emit('storage:imported', {key, file}); resolve(data); } else { reject(new Error(`Failed to save imported data for key: ${key}`)); } } catch (error) { reject(new Error(`Failed to parse imported file: ${error.message}`)); } }; reader.onerror = () => { reject(new Error('Failed to read file')); }; reader.readAsText(file); } catch (error) { reject(error); } }); } } // เปิดเผยคลาส StorageService ทั่วโลก global.StorageService = StorageService; })(typeof window !== 'undefined' ? window : this);