Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
tableName=Testing
bucketName=notes-api-prod-serverlessdeploymentbucket-1dedyda5s1idw
8 changes: 3 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# package directories
node_modules
jspm_packages

# Serverless directories
.serverless
.webpack
.serverless
.dynamodb
5 changes: 5 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions ReadMe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# install pre-requisites

`npm install`
`sls dynamodb install`

# Running the Project Locally

`sls offline start --location .`
1 change: 0 additions & 1 deletion UploadData/UploadMe.txt

This file was deleted.

18 changes: 0 additions & 18 deletions handler.js

This file was deleted.

20 changes: 20 additions & 0 deletions jest-dynamodb-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = {
tables: [
{
TableName: 'player-points-table',
KeySchema: [
{
AttributeName: 'ID',
KeyType: 'HASH',
},
],
AttributeDefinitions: [
{
AttributeName: 'ID',
AttributeType: 'S',
},
],
BillingMode: 'PAY_PER_REQUEST',
},
],
};
4 changes: 4 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
verbose: true,
preset: '@shelf/jest-dynamodb',
};
29 changes: 29 additions & 0 deletions lambdas/common/API_Responses.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const Responses = {
_DefineResponse(statusCode = 502, data = {}) {
return {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Methods': '*',
'Access-Control-Allow-Origin': '*',
},
statusCode,
body: JSON.stringify(data),
};
},

_200(data = {}) {
return this._DefineResponse(200, data);
},
_204(data = {}) {
return this._DefineResponse(204, data);
},

_400(data = {}) {
return this._DefineResponse(400, data);
},
_404(data = {}) {
return this._DefineResponse(404, data);
},
};

module.exports = Responses;
32 changes: 32 additions & 0 deletions lambdas/common/API_Responses.unit.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const Responses = require('../common/API_Responses');

test('Responses is an object', () => {
expect(typeof Responses).toBe('object');
});

test('_200 works', () => {
const res = Responses._200({ name: 'josh' });
expect(res.statusCode).toBe(200);
expect(typeof res.body).toBe('string');
expect(res.headers['Content-Type']).toBe('application/json');
});

test('_400 works', () => {
const res = Responses._400({ name: 'josh' });
expect(res.statusCode).toBe(400);
expect(typeof res.body).toBe('string');
expect(res.headers['Content-Type']).toBe('application/json');
});

test('_404 works', () => {
const res = Responses._404({ name: 'josh' });
expect(res.statusCode).toBe(404);
expect(typeof res.body).toBe('string');
expect(res.headers['Content-Type']).toBe('application/json');
});

test('define response', () => {
const res = Responses._DefineResponse(382, { any: 'thing' });
expect(res.statusCode).toBe(382);
expect(res.body).toBe(JSON.stringify({ any: 'thing' }));
});
59 changes: 59 additions & 0 deletions lambdas/common/Dynamo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const AWS = require('aws-sdk');

let options = {};
if (process.env.IS_OFFLINE) {
options = {
region: 'localhost',
endpoint: 'http://localhost:8000',
};
}

if (process.env.JEST_WORKER_ID) {
options = {
endpoint: 'http://localhost:8000',
region: 'local-env',
sslEnabled: false,
};
}

const documentClient = new AWS.DynamoDB.DocumentClient(options);

const Dynamo = {
async get(ID, TableName) {
const params = {
TableName,
Key: {
ID,
},
};

const data = await documentClient.get(params).promise();

if (!data || !data.Item) {
throw Error(`There was an error fetching the data for ID of ${ID} from ${TableName}`);
}
console.log(data);

return data.Item;
},

async write(data, TableName) {
if (!data.ID) {
throw Error('no ID on the data');
}

const params = {
TableName,
Item: data,
};

const res = await documentClient.put(params).promise();

if (!res) {
throw Error(`There was an error inserting ID of ${data.ID} in table ${TableName}`);
}

return data;
},
};
module.exports = Dynamo;
33 changes: 33 additions & 0 deletions lambdas/common/Dynamo.unit.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const Dynamo = require('../common/Dynamo');

test('Dynamo is an object', () => {
expect(typeof Dynamo).toBe('object');
});

test('dynamo has get and write', () => {
expect(typeof Dynamo.get).toBe('function');
expect(typeof Dynamo.write).toBe('function');
});

const validTableName = 'player-points-table';
const data = { ID: '3081042', score: 25, name: 'Chris' };

test('Dynamo write works', async () => {
expect.assertions(1);
try {
const res = await Dynamo.write(data, validTableName);
expect(res).toBe(data);
} catch (error) {
console.log('error in dynamo write test', error);
}
});

test('dynamo get works', async () => {
expect.assertions(1);
try {
const res = await Dynamo.get(data.ID, validTableName);
expect(res).toEqual(data);
} catch (error) {
console.log('error in dynamo get', error);
}
});
40 changes: 40 additions & 0 deletions lambdas/common/S3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const AWS = require('aws-sdk');

const s3Client = new AWS.S3();

const S3 = {
async get(fileName, bucket) {
const params = {
Bucket: bucket,
Key: fileName,
};

let data = await s3Client.getObject(params).promise();

if (!data) {
throw Error(`Failed to get file ${fileName}, from ${bucket}`);
}

if (/\.json$/.test(fileName)) {
data = JSON.parse(data.Body.toString());
}
return data;
},
async write(data, fileName, bucket) {
const params = {
Bucket: bucket,
Body: JSON.stringify(data),
Key: fileName,
};

const newData = await s3Client.putObject(params).promise();

if (!newData) {
throw Error('there was an error writing the file');
}

return newData;
},
};

module.exports = S3;
27 changes: 27 additions & 0 deletions lambdas/endpoints/createFile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const Responses = require('../common/API_Responses');
const S3 = require('../common/S3');

const bucket = process.env.bucketName;

exports.handler = async event => {
console.log('event', event);

if (!event.pathParameters || !event.pathParameters.fileName) {
// failed without an fileName
return Responses._400({ message: 'missing the fileName from the path' });
}

let fileName = event.pathParameters.fileName;
const data = JSON.parse(event.body);

const newData = await S3.write(data, fileName, bucket).catch(err => {
console.log('error in S3 write', err);
return null;
});

if (!newData) {
return Responses._400({ message: 'Failed to write data by filename' });
}

return Responses._200({ newData });
};
28 changes: 28 additions & 0 deletions lambdas/endpoints/createPlayerScore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const Responses = require('../common/API_Responses');
const Dynamo = require('../common/Dynamo');

const tableName = process.env.tableName;

exports.handler = async event => {
console.log('event', event);

if (!event.pathParameters || !event.pathParameters.ID) {
// failed without an ID
return Responses._400({ message: 'missing the ID from the path' });
}

let ID = event.pathParameters.ID;
const user = JSON.parse(event.body);
user.ID = ID;

const newUser = await Dynamo.write(user, tableName).catch(err => {
console.log('error in dynamo write', err);
return null;
});

if (!newUser) {
return Responses._400({ message: 'Failed to write user by ID' });
}

return Responses._200({ newUser });
};
26 changes: 26 additions & 0 deletions lambdas/endpoints/getFile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const Responses = require('../common/API_Responses');
const S3 = require('../common/S3');

const bucket = process.env.bucketName;

exports.handler = async event => {
console.log('event', event);

if (!event.pathParameters || !event.pathParameters.fileName) {
// failed without an fileName
return Responses._400({ message: 'missing the fileName from the path' });
}

let fileName = event.pathParameters.fileName;

const file = await S3.get(fileName, bucket).catch(err => {
console.log('error in S3 get', err);
return null;
});

if (!file) {
return Responses._404({ message: 'Failed to read data by filename' });
}

return Responses._200(file);
};
26 changes: 26 additions & 0 deletions lambdas/endpoints/getPlayerScore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const Responses = require('../common/API_Responses');
const Dynamo = require('../common/Dynamo');

const tableName = process.env.tableName;

exports.handler = async event => {
console.log('event', event);

if (!event.pathParameters || !event.pathParameters.ID) {
// failed without an ID
return Responses._400({ message: 'missing the ID from the path' });
}

let ID = event.pathParameters.ID;

const user = await Dynamo.get(ID, tableName).catch(err => {
console.log('error in Dynamo Get', err);
return null;
});

if (!user) {
return Responses._204({ message: 'Failed to get user by ID' });
}

return Responses._200({ user });
};
Loading