Aws-mobile-appsync-sdk-js: app will crash for the custom fetch is not used by aws-appsync client.

Created on 14 Jul 2018  路  4Comments  路  Source: awslabs/aws-mobile-appsync-sdk-js

// app code

import Vue from 'vue';
import { AWSAppSyncClient, createAppSyncLink } from 'aws-appsync';
import VueApollo from 'vue-apollo';
import wxFetch from 'wxapp-fetch';
import { HttpLink } from 'apollo-link-http';
import appSyncConfig from '../../AppSync';

const config = {
  disableOffline: true,
};

const uri = appSyncConfig.graphqlEndpoint;
const resultsFetcherLink = new HttpLink({ uri, fetch: wxFetch });
const link = createAppSyncLink({
  url: uri,
  region: appSyncConfig.region,
  auth: {
    type: appSyncConfig.authenticationType,
    apiKey: appSyncConfig.apiKey,
  },
  resultsFetcherLink,             //  resultsFetcherLink  will use the custom fetch 
});

const options = {
  link,
  defaultOptions: {
    watchQuery: {
      fetchPolicy: 'cache-and-network',
    },
  },
};

const client = new AWSAppSyncClient(config, options);
const appsyncProvider = new VueApollo({
  defaultClient: client,
}).provide();

Vue.config.productionTip = false;
Vue.use(VueApollo);

// crash from here.
// pakages/aws-appsync/src/client.ts

 export const createSubscriptionHandshakeLink = (url, resultsFetcherLink = new HttpLink({ uri: url })) => {

    return ApolloLink.split(
        operation => {
            const { query } = operation;
            const { kind, operation: graphqlOperation } = getMainDefinition(query);
            const isSubscription = kind === 'OperationDefinition' && graphqlOperation === 'subscription';

            return isSubscription;
        },
        ApolloLink.from([
            new NonTerminatingHttpLink('subsInfo', { uri: url }),      // the fetch option is not use here..
            new SubscriptionHandshakeLink('subsInfo'),
        ]),
        resultsFetcherLink,
    );
};

//temporary to fix this .
new NonTerminatingHttpLink('subsInfo', { uri: url , fetch: resultsFetcherLink.request }),

// Error log

fetch is not found globally and no fetcher passed, to fix pass a fetch for
your environment like https://www.npmjs.com/package/node-fetch.

For example:
import fetch from 'node-fetch';
import { createHttpLink } from 'apollo-link-http';

const link = createHttpLink({ uri: '/graphql', fetch: fetch }); 
 Error: 
fetch is not found globally and no fetcher passed, to fix pass a fetch for
your environment like https://www.npmjs.com/package/node-fetch.

For example:
import fetch from 'node-fetch';
import { createHttpLink } from 'apollo-link-http';

const link = createHttpLink({ uri: '/graphql', fetch: fetch });
    at checkFetcher (http://127.0.0.1:13974/appservice/static/js/vendor.js:36781:15)
    at Object.createHttpLink (http://127.0.0.1:13974/appservice/static/js/vendor.js:36042:90)
    at new NonTerminatingHttpLink (http://127.0.0.1:13974/appservice/static/js/vendor.js:48880:41)
    at Object.global.webpackJsonp.exports.createSubscriptionHandshakeLink (http://127.0.0.1:13974/appservice/static/js/vendor.js:22153:9)
    at global.webpackJsonp.exports.createAppSyncLink (http://127.0.0.1:13974/appservice/static/js/vendor.js:22169:17)
    at Object.221 (http://127.0.0.1:13974/appservice/static/js/pages/index/main.js:116:82)
    at __webpack_require__ (http://127.0.0.1:13974/appservice/static/js/manifest.js:56:30)
    at Object.219 (http://127.0.0.1:13974/appservice/static/js/pages/index/main.js:24:141)
    at __webpack_require__ (http://127.0.0.1:13974/appservice/static/js/manifest.js:56:30)
    at Object.218 (http://127.0.0.1:13974/appservice/static/js/pages/index/main.js:11:65)
good first issue

Most helpful comment

But looks like to me, if you create a new AWSAppSyncClient with AWSAppSyncClientOptions only - and no ApolloClientOptions (2nd arg) - you will still get that error on server side (rendering).
I had to create a custom link in order to fix it.

I'm using next.js, which uses SSR.

I also updated my dependencies:

"aws-appsync": "^1.4.0"
"aws-appsync-react": "^1.2.0"

Non-working code example:

import AWSAppSyncClient from "aws-appsync";

import appSyncConfig from "./appsync-config";

const token = "...";

const appSyncClientOptions = {
  auth: {
    type: appSyncConfig.authenticationType,
    jwtToken: async () => token
  },
  region: appSyncConfig.region,
  url: appSyncConfig.graphqlEndpoint
};

export default new AWSAppSyncClient(appSyncClientOptions);

Working code example:

import AWSAppSyncClient, { createAppSyncLink } from "aws-appsync";
import { createHttpLink } from "apollo-link-http";

import appSyncConfig from "./appsync-config";

if (!process.browser) {
  global.fetch = require("node-fetch");
}

const token = "...";

const appSyncClientOptions = {
  auth: {
    type: appSyncConfig.authenticationType,
    jwtToken: async () => token
  },
  region: appSyncConfig.region,
  url: appSyncConfig.graphqlEndpoint
};

const apolloClientOptions = {
  link: createAppSyncLink({
    ...appSyncClientOptions,
    resultsFetcherLink: createHttpLink({ uri: appSyncClientOptions.url, fetch })
  })
};

export default new AWSAppSyncClient(appSyncClientOptions, apolloClientOptions);

All 4 comments

I had a similar issue. Can you try adding:

require('isomorphic-fetch')

@JohnRbk that fixed my issue.

the latest version has fixed this bug.

export const createSubscriptionHandshakeLink = (url: string, resultsFetcherLink: ApolloLink = createHttpLink({ uri: url })) => {
    return ApolloLink.split(
        operation => {
            const { query } = operation;
            const { kind, operation: graphqlOperation } = getMainDefinition(query) as OperationDefinitionNode;
            const isSubscription = kind === 'OperationDefinition' && graphqlOperation === 'subscription';

            return isSubscription;
        },
        ApolloLink.from([
            new NonTerminatingLink('subsInfo', { link: resultsFetcherLink }),        // ok now.
            new SubscriptionHandshakeLink('subsInfo'),
        ]),
        resultsFetcherLink,
    );
};

But looks like to me, if you create a new AWSAppSyncClient with AWSAppSyncClientOptions only - and no ApolloClientOptions (2nd arg) - you will still get that error on server side (rendering).
I had to create a custom link in order to fix it.

I'm using next.js, which uses SSR.

I also updated my dependencies:

"aws-appsync": "^1.4.0"
"aws-appsync-react": "^1.2.0"

Non-working code example:

import AWSAppSyncClient from "aws-appsync";

import appSyncConfig from "./appsync-config";

const token = "...";

const appSyncClientOptions = {
  auth: {
    type: appSyncConfig.authenticationType,
    jwtToken: async () => token
  },
  region: appSyncConfig.region,
  url: appSyncConfig.graphqlEndpoint
};

export default new AWSAppSyncClient(appSyncClientOptions);

Working code example:

import AWSAppSyncClient, { createAppSyncLink } from "aws-appsync";
import { createHttpLink } from "apollo-link-http";

import appSyncConfig from "./appsync-config";

if (!process.browser) {
  global.fetch = require("node-fetch");
}

const token = "...";

const appSyncClientOptions = {
  auth: {
    type: appSyncConfig.authenticationType,
    jwtToken: async () => token
  },
  region: appSyncConfig.region,
  url: appSyncConfig.graphqlEndpoint
};

const apolloClientOptions = {
  link: createAppSyncLink({
    ...appSyncClientOptions,
    resultsFetcherLink: createHttpLink({ uri: appSyncClientOptions.url, fetch })
  })
};

export default new AWSAppSyncClient(appSyncClientOptions, apolloClientOptions);
Was this page helpful?
0 / 5 - 0 ratings

Related issues

AlexThomas90210 picture AlexThomas90210  路  3Comments

asadowns picture asadowns  路  3Comments

wzup picture wzup  路  3Comments

mwarger picture mwarger  路  3Comments

yarax picture yarax  路  3Comments