diff --git a/.gitignore b/.gitignore index 3c32c59..45c254c 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,5 @@ typings/ .env .idea + +.serverless diff --git a/src/db.js b/src/db.js index 21f380a..b3076a4 100644 --- a/src/db.js +++ b/src/db.js @@ -1,44 +1,46 @@ 'use strict' const AWS = require('aws-sdk') -const config = require('./config.json') -const options = config[process.env.STAGE] || {} -const db = () => new AWS.DynamoDB.DocumentClient(options) -module.exports = { - getValue: key => { - const params = { - TableName: process.env.DB_TABLE, - Key: { key } - } +module.exports = (stage, tableName) => { + const client = stage => new AWS.DynamoDB.DocumentClient(require('./config.json')[stage] || {}) + + return { + getValue: key => { + const params = { + TableName: tableName, + Key: { key } + } - return new Promise((resolve, reject) => { - db().get(params, (error, data) => { - if (error) { - reject(error) - } else { - resolve(typeof data.Item === 'undefined' ? '' : data.Item.info) - } + return new Promise((resolve, reject) => { + client(stage).get(params, (error, data) => { + if (error) { + reject(error) + } else { + resolve(typeof data.Item === 'undefined' ? '' : data.Item.val) + } + }) }) - }) - }, - setValue: (key, info) => { - const params = { - TableName: process.env.DB_TABLE, - Key: { key: key }, - UpdateExpression: 'SET info = :info', - ExpressionAttributeValues: { - ':info': info + }, + setValue: (key, value) => { + const params = { + TableName: tableName, + Key: { key: key }, + UpdateExpression: 'SET val = :value', + ExpressionAttributeValues: { + ':value': value + }, + ReturnValues: 'ALL_NEW' } - } - return new Promise((resolve, reject) => { - db().update(params, (error, data) => { - if (error) { - reject(error) - } else { - resolve(info) - } + return new Promise((resolve, reject) => { + client(stage).update(params, (error, data) => { + if (error) { + reject(error) + } else { + resolve(data.Attributes.val) + } + }) }) - }) + } } } diff --git a/src/handler.js b/src/handler.js index 86cd377..6118add 100644 --- a/src/handler.js +++ b/src/handler.js @@ -1,17 +1,23 @@ 'use strict' const {graphql} = require('graphql') -const db = require('./db') const typeDefs = require('./schema') const resolvers = require('./resolvers') const {makeExecutableSchema} = require('graphql-tools') module.exports.graphql = (event, context, callback) => { + const db = require('./db')(process.env.STAGE, process.env.DB_TABLE) const source = event.queryStringParameters.query const contextValue = db const schema = makeExecutableSchema({typeDefs, resolvers}) graphql({schema, source, contextValue}) - .then(result => callback(null, { - statusCode: 200, - body: JSON.stringify(result) - }), error => callback(error)) + .then(result => { + callback(null, { + statusCode: 200, + body: JSON.stringify(result) + }) + }) + .catch(error => { + console.error(JSON.stringify(error)) + callback(error) + }) } diff --git a/src/resolvers.js b/src/resolvers.js index 8ff607a..6bcd824 100644 --- a/src/resolvers.js +++ b/src/resolvers.js @@ -1,11 +1,11 @@ module.exports = { Query: { - value(obj, { key }, context, info) { + value: (obj, { key }, context, info) => { return context.getValue(key) } }, Mutation: { - value(obj, { key, value }, context, info) { + set: (obj, { key, value }, context, info) => { return context.setValue(key, value) } } diff --git a/src/schema.js b/src/schema.js index ddc97b8..77e3cd1 100644 --- a/src/schema.js +++ b/src/schema.js @@ -5,5 +5,5 @@ module.exports = `type Query { } type Mutation { - value(key: String!, value: String!): String + set(key: String!, value: String!): String }` diff --git a/tests/integration.test.js b/tests/integration.test.js index fc6adce..3853aa7 100644 --- a/tests/integration.test.js +++ b/tests/integration.test.js @@ -2,32 +2,40 @@ const assert = require('assert') const utils = require('./utils') const supertest = require('supertest') -describe('with graphql endpoint', function() { - this.timeout(5 * 1000) +const prop = (...arr) => obj => arr.reduce((acc, v) => acc && acc.hasOwnProperty(v) ? acc[v] : undefined, obj) - const request = () => { - const endpoint = utils.getServiceEndpoint() +describe('with graphql endpoint', function() { + this.timeout(30 * 1000) - return supertest(endpoint) - } + const request = () => supertest(utils.getServiceEndpoint()) - it('read your write', () => { + it('writing a value', () => { const key = 'SET-KEY' const expected = 'some value' + + return request().get('/graphql') + .query({query: `mutation {set(key:"${key}", value:"${expected}")}`}) + .expect('Content-Type', /json/) + .expect(200) + .expect(r => { + assert.equal(expected, + prop('body', 'data', 'set')(r), + JSON.stringify(prop('body', 'errors')(r))) }) + }) + + it('reading a value', () => { + const key = 'GET-KEY' + const expected = '' + return request().get('/graphql') - .query({query: `mutation {value(key:"${key}", value:"${expected}")}`}) + .query({query: `{value(key:"${key}")}`}) .expect('Content-Type', /json/) .expect(200) - .then(r => request().get('/graphql') - .query({query: `{value(key:"${key}")}`}) - .expect(res => { - assert.equal(expected, res.body.data.value) - })) - .catch(e => { - if (e) { - throw e - } - }) + .expect(r => { + assert.equal(expected, + prop('body', 'data', 'value')(r), + JSON.stringify(prop('body', 'errors')(r))) + }) }) it('getting an error', () => { @@ -35,6 +43,10 @@ describe('with graphql endpoint', function() { .query({query: '{value}'}) .expect('Content-Type', /json/) .expect(200) - .expect(res => { assert.equal(1, res.body.errors.length) }) + .expect(r => { + assert.equal(1, + prop('body', 'errors', 'length')(r), + JSON.stringify(prop('body', 'errors')(r))) + }) }) }) diff --git a/tests/unit.test.js b/tests/unit.test.js index 7e6a8e6..dccf501 100644 --- a/tests/unit.test.js +++ b/tests/unit.test.js @@ -17,7 +17,7 @@ describe('querying', () => { const expected = 'fake value' stubDocumentClientRead({ Item: { - info: expected + val: expected } }) const evt = { @@ -65,14 +65,18 @@ describe('querying', () => { describe('mutating', () => { it('writing value for a key', done => { const expected = 'Mario' - stubDocumentClientWrite({ }) + stubDocumentClientWrite({ + Attributes: { + val: expected + } + }) const evt = { queryStringParameters: { - query: `mutation {value(key: "Username", value: "${expected}")}` + query: `mutation {set(key: "Username", value: "${expected}")}` } } handler.graphql(evt, null, (error, result) => { - assert.equal(expected, JSON.parse(result.body).data.value) + assert.equal(expected, JSON.parse(result.body).data.set) done() }) })