Deployable hello function behind api gateway

This commit is contained in:
Ben Ramey
2018-09-18 06:50:29 -05:00
parent 5437fe88b0
commit 435060a764
6 changed files with 176 additions and 0 deletions

13
dynamoClient.js Normal file
View File

@@ -0,0 +1,13 @@
const AWS = require('aws-sdk');
// Set the region
AWS.config.update({region: 'us-east-2'});
// also set local endpoint while in development
if (process.env.NODE_ENV === 'development') {
AWS.config.update({endpoint: "http://localhost:8000"});
}
const client = new AWS.DynamoDB.DocumentClient({});
module.exports = client;

14
handlers/hello/get.js Normal file
View File

@@ -0,0 +1,14 @@
'use strict';
module.exports.hello = async (event, context) => {
return {
statusCode: 200,
body: JSON.stringify({
message: 'Go Serverless v1.0! Your function executed successfully!',
input: event,
}),
};
// Use this code if you don't use the http event with the LAMBDA-PROXY integration
// return { message: 'Go Serverless v1.0! Your function executed successfully!', event };
};

20
helpers.js Normal file
View File

@@ -0,0 +1,20 @@
const customThrow = (statusCode, message) => {
const err = new Error();
err.statusCode = statusCode;
err.message = message;
throw err;
};
const createResponse = (statusCode, body) => ({
statusCode,
headers: {
"Access-Control-Allow-Origin" : "*", // Required for CORS support to work
"Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS
},
body: JSON.stringify(body),
});
module.exports = {
customThrow,
createResponse
};

61
services/db.js Normal file
View File

@@ -0,0 +1,61 @@
const dynamoClient = require('../dynamoClient');
const create = async (tableName, item) => {
const fullItem = {...item, created_at: Date.now()};
await dynamoClient.put({
TableName: tableName,
Item: fullItem
}).promise();
// put does not return saved item, just return our object
return fullItem;
};
const get = async (tableName, keyMap) => {
const res = await dynamoClient.get({
TableName: tableName,
Key: keyMap
}).promise();
return res && res.Item;
};
const queryByID = async (tableName, idKeyName, id) => {
// querying by id can be used when we are querying a table
// that has a sortKey, but we don't need to use the sortKey
const res = await dynamoClient.query({
TableName: "gt_answers",
KeyConditionExpression: "#id = :idValue",
ExpressionAttributeNames: {
"#id": idKeyName,
},
ExpressionAttributeValues: {
":idValue": id,
}
}).promise();
return res && res.Items;
};
const update = async (tableName, keyMap, ue, eav) => {
const res = await dynamoClient.update({
TableName: tableName,
Key: keyMap,
UpdateExpression: ue,
ExpressionAttributeValues: eav,
ReturnValues: 'UPDATED_NEW'
}).promise();
console.log('update res', res);
return res;
};
module.exports = {
client: dynamoClient,
create,
get,
queryByID,
update
};

35
validators/index.js Normal file
View File

@@ -0,0 +1,35 @@
const Ajv = require('ajv');
const {customThrow} = require('../helpers');
const parseAndValidateBody = async (schema, body) => {
let parsedBody;
try {
parsedBody = JSON.parse(body);
} catch (err) {
customThrow(400, 'Error. Malformed event.parsedBody.');
}
const validation = validateBody(schema, parsedBody);
if (!validation.isValid) {
customThrow(400, validation.error);
}
return parsedBody;
};
const validateBody = (schema, body) => {
const ajv = new Ajv();
const validate = ajv.compile(schema);
const isValid = validate(body);
return {
isValid: isValid,
error: JSON.stringify(validate.errors)
}
};
module.exports = {
parseAndValidateBody,
};

33
validators/schemas.js Normal file
View File

@@ -0,0 +1,33 @@
const answerSchema = {
"type": "object",
"properties": {
"user_id": {"type": "string"},
"question_id": {"type": "string"},
"is_correct": {"type": "boolean"}
},
"required": ["user_id", "question_id", "is_correct"]
};
const userSchema = {
"type": "object",
"properties": {
"id": {"type": "string"},
"score": {"type": "number"}
},
"required": ["user_id", "question_id", "is_correct"]
};
const loginFollowUpSchema = {
"type": "object",
"properties": {
"accessToken": {"type": "string"}
},
"required": ["accessToken"]
};
module.exports = {
answerSchema,
userSchema,
loginFollowUpSchema
};