{"version":3,"file":"IndexedDBAdapter.mjs","sources":["../../../../src/storage/adapter/IndexedDBAdapter.ts"],"sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport * as idb from 'idb';\nimport { ConsoleLogger } from '@aws-amplify/core';\nimport { OpType, QueryOne, isPredicateGroup, isPredicateObj, } from '../../types';\nimport { getStorename, inMemoryPagination, isPrivateMode, isSafariCompatabilityMode, keysEqual, traverseModel, validatePredicate, } from '../../util';\nimport { StorageAdapterBase } from './StorageAdapterBase';\nconst logger = new ConsoleLogger('DataStore');\n/**\n * The point after which queries composed of multiple simple OR conditions\n * should scan-and-filter instead of individual queries for each condition.\n *\n * At some point, this should be configurable and/or dynamic based on table\n * size and possibly even on observed average seek latency. For now, it's\n * based on an manual \"binary search\" for the breakpoint as measured in the\n * unit test suite. This isn't necessarily optimal. But, it's at least derived\n * empirically, rather than theoretically and without any verification!\n *\n * REMEMBER! If you run more realistic benchmarks and update this value, update\n * this comment so the validity and accuracy of future query tuning exercises\n * can be compared to the methods used to derive the current value. E.g.,\n *\n * 1. In browser benchmark > unit test benchmark\n * 2. Multi-browser benchmark > single browser benchmark\n * 3. Benchmarks of various table sizes > static table size benchmark\n *\n * etc...\n *\n */\nconst MULTI_OR_CONDITION_SCAN_BREAKPOINT = 7;\n//\nconst DB_VERSION = 3;\nclass IndexedDBAdapter extends StorageAdapterBase {\n    constructor() {\n        super(...arguments);\n        this.safariCompatabilityMode = false;\n        /**\n         * Checks the given path against the browser's IndexedDB implementation for\n         * necessary compatibility transformations, applying those transforms if needed.\n         *\n         * @param `keyArr` strings to compatibilize for browser-indexeddb index operations\n         * @returns An array or string, depending on and given key,\n         * that is ensured to be compatible with the IndexedDB implementation's nuances.\n         */\n        this.canonicalKeyPath = (keyArr) => {\n            if (this.safariCompatabilityMode) {\n                return keyArr.length > 1 ? keyArr : keyArr[0];\n            }\n            return keyArr;\n        };\n        // #endregion\n    }\n    // checks are called by StorageAdapterBase class\n    async preSetUpChecks() {\n        await this.checkPrivate();\n        await this.setSafariCompatabilityMode();\n    }\n    async preOpCheck() {\n        await this.checkPrivate();\n    }\n    /**\n     * Initialize IndexedDB database\n     * Create new DB if one doesn't exist\n     * Upgrade outdated DB\n     *\n     * Called by `StorageAdapterBase.setUp()`\n     *\n     * @returns IDB Database instance\n     */\n    async initDb() {\n        return idb.openDB(this.dbName, DB_VERSION, {\n            upgrade: async (db, oldVersion, newVersion, txn) => {\n                // create new database\n                if (oldVersion === 0) {\n                    Object.keys(this.schema.namespaces).forEach(namespaceName => {\n                        const namespace = this.schema.namespaces[namespaceName];\n                        Object.keys(namespace.models).forEach(modelName => {\n                            const storeName = getStorename(namespaceName, modelName);\n                            this.createObjectStoreForModel(db, namespaceName, storeName, modelName);\n                        });\n                    });\n                    return;\n                }\n                // migrate existing database to latest schema\n                if ((oldVersion === 1 || oldVersion === 2) && newVersion === 3) {\n                    try {\n                        for (const storeName of txn.objectStoreNames) {\n                            const origStore = txn.objectStore(storeName);\n                            // rename original store\n                            const tmpName = `tmp_${storeName}`;\n                            origStore.name = tmpName;\n                            const { namespaceName, modelName } = this.getNamespaceAndModelFromStorename(storeName);\n                            const modelInCurrentSchema = modelName in this.schema.namespaces[namespaceName].models;\n                            if (!modelInCurrentSchema) {\n                                // delete original\n                                db.deleteObjectStore(tmpName);\n                                continue;\n                            }\n                            const newStore = this.createObjectStoreForModel(db, namespaceName, storeName, modelName);\n                            let cursor = await origStore.openCursor();\n                            let count = 0;\n                            // Copy data from original to new\n                            while (cursor && cursor.value) {\n                                // we don't pass key, since they are all new entries in the new store\n                                await newStore.put(cursor.value);\n                                cursor = await cursor.continue();\n                                count++;\n                            }\n                            // delete original\n                            db.deleteObjectStore(tmpName);\n                            logger.debug(`${count} ${storeName} records migrated`);\n                        }\n                        // add new models created after IndexedDB, but before migration\n                        // this case may happen when a user has not opened an app for\n                        // some time and a new model is added during that time\n                        Object.keys(this.schema.namespaces).forEach(namespaceName => {\n                            const namespace = this.schema.namespaces[namespaceName];\n                            const objectStoreNames = new Set(txn.objectStoreNames);\n                            Object.keys(namespace.models)\n                                .map(modelName => {\n                                return [modelName, getStorename(namespaceName, modelName)];\n                            })\n                                .filter(([, storeName]) => !objectStoreNames.has(storeName))\n                                .forEach(([modelName, storeName]) => {\n                                this.createObjectStoreForModel(db, namespaceName, storeName, modelName);\n                            });\n                        });\n                    }\n                    catch (error) {\n                        logger.error('Error migrating IndexedDB data', error);\n                        txn.abort();\n                        throw error;\n                    }\n                }\n            },\n        });\n    }\n    async _get(storeOrStoreName, keyArr) {\n        let index;\n        if (typeof storeOrStoreName === 'string') {\n            const storeName = storeOrStoreName;\n            index = this.db.transaction(storeName, 'readonly').store.index('byPk');\n        }\n        else {\n            const store = storeOrStoreName;\n            index = store.index('byPk');\n        }\n        const result = await index.get(this.canonicalKeyPath(keyArr));\n        return result;\n    }\n    async clear() {\n        await this.checkPrivate();\n        this.db?.close();\n        await idb.deleteDB(this.dbName);\n        this.db = undefined;\n        this.initPromise = undefined;\n    }\n    async save(model, condition) {\n        await this.checkPrivate();\n        const { storeName, set, connectionStoreNames, modelKeyValues } = this.saveMetadata(model);\n        const tx = this.db.transaction([storeName, ...Array.from(set.values())], 'readwrite');\n        const store = tx.objectStore(storeName);\n        const fromDB = await this._get(store, modelKeyValues);\n        this.validateSaveCondition(condition, fromDB);\n        const result = [];\n        for await (const resItem of connectionStoreNames) {\n            const { storeName: storeNameForRestItem, item, instance, keys } = resItem;\n            const storeForRestItem = tx.objectStore(storeNameForRestItem);\n            const itemKeyValues = keys.map(key => item[key]);\n            const fromDBForRestItem = (await this._get(storeForRestItem, itemKeyValues));\n            const opType = fromDBForRestItem ? OpType.UPDATE : OpType.INSERT;\n            if (keysEqual(itemKeyValues, modelKeyValues) ||\n                opType === OpType.INSERT) {\n                const key = await storeForRestItem\n                    .index('byPk')\n                    .getKey(this.canonicalKeyPath(itemKeyValues));\n                await storeForRestItem.put(item, key);\n                result.push([instance, opType]);\n            }\n        }\n        await tx.done;\n        return result;\n    }\n    async query(modelConstructor, predicate, pagination) {\n        await this.checkPrivate();\n        const { storeName, namespaceName, queryByKey, predicates, hasSort, hasPagination, } = this.queryMetadata(modelConstructor, predicate, pagination);\n        const records = (await (async () => {\n            //\n            // NOTE: @svidgen explored removing this and letting query() take care of automatic\n            // index leveraging. This would eliminate some amount of very similar code.\n            // But, getAll is slightly slower than get()\n            //\n            // On Chrome:\n            //   ~700ms vs ~1175ms per 10k reads.\n            //\n            // You can (and should) check my work here:\n            // \thttps://gist.github.com/svidgen/74e55d573b19c3e5432b1b5bdf0f4d96\n            //\n            if (queryByKey) {\n                const record = await this.getByKey(storeName, queryByKey);\n                return record ? [record] : [];\n            }\n            if (predicates) {\n                const filtered = await this.filterOnPredicate(storeName, predicates);\n                return this.inMemoryPagination(filtered, pagination);\n            }\n            if (hasSort) {\n                const all = await this.getAll(storeName);\n                return this.inMemoryPagination(all, pagination);\n            }\n            if (hasPagination) {\n                return this.enginePagination(storeName, pagination);\n            }\n            return this.getAll(storeName);\n        })());\n        return this.load(namespaceName, modelConstructor.name, records);\n    }\n    async queryOne(modelConstructor, firstOrLast = QueryOne.FIRST) {\n        await this.checkPrivate();\n        const storeName = this.getStorenameForModel(modelConstructor);\n        const cursor = await this.db\n            .transaction([storeName], 'readonly')\n            .objectStore(storeName)\n            .openCursor(undefined, firstOrLast === QueryOne.FIRST ? 'next' : 'prev');\n        const result = cursor ? cursor.value : undefined;\n        return result && this.modelInstanceCreator(modelConstructor, result);\n    }\n    async batchSave(modelConstructor, items) {\n        await this.checkPrivate();\n        if (items.length === 0) {\n            return [];\n        }\n        const modelName = modelConstructor.name;\n        const namespaceName = this.namespaceResolver(modelConstructor);\n        const storeName = this.getStorenameForModel(modelConstructor);\n        const result = [];\n        const txn = this.db.transaction(storeName, 'readwrite');\n        const { store } = txn;\n        for (const item of items) {\n            const model = this.modelInstanceCreator(modelConstructor, item);\n            const connectedModels = traverseModel(modelName, model, this.schema.namespaces[namespaceName], this.modelInstanceCreator, this.getModelConstructorByModelName);\n            const keyValues = this.getIndexKeyValuesFromModel(model);\n            const { _deleted } = item;\n            const index = store.index('byPk');\n            const key = await index.getKey(this.canonicalKeyPath(keyValues));\n            if (!_deleted) {\n                const { instance } = connectedModels.find(({ instance: connectedModelInstance }) => {\n                    const instanceKeyValues = this.getIndexKeyValuesFromModel(connectedModelInstance);\n                    return keysEqual(instanceKeyValues, keyValues);\n                });\n                result.push([\n                    instance,\n                    key ? OpType.UPDATE : OpType.INSERT,\n                ]);\n                await store.put(instance, key);\n            }\n            else {\n                result.push([item, OpType.DELETE]);\n                if (key) {\n                    await store.delete(key);\n                }\n            }\n        }\n        await txn.done;\n        return result;\n    }\n    async deleteItem(deleteQueue) {\n        const connectionStoreNames = deleteQueue.map(({ storeName }) => {\n            return storeName;\n        });\n        const tx = this.db.transaction([...connectionStoreNames], 'readwrite');\n        for await (const deleteItem of deleteQueue) {\n            const { storeName, items } = deleteItem;\n            const store = tx.objectStore(storeName);\n            for await (const item of items) {\n                if (item) {\n                    let key;\n                    if (typeof item === 'object') {\n                        const keyValues = this.getIndexKeyValuesFromModel(item);\n                        key = await store\n                            .index('byPk')\n                            .getKey(this.canonicalKeyPath(keyValues));\n                    }\n                    else {\n                        const itemKey = item.toString();\n                        key = await store.index('byPk').getKey(itemKey);\n                    }\n                    if (key !== undefined) {\n                        await store.delete(key);\n                    }\n                }\n            }\n        }\n    }\n    // #region platform-specific helper methods\n    async checkPrivate() {\n        const isPrivate = await isPrivateMode();\n        if (isPrivate) {\n            logger.error(\"IndexedDB not supported in this browser's private mode\");\n            // eslint-disable-next-line prefer-promise-reject-errors\n            return Promise.reject(\"IndexedDB not supported in this browser's private mode\");\n        }\n        else {\n            return Promise.resolve();\n        }\n    }\n    /**\n     * Whether the browser's implementation of IndexedDB is coercing single-field\n     * indexes to a scalar key.\n     *\n     * If this returns `true`, we need to treat indexes containing a single field\n     * as scalars.\n     *\n     * See PR description for reference:\n     * https://github.com/aws-amplify/amplify-js/pull/10527\n     */\n    async setSafariCompatabilityMode() {\n        this.safariCompatabilityMode = await isSafariCompatabilityMode();\n        if (this.safariCompatabilityMode === true) {\n            logger.debug('IndexedDB Adapter is running in Safari Compatability Mode');\n        }\n    }\n    getNamespaceAndModelFromStorename(storeName) {\n        const [namespaceName, ...modelNameArr] = storeName.split('_');\n        return {\n            namespaceName,\n            modelName: modelNameArr.join('_'),\n        };\n    }\n    createObjectStoreForModel(db, namespaceName, storeName, modelName) {\n        const store = db.createObjectStore(storeName, {\n            autoIncrement: true,\n        });\n        const { indexes } = this.schema.namespaces[namespaceName].relationships[modelName];\n        indexes.forEach(([idxName, keyPath, options]) => {\n            store.createIndex(idxName, keyPath, options);\n        });\n        return store;\n    }\n    async getByKey(storeName, keyValue) {\n        return (await this._get(storeName, keyValue));\n    }\n    async getAll(storeName) {\n        return this.db.getAll(storeName);\n    }\n    /**\n     * Tries to generate an index fetcher for the given predicates. Assumes\n     * that the given predicate conditions are contained by an AND group and\n     * should therefore all match a single record.\n     *\n     * @param storeName The table to query.\n     * @param predicates The predicates to try to AND together.\n     * @param transaction\n     */\n    matchingIndexQueries(storeName, predicates, transaction) {\n        // could be expanded later to include `exec()` and a `cardinality` estimate?\n        const queries = [];\n        const predicateIndex = new Map();\n        for (const predicate of predicates) {\n            predicateIndex.set(String(predicate.field), predicate);\n        }\n        const store = transaction.objectStore(storeName);\n        for (const name of store.indexNames) {\n            const idx = store.index(name);\n            const keypath = Array.isArray(idx.keyPath) ? idx.keyPath : [idx.keyPath];\n            const matchingPredicateValues = [];\n            for (const field of keypath) {\n                const p = predicateIndex.get(field);\n                if (p && p.operand !== null && p.operand !== undefined) {\n                    matchingPredicateValues.push(p.operand);\n                }\n                else {\n                    break;\n                }\n            }\n            // if we have a matching predicate field for each component of this index,\n            // we can build a query for it. otherwise, we can't.\n            if (matchingPredicateValues.length === keypath.length) {\n                // re-create a transaction, because the transaction used to fetch the\n                // indexes may no longer be active.\n                queries.push(() => this.db\n                    .transaction(storeName)\n                    .objectStore(storeName)\n                    .index(name)\n                    .getAll(this.canonicalKeyPath(matchingPredicateValues)));\n            }\n        }\n        return queries;\n    }\n    async baseQueryIndex(storeName, predicates, transaction) {\n        let { predicates: predicateObjs, type } = predicates;\n        // the predicate objects we care about tend to be nested at least\n        // one level down: `{and: {or: {and: { <the predicates we want> }}}}`\n        // so, we unpack and/or groups until we find a group with more than 1\n        // child OR a child that is not a group (and is therefore a predicate \"object\").\n        while (predicateObjs.length === 1 &&\n            isPredicateGroup(predicateObjs[0]) &&\n            predicateObjs[0].type !== 'not') {\n            ({ type } = predicateObjs[0]);\n            predicateObjs = predicateObjs[0].predicates;\n        }\n        const fieldPredicates = predicateObjs.filter(p => isPredicateObj(p) && p.operator === 'eq');\n        // several sub-queries could occur here. explicitly start a txn here to avoid\n        // opening/closing multiple txns.\n        const txn = transaction || this.db.transaction(storeName);\n        let result = {};\n        // `or` conditions, if usable, need to generate multiple queries. this is unlike\n        // `and` conditions, which should just be combined.\n        if (type === 'or') {\n            /**\n             * Base queries for each child group.\n             *\n             * For each child group, if it's an AND condition that results in a single\n             * subordinate \"base query\", we can use it. if it's any more complicated\n             * than that, it's not a simple join condition we want to use.\n             */\n            const groupQueries = await Promise.all(predicateObjs\n                .filter(o => isPredicateGroup(o) && o.type === 'and')\n                .map(o => this.baseQueryIndex(storeName, o, txn))).then(queries => queries\n                .filter(q => q.indexedQueries.length === 1)\n                .map(i => i.indexedQueries));\n            /**\n             * Base queries for each simple child \"object\" (field condition).\n             */\n            const objectQueries = predicateObjs\n                .filter(o => isPredicateObj(o))\n                .map(o => this.matchingIndexQueries(storeName, [o], txn));\n            const indexedQueries = [...groupQueries, ...objectQueries]\n                .map(q => q[0])\n                .filter(i => i);\n            // if, after hunting for base queries, we don't have exactly 1 base query\n            // for each child group + object, stop trying to optimize. we're not dealing\n            // with a simple query that fits the intended optimization path.\n            if (predicateObjs.length > indexedQueries.length) {\n                result = {\n                    groupType: null,\n                    indexedQueries: [],\n                };\n            }\n            else {\n                result = {\n                    groupType: 'or',\n                    indexedQueries,\n                };\n            }\n        }\n        else if (type === 'and') {\n            // our potential indexes or lacks thereof.\n            // note that we're only optimizing for `eq` right now.\n            result = {\n                groupType: type,\n                indexedQueries: this.matchingIndexQueries(storeName, fieldPredicates, txn),\n            };\n        }\n        else {\n            result = {\n                groupType: null,\n                indexedQueries: [],\n            };\n        }\n        // Explicitly wait for txns from index queries to complete before proceding.\n        // This helps ensure IndexedDB is in a stable, ready state. Else, subseqeuent\n        // qeuries can sometimes appear to deadlock (at least in FakeIndexedDB).\n        // (Unless we were *given* the transaction -- we'll assume the parent handles it.)\n        if (!transaction)\n            await txn.done;\n        return result;\n    }\n    async filterOnPredicate(storeName, predicates) {\n        const { predicates: predicateObjs, type } = predicates;\n        const { groupType, indexedQueries } = await this.baseQueryIndex(storeName, predicates);\n        // where we'll accumulate candidate results, which will be filtered at the end.\n        let candidateResults;\n        // semi-naive implementation:\n        if (groupType === 'and' && indexedQueries.length > 0) {\n            // each condition must be satsified, we can form a base set with any\n            // ONE of those conditions and then filter.\n            candidateResults = await indexedQueries[0]();\n        }\n        else if (groupType === 'or' &&\n            indexedQueries.length > 0 &&\n            indexedQueries.length <= MULTI_OR_CONDITION_SCAN_BREAKPOINT) {\n            // NOTE: each condition implies a potentially distinct set. we only benefit\n            // from using indexes here if EVERY condition uses an index. if any one\n            // index requires a table scan, we gain nothing from the indexes.\n            // NOTE: results must be DISTINCT-ified if we leverage indexes.\n            const distinctResults = new Map();\n            for (const query of indexedQueries) {\n                const resultGroup = await query();\n                for (const item of resultGroup) {\n                    const distinctificationString = JSON.stringify(item);\n                    distinctResults.set(distinctificationString, item);\n                }\n            }\n            // we could conceivably check for special conditions and return early here.\n            // but, this is simpler and has not yet had a measurable performance impact.\n            candidateResults = Array.from(distinctResults.values());\n        }\n        else {\n            // nothing intelligent we can do with `not` groups unless or until we start\n            // smashing comparison operators against indexes -- at which point we could\n            // perform some reversal here.\n            candidateResults = (await this.getAll(storeName));\n        }\n        const filtered = predicateObjs\n            ? candidateResults.filter(m => validatePredicate(m, type, predicateObjs))\n            : candidateResults;\n        return filtered;\n    }\n    inMemoryPagination(records, pagination) {\n        return inMemoryPagination(records, pagination);\n    }\n    async enginePagination(storeName, pagination) {\n        let result;\n        if (pagination) {\n            const { page = 0, limit = 0 } = pagination;\n            const initialRecord = Math.max(0, page * limit) || 0;\n            let cursor = await this.db\n                .transaction(storeName)\n                .objectStore(storeName)\n                .openCursor();\n            if (cursor && initialRecord > 0) {\n                await cursor.advance(initialRecord);\n            }\n            const pageResults = [];\n            const hasLimit = typeof limit === 'number' && limit > 0;\n            while (cursor && cursor.value) {\n                pageResults.push(cursor.value);\n                if (hasLimit && pageResults.length === limit) {\n                    break;\n                }\n                cursor = await cursor.continue();\n            }\n            result = pageResults;\n        }\n        else {\n            result = (await this.db.getAll(storeName));\n        }\n        return result;\n    }\n}\nexport default new IndexedDBAdapter();\n"],"names":[],"mappings":"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"}