Skip to content

Commit a703164

Browse files
author
Anna Spysz
committed
Add initial template and demo code for project
1 parent b6ca273 commit a703164

File tree

12 files changed

+508
-0
lines changed

12 files changed

+508
-0
lines changed

samconfig.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
version = 0.1
2+
[default.global.parameters]
3+
stack_name = "aws-app-composer-basic-api"
4+
[default.deploy.parameters]
5+
capabilities = "CAPABILITY_IAM"

src/CreateUser/index.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
const { randomUUID } = require("crypto");
2+
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
3+
const { DynamoDBDocumentClient, PutCommand } = require("@aws-sdk/lib-dynamodb");
4+
5+
const client = new DynamoDBClient({});
6+
const ddbDocClient = DynamoDBDocumentClient.from(client);
7+
8+
9+
exports.handler = async event => {
10+
try {
11+
// Log the event argument for debugging and for use in local development.
12+
console.log(JSON.stringify(event, undefined, 2));
13+
14+
const item = JSON.parse(event.body);
15+
16+
// We generate a random ID to prevent collisions and distribute records in the
17+
// DynamoDB Table keyspace.
18+
if ("id" in item) {
19+
return {
20+
statusCode: 400,
21+
body: "'id' may not be provided in item attributes"
22+
};
23+
}
24+
25+
// Generate a random UUID as the hash key ID for the item
26+
item.id = randomUUID();
27+
28+
console.log(`Adding item with ID '${item.id}' to table '${({}).ITEMS_TABLE_NAME}' with attributes: ${JSON.stringify(item, null, 2)}`);
29+
30+
// We use a ConditionExpression to ensure we don't overwrite a record that
31+
// already exists for the same id. An error will be thrown if this happens
32+
// and we'll return a 500 error.
33+
const command = new PutCommand({
34+
TableName: ({}).ITEMS_TABLE_NAME,
35+
Item: item,
36+
ConditionExpression: "#idKey <> :idValue",
37+
ExpressionAttributeNames: {
38+
"#idKey": "id"
39+
},
40+
ExpressionAttributeValues: {
41+
":idValue": item.id
42+
}
43+
});
44+
45+
await ddbDocClient.send(command);
46+
47+
console.log(`Successfully saved item '${item.id}'`);
48+
49+
return {
50+
statusCode: 200
51+
};
52+
} catch (e) {
53+
console.error(`Failed to save item: ${e.message} (${e.constructor.name})`);
54+
55+
return {
56+
statusCode: 500,
57+
body: "Internal Service Error"
58+
};
59+
}
60+
};

src/CreateUser/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "function",
3+
"version": "1.0.0"
4+
}

src/DeleteUser/index.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
2+
const { DynamoDBDocumentClient, DeleteCommand } = require("@aws-sdk/lib-dynamodb");
3+
4+
const client = new DynamoDBClient({});
5+
const ddbDocClient = DynamoDBDocumentClient.from(client);
6+
7+
exports.handler = async event => {
8+
try {
9+
// Log the event argument for debugging and for use in local development.
10+
console.log(JSON.stringify(event, undefined, 2));
11+
12+
const id = event.pathParameters.id;
13+
14+
console.log(`Deleting item with ID '${id}' from table '${({}).ITEMS_TABLE_NAME}'`);
15+
16+
// When deleting the record, return its values to us so we can see if the
17+
// record actually existed
18+
const command = new DeleteCommand({
19+
TableName: ({}).ITEMS_TABLE_NAME,
20+
Key: { id },
21+
ReturnValues: "ALL_OLD"
22+
});
23+
24+
const response = await ddbDocClient.send(command);
25+
26+
// If we deleted an item, Attributes will have its old attributes.
27+
// Otherwise, Attributes will be null.
28+
if (response.Attributes) {
29+
console.log(`Item '${id}' deleted`);
30+
31+
return {
32+
statusCode: 200
33+
};
34+
} else {
35+
console.log(`Item '${id}' not found`);
36+
37+
return {
38+
statusCode: 404,
39+
body: "Item not found"
40+
};
41+
}
42+
} catch (e) {
43+
console.error(`Failed to delete item: ${e.message} (${e.constructor.name})`);
44+
45+
return {
46+
statusCode: 500,
47+
body: `Internal Service Error`
48+
};
49+
}
50+
};

src/DeleteUser/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "function",
3+
"version": "1.0.0"
4+
}

src/GetUser/index.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
2+
const { DynamoDBDocumentClient, GetCommand } = require("@aws-sdk/lib-dynamodb");
3+
4+
const client = new DynamoDBClient({});
5+
const ddbDocClient = DynamoDBDocumentClient.from(client);
6+
7+
exports.handler = async event => {
8+
try {
9+
// Log the event argument for debugging and for use in local development.
10+
console.log(JSON.stringify(event, undefined, 2));
11+
12+
const id = event.pathParameters.id;
13+
14+
console.log(`Getting item with ID '${id}' from table '${({}).ITEMS_TABLE_NAME}'`);
15+
16+
const command = new GetCommand({
17+
TableName: ({}).ITEMS_TABLE_NAME,
18+
Key: { id }
19+
});
20+
21+
const response = await ddbDocClient.send(command);
22+
23+
if (response.Item) {
24+
console.log(`Retrieved item '${id}' with attributes ${JSON.stringify(response.Item)}`);
25+
26+
return {
27+
statusCode: 200,
28+
body: JSON.stringify({
29+
item: response.Item
30+
})
31+
};
32+
} else {
33+
console.log(`No item found with id '${id}'`);
34+
35+
return {
36+
statusCode: 404,
37+
body: "Item not found"
38+
};
39+
}
40+
} catch (e) {
41+
console.error(`Failed to get item: ${e.message} (${e.constructor.name})`);
42+
43+
return {
44+
statusCode: 500,
45+
body: "Internal Service Error"
46+
};
47+
}
48+
};

src/GetUser/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "function",
3+
"version": "1.0.0"
4+
}

src/ListUsers/index.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
const { DynamoDBClient, ScanCommand } = require("@aws-sdk/client-dynamodb");
2+
3+
const client = new DynamoDBClient({});
4+
5+
exports.handler = async event => {
6+
try {
7+
// Log the event argument for debugging and for use in local development.
8+
console.log(JSON.stringify(event, undefined, 2));
9+
10+
console.log(`Listing items from table '${({}).ITEMS_TABLE_NAME}'`);
11+
12+
let ids = [];
13+
14+
// Loop over all items. If there are more items after a request, the
15+
// response LastEvaluatedKey will have a non-null value that we can
16+
// pass in the next request to continue fetching more items.
17+
let lastEvaluatedKey;
18+
do {
19+
const command = new ScanCommand({
20+
TableName: ({}).ITEMS_TABLE_NAME,
21+
ProjectionExpression: "id",
22+
ExclusiveStartKey: lastEvaluatedKey
23+
});
24+
25+
const response = await client.send(command);
26+
27+
const additionalIds = response.Items.map(item => item.id);
28+
29+
ids = [...ids, ...additionalIds];
30+
31+
lastEvaluatedKey = response.LastEvaluatedKey;
32+
} while (lastEvaluatedKey);
33+
34+
console.log(`Successfully scanned for list of IDs: ${JSON.stringify(ids, null, 2)}`);
35+
36+
return {
37+
statusCode: 200,
38+
body: JSON.stringify({
39+
ids
40+
})
41+
};
42+
} catch (e) {
43+
console.error(`Failed to list items: ${e.message} (${e.constructor.name})`);
44+
45+
return {
46+
statusCode: 500,
47+
body: "Internal Service Error"
48+
};
49+
}
50+
};

src/ListUsers/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "function",
3+
"version": "1.0.0"
4+
}

src/UpdateUser/index.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
const { DynamoDBClient, ConditionalCheckFailedException } = require("@aws-sdk/client-dynamodb");
2+
const { DynamoDBDocumentClient, PutCommand } = require("@aws-sdk/lib-dynamodb");
3+
4+
const client = new DynamoDBClient({});
5+
const ddbDocClient = DynamoDBDocumentClient.from(client);
6+
7+
exports.handler = async event => {
8+
try {
9+
// Log the event argument for debugging and for use in local development.
10+
console.log(JSON.stringify(event, undefined, 2));
11+
12+
const item = JSON.parse(event.body);
13+
14+
if ("id" in item) {
15+
return {
16+
statusCode: 400,
17+
body: "'id' may not be provided in item attributes"
18+
};
19+
}
20+
21+
item.id = event.pathParameters.id;
22+
23+
console.log(`Updating item with ID '${item.id}' in table '${({}).ITEMS_TABLE_NAME}'`);
24+
25+
// Use a ConditionExpression to overwrite a record only if there is
26+
// already a record (i.e. there already is a record with an id attribute,
27+
// because all records must have a hash key attribute)
28+
const command = new PutCommand({
29+
TableName: ({}).ITEMS_TABLE_NAME,
30+
Item: item,
31+
ConditionExpression: "attribute_exists(#idKey)",
32+
ExpressionAttributeNames: {
33+
"#idKey": "id"
34+
}
35+
});
36+
37+
await ddbDocClient.send(command);
38+
39+
console.log(`Successfully updated item '${item.id}'`);
40+
41+
return {
42+
statusCode: 200
43+
};
44+
} catch (e) {
45+
if (e instanceof ConditionalCheckFailedException) {
46+
console.log("Item not found");
47+
48+
return {
49+
statusCode: 404,
50+
body: "Item not found"
51+
};
52+
}
53+
54+
console.error(`Failed to update item: ${e.message} (${e.constructor.name})`);
55+
56+
return {
57+
statusCode: 500,
58+
body: "Internal Service Error"
59+
};
60+
}
61+
};

src/UpdateUser/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "function",
3+
"version": "1.0.0"
4+
}

0 commit comments

Comments
 (0)