How to Update a DynamoDB Item using NodeJS with AWS Lambda and Amplify CLI
Tags: aws, amplify, lambda, javascript
Published: 2022-01-14 20:32:16

## Table Of Contents
  * [Introduction](#3)
  * [What is AWS Amplify?](#2)
  * [Prerequisites & Installation](#3)
  * [How to Write a NodeJS Function to Update a DynamoDB Item using AWS Lambda and Amplify CLI](#4)
  * [Conclusion](#4)

## Introduction <a name="1"></a> 🎁
✨ *Recently I've had the wonderful opportunity of working with AWS Amplify on a NextJS codebase. So, I thought I'd write an article about it.* ✨

Amazon Web Services (AWS) provides viable cloud computing platforms and APIs, its popularity is high. The demand for AWS developers is increasing by the day, *and just that may be the very reason you're here.* For most first-time AWS developers understanding the AWS documentation can be a daunting task that takes patience and practice. *Not to say it's not possible, especially with the help of our good friend [Nader Dabit](https://www.youtube.com/channel/UC7mca3O0DmdSG2Cr80sOD7g).* Today we're going to *hopefully* speed up your production and discuss exactly how to create an update Lambda function using AWS Amplify in NodeJS. 

## What is AWS Amplify?<a name="2"></a> ☁️

Amazon Web Services (AWS), is an offshoot of Amazon providing on-demand cloud computing platforms and APIs to pretty much anyone that can pay since you're charged on a metered pay-as-you-go basis. These cloud computing services bestow a variety of basic abstract technical infrastructure, distributed computing building blocks, and tools. One of these tools services is AWS Amplify. With Amplify, you can configure a web/mobile app backend and watch with continuous deployments through the CI/CD. Amplify has a subset of tools including Amplify Studio, Amplify Libraries, Amplify Hosting and more.

You may have chosen Amplify to configure an app backend with a guided CLI workflow. The Amplify Command Line Interface (CLI) is a toolchain used to configure/maintain an app backend from your local desktop. You can even configure cloud functionality using the CLI's interactive workflow and intuitive use cases such as auth, storage, API. AWS Amplify gives you the ability to test features locally and deploy multiple environments. All configured resources are available to customers as infrastructure-as-code templates permitting easy meshing with Amplify's CI/CD workflow.

With most applications, you'll eventually need to update some data. Today you're going to see exactly how you can update information in a DynamoDB table by creating a NodeJS lambda function with the AWS Amplify CLI. 

### Prerequisites & Installation<a name="3"></a> 🚧 

+ NodeJS installed on your local machine 💻
+ Some knowledge of NodeJS ✅ 
+ Have an AWS account 🔒 
+ Some knowledge of AWS 🧠


### How to Write a NodeJS Function to Update a DynamoDB Item using AWS Lambda and Amplify CLI<a name="4"></a> 🛠️

*This example will be assuming you're working with an established AWS Amplify NextJS project with your environment already configured.*

1.To begin creating your update function, navigate to your <code>amplify</code> directory in your current project. This directory should have been created with you initiating your amplify project. 

*If you haven't yet done so, check out the npm packages [AWS Amplify Package](https://www.npmjs.com/package/aws-amplify), [aws-amplify/ui-react](https://www.npmjs.com/package/@aws-amplify/ui-react), and [aws-sdk](https://www.npmjs.com/package/aws-sdk).*

Once you've navigated to the amplify directory within your terminal, you can run the <code>amplify</code> command:

```shell
amplify add function
```
You should receive back a message asking:

```shell
? Select which capability you want to add: 
❯ Lambda function (serverless function) 
  Lambda layer (shared code & resource used across functions) 
```

While you may want to use [Lambda layers](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) in the future, currently you are going to select the <code>Lambda function (serverless function)</code> option.

2.Next you will be taken through several questions that will ultimately write and configure the base of the function for you. 

   + Enter the desire function name:

```shell
? Provide an AWS Lambda function name: <Function Name>
```
  + Chose NodeJS, *since this is an article for NodeJS and such*:
```shell
? Choose the runtime that you want to use: (Use arrow keys)
  .NET Core 3.1 
  Go 
  Java 
❯ NodeJS 
  Python 
```

Next select <code>Hello World</code>:

```shell
Choose the function template that you want to use: (Use arrow keys)
  CRUD function for DynamoDB (Integration with API Gateway) 
❯ Hello World 
  Lambda trigger 
  Serverless ExpressJS function (Integration with API Gateway) 
```

You should be presented with the option to configure advanced settings, and the answer to this is *YES*! *So type "y"*:

```shell
Available advanced settings:
- Resource access permissions
- Scheduled recurring invocation
- Lambda layers configuration
- Environment variables configuration
- Secret values configuration

? Do you want to configure advanced settings? y
```

While the actual configured advanced settings are ultimately up to you as the developer, for this example, you'll only be configuring environment variables, so select "No" (n), until you arrive at the configure environment variables option and select "Yes" (y):

```shell
? Do you want to configure advanced settings? Yes
? Do you want to access other resources in this project from your Lambda function? No
? Do you want to invoke this function on a recurring schedule? No
? Do you want to enable Lambda layers for this function? No
? Do you want to configure environment variables for this function? Yes
```

When you select "Yes", you will be asked to name, and set the env variable. If you are updating a dynamoDB table, you would use the dynamoDB table name for the variable value:

```shell
? Enter the environment variable name: <YOUR_ENV_NAME>
? Enter the environment variable value: <your_env_var>
```

Once you've finished adding in the value, you'll be prompted to either add, update, or quit the environment variables selection. Feel free to select <code>I'm done</code> *unless you have any more variables (tables) that are necessary*:

```shell
? Select what you want to do with environment variables: (Use arrow keys)
  Add new environment variable 
  Update existing environment variables 
  Remove existing environment variables 
❯ I'm done 
```
You should be prompted with one more question asking if you would like to add secret values, but for this example, you won't be needing that. Feel free to select "Yes" to edit the local function now, or head over to <code> amplify/backend/function/</code> directory to see your newly made function.

3.Once you've navigated to your Amplify generated function’s folder in the <code>function</code> directory, you should see a <code>src</code> folder, with an <code>index.js</code> file inside, go ahead and open it up, you should see something similar to this:

```Javascript
/* Amplify Params - DO NOT EDIT
	ENV
	REGION
	YOUR_ENV_VARIABLE
Amplify Params - DO NOT EDIT */

exports.handler = async (event) => {
    // TODO implement
    const response = {
        statusCode: 200,
    //  Uncomment below to enable CORS requests
    //  headers: {
    //      "Access-Control-Allow-Origin": "*",
    //      "Access-Control-Allow-Headers": "*"
    //  }, 
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};
```

🚩 *Don't forget to add in permissions to preform dynamoDB actions, such as updating, in the <code>custom-policies.json</code> file.*

First let's establish a connection to the DynamoDB, in the first few lines under the generated comment from <code>Amplify Params</code>, add in:

``` Javascript
const AWS = require("aws-sdk");
const ddb = new AWS.DynamoDB.DocumentClient({ region: "your region" });
```

The first line is importing the npm package mentioned at the beginning of this article. The second line works with DynamoDB items by abstracting away DynamoDB Types and converting responses to native Javascript.

4.Now let's write that update function! Amplify provided you with some nice boilerplate, but you can trash it, for now, instead, you're going to write something similar to this:

``` Javascript

const itemId = event.pathParameters.proxy; // This is assuming you're extracting the itemId you would like to update from a proxy under the resource. 
	console.log("event: ", event); // It's always a good idea to log the event so you can see what data you're working with and what is being passed through
	const body = JSON.parse(event.body); // Ideally you will be passing though the item data you would like to update through the event body.
	let response = {
		statusCode: 200,
		headers: {
			"Access-Control-Allow-Origin": "*",
			"Access-Control-Allow-Headers": "*",
			"Access-Control-Allow-Methods": "*",
			"Content-Type": "*/*",
			"Accept": "*/*",
		},
	}; // You may receive some CORS issues when initially testing your function, this is because before the request you specify fires, it is going to pass through the "OPTIONS" request, where you will need to pass through the headers above. You may even see this in your Cloud Watch logs.
	if (event.requestContext.httpMethod === "OPTIONS") {
		return response;
	} // Handle the "OPTIONS" method
	const whatYouWantToUpdate = body.whatYouWantToUpdate;
	let updateItemResponse = await updateItem(
		itemId,
		whatYouWantToUpdate
	);
	response.body = JSON.stringify(updateItemResponse);
	return response;
};
// Now lets actually make a call to the table and update the item!
function updateItem(itemId, newWhatYouWantToUpdate) {
	const params = {
		TableName: process.env.YOUR_ENV_VARIABLE_TABLE
,
// this is your DynamoDB Table 
		Key: {
			itemId: itemId,
//find the itemId in the table that you pull from the event 
		},
		UpdateExpression: "set whatYouWantToUpdate = :whatYouWantToUpdate",
		// This expression is what updates the item attribute 
ExpressionAttributeValues: {
			":whatYouWantToUpdate": newWhatYouWantToUpdate,
//create an Expression Attribute Value to pass in the expression above
		},
		ReturnValues: "UPDATED_NEW",
// Return the newly updated values 
	};
	return ddb.update(params).promise();
// pass in the params above and fire the actual dynamoDB update method
}
```

If you read the comments, you should see an explanation for what each bit of code means, but in case you didn't here's what we're doing:

+ Get the Item Id
+ Create an initial response
+ Handle the "OPTIONS" httpMethod request
+ Extract the new value you'd like to update from the event body, and pass it in as an argument to the dynamoDB update function
+ Create your DynamoDB update function
+ Run the function and return your response

And, there you have it. Your update function is complete.🎉

5.It's always a good idea to run the <code>amplify status</code> command before pushing or publishing any of your new amplify code/functions, using the <code>amplify</code> commands <code>amplify push</code> or <code>amplify publish</code>. This allows you to check which functions were updated, as well as the api for that amplify project. 

If you feel comfortable with the code, feel free to <code>amplify push</code> it up.

If you head over to Lambda within the AWS console, you should be able to see and test out your newly created function! 🎉

If you are interested in connecting the lambda function to your API, you can do so with the <code>amplify update api</code> command, and add in a new resource. Thus, ultimately allowing you to select your newly made function to execute on the path you create. Your function can be further inspected within the AWS console through API Gateway under your API. 

### Conclusion<a name="5"></a> 📍

Congrats, you have officially created a NodeJS Update Lambda Function using the AWS Amplify CLI. This was something I struggled with when onboarding and understanding what is AWS Amplify, how does it work, and how to incorporate Lambda. *Basically, me just being a noob*. But, in hopes of helping someone else, I wrote this article. 😊 

If this helped you in any way feel free to give me a 👍. Also if there is anything that can be improved upon to make this article more clear/correct, by all means, comment below! Thanks for reading! 💖

#### Feel Free to Check out these Extra Resources

+ https://dynobase.dev/dynamodb-nodejs/#put-item
+ https://www.dynamodbguide.com/what-is-dynamo-db
+ https://docs.aws.amazon.com/lambda/latest/dg/welcome.html