UNPKG

@aws-amplify/datastore

Version:

AppSyncLocal support for aws-amplify

146 lines (143 loc) 6.37 kB
import { OpType, QueryOne } from '../../types.mjs'; import { getIndexKeys, traverseModel, keysEqual, getStorename, DEFAULT_PRIMARY_KEY_VALUE_SEPARATOR, validatePredicate, inMemoryPagination } from '../../util.mjs'; import AsyncStorageDatabase from './AsyncStorageDatabase.mjs'; import { StorageAdapterBase } from './StorageAdapterBase.mjs'; // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 class AsyncStorageAdapter extends StorageAdapterBase { async preSetUpChecks() { // no-ops for AsyncStorageAdapter } async preOpCheck() { // no-ops for AsyncStorageAdapter } /** * Open AsyncStorage database * Create new DB if one doesn't exist * * Called by `StorageAdapterBase.setUp()` * * @returns AsyncStorageDatabase instance */ async initDb() { const db = new AsyncStorageDatabase(); await db.init(); return db; } async clear() { await this.db.clear(); this.db = undefined; this.initPromise = undefined; } async batchSave(modelConstructor, items) { if (items.length === 0) { return []; } const modelName = modelConstructor.name; const namespaceName = this.namespaceResolver(modelConstructor); const storeName = getStorename(namespaceName, modelName); const keys = getIndexKeys(this.schema.namespaces[namespaceName], modelName); const batch = []; for (const item of items) { const model = this.modelInstanceCreator(modelConstructor, item); const connectedModels = traverseModel(modelName, model, this.schema.namespaces[namespaceName], this.modelInstanceCreator, this.getModelConstructorByModelName); const keyValuesPath = this.getIndexKeyValuesPath(model); const { instance } = connectedModels.find(({ instance: connectedModelInstance }) => { const instanceKeyValuesPath = this.getIndexKeyValuesPath(connectedModelInstance); return keysEqual([instanceKeyValuesPath], [keyValuesPath]); }); batch.push(instance); } return this.db.batchSave(storeName, batch, keys); } async _get(storeName, keyArr) { const itemKeyValuesPath = keyArr.join(DEFAULT_PRIMARY_KEY_VALUE_SEPARATOR); return (await this.db.get(itemKeyValuesPath, storeName)); } async save(model, condition) { const { storeName, connectionStoreNames, modelKeyValues } = this.saveMetadata(model); const fromDB = await this._get(storeName, modelKeyValues); this.validateSaveCondition(condition, fromDB); const result = []; for await (const resItem of connectionStoreNames) { const { storeName: storeNameForRestItem, item, instance, keys } = resItem; const itemKeyValues = keys.map(key => item[key]); const fromDBForRestItem = (await this._get(storeNameForRestItem, itemKeyValues)); const opType = fromDBForRestItem ? OpType.UPDATE : OpType.INSERT; if (keysEqual(itemKeyValues, modelKeyValues) || opType === OpType.INSERT) { await this.db.save(item, storeNameForRestItem, keys, itemKeyValues.join(DEFAULT_PRIMARY_KEY_VALUE_SEPARATOR)); result.push([instance, opType]); } } return result; } async query(modelConstructor, predicate, pagination) { const { storeName, namespaceName, queryByKey, predicates, hasSort, hasPagination, } = this.queryMetadata(modelConstructor, predicate, pagination); const records = (await (async () => { if (queryByKey) { const keyValues = queryByKey.join(DEFAULT_PRIMARY_KEY_VALUE_SEPARATOR); const record = await this.getByKey(storeName, keyValues); return record ? [record] : []; } if (predicates) { const filtered = await this.filterOnPredicate(storeName, predicates); return this.inMemoryPagination(filtered, pagination); } if (hasSort || hasPagination) { const all = await this.getAll(storeName); return this.inMemoryPagination(all, pagination); } return this.getAll(storeName); })()); return this.load(namespaceName, modelConstructor.name, records); } async getByKey(storeName, keyValuePath) { return (await this.db.get(keyValuePath, storeName)); } async getAll(storeName) { return this.db.getAll(storeName); } async filterOnPredicate(storeName, predicates) { const { predicates: predicateObjs, type } = predicates; const all = (await this.getAll(storeName)); const filtered = predicateObjs ? all.filter(m => validatePredicate(m, type, predicateObjs)) : all; return filtered; } inMemoryPagination(records, pagination) { return inMemoryPagination(records, pagination); } async queryOne(modelConstructor, firstOrLast = QueryOne.FIRST) { const storeName = this.getStorenameForModel(modelConstructor); const result = (await this.db.getOne(firstOrLast, storeName)); return result && this.modelInstanceCreator(modelConstructor, result); } async deleteItem(deleteQueue) { for await (const deleteItem of deleteQueue) { const { storeName, items } = deleteItem; for await (const item of items) { if (item) { if (typeof item === 'object') { const keyValuesPath = this.getIndexKeyValuesPath(item); await this.db.delete(keyValuesPath, storeName); } } } } } // #region platform-specific helper methods /** * Retrieves concatenated primary key values from a model * * @param model * @returns */ getIndexKeyValuesPath(model) { return this.getIndexKeyValuesFromModel(model).join(DEFAULT_PRIMARY_KEY_VALUE_SEPARATOR); } } var AsyncStorageAdapter$1 = new AsyncStorageAdapter(); export { AsyncStorageAdapter, AsyncStorageAdapter$1 as default }; //# sourceMappingURL=AsyncStorageAdapter.mjs.map