From a871be36ba570224b341947a8bd275dca3b157f3 Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Wed, 14 Dec 2016 17:02:10 -0800 Subject: [PATCH 01/18] scaffold files --- .eslintrc | 21 ++++++++++ .gitignore | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 4 ++ gulpfile.js | 22 ++++++++++ package.json | 34 +++++++++++++++ server.js | 0 6 files changed, 197 insertions(+) create mode 100644 .eslintrc create mode 100644 .gitignore create mode 100644 README.md create mode 100644 gulpfile.js create mode 100644 package.json create mode 100644 server.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..8dc6807 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,21 @@ +{ + "rules": { + "no-console": "off", + "indent": [ "error", 2 ], + "quotes": [ "error", "single" ], + "semi": ["error", "always"], + "linebreak-style": [ "error", "unix" ] + }, + "env": { + "es6": true, + "node": true, + "mocha": true, + "jasmine": true + }, + "ecmaFeatures": { + "modules": true, + "experimentalObjectRestSpread": true, + "impliedStrict": true + }, + "extends": "eslint:recommended" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84cac89 --- /dev/null +++ b/.gitignore @@ -0,0 +1,116 @@ + +# Created by https://www.gitignore.io/api/node,macos,windows,linux + +### Node ### +# Logs +logs +*.log +npm-debug.log* +node_modules +coverage + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + + + +### macOS ### +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon +# Thumbnails +._* +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + + +### Windows ### +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* diff --git a/README.md b/README.md new file mode 100644 index 0000000..d9cbe6f --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# Vanilla Ski Report REST api + +## About +The vanilla Ski Report REST api is built to allow consumers to get valuable ski report data about any area they want to ski in. diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..11af581 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,22 @@ +'use strict'; + +const gulp = require('gulp'); +const eslint = require('gulp-eslint'); + +gulp.task('lint', function() { + gulp.src(['**/*.js', '!node_modules']) + .pipe(eslint()) + .pipe(eslint.format()) + .pipe(eslint.failAfterError()); +}); + +gulp.task('test', function() { + gulp.src('./test/*-test.js', {read:false}) + .pipe(mocha({report: 'spec'})); +}); + +gulp.task('dev', function() { + gulp.watch(['**/*.js', '!node_modules'], ['lint', 'test']); +}); + +gulp.task('default', ['dev']); diff --git a/package.json b/package.json new file mode 100644 index 0000000..2e00943 --- /dev/null +++ b/package.json @@ -0,0 +1,34 @@ +{ + "name": "08-vanilla_rest_api", + "version": "1.0.0", + "description": "", + "main": "gulpfile.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node server.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/jonathanheemstra/08-vanilla_rest_api.git" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/jonathanheemstra/08-vanilla_rest_api/issues" + }, + "homepage": "https://github.com/jonathanheemstra/08-vanilla_rest_api#readme", + "devDependencies": { + "chai": "^3.5.0", + "eslint": "^3.12.2", + "gulp-eslint": "^3.0.1", + "mocha": "^3.2.0", + "superagent": "^3.3.0" + }, + "dependencies": { + "node-uuid": "^1.4.7" + } +} diff --git a/server.js b/server.js new file mode 100644 index 0000000..e69de29 From 1aa757a698cea4ce26c40c5feccdd4cf36beb0bf Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Wed, 14 Dec 2016 17:06:32 -0800 Subject: [PATCH 02/18] set up server --- server.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/server.js b/server.js index e69de29..81c09cd 100644 --- a/server.js +++ b/server.js @@ -0,0 +1,10 @@ +'use strict'; + +const http = require('http'); +const PORT = process.env.PORT || 8080; + +const server = http.createServer(); + +server.listen(PORT, () => { + console.log(`Server is up on ${PORT}`); +}); From 43b1046a5c764b251ea956408f89a204036ed76a Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Wed, 14 Dec 2016 18:10:47 -0800 Subject: [PATCH 03/18] set up parse json file --- lab-08_in_memory_resource_api.md | 10 +++++----- lib/parse-json.js | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 lib/parse-json.js diff --git a/lab-08_in_memory_resource_api.md b/lab-08_in_memory_resource_api.md index c488aaa..d64a202 100644 --- a/lab-08_in_memory_resource_api.md +++ b/lab-08_in_memory_resource_api.md @@ -18,11 +18,11 @@ * `README.md` ## Description -* Create the following directories to organize your code: - * `lib` - * `model` - * `test` -* Create an HTTP server using the native NodeJS `http` module +* [x] Create the following directories to organize your code: + * [x] `lib` + * [x] `model` + * [x] `test` +* [x] Create an HTTP server using the native NodeJS `http` module * Create an object constructor that creates a _simple resource_ with at least 3 properties * include an `id` property that is set to a unique id (**hint:** you'll need to use `node-uuid`) * include two additional properties of your choice (ex: name, content, etc.) diff --git a/lib/parse-json.js b/lib/parse-json.js new file mode 100644 index 0000000..d6bf4bd --- /dev/null +++ b/lib/parse-json.js @@ -0,0 +1,30 @@ +'use strict'; + +module.exports = function(req) { + return new Promise( (resolve, reject) => { + if(req.method === 'POST' || req.method === 'PUT') { + var body = ''; + + req.on('data', data => { + body += data.toString(); + }); + + req.on('end', () => { + try { + req.body = JSON.parse(body); + resolve(req); + } catch(err) { + console.error(err); + reject(err); + } + }); + + req.on('end', err => { + console.error(err); + reject(err); + }); + + return; + } + }); +}; From d5d1bee5f775f20d0c8b451de91a46c56eb4bf6f Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Wed, 14 Dec 2016 18:16:28 -0800 Subject: [PATCH 04/18] set up parse url --- lib/parse-url.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 lib/parse-url.js diff --git a/lib/parse-url.js b/lib/parse-url.js new file mode 100644 index 0000000..3c88889 --- /dev/null +++ b/lib/parse-url.js @@ -0,0 +1,10 @@ +'use strict'; + +const parseURL = require('url').parse; +const parseQuery = require('querystring').parse; + +module.exports = function(req) { + req.url = parseURL(req.url); + req.url.query = parseQuery(req.url.query); + return Promise.resolve(req); +}; From 7e917501d26ea3169257aa58db9c958311a2fe73 Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Wed, 14 Dec 2016 18:25:32 -0800 Subject: [PATCH 05/18] set up ski data model --- model/ski-data.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 model/ski-data.js diff --git a/model/ski-data.js b/model/ski-data.js new file mode 100644 index 0000000..d99d1ec --- /dev/null +++ b/model/ski-data.js @@ -0,0 +1,15 @@ +'use strict'; + +const uuid = require('node-uuid'); + +module.exports = function(location, rating, lat, long) { + if(!location) throw new Error('expected location'); + if(!rating) throw new Error('expected rating'); + if(!lat) throw new Error('expected lat data'); + if(!long) throw new Error('expected long data'); + + this.id = uuid.v4(); + this.location = location; + this.rating = rating; + this.latlong = [lat, long]; +}; From bf9d107560667629eff0d938d41584bb6ca61385 Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Wed, 14 Dec 2016 19:00:02 -0800 Subject: [PATCH 06/18] build router for app --- lib/router.js | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 lib/router.js diff --git a/lib/router.js b/lib/router.js new file mode 100644 index 0000000..9421f83 --- /dev/null +++ b/lib/router.js @@ -0,0 +1,54 @@ +'use strict'; + +const parseURL = require('./parse-url.js'); +const parseJSON = require('./parse-json.js'); + +const Router = module.exports = function() { + this.routes = { + GET: {}, + POST: {}, + PUT: {}, + DELETE: {} + }; +}; + +Router.prototype.get = (endpoint, callback) => { + this.routes.GET[endpoint] = callback; +}; + +Router.prototype.post = (endpoint, callback) => { + this.routes.POST[endpoint] = callback; +}; + +Router.prototype.put = (endpoint, callback) => { + this.routes.PUT[endpoint] = callback; +}; + +Router.prototype.delete = (endpoint, callback) => { + this.routes.DELETE[endpoint] = callback; +}; + +Router.prototype.route = () => { + return (req, res) => { + Promise.all([ + parseURL(req), + parseJSON(req) + ]) + .then(() => { + if(typeof this.routes[req.method][req.url.pathname] === 'function') { + this.routes[req.method][req.url.pathname](req, res); + return; + } + console.error('route not found'); + res.writeHead(404, {'Content-Type': 'text/plain'}); + res.write('route not found'); + res.end(); + }) + .catch( err => { + console.error(err); + res.writeHead(400, {'Content-Type': 'text/plain'}); + res.write('bad request'); + res.end(); + }); + }; +}; From c555b7bfb103fe7a20651f982ebfb619ad3aecc7 Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Wed, 14 Dec 2016 19:11:42 -0800 Subject: [PATCH 07/18] set up routes on server file --- server.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/server.js b/server.js index 81c09cd..e8b9385 100644 --- a/server.js +++ b/server.js @@ -1,8 +1,28 @@ 'use strict'; const http = require('http'); +const SkiData = require('./model/ski-data.js'); +const Router = require('./lib/router.js'); const PORT = process.env.PORT || 8080; +const routes = new Router(); + +routes.get('/api/ski-data', (req, res) => { + +}); + +routes.post('/api/ski-data', (req, res) => { + +}); + +routes.put('/api/ski-data', (req, res) => { + +}); + +routes.delete('/api/ski-data', (req, res) => { + +}); + const server = http.createServer(); server.listen(PORT, () => { From 0ded4899d52d404d8fdd2106f2dad889655d0d65 Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Wed, 14 Dec 2016 20:45:53 -0800 Subject: [PATCH 08/18] set up data storage --- lib/data.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 lib/data.js diff --git a/lib/data.js b/lib/data.js new file mode 100644 index 0000000..82f968a --- /dev/null +++ b/lib/data.js @@ -0,0 +1,29 @@ +'use strict'; + +const data = {}; + +module.exports = exports = {}; + +exports.setData = (schemaName, item) => { + if(!schemaName) return Promise.reject(new Error('Expected schema name but was not provided one')); + if(!item) return Promise.reject(new Error('Expected item but was not provided one')); + if(!data[schemaName]) data[schemaName] = {}; + + data[schemaName][item.id] = item; + return Promise.resolve(item); +}; + +exports.getData = (schemaName, id) => { + return new Promise((resolve, reject) => { + if(!schemaName) return reject(new Error('Expected schema name but was not provided one')); + if(!id) return reject(new Error('Expected id but was not provided one')); + + var schema = data[schemaName]; + if(!schema) return reject(new Error('schema not found')); + + var item = schema[id]; + if(!item) return reject(new Error('item not found')); + + resolve(item); + }); +}; From d5073447f0be1914d856372a56b5d99c283b2c8b Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Thu, 15 Dec 2016 10:17:08 -0800 Subject: [PATCH 09/18] add routes to server.js --- lib/parse-json.js | 9 +++++++-- lib/router.js | 19 ++++++++++++------- model/ski-data.js | 5 +---- server.js | 43 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 56 insertions(+), 20 deletions(-) diff --git a/lib/parse-json.js b/lib/parse-json.js index d6bf4bd..87be083 100644 --- a/lib/parse-json.js +++ b/lib/parse-json.js @@ -12,19 +12,24 @@ module.exports = function(req) { req.on('end', () => { try { req.body = JSON.parse(body); + console.log('parse-json.js 15 ==========================\r\n', req.body); resolve(req); } catch(err) { + console.log('parse-json.js 18 ==========================\r\n', err); console.error(err); reject(err); } }); - req.on('end', err => { - console.error(err); + req.on('error', err => { + console.log('parse-json.js 25 ==========================\r\n', err); + // console.error(err); reject(err); }); return; } + + resolve(); }); }; diff --git a/lib/router.js b/lib/router.js index 9421f83..a45381c 100644 --- a/lib/router.js +++ b/lib/router.js @@ -12,40 +12,45 @@ const Router = module.exports = function() { }; }; -Router.prototype.get = (endpoint, callback) => { +// why can't I use => functions here? +Router.prototype.get = function(endpoint, callback) { this.routes.GET[endpoint] = callback; }; -Router.prototype.post = (endpoint, callback) => { +Router.prototype.post = function(endpoint, callback) { this.routes.POST[endpoint] = callback; }; -Router.prototype.put = (endpoint, callback) => { +Router.prototype.put = function(endpoint, callback) { this.routes.PUT[endpoint] = callback; }; -Router.prototype.delete = (endpoint, callback) => { +Router.prototype.delete = function(endpoint, callback) { this.routes.DELETE[endpoint] = callback; }; -Router.prototype.route = () => { +Router.prototype.route = function() { return (req, res) => { + console.log('router.js 34 ==========================\r\n', req.method); Promise.all([ parseURL(req), parseJSON(req) ]) - .then(() => { + .then( () => { + console.log('router.js 40 ==========================\r\n', this.routes, req.method, req.url.pathname); if(typeof this.routes[req.method][req.url.pathname] === 'function') { this.routes[req.method][req.url.pathname](req, res); return; } + console.log('router.js 45 ==========================\r\n'); console.error('route not found'); res.writeHead(404, {'Content-Type': 'text/plain'}); res.write('route not found'); res.end(); }) .catch( err => { - console.error(err); + console.log('router.js 52 ==========================\r\n', err); + // console.error(err); res.writeHead(400, {'Content-Type': 'text/plain'}); res.write('bad request'); res.end(); diff --git a/model/ski-data.js b/model/ski-data.js index d99d1ec..8d7e072 100644 --- a/model/ski-data.js +++ b/model/ski-data.js @@ -2,14 +2,11 @@ const uuid = require('node-uuid'); -module.exports = function(location, rating, lat, long) { +module.exports = function(location, rating) { if(!location) throw new Error('expected location'); if(!rating) throw new Error('expected rating'); - if(!lat) throw new Error('expected lat data'); - if(!long) throw new Error('expected long data'); this.id = uuid.v4(); this.location = location; this.rating = rating; - this.latlong = [lat, long]; }; diff --git a/server.js b/server.js index e8b9385..9727882 100644 --- a/server.js +++ b/server.js @@ -3,27 +3,56 @@ const http = require('http'); const SkiData = require('./model/ski-data.js'); const Router = require('./lib/router.js'); +const data = require('./lib/data.js'); const PORT = process.env.PORT || 8080; const routes = new Router(); routes.get('/api/ski-data', (req, res) => { - + if(req.url.query.id) { + data.getData('location', req.url.query.id) + .then( skiData => { + res.writeHead(200, {'Content-Type': 'application/json'}); + res.write(JSON.stringify(skiData)); + res.end(); + }) + .catch( err => { + console.log('server.js 20 ==========================\r\n', err); + console.error(err); + res.writeHead(404, {'Content-Type': 'text/plain'}); + res.write('Not found'); + res.end(); + }); + return; + } }); routes.post('/api/ski-data', (req, res) => { - -}); - -routes.put('/api/ski-data', (req, res) => { - + try { + var skiData = new SkiData(req.body.location, req.body.rating); + console.log('server.js 33 ==========================\r\n', skiData); + data.setData('location', skiData); + res.writeHead(200, {'Content-Type': 'application/json'}); + res.write(JSON.stringify(skiData)); + res.end(); + } catch(err) { + console.log('server.js 39 ==========================\r\n', err); + console.error(err); + res.writeHead(400, {'Content-Type': 'text/plain'}); + res.write('bad request'); + res.end(); + } }); +// routes.put('/api/ski-data', (req, res) => { +// +// }); +// routes.delete('/api/ski-data', (req, res) => { }); -const server = http.createServer(); +const server = http.createServer(routes.route()); server.listen(PORT, () => { console.log(`Server is up on ${PORT}`); From 403644463a5e2b7dce07b0f74de1c4901c187504 Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Thu, 15 Dec 2016 11:38:27 -0800 Subject: [PATCH 10/18] set up delete route --- lib/data.js | 14 +++++++++++++- lib/parse-json.js | 5 +---- lib/router.js | 6 +----- server.js | 22 ++++++++++++++++------ 4 files changed, 31 insertions(+), 16 deletions(-) diff --git a/lib/data.js b/lib/data.js index 82f968a..21ac077 100644 --- a/lib/data.js +++ b/lib/data.js @@ -23,7 +23,19 @@ exports.getData = (schemaName, id) => { var item = schema[id]; if(!item) return reject(new Error('item not found')); - resolve(item); }); }; + +exports.removeData = (schemaName, id) => { + return new Promise((resolve, reject) => { + if(!schemaName) return reject(new Error('Expected schema name but was not provided one')); + if(!id) return reject(new Error('Expected id but was not provided one')); + + var schema = data[schemaName]; + if(!schema) return reject(new Error('schema not found')); + + delete schema[id]; + resolve(); + }); +}; diff --git a/lib/parse-json.js b/lib/parse-json.js index 87be083..e6874e8 100644 --- a/lib/parse-json.js +++ b/lib/parse-json.js @@ -12,18 +12,15 @@ module.exports = function(req) { req.on('end', () => { try { req.body = JSON.parse(body); - console.log('parse-json.js 15 ==========================\r\n', req.body); resolve(req); } catch(err) { - console.log('parse-json.js 18 ==========================\r\n', err); console.error(err); reject(err); } }); req.on('error', err => { - console.log('parse-json.js 25 ==========================\r\n', err); - // console.error(err); + console.error(err); reject(err); }); diff --git a/lib/router.js b/lib/router.js index a45381c..cec8654 100644 --- a/lib/router.js +++ b/lib/router.js @@ -31,26 +31,22 @@ Router.prototype.delete = function(endpoint, callback) { Router.prototype.route = function() { return (req, res) => { - console.log('router.js 34 ==========================\r\n', req.method); Promise.all([ parseURL(req), parseJSON(req) ]) .then( () => { - console.log('router.js 40 ==========================\r\n', this.routes, req.method, req.url.pathname); if(typeof this.routes[req.method][req.url.pathname] === 'function') { this.routes[req.method][req.url.pathname](req, res); return; } - console.log('router.js 45 ==========================\r\n'); console.error('route not found'); res.writeHead(404, {'Content-Type': 'text/plain'}); res.write('route not found'); res.end(); }) .catch( err => { - console.log('router.js 52 ==========================\r\n', err); - // console.error(err); + console.error(err); res.writeHead(400, {'Content-Type': 'text/plain'}); res.write('bad request'); res.end(); diff --git a/server.js b/server.js index 9727882..b872732 100644 --- a/server.js +++ b/server.js @@ -17,7 +17,6 @@ routes.get('/api/ski-data', (req, res) => { res.end(); }) .catch( err => { - console.log('server.js 20 ==========================\r\n', err); console.error(err); res.writeHead(404, {'Content-Type': 'text/plain'}); res.write('Not found'); @@ -30,13 +29,11 @@ routes.get('/api/ski-data', (req, res) => { routes.post('/api/ski-data', (req, res) => { try { var skiData = new SkiData(req.body.location, req.body.rating); - console.log('server.js 33 ==========================\r\n', skiData); data.setData('location', skiData); res.writeHead(200, {'Content-Type': 'application/json'}); res.write(JSON.stringify(skiData)); res.end(); } catch(err) { - console.log('server.js 39 ==========================\r\n', err); console.error(err); res.writeHead(400, {'Content-Type': 'text/plain'}); res.write('bad request'); @@ -45,11 +42,24 @@ routes.post('/api/ski-data', (req, res) => { }); // routes.put('/api/ski-data', (req, res) => { -// +//TODO: add put route // }); -// -routes.delete('/api/ski-data', (req, res) => { +routes.delete('/api/ski-data', (req, res) => { + if(req.url.query.id) { + data.removeData('location', req.url.query.id) + .then( () => { + res.writeHead(204, {'Content-Type': 'application/json'}); + res.end(); + }) + .catch( err => { + console.error(err); + res.writeHead(404, {'Content-Type': 'text/plain'}); + res.write('Not found'); + res.end(); + }); + return; + } }); const server = http.createServer(routes.route()); From e77e640b9f9c69d6d7d4a795d106b5c078d2f2c9 Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Thu, 15 Dec 2016 11:55:15 -0800 Subject: [PATCH 11/18] add testing --- test/tests.js | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 test/tests.js diff --git a/test/tests.js b/test/tests.js new file mode 100644 index 0000000..de228f5 --- /dev/null +++ b/test/tests.js @@ -0,0 +1,46 @@ +'use strict'; + +const request = require('superagent'); +const expect = require('chai').expect; +require('../server.js'); + +describe('Data routes', function() { + var data = null; + + describe('POST: /api/ski-data', function() { + it('should return a data object', function(done) { + request.post('localhost:3000/api/ski-data') + .send({location: 'Mt baker', rating: 10}) + .end((err, res) => { + if(err) return done(err); + expect(res.status).to.equal(200); + expect(res.body.location).to.equal('Mt baker'); + expect(res.body.rating).to.equal(10); + data = res.body; + done(); + }); + }); + }); + describe('GET: /api/ski-data', function() { + it('should return a data object', function(done) { + request.get(`localhost:3000/api/ski-data?id=${data.id}`) + .end((err, res) => { + if(err) return done(err); + expect(res.status).to.equal(200); + expect(res.body.location).to.equal('Mt baker'); + expect(res.body.rating).to.equal(10); + done(); + }); + }); + }); + describe('DELETE: /api/ski-data', function() { + it('should delete a data object', function(done) { + request.delete(`localhost:3000/api/ski-data?id=${data.id}`) + .end((err, res) => { + if(err) return done(err); + expect(res.status).to.equal(204); + done(); + }); + }); + }); +}); From 6a0b254a5bafc74eca2521384a5f50b1170a57a0 Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Thu, 15 Dec 2016 12:11:00 -0800 Subject: [PATCH 12/18] set up tests --- README.md | 14 +++++++++++++- test/tests.js | 25 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d9cbe6f..26c9b51 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,16 @@ # Vanilla Ski Report REST api ## About -The vanilla Ski Report REST api is built to allow consumers to get valuable ski report data about any area they want to ski in. +The vanilla Ski Report REST api is built to allow consumers to get valuable ski report data about any area they want to ski in. The api will respond to any of the following commands `GET`, `POST`, `DELETE`. The routes on the api are currently set to be reachable at `localhost:/api/ski-data`. In order for this API to work you will need to `npm i` to install `node-uuid`, which is required to run this API. You will also need HTTPie installed globally on your machine in order for the API responses to reach your terminal correctly. + +## API Commands +* `POST`: `http POST localhost:/api/ski-data location='' rating=''` + * This will return a header with status code and a JSON representation of the data you just added. + * The data returned will also return an `id:` property that will be contained in the JSON. In order to `GET` a specific piece of data you will need this `id:` +* `GET`: `http localhost:/api/ski-data?id=` + * This will return a header with status code and a JSON representation of the data you just requested. + * If you request an object that does not exist then the api will return 404. + * If you run a bad `GET` method and do not pass an `id` the api will return 400. +* `DELETE`: `http DELETE localhost:/api/ski-data?id=` + * This will return a header with a status code of 204. + * The object deleted will be removed for the database. diff --git a/test/tests.js b/test/tests.js index de228f5..330e04f 100644 --- a/test/tests.js +++ b/test/tests.js @@ -20,6 +20,15 @@ describe('Data routes', function() { done(); }); }); + it('should return a data object', function(done) { + request.post('localhost:3000/api/ski-data') + .send({rating: 10}) + .end((err, res) => { + if(err) return done(err); + expect(res.status).to.equal(400); + done(); + }); + }); }); describe('GET: /api/ski-data', function() { it('should return a data object', function(done) { @@ -32,6 +41,22 @@ describe('Data routes', function() { done(); }); }); + it('should return a 404 error', function(done) { + request.get('localhost:3000/api/ski-data?id=123456789') + .end((err, res) => { + if(err) return done(err); + expect(res.status).to.equal(404); + done(); + }); + }); + it('should return a 400 error', function(done) { + request.get('localhost:3000/api/ski-data?id=') + .end((err, res) => { + if(err) return done(err); + expect(res.status).to.equal(400); + done(); + }); + }); }); describe('DELETE: /api/ski-data', function() { it('should delete a data object', function(done) { From 6c5738b759aec9bef1e3ea9758aff2431b5ad676 Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Thu, 15 Dec 2016 12:57:13 -0800 Subject: [PATCH 13/18] fix tests --- server.js | 5 +++++ test/tests.js | 13 +++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/server.js b/server.js index b872732..9ac2165 100644 --- a/server.js +++ b/server.js @@ -24,6 +24,11 @@ routes.get('/api/ski-data', (req, res) => { }); return; } + if(!req.url.query.id) { + res.writeHead(400, {'Content-Type': 'text/plain'}); + res.write('bad request'); + res.end(); + } }); routes.post('/api/ski-data', (req, res) => { diff --git a/test/tests.js b/test/tests.js index 330e04f..ee1956e 100644 --- a/test/tests.js +++ b/test/tests.js @@ -22,9 +22,8 @@ describe('Data routes', function() { }); it('should return a data object', function(done) { request.post('localhost:3000/api/ski-data') - .send({rating: 10}) - .end((err, res) => { - if(err) return done(err); + .send({location: 'mt baker'}) + .end((res) => { expect(res.status).to.equal(400); done(); }); @@ -43,16 +42,14 @@ describe('Data routes', function() { }); it('should return a 404 error', function(done) { request.get('localhost:3000/api/ski-data?id=123456789') - .end((err, res) => { - if(err) return done(err); + .end((res) => { expect(res.status).to.equal(404); done(); }); }); it('should return a 400 error', function(done) { - request.get('localhost:3000/api/ski-data?id=') - .end((err, res) => { - if(err) return done(err); + request.get('localhost:3000/api/ski-data') + .end((res) => { expect(res.status).to.equal(400); done(); }); From 48663fccf646e4687242ace95532e3dfd7fa6489 Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Thu, 15 Dec 2016 16:35:10 -0800 Subject: [PATCH 14/18] scaffold files for lab 9 --- .gitignore | 4 ++++ lib/response.js | 0 package.json | 1 + routes/routes.js | 0 4 files changed, 5 insertions(+) create mode 100644 lib/response.js create mode 100644 routes/routes.js diff --git a/.gitignore b/.gitignore index 84cac89..aa783c3 100644 --- a/.gitignore +++ b/.gitignore @@ -103,6 +103,10 @@ $RECYCLE.BIN/ ### Linux ### *~ + +### Extra ignore ### +.console.js + # temporary files which can be created if a process still has a handle open of a deleted file .fuse_hidden* diff --git a/lib/response.js b/lib/response.js new file mode 100644 index 0000000..e69de29 diff --git a/package.json b/package.json index 2e00943..7185eeb 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "superagent": "^3.3.0" }, "dependencies": { + "bluebird": "^3.4.6", "node-uuid": "^1.4.7" } } diff --git a/routes/routes.js b/routes/routes.js new file mode 100644 index 0000000..e69de29 From 0d02d42d8f27e9174150c1401715c461e7498394 Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Thu, 15 Dec 2016 16:42:30 -0800 Subject: [PATCH 15/18] set up routes file --- package.json | 1 + routes/routes.js | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ server.js | 62 +-------------------------------------------- 3 files changed, 67 insertions(+), 61 deletions(-) diff --git a/package.json b/package.json index 7185eeb..698676e 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "devDependencies": { "chai": "^3.5.0", "eslint": "^3.12.2", + "gulp": "^3.9.1", "gulp-eslint": "^3.0.1", "mocha": "^3.2.0", "superagent": "^3.3.0" diff --git a/routes/routes.js b/routes/routes.js index e69de29..abf5270 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -0,0 +1,65 @@ +'use strict'; + +const data = require('../lib/data.js'); +const SkiData = require('../model/ski-data.js'); + +module.exports = function(routes){ + routes.get('/api/ski-data', (req, res) => { + if(req.url.query.id) { + data.getData('location', req.url.query.id) + .then( skiData => { + res.writeHead(200, {'Content-Type': 'application/json'}); + res.write(JSON.stringify(skiData)); + res.end(); + }) + .catch( err => { + console.error(err); + res.writeHead(404, {'Content-Type': 'text/plain'}); + res.write('Not found'); + res.end(); + }); + return; + } + if(!req.url.query.id) { + res.writeHead(400, {'Content-Type': 'text/plain'}); + res.write('bad request'); + res.end(); + } + }); + + routes.post('/api/ski-data', (req, res) => { + try { + var skiData = new SkiData(req.body.location, req.body.rating); + data.setData('location', skiData); + res.writeHead(200, {'Content-Type': 'application/json'}); + res.write(JSON.stringify(skiData)); + res.end(); + } catch(err) { + console.error(err); + res.writeHead(400, {'Content-Type': 'text/plain'}); + res.write('bad request'); + res.end(); + } + }); + + // routes.put('/api/ski-data', (req, res) => { + //TODO: add put route + // }); + + routes.delete('/api/ski-data', (req, res) => { + if(req.url.query.id) { + data.removeData('location', req.url.query.id) + .then( () => { + res.writeHead(204, {'Content-Type': 'application/json'}); + res.end(); + }) + .catch( err => { + console.error(err); + res.writeHead(404, {'Content-Type': 'text/plain'}); + res.write('Not found'); + res.end(); + }); + return; + } + }); +}; diff --git a/server.js b/server.js index 9ac2165..f6d075e 100644 --- a/server.js +++ b/server.js @@ -1,71 +1,11 @@ 'use strict'; const http = require('http'); -const SkiData = require('./model/ski-data.js'); const Router = require('./lib/router.js'); -const data = require('./lib/data.js'); const PORT = process.env.PORT || 8080; - const routes = new Router(); -routes.get('/api/ski-data', (req, res) => { - if(req.url.query.id) { - data.getData('location', req.url.query.id) - .then( skiData => { - res.writeHead(200, {'Content-Type': 'application/json'}); - res.write(JSON.stringify(skiData)); - res.end(); - }) - .catch( err => { - console.error(err); - res.writeHead(404, {'Content-Type': 'text/plain'}); - res.write('Not found'); - res.end(); - }); - return; - } - if(!req.url.query.id) { - res.writeHead(400, {'Content-Type': 'text/plain'}); - res.write('bad request'); - res.end(); - } -}); - -routes.post('/api/ski-data', (req, res) => { - try { - var skiData = new SkiData(req.body.location, req.body.rating); - data.setData('location', skiData); - res.writeHead(200, {'Content-Type': 'application/json'}); - res.write(JSON.stringify(skiData)); - res.end(); - } catch(err) { - console.error(err); - res.writeHead(400, {'Content-Type': 'text/plain'}); - res.write('bad request'); - res.end(); - } -}); - -// routes.put('/api/ski-data', (req, res) => { -//TODO: add put route -// }); - -routes.delete('/api/ski-data', (req, res) => { - if(req.url.query.id) { - data.removeData('location', req.url.query.id) - .then( () => { - res.writeHead(204, {'Content-Type': 'application/json'}); - res.end(); - }) - .catch( err => { - console.error(err); - res.writeHead(404, {'Content-Type': 'text/plain'}); - res.write('Not found'); - res.end(); - }); - return; - } -}); +require('./routes/routes.js')(routes); const server = http.createServer(routes.route()); From b3045ef3134c434d3678c8667529cd6574631e9a Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Thu, 15 Dec 2016 16:59:17 -0800 Subject: [PATCH 16/18] add response file --- gulpfile.js | 3 ++- lib/response.js | 15 +++++++++++++++ routes/routes.js | 31 +++++++++++-------------------- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 11af581..e1b95d1 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -2,6 +2,7 @@ const gulp = require('gulp'); const eslint = require('gulp-eslint'); +const mocha = require('mocha'); gulp.task('lint', function() { gulp.src(['**/*.js', '!node_modules']) @@ -11,7 +12,7 @@ gulp.task('lint', function() { }); gulp.task('test', function() { - gulp.src('./test/*-test.js', {read:false}) + gulp.src(['./test/*test.js','!node_modules'], {read:false}) .pipe(mocha({report: 'spec'})); }); diff --git a/lib/response.js b/lib/response.js index e69de29..3c126ae 100644 --- a/lib/response.js +++ b/lib/response.js @@ -0,0 +1,15 @@ +'use strict'; + +module.exports = exports = {}; + +exports.JSON = function(res, status, data) { + res.writeHead(status, {'Content-Type': 'application/json'}); + res.write(JSON.stringify(data)); + res.end(); +}; + +exports.text = function(res, status, msg) { + res.writeHead(status, {'Content-Type': 'text/plain'}); + res.write(msg); + res.end(); +}; diff --git a/routes/routes.js b/routes/routes.js index abf5270..b0b77db 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -2,28 +2,23 @@ const data = require('../lib/data.js'); const SkiData = require('../model/ski-data.js'); +const response = require('../lib/response.js'); module.exports = function(routes){ routes.get('/api/ski-data', (req, res) => { if(req.url.query.id) { data.getData('location', req.url.query.id) .then( skiData => { - res.writeHead(200, {'Content-Type': 'application/json'}); - res.write(JSON.stringify(skiData)); - res.end(); + response.JSON(res, 200, skiData); }) .catch( err => { console.error(err); - res.writeHead(404, {'Content-Type': 'text/plain'}); - res.write('Not found'); - res.end(); + response.text(res, 404, 'Not found'); }); return; } if(!req.url.query.id) { - res.writeHead(400, {'Content-Type': 'text/plain'}); - res.write('bad request'); - res.end(); + response.text(res, 400, 'Bad request'); } }); @@ -31,14 +26,10 @@ module.exports = function(routes){ try { var skiData = new SkiData(req.body.location, req.body.rating); data.setData('location', skiData); - res.writeHead(200, {'Content-Type': 'application/json'}); - res.write(JSON.stringify(skiData)); - res.end(); + response.JSON(res, 200, skiData); } catch(err) { console.error(err); - res.writeHead(400, {'Content-Type': 'text/plain'}); - res.write('bad request'); - res.end(); + response.text(res, 400, 'Bad request'); } }); @@ -50,16 +41,16 @@ module.exports = function(routes){ if(req.url.query.id) { data.removeData('location', req.url.query.id) .then( () => { - res.writeHead(204, {'Content-Type': 'application/json'}); - res.end(); + response.JSON(res, 204, 'No content'); }) .catch( err => { console.error(err); - res.writeHead(404, {'Content-Type': 'text/plain'}); - res.write('Not found'); - res.end(); + response.text(res, 404, 'Not found'); }); return; } + if(!req.url.query.id) { + response.text(res, 400, 'Bad request'); + } }); }; From 77ff834681133939b30f52a00c666a7ba77734e9 Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Thu, 15 Dec 2016 17:33:35 -0800 Subject: [PATCH 17/18] successfully refactored --- .../5d25c28d-0473-4bea-ae78-6b469b8035c3.json | 1 + .../82007ecc-4bf0-4207-8b59-f6b1c09b06a0.json | 1 + .../8b6a4e5c-0bc0-4d57-978d-9fa88fb67e4c.json | 1 + lib/data.js | 44 +++++++++---------- lib/router.js | 10 ++--- package.json | 1 + test/tests.js | 2 +- 7 files changed, 28 insertions(+), 32 deletions(-) create mode 100644 data/location/5d25c28d-0473-4bea-ae78-6b469b8035c3.json create mode 100644 data/location/82007ecc-4bf0-4207-8b59-f6b1c09b06a0.json create mode 100644 data/location/8b6a4e5c-0bc0-4d57-978d-9fa88fb67e4c.json diff --git a/data/location/5d25c28d-0473-4bea-ae78-6b469b8035c3.json b/data/location/5d25c28d-0473-4bea-ae78-6b469b8035c3.json new file mode 100644 index 0000000..136cb71 --- /dev/null +++ b/data/location/5d25c28d-0473-4bea-ae78-6b469b8035c3.json @@ -0,0 +1 @@ +{"id":"5d25c28d-0473-4bea-ae78-6b469b8035c3","location":"mt baker","rating":"5"} \ No newline at end of file diff --git a/data/location/82007ecc-4bf0-4207-8b59-f6b1c09b06a0.json b/data/location/82007ecc-4bf0-4207-8b59-f6b1c09b06a0.json new file mode 100644 index 0000000..7ac39f9 --- /dev/null +++ b/data/location/82007ecc-4bf0-4207-8b59-f6b1c09b06a0.json @@ -0,0 +1 @@ +{"id":"82007ecc-4bf0-4207-8b59-f6b1c09b06a0","location":"Mt baker","rating":10} \ No newline at end of file diff --git a/data/location/8b6a4e5c-0bc0-4d57-978d-9fa88fb67e4c.json b/data/location/8b6a4e5c-0bc0-4d57-978d-9fa88fb67e4c.json new file mode 100644 index 0000000..a091d46 --- /dev/null +++ b/data/location/8b6a4e5c-0bc0-4d57-978d-9fa88fb67e4c.json @@ -0,0 +1 @@ +{"id":"8b6a4e5c-0bc0-4d57-978d-9fa88fb67e4c","location":"mt baker","rating":"5"} \ No newline at end of file diff --git a/lib/data.js b/lib/data.js index 21ac077..0107737 100644 --- a/lib/data.js +++ b/lib/data.js @@ -1,41 +1,37 @@ 'use strict'; -const data = {}; +const Promise = require('bluebird'); +const fs = Promise.promisifyAll(require('fs'), {suffix: 'Prom'}); module.exports = exports = {}; exports.setData = (schemaName, item) => { if(!schemaName) return Promise.reject(new Error('Expected schema name but was not provided one')); if(!item) return Promise.reject(new Error('Expected item but was not provided one')); - if(!data[schemaName]) data[schemaName] = {}; - data[schemaName][item.id] = item; - return Promise.resolve(item); + let json = JSON.stringify(item); + return fs.writeFileProm(`${__dirname}/../data/${schemaName}/${item.id}.json`, json) + .then( () => item) + .catch( err => Promise.reject(err)); }; exports.getData = (schemaName, id) => { - return new Promise((resolve, reject) => { - if(!schemaName) return reject(new Error('Expected schema name but was not provided one')); - if(!id) return reject(new Error('Expected id but was not provided one')); - - var schema = data[schemaName]; - if(!schema) return reject(new Error('schema not found')); - - var item = schema[id]; - if(!item) return reject(new Error('item not found')); - resolve(item); - }); + if(!schemaName) return Promise.reject(new Error('Expected schema name but was not provided one')); + if(!id) return Promise.reject(new Error('Expected id but was not provided one')); + + return fs.readFileProm(`${__dirname}/../data/${schemaName}/${id}.json`) + .then( data => { + let item = JSON.parse(data.toString()); + return item; + }) + .catch( err => Promise.reject(err)); }; exports.removeData = (schemaName, id) => { - return new Promise((resolve, reject) => { - if(!schemaName) return reject(new Error('Expected schema name but was not provided one')); - if(!id) return reject(new Error('Expected id but was not provided one')); - - var schema = data[schemaName]; - if(!schema) return reject(new Error('schema not found')); + if(!schemaName) return Promise.reject(new Error('Expected schema name but was not provided one')); + if(!id) return Promise.reject(new Error('Expected id but was not provided one')); - delete schema[id]; - resolve(); - }); + return fs.unlinkProm(`${__dirname}/../data/${schemaName}/${id}.json`) + .then( () => id) + .catch( err => Promise.reject(err)); }; diff --git a/lib/router.js b/lib/router.js index cec8654..b514f4a 100644 --- a/lib/router.js +++ b/lib/router.js @@ -2,6 +2,7 @@ const parseURL = require('./parse-url.js'); const parseJSON = require('./parse-json.js'); +const response = require('../lib/response.js'); const Router = module.exports = function() { this.routes = { @@ -12,7 +13,6 @@ const Router = module.exports = function() { }; }; -// why can't I use => functions here? Router.prototype.get = function(endpoint, callback) { this.routes.GET[endpoint] = callback; }; @@ -41,15 +41,11 @@ Router.prototype.route = function() { return; } console.error('route not found'); - res.writeHead(404, {'Content-Type': 'text/plain'}); - res.write('route not found'); - res.end(); + response.text(res, 404, 'Not found'); }) .catch( err => { console.error(err); - res.writeHead(400, {'Content-Type': 'text/plain'}); - res.write('bad request'); - res.end(); + response.text(res, 400, 'Bad request'); }); }; }; diff --git a/package.json b/package.json index 698676e..513c6d9 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ }, "dependencies": { "bluebird": "^3.4.6", + "cowsay": "^1.1.9", "node-uuid": "^1.4.7" } } diff --git a/test/tests.js b/test/tests.js index ee1956e..81e0458 100644 --- a/test/tests.js +++ b/test/tests.js @@ -2,7 +2,7 @@ const request = require('superagent'); const expect = require('chai').expect; -require('../server.js'); +// require('../server.js'); describe('Data routes', function() { var data = null; From 3a6aa70949bbba111b1546da99793bddcaa08578 Mon Sep 17 00:00:00 2001 From: Jonathan Heemstra Date: Fri, 16 Dec 2016 11:04:55 -0800 Subject: [PATCH 18/18] readme updated --- README.md | 21 +++++++++++++++---- .../5d25c28d-0473-4bea-ae78-6b469b8035c3.json | 1 - lib/data.js | 1 - package.json | 1 - routes/routes.js | 11 ++-------- server.js | 2 +- test/tests.js | 13 ++++++------ 7 files changed, 27 insertions(+), 23 deletions(-) delete mode 100644 data/location/5d25c28d-0473-4bea-ae78-6b469b8035c3.json diff --git a/README.md b/README.md index 26c9b51..691786d 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,29 @@ # Vanilla Ski Report REST api ## About -The vanilla Ski Report REST api is built to allow consumers to get valuable ski report data about any area they want to ski in. The api will respond to any of the following commands `GET`, `POST`, `DELETE`. The routes on the api are currently set to be reachable at `localhost:/api/ski-data`. In order for this API to work you will need to `npm i` to install `node-uuid`, which is required to run this API. You will also need HTTPie installed globally on your machine in order for the API responses to reach your terminal correctly. +The vanilla Ski Report REST api is built to allow consumers to get valuable ski report data about any area they want to ski in. The api will respond to any of the following commands `GET`, `POST`, `DELETE`. The routes on the api are currently set to be reachable at `localhost:/api/ski-data`. In order for this API to work you will need to `npm i` to install `node-uuid` and `bluebird`, which is required to run this API. You will also need HTTPie installed globally on your machine in order for the API responses to reach your terminal correctly. + +## Current Version (0.1.0) +* The current version of this application will persist user data locally on the users file system. Users can `POST`, `GET`, and `DELETE` files. + +## Setting up Vanilla Ski Report REST api on your local machine +* Fork this repo +* `git clone` the forked copy to your local machine +* Node is required to run the server. Confirm you have `node` installed on your local machine by typing `npm -v` into your terminal. If you don't have node installed please follow the instructions [here](https://nodejs.org/en/). +* Install the dependencies of `node-uuid` and `bluebird` by running `npm i`. +* In order to turn on the server you will need to run either `nodemon server.js` or `node server.js` if you do not have nodemon installed globally. + * When you start the server via `node server.js` the port number should be printed to the terminal console. You will need to provide this to any users wanting to connect. ## API Commands -* `POST`: `http POST localhost:/api/ski-data location='' rating=''` +* `POST`: `http POST localhost:/api/ski-data location='' rating=` * This will return a header with status code and a JSON representation of the data you just added. - * The data returned will also return an `id:` property that will be contained in the JSON. In order to `GET` a specific piece of data you will need this `id:` + * The `POST` will write a file to the `../data/location/` file saved with `uuid` as the file name. * `GET`: `http localhost:/api/ski-data?id=` * This will return a header with status code and a JSON representation of the data you just requested. - * If you request an object that does not exist then the api will return 404. + * If you request a file via and `id` that does not exist then the api will return 404. * If you run a bad `GET` method and do not pass an `id` the api will return 400. * `DELETE`: `http DELETE localhost:/api/ski-data?id=` * This will return a header with a status code of 204. * The object deleted will be removed for the database. +* `Mocha`: this will run tests set up to validate that the code is working as expected. + * at the time of publication of this README.md all tests are currently passing. diff --git a/data/location/5d25c28d-0473-4bea-ae78-6b469b8035c3.json b/data/location/5d25c28d-0473-4bea-ae78-6b469b8035c3.json deleted file mode 100644 index 136cb71..0000000 --- a/data/location/5d25c28d-0473-4bea-ae78-6b469b8035c3.json +++ /dev/null @@ -1 +0,0 @@ -{"id":"5d25c28d-0473-4bea-ae78-6b469b8035c3","location":"mt baker","rating":"5"} \ No newline at end of file diff --git a/lib/data.js b/lib/data.js index 0107737..d1d27e1 100644 --- a/lib/data.js +++ b/lib/data.js @@ -32,6 +32,5 @@ exports.removeData = (schemaName, id) => { if(!id) return Promise.reject(new Error('Expected id but was not provided one')); return fs.unlinkProm(`${__dirname}/../data/${schemaName}/${id}.json`) - .then( () => id) .catch( err => Promise.reject(err)); }; diff --git a/package.json b/package.json index 513c6d9..698676e 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,6 @@ }, "dependencies": { "bluebird": "^3.4.6", - "cowsay": "^1.1.9", "node-uuid": "^1.4.7" } } diff --git a/routes/routes.js b/routes/routes.js index b0b77db..a81e96d 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -11,8 +11,7 @@ module.exports = function(routes){ .then( skiData => { response.JSON(res, 200, skiData); }) - .catch( err => { - console.error(err); + .catch( () => { response.text(res, 404, 'Not found'); }); return; @@ -28,23 +27,17 @@ module.exports = function(routes){ data.setData('location', skiData); response.JSON(res, 200, skiData); } catch(err) { - console.error(err); response.text(res, 400, 'Bad request'); } }); - // routes.put('/api/ski-data', (req, res) => { - //TODO: add put route - // }); - routes.delete('/api/ski-data', (req, res) => { if(req.url.query.id) { data.removeData('location', req.url.query.id) .then( () => { response.JSON(res, 204, 'No content'); }) - .catch( err => { - console.error(err); + .catch( () => { response.text(res, 404, 'Not found'); }); return; diff --git a/server.js b/server.js index f6d075e..76c4bf1 100644 --- a/server.js +++ b/server.js @@ -2,7 +2,7 @@ const http = require('http'); const Router = require('./lib/router.js'); -const PORT = process.env.PORT || 8080; +const PORT = process.env.PORT || 3000; const routes = new Router(); require('./routes/routes.js')(routes); diff --git a/test/tests.js b/test/tests.js index 81e0458..1bbe748 100644 --- a/test/tests.js +++ b/test/tests.js @@ -2,6 +2,7 @@ const request = require('superagent'); const expect = require('chai').expect; +const PORT = process.env.PORT || 3000; // require('../server.js'); describe('Data routes', function() { @@ -9,7 +10,7 @@ describe('Data routes', function() { describe('POST: /api/ski-data', function() { it('should return a data object', function(done) { - request.post('localhost:3000/api/ski-data') + request.post(`localhost:${PORT}/api/ski-data`) .send({location: 'Mt baker', rating: 10}) .end((err, res) => { if(err) return done(err); @@ -21,7 +22,7 @@ describe('Data routes', function() { }); }); it('should return a data object', function(done) { - request.post('localhost:3000/api/ski-data') + request.post(`localhost:${PORT}/api/ski-data`) .send({location: 'mt baker'}) .end((res) => { expect(res.status).to.equal(400); @@ -31,7 +32,7 @@ describe('Data routes', function() { }); describe('GET: /api/ski-data', function() { it('should return a data object', function(done) { - request.get(`localhost:3000/api/ski-data?id=${data.id}`) + request.get(`localhost:${PORT}/api/ski-data?id=${data.id}`) .end((err, res) => { if(err) return done(err); expect(res.status).to.equal(200); @@ -41,14 +42,14 @@ describe('Data routes', function() { }); }); it('should return a 404 error', function(done) { - request.get('localhost:3000/api/ski-data?id=123456789') + request.get(`localhost:${PORT}/api/ski-data?id=123456789`) .end((res) => { expect(res.status).to.equal(404); done(); }); }); it('should return a 400 error', function(done) { - request.get('localhost:3000/api/ski-data') + request.get(`localhost:${PORT}/api/ski-data`) .end((res) => { expect(res.status).to.equal(400); done(); @@ -57,7 +58,7 @@ describe('Data routes', function() { }); describe('DELETE: /api/ski-data', function() { it('should delete a data object', function(done) { - request.delete(`localhost:3000/api/ski-data?id=${data.id}`) + request.delete(`localhost:${PORT}/api/ski-data?id=${data.id}`) .end((err, res) => { if(err) return done(err); expect(res.status).to.equal(204);