@aws-amplify/datastore
Version:
AppSyncLocal support for aws-amplify
149 lines (147 loc) • 6.56 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsyncStorageAdapter = void 0;
const tslib_1 = require("tslib");
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
const types_1 = require("../../types");
const util_1 = require("../../util");
const AsyncStorageDatabase_1 = tslib_1.__importDefault(require("./AsyncStorageDatabase"));
const StorageAdapterBase_1 = require("./StorageAdapterBase");
class AsyncStorageAdapter extends StorageAdapterBase_1.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_1.default();
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 = (0, util_1.getStorename)(namespaceName, modelName);
const keys = (0, util_1.getIndexKeys)(this.schema.namespaces[namespaceName], modelName);
const batch = [];
for (const item of items) {
const model = this.modelInstanceCreator(modelConstructor, item);
const connectedModels = (0, util_1.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 (0, util_1.keysEqual)([instanceKeyValuesPath], [keyValuesPath]);
});
batch.push(instance);
}
return this.db.batchSave(storeName, batch, keys);
}
async _get(storeName, keyArr) {
const itemKeyValuesPath = keyArr.join(util_1.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 ? types_1.OpType.UPDATE : types_1.OpType.INSERT;
if ((0, util_1.keysEqual)(itemKeyValues, modelKeyValues) ||
opType === types_1.OpType.INSERT) {
await this.db.save(item, storeNameForRestItem, keys, itemKeyValues.join(util_1.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(util_1.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 => (0, util_1.validatePredicate)(m, type, predicateObjs))
: all;
return filtered;
}
inMemoryPagination(records, pagination) {
return (0, util_1.inMemoryPagination)(records, pagination);
}
async queryOne(modelConstructor, firstOrLast = types_1.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(util_1.DEFAULT_PRIMARY_KEY_VALUE_SEPARATOR);
}
}
exports.AsyncStorageAdapter = AsyncStorageAdapter;
exports.default = new AsyncStorageAdapter();
//# sourceMappingURL=AsyncStorageAdapter.js.map