Search code examples
node.jsaws-lambdaaws-sdkaws-appsyncgraphql-tag

Invariant Violation: fetch is not found globally and no fetcher passed, to fix pass a fetch for your environment


I'm trying to run a NodeJS app with an AWS Lambda handler. My package.json is very simple:

...
  "dependencies": {
    "aws-appsync": "^4.1.7",
    "aws-sdk": "^2.1202.0",
    "graphql-tag": "^2.12.6"
  }

When I try to run anything I get:


Invariant Violation: 
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 new InvariantError (/Users/jamesdaniels/Code/node_modules/ts-invariant/lib/invariant.js:16:28)
    at Object.exports.checkFetcher (/Users/jamesdaniels/Code/node_modules/apollo-link-http-common/lib/index.js:65:15)
    at Object.createHttpLink (/Users/jamesdaniels/Code/node_modules/apollo-link-http/lib/bundle.umd.js:47:30)
    at Object.exports.createAppSyncLink (/Users/jamesdaniels/Code/node_modules/aws-appsync/lib/client.js:144:201)
    at new AWSAppSyncClient (/Users/jamesdaniels/Code/node_modules/aws-appsync/lib/client.js:214:72)
    at Object.<anonymous> (/Users/jamesdaniels/Code/utils/appsync.js:16:23)

The error appears to be with the aws-appsync package. The error only occurs when I introduce that to my app:

const AWS = require("aws-sdk") // Works fine
const AUTH_TYPE = require("aws-appsync").AUTH_TYPE;
const AWSAppSyncClient = require("aws-appsync").default;

// GraphQL client config
const appSyncClientConfig = {
    url: "https://xxxxxxxxxxxxxxxxx.appsync-api.eu-west-2.amazonaws.com/graphql",
    region: "eu-west-2",
    auth: {
      type: AUTH_TYPE.AWS_IAM,
      credentials: AWS.config.credentials,
    },
    disableOffline: true,
  };

// Initialise the AppSync client
const appSyncClient = new AWSAppSyncClient(appSyncClientConfig);

An error is thrown from dependent modules aws-appsync > apollo-link-http > apollo-link-http-common.


Solution

  • Turns out the error message was telling me exactly what I needed to know. aws-appsync isn't designed for a back-end environment. It's intended for front-end environments, where fetch is available globally. In the back-end we need to create our own global variable for our own fetch if we want it to be available for any node packages that we've installed.

    The solution is to download node-fetch and then follow the instructions in the "Provide Global Access" section:

    Providing global access

    To use fetch() without importing it, you can patch the global object in node:

    // fetch-polyfill.js
    import fetch, {
      Blob,
      blobFrom,
      blobFromSync,
      File,
      fileFrom,
      fileFromSync,
      FormData,
      Headers,
      Request,
      Response,
    } from 'node-fetch'
    
    if (!globalThis.fetch) {
      globalThis.fetch = fetch
      globalThis.Headers = Headers
      globalThis.Request = Request
      globalThis.Response = Response
    }
    
    // index.js
    import './fetch-polyfill'
    
    // ...