IndexedDBWrapper предоставляет высокоуровневый интерфейс для выполнения основных операций с IndexedDB: открытия базы данных, добавления, получения, обновления и удаления записей. Использование асинхронного программирования через async/await обеспечивает более читаемый и поддерживаемый код.

Обёртка для работы с IndexedDB на JavaScript: класс IndexedDBWrapper

IndexedDBWrapper предоставляет высокоуровневый интерфейс для выполнения основных операций с IndexedDB: открытия базы данных, добавления, получения, обновления и удаления записей. Использование асинхронного программирования через async/await обеспечивает более читаемый и поддерживаемый код.

// Класс-обёртка для удобной работы с IndexedDB
export default class IndexedDBWrapper {
    /**
     * Конструктор класса
     * @param {string} dbName - Имя базы данных
     * @param {number} version - Версия базы данных (по умолчанию 1)
     * @param {function} onUpgradeNeededCallback - Функция, вызываемая при обновлении базы данных
     */
    constructor(dbName, version = 1, onUpgradeNeededCallback = null) {
        this.dbName = dbName;
        this.version = version;
        this.db = null;
        this.onUpgradeNeededCallback = onUpgradeNeededCallback;
    }

    /**
     * Открытие базы данных с использованием async/await
     */
    async open() {
        try {
            this.db = await this.openDB();
            console.log(`Database ${this.dbName} opened successfully`);
        } catch (err) {
            console.error("Error opening database", err);
        }
    }

    /**
     * Открытие базы данных и обработка обновления версии
     * @returns {Promise<IDBDatabase>}
     */
    openDB() {
        return new Promise((resolve, reject) => {
            const request = indexedDB.open(this.dbName, this.version);

            // Обработка события обновления базы данных
            request.onupgradeneeded = (event) => {
                if (this.onUpgradeNeededCallback) {
                    this.onUpgradeNeededCallback(event);
                }
            };

            // Успешное открытие базы данных
            request.onsuccess = (event) => resolve(event.target.result);

            // Ошибка открытия базы данных
            request.onerror = (event) => reject(event.target.error);
        });
    }

    /**
     * Добавление данных в указанное хранилище
     * @param {string} storeName - Имя хранилища объектов
     * @param {Object} data - Данные для добавления
     */
    async add(storeName, data) {
        try {
            const result = await this.transaction(storeName, 'readwrite', (store) => store.add(data));
            console.log('Data added', result);
            return result;
        } catch (err) {
            console.error('Error adding data', err);
        }
    }

    /**
     * Получение данных по ключу из указанного хранилища
     * @param {string} storeName - Имя хранилища объектов
     * @param {IDBValidKey} key - Ключ для поиска
     */
    async get(storeName, key) {
        try {
            const result = await this.transaction(storeName, 'readonly', (store) => store.get(key));
            console.log('Data retrieved', result);
            return result;
        } catch (err) {
            console.error('Error retrieving data', err);
        }
    }

    /**
     * Обновление данных в указанном хранилище
     * @param {string} storeName - Имя хранилища объектов
     * @param {Object} data - Данные для обновления (должны содержать ключ)
     */
    async update(storeName, data) {
        try {
            const result = await this.transaction(storeName, 'readwrite', (store) => store.put(data));
            console.log('Data updated', result);
            return result;
        } catch (err) {
            console.error('Error updating data', err);
        }
    }

    /**
     * Удаление данных по ключу из указанного хранилища
     * @param {string} storeName - Имя хранилища объектов
     * @param {IDBValidKey} key - Ключ записи для удаления
     */
    async delete(storeName, key) {
        try {
            await this.transaction(storeName, 'readwrite', (store) => store.delete(key));
            console.log('Data deleted');
        } catch (err) {
            console.error('Error deleting data', err);
        }
    }

    /**
     * Выполнение транзакции с использованием async/await
     * @param {string} storeName - Имя хранилища объектов
     * @param {string} mode - Режим транзакции ('readonly' или 'readwrite')
     * @param {function} callback - Функция, выполняющая операцию над хранилищем
     * @returns {Promise<any>}
     */
    transaction(storeName, mode, callback) {
        return new Promise((resolve, reject) => {
            const transaction = this.db.transaction(storeName, mode);
            const store = transaction.objectStore(storeName);

            const request = callback(store);

            request.onsuccess = (event) => resolve(event.target.result);
            request.onerror = (event) => reject(event.target.error);
        });
    }

    /**
     * Закрытие соединения с базой данных
     */
    close() {
        if (this.db) {
            this.db.close();
            console.log('Database closed');
        }
    }
}