UNPKG

@aws-amplify/datastore

Version:

AppSyncLocal support for aws-amplify

1 lines • 42.5 kB
{"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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"}