"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.addItem = exports.updateItem = exports.createItem = exports.deleteItem = exports.readItem = void 0;
const helpers_1 = require("./helpers");
const open_database_1 = require("./open-database");
/**
 * Read item for the provided store key
 *
 * @remarks The `readItem` method yields the value of the provided key, or undefined if it does not exist. You can chain assertions from this method. If you use TypeScript, you can set the type of the returned value
 *
 * @param store `IDBObjectStore` instance
 * @param key
 *
 * @returns  Promise<T>
 * @throws {Error} If it is chained off from a method that does not return an object store.
 */
function readItem(store, key) {
    const { log, consoleProps } = createCRUDLog('read', key);
    if (!(0, helpers_1.isIDBObjectStore)(store)) {
        const error = new Error(`You tried to use the 'readItem' method without calling 'getObjectStore' first`);
        consoleProps.error = error;
        log.error(error).end();
        throw error;
    }
    return cy.wrap((0, open_database_1.createDatabaseConnection)(store.transaction.db.name)
        .then((openDb) => makeCreateUpdateDeleteRequest('get', openDb, store, key))
        .then((result) => {
        consoleProps.value = result;
        log.end();
        return result;
    })
        .catch((e) => {
        consoleProps.error = e;
        log.error(e).end();
        throw e;
    }));
}
exports.readItem = readItem;
/**
 * Delete item for the provided store key
 *
 * @remarks The `deleteItem` method deletes the value of the provided key, or undefined if it does not exist. You can chain assertions from this method. If you use TypeScript, you can set the type of the returned value
 *
 * @param store `IDBObjectStore` instance
 * @param key
 *
 * @returns Promise<IDBObjectStore>
 * @throws {Error} If it is chained off from a method that does not return an object store.
 */
function deleteItem(store, key) {
    const { log, consoleProps } = createCRUDLog('delete', key);
    if (!(0, helpers_1.isIDBObjectStore)(store)) {
        const error = new Error(`You tried to use the 'deleteItem' method without calling 'getObjectStore' first`);
        consoleProps.error = error;
        log.error(error).end();
        throw error;
    }
    return cy.wrap((0, open_database_1.createDatabaseConnection)(store.transaction.db.name)
        .then((openDb) => makeCreateUpdateDeleteRequest('delete', openDb, store, key))
        .then((store) => {
        log.end();
        return store;
    })
        .catch((e) => {
        consoleProps.error = e;
        log.error(e).end();
        throw e;
    }));
}
exports.deleteItem = deleteItem;
/**
 * Create item for the provided store key
 *
 * @remarks The `createItem` method creates the key and value. You can chain assertions from this method. If you use TypeScript, you can set the type of the returned value
 *
 * @param store `IDBObjectStore` instance
 * @param key item key
 * @param value item value
 *
 * @returns Promise<IDBObjectStore>
 * @throws {Error} If it is chained off from a method that does not return an object store.
 */
function createItem(store, key, value) {
    return setItem('add', store, key, value);
}
exports.createItem = createItem;
/**
 * Update item for the provided store key
 *
 * @remarks The `updateItem` method updates the value for the key provided. You can chain assertions from this method. If you use TypeScript, you can set the type of the returned value
 *
 * @param store `IDBObjectStore` instance
 * @param key item key
 * @param value item value
 *
 * @returns Promise<IDBObjectStore>
 * @throws {Error} If it is chained off from a method that does not return an object store.
 */
function updateItem(store, key, value) {
    return setItem('update', store, key, value);
}
exports.updateItem = updateItem;
/**
 * Add item
 *
 * @remarks The `addItem` method adds the value provided to the store. You can chain assertions from this method. If you use TypeScript, you can set the type of the returned value
 * @remarks This method is only useable if the `IDBObjectStore` it is called upon is created with autoIncrement: true
 *
 * @param store `IDBObjectStore` instance
 * @param value item value
 *
 * @returns Promise<IDBObjectStore>
 * @throws {Error} If it is chained off from a method that does not return an object store.
 */
function addItem(store, value) {
    return setItem('add', store, null, value);
}
exports.addItem = addItem;
function setItem(operation, store, key, value) {
    const { log, consoleProps } = createCRUDLog(operation, key);
    consoleProps.value = value;
    if (!(0, helpers_1.isIDBObjectStore)(store)) {
        const error = new Error(`You tried to use the '${operation}Item' method without calling 'getObjectStore' first`);
        consoleProps.error = error;
        log.error(error).end();
        throw error;
    }
    return cy.wrap((0, open_database_1.createDatabaseConnection)(store.transaction.db.name)
        .then((openDb) => makeCreateUpdateDeleteRequest(key ? 'put' : 'add', openDb, store, key, value))
        .then((store) => {
        log.end();
        return store;
    })
        .catch((e) => {
        consoleProps.error = e;
        log.error(e).end();
        throw e;
    }));
}
function makeCreateUpdateDeleteRequest(operation, db, store, key, value) {
    const commandArguments = (0, helpers_1.getCommandArguments)(key, value);
    return new Promise((resolve, reject) => {
        const request = db
            .transaction(store.name, 'readwrite')
            .objectStore(store.name)
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore
        [operation](...commandArguments);
        request.onerror = (e) => {
            db.close();
            reject(e);
        };
        request.onsuccess = () => {
            request.onerror = () => void 0;
            db.close();
            const result = operation === 'get' ? request.result : store;
            resolve(result);
        };
    });
}
function createCRUDLog(operation, key) {
    const consoleProps = {
        key: key || 'no key provided',
    };
    const log = Cypress.log({
        autoEnd: false,
        type: 'child',
        name: operation,
        message: `IDBObjectStore key: ${key}`,
        consoleProps: () => consoleProps,
    });
    return { log, consoleProps };
}
//# sourceMappingURL=object-store-CRUD.js.map