/*! @azure/msal-browser v2.30.0 2022-10-10 */
'use strict';
import { __awaiter, __generator } from '../_virtual/_tslib.js';
import { BrowserAuthError } from '../error/BrowserAuthError.js';
import { DB_NAME, DB_VERSION, DB_TABLE_NAME } from '../utils/BrowserConstants.js';

/*
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License.
 */
/**
 * Storage wrapper for IndexedDB storage in browsers: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
 */
var DatabaseStorage = /** @class */ (function () {
    function DatabaseStorage() {
        this.dbName = DB_NAME;
        this.version = DB_VERSION;
        this.tableName = DB_TABLE_NAME;
        this.dbOpen = false;
    }
    /**
     * Opens IndexedDB instance.
     */
    DatabaseStorage.prototype.open = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            return __generator(this, function (_a) {
                return [2 /*return*/, new Promise(function (resolve, reject) {
                        var openDB = window.indexedDB.open(_this.dbName, _this.version);
                        openDB.addEventListener("upgradeneeded", function (e) {
                            var event = e;
                            event.target.result.createObjectStore(_this.tableName);
                        });
                        openDB.addEventListener("success", function (e) {
                            var event = e;
                            _this.db = event.target.result;
                            _this.dbOpen = true;
                            resolve();
                        });
                        openDB.addEventListener("error", function () { return reject(BrowserAuthError.createDatabaseUnavailableError()); });
                    })];
            });
        });
    };
    /**
     * Closes the connection to IndexedDB database when all pending transactions
     * complete.
     */
    DatabaseStorage.prototype.closeConnection = function () {
        var db = this.db;
        if (db && this.dbOpen) {
            db.close();
            this.dbOpen = false;
        }
    };
    /**
     * Opens database if it's not already open
     */
    DatabaseStorage.prototype.validateDbIsOpen = function () {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!!this.dbOpen) return [3 /*break*/, 2];
                        return [4 /*yield*/, this.open()];
                    case 1: return [2 /*return*/, _a.sent()];
                    case 2: return [2 /*return*/];
                }
            });
        });
    };
    /**
     * Retrieves item from IndexedDB instance.
     * @param key
     */
    DatabaseStorage.prototype.getItem = function (key) {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.validateDbIsOpen()];
                    case 1:
                        _a.sent();
                        return [2 /*return*/, new Promise(function (resolve, reject) {
                                // TODO: Add timeouts?
                                if (!_this.db) {
                                    return reject(BrowserAuthError.createDatabaseNotOpenError());
                                }
                                var transaction = _this.db.transaction([_this.tableName], "readonly");
                                var objectStore = transaction.objectStore(_this.tableName);
                                var dbGet = objectStore.get(key);
                                dbGet.addEventListener("success", function (e) {
                                    var event = e;
                                    _this.closeConnection();
                                    resolve(event.target.result);
                                });
                                dbGet.addEventListener("error", function (e) {
                                    _this.closeConnection();
                                    reject(e);
                                });
                            })];
                }
            });
        });
    };
    /**
     * Adds item to IndexedDB under given key
     * @param key
     * @param payload
     */
    DatabaseStorage.prototype.setItem = function (key, payload) {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.validateDbIsOpen()];
                    case 1:
                        _a.sent();
                        return [2 /*return*/, new Promise(function (resolve, reject) {
                                // TODO: Add timeouts?
                                if (!_this.db) {
                                    return reject(BrowserAuthError.createDatabaseNotOpenError());
                                }
                                var transaction = _this.db.transaction([_this.tableName], "readwrite");
                                var objectStore = transaction.objectStore(_this.tableName);
                                var dbPut = objectStore.put(payload, key);
                                dbPut.addEventListener("success", function () {
                                    _this.closeConnection();
                                    resolve();
                                });
                                dbPut.addEventListener("error", function (e) {
                                    _this.closeConnection();
                                    reject(e);
                                });
                            })];
                }
            });
        });
    };
    /**
     * Removes item from IndexedDB under given key
     * @param key
     */
    DatabaseStorage.prototype.removeItem = function (key) {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.validateDbIsOpen()];
                    case 1:
                        _a.sent();
                        return [2 /*return*/, new Promise(function (resolve, reject) {
                                if (!_this.db) {
                                    return reject(BrowserAuthError.createDatabaseNotOpenError());
                                }
                                var transaction = _this.db.transaction([_this.tableName], "readwrite");
                                var objectStore = transaction.objectStore(_this.tableName);
                                var dbDelete = objectStore.delete(key);
                                dbDelete.addEventListener("success", function () {
                                    _this.closeConnection();
                                    resolve();
                                });
                                dbDelete.addEventListener("error", function (e) {
                                    _this.closeConnection();
                                    reject(e);
                                });
                            })];
                }
            });
        });
    };
    /**
     * Get all the keys from the storage object as an iterable array of strings.
     */
    DatabaseStorage.prototype.getKeys = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.validateDbIsOpen()];
                    case 1:
                        _a.sent();
                        return [2 /*return*/, new Promise(function (resolve, reject) {
                                if (!_this.db) {
                                    return reject(BrowserAuthError.createDatabaseNotOpenError());
                                }
                                var transaction = _this.db.transaction([_this.tableName], "readonly");
                                var objectStore = transaction.objectStore(_this.tableName);
                                var dbGetKeys = objectStore.getAllKeys();
                                dbGetKeys.addEventListener("success", function (e) {
                                    var event = e;
                                    _this.closeConnection();
                                    resolve(event.target.result);
                                });
                                dbGetKeys.addEventListener("error", function (e) {
                                    _this.closeConnection();
                                    reject(e);
                                });
                            })];
                }
            });
        });
    };
    /**
     *
     * Checks whether there is an object under the search key in the object store
     */
    DatabaseStorage.prototype.containsKey = function (key) {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.validateDbIsOpen()];
                    case 1:
                        _a.sent();
                        return [2 /*return*/, new Promise(function (resolve, reject) {
                                if (!_this.db) {
                                    return reject(BrowserAuthError.createDatabaseNotOpenError());
                                }
                                var transaction = _this.db.transaction([_this.tableName], "readonly");
                                var objectStore = transaction.objectStore(_this.tableName);
                                var dbContainsKey = objectStore.count(key);
                                dbContainsKey.addEventListener("success", function (e) {
                                    var event = e;
                                    _this.closeConnection();
                                    resolve(event.target.result === 1);
                                });
                                dbContainsKey.addEventListener("error", function (e) {
                                    _this.closeConnection();
                                    reject(e);
                                });
                            })];
                }
            });
        });
    };
    /**
     * Deletes the MSAL database. The database is deleted rather than cleared to make it possible
     * for client applications to downgrade to a previous MSAL version without worrying about forward compatibility issues
     * with IndexedDB database versions.
     */
    DatabaseStorage.prototype.deleteDatabase = function () {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                // Check if database being deleted exists
                if (this.db && this.dbOpen) {
                    this.closeConnection();
                }
                return [2 /*return*/, new Promise(function (resolve, reject) {
                        var deleteDbRequest = window.indexedDB.deleteDatabase(DB_NAME);
                        deleteDbRequest.addEventListener("success", function () { return resolve(true); });
                        deleteDbRequest.addEventListener("blocked", function () { return resolve(true); });
                        deleteDbRequest.addEventListener("error", function () { return reject(false); });
                    })];
            });
        });
    };
    return DatabaseStorage;
}());

export { DatabaseStorage };
//# sourceMappingURL=DatabaseStorage.js.map
