AWS AppSync ToDo APIs with AWS Lambda Resolvers using Serverless Framework

Implement basic ToDo APIs using AWS AppSync with AWS Lambda Resolvers by using Serverless Framework

Application Stack:

Serverless Framework
AWS AppSync
AWS Lambda
AWS DynamoDB
AWS IAM
NodeJs
GraphQL

Install NodeJs as per instruction give…


This content originally appeared on DEV Community and was authored by Jaymit Bhoraniya

Implement basic ToDo APIs using AWS AppSync with AWS Lambda Resolvers by using Serverless Framework

Application Stack:
  • Serverless Framework
  • AWS AppSync
  • AWS Lambda
  • AWS DynamoDB
  • AWS IAM
  • NodeJs
  • GraphQL

Install NodeJs as per instruction given here

1. Install Serverless Framework

npm install -g serverless

2. Create basic NodeJs type template project using Serverless Framework

serverless create --template aws-nodejs

By default it will generate a folder structure like this:

  • handler.js
  • serverless.yml

Default serverless.yml will have below IaC code:

service: default-aws-nodejs
frameworkVersion: '2'
provider:
  name: aws
  runtime: nodejs12.x
  lambdaHashingVersion: 20201221

functions:
  hello:
    handler: handler.hello

Default handler.js will have below NodeJs code:

'use strict';

module.exports.hello = async (event) => {
  return {
    statusCode: 200,
    body: JSON.stringify(
      {
        message: 'Go Serverless v1.0! Your function executed successfully!',
        input: event,
      },
      null,
      2
    ),
  };
};

3. Install required Serverless Framework Plugins

  • npm install serverless-appsync-plugin
  • npm install serverless-pseudo-parameters

4. Modify serverless.yml Infrastructure as code to provision needful AppSync, DynamoDb, Lambda resources, and relevant configuration

service: appsync-todo-apis-demo
frameworkVersion: "2"

plugins:
   - serverless-appsync-plugin
   - serverless-pseudo-parameters

provider:
  name: aws
  runtime: nodejs12.x
  stage: dev
  region: ap-south-1
  lambdaHashingVersion: 20201221
  iam:
    role:
      statements:
        - Effect: "Allow"
          Action:            
            - "dynamodb:PutItem"
            - "dynamodb:UpdateItem"
            - "dynamodb:DeleteItem"
            - "dynamodb:GetItem"
            - "dynamodb:Scan"
          Resource: "arn:aws:dynamodb:#{AWS::Region}:*:table/${self:custom.TODO_TABLE}"

custom:      
  TODO_TABLE: todo-table

  appSync:
    name: appsync-todo-apis-demo
    authenticationType: API_KEY
    mappingTemplates:      
      - type: Mutation
        field: createTodo
        dataSource: createTodoFunction
        request: false
        response: false
      - type: Mutation
        field: updateTodo
        dataSource: updateTodoFunction
        request: false
        response: false
      - type: Mutation
        field: deleteTodo
        dataSource: deleteTodoFunction
        request: false
        response: false
      - type: Query
        field: getTodos
        dataSource: getTodosFunction
        request: false
        response: false      
    dataSources:        
      - type: AWS_LAMBDA
        name: createTodoFunction
        config:
          functionName: createTodo

      - type: AWS_LAMBDA
        name: updateTodoFunction
        config:
          functionName: updateTodo

      - type: AWS_LAMBDA
        name: deleteTodoFunction
        config:
          functionName: deleteTodo

      - type: AWS_LAMBDA
        name: getTodosFunction
        config:
          functionName: getTodos                     

functions: 
  getTodos:
    handler: functions/getTodos.handler
    environment:
      TODO_TABLE_NAME: !Ref TodoTable

  createTodo:
    handler: functions/createTodo.handler
    environment:
      TODO_TABLE_NAME: !Ref TodoTable

  updateTodo:
    handler: functions/updateTodo.handler
    environment:
      TODO_TABLE_NAME: !Ref TodoTable

  deleteTodo:
    handler: functions/deleteTodo.handler
    environment:
      TODO_TABLE_NAME: !Ref TodoTable

resources:
  Resources:
    TodoTable:
      Type: "AWS::DynamoDB::Table"
      Properties:
        KeySchema:
          - AttributeName: id
            KeyType: HASH
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S
        BillingMode: PAY_PER_REQUEST
        TableName: ${self:custom.TODO_TABLE}

5. Create GraphQL Schema new file schema.graphql

schema {
    query: Query
    mutation: Mutation
}

type Query {
    getTodos: [Get!]!
}

type Mutation {
    createTodo(id: ID!, name: String!, description: String!): Save
    updateTodo(id: ID!, name: String!, description: String!): Update
    deleteTodo(id: ID!): Delete
}

type Get {
    id: ID!
    name: String
    description: String 
}

type Save {
    id: ID!
    name: String
    description: String 
}

type Update {
    id: ID!
    name: String
    description: String 
}

type Delete {
    id: ID! 
}

6. Implement AWS Lambda Resolver CRUD handlers

Create new folder 'functions' with this files:

  • createTodo.js
  • deleteTodo.js
  • getTodos.js
  • updateTodo.js
6.1 createTodo.js handler
const AWS = require('aws-sdk')
const dynamodb = new AWS.DynamoDB()

module.exports.handler = async (event) => {    
    const id = event.arguments.id
    const name = event.arguments.name
    const description = event.arguments.description    

    const params = {
        Item: {
            "id": {
                S: id
            },
            "name": {
                S: name
            },
            "description": {
                S: description
            }            
        },
        ReturnConsumedCapacity: "TOTAL",
        TableName: process.env.TODO_TABLE_NAME
    }

    return dynamodb.putItem(params).promise()
        .then(data => {            
            return {
                id,
                name,
                description
            }
        })
        .catch(err => {
            console.log(err)
        })
};
6.2 deleteTodo.js handler
const AWS = require('aws-sdk')
const dynamodb = new AWS.DynamoDB()

module.exports.handler = async (event) => {
    const id = event.arguments.id

    const params = {
      Key: {
          "id": {
              S: id
          }
      },
      TableName: process.env.TODO_TABLE_NAME
    }


    return dynamodb.deleteItem(params).promise()
        .then(data => {            
            return {
                id
            }
        })
        .catch(err => {
          console.log(err)
        })
};
6.3 updateTodo.js handler
const AWS = require('aws-sdk')
const dynamodb = new AWS.DynamoDB()

module.exports.handler = async (event) => {
    const id = event.arguments.id
    const name = event.arguments.name
    const description = event.arguments.description

    const params = {
      ExpressionAttributeNames: {
          "#n": "name",
          "#d": "description"          
      },
      ExpressionAttributeValues: {
          ":n": {
              S: name
          },
          ":d": {
              S: description
          }
      },
      Key: {
          "id": {
              S: id
          }
      },
      ReturnValues: "ALL_NEW",
      TableName: process.env.TODO_TABLE_NAME,
      UpdateExpression: "SET #n = :n, #d = :d"
  }

  return dynamodb.updateItem(params).promise()
      .then(data => {
          const body = data.Attributes
          return {
            id: body.id.S,
            name: body.name.S,
            description: body.description.S
          }
      })
      .catch(err => {
        console.log(err)
      })
};
6.4 getTodos.js handler
const AWS = require('aws-sdk')
const dynamodb = new AWS.DynamoDB()

module.exports.handler = async (event) => {

    const params = {        
        TableName: process.env.TODO_TABLE_NAME
    }

    return dynamodb.scan(params).promise()
        .then(data => {            
            const todoList = [];
            for (let i = 0; i < data.Items.length; i++) {
                todoList.push({
                    id: data.Items[i].id.S,
                    name: data.Items[i].name.S,
                    description: data.Items[i].description.S
                });        
            }
            return todoList;            
        })
        .catch(err => {
            console.log(err)
        })
};

7. Create AWS IAM user with programmatic access and give needful permission that allows Serverless Framework to provision resources

The Serverless Framework needs access to your cloud provider account so that it can create and manage resources on your behalf.

During Creating AWS IAM user copy API Key & Secret.

8. Configure AWS Credentials for Serverless Framework Deployment

serverless config credentials --provider aws --key xxxxx --secret xxxxx

9. Deploy using Serverless Framework

serverless deploy
> serverless deploy
AppSync Plugin: GraphQl schema valid
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
........
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service appsync-todo-apis-demo.zip file to S3 (16.98 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
..........................................................................................
Serverless: Stack update finished...
Service Information
service: appsync-todo-apis-demo  
stage: dev
region: ap-south-1
stack: appsync-todo-apis-demo-dev
resources: 31
api keys:
  None
appsync api keys:
  xxxxxxxxxxxxxxx
endpoints:
  None
appsync endpoints:
  https://xxxxxxxxxxxxxxx.appsync-api.ap-south-1.amazonaws.com/graphql
functions:
  getTodos: appsync-todo-apis-demo-dev-getTodos
  createTodo: appsync-todo-apis-demo-dev-createTodo
  updateTodo: appsync-todo-apis-demo-dev-updateTodo
  deleteTodo: appsync-todo-apis-demo-dev-deleteTodo
layers:
  None

10. AWS AppSync APIs Verification Screenshots

AppSync API Verification - getTodos

getTodos API verification

AppSync API Verification - createTodo

createTodo API Verification

Relevant Resources Link


This content originally appeared on DEV Community and was authored by Jaymit Bhoraniya


Print Share Comment Cite Upload Translate Updates
APA

Jaymit Bhoraniya | Sciencx (2021-09-26T14:20:30+00:00) AWS AppSync ToDo APIs with AWS Lambda Resolvers using Serverless Framework. Retrieved from https://www.scien.cx/2021/09/26/aws-appsync-todo-apis-with-aws-lambda-resolvers-using-serverless-framework/

MLA
" » AWS AppSync ToDo APIs with AWS Lambda Resolvers using Serverless Framework." Jaymit Bhoraniya | Sciencx - Sunday September 26, 2021, https://www.scien.cx/2021/09/26/aws-appsync-todo-apis-with-aws-lambda-resolvers-using-serverless-framework/
HARVARD
Jaymit Bhoraniya | Sciencx Sunday September 26, 2021 » AWS AppSync ToDo APIs with AWS Lambda Resolvers using Serverless Framework., viewed ,<https://www.scien.cx/2021/09/26/aws-appsync-todo-apis-with-aws-lambda-resolvers-using-serverless-framework/>
VANCOUVER
Jaymit Bhoraniya | Sciencx - » AWS AppSync ToDo APIs with AWS Lambda Resolvers using Serverless Framework. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/09/26/aws-appsync-todo-apis-with-aws-lambda-resolvers-using-serverless-framework/
CHICAGO
" » AWS AppSync ToDo APIs with AWS Lambda Resolvers using Serverless Framework." Jaymit Bhoraniya | Sciencx - Accessed . https://www.scien.cx/2021/09/26/aws-appsync-todo-apis-with-aws-lambda-resolvers-using-serverless-framework/
IEEE
" » AWS AppSync ToDo APIs with AWS Lambda Resolvers using Serverless Framework." Jaymit Bhoraniya | Sciencx [Online]. Available: https://www.scien.cx/2021/09/26/aws-appsync-todo-apis-with-aws-lambda-resolvers-using-serverless-framework/. [Accessed: ]
rf:citation
» AWS AppSync ToDo APIs with AWS Lambda Resolvers using Serverless Framework | Jaymit Bhoraniya | Sciencx | https://www.scien.cx/2021/09/26/aws-appsync-todo-apis-with-aws-lambda-resolvers-using-serverless-framework/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.