diff --git a/.gitignore b/.gitignore index 986e468a..ba28bbba 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules lib *.tgz lerna-debug.log +.npmrc diff --git a/packages/aws-appsync-react/CHANGELOG.md b/packages/aws-appsync-react/CHANGELOG.md index bbe75086..c954fd21 100644 --- a/packages/aws-appsync-react/CHANGELOG.md +++ b/packages/aws-appsync-react/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [1.2.7](https://github.com/awslabs/aws-mobile-appsync-sdk-js/compare/aws-appsync-react@1.2.6...aws-appsync-react@1.2.7) (2019-03-12) + + + + +**Note:** Version bump only for package aws-appsync-react + + +## [1.2.6](https://github.com/awslabs/aws-mobile-appsync-sdk-js/compare/aws-appsync-react@1.2.5...aws-appsync-react@1.2.6) (2019-01-11) + + + + +**Note:** Version bump only for package aws-appsync-react + ## [1.2.5](https://github.com/awslabs/aws-mobile-appsync-sdk-js/compare/aws-appsync-react@1.2.4...aws-appsync-react@1.2.5) (2018-12-12) diff --git a/packages/aws-appsync-react/package.json b/packages/aws-appsync-react/package.json index 05e6c692..d01d10d8 100644 --- a/packages/aws-appsync-react/package.json +++ b/packages/aws-appsync-react/package.json @@ -1,6 +1,6 @@ { "name": "aws-appsync-react", - "version": "1.2.5", + "version": "1.2.7", "main": "lib/index.js", "license": "SEE LICENSE IN LICENSE", "description": "AWS Mobile AppSync SDK for JavaScript - React and React Native components", @@ -27,7 +27,7 @@ "devDependencies": { "@types/graphql": "0.12.4", "@types/react": "^16.0.25", - "aws-appsync": "^1.7.0", + "aws-appsync": "^1.7.2", "react": "^16.1.1", "react-apollo": "^2.1.9", "react-native": "^0.50.3", diff --git a/packages/aws-appsync/CHANGELOG.md b/packages/aws-appsync/CHANGELOG.md index c065129d..76409409 100644 --- a/packages/aws-appsync/CHANGELOG.md +++ b/packages/aws-appsync/CHANGELOG.md @@ -3,6 +3,33 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [1.7.2](https://github.com/awslabs/aws-mobile-appsync-sdk-js/compare/aws-appsync@1.7.1...aws-appsync@1.7.2) (2019-03-12) + + +### Bug Fixes + +* **auth:** Remove temporary variables (starting with '@@') before signing ([#347](https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/347)) ([920b47d](https://github.com/awslabs/aws-mobile-appsync-sdk-js/commit/920b47d)), closes [#354](https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/354) +* **deltaSync:** Make sure query manager is initialized ([13a2dec](https://github.com/awslabs/aws-mobile-appsync-sdk-js/commit/13a2dec)), closes [#893237](https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/893237) + + + + + +## [1.7.1](https://github.com/awslabs/aws-mobile-appsync-sdk-js/compare/aws-appsync@1.7.0...aws-appsync@1.7.1) (2019-01-11) + + +### Bug Fixes + +* **deltasync:** Fix error when baseQuery is not specified ([#320](https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/320)) ([8dbe01d](https://github.com/awslabs/aws-mobile-appsync-sdk-js/commit/8dbe01d)) +* **offline-helpers:** Offline helpers types and fix issue with different options ([#329](https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/329)) ([42ac50a](https://github.com/awslabs/aws-mobile-appsync-sdk-js/commit/42ac50a)) +* **offline-helpers:** Preserve order of elements in update cache operation type ([#325](https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/325)) ([5b49946](https://github.com/awslabs/aws-mobile-appsync-sdk-js/commit/5b49946)) +* **subscriptions:** Do not retry mqtt disconnections ([#319](https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/319)) ([b933379](https://github.com/awslabs/aws-mobile-appsync-sdk-js/commit/b933379)) +* **subscriptions:** Guard against errors: null response in subscription handshake ([#337](https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/337)) ([a2035d0](https://github.com/awslabs/aws-mobile-appsync-sdk-js/commit/a2035d0)) + + + + # [1.7.0](https://github.com/awslabs/aws-mobile-appsync-sdk-js/compare/aws-appsync@1.6.0...aws-appsync@1.7.0) (2018-12-12) diff --git a/packages/aws-appsync/package.json b/packages/aws-appsync/package.json index b3c8306e..6acc5437 100644 --- a/packages/aws-appsync/package.json +++ b/packages/aws-appsync/package.json @@ -1,6 +1,6 @@ { "name": "aws-appsync", - "version": "1.7.0", + "version": "1.7.2", "main": "lib/index.js", "license": "SEE LICENSE IN LICENSE", "description": "AWS Mobile AppSync SDK for JavaScript", @@ -28,7 +28,7 @@ "apollo-link-retry": "2.2.5", "aws-sdk": "2.329.0", "debug": "2.6.9", - "graphql": "^0.11.7", + "graphql": "0.13.0", "redux": "^3.7.2", "redux-thunk": "^2.2.0", "setimmediate": "^1.0.5", diff --git a/packages/aws-appsync/src/client.ts b/packages/aws-appsync/src/client.ts index e7caf648..a0edd81c 100644 --- a/packages/aws-appsync/src/client.ts +++ b/packages/aws-appsync/src/client.ts @@ -124,7 +124,7 @@ const createLinkWithStore = (createLinkFunc = (store: Store) = }); } -type CredentialsGetter = () => (Credentials | CredentialsOptions | null) | Credentials | CredentialsOptions | null; +type CredentialsGetter = () => (Credentials | CredentialsOptions | Promise | Promise | null) | Credentials | CredentialsOptions | Promise | Promise | null; export interface AWSAppSyncClientOptions { url: string, diff --git a/packages/aws-appsync/src/deltaSync.ts b/packages/aws-appsync/src/deltaSync.ts index 8cf6703b..91f8fbf1 100644 --- a/packages/aws-appsync/src/deltaSync.ts +++ b/packages/aws-appsync/src/deltaSync.ts @@ -318,7 +318,7 @@ const effect = async ( } //#endregion - const { baseRefreshIntervalInSeconds } = baseQuery; + const { baseRefreshIntervalInSeconds } = baseQuery || { baseRefreshIntervalInSeconds: undefined }; upperBoundTimeMS = baseRefreshIntervalInSeconds ? baseRefreshIntervalInSeconds * 1000 : DEFAULT_UPPER_BOUND_TIME_MS; const skipBaseQuery = !(baseQuery && baseQuery.query) || (baseLastSyncTimestamp @@ -336,7 +336,7 @@ const effect = async ( query, variables, }); - cacheProxy.writeQuery({ query, data: result.data }); + cacheProxy.writeQuery({ query, variables, data: result.data }); if (typeof update === 'function') { tryFunctionOrLogError(() => { @@ -417,6 +417,7 @@ const effect = async ( boundSaveSnapshot(store, client.cache); + client.initQueryManager(); const dataStore = client.queryManager.dataStore; const enqueuedActionsFilter = [mutationsConfig.enqueueAction]; enquededMutations diff --git a/packages/aws-appsync/src/helpers/offline.ts b/packages/aws-appsync/src/helpers/offline.ts index 60d1be98..5f0b2c80 100644 --- a/packages/aws-appsync/src/helpers/offline.ts +++ b/packages/aws-appsync/src/helpers/offline.ts @@ -87,9 +87,9 @@ export type CacheUpdateQuery = QueryWithVariables | DocumentNode; export type CacheUpdatesDefinitions = { [key in CacheOperationTypes]?: CacheUpdateQuery | CacheUpdateQuery[] -}; +} | CacheUpdateQuery | CacheUpdateQuery[]; -export type CacheUpdatesOptions = (variables?: object) => CacheUpdatesDefinitions | CacheUpdatesDefinitions; +export type CacheUpdatesOptions = ((variables?: object) => CacheUpdatesDefinitions) | CacheUpdatesDefinitions; /** * Builds a SubscribeToMoreOptions object ready to be used by Apollo's subscribeToMore() to automatically update the query result in the @@ -171,9 +171,14 @@ const getOpTypeQueriesMap = (cacheUpdateQuery: CacheUpdatesOptions, variables): const cacheUpdateQueryVal = typeof cacheUpdateQuery === 'function' ? cacheUpdateQuery(variables) : cacheUpdateQuery || {}; - const opTypeQueriesMap = isDocument(cacheUpdateQueryVal) ? - { [CacheOperationTypes.AUTO]: [].concat(cacheUpdateQueryVal) } as CacheUpdatesDefinitions : - cacheUpdateQueryVal; + + let opTypeQueriesMap = cacheUpdateQueryVal; + + if (isDocument(cacheUpdateQueryVal) || + isDocument((cacheUpdateQueryVal as QueryWithVariables).query) || + Array.isArray(cacheUpdateQuery)) { + opTypeQueriesMap = { [CacheOperationTypes.AUTO]: [].concat(cacheUpdateQueryVal) } as CacheUpdatesDefinitions; + } return opTypeQueriesMap; }; diff --git a/packages/aws-appsync/src/link/auth-link.ts b/packages/aws-appsync/src/link/auth-link.ts index a4beb560..a4562137 100644 --- a/packages/aws-appsync/src/link/auth-link.ts +++ b/packages/aws-appsync/src/link/auth-link.ts @@ -36,7 +36,7 @@ export class AuthLink extends ApolloLink { private link: ApolloLink; /** - * + * * @param {*} options */ constructor(options) { @@ -167,7 +167,7 @@ export const authLink = ({ url, region, auth: { type = AUTH_TYPE.NONE, credentia const formatAsRequest = ({ operationName, variables, query }, options) => { const body = { operationName, - variables, + variables: removeTemporaryVariables(variables), query: print(query) }; @@ -182,3 +182,15 @@ const formatAsRequest = ({ operationName, variables, query }, options) => { }, }; } + +/** + * Removes all temporary variables (starting with '@@') so that the signature matches the final request. + */ +const removeTemporaryVariables = (variables: any) => + Object.keys(variables) + .filter(key => !key.startsWith("@@")) + .reduce((acc, key) => { + acc[key] = variables[key]; + return acc; + }, {}); + diff --git a/packages/aws-appsync/src/link/offline-link.ts b/packages/aws-appsync/src/link/offline-link.ts index 7aa43291..c5e92f3f 100644 --- a/packages/aws-appsync/src/link/offline-link.ts +++ b/packages/aws-appsync/src/link/offline-link.ts @@ -240,7 +240,7 @@ const effect = async ( } = store.getState(); // Restore from cache snapshot - client.cache.restore(cacheSnapshot as TCache); + // client.cache.restore(cacheSnapshot as TCache); const dataStore = client.queryManager.dataStore; diff --git a/packages/aws-appsync/src/link/retry-link.ts b/packages/aws-appsync/src/link/retry-link.ts index a08bfeb8..159b7e26 100644 --- a/packages/aws-appsync/src/link/retry-link.ts +++ b/packages/aws-appsync/src/link/retry-link.ts @@ -18,6 +18,7 @@ const MAX_DELAY_MS = 5 * 60 * 1000; const getDelay = count => ((2 ** count) * BASE_TIME_MS) + (JITTER_FACTOR * Math.random()); export const SKIP_RETRY_KEY = '@@skipRetry'; +export const PERMANENT_ERROR_KEY = typeof Symbol !== 'undefined' ? Symbol('permanentError') : '@@permanentError'; export const getEffectDelay = (_action: OfflineAction, retries: number) => { const delay = getDelay(retries); @@ -30,8 +31,13 @@ export const createRetryLink = (origLink: ApolloLink) => { const retryLink = new RetryLink({ attempts: (count, operation, error) => { + const { [PERMANENT_ERROR_KEY]: permanent = false } = error; const { [SKIP_RETRY_KEY]: skipRetry = false } = operation.variables; + if (permanent) { + return false; + } + if (error.statusCode >= 400 && error.statusCode < 500) { return false; } diff --git a/packages/aws-appsync/src/link/subscription-handshake-link.ts b/packages/aws-appsync/src/link/subscription-handshake-link.ts index 31a2d439..64e04ff3 100644 --- a/packages/aws-appsync/src/link/subscription-handshake-link.ts +++ b/packages/aws-appsync/src/link/subscription-handshake-link.ts @@ -13,6 +13,7 @@ import * as Paho from '../vendor/paho-mqtt'; import { ApolloError } from "apollo-client"; import { FieldNode } from "graphql"; import { getMainDefinition } from "apollo-utilities"; +import { PERMANENT_ERROR_KEY } from "./retry-link"; const logger = rootLogger.extend('subscriptions'); const mqttLogger = logger.extend('mqtt'); @@ -66,13 +67,13 @@ export class SubscriptionHandshakeLink extends ApolloLink { } = { subscription: { newSubscriptions: {}, mqttConnections: [] } }, errors = [], }: { - extensions?: { - subscription: SubscriptionExtension - }, - errors: any[] - } = subsInfo; + extensions?: { + subscription: SubscriptionExtension + }, + errors: any[] + } = subsInfo; - if (errors.length) { + if (errors && errors.length) { return new Observable(observer => { observer.error(new ApolloError({ errorMessage: 'Error during subscription handshake', @@ -170,7 +171,7 @@ export class SubscriptionHandshakeLink extends ApolloLink { if (errorCode !== 0) { topics.forEach(t => { if (this.topicObservers.has(t)) { - this.topicObservers.get(t).forEach(observer => observer.error(args)); + this.topicObservers.get(t).forEach(observer => observer.error({ ...args, [PERMANENT_ERROR_KEY]: true })); } }); } diff --git a/tutorials/react-offline-realtime-todos/README.md b/tutorials/react-offline-realtime-todos/README.md index 7ec96e04..90220814 100644 --- a/tutorials/react-offline-realtime-todos/README.md +++ b/tutorials/react-offline-realtime-todos/README.md @@ -52,7 +52,7 @@ input UpdateTodoInput { } ``` -**Save** the schema again. On the navigation bar in the left of the console, click on ``, scroll down and select the **Web** section then click **Download** and save the `AppSync.js` file somewhere for later. +**Save** the schema again. On the navigation bar in the left of the console, click on ``, scroll down and select the **Web** section then click **Download Config** and save the `aws-exports.js` file somewhere for later. ## Imports and configuration @@ -65,13 +65,13 @@ create-react-app todos && cd ./todos yarn add aws-appsync aws-appsync-react graphql-tag react-apollo ``` -Copy the `AppSync.js` file that you downloaded from the console into the `./todos/src` directory. Next add the following imports towards the top of the `App.js` file: +Copy the `aws-exports.js` file that you downloaded from the console into the `./todos/src` directory. Next add the following imports towards the top of the `App.js` file: ```javascript import AWSAppSyncClient, { buildSubscription } from 'aws-appsync'; import { Rehydrated, graphqlMutation } from 'aws-appsync-react'; -import AppSyncConfig from './AppSync'; +import awsmobile from './aws-exports'; import { ApolloProvider } from 'react-apollo'; ``` @@ -79,11 +79,11 @@ Replace everything __after__ the definition of the `` component with the ```jsx const client = new AWSAppSyncClient({ - url: AppSyncConfig.graphqlEndpoint, - region: AppSyncConfig.region, + url: awsmobile.graphqlEndpoint, + region: awsmobile.region, auth: { - type: AppSyncConfig.authenticationType, - apiKey: AppSyncConfig.apiKey + type: awsmobile.authenticationType, + apiKey: awsmobile.apiKey } })