From 99dbe4c75e491f579e717f8bf17ea4325b0e8058 Mon Sep 17 00:00:00 2001 From: Ashish Nanda Date: Tue, 11 Feb 2020 20:48:00 -0800 Subject: [PATCH 01/25] Adding database abstraction for AsyncStorage --- .../storage/adapter/AsyncStorageDatabase.ts | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 packages/datastore/src/storage/adapter/AsyncStorageDatabase.ts diff --git a/packages/datastore/src/storage/adapter/AsyncStorageDatabase.ts b/packages/datastore/src/storage/adapter/AsyncStorageDatabase.ts new file mode 100644 index 00000000000..e8a67ec1f9f --- /dev/null +++ b/packages/datastore/src/storage/adapter/AsyncStorageDatabase.ts @@ -0,0 +1,97 @@ +import { AsyncStorage } from 'react-native'; +import { PersistentModel, QueryOne } from '../../types'; + +const DB_NAME = '@AmplifyDatastore'; +const COLLECTION = 'Collection'; +const DATA = 'Data'; + +// write a function for getCollectionForStore. +// handle errors. +// write batch save/ transactional save. +class AsyncStorageDatabase { + async save(item: T, storeName: string) { + const itemKey = this.getKeyForItem(storeName, item.id); + await AsyncStorage.setItem(itemKey, JSON.stringify(item)); + const storeKey = this.getKeyForStore(storeName); + const collectionForStoreAsString = await AsyncStorage.getItem(storeKey); + const collectionForStore = JSON.parse(collectionForStoreAsString); + const collection = collectionForStore || []; + collection.push(itemKey); + await AsyncStorage.setItem(storeKey, JSON.stringify(collection)); + } + + async get( + id: string, + storeName: string + ): Promise { + const itemKey = this.getKeyForItem(storeName, id); + const recordAsString = await AsyncStorage.getItem(itemKey); + const record = JSON.parse(recordAsString); + return record; + } + + async getOne(firstOrLast: QueryOne, storeName: string) { + const storeKey = this.getKeyForStore(storeName); + const collectionForStoreAsString = await AsyncStorage.getItem(storeKey); + const collectionForStore = JSON.parse(collectionForStoreAsString); + const collection = collectionForStore || []; + const itemKey = + firstOrLast === QueryOne.FIRST + ? collection[0] + : collection[collection.length - 1]; + const result = itemKey + ? JSON.parse(await AsyncStorage.getItem(itemKey)) + : undefined; + return result; + } + + /** + * This function gets all the records stored in async storage for a particular storeName + * It uses getAllKeys to first retrieve the keys and then filters based on the prefix + * It then loads all the records for that filtered set of keys using multiGet() + */ + async getAll(storeName: string): Promise { + const allKeys = await AsyncStorage.getAllKeys(); + const prefixForStoreItems = this.getKeyPrefixForStoreItems(storeName); + const keysForStore = allKeys.filter(key => + key.startsWith(prefixForStoreItems) + ); + const storeRecordStrings = await AsyncStorage.multiGet(keysForStore); + const records = storeRecordStrings.map(([key, value]) => JSON.parse(value)); + return records; + } + + async delete(id: string, storeName: string) { + const itemKey = this.getKeyForItem(storeName, id); + const storeKey = this.getKeyForStore(storeName); + const collectionForStoreAsString = await AsyncStorage.getItem(storeKey); + const collectionForStore = JSON.parse(collectionForStoreAsString); + const collection = collectionForStore || []; + collection.splice(collection.indexOf(itemKey), 1); + await AsyncStorage.setItem(storeKey, JSON.stringify(collection)); + await AsyncStorage.removeItem(itemKey); + } + /** + * Clear the AsyncStorage of all DataStore entries + */ + async clear() { + const allKeys = await AsyncStorage.getAllKeys(); + const allDataStoreKeys = allKeys.filter(key => key.startsWith(DB_NAME)); + await AsyncStorage.multiRemove(allDataStoreKeys); + } + + // Can ID not be a string? + private getKeyForItem(storeName: string, id: string): string { + return `${DB_NAME}::${storeName}::${DATA}::${id}`; + } + + private getKeyForStore(storeName: string): string { + return `${DB_NAME}::${storeName}::${COLLECTION}`; + } + + private getKeyPrefixForStoreItems(storeName: string): string { + return `${DB_NAME}::${storeName}::${DATA}`; + } +} + +export default new AsyncStorageDatabase(); From 9e48b187d7609968187b62883f43628b93245eb0 Mon Sep 17 00:00:00 2001 From: Ashish Nanda Date: Tue, 11 Feb 2020 20:51:56 -0800 Subject: [PATCH 02/25] Add storage adapter for React Native using AsyncStorage --- .../src/storage/adapter/asyncstorage.ts | 524 ++++++++++++++++++ 1 file changed, 524 insertions(+) create mode 100644 packages/datastore/src/storage/adapter/asyncstorage.ts diff --git a/packages/datastore/src/storage/adapter/asyncstorage.ts b/packages/datastore/src/storage/adapter/asyncstorage.ts new file mode 100644 index 00000000000..274f365d894 --- /dev/null +++ b/packages/datastore/src/storage/adapter/asyncstorage.ts @@ -0,0 +1,524 @@ +import { ConsoleLogger as Logger } from '@aws-amplify/core'; +import { AsyncStorage } from 'react-native'; +import AsyncStorageDatabase from './AsyncStorageDatabase'; +import { Adapter } from '.'; +import { ModelInstanceCreator } from '../../datastore/datastore'; +import { ModelPredicateCreator } from '../../predicates'; +import { + InternalSchema, + isPredicateObj, + ModelPredicate, + NamespaceResolver, + OpType, + PersistentModel, + PersistentModelConstructor, + PredicateObject, + QueryOne, + RelationType, + PaginationInput, +} from '../../types'; +import { + exhaustiveCheck, + getIndex, + isModelConstructor, + traverseModel, + validatePredicate, +} from '../../util'; + +const logger = new Logger('DataStore'); + +class AsyncStorageAdapter implements Adapter { + private schema: InternalSchema; + private namespaceResolver: NamespaceResolver; + private modelInstanceCreator: ModelInstanceCreator; + private getModelConstructorByModelName: ( + namsespaceName: string, + modelName: string + ) => PersistentModelConstructor; + private db: any; + private initPromise: Promise; + private resolve: (value?: any) => void; + private reject: (value?: any) => void; + + private getStorenameForModel( + modelConstructor: PersistentModelConstructor + ) { + const namespace = this.namespaceResolver(modelConstructor); + const { name: modelName } = modelConstructor; + + return this.getStorename(namespace, modelName); + } + + private getStorename(namespace: string, modelName: string) { + const storeName = `${namespace}_${modelName}`; + + return storeName; + } + + async setUp( + theSchema: InternalSchema, + namespaceResolver: NamespaceResolver, + modelInstanceCreator: ModelInstanceCreator, + getModelConstructorByModelName: ( + namsespaceName: string, + modelName: string + ) => PersistentModelConstructor + ) { + if (!this.initPromise) { + this.initPromise = new Promise((res, rej) => { + this.resolve = res; + this.reject = rej; + }); + } else { + await this.initPromise; + } + this.schema = theSchema; + this.namespaceResolver = namespaceResolver; + this.modelInstanceCreator = modelInstanceCreator; + this.getModelConstructorByModelName = getModelConstructorByModelName; + try { + if (!this.db) { + this.db = AsyncStorageDatabase; + this.resolve(); + } + } catch (error) { + this.reject(error); + } + } + + async save( + model: T, + condition?: ModelPredicate + ): Promise<[T, OpType.INSERT | OpType.UPDATE][]> { + const modelConstructor = Object.getPrototypeOf(model) + .constructor as PersistentModelConstructor; + const storeName = this.getStorenameForModel(modelConstructor); + const connectedModels = traverseModel( + modelConstructor.name, + model, + this.schema.namespaces[this.namespaceResolver(modelConstructor)], + this.modelInstanceCreator, + this.getModelConstructorByModelName + ); + const namespaceName = this.namespaceResolver(modelConstructor); + const set = new Set(); + const connectionStoreNames = Object.values(connectedModels).map( + ({ modelName, item, instance }) => { + const storeName = this.getStorename(namespaceName, modelName); + set.add(storeName); + return { storeName, item, instance }; + } + ); + const fromDB = await AsyncStorageDatabase.get(model.id, storeName); + + if (condition) { + const predicates = ModelPredicateCreator.getPredicates(condition); + const { predicates: predicateObjs, type } = predicates; + + const isValid = validatePredicate(fromDB, type, predicateObjs); + + if (!isValid) { + const msg = 'Conditional update failed'; + logger.error(msg, { model: fromDB, condition: predicateObjs }); + + throw new Error(msg); + } + } + + const result: [T, OpType.INSERT | OpType.UPDATE][] = []; + + for await (const resItem of connectionStoreNames) { + const { storeName, item, instance } = resItem; + + const { id } = item; + + const opType: OpType = (await AsyncStorageDatabase.get(id, storeName)) + ? OpType.UPDATE + : OpType.INSERT; + + if (id === model.id) { + await AsyncStorageDatabase.save(item, storeName); + + result.push([instance, opType]); + } else { + if (opType === OpType.INSERT) { + await AsyncStorageDatabase.save(item, storeName); + + result.push([instance, opType]); + } + } + const savedItem = await AsyncStorageDatabase.get(id, storeName); + } + + return result; + } + + private async load( + namespaceName: string, + srcModelName: string, + records: T[] + ): Promise { + const namespace = this.schema.namespaces[namespaceName]; + const relations = namespace.relationships[srcModelName].relationTypes; + const connectionStoreNames = relations.map(({ modelName }) => { + return this.getStorename(namespaceName, modelName); + }); + const modelConstructor = this.getModelConstructorByModelName( + namespaceName, + srcModelName + ); + + if (connectionStoreNames.length === 0) { + return records.map(record => + this.modelInstanceCreator(modelConstructor, record) + ); + } + + for await (const relation of relations) { + const { fieldName, modelName, targetName, relationType } = relation; + const storeName = this.getStorename(namespaceName, modelName); + const modelConstructor = this.getModelConstructorByModelName( + namespaceName, + modelName + ); + + switch (relationType) { + case 'HAS_ONE': + for await (const recordItem of records) { + if (recordItem[fieldName]) { + const connectionRecord = await AsyncStorageDatabase.get( + recordItem[fieldName], + storeName + ); + + recordItem[fieldName] = + connectionRecord && + this.modelInstanceCreator(modelConstructor, connectionRecord); + } + } + + break; + case 'BELONGS_TO': + for await (const recordItem of records) { + if (recordItem[targetName]) { + const connectionRecord = await AsyncStorageDatabase.get( + recordItem[targetName], + storeName + ); + + recordItem[fieldName] = + connectionRecord && + this.modelInstanceCreator(modelConstructor, connectionRecord); + delete recordItem[targetName]; + } + } + + break; + case 'HAS_MANY': + // TODO: Lazy loading + break; + default: + exhaustiveCheck(relationType); + break; + } + } + + return records.map(record => + this.modelInstanceCreator(modelConstructor, record) + ); + } + + async query( + modelConstructor: PersistentModelConstructor, + predicate?: ModelPredicate, + pagination?: PaginationInput + ): Promise { + const storeName = this.getStorenameForModel(modelConstructor); + const namespaceName = this.namespaceResolver(modelConstructor); + + if (predicate) { + const predicates = ModelPredicateCreator.getPredicates(predicate); + if (predicates) { + const { predicates: predicateObjs, type } = predicates; + const idPredicate = + predicateObjs.length === 1 && + (predicateObjs.find( + p => isPredicateObj(p) && p.field === 'id' && p.operator === 'eq' + ) as PredicateObject); + + if (idPredicate) { + const { operand: id } = idPredicate; + + const record = await AsyncStorageDatabase.get(id, storeName); + + if (record) { + const [x] = await this.load(namespaceName, modelConstructor.name, [ + record, + ]); + return [x]; + } + return []; + } + + const all = await AsyncStorageDatabase.getAll(storeName); + + const filtered = predicateObjs + ? all.filter(m => validatePredicate(m, type, predicateObjs)) + : all; + + return await this.load( + namespaceName, + modelConstructor.name, + this.inMemoryPagination(filtered, pagination) + ); + } + } + const all = await AsyncStorageDatabase.getAll(storeName); + + return await this.load( + namespaceName, + modelConstructor.name, + this.inMemoryPagination(all, pagination) + ); + } + + private inMemoryPagination( + records: T[], + pagination?: PaginationInput + ): T[] { + if (pagination) { + const { page = 0, limit = 0 } = pagination; + const start = Math.max(0, page * limit) || 0; + + const end = limit > 0 ? start + limit : records.length; + + return records.slice(start, end); + } + + return records; + } + + async queryOne( + modelConstructor: PersistentModelConstructor, + firstOrLast: QueryOne = QueryOne.FIRST + ): Promise { + const storeName = this.getStorenameForModel(modelConstructor); + const result = await AsyncStorageDatabase.getOne(firstOrLast, storeName); + return result && this.modelInstanceCreator(modelConstructor, result); + } + + async delete( + modelOrModelConstructor: T | PersistentModelConstructor, + condition?: ModelPredicate + ): Promise<[T[], T[]]> { + const deleteQueue: { storeName: string; items: T[] }[] = []; + + if (isModelConstructor(modelOrModelConstructor)) { + const modelConstructor = modelOrModelConstructor; + const nameSpace = this.namespaceResolver(modelConstructor); + + const storeName = this.getStorenameForModel(modelConstructor); + // models to be deleted. + const models = await this.query(modelConstructor, condition); + // TODO: refactor this to use a function like getRelations() + const relations = this.schema.namespaces[nameSpace].relationships[ + modelConstructor.name + ].relationTypes; + + if (condition !== undefined) { + await this.deleteTraverse( + relations, + models, + modelConstructor.name, + nameSpace, + deleteQueue + ); + + await this.deleteItem(deleteQueue); + + const deletedModels = deleteQueue.reduce( + (acc, { items }) => acc.concat(items), + [] + ); + return [models, deletedModels]; + } else { + await this.deleteTraverse( + relations, + models, + modelConstructor.name, + nameSpace, + deleteQueue + ); + + await this.deleteItem(deleteQueue); + + const deletedModels = deleteQueue.reduce( + (acc, { items }) => acc.concat(items), + [] + ); + + return [models, deletedModels]; + } + } else { + const model = modelOrModelConstructor; + + const modelConstructor = Object.getPrototypeOf(model) + .constructor as PersistentModelConstructor; + const nameSpace = this.namespaceResolver(modelConstructor); + + const storeName = this.getStorenameForModel(modelConstructor); + if (condition) { + const fromDB = await AsyncStorageDatabase.get(model.id, storeName); + const predicates = ModelPredicateCreator.getPredicates(condition); + const { predicates: predicateObjs, type } = predicates; + + const isValid = validatePredicate(fromDB, type, predicateObjs); + if (!isValid) { + const msg = 'Conditional update failed'; + logger.error(msg, { model: fromDB, condition: predicateObjs }); + + throw new Error(msg); + } + + const relations = this.schema.namespaces[nameSpace].relationships[ + modelConstructor.name + ].relationTypes; + await this.deleteTraverse( + relations, + [model], + modelConstructor.name, + nameSpace, + deleteQueue + ); + } else { + const relations = this.schema.namespaces[nameSpace].relationships[ + modelConstructor.name + ].relationTypes; + + await this.deleteTraverse( + relations, + [model], + modelConstructor.name, + nameSpace, + deleteQueue + ); + } + + await this.deleteItem(deleteQueue); + + const deletedModels = deleteQueue.reduce( + (acc, { items }) => acc.concat(items), + [] + ); + + return [[model], deletedModels]; + } + } + + private async deleteItem( + deleteQueue?: { storeName: string; items: T[] | IDBValidKey[] }[] + ) { + const connectionStoreNames = deleteQueue.map(({ storeName }) => { + return storeName; + }); + + for await (const deleteItem of deleteQueue) { + const { storeName, items } = deleteItem; + + for await (const item of items) { + if (item) { + if (typeof item === 'object') { + const id = item['id']; + await AsyncStorageDatabase.delete(id, storeName); + } + } + } + } + } + /** + * Populates the delete Queue with all the items to delete + * @param relations + * @param models + * @param srcModel + * @param nameSpace + * @param deleteQueue + */ + private async deleteTraverse( + relations: RelationType[], + models: T[], + srcModel: string, + nameSpace: string, + deleteQueue: { storeName: string; items: T[] }[] + ): Promise { + for await (const rel of relations) { + const { relationType, modelName } = rel; + const storeName = this.getStorename(nameSpace, modelName); + const index = getIndex( + this.schema.namespaces[nameSpace].relationships[modelName] + .relationTypes, + srcModel + ); + switch (relationType) { + case 'HAS_ONE': + for await (const model of models) { + const allRecords = await AsyncStorageDatabase.getAll(storeName); + const recordToDelete = allRecords.filter( + childItem => childItem[index] === model.id + ); + + await this.deleteTraverse( + this.schema.namespaces[nameSpace].relationships[modelName] + .relationTypes, + recordToDelete, + modelName, + nameSpace, + deleteQueue + ); + } + break; + case 'HAS_MANY': + for await (const model of models) { + const allRecords = await AsyncStorageDatabase.getAll(storeName); + const childrenArray = allRecords.filter( + childItem => childItem[index] === model.id + ); + + await this.deleteTraverse( + this.schema.namespaces[nameSpace].relationships[modelName] + .relationTypes, + childrenArray, + modelName, + nameSpace, + deleteQueue + ); + } + break; + case 'BELONGS_TO': + // Intentionally blank + break; + default: + exhaustiveCheck(relationType); + break; + } + } + + deleteQueue.push({ + storeName: this.getStorename(nameSpace, srcModel), + items: models.map(record => + this.modelInstanceCreator( + this.getModelConstructorByModelName(nameSpace, srcModel), + record + ) + ), + }); + } + + async clear(): Promise { + await AsyncStorageDatabase.clear(); + + this.db = undefined; + this.initPromise = undefined; + } +} + +export default new AsyncStorageAdapter(); From 619cd9cdc395370a5b78f2396cca8e6df345a226 Mon Sep 17 00:00:00 2001 From: Ashish Nanda Date: Tue, 11 Feb 2020 20:55:04 -0800 Subject: [PATCH 03/25] Add separate default adapters for Web and React Native --- .../adapter/getDefaultAdapter/index.native.ts | 8 ++++++++ .../src/storage/adapter/getDefaultAdapter/index.ts | 12 ++++++++++++ packages/datastore/src/storage/storage.ts | 12 ++---------- 3 files changed, 22 insertions(+), 10 deletions(-) create mode 100644 packages/datastore/src/storage/adapter/getDefaultAdapter/index.native.ts create mode 100644 packages/datastore/src/storage/adapter/getDefaultAdapter/index.ts diff --git a/packages/datastore/src/storage/adapter/getDefaultAdapter/index.native.ts b/packages/datastore/src/storage/adapter/getDefaultAdapter/index.native.ts new file mode 100644 index 00000000000..2a6ed7f7062 --- /dev/null +++ b/packages/datastore/src/storage/adapter/getDefaultAdapter/index.native.ts @@ -0,0 +1,8 @@ +import { Adapter } from '..'; +import AsyncStorageAdapter from '../asyncstorage'; + +const getDefaultAdapter: () => Adapter = () => { + return AsyncStorageAdapter; +}; + +export default getDefaultAdapter; diff --git a/packages/datastore/src/storage/adapter/getDefaultAdapter/index.ts b/packages/datastore/src/storage/adapter/getDefaultAdapter/index.ts new file mode 100644 index 00000000000..8e09cdfafbc --- /dev/null +++ b/packages/datastore/src/storage/adapter/getDefaultAdapter/index.ts @@ -0,0 +1,12 @@ +import { Adapter } from '..'; + +const getDefaultAdapter: () => Adapter = () => { + if (window.indexedDB) { + return require('../indexeddb').default; + } + if (process && process.env) { + throw new Error('Node is not supported'); + } +}; + +export default getDefaultAdapter; diff --git a/packages/datastore/src/storage/storage.ts b/packages/datastore/src/storage/storage.ts index 1296d6a9e17..3909aa68e49 100644 --- a/packages/datastore/src/storage/storage.ts +++ b/packages/datastore/src/storage/storage.ts @@ -20,15 +20,7 @@ import { } from '../types'; import { isModelConstructor, STORAGE, validatePredicate } from '../util'; import { Adapter } from './adapter'; - -const getDefaultAdapter: () => Adapter = () => { - if (window.indexedDB) { - return require('./adapter/indexeddb').default; - } - if (process && process.env) { - throw new Error('Node is not supported'); - } -}; +import getDefaultAdapter from './adapter/getDefaultAdapter'; export type StorageSubscriptionMessage = SubscriptionMessage & { mutator?: Symbol; @@ -52,7 +44,7 @@ class Storage implements StorageFacade { private readonly modelInstanceCreator: ModelInstanceCreator, private readonly adapter?: Adapter ) { - this.adapter = adapter || getDefaultAdapter(); + this.adapter = getDefaultAdapter(); this.pushStream = new PushStream(); } From c259d9c8c2bab321f632a0f4c15172d9e2c2bda8 Mon Sep 17 00:00:00 2001 From: Ashish Nanda Date: Tue, 11 Feb 2020 21:06:34 -0800 Subject: [PATCH 04/25] Make error messages more meaningful --- packages/datastore/src/sync/index.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/datastore/src/sync/index.ts b/packages/datastore/src/sync/index.ts index 23be8e779fc..b83ca81ce4e 100644 --- a/packages/datastore/src/sync/index.ts +++ b/packages/datastore/src/sync/index.ts @@ -130,9 +130,7 @@ export class SyncEngine { try { await this.setupModels(params); } catch (err) { - logger.error( - "Sync engine stopped. IndexedDB not supported in this browser's private mode" - ); + logger.error('Sync engine error on start', err); return; } From 5d61f39cf3c5fcef11a4082ed6ae7fc70a43311e Mon Sep 17 00:00:00 2001 From: Ashish Nanda Date: Tue, 11 Feb 2020 21:09:39 -0800 Subject: [PATCH 05/25] Add support for Reachability in React Native --- packages/core/src/Util/Reachability.native.ts | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 packages/core/src/Util/Reachability.native.ts diff --git a/packages/core/src/Util/Reachability.native.ts b/packages/core/src/Util/Reachability.native.ts new file mode 100644 index 00000000000..3350698e835 --- /dev/null +++ b/packages/core/src/Util/Reachability.native.ts @@ -0,0 +1,52 @@ +import { + default as NetInfo, + NetInfoState, +} from '@react-native-community/netinfo'; +import * as Observable from 'zen-observable'; +import { ConsoleLogger as Logger } from '../Logger'; + +const logger = new Logger('Reachability', 'DEBUG'); + +type NetworkStatus = { + online: boolean; +}; + +export default class ReachabilityNavigator implements Reachability { + networkMonitor(): Observable { + return new Observable(observer => { + logger.log('subscribing to reachability'); + + let online = false; + + NetInfo.fetch().then(({ isInternetReachable }) => { + online = isInternetReachable; + + logger.log('Notifying initial reachability state', online); + + observer.next({ online }); + }); + + const id = setInterval(async () => { + const { isInternetReachable } = await NetInfo.fetch(); + + if (online !== isInternetReachable) { + online = isInternetReachable; + + logger.log('Notifying reachability change', online); + + observer.next({ online }); + } + }, 2000); + + return () => { + logger.warn('unsubscribing reachability'); + + clearInterval(id); + }; + }); + } +} + +interface Reachability { + networkMonitor(): Observable; +} From 6153dc6ecd9c7deae9bb1c44d9b58df97de58ccd Mon Sep 17 00:00:00 2001 From: Ashish Nanda Date: Tue, 11 Feb 2020 21:10:54 -0800 Subject: [PATCH 06/25] Add @react-native-community/netinfo to devDependencies --- packages/core/package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core/package.json b/packages/core/package.json index 817faa3f559..9d8e271a02c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -38,7 +38,9 @@ "homepage": "https://aws-amplify.github.io/", "devDependencies": { "find": "^0.2.7", - "prepend-file": "^1.3.1" + "prepend-file": "^1.3.1", + "@react-native-community/netinfo": "4.7.0", + "react-native": "0.59.0" }, "dependencies": { "aws-sdk": "2.518.0", From 352533387a7d47255aad14bf1dd27934d364bf51 Mon Sep 17 00:00:00 2001 From: Ashish Nanda Date: Tue, 11 Feb 2020 21:14:30 -0800 Subject: [PATCH 07/25] Pin down the version of crypto-js --- packages/amazon-cognito-identity-js/package.json | 2 +- packages/auth/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/amazon-cognito-identity-js/package.json b/packages/amazon-cognito-identity-js/package.json index 8398ca4b785..5b717630b99 100644 --- a/packages/amazon-cognito-identity-js/package.json +++ b/packages/amazon-cognito-identity-js/package.json @@ -63,7 +63,7 @@ "types": "./index.d.ts", "dependencies": { "buffer": "4.9.1", - "crypto-js": "^3.1.9-1", + "crypto-js": "3.1.9-1", "js-cookie": "^2.1.4" }, "devDependencies": { diff --git a/packages/auth/package.json b/packages/auth/package.json index 644495455b3..77364754db9 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -37,7 +37,7 @@ "@aws-amplify/cache": "^2.1.5", "@aws-amplify/core": "^2.2.4", "amazon-cognito-identity-js": "^3.2.4", - "crypto-js": "^3.1.9-1" + "crypto-js": "3.1.9-1" }, "jest": { "globals": { From 9690af0527f90ee460fd94b361edf7b7c1e92736 Mon Sep 17 00:00:00 2001 From: Ashish Nanda Date: Wed, 12 Feb 2020 08:45:46 -0800 Subject: [PATCH 08/25] Enable publish from rn-datastore branch --- .circleci/config.yml | 1 + package.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a6879a51cb3..92507b5e39f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -336,6 +336,7 @@ workflows: - master - beta - 1.0-stable + - rn-datastore requires: - unit_test - integ_react_predictions diff --git a/package.json b/package.json index ade4faace5b..b1cb0aa0647 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,8 @@ "publish:master": "lerna publish --canary --force-publish \"*\" --yes --dist-tag=unstable --preid=unstable --exact", "publish:beta": "lerna publish --canary --force-publish \"*\" --yes --dist-tag=beta --preid=beta --exact", "publish:release": "lerna publish --conventional-commits --yes --message 'chore(release): Publish [ci skip]'", - "publish:1.0-stable": "lerna publish --conventional-commits --yes --dist-tag=stable-1.0 --message 'chore(release): Publish [ci skip]'" + "publish:1.0-stable": "lerna publish --conventional-commits --yes --dist-tag=stable-1.0 --message 'chore(release): Publish [ci skip]'", + "publish:rn-datastore": "lerna publish --canary --force-publish \"*\" --yes --dist-tag=rn-datastore --preid=rn-datastore --exact" }, "husky": { "hooks": { From 3744cc918a8e99afd92ec6b99a0d93e48ee12ec8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Feb 2020 11:42:30 -0800 Subject: [PATCH 09/25] chore(deps-dev): bump codecov from 1.0.1 to 3.6.5 (#4951) Bumps [codecov](https://github.com/codecov/codecov-node) from 1.0.1 to 3.6.5. - [Release notes](https://github.com/codecov/codecov-node/releases) - [Commits](https://github.com/codecov/codecov-node/commits) Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ade4faace5b..307028be11e 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "@types/jest": "^24.0.18", "@types/node": "^8.9.5", "babel-loader": "^8.0.0", - "codecov": "^1.0.1", + "codecov": "^3.6.5", "compression-webpack-plugin": "^1.1.3", "cypress": "^3.2.0", "husky": "^3.0.5", From a577935c9e3128edac8004e36b9a200c4f9d101d Mon Sep 17 00:00:00 2001 From: Francisco Rodriguez Date: Thu, 20 Feb 2020 10:34:21 -0800 Subject: [PATCH 10/25] (fix:@aws-amplify/pubsub) Fix for unsubscription new subscription race condition (#4956) * Fix for unsubscription new subscription race condition * Update packages/pubsub/src/Providers/AWSAppSyncRealTimeProvider.ts --- .../Providers/AWSAppSyncRealTimeProvider.ts | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/pubsub/src/Providers/AWSAppSyncRealTimeProvider.ts b/packages/pubsub/src/Providers/AWSAppSyncRealTimeProvider.ts index 75c85d456dd..aba6a2908a8 100644 --- a/packages/pubsub/src/Providers/AWSAppSyncRealTimeProvider.ts +++ b/packages/pubsub/src/Providers/AWSAppSyncRealTimeProvider.ts @@ -372,22 +372,27 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider { private _removeSubscriptionObserver(subscriptionId) { this.subscriptionObserverMap.delete(subscriptionId); - if (this.subscriptionObserverMap.size === 0) { - // Socket could be sending data to unsubscribe so is required to wait until is flushed - this._closeSocketWhenFlushed(); - } + + // Verifying 1000ms after removing subscription in case there are new subscription unmount/mount + setTimeout(this._closeSocketIfRequired.bind(this), 1000); } - private _closeSocketWhenFlushed() { - logger.debug('closing WebSocket...'); - clearTimeout(this.keepAliveTimeoutId); + private _closeSocketIfRequired() { + if (this.subscriptionObserverMap.size > 0) { + // Active subscriptions on the WebSocket + return; + } + if (!this.awsRealTimeSocket) { this.socketStatus = SOCKET_STATUS.CLOSED; return; } if (this.awsRealTimeSocket.bufferedAmount > 0) { - setTimeout(this._closeSocketWhenFlushed.bind(this), 1000); + // Still data on the WebSocket + setTimeout(this._closeSocketIfRequired.bind(this), 1000); } else { + logger.debug('closing WebSocket...'); + clearTimeout(this.keepAliveTimeoutId); const tempSocket = this.awsRealTimeSocket; tempSocket.close(1000); this.awsRealTimeSocket = null; From 7f60396fd47255be13ff499a65624914ea8a46f3 Mon Sep 17 00:00:00 2001 From: Manuel Iglesias Date: Mon, 24 Feb 2020 05:04:24 -0800 Subject: [PATCH 11/25] Fix to initialize only once and handle disconnection from network (#4921) * initialize only once * Fix onerror handler for WebSocket * Change log level for unsubscribe message * Add regions and fix typo * Handle disconnection --- packages/core/src/Util/Reachability.native.ts | 2 +- packages/datastore/__tests__/DataStore.ts | 67 ++++++++++++++++++- packages/datastore/src/datastore/datastore.ts | 52 +++++++++----- packages/datastore/src/sync/index.ts | 10 ++- .../Providers/AWSAppSyncRealTimeProvider.ts | 14 ++-- 5 files changed, 117 insertions(+), 28 deletions(-) diff --git a/packages/core/src/Util/Reachability.native.ts b/packages/core/src/Util/Reachability.native.ts index 3350698e835..391013f2565 100644 --- a/packages/core/src/Util/Reachability.native.ts +++ b/packages/core/src/Util/Reachability.native.ts @@ -39,7 +39,7 @@ export default class ReachabilityNavigator implements Reachability { }, 2000); return () => { - logger.warn('unsubscribing reachability'); + logger.log('unsubscribing reachability'); clearInterval(id); }; diff --git a/packages/datastore/__tests__/DataStore.ts b/packages/datastore/__tests__/DataStore.ts index 08a7a7f9df7..767bf96c9fa 100644 --- a/packages/datastore/__tests__/DataStore.ts +++ b/packages/datastore/__tests__/DataStore.ts @@ -1,19 +1,37 @@ import 'fake-indexeddb/auto'; import * as uuidValidate from 'uuid-validate'; -import { initSchema as initSchemaType } from '../src/datastore/datastore'; +import { + initSchema as initSchemaType, + DataStore as DataStoreType, +} from '../src/datastore/datastore'; import { ModelInit, MutableModel, PersistentModelConstructor, Schema, } from '../src/types'; +import StorageType from '../src/storage/storage'; +import Observable from 'zen-observable-ts'; let initSchema: typeof initSchemaType; +let DataStore: typeof DataStoreType; +let Storage: typeof StorageType; beforeEach(() => { jest.resetModules(); - ({ initSchema } = require('../src/datastore/datastore')); + jest.doMock('../src/storage/storage', () => { + const mock = jest.fn().mockImplementation(() => ({ + runExclusive: jest.fn(), + query: jest.fn(), + observe: jest.fn(() => Observable.of()), + })); + + (mock).getNamespace = () => ({ models: {} }); + + return { default: mock }; + }); + ({ initSchema, DataStore } = require('../src/datastore/datastore')); }); describe('DataStore tests', () => { @@ -66,6 +84,14 @@ describe('DataStore tests', () => { uuidValidate(model.id.replace(/^(.{4})-(.{4})-(.{8})/, '$3-$2-$1'), 1) ).toBe(true); }); + + test('initSchema is executed only once', () => { + initSchema(testSchema()); + + expect(() => { + initSchema(testSchema()); + }).toThrow('The schema has already been initialized'); + }); }); describe('Immutability', () => { @@ -122,6 +148,39 @@ describe('DataStore tests', () => { expect(model1.id).toBe(model2.id); }); }); + + describe('Initialization', () => { + test('start is called only once', async () => { + Storage = require('../src/storage/storage').default; + + const classes = initSchema(testSchema()); + + const { Model } = classes; + + const promises = [ + DataStore.query(Model), + DataStore.query(Model), + DataStore.query(Model), + DataStore.query(Model), + ]; + + await Promise.all(promises); + + expect(Storage).toHaveBeenCalledTimes(1); + }); + }); + + test('It is initialized when observing (no query)', async () => { + Storage = require('../src/storage/storage').default; + + const classes = initSchema(testSchema()); + + const { Model } = classes; + + DataStore.observe(Model).subscribe(jest.fn()); + + expect(Storage).toHaveBeenCalledTimes(1); + }); }); //#region Test helpers @@ -144,6 +203,7 @@ function testSchema(): Schema { models: { Model: { name: 'Model', + pluralName: 'Models', syncable: true, fields: { id: { @@ -162,6 +222,7 @@ function testSchema(): Schema { }, LocalModel: { name: 'LocalModel', + pluralName: 'LocalModels', syncable: false, fields: { id: { @@ -179,7 +240,7 @@ function testSchema(): Schema { }, }, }, - version: 1, + version: '1', }; } diff --git a/packages/datastore/src/datastore/datastore.ts b/packages/datastore/src/datastore/datastore.ts index ecfb405ba6d..8c24accb48e 100644 --- a/packages/datastore/src/datastore/datastore.ts +++ b/packages/datastore/src/datastore/datastore.ts @@ -474,7 +474,6 @@ const observe: { modelConstructor?: PersistentModelConstructor, idOrCriteria?: string | ProducerModelPredicate ) => { - start(); let predicate: ModelPredicate; if (idOrCriteria !== undefined && modelConstructor === undefined) { @@ -504,9 +503,24 @@ const observe: { ); } - return storage - .observe(modelConstructor, predicate) - .filter(({ model }) => namespaceResolver(model) === USER); + return new Observable>(observer => { + let handle: ZenObservable.Subscription; + + (async () => { + await start(); + + handle = storage + .observe(modelConstructor, predicate) + .filter(({ model }) => namespaceResolver(model) === USER) + .subscribe(observer); + })(); + + return () => { + if (handle) { + handle.unsubscribe(); + } + }; + }); }; const query: { @@ -683,21 +697,29 @@ async function checkSchemaVersion( if (storedValue !== version) { await s.clear(false); } + } else { + await s.save( + modelInstanceCreator(Setting, { + key: SETTING_SCHEMA_VERSION, + value: JSON.stringify(version), + }) + ); } - - await s.save( - modelInstanceCreator(Setting, { - key: SETTING_SCHEMA_VERSION, - value: JSON.stringify(version), - }) - ); }); } let syncSubscription: ZenObservable.Subscription; +let initResolve: Function; +let initialized: Promise; async function start(): Promise { - if (storage !== undefined) { + if (initialized === undefined) { + initialized = new Promise(res => { + initResolve = res; + }); + } else { + await initialized; + return; } @@ -710,10 +732,6 @@ async function start(): Promise { await checkSchemaVersion(storage, schema.version); - if (sync !== undefined) { - return; - } - const { aws_appsync_graphqlEndpoint } = amplifyConfig; if (aws_appsync_graphqlEndpoint) { @@ -738,6 +756,8 @@ async function start(): Promise { }, }); } + + initResolve(); } async function clear() { diff --git a/packages/datastore/src/sync/index.ts b/packages/datastore/src/sync/index.ts index b83ca81ce4e..526fced2a6a 100644 --- a/packages/datastore/src/sync/index.ts +++ b/packages/datastore/src/sync/index.ts @@ -137,6 +137,7 @@ export class SyncEngine { new Reachability().networkMonitor().subscribe(async ({ online }) => { this.online = online; if (online) { + //#region GraphQL Subscriptions const [ ctlSubsObservable, dataSubsObservable, @@ -151,6 +152,9 @@ export class SyncEngine { } logger.log('Realtime ready'); + //#endregion + + //#region Base & Sync queries const currentTimeStamp = new Date().getTime(); const modelLastSync: Map< @@ -181,8 +185,9 @@ export class SyncEngine { observer.error(err); return; } + //#endregion - // process mutations + //#region process mutations subscriptions.push( this.mutationsProcessor .start() @@ -201,8 +206,9 @@ export class SyncEngine { } ) ); + //#endregion - // TODO: extract to funciton + // TODO: extract to function subscriptions.push( dataSubsObservable.subscribe( ([_transformerMutationType, modelDefinition, item]) => { diff --git a/packages/pubsub/src/Providers/AWSAppSyncRealTimeProvider.ts b/packages/pubsub/src/Providers/AWSAppSyncRealTimeProvider.ts index aba6a2908a8..da148207404 100644 --- a/packages/pubsub/src/Providers/AWSAppSyncRealTimeProvider.ts +++ b/packages/pubsub/src/Providers/AWSAppSyncRealTimeProvider.ts @@ -456,7 +456,7 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider { if (type === MESSAGE_TYPES.GQL_CONNECTION_KEEP_ALIVE) { clearTimeout(this.keepAliveTimeoutId); this.keepAliveTimeoutId = setTimeout( - this._timeoutDisconnect.bind(this), + this._errorDisconnect.bind(this, 'Timeout disconnect'), this.keepAliveTimeout ); return; @@ -492,16 +492,15 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider { } } - private _timeoutDisconnect() { + private _errorDisconnect(msg: string) { this.subscriptionObserverMap.forEach(({ observer }) => { if (!observer.closed) { observer.error({ - errors: [{ ...new GraphQLError(`Timeout disconnect`) }], + errors: [{ ...new GraphQLError(msg) }], }); - observer.complete(); } }); - this.subscriptionObserverMap = new Map(); + this.subscriptionObserverMap.clear(); if (this.awsRealTimeSocket) { this.awsRealTimeSocket.close(); } @@ -661,7 +660,10 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider { this.awsRealTimeSocket.onmessage = this._handleIncomingSubscriptionMessage.bind( this ); - this.awsRealTimeSocket.onerror = logger.debug; + this.awsRealTimeSocket.onerror = err => { + logger.debug(err); + this._errorDisconnect('Connection closed'); + }; res('Cool, connected to AWS AppSyncRealTime'); return; } From ce7ca96dd59ca90455d17898a205b5dab05bbfff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2020 09:12:53 -0500 Subject: [PATCH 12/25] chore(deps): bump nokogiri from 1.10.4 to 1.10.8 in /docs (#4974) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.4 to 1.10.8. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.4...v1.10.8) Signed-off-by: dependabot[bot] --- docs/Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index 96c7f0dced9..8e2c0ba52a5 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -197,7 +197,7 @@ GEM minitest (5.11.3) multipart-post (2.0.0) net-dns (0.8.0) - nokogiri (1.10.4) + nokogiri (1.10.8) mini_portile2 (~> 2.4.0) octokit (4.8.0) sawyer (~> 0.8.0, >= 0.5.3) From 3cd2468dd0a278a31e6065cc9c6590b5a016069f Mon Sep 17 00:00:00 2001 From: Ashish Nanda Date: Thu, 27 Feb 2020 13:54:55 -0800 Subject: [PATCH 13/25] Use the db instance property of the Adapter class for all database operations (#4995) Use the db instance property of the Adapter class for all database operations --- .../storage/adapter/AsyncStorageDatabase.ts | 7 +--- .../src/storage/adapter/asyncstorage.ts | 38 ++++++++----------- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/packages/datastore/src/storage/adapter/AsyncStorageDatabase.ts b/packages/datastore/src/storage/adapter/AsyncStorageDatabase.ts index e8a67ec1f9f..7d7aeaee1a4 100644 --- a/packages/datastore/src/storage/adapter/AsyncStorageDatabase.ts +++ b/packages/datastore/src/storage/adapter/AsyncStorageDatabase.ts @@ -5,9 +5,7 @@ const DB_NAME = '@AmplifyDatastore'; const COLLECTION = 'Collection'; const DATA = 'Data'; -// write a function for getCollectionForStore. -// handle errors. -// write batch save/ transactional save. +//TODO: Consider refactoring to a batch save operation. class AsyncStorageDatabase { async save(item: T, storeName: string) { const itemKey = this.getKeyForItem(storeName, item.id); @@ -80,7 +78,6 @@ class AsyncStorageDatabase { await AsyncStorage.multiRemove(allDataStoreKeys); } - // Can ID not be a string? private getKeyForItem(storeName: string, id: string): string { return `${DB_NAME}::${storeName}::${DATA}::${id}`; } @@ -94,4 +91,4 @@ class AsyncStorageDatabase { } } -export default new AsyncStorageDatabase(); +export default AsyncStorageDatabase; diff --git a/packages/datastore/src/storage/adapter/asyncstorage.ts b/packages/datastore/src/storage/adapter/asyncstorage.ts index 274f365d894..457f352151a 100644 --- a/packages/datastore/src/storage/adapter/asyncstorage.ts +++ b/packages/datastore/src/storage/adapter/asyncstorage.ts @@ -1,5 +1,4 @@ import { ConsoleLogger as Logger } from '@aws-amplify/core'; -import { AsyncStorage } from 'react-native'; import AsyncStorageDatabase from './AsyncStorageDatabase'; import { Adapter } from '.'; import { ModelInstanceCreator } from '../../datastore/datastore'; @@ -78,7 +77,7 @@ class AsyncStorageAdapter implements Adapter { this.getModelConstructorByModelName = getModelConstructorByModelName; try { if (!this.db) { - this.db = AsyncStorageDatabase; + this.db = new AsyncStorageDatabase(); this.resolve(); } } catch (error) { @@ -109,7 +108,7 @@ class AsyncStorageAdapter implements Adapter { return { storeName, item, instance }; } ); - const fromDB = await AsyncStorageDatabase.get(model.id, storeName); + const fromDB = await this.db.get(model.id, storeName); if (condition) { const predicates = ModelPredicateCreator.getPredicates(condition); @@ -132,22 +131,21 @@ class AsyncStorageAdapter implements Adapter { const { id } = item; - const opType: OpType = (await AsyncStorageDatabase.get(id, storeName)) + const opType: OpType = (await this.db.get(id, storeName)) ? OpType.UPDATE : OpType.INSERT; if (id === model.id) { - await AsyncStorageDatabase.save(item, storeName); + await this.db.save(item, storeName); result.push([instance, opType]); } else { if (opType === OpType.INSERT) { - await AsyncStorageDatabase.save(item, storeName); + await this.db.save(item, storeName); result.push([instance, opType]); } } - const savedItem = await AsyncStorageDatabase.get(id, storeName); } return result; @@ -186,7 +184,7 @@ class AsyncStorageAdapter implements Adapter { case 'HAS_ONE': for await (const recordItem of records) { if (recordItem[fieldName]) { - const connectionRecord = await AsyncStorageDatabase.get( + const connectionRecord = await this.db.get( recordItem[fieldName], storeName ); @@ -201,7 +199,7 @@ class AsyncStorageAdapter implements Adapter { case 'BELONGS_TO': for await (const recordItem of records) { if (recordItem[targetName]) { - const connectionRecord = await AsyncStorageDatabase.get( + const connectionRecord = await this.db.get( recordItem[targetName], storeName ); @@ -249,7 +247,7 @@ class AsyncStorageAdapter implements Adapter { if (idPredicate) { const { operand: id } = idPredicate; - const record = await AsyncStorageDatabase.get(id, storeName); + const record = await this.db.get(id, storeName); if (record) { const [x] = await this.load(namespaceName, modelConstructor.name, [ @@ -260,7 +258,7 @@ class AsyncStorageAdapter implements Adapter { return []; } - const all = await AsyncStorageDatabase.getAll(storeName); + const all = await this.db.getAll(storeName); const filtered = predicateObjs ? all.filter(m => validatePredicate(m, type, predicateObjs)) @@ -273,7 +271,7 @@ class AsyncStorageAdapter implements Adapter { ); } } - const all = await AsyncStorageDatabase.getAll(storeName); + const all = await this.db.getAll(storeName); return await this.load( namespaceName, @@ -303,7 +301,7 @@ class AsyncStorageAdapter implements Adapter { firstOrLast: QueryOne = QueryOne.FIRST ): Promise { const storeName = this.getStorenameForModel(modelConstructor); - const result = await AsyncStorageDatabase.getOne(firstOrLast, storeName); + const result = await this.db.getOne(firstOrLast, storeName); return result && this.modelInstanceCreator(modelConstructor, result); } @@ -368,7 +366,7 @@ class AsyncStorageAdapter implements Adapter { const storeName = this.getStorenameForModel(modelConstructor); if (condition) { - const fromDB = await AsyncStorageDatabase.get(model.id, storeName); + const fromDB = await this.db.get(model.id, storeName); const predicates = ModelPredicateCreator.getPredicates(condition); const { predicates: predicateObjs, type } = predicates; @@ -418,10 +416,6 @@ class AsyncStorageAdapter implements Adapter { private async deleteItem( deleteQueue?: { storeName: string; items: T[] | IDBValidKey[] }[] ) { - const connectionStoreNames = deleteQueue.map(({ storeName }) => { - return storeName; - }); - for await (const deleteItem of deleteQueue) { const { storeName, items } = deleteItem; @@ -429,7 +423,7 @@ class AsyncStorageAdapter implements Adapter { if (item) { if (typeof item === 'object') { const id = item['id']; - await AsyncStorageDatabase.delete(id, storeName); + await this.db.delete(id, storeName); } } } @@ -461,7 +455,7 @@ class AsyncStorageAdapter implements Adapter { switch (relationType) { case 'HAS_ONE': for await (const model of models) { - const allRecords = await AsyncStorageDatabase.getAll(storeName); + const allRecords = await this.db.getAll(storeName); const recordToDelete = allRecords.filter( childItem => childItem[index] === model.id ); @@ -478,7 +472,7 @@ class AsyncStorageAdapter implements Adapter { break; case 'HAS_MANY': for await (const model of models) { - const allRecords = await AsyncStorageDatabase.getAll(storeName); + const allRecords = await this.db.getAll(storeName); const childrenArray = allRecords.filter( childItem => childItem[index] === model.id ); @@ -514,7 +508,7 @@ class AsyncStorageAdapter implements Adapter { } async clear(): Promise { - await AsyncStorageDatabase.clear(); + await this.db.clear(); this.db = undefined; this.initPromise = undefined; From 788d64ba1cdcebeabfcf2f0246143885dfba4cac Mon Sep 17 00:00:00 2001 From: Ashish Nanda Date: Thu, 27 Feb 2020 15:47:10 -0800 Subject: [PATCH 14/25] Removing unused code --- packages/core/src/Util/Reachability.native.ts | 5 +---- packages/datastore/src/storage/adapter/asyncstorage.ts | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/core/src/Util/Reachability.native.ts b/packages/core/src/Util/Reachability.native.ts index 391013f2565..34ddf54cf54 100644 --- a/packages/core/src/Util/Reachability.native.ts +++ b/packages/core/src/Util/Reachability.native.ts @@ -1,7 +1,4 @@ -import { - default as NetInfo, - NetInfoState, -} from '@react-native-community/netinfo'; +import { default as NetInfo } from '@react-native-community/netinfo'; import * as Observable from 'zen-observable'; import { ConsoleLogger as Logger } from '../Logger'; diff --git a/packages/datastore/src/storage/adapter/asyncstorage.ts b/packages/datastore/src/storage/adapter/asyncstorage.ts index 457f352151a..4502c0588a6 100644 --- a/packages/datastore/src/storage/adapter/asyncstorage.ts +++ b/packages/datastore/src/storage/adapter/asyncstorage.ts @@ -315,7 +315,6 @@ class AsyncStorageAdapter implements Adapter { const modelConstructor = modelOrModelConstructor; const nameSpace = this.namespaceResolver(modelConstructor); - const storeName = this.getStorenameForModel(modelConstructor); // models to be deleted. const models = await this.query(modelConstructor, condition); // TODO: refactor this to use a function like getRelations() From 1682c0eabecc87693fadba31b6546d14bad1d961 Mon Sep 17 00:00:00 2001 From: Ashish Nanda Date: Thu, 27 Feb 2020 16:49:49 -0800 Subject: [PATCH 15/25] Remove rn-datastore branch publish config --- .circleci/config.yml | 1 - package.json | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 92507b5e39f..a6879a51cb3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -336,7 +336,6 @@ workflows: - master - beta - 1.0-stable - - rn-datastore requires: - unit_test - integ_react_predictions diff --git a/package.json b/package.json index acb66472702..307028be11e 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,7 @@ "publish:master": "lerna publish --canary --force-publish \"*\" --yes --dist-tag=unstable --preid=unstable --exact", "publish:beta": "lerna publish --canary --force-publish \"*\" --yes --dist-tag=beta --preid=beta --exact", "publish:release": "lerna publish --conventional-commits --yes --message 'chore(release): Publish [ci skip]'", - "publish:1.0-stable": "lerna publish --conventional-commits --yes --dist-tag=stable-1.0 --message 'chore(release): Publish [ci skip]'", - "publish:rn-datastore": "lerna publish --canary --force-publish \"*\" --yes --dist-tag=rn-datastore --preid=rn-datastore --exact" + "publish:1.0-stable": "lerna publish --conventional-commits --yes --dist-tag=stable-1.0 --message 'chore(release): Publish [ci skip]'" }, "husky": { "hooks": { From e825ce10c4c96bb716233ccb3c4d8b1fa858795e Mon Sep 17 00:00:00 2001 From: Ashish Nanda Date: Thu, 27 Feb 2020 21:28:36 -0800 Subject: [PATCH 16/25] Preparing release From f2efeb1531d013e87dfd747c45272dccdbd0e985 Mon Sep 17 00:00:00 2001 From: aws-amplify-bot Date: Fri, 28 Feb 2020 05:43:25 +0000 Subject: [PATCH 17/25] chore(release): Publish [ci skip] - amazon-cognito-identity-js@3.2.5 - @aws-amplify/analytics@2.2.6 - @aws-amplify/api@2.1.6 - @aws-amplify/auth@2.1.6 - aws-amplify-angular@4.1.7 - aws-amplify-react@3.1.7 - aws-amplify@2.2.6 - @aws-amplify/cache@2.1.6 - @aws-amplify/core@2.2.5 - @aws-amplify/datastore@1.0.8 - @aws-amplify/interactions@2.1.6 - @aws-amplify/predictions@2.1.6 - @aws-amplify/pubsub@2.1.7 - @aws-amplify/pushnotification@2.1.6 - @aws-amplify/storage@2.2.1 - @aws-amplify/xr@1.1.6 --- .../amazon-cognito-identity-js/CHANGELOG.md | 8 +++++++ .../package-lock.json | 2 +- .../amazon-cognito-identity-js/package.json | 2 +- packages/analytics/CHANGELOG.md | 8 +++++++ packages/analytics/package.json | 6 ++--- packages/api/CHANGELOG.md | 8 +++++++ packages/api/package.json | 8 +++---- packages/auth/CHANGELOG.md | 8 +++++++ packages/auth/package.json | 8 +++---- packages/aws-amplify-angular/CHANGELOG.md | 8 +++++++ packages/aws-amplify-angular/package.json | 4 ++-- packages/aws-amplify-react/CHANGELOG.md | 8 +++++++ packages/aws-amplify-react/package.json | 4 ++-- packages/aws-amplify/CHANGELOG.md | 8 +++++++ packages/aws-amplify/package.json | 22 +++++++++---------- packages/cache/CHANGELOG.md | 8 +++++++ packages/cache/package.json | 4 ++-- packages/core/CHANGELOG.md | 8 +++++++ packages/core/package.json | 4 ++-- packages/datastore/CHANGELOG.md | 8 +++++++ packages/datastore/package.json | 8 +++---- packages/interactions/CHANGELOG.md | 8 +++++++ packages/interactions/package.json | 4 ++-- packages/predictions/CHANGELOG.md | 8 +++++++ packages/predictions/package.json | 6 ++--- packages/pubsub/CHANGELOG.md | 8 +++++++ packages/pubsub/package.json | 8 +++---- packages/pushnotification/CHANGELOG.md | 8 +++++++ packages/pushnotification/package.json | 4 ++-- packages/storage/CHANGELOG.md | 8 +++++++ packages/storage/package.json | 4 ++-- packages/xr/CHANGELOG.md | 8 +++++++ packages/xr/package.json | 4 ++-- 33 files changed, 179 insertions(+), 51 deletions(-) diff --git a/packages/amazon-cognito-identity-js/CHANGELOG.md b/packages/amazon-cognito-identity-js/CHANGELOG.md index 07253e5ecf9..4a0249dc7e2 100644 --- a/packages/amazon-cognito-identity-js/CHANGELOG.md +++ b/packages/amazon-cognito-identity-js/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [3.2.5](https://github.com/aws-amplify/amplify-js/compare/amazon-cognito-identity-js@3.2.4...amazon-cognito-identity-js@3.2.5) (2020-02-28) + +**Note:** Version bump only for package amazon-cognito-identity-js + + + + + ## [3.2.4](https://github.com/aws-amplify/amplify-js/compare/amazon-cognito-identity-js@3.2.2...amazon-cognito-identity-js@3.2.4) (2020-02-07) **Note:** Version bump only for package amazon-cognito-identity-js diff --git a/packages/amazon-cognito-identity-js/package-lock.json b/packages/amazon-cognito-identity-js/package-lock.json index d2f36b78c5b..30e0b0a6f7e 100644 --- a/packages/amazon-cognito-identity-js/package-lock.json +++ b/packages/amazon-cognito-identity-js/package-lock.json @@ -1,6 +1,6 @@ { "name": "amazon-cognito-identity-js", - "version": "3.2.4", + "version": "3.2.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/packages/amazon-cognito-identity-js/package.json b/packages/amazon-cognito-identity-js/package.json index 5b717630b99..afb0d33a309 100644 --- a/packages/amazon-cognito-identity-js/package.json +++ b/packages/amazon-cognito-identity-js/package.json @@ -1,7 +1,7 @@ { "name": "amazon-cognito-identity-js", "description": "Amazon Cognito Identity Provider JavaScript SDK", - "version": "3.2.4", + "version": "3.2.5", "author": { "name": "Amazon Web Services", "email": "aws@amazon.com", diff --git a/packages/analytics/CHANGELOG.md b/packages/analytics/CHANGELOG.md index 3b64809c089..d9178d26aca 100644 --- a/packages/analytics/CHANGELOG.md +++ b/packages/analytics/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.2.6](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/analytics@2.2.5...@aws-amplify/analytics@2.2.6) (2020-02-28) + +**Note:** Version bump only for package @aws-amplify/analytics + + + + + ## [2.2.5](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/analytics@2.2.4...@aws-amplify/analytics@2.2.5) (2020-02-14) **Note:** Version bump only for package @aws-amplify/analytics diff --git a/packages/analytics/package.json b/packages/analytics/package.json index 51bc5144c27..9a8d14fc9ca 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -1,6 +1,6 @@ { "name": "@aws-amplify/analytics", - "version": "2.2.5", + "version": "2.2.6", "description": "Analytics category of aws-amplify", "main": "./lib/index.js", "module": "./lib-esm/index.js", @@ -36,8 +36,8 @@ }, "homepage": "https://aws-amplify.github.io/", "dependencies": { - "@aws-amplify/cache": "^2.1.5", - "@aws-amplify/core": "^2.2.4", + "@aws-amplify/cache": "^2.1.6", + "@aws-amplify/core": "^2.2.5", "uuid": "^3.2.1" }, "jest": { diff --git a/packages/api/CHANGELOG.md b/packages/api/CHANGELOG.md index a0b3c088570..701e01973be 100644 --- a/packages/api/CHANGELOG.md +++ b/packages/api/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.1.6](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/api@2.1.5...@aws-amplify/api@2.1.6) (2020-02-28) + +**Note:** Version bump only for package @aws-amplify/api + + + + + ## [2.1.5](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/api@2.1.3...@aws-amplify/api@2.1.5) (2020-02-07) diff --git a/packages/api/package.json b/packages/api/package.json index 6030e2f6935..a2a2ac815b1 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "@aws-amplify/api", - "version": "2.1.5", + "version": "2.1.6", "description": "Api category of aws-amplify", "main": "./lib/index.js", "module": "./lib-esm/index.js", @@ -37,9 +37,9 @@ "@types/zen-observable": "^0.8.0" }, "dependencies": { - "@aws-amplify/auth": "^2.1.5", - "@aws-amplify/cache": "^2.1.5", - "@aws-amplify/core": "^2.2.4", + "@aws-amplify/auth": "^2.1.6", + "@aws-amplify/cache": "^2.1.6", + "@aws-amplify/core": "^2.2.5", "axios": "^0.19.0", "graphql": "14.0.0", "uuid": "^3.2.1", diff --git a/packages/auth/CHANGELOG.md b/packages/auth/CHANGELOG.md index 2a92d872516..2ff496c4df1 100644 --- a/packages/auth/CHANGELOG.md +++ b/packages/auth/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.1.6](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/auth@2.1.5...@aws-amplify/auth@2.1.6) (2020-02-28) + +**Note:** Version bump only for package @aws-amplify/auth + + + + + ## [2.1.5](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/auth@2.1.3...@aws-amplify/auth@2.1.5) (2020-02-07) diff --git a/packages/auth/package.json b/packages/auth/package.json index 77364754db9..6ecccf9aa22 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@aws-amplify/auth", - "version": "2.1.5", + "version": "2.1.6", "description": "Auth category of aws-amplify", "main": "./lib/index.js", "module": "./lib-esm/index.js", @@ -34,9 +34,9 @@ }, "homepage": "https://aws-amplify.github.io/", "dependencies": { - "@aws-amplify/cache": "^2.1.5", - "@aws-amplify/core": "^2.2.4", - "amazon-cognito-identity-js": "^3.2.4", + "@aws-amplify/cache": "^2.1.6", + "@aws-amplify/core": "^2.2.5", + "amazon-cognito-identity-js": "^3.2.5", "crypto-js": "3.1.9-1" }, "jest": { diff --git a/packages/aws-amplify-angular/CHANGELOG.md b/packages/aws-amplify-angular/CHANGELOG.md index 31918b9ead9..80898561741 100644 --- a/packages/aws-amplify-angular/CHANGELOG.md +++ b/packages/aws-amplify-angular/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [4.1.7](https://github.com/aws-amplify/amplify-js/compare/aws-amplify-angular@4.1.6...aws-amplify-angular@4.1.7) (2020-02-28) + +**Note:** Version bump only for package aws-amplify-angular + + + + + ## [4.1.6](https://github.com/aws-amplify/amplify-js/compare/aws-amplify-angular@4.1.5...aws-amplify-angular@4.1.6) (2020-02-14) **Note:** Version bump only for package aws-amplify-angular diff --git a/packages/aws-amplify-angular/package.json b/packages/aws-amplify-angular/package.json index 27da3948a87..ba0a9a4897c 100644 --- a/packages/aws-amplify-angular/package.json +++ b/packages/aws-amplify-angular/package.json @@ -1,6 +1,6 @@ { "name": "aws-amplify-angular", - "version": "4.1.6", + "version": "4.1.7", "description": "AWS Amplify Angular Components", "main": "bundles/aws-amplify-angular.umd.js", "module": "dist/index.js", @@ -39,7 +39,7 @@ "@types/zen-observable": "^0.5.3", "angular2-template-loader": "^0.6.2", "awesome-typescript-loader": "^4.0.1", - "aws-amplify": "^2.2.5", + "aws-amplify": "^2.2.6", "babel-core": "^6.26.3", "babel-plugin-lodash": "^3.3.4", "babel-preset-env": "^1.7.0", diff --git a/packages/aws-amplify-react/CHANGELOG.md b/packages/aws-amplify-react/CHANGELOG.md index eb5b8a08d26..f4d243485ac 100644 --- a/packages/aws-amplify-react/CHANGELOG.md +++ b/packages/aws-amplify-react/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [3.1.7](https://github.com/aws-amplify/amplify-js/compare/aws-amplify-react@3.1.6...aws-amplify-react@3.1.7) (2020-02-28) + +**Note:** Version bump only for package aws-amplify-react + + + + + ## [3.1.6](https://github.com/aws-amplify/amplify-js/compare/aws-amplify-react@3.1.5...aws-amplify-react@3.1.6) (2020-02-14) diff --git a/packages/aws-amplify-react/package.json b/packages/aws-amplify-react/package.json index 0b029dc0966..02dfaaca322 100644 --- a/packages/aws-amplify-react/package.json +++ b/packages/aws-amplify-react/package.json @@ -1,6 +1,6 @@ { "name": "aws-amplify-react", - "version": "3.1.6", + "version": "3.1.7", "description": "AWS Amplify is a JavaScript library for Frontend and mobile developers building cloud-enabled applications.", "main": "./lib/index.js", "module": "./lib-esm/index.js", @@ -25,7 +25,7 @@ "@types/enzyme-adapter-react-16": "^1.0.3", "@types/react": "^16.0.41", "@types/react-dom": "^16.0.11", - "aws-amplify": "^2.2.5", + "aws-amplify": "^2.2.6", "enzyme": "^3.1.0", "enzyme-adapter-react-16": "^1.0.3", "enzyme-to-json": "^3.2.1", diff --git a/packages/aws-amplify/CHANGELOG.md b/packages/aws-amplify/CHANGELOG.md index c9a3ace6c69..201375c7f9f 100644 --- a/packages/aws-amplify/CHANGELOG.md +++ b/packages/aws-amplify/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.2.6](https://github.com/aws-amplify/amplify-js/compare/aws-amplify@2.2.5...aws-amplify@2.2.6) (2020-02-28) + +**Note:** Version bump only for package aws-amplify + + + + + ## [2.2.5](https://github.com/aws-amplify/amplify-js/compare/aws-amplify@2.2.4...aws-amplify@2.2.5) (2020-02-14) **Note:** Version bump only for package aws-amplify diff --git a/packages/aws-amplify/package.json b/packages/aws-amplify/package.json index 2d34ea822b9..53d69956943 100644 --- a/packages/aws-amplify/package.json +++ b/packages/aws-amplify/package.json @@ -1,6 +1,6 @@ { "name": "aws-amplify", - "version": "2.2.5", + "version": "2.2.6", "description": "AWS Amplify is a JavaScript library for Frontend and mobile developers building cloud-enabled applications.", "main": "./lib/index.js", "module": "./lib-esm/index.js", @@ -33,16 +33,16 @@ }, "homepage": "https://aws-amplify.github.io/", "dependencies": { - "@aws-amplify/analytics": "^2.2.5", - "@aws-amplify/api": "^2.1.5", - "@aws-amplify/auth": "^2.1.5", - "@aws-amplify/cache": "^2.1.5", - "@aws-amplify/core": "^2.2.4", - "@aws-amplify/interactions": "^2.1.5", - "@aws-amplify/predictions": "^2.1.5", - "@aws-amplify/pubsub": "^2.1.6", - "@aws-amplify/storage": "^2.2.0", + "@aws-amplify/analytics": "^2.2.6", + "@aws-amplify/api": "^2.1.6", + "@aws-amplify/auth": "^2.1.6", + "@aws-amplify/cache": "^2.1.6", + "@aws-amplify/core": "^2.2.5", + "@aws-amplify/interactions": "^2.1.6", + "@aws-amplify/predictions": "^2.1.6", + "@aws-amplify/pubsub": "^2.1.7", + "@aws-amplify/storage": "^2.2.1", "@aws-amplify/ui": "^1.1.5", - "@aws-amplify/xr": "^1.1.5" + "@aws-amplify/xr": "^1.1.6" } } diff --git a/packages/cache/CHANGELOG.md b/packages/cache/CHANGELOG.md index b0477c4bbd9..d0c076603f9 100644 --- a/packages/cache/CHANGELOG.md +++ b/packages/cache/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.1.6](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/cache@2.1.5...@aws-amplify/cache@2.1.6) (2020-02-28) + +**Note:** Version bump only for package @aws-amplify/cache + + + + + ## [2.1.5](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/cache@2.1.3...@aws-amplify/cache@2.1.5) (2020-02-07) diff --git a/packages/cache/package.json b/packages/cache/package.json index 110a8415547..b2e793efffc 100644 --- a/packages/cache/package.json +++ b/packages/cache/package.json @@ -1,6 +1,6 @@ { "name": "@aws-amplify/cache", - "version": "2.1.5", + "version": "2.1.6", "description": "Cache category of aws-amplify", "main": "./lib/index.js", "module": "./lib-esm/index.js", @@ -34,7 +34,7 @@ }, "homepage": "https://aws-amplify.github.io/", "dependencies": { - "@aws-amplify/core": "^2.2.4" + "@aws-amplify/core": "^2.2.5" }, "jest": { "globals": { diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index e687a499daa..03f05a764b7 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.2.5](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/core@2.2.4...@aws-amplify/core@2.2.5) (2020-02-28) + +**Note:** Version bump only for package @aws-amplify/core + + + + + ## [2.2.4](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/core@2.2.2...@aws-amplify/core@2.2.4) (2020-02-07) diff --git a/packages/core/package.json b/packages/core/package.json index 9d8e271a02c..37d07e657d1 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@aws-amplify/core", - "version": "2.2.4", + "version": "2.2.5", "description": "Core category of aws-amplify", "main": "./lib/index.js", "module": "./lib-esm/index.js", @@ -37,9 +37,9 @@ }, "homepage": "https://aws-amplify.github.io/", "devDependencies": { + "@react-native-community/netinfo": "4.7.0", "find": "^0.2.7", "prepend-file": "^1.3.1", - "@react-native-community/netinfo": "4.7.0", "react-native": "0.59.0" }, "dependencies": { diff --git a/packages/datastore/CHANGELOG.md b/packages/datastore/CHANGELOG.md index f07f7f4c6e5..733a76ab505 100644 --- a/packages/datastore/CHANGELOG.md +++ b/packages/datastore/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.8](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/datastore@1.0.7...@aws-amplify/datastore@1.0.8) (2020-02-28) + +**Note:** Version bump only for package @aws-amplify/datastore + + + + + ## [1.0.7](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/datastore@1.0.6...@aws-amplify/datastore@1.0.7) (2020-02-14) **Note:** Version bump only for package @aws-amplify/datastore diff --git a/packages/datastore/package.json b/packages/datastore/package.json index fe45cb6ff90..b49e39971ba 100644 --- a/packages/datastore/package.json +++ b/packages/datastore/package.json @@ -1,6 +1,6 @@ { "name": "@aws-amplify/datastore", - "version": "1.0.7", + "version": "1.0.8", "description": "AppSyncLocal support for aws-amplify", "main": "./lib/index.js", "module": "./lib-esm/index.js", @@ -35,9 +35,9 @@ "fake-indexeddb": "3.0.0" }, "dependencies": { - "@aws-amplify/api": "^2.1.5", - "@aws-amplify/core": "^2.2.4", - "@aws-amplify/pubsub": "^2.1.6", + "@aws-amplify/api": "^2.1.6", + "@aws-amplify/core": "^2.2.5", + "@aws-amplify/pubsub": "^2.1.7", "idb": "4.0.4", "immer": "3.1.3", "uuid": "3.3.2", diff --git a/packages/interactions/CHANGELOG.md b/packages/interactions/CHANGELOG.md index d175ebe074a..59286f89868 100644 --- a/packages/interactions/CHANGELOG.md +++ b/packages/interactions/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.1.6](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/interactions@2.1.5...@aws-amplify/interactions@2.1.6) (2020-02-28) + +**Note:** Version bump only for package @aws-amplify/interactions + + + + + ## [2.1.5](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/interactions@2.1.3...@aws-amplify/interactions@2.1.5) (2020-02-07) diff --git a/packages/interactions/package.json b/packages/interactions/package.json index 1054efc6853..9d1a35e680c 100644 --- a/packages/interactions/package.json +++ b/packages/interactions/package.json @@ -1,6 +1,6 @@ { "name": "@aws-amplify/interactions", - "version": "2.1.5", + "version": "2.1.6", "description": "Interactions category of aws-amplify", "main": "./lib/index.js", "module": "./lib-esm/index.js", @@ -34,7 +34,7 @@ }, "homepage": "https://aws-amplify.github.io/", "dependencies": { - "@aws-amplify/core": "^2.2.4" + "@aws-amplify/core": "^2.2.5" }, "jest": { "globals": { diff --git a/packages/predictions/CHANGELOG.md b/packages/predictions/CHANGELOG.md index 18ebab8db83..e7814fbefc1 100644 --- a/packages/predictions/CHANGELOG.md +++ b/packages/predictions/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.1.6](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/predictions@2.1.5...@aws-amplify/predictions@2.1.6) (2020-02-28) + +**Note:** Version bump only for package @aws-amplify/predictions + + + + + ## [2.1.5](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/predictions@2.1.3...@aws-amplify/predictions@2.1.5) (2020-02-07) diff --git a/packages/predictions/package.json b/packages/predictions/package.json index 6b91ce6396b..4d6bf367054 100644 --- a/packages/predictions/package.json +++ b/packages/predictions/package.json @@ -1,6 +1,6 @@ { "name": "@aws-amplify/predictions", - "version": "2.1.5", + "version": "2.1.6", "description": "Machine learning category of aws-amplify", "main": "./lib/index.js", "module": "./lib-esm/index.js", @@ -33,8 +33,8 @@ }, "homepage": "https://aws-amplify.github.io/", "dependencies": { - "@aws-amplify/core": "^2.2.4", - "@aws-amplify/storage": "^2.2.0", + "@aws-amplify/core": "^2.2.5", + "@aws-amplify/storage": "^2.2.1", "@aws-sdk/eventstream-marshaller": "0.1.0-preview.2", "@aws-sdk/util-utf8-node": "0.1.0-preview.1", "uuid": "^3.2.1" diff --git a/packages/pubsub/CHANGELOG.md b/packages/pubsub/CHANGELOG.md index 41416c54739..dbc59f5f15b 100644 --- a/packages/pubsub/CHANGELOG.md +++ b/packages/pubsub/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.1.7](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/pubsub@2.1.6...@aws-amplify/pubsub@2.1.7) (2020-02-28) + +**Note:** Version bump only for package @aws-amplify/pubsub + + + + + ## [2.1.6](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/pubsub@2.1.5...@aws-amplify/pubsub@2.1.6) (2020-02-14) **Note:** Version bump only for package @aws-amplify/pubsub diff --git a/packages/pubsub/package.json b/packages/pubsub/package.json index 420816525f4..5b8a44140fb 100644 --- a/packages/pubsub/package.json +++ b/packages/pubsub/package.json @@ -1,6 +1,6 @@ { "name": "@aws-amplify/pubsub", - "version": "2.1.6", + "version": "2.1.7", "description": "Pubsub category of aws-amplify", "main": "./lib/index.js", "module": "./lib-esm/index.js", @@ -38,9 +38,9 @@ "cpx": "^1.5.0" }, "dependencies": { - "@aws-amplify/auth": "^2.1.5", - "@aws-amplify/cache": "^2.1.5", - "@aws-amplify/core": "^2.2.4", + "@aws-amplify/auth": "^2.1.6", + "@aws-amplify/cache": "^2.1.6", + "@aws-amplify/core": "^2.2.5", "graphql": "14.0.0", "paho-mqtt": "^1.1.0", "uuid": "^3.2.1", diff --git a/packages/pushnotification/CHANGELOG.md b/packages/pushnotification/CHANGELOG.md index 2784490622e..80c0affc3f7 100644 --- a/packages/pushnotification/CHANGELOG.md +++ b/packages/pushnotification/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.1.6](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/pushnotification@2.1.5...@aws-amplify/pushnotification@2.1.6) (2020-02-28) + +**Note:** Version bump only for package @aws-amplify/pushnotification + + + + + ## [2.1.5](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/pushnotification@2.1.3...@aws-amplify/pushnotification@2.1.5) (2020-02-07) **Note:** Version bump only for package @aws-amplify/pushnotification diff --git a/packages/pushnotification/package.json b/packages/pushnotification/package.json index 927095e2350..6a3a943471a 100644 --- a/packages/pushnotification/package.json +++ b/packages/pushnotification/package.json @@ -1,6 +1,6 @@ { "name": "@aws-amplify/pushnotification", - "version": "2.1.5", + "version": "2.1.6", "description": "Push notifications category of aws-amplify", "main": "./lib/index.js", "module": "./lib/index.js", @@ -48,7 +48,7 @@ "webpack": "^3.5.5" }, "dependencies": { - "@aws-amplify/core": "^2.2.4", + "@aws-amplify/core": "^2.2.5", "@react-native-community/push-notification-ios": "1.0.3" }, "peerdependencies": { diff --git a/packages/storage/CHANGELOG.md b/packages/storage/CHANGELOG.md index f54794446cc..af115a06e85 100644 --- a/packages/storage/CHANGELOG.md +++ b/packages/storage/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.2.1](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/storage@2.2.0...@aws-amplify/storage@2.2.1) (2020-02-28) + +**Note:** Version bump only for package @aws-amplify/storage + + + + + # [2.2.0](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/storage@2.1.3...@aws-amplify/storage@2.2.0) (2020-02-07) diff --git a/packages/storage/package.json b/packages/storage/package.json index 27e7d44b7a1..33d0647a978 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -1,6 +1,6 @@ { "name": "@aws-amplify/storage", - "version": "2.2.0", + "version": "2.2.1", "description": "Storage category of aws-amplify", "main": "./lib/index.js", "module": "./lib-esm/index.js", @@ -34,7 +34,7 @@ }, "homepage": "https://aws-amplify.github.io/", "dependencies": { - "@aws-amplify/core": "^2.2.4" + "@aws-amplify/core": "^2.2.5" }, "jest": { "globals": { diff --git a/packages/xr/CHANGELOG.md b/packages/xr/CHANGELOG.md index e4972009489..9b416436290 100644 --- a/packages/xr/CHANGELOG.md +++ b/packages/xr/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.6](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/xr@1.1.5...@aws-amplify/xr@1.1.6) (2020-02-28) + +**Note:** Version bump only for package @aws-amplify/xr + + + + + ## [1.1.5](https://github.com/aws-amplify/amplify-js/compare/@aws-amplify/xr@1.1.3...@aws-amplify/xr@1.1.5) (2020-02-07) diff --git a/packages/xr/package.json b/packages/xr/package.json index bcea27bcd54..08d47bb2592 100644 --- a/packages/xr/package.json +++ b/packages/xr/package.json @@ -1,6 +1,6 @@ { "name": "@aws-amplify/xr", - "version": "1.1.5", + "version": "1.1.6", "description": "XR category of aws-amplify", "main": "./lib/index.js", "module": "./lib-esm/index.js", @@ -34,7 +34,7 @@ }, "homepage": "https://aws-amplify.github.io/", "dependencies": { - "@aws-amplify/core": "^2.2.4" + "@aws-amplify/core": "^2.2.5" }, "jest": { "globals": { From fedf0b331cb8e2263f0c7b7ae57bac5d8f69c888 Mon Sep 17 00:00:00 2001 From: Ivan Artemiev <29709626+iartemiev@users.noreply.github.com> Date: Fri, 28 Feb 2020 10:43:42 -0500 Subject: [PATCH 18/25] fix(core): move react-native dependency from dev --- packages/core/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 37d07e657d1..1fcbb1f1187 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -37,7 +37,6 @@ }, "homepage": "https://aws-amplify.github.io/", "devDependencies": { - "@react-native-community/netinfo": "4.7.0", "find": "^0.2.7", "prepend-file": "^1.3.1", "react-native": "0.59.0" @@ -45,7 +44,8 @@ "dependencies": { "aws-sdk": "2.518.0", "url": "^0.11.0", - "zen-observable": "^0.8.6" + "zen-observable": "^0.8.6", + "@react-native-community/netinfo": "4.7.0" }, "jest": { "globals": { From b2a22e53532663328b200761ce1ecf35495acbd1 Mon Sep 17 00:00:00 2001 From: Ivan Artemiev <29709626+iartemiev@users.noreply.github.com> Date: Fri, 28 Feb 2020 12:55:23 -0500 Subject: [PATCH 19/25] fix(core): revert dep addition. Add to peer and devDeps --- packages/core/package.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 1fcbb1f1187..d3a023c7d36 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -39,13 +39,16 @@ "devDependencies": { "find": "^0.2.7", "prepend-file": "^1.3.1", - "react-native": "0.59.0" + "react-native": "0.59.0", + "@react-native-community/netinfo": "4.7.0" }, "dependencies": { "aws-sdk": "2.518.0", "url": "^0.11.0", - "zen-observable": "^0.8.6", - "@react-native-community/netinfo": "4.7.0" + "zen-observable": "^0.8.6" + }, + "peerDependencies": { + "@react-native-community/netinfo": "^5.5.0" }, "jest": { "globals": { From bbd02714aa84dc6bfcd8b3c4b05dbb285b0bda2c Mon Sep 17 00:00:00 2001 From: Ivan Artemiev <29709626+iartemiev@users.noreply.github.com> Date: Fri, 28 Feb 2020 17:45:35 -0500 Subject: [PATCH 20/25] ci: Add React Native integration testing with Detox (#5007) --- .circleci/config.yml | 137 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 134 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a6879a51cb3..d4ef07c53f1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ # # Check https://circleci.com/docs/2.0/language-javascript/ for more details # -version: 2 +version: 2.1 machine: environment: PATH: '${PATH}:${HOME}/${CIRCLE_PROJECT_REPONAME}/node_modules/.bin' @@ -14,6 +14,26 @@ defaults: &defaults ## this enables colors in the output TERM: xterm +defaults_rn: &defaults_rn + macos: + xcode: '11.3.1' + working_directory: ~/amplify-js-samples-staging + +commands: + restore_pods: + steps: + - restore_cache: + keys: + - v1-storage-app-pods-{{ checksum "ios/Podfile.lock" }} + - v1-storage-app-pods- + + save_pods: + steps: + - save_cache: + key: v1-storage-app-pods-{{ checksum "ios/Podfile.lock" }} + paths: + - ios/Pods + jobs: build: <<: *defaults @@ -23,8 +43,8 @@ jobs: - checkout - run: yarn config set workspaces-experimental true - run: yarn - - run: yarn run bootstrap - - run: yarn run build + - run: yarn bootstrap + - run: yarn build - save_cache: key: amplify-ssh-deps-{{ .Branch }} @@ -250,6 +270,108 @@ jobs: path: amplify-js-samples-staging/cypress/videos - store_artifacts: path: amplify-js-samples-staging/cypress/screenshots + + integ_rn_ios_storage: + <<: *defaults_rn + working_directory: ~/amplify-js-samples-staging/samples/react-native/storage/StorageApp + steps: + - attach_workspace: + at: ~/ + - run: + name: Yarn Install + command: yarn install --non-interactive --no-lockfile + # Metro Bundler doesn't work with linked packages so we're copying them from amplify-js + # TODO: utilize Verdaccio for this instead + - run: + name: 'Link aws-amplify' + command: | + cp -rf ~/amplify-js/packages/aws-amplify/dist ./node_modules/aws-amplify/dist + cp -rf ~/amplify-js/packages/aws-amplify/lib ./node_modules/aws-amplify/lib + cp -rf ~/amplify-js/packages/aws-amplify/lib-esm ./node_modules/aws-amplify/lib-esm + + cp -rf ~/amplify-js/packages/amazon-cognito-identity-js/dist ./node_modules/amazon-cognito-identity-js/dist + cp -rf ~/amplify-js/packages/amazon-cognito-identity-js/lib ./node_modules/amazon-cognito-identity-js/lib + + cp -rf ~/amplify-js/packages/analytics/dist ./node_modules/@aws-amplify/analytics/dist + cp -rf ~/amplify-js/packages/analytics/lib ./node_modules/@aws-amplify/analytics/lib + cp -rf ~/amplify-js/packages/analytics/lib-esm ./node_modules/@aws-amplify/analytics/lib-esm + + cp -rf ~/amplify-js/packages/api/dist ./node_modules/@aws-amplify/api/dist + cp -rf ~/amplify-js/packages/api/lib ./node_modules/@aws-amplify/api/lib + cp -rf ~/amplify-js/packages/api/lib-esm ./node_modules/@aws-amplify/api/lib-esm + + cp -rf ~/amplify-js/packages/auth/dist ./node_modules/@aws-amplify/auth/dist + cp -rf ~/amplify-js/packages/auth/lib ./node_modules/@aws-amplify/auth/lib + cp -rf ~/amplify-js/packages/auth/lib-esm ./node_modules/@aws-amplify/auth/lib-esm + + cp -rf ~/amplify-js/packages/cache/dist ./node_modules/@aws-amplify/cache/dist + cp -rf ~/amplify-js/packages/cache/lib ./node_modules/@aws-amplify/cache/lib + cp -rf ~/amplify-js/packages/cache/lib-esm ./node_modules/@aws-amplify/cache/lib-esm + + cp -rf ~/amplify-js/packages/core/dist ./node_modules/@aws-amplify/core/dist + cp -rf ~/amplify-js/packages/core/lib ./node_modules/@aws-amplify/core/lib + cp -rf ~/amplify-js/packages/core/lib-esm ./node_modules/@aws-amplify/core/lib-esm + + cp -rf ~/amplify-js/packages/interactions/dist ./node_modules/@aws-amplify/interactions/dist + cp -rf ~/amplify-js/packages/interactions/lib ./node_modules/@aws-amplify/interactions/lib + cp -rf ~/amplify-js/packages/interactions/lib-esm ./node_modules/@aws-amplify/interactions/lib-esm + + cp -rf ~/amplify-js/packages/predictions/dist ./node_modules/@aws-amplify/predictions/dist + cp -rf ~/amplify-js/packages/predictions/lib ./node_modules/@aws-amplify/predictions/lib + cp -rf ~/amplify-js/packages/predictions/lib-esm ./node_modules/@aws-amplify/predictions/lib-esm + + cp -rf ~/amplify-js/packages/pubsub/dist ./node_modules/@aws-amplify/pubsub/dist + cp -rf ~/amplify-js/packages/pubsub/lib ./node_modules/@aws-amplify/pubsub/lib + cp -rf ~/amplify-js/packages/pubsub/lib-esm ./node_modules/@aws-amplify/pubsub/lib-esm + + cp -rf ~/amplify-js/packages/storage/dist ./node_modules/@aws-amplify/storage/dist + cp -rf ~/amplify-js/packages/storage/lib ./node_modules/@aws-amplify/storage/lib + cp -rf ~/amplify-js/packages/storage/lib-esm ./node_modules/@aws-amplify/storage/lib-esm + + cp -rf ~/amplify-js/packages/amplify-ui/dist ./node_modules/@aws-amplify/ui/dist + cp -rf ~/amplify-js/packages/amplify-ui/lib ./node_modules/@aws-amplify/ui/lib + + cp -rf ~/amplify-js/packages/xr/dist ./node_modules/@aws-amplify/xr/dist + cp -rf ~/amplify-js/packages/xr/lib ./node_modules/@aws-amplify/xr/lib + cp -rf ~/amplify-js/packages/xr/lib-esm ./node_modules/@aws-amplify/xr/lib-esm + + - restore_pods + - run: + name: Install CocoaPods + command: | + cd ios + pod install + - save_pods + - run: + background: true + command: xcrun simctl boot "iPhone 11" || true + name: Start iOS simulator (background) + - run: + background: true + command: yarn start + name: Start Metro Packager (background) + - run: + name: Configure Detox + environment: + HOMEBREW_NO_AUTO_UPDATE: 1 + command: | + brew tap wix/brew + brew install applesimutils + yarn global add detox-cli + - run: + name: Detox Build + command: detox build -c ios.sim.debug + - run: + environment: + JEST_JUNIT_OUTPUT_DIR: 'reports/junit' + JEST_JUNIT_OUTPUT_NAME: 'detox-test-results.xml' + name: Detox Test + command: detox test -c ios.sim.debug -u + - store_test_results: + path: reports/junit + - store_artifacts: + path: reports/junit + deploy: <<: *defaults working_directory: ~/amplify-js @@ -328,6 +450,15 @@ workflows: - 1.0-stable requires: - integ_setup + - integ_rn_ios_storage: + filters: + branches: + only: + - release + - master + - 1.0-stable + requires: + - integ_setup - deploy: filters: branches: From 8f6acca5fd1da33dced154d6286700668fb83106 Mon Sep 17 00:00:00 2001 From: Ivan Artemiev <29709626+iartemiev@users.noreply.github.com> Date: Fri, 28 Feb 2020 18:18:19 -0500 Subject: [PATCH 21/25] Make deploy wait on integ_rn_ios_storage (#5009) --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index d4ef07c53f1..838e5c6db6e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -473,3 +473,4 @@ workflows: - integ_react_auth - integ_angular_auth - integ_vue_auth + - integ_rn_ios_storage From 44b4faf294088cee533c8a5a6ff3b3d1334162c3 Mon Sep 17 00:00:00 2001 From: Jens Bodal Date: Tue, 3 Mar 2020 14:53:55 -0800 Subject: [PATCH 22/25] feat(@aws-amplify/api): pass additionalHeaders to graphql function (#5001) Additional headers are merged **after** merging in headers set at config time. Additional headers will overwrite any existing values and merge the rest. --- packages/api/__tests__/API-test.ts | 94 ++++++++++++++++++++++++++++++ packages/api/src/API.ts | 10 +++- 2 files changed, 101 insertions(+), 3 deletions(-) diff --git a/packages/api/__tests__/API-test.ts b/packages/api/__tests__/API-test.ts index 044d1608ed3..4fa93305e1e 100644 --- a/packages/api/__tests__/API-test.ts +++ b/packages/api/__tests__/API-test.ts @@ -954,6 +954,100 @@ describe('API test', () => { expect(spyon).toBeCalledWith(url, init); }); + + test('happy case query with additionalHeaders', async () => { + const spyonAuth = jest + .spyOn(Credentials, 'get') + .mockImplementationOnce(() => { + return new Promise((res, rej) => { + res('cred'); + }); + }); + + const spyon = jest + .spyOn(RestClient.prototype, 'post') + .mockImplementationOnce((url, init) => { + return new Promise((res, rej) => { + res({}); + }); + }); + + const api = new API(config); + const url = 'https://appsync.amazonaws.com', + region = 'us-east-2', + apiKey = 'secret_api_key', + variables = { id: '809392da-ec91-4ef0-b219-5238a8f942b2' }; + api.configure({ + aws_appsync_graphqlEndpoint: url, + aws_appsync_region: region, + aws_appsync_authenticationType: 'API_KEY', + aws_appsync_apiKey: apiKey, + graphql_headers: async () => + Promise.resolve({ + someHeaderSetAtConfigThatWillBeOverridden: 'initialValue', + someOtherHeaderSetAtConfig: 'expectedValue', + }), + }); + const GetEvent = `query GetEvent($id: ID! $nextToken: String) { + getEvent(id: $id) { + id + name + where + when + description + comments(nextToken: $nextToken) { + items { + commentId + content + createdAt + } + } + } + }`; + + const doc = parse(GetEvent); + const query = print(doc); + + const headers = { + Authorization: null, + 'X-Api-Key': apiKey, + 'x-amz-user-agent': Constants.userAgent, + }; + + const body = { + query, + variables, + }; + + const init = { + headers, + body, + signerServiceInfo: { + service: 'appsync', + region, + }, + }; + + const additionalHeaders = { + someAddtionalHeader: 'foo', + someHeaderSetAtConfigThatWillBeOverridden: 'expectedValue', + }; + + await api.graphql( + graphqlOperation(GetEvent, variables), + additionalHeaders + ); + + expect(spyon).toBeCalledWith(url, { + ...init, + headers: { + someAddtionalHeader: 'foo', + someHeaderSetAtConfigThatWillBeOverridden: 'expectedValue', + ...init.headers, + someOtherHeaderSetAtConfig: 'expectedValue', + }, + }); + }); }); describe('configure test', () => { diff --git a/packages/api/src/API.ts b/packages/api/src/API.ts index 6f9da9843d7..bab9641de4c 100644 --- a/packages/api/src/API.ts +++ b/packages/api/src/API.ts @@ -347,9 +347,13 @@ export default class APIClass { * Executes a GraphQL operation * * @param {GraphQLOptions} GraphQL Options + * @param {object} additionalHeaders headers to merge in after any `graphql_headers` set in the config * @returns {Promise | Observable} */ - graphql({ query: paramQuery, variables = {}, authMode }: GraphQLOptions) { + graphql( + { query: paramQuery, variables = {}, authMode }: GraphQLOptions, + addtionalHeaders?: { [key: string]: string } + ) { const query = typeof paramQuery === 'string' ? parse(paramQuery) @@ -365,7 +369,7 @@ export default class APIClass { switch (operationType) { case 'query': case 'mutation': - return this._graphql({ query, variables, authMode }); + return this._graphql({ query, variables, authMode }, addtionalHeaders); case 'subscription': return this._graphqlSubscribe({ query, @@ -399,8 +403,8 @@ export default class APIClass { (customEndpointRegion ? await this._headerBasedAuth(authMode) : { Authorization: null })), - ...additionalHeaders, ...(await graphql_headers({ query, variables })), + ...additionalHeaders, ...(!customGraphqlEndpoint && { [USER_AGENT_HEADER]: Constants.userAgent, }), From 69d9fd46d4f935cb6568f10d6598a94b36b1a51f Mon Sep 17 00:00:00 2001 From: Jens Bodal Date: Tue, 3 Mar 2020 15:33:35 -0800 Subject: [PATCH 23/25] chore(@aws-amplify/api): fix non-breaking typo in function (#5034) --- packages/api/src/API.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/api/src/API.ts b/packages/api/src/API.ts index bab9641de4c..75befe47542 100644 --- a/packages/api/src/API.ts +++ b/packages/api/src/API.ts @@ -352,7 +352,7 @@ export default class APIClass { */ graphql( { query: paramQuery, variables = {}, authMode }: GraphQLOptions, - addtionalHeaders?: { [key: string]: string } + additionalHeaders?: { [key: string]: string } ) { const query = typeof paramQuery === 'string' @@ -369,7 +369,7 @@ export default class APIClass { switch (operationType) { case 'query': case 'mutation': - return this._graphql({ query, variables, authMode }, addtionalHeaders); + return this._graphql({ query, variables, authMode }, additionalHeaders); case 'subscription': return this._graphqlSubscribe({ query, From fdca5541372662ffa1d932b665c481a78e4ccdc7 Mon Sep 17 00:00:00 2001 From: Manuel Iglesias Date: Tue, 3 Mar 2020 16:17:35 -0800 Subject: [PATCH 24/25] fix(@aws-amplify/datastore): Fix query and delete types (#5032) Fixes #4827 --- packages/datastore/src/datastore/datastore.ts | 30 ++++++++++++++----- packages/datastore/src/predicates/index.ts | 9 ++++-- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/packages/datastore/src/datastore/datastore.ts b/packages/datastore/src/datastore/datastore.ts index 8c24accb48e..f138cde7b12 100644 --- a/packages/datastore/src/datastore/datastore.ts +++ b/packages/datastore/src/datastore/datastore.ts @@ -2,7 +2,11 @@ import { ConsoleLogger as Logger } from '@aws-amplify/core'; import { Draft, immerable, produce, setAutoFreeze } from 'immer'; import { v1 as uuid1, v4 as uuid4 } from 'uuid'; import Observable from 'zen-observable-ts'; -import { isPredicatesAll, ModelPredicateCreator } from '../predicates'; +import { + isPredicatesAll, + ModelPredicateCreator, + PredicateAll, +} from '../predicates'; import Storage from '../storage/storage'; import { SyncEngine } from '../sync'; import { @@ -368,11 +372,11 @@ const remove: { ): Promise; ( modelConstructor: PersistentModelConstructor, - condition: ProducerModelPredicate + condition: ProducerModelPredicate | typeof PredicateAll ): Promise; } = async ( modelOrConstructor: T | PersistentModelConstructor, - idOrCriteria?: string | ProducerModelPredicate + idOrCriteria?: string | ProducerModelPredicate | typeof PredicateAll ) => { await start(); let condition: ModelPredicate; @@ -403,7 +407,11 @@ const remove: { } else { condition = ModelPredicateCreator.createFromExisting( getModelDefinition(modelConstructor), - idOrCriteria + /** + * idOrCriteria is always a ProducerModelPredicate, never a symbol. + * The symbol is used only for typing purposes. e.g. see Predicates.ALL + */ + idOrCriteria as ProducerModelPredicate ); if (!condition || !ModelPredicateCreator.isValidPredicate(condition)) { @@ -530,12 +538,12 @@ const query: { ): Promise; ( modelConstructor: PersistentModelConstructor, - criteria?: ProducerModelPredicate, + criteria?: ProducerModelPredicate | typeof PredicateAll, pagination?: PaginationInput ): Promise; } = async ( modelConstructor: PersistentModelConstructor, - idOrCriteria?: string | ProducerModelPredicate, + idOrCriteria?: string | ProducerModelPredicate | typeof PredicateAll, pagination?: PaginationInput ) => { await start(); @@ -564,11 +572,17 @@ const query: { return undefined; } + /** + * idOrCriteria is always a ProducerModelPredicate, never a symbol. + * The symbol is used only for typing purposes. e.g. see Predicates.ALL + */ + const criteria = idOrCriteria as ProducerModelPredicate; + // Predicates.ALL means "all records", so no predicate (undefined) - const predicate = !isPredicatesAll(idOrCriteria) + const predicate = !isPredicatesAll(criteria) ? ModelPredicateCreator.createFromExisting( getModelDefinition(modelConstructor), - idOrCriteria + criteria ) : undefined; diff --git a/packages/datastore/src/predicates/index.ts b/packages/datastore/src/predicates/index.ts index ed9e24fb486..14c9b3d7baa 100644 --- a/packages/datastore/src/predicates/index.ts +++ b/packages/datastore/src/predicates/index.ts @@ -12,17 +12,20 @@ import { exhaustiveCheck } from '../util'; const predicatesAllSet = new WeakSet>(); -export function isPredicatesAll(predicate: ProducerModelPredicate) { +export function isPredicatesAll(predicate: any) { return predicatesAllSet.has(predicate); } +// This symbol is not used at runtime, only its type (unique symbol) +export const PredicateAll = Symbol('A predicate that matches all records'); + export class Predicates { - public static get ALL() { + public static get ALL(): typeof PredicateAll { const predicate = >(c => c); predicatesAllSet.add(predicate); - return predicate; + return (predicate); } } From dae4824055dce2112c0815750eb19a241f2b39e3 Mon Sep 17 00:00:00 2001 From: Manuel Iglesias Date: Wed, 4 Mar 2020 15:53:11 -0800 Subject: [PATCH 25/25] Fix(@aws-amplify/interactions) fixes 4750 to properly use the spread operator (#4806) --- packages/aws-amplify-react/src/Interactions/ChatBot.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/aws-amplify-react/src/Interactions/ChatBot.tsx b/packages/aws-amplify-react/src/Interactions/ChatBot.tsx index 8c2a8996922..0c4d274c214 100644 --- a/packages/aws-amplify-react/src/Interactions/ChatBot.tsx +++ b/packages/aws-amplify-react/src/Interactions/ChatBot.tsx @@ -376,7 +376,7 @@ export class ChatBot extends Component { this.setState( { dialog: [ - ...(!clearOnComplete && this.state.dialog), + ...(clearOnComplete ? [] : this.state.dialog), message && { from: 'bot', message }, ].filter(Boolean), },