532 words
3 minutes
Using AppSync Client from Lambda

It took me a while to figure out how to use the Amplify GraphQL client in a lambda, so I can access my AppSync API. The main reason I wanted to use this is, so I can invoke subscription updates to my frontend. If you’re interested in making signed https request, check out this tutorial.

Code#

npm install aws-appsync es6-promise graphql-tag isomorphic-fetch

The env variables should all be provided by Amplify.

/* eslint-disable no-console */
require("es6-promise").polyfill();
require("isomorphic-fetch");
// eslint-disable-next-line import/no-extraneous-dependencies
const AWS = require("aws-sdk");
const AWSAppSyncClient = require("aws-appsync").default;
const { AUTH_TYPE } = require("aws-appsync");

const region = process.env.REGION;
AWS.config.update({
  region
});
const appsyncUrl = process.env.API_RADLOOP_GRAPHQLAPIENDPOINTOUTPUT;
const gql = require("graphql-tag");

// graphql client.  We define it outside of the lambda function in order for it to be reused during subsequent calls
let client;

// used to parse different types of query results to return only the item.
function parseResults(operationName, data) {
  if (operationName.includes("List")) {
    return data[`l${operationName.substring(1, operationName.length)}`];
  }
  if (operationName.includes("GetOrders")) {
    return data[`g${operationName.substring(1, operationName.length)}`];
  }
  return data[operationName];
}

// initializes our graphql client
function initializeClient() {
  client = new AWSAppSyncClient({
    url: appsyncUrl,
    region,
    auth: {
      type: AUTH_TYPE.AWS_IAM,
      credentials: AWS.config.credentials
    },
    disableOffline: true
  });
}

// generic mutation function.  A way to quickly reuse mutation statements
async function executeMutation(mutation, operationName, variables) {
  if (!client) {
    initializeClient();
  }

  try {
    const response = await client.mutate({
      mutation: gql(mutation),
      variables,
      fetchPolicy: "network-only"
    });
    return parseResults(operationName, response.data);
  } catch (err) {
    console.log("Error while trying to mutate data");
    throw JSON.stringify(err);
  }
}

// generic query function.  A way to quickly reuse query statements
async function executeQuery(query, operationName, variables) {
  if (!client) {
    initializeClient();
  }
  try {
    const response = await client.query({
      query: gql(query),
      variables,
      fetchPolicy: "network-only"
    });
    return parseResults(operationName, response.data);
  } catch (err) {
    console.log("Error while trying to fetch data");
    throw JSON.stringify(err);
  }
}

exports.handler = async event => {
  console.log(event); // logging so you can see what gets passed when you invoke it

  // updating a users firstName
  await executeMutation(
    `mutation updateUser($id: ID!) {
        updateUser(id: $id) {
      id
      firstName
     }
   }`,
    "updateOrder",
    {
      input: {
        id: "1234",
        firstName: "Bob"
      }
    }
  );

  // querying the user that we changed
  const user = await executeQuery(
    `query getUser($id: ID!) {
    getUser(id: $id) {
      id
      fullName
      firstName
      lastName
     }
   }`,
    "updateOrder",
    {
      id: "1234"
    }
  );

  return user;
};

If you have trouble with permissions make sure the schema that you are accessing has lambda permissions as well as your lambda has permissions to access that schema.

Permissions for the schema#

Example schema. This will allow cognito userpools as well as IAM(for lambda)

type User
@model
@auth(
 rules: [
    {
      allow: private
      provider: userPools
      operations: [read, update, create]
    }
    {
      allow: private
      provider: iam
      operations: [read, update, create, delete]
    }
  ]
) {
  id: ID!
  firstName: String
}

Run an amplify push after

Permissions for the lambda#

In your terminal at the root of your amplify directory:

amplify function update

2. Select function that this code is in
3. Let this function access other resources
4. Select GraphQL/Appsync option
5. Regardless of what this function does, give it Create, Update and Read.  AWS is strange and your lambda requires these permissions to be able to access the AppSync API even if your lambda may not be using the those permissions.
6. ```bash
amplify push
Using AppSync Client from Lambda
https://edwardbeazer.com/posts/using-appsync-client-from-lambda/
Author
Edward Beazer
Published at
2020-07-06