Skip to content

Commit

Permalink
update readme
Browse files Browse the repository at this point in the history
  • Loading branch information
ebisbe committed Jul 13, 2024
1 parent f67c149 commit 4d3d334
Showing 1 changed file with 82 additions and 43 deletions.
125 changes: 82 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,69 +1,108 @@
<!--
title: 'AWS Simple HTTP Endpoint example in NodeJS'
description: 'This template demonstrates how to make a simple HTTP API with Node.js running on AWS Lambda and API Gateway using the Serverless Framework.'
layout: Doc
framework: v4
platform: AWS
language: nodeJS
authorLink: 'https://github.com/serverless'
authorName: 'Serverless, Inc.'
authorAvatar: 'https://avatars1.githubusercontent.com/u/13742415?s=200&v=4'
-->
# Project characteristics

# Serverless Framework Node HTTP API on AWS
Serverless guru code challenge n5. The implementation of this challenge has been materialised as a backend for a 'Wedding list' app. It's main purpose is to provide an example of how to implement a serverless architecture with Api gateway and Dynamodb built with the [Serverless Framework](https://www.serverless.com/) and [Typescript](https://www.typescriptlang.org/).

This template demonstrates how to make a simple HTTP API with Node.js running on AWS Lambda and API Gateway using the Serverless Framework.
## Table of Contents
- [Installation](#installation)
- [Usage](#usage)
- [Project Structure](#project-structure)
- [Folder Structure](#folder-structure)
- [Plugins](#plugins)
- [CI/CD](#cicd)
- [Unit testing](#unit-testing)
- [E2E testing](#e2e-testing)

This template does not include any kind of persistence (database). For more advanced examples, check out the [serverless/examples repository](https://github.com/serverless/examples/) which includes Typescript, Mongo, DynamoDB and other examples.

## Usage
## Installation

### Deployment
Install dependencies:
```bash
pnpm install
```
This project uses the following packages:
- [pnpm](https://pnpm.io/) as a package manager.
- [jest](https://jestjs.io/) as a testing framework.
- [eslint](https://eslint.org/) as a linter.
- [prettier](https://prettier.io/) as a code formatter. Used through eslint.
- [github actions](https://github.com/features/actions) as a CI/CD.
- [DynamoDB OneTable](https://doc.onetable.io/start/quick-tour/) as a database wrapper.
- [middy](https://github.com/middyjs/middy) as a middleware.
- [zod](https://github.com/colinhacks/zod) as a schema validation.

In order to deploy the example, you need to run the following command:
## Usage

To deploy the project run this command in the root folder :
```bash
pnpm sls deploy
```
serverless deploy
```
Remember you need proper AWS credentials. For reference, check [AWS credentials](https://www.serverless.com/framework/docs/providers/aws/guide/credentials).
As of Serverless Framework V4 there have been some licensing changes that require you to have a [Serverless Account](https://www.serverless.com/framework/docs/guides/upgrading-v4#license-changes). You need a `SERVERLESS_ACCESS_KEY` configured at https://github.com/ebisbe/serverless-guru-code-challenge/settings/secrets/actions. The key is free to get from the Serverless Dashboard.

After running deploy, you should see output similar to:
## Project Structure

```
Deploying "serverless-http-api" to stage "dev" (us-east-1)
As defined by the challenge we need to use Api Gateway to access the resources. We have two endpoints:
- `/list/{?id}`
- `/list/{listId}/item/{id}`

We have defined the following method operations `GET` `POST`, `PATCH` and `DELETE`.

✔ Service deployed to stack serverless-http-api-dev (91s)
This project uses the single database pattern for DynamoDb. All the data is stored in a single table. We have defined a Primary Key ( pk ) and a Secondary Key ( sk ) as the Key Schema. We have also enabled streams to be able to update related changes.

endpoint: GET - https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/
functions:
hello: serverless-http-api-dev-hello (1.6 kB)
```
For example after we create a list that list contains 0 items and a total price of 0. When we add an item to that list, the total price will be updated and the number of items will be increased by 1 throgh the streams.
The streams are connected to an AWS Pipe that sends any `Item` change as a new Event to an EventBus. We can know if the change proceeds from an Item thanks to the attribute `__typeName`.

_Note_: In current form, after deployment, your API is public and can be invoked by anyone. For production deployments, you might want to configure an authorizer. For details on how to do that, refer to [HTTP API (API Gateway V2) event docs](https://www.serverless.com/framework/docs/providers/aws/events/http-api).
We have added a rule that will format the event and send it to an AWS StepFunction. There we will check what kind of event ( CREATE, MODIFY, REMOVE ) to do proper update on the parent `List` item.

### Invocation
## Folder Structure

After successful deployment, you can call the created application via HTTP:
All the project files are in the `src` folder. The structure is the following:

```
curl https://xxxxxxx.execute-api.us-east-1.amazonaws.com/
└── src
├── functions
├── models
├── resources
├── stepFunctions
├── types
└── utils
```

Which should result in response similar to:
- `functions`: contains all the lambda functions of the project. As the implementation of this challenge, there are 4 functions: `create`, `get`, `update` and `delete`. Each of those are grouped in a folder with the resource their are related to. Tests are also included for each function.
- `models`: contains all the information related to the database. We are using [Dynamodb OneTable](https://doc.onetable.io/start/quick-tour/) package for this challenge. With one schema we can define multiple models with default values, attributes types, any primary and secondary indexes.
- `resources`: contains all the Cloud Formation resources that are used in the project. It's all typed thanks to [@awboost/cfntypes](https://github.com/awboost/cfntypes) package. It's meant to be used as a reference.
- `stepFunctions`: contains all the step functions that are used in the project.
- `types`: contains all the types used for resources, the helper functions to avoid linting errors and an enhanced version of the default Serverless Types.
- `utils`: contains all the utils functions used by the project that don't have a proper place in another folder.

```json
{ "message": "Go Serverless v4! Your function executed successfully!" }
```
## Plugins
This project is using 3 Sls plugins:
- `serverless-iam-roles-per-function`: Lets you define IAM roles per function. It's a good practice to avoid having the same role for all functions.
- `serverless-step-functions`: Lets you define step functions. This is used in the project to create the state machines.
- `serverless-plugin-scripts`: Lets you run scripts before and after deploy. The only usage for this project is to generate an `env.e2e` file to be able to run the E2E tests right after the deploy.

### Local development
## CI/CD

The easiest way to develop and test your function is to use the `dev` command:
The CI/CD pipeline is using [Github Actions](https://docs.github.com/en/actions). It's configured to run on every push to main or pull request. There are 2 action scripts:

```
serverless dev
```
- `deploy-sls.yml`: Deploys the project with serverless. When the commit it is from a PR it generates a different stage for that PR with `pr<number>` otherwise defaults to `dev`.
- `remove-sls.yml`: Removes the project after a closed PR event is triggered.

### Unit testing

To run the unit tests execute:
```bash
pnpm test
```
The unit tests for all the lambdas are under `__tests__` folder on each `src/functions/{model}` folder. We are using [Jest](https://jestjs.io/) to run them with [jest-dynalite](https://github.com/mhart/jest-dynalite) as a mock for the DynamoDB.

Those tests use `jest.config.ddb.cjs` configuration.

This will start a local emulator of AWS Lambda and tunnel your requests to and from AWS Lambda, allowing you to interact with your function as if it were running in the cloud.
### E2E testing

Now you can invoke the function as before, but this time the function will be executed locally. Now you can develop your function locally, invoke it, and see the results immediately without having to re-deploy.
To run the E2E tests execute:
```bash
pnpm test-e2e
```

When you are done developing, don't forget to run `serverless deploy` to deploy the function to the cloud.
The E2E test is under `__tests__/e2e.test.js`. The single test covers creation of a new List and Item. Also is covering the pipes triggers from each DynamoDb stream and EBS rules.
After each deploy a `.env.e2e` file is generated with the endpoint to be able to run the tests.

0 comments on commit 4d3d334

Please sign in to comment.