Skip to content

Commit 0d81d5d

Browse files
committed
Add CRUD API
1 parent a09033d commit 0d81d5d

14 files changed

+234
-22
lines changed

Diff for: create.js

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import uuid from "uuid";
2+
import * as dynamoDbLib from "./libs/dynamodb-lib";
3+
import { success, failure } from "./libs/response-lib";
4+
5+
export async function main(event, context) {
6+
const data = JSON.parse(event.body);
7+
const params = {
8+
TableName: process.env.tableName,
9+
Item: {
10+
userId: event.requestContext.identity.cognitoIdentityId,
11+
noteId: uuid.v1(),
12+
content: data.content,
13+
attachment: data.attachment,
14+
createdAt: Date.now()
15+
}
16+
};
17+
18+
try {
19+
await dynamoDbLib.call("put", params);
20+
return success(params.Item);
21+
} catch (e) {
22+
return failure({ status: false });
23+
}
24+
}

Diff for: delete.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import * as dynamoDbLib from "./libs/dynamodb-lib";
2+
import { success, failure } from "./libs/response-lib";
3+
4+
export async function main(event, context) {
5+
const params = {
6+
TableName: process.env.tableName,
7+
Key: {
8+
userId: event.requestContext.identity.cognitoIdentityId,
9+
noteId: event.pathParameters.id
10+
}
11+
};
12+
13+
try {
14+
await dynamoDbLib.call("delete", params);
15+
return success({ status: true });
16+
} catch (e) {
17+
return failure({ status: false });
18+
}
19+
}

Diff for: env.example

-8
This file was deleted.

Diff for: get.js

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import * as dynamoDbLib from "./libs/dynamodb-lib";
2+
import { success, failure } from "./libs/response-lib";
3+
4+
export async function main(event, context) {
5+
const params = {
6+
TableName: process.env.tableName,
7+
Key: {
8+
userId: event.requestContext.identity.cognitoIdentityId,
9+
noteId: event.pathParameters.id
10+
}
11+
};
12+
13+
try {
14+
const result = await dynamoDbLib.call("get", params);
15+
if (result.Item) {
16+
return success(result.Item);
17+
} else {
18+
return failure({ status: false, error: "Item not found." });
19+
}
20+
} catch (e) {
21+
return failure({ status: false });
22+
}
23+
}

Diff for: libs/dynamodb-lib.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import AWS from "aws-sdk";
2+
3+
export function call(action, params) {
4+
const dynamoDb = new AWS.DynamoDB.DocumentClient();
5+
6+
return dynamoDb[action](params).promise();
7+
}

Diff for: libs/response-lib.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export function success(body) {
2+
return buildResponse(200, body);
3+
}
4+
5+
export function failure(body) {
6+
return buildResponse(500, body);
7+
}
8+
9+
function buildResponse(statusCode, body) {
10+
return {
11+
statusCode: statusCode,
12+
headers: {
13+
"Access-Control-Allow-Origin": "*",
14+
"Access-Control-Allow-Credentials": true
15+
},
16+
body: JSON.stringify(body)
17+
};
18+
}

Diff for: list.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import * as dynamoDbLib from "./libs/dynamodb-lib";
2+
import { success, failure } from "./libs/response-lib";
3+
4+
export async function main(event, context) {
5+
const params = {
6+
TableName: process.env.tableName,
7+
KeyConditionExpression: "userId = :userId",
8+
ExpressionAttributeValues: {
9+
":userId": event.requestContext.identity.cognitoIdentityId
10+
}
11+
};
12+
13+
try {
14+
const result = await dynamoDbLib.call("query", params);
15+
return success(result.Items);
16+
} catch (e) {
17+
return failure({ status: false });
18+
}
19+
}

Diff for: mocks/create-event.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"body": "{\"content\":\"hello world\",\"attachment\":\"hello.jpg\"}",
3+
"requestContext": {
4+
"identity": {
5+
"cognitoIdentityId": "USER-SUB-1234"
6+
}
7+
}
8+
}

Diff for: mocks/delete-event.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"pathParameters": {
3+
"id": "20e832c0-72a5-11ea-a23d-91417b8ca86b"
4+
},
5+
"requestContext": {
6+
"identity": {
7+
"cognitoIdentityId": "USER-SUB-1234"
8+
}
9+
}
10+
}

Diff for: mocks/get-event.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"pathParameters": {
3+
"id": "20e832c0-72a5-11ea-a23d-91417b8ca86b"
4+
},
5+
"requestContext": {
6+
"identity": {
7+
"cognitoIdentityId": "USER-SUB-1234"
8+
}
9+
}
10+
}

Diff for: mocks/list-event.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"requestContext": {
3+
"identity": {
4+
"cognitoIdentityId": "USER-SUB-1234"
5+
}
6+
}
7+
}

Diff for: mocks/update-event.json

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"body": "{\"content\":\"new world\",\"attachment\":\"new.jpg\"}",
3+
"pathParameters": {
4+
"id": "20e832c0-72a5-11ea-a23d-91417b8ca86b"
5+
},
6+
"requestContext": {
7+
"identity": {
8+
"cognitoIdentityId": "USER-SUB-1234"
9+
}
10+
}
11+
}

Diff for: serverless.yml

+52-14
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,70 @@
1-
# NOTE: update this with your service name
21
service: serverless-react-notes-app-api
32

4-
# Create an optimized package for our functions
53
package:
64
individually: true
75

86
plugins:
9-
- serverless-bundle # Package our functions with Webpack
7+
- serverless-bundle
108
- serverless-offline
11-
- serverless-dotenv-plugin # Load .env as environment variables
9+
- serverless-dotenv-plugin
1210

1311
provider:
1412
name: aws
1513
runtime: nodejs10.x
1614
stage: prod
1715
region: eu-central-1
18-
# To load environment variables externally
19-
# rename env.example to .env and uncomment
20-
# the following line. Also, make sure to not
21-
# commit your .env.
22-
#
23-
#environment:
24-
# SAMPLE_ENV_VAR: ${env:SAMPLE_ENV_VAR}
16+
environment:
17+
tableName: notes
18+
iamRoleStatements:
19+
- Effect: Allow
20+
Action:
21+
- dynamodb:DescribeTable
22+
- dynamodb:Query
23+
- dynamodb:Scan
24+
- dynamodb:GetItem
25+
- dynamodb:PutItem
26+
- dynamodb:UpdateItem
27+
- dynamodb:DeleteItem
28+
Resource: "arn:aws:dynamodb:eu-central-1:*:*"
2529

2630
functions:
27-
hello:
28-
handler: handler.hello
31+
create:
32+
handler: create.main
2933
events:
3034
- http:
31-
path: hello
35+
path: notes
36+
method: post
37+
cors: true
38+
authorizer: aws_iam
39+
get:
40+
handler: get.main
41+
events:
42+
- http:
43+
path: notes/{id}
44+
method: get
45+
cors: true
46+
authorizer: aws_iam
47+
list:
48+
handler: list.main
49+
events:
50+
- http:
51+
path: notes
3252
method: get
53+
cors: true
54+
authorizer: aws_iam
55+
update:
56+
handler: update.main
57+
events:
58+
- http:
59+
path: notes/{id}
60+
method: put
61+
cors: true
62+
authorizer: aws_iam
63+
delete:
64+
handler: delete.main
65+
events:
66+
- http:
67+
path: notes/{id}
68+
method: delete
69+
cors: true
70+
authorizer: aws_iam

Diff for: update.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import * as dynamoDbLib from "./libs/dynamodb-lib";
2+
import { success, failure } from "./libs/response-lib";
3+
4+
export async function main(event, context) {
5+
const data = JSON.parse(event.body);
6+
const params = {
7+
TableName: process.env.tableName,
8+
Key: {
9+
userId: event.requestContext.identity.cognitoIdentityId,
10+
noteId: event.pathParameters.id
11+
},
12+
UpdateExpression: "SET content = :content, attachment = :attachment",
13+
ExpressionAttributeValues: {
14+
":attachment": data.attachment || null,
15+
":content": data.content || null
16+
},
17+
ReturnValues: "ALL_NEW"
18+
};
19+
20+
try {
21+
await dynamoDbLib.call("update", params);
22+
return success({ status: true });
23+
} catch (e) {
24+
return failure({ status: false });
25+
}
26+
}

0 commit comments

Comments
 (0)