Building a NodeJS Client App - AWS AppSync

Building a NodeJS Client App

AWS AppSync integrates with the Apollo GraphQL client for building client applications. AWS provides Apollo plugins for offline support, authorization, and subscription handshaking. This tutorial shows how you can use the AWS AppSync SDK with the Apollo client directly in a Node.js application.

Note: For AWS Lambda functions, ensure you set fetchPolicy: 'network-only' as well as disableOffline: true in your AppSync client constructor.

Before You Begin

This tutorial expects a GraphQL schema with the following structure:

schema { query: Query mutation: Mutation subscription: Subscription } type Mutation { addPost(id: ID! author: String! title: String content: String url: String): Post! updatePost(id: ID! author: String! title: String content: String url: String ups: Int! downs: Int! expectedVersion: Int!): Post! deletePost(id: ID!): Post! } type Post { id: ID! author: String! title: String content: String url: String ups: Int downs: Int version: Int! } type Query { allPost: [Post] getPost(id: ID!): Post } type Subscription { newPost: Post @aws_subscribe(mutations:["addPost"]) }

This schema is from the DynamoDB resolvers tutorial, with a subscription added. To follow the complete flow, you can optionally walk through that tutorial first. If you would like to do more customization of GraphQL resolvers, such as those that use DynamoDB, see the Resolver Mapping Template Reference.

Get the GraphQL API Endpoint

After you create your GraphQL API, you’ll need to get the API endpoint (URL) so you can use it in your client application. You can get the API endpoint in either of the following ways:

  • In the AWS AppSync console, choose Settings. The API URL is displayed in the API Details section.

  • Alternately, run the following CLI command. Replace the $GRAPHQL_API_ID parameter with a string specifying your API id:

aws appsync get-graphql-api --api-id $GRAPHQL_API_ID

The following instructions show how you can use AWS_IAM for client authorization. In the console, select Settings on the left, and then click AWS_IAM.

Create a Client Application

Create a new project and initialize it with npm, accepting the defaults, as follows:

mkdir appsync && cd appsync touch index.js aws-exports.js npm init

AWS AppSync supports several authorization types, which you can learn more about in Security. We recommend using short-term credentials from Amazon Cognito Federated Identities or Amazon Cognito user pools. For example purposes, we show how you can use IAM keys. Your aws-exports file should look like the following:

"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var config = { AWS_ACCESS_KEY_ID: '', AWS_SECRET_ACCESS_KEY: '', HOST: '', REGION: 'YOURREGION', PATH: '/graphql', ENDPOINT: '', }; config.ENDPOINT = "https://" + config.HOST + config.PATH; exports.default = config;

Edit your package.json dependencies file to include the following.

"apollo-cache-inmemory" "apollo-client" "apollo-link" "apollo-link-http" "aws-sdk" "aws-appsync" "es6-promise" "graphql" "graphql-tag" "isomorphic-fetch" "ws"

Note: You _*MUST*_ use "ws": "^3.3.1" otherwise you will get WebSocket errors. Also note that you cannot use the WebSocket features in an AWS Lambda function, only GraphQL queries and mutations.

From a command line, run the following:

npm install

Now add the following code to your index.js file:

Note: If you’re using this sample in an AWS Lambda function you must uncomment and use the client.query({ query: query, fetchPolicy: 'network-only' }) statement. You must also uncomment disableOffline: true in the AppSync client constructor.

"use strict"; /** * This shows how to use standard Apollo client on Node.js */ global.WebSocket = require('ws'); require('es6-promise').polyfill(); require('isomorphic-fetch'); // Require exports file with endpoint and auth info const aws_exports = require('./aws-exports').default; // Require AppSync module const AUTH_TYPE = require('aws-appsync/lib/link/auth-link').AUTH_TYPE; const AWSAppSyncClient = require('aws-appsync').default; const url = aws_exports.ENDPOINT; const region = aws_exports.REGION; const type = AUTH_TYPE.AWS_IAM; // If you want to use API key-based auth const apiKey = 'xxxxxxxxx'; // If you want to use a jwtToken from Amazon Cognito identity: const jwtToken = 'xxxxxxxx'; // If you want to use AWS... const AWS = require('aws-sdk'); AWS.config.update({ region: aws_exports.REGION, credentials: new AWS.Credentials({ accessKeyId: aws_exports.AWS_ACCESS_KEY_ID, secretAccessKey: aws_exports.AWS_SECRET_ACCESS_KEY }) }); const credentials = AWS.config.credentials; // Import gql helper and craft a GraphQL query const gql = require('graphql-tag'); const query = gql(` query AllPosts { allPost { __typename id title content author version } }`); // Set up a subscription query const subquery = gql(` subscription NewPostSub { newPost { __typename id title author version } }`); // Set up Apollo client const client = new AWSAppSyncClient({ url: url, region: region, auth: { type: type, credentials: credentials, } //disableOffline: true //Uncomment for AWS Lambda }); client.hydrated().then(function (client) { //Now run a query client.query({ query: query }) //client.query({ query: query, fetchPolicy: 'network-only' }) //Uncomment for AWS Lambda .then(function logData(data) { console.log('results of query: ', data); }) .catch(console.error); //Now subscribe to results const observable = client.subscribe({ query: subquery }); const realtimeResults = function realtimeResults(data) { console.log('realtime data: ', data); }; observable.subscribe({ next: realtimeResults, complete: console.log, error: console.log, }); });

If you want to use an API key or Amazon Cognito user pools in the previous example, you could update the AUTH_TYPE as follows:


You need to provide the key or JWT token, as appropriate.