Skip to content

Commit a7c8f8a

Browse files
committed
feat: NERDS enchanced example, backend and frontend
1 parent 8ee88f3 commit a7c8f8a

File tree

21 files changed

+1271
-0
lines changed

21 files changed

+1271
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Esteban Serna
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# NERDS Stack - NodeJS Express React DynamoDB and SAM
2+
3+
## Enhanced example
4+
5+
This example includes additional DynamoDB functionality, you will work with a table with a Partition Key and a Sort Key that will allow you to run more elegant queries.
6+
7+
We will be working with an ehnahced task example where you will retrieve the tasks for a given user, and optional by priority.
8+
9+
This project contains source code and supporting files for a sample application running on Express and NodeJS with Amazon DynamoDB local. It includes the following files and folders:
10+
11+
![enhanced-recording](./enhanced-recording.gif)
12+
13+
- `src` - Code for the express application and the APIs.
14+
- `package.json` - Includes all the scripts to work on this project and the pre-requisites.
15+
16+
This application will create a couple of API methods to add and list the ToDos.
17+
18+
## Requirements
19+
20+
- [Docker Desktop](https://www.docker.com/products/docker-desktop/)
21+
- [DynamoDB Local Docker Image](https://hub.docker.com/r/amazon/dynamodb-local)
22+
- [Node v22.3.0](https://nodejs.org/en/blog/release/v22.3.0)
23+
- [AWS JavaScript SDK v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/)
24+
25+
## Usage
26+
27+
To start working with this project you need to first run `npm install`.
28+
29+
### Running the tool in conjuntion with the front end.
30+
31+
![Demo](./documentation/Darn-basic-stack.gif)
32+
33+
### DynamoDB local
34+
35+
This application will store all the information in an Amazon DynamoDB local instance, you will experience all the benefits from Amazon DynamoDB in your workstation.
36+
37+
Execute the command `npm run start-db`. If this is the first time running the command your output should look like the one below. Docker will obtain the latest version for you!
38+
39+
```shell
40+
❯ npm run start-db
41+
42+
> basic-backend@0.0.1 start-db
43+
> echo "CID=$(docker run -p $npm_package_config_ddbport:$npm_package_config_ddbport -d amazon/dynamodb-local -jar DynamoDBLocal.jar -sharedDb)" > .ddb_cid
44+
45+
Unable to find image 'amazon/dynamodb-local:latest' locally
46+
latest: Pulling from amazon/dynamodb-local
47+
decbb28a26fa: Pull complete
48+
4b968a8d55bd: Pull complete
49+
4f4fb700ef54: Pull complete
50+
16d147f186fa: Pull complete
51+
Digest: sha256:d7ebddeb60fa418bcda218a6c6a402a58441b2a20d54c9cb1d85fd5194341753
52+
Status: Downloaded newer image for amazon/dynamodb-local:latest
53+
```
54+
55+
If you want to stop DynamoDB local execution you just need to run the command `npm run stop-db`. The long number at the end represents your docker container ID.
56+
57+
```shell
58+
❯ npm run stop-db
59+
60+
> basic-backend@0.0.1 stop-db
61+
> source .ddb_cid && docker stop $CID && rm .ddb_cid
62+
63+
904e9a494f0f09acd027e33d275d3a51a05716f09cc4eace87b778bc3e65e650
64+
```
65+
66+
### Working with DynamoDB tables
67+
68+
This project consists of a To-Do application and you will be storing all the items in a DynamoDB table. First you need to create a `Notes` table, where you will store all your to-dos.
69+
70+
Run the command `npm run create-table`.
71+
72+
```shell
73+
❯ npm run create-table
74+
75+
> basic-backend@0.0.1 create-table
76+
> aws dynamodb create-table --table-name $npm_package_config_ddbtable --attribute-definitions AttributeName=PK,AttributeType=S --key-schema AttributeName=PK,KeyType=HASH --billing-mode PAY_PER_REQUEST --endpoint-url http://$npm_package_config_ddbhost:$npm_package_config_ddbport --no-cli-page
77+
78+
{
79+
"TableDescription": {
80+
"AttributeDefinitions": [
81+
{
82+
"AttributeName": "PK",
83+
"AttributeType": "S"
84+
}
85+
],
86+
"TableName": "Notes",
87+
"KeySchema": [
88+
{
89+
"AttributeName": "PK",
90+
"KeyType": "HASH"
91+
}
92+
],
93+
"TableStatus": "ACTIVE",
94+
"CreationDateTime": "2024-07-29T10:40:09.344000-04:00",
95+
"ProvisionedThroughput": {
96+
"LastIncreaseDateTime": "1969-12-31T19:00:00-05:00",
97+
"LastDecreaseDateTime": "1969-12-31T19:00:00-05:00",
98+
"NumberOfDecreasesToday": 0,
99+
"ReadCapacityUnits": 0,
100+
"WriteCapacityUnits": 0
101+
},
102+
"TableSizeBytes": 0,
103+
"ItemCount": 0,
104+
"TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/Notes",
105+
"BillingModeSummary": {
106+
"BillingMode": "PAY_PER_REQUEST",
107+
"LastUpdateToPayPerRequestDateTime": "2024-07-29T10:40:09.344000-04:00"
108+
},
109+
"DeletionProtectionEnabled": false
110+
}
111+
}
112+
```
113+
114+
If you run the command twice by mistake, the second time you will get an error saying that you already have a table called `Notes`.
115+
116+
```shell
117+
❯ npm run create-table
118+
119+
> basic-backend@0.0.1 create-table
120+
> aws dynamodb create-table --table-name $npm_package_config_ddbtable --attribute-definitions AttributeName=PK,AttributeType=S --key-schema AttributeName=PK,KeyType=HASH --billing-mode PAY_PER_REQUEST --endpoint-url http://$npm_package_config_ddbhost:$npm_package_config_ddbport --no-cli-page
121+
122+
123+
An error occurred (ResourceInUseException) when calling the CreateTable operation: Cannot create preexisting table
124+
```
125+
126+
### List all the existing tables
127+
128+
To idenfity which tables you have created execute the command `npm run show-tables`.
129+
130+
```shell
131+
❯ npm run show-tables
132+
133+
> basic-backend@0.0.1 show-tables
134+
> aws dynamodb list-tables --endpoint-url http://$npm_package_config_ddbhost:$npm_package_config_ddbport
135+
136+
{
137+
"TableNames": [
138+
"Notes"
139+
]
140+
}
141+
```
142+
143+
### Retrieve all the items from one table
144+
145+
To return all the elements from the `Notes` table you can run the command `npm run scan-table`. However if your table is empty you will get this output.
146+
147+
```shell
148+
❯ npm run scan-table
149+
150+
> basic-backend@0.0.1 scan-table
151+
> aws dynamodb scan --table-name $npm_package_config_ddbtable --endpoint-url http://$npm_package_config_ddbhost:$npm_package_config_ddbport
152+
153+
{
154+
"Items": [],
155+
"Count": 0,
156+
"ScannedCount": 0,
157+
"ConsumedCapacity": null
158+
}
159+
```
160+
161+
### Initialize the backend
162+
163+
Finally to work with the sample express application, included in this project you will need to execute the instruction `npm run start-backend`, this process will start the express application that will be listening at port 3000.
164+
165+
Tip: execute this command in a new terminal
166+
167+
```shell
168+
❯ npm run start-backend
169+
170+
> basic-backend@0.0.1 start-backend
171+
> node src/server.js
172+
173+
Server is running on port 3000
174+
```
175+
176+
## Contributing
177+
178+
As soon as you clone this repository you need to run `pre-commit install` and before pushing any commit you need to run `detect-secrets scan > .secrets.baseline`. Failing to run this command will result in an invalid commit and it will be rejected.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"name": "enhanced-backend",
3+
"description": "Enhanced backend project sample for the NodeJS Express React DynamoDB and SAM (NERDS) Stack",
4+
"version": "0.0.1",
5+
"private": true,
6+
"dependencies": {
7+
"@aws-sdk/client-dynamodb": "^3.620.0",
8+
"@aws-sdk/lib-dynamodb": "^3.620.0",
9+
"@aws-sdk/util-dynamodb": "^3.620.0",
10+
"aws-sdk": "^2.1664.0",
11+
"body-parser": "^1.20.2",
12+
"cors": "^2.8.5",
13+
"express": "^4.19.2",
14+
"nanoid": "^5.0.7"
15+
},
16+
"type": "module",
17+
"config": {
18+
"ddbhost": "0.0.0.0",
19+
"ddbport": "8000",
20+
"ddbtable": "Tasks",
21+
"ddbEnhancedTable": "social-recipes"
22+
},
23+
"scripts": {
24+
"start-db": "echo \"CID=$(docker run -p $npm_package_config_ddbport:$npm_package_config_ddbport -d amazon/dynamodb-local -jar DynamoDBLocal.jar -sharedDb)\" > .ddb_cid",
25+
"stop-db": "source .ddb_cid && docker stop $CID && rm .ddb_cid",
26+
"start-backend": "node src/server.js",
27+
"populate-recipe-table": "node src/populate.js",
28+
"create-table": "aws dynamodb create-table --table-name $npm_package_config_ddbtable --attribute-definitions AttributeName=PK,AttributeType=S --key-schema AttributeName=PK,KeyType=HASH --billing-mode PAY_PER_REQUEST --endpoint-url http://$npm_package_config_ddbhost:$npm_package_config_ddbport --no-cli-page",
29+
"create-recipes-table": "aws dynamodb create-table --table-name $npm_package_config_ddbEnhancedTable --attribute-definitions AttributeName=PK,AttributeType=S AttributeName=SK,AttributeType=S --key-schema AttributeName=PK,KeyType=HASH AttributeName=SK,KeyType=RANGE --billing-mode PAY_PER_REQUEST --endpoint-url http://${npm_package_config_ddbhost}:${npm_package_config_ddbport} --no-cli-page",
30+
"show-tables": "aws dynamodb list-tables --endpoint-url http://$npm_package_config_ddbhost:$npm_package_config_ddbport --no-cli-page",
31+
"scan-tasks": "aws dynamodb scan --table-name $npm_package_config_ddbtable --endpoint-url http://$npm_package_config_ddbhost:$npm_package_config_ddbport --no-cli-page",
32+
"scan-recipes": "aws dynamodb scan --table-name $npm_package_config_ddbEnhancedTable --endpoint-url http://$npm_package_config_ddbhost:$npm_package_config_ddbport --no-cli-page"
33+
}
34+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
[
2+
{
3+
"PK": "USER#4Rl17WTewD6aa1-k73cBJ",
4+
"SK": "USER#4Rl17WTewD6aa1-k73cBJ",
5+
"Priorities": [0, 1, 2, 3],
6+
"Name": "John Doe",
7+
"userId": "4Rl17WTewD6aa1-k73cBJ"
8+
},
9+
{
10+
"PK": "USER#4Rl17WTewD6aa1-k73cBJ",
11+
"SK": "TASKS#2024-09-21T10:57:01#o5-Y6L4cyBdZUWE4a5U2a",
12+
"title": "Get some onions",
13+
"description": "We are cooking some seviche, it needs purple onions",
14+
"taskDate": "2024-09-21T10:57:01",
15+
"taskId": "o5-Y6L4cyBdZUWE4a5U2a",
16+
"userId": "4Rl17WTewD6aa1-k73cBJ"
17+
},
18+
{
19+
"PK": "USER#4Rl17WTewD6aa1-k73cBJ",
20+
"SK": "TASKS#2024-09-21T10:04:51#bT_-eE-I2XMEhs-qNltOS",
21+
"Name": "Complete assignment",
22+
"description": "This extra ssignment will give me 10 points",
23+
"taskId": "bT_-eE-I2XMEhs-qNltOS",
24+
"taskDate": "2024-09-21T10:04:51",
25+
"userId": "4Rl17WTewD6aa1-k73cBJ"
26+
},
27+
{
28+
"PK": "USER#4Rl17WTewD6aa1-k73cBJ",
29+
"SK": "TASKS#2024-09-21T10:51:47#45iOrKCdW7ppFYOx1eTWR",
30+
"title": "Is it raining in mars",
31+
"description": "Investigate if there is water in mars",
32+
"taskId": "45iOrKCdW7ppFYOx1eTWR",
33+
"taskDate": "2024-09-21T10:51:47",
34+
"userId": "4Rl17WTewD6aa1-k73cBJ"
35+
},
36+
{
37+
"PK": "USER#4Rl17WTewD6aa1-k73cBJ",
38+
"SK": "TASKS#0#2024-09-21T10:35:39#hUkIVS7H3BKlEmQTNvNOe",
39+
"taskPriority": "0",
40+
"title": "Get some Corvina",
41+
"description": "Corvina is the best for a seviche",
42+
"taskId": "hUkIVS7H3BKlEmQTNvNOe",
43+
"taskDate": "2024-09-21T10:35:39",
44+
"userId": "4Rl17WTewD6aa1-k73cBJ"
45+
},
46+
{
47+
"PK": "USER#4Rl17WTewD6aa1-k73cBJ",
48+
"SK": "TASKS#0#2024-09-21T12:16:26#V9HbF9Edu2NdnkrY6PcCk",
49+
"taskPriority": "0",
50+
"title": "Chili flakes",
51+
"description": "This will really give the seviche that kick!",
52+
"taskId": "V9HbF9Edu2NdnkrY6PcCk",
53+
"taskDate": "2024-09-21T12:16:26",
54+
"userId": "4Rl17WTewD6aa1-k73cBJ"
55+
},
56+
{
57+
"PK": "USER#4Rl17WTewD6aa1-k73cBJ",
58+
"SK": "TASKS#1#2024-09-21T10:40:29#qytMVJUgUK3I0TlC--G9y",
59+
"taskPriority": "1",
60+
"title": "Get mangos",
61+
"description": "The mango should not be very ripe, try something in the middle",
62+
"taskId": "qytMVJUgUK3I0TlC--G9y",
63+
"taskDate": "2024-09-21T10:40:29",
64+
"userId": "4Rl17WTewD6aa1-k73cBJ"
65+
}
66+
]

0 commit comments

Comments
 (0)