Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f4e2383
Initial scaffold.
BatemanVO Dec 21, 2016
ec17a53
Created initial server file.
BatemanVO Dec 21, 2016
a30b8f7
Updated package.json with npm scripts.
BatemanVO Dec 21, 2016
f60c027
Replaced debug with console.log in app.listen.
BatemanVO Dec 21, 2016
cf68612
Created student constructor.
BatemanVO Dec 21, 2016
88994ac
Updated constructor with debug and error handling.
BatemanVO Dec 21, 2016
06f5870
Added createItem method to storage.js.
BatemanVO Dec 21, 2016
bea83ef
Added getItem method to storage.js.
BatemanVO Dec 21, 2016
67825a2
Added updateItem method to storage.js.
BatemanVO Dec 21, 2016
17c56b9
Added getAllItems method to storage.js.
BatemanVO Dec 21, 2016
87cf710
Added getStudent method to Student constructor.
BatemanVO Dec 21, 2016
c9c0b5c
Added readStudent and updateStudent method to Student constructor.
BatemanVO Dec 21, 2016
d362b85
Added readAllStudents method to Student constructor.
BatemanVO Dec 21, 2016
7a7e022
Created error middleware.
BatemanVO Dec 21, 2016
fbeeb36
Created cors middleware.
BatemanVO Dec 21, 2016
a28faea
Required in new middleware in server.js.
BatemanVO Dec 21, 2016
74e28f6
Added router file to route directory.
BatemanVO Dec 21, 2016
a6e4762
Exported and required studentRouter.
BatemanVO Dec 21, 2016
1c6e265
Fixes to updateItem.
BatemanVO Dec 21, 2016
f01c3d2
Added tests for createStudent.
BatemanVO Dec 21, 2016
3d77e1e
Fixed unterminated quote in npm test.
BatemanVO Dec 21, 2016
1a7b5d9
Required server in for tests.
BatemanVO Dec 21, 2016
e4ddd7f
Removed unnecessary after hook in invalid post test.
BatemanVO Dec 21, 2016
607843b
Created tests for GET routes.
BatemanVO Dec 21, 2016
33b23e6
Fixed no ID test.
BatemanVO Dec 21, 2016
decb8ae
Added tests for PUT routes.
BatemanVO Dec 21, 2016
4be7911
Minor corrections.
BatemanVO Dec 21, 2016
4bf42b6
Added tests for DELETE routes.
BatemanVO Dec 21, 2016
97e3ada
Fixed minor issues.
BatemanVO Dec 21, 2016
bce0637
Added README file.
BatemanVO Dec 21, 2016
cee867a
Refactored tests to make use of beforeEach and afterEach.
BatemanVO Dec 21, 2016
b97f4e0
Moved app.use(cors) call.
BatemanVO Dec 21, 2016
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
21 changes: 21 additions & 0 deletions lab-steven/.eslintrc
Original file line number Diff line number Diff line change
@@ -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"
}
113 changes: 113 additions & 0 deletions lab-steven/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@

# Created by https://www.gitignore.io/api/windows,macos,linux,node

### 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


### 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


### 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*


### Node ###
# Logs
logs
*.log
npm-debug.log*

# 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
38 changes: 38 additions & 0 deletions lab-steven/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#Single-Resource API Using Express
###Steven Bateman's lab 12 assignment for JS 401

###Overview
This is a simple, single-resource app that will allow you to practice GET, POST, PUT, and DELETE requests against a single-resource API that collects data on students.

###Installation
To install this app, clone down this repository, navigate to the `lab-steven` directory, then run `npm i`.

###Usage
To start your server, run `npm start`. If you are not interested in seeing debugging messages, you can simply run `node server.js`. You should see a message that says, "Server running on port <port#>".

From there, you can open up another terminal window and connect to your server using HTTPIE. To install HTTPIE:
* For Mac, run `brew install httpie`
* For linux, run `sudo apt install httpie`

###POST requests
There is a layer of persistence with this app through using the file system module, so you will be unable to GET or DELETE any students without first POSTing some. In order to POST a student, you will need to make a POST request to `/api/student` and pass in a JSON object with at least a name and age field. You can include any additional fields as desired, but you must at least have a name and age.

* Example: `http POST localhost:8080/api/student name="Steven" age="30" badass="Definitely"`

###PUT requests
If you want to update a particular student, simply make a request to the API and pass in the student's ID, along with the content you'd like to update.

* Example: `http PUT localhost:8080/api/student/0238b-a97sdf-fdhd-f3893 name="Weasel" age="45"` (will update the student with that ID to have a new name and age of Weasel and 45)

###GET requests
You can make a get request with no headers to receive a list of all IDs that have been POSTed, or you can pass in an ID through the URL to get back a specific student.

* Example: `http localhost:8080/api/student` (returns all student IDs)
* Example: `http localhost:8080/api/student/0238b-a97sdf-fdhd-f3893` (will return a student with that particular ID)

###DELETE requests
You can DELETE a student the same way you make a GET request, by passing in an ID. To delete our example student from the GET request subsection, we could do the following:

* Example: `http DELETE localhost:8080/api/student/0238b-a97sdf-fdhd-f3893`

All students will be stored in the data/student directory until they are DELETED or manually `rm`ed.
1 change: 1 addition & 0 deletions lab-steven/data/student/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This file ensures Github will push up the empty data/student directory.
14 changes: 14 additions & 0 deletions lab-steven/gulpfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict';

const gulp = require('gulp');
const mocha = require('gulp-mocha');

gulp.task('test', function() {
gulp.src('./test/*-test.js', {read: false}).pipe(mocha({reporter: 'spec'}));
});

gulp.task('dev', function() {
gulp.watch(['**/*.js', '!node_modules/**'], ['test']);
});

gulp.task('default', ['dev']);
7 changes: 7 additions & 0 deletions lab-steven/lib/cors-middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

module.exports = function(request, response, next) {
response.append('Access-Control-Allow-Origin', '*');
response.append('Access-Control-Allow-Headers', '*');
next();
};
21 changes: 21 additions & 0 deletions lab-steven/lib/error-middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use strict';

const createError = require('http-errors');
const debug = require('debug')('student:error-middleware');

module.exports = function(err, request, response, next) {
console.error(err.message);

if (err.status) {
debug('User error.');

response.status(err.status).send(err.name);
next();
return;
}

debug('Server error.');
err = createError(500, err.message);
response.status(err.status).send(err.name);
next();
};
67 changes: 67 additions & 0 deletions lab-steven/lib/storage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use strict';

const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'), {suffix: 'Prom'});
const createError = require('http-errors');
const debug = require('debug')('student:storage');

module.exports = exports = {};

exports.createItem = function(schemaName, item) {
debug('Storage.js: createItem method.');

if (!schemaName) throw createError(400, 'Expected a schema name.');
if (!item) throw createError(400, 'Expected an item.');

let stringifiedItem = JSON.stringify(item);
return fs.writeFileProm(`${__dirname}/../data/${schemaName}/${item.id}.json`, stringifiedItem)
.then(() => item)
.catch(err => Promise.reject(createError(500, err.message)));
};

exports.readItem = function(schemaName, id) {
debug('Storage.js: readItem method.');

if (!schemaName) throw createError(400, 'Expected a schema name.');
if (!id) throw createError(400, 'Expected an ID.');

return fs.readFileProm(`${__dirname}/../data/${schemaName}/${id}.json`)
.then(data => JSON.parse(data.toString()))
.catch(err => Promise.reject(createError(404, err.message)));
};

exports.updateItem = function(schemaName, id, content) {
debug('Storage.js: updateItem method.');

if (!schemaName) throw createError(400, 'Expected a schema name.');
if (!id) throw createError(400, 'Expected an ID.');
if (Object.keys(content).length < 1) throw createError(400, 'Expected content to update with.');

return exports.readItem(schemaName, id)
.then(student => {
for (var key in content) {
if (key === 'id') continue;
student[key] = content[key];
}
return exports.createItem(schemaName, student);
})
.catch(err => Promise.reject(createError(404, err.message)));
};

exports.deleteItem = function(schemaName, id) {
debug('Storage.js: deleteItem method.');

if (!schemaName) throw createError(400, 'Expected a schema name.');
if (!id) throw createError(400, 'Expected an ID.');

return fs.unlinkProm(`${__dirname}/../data/${schemaName}/${id}.json`)
.catch(err => Promise.reject(createError(404, err.message)));
};

exports.readAllItems = function(schemaName) {
if (!schemaName) throw createError(400, 'Expected a schema name.');

return fs.readdirProm(`${__dirname}/../data/${schemaName}`)
.then(arrayOfFiles => Promise.resolve(arrayOfFiles.filter(element => element !== '.gitkeep').map(element => element.split('.json')[0])))
.catch(err => Promise.reject(createError(500, err.message)));
};
43 changes: 43 additions & 0 deletions lab-steven/model/student-constructor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict';

const uuid = require('node-uuid');
const debug = require('debug')('student:constructor');
const createError = require('http-errors');
const storage = require('../lib/storage.js');

const Student = module.exports = function(student) {
debug('Student constructor.');

if (!student.name) throw createError(400, 'Expected a name field.');
if (!student.age) throw createError(400, 'Expected an age field.');

this.id = uuid.v1();
for (var key in student) {
this[key] = student[key];
}
};

Student.createStudent = function(student) {
debug('Student constructor: createStudent method.');
return storage.createItem('student', new Student(student));
};

Student.readStudent = function(id) {
debug('Student constructor: readStudent method.');
return storage.readItem('student', id);
};

Student.updateStudent = function(id, content) {
debug('Student constructor: updateStudent method.');
return storage.updateItem('student', id, content);
};

Student.deleteStudent = function(id) {
debug('Student constructor: deleteStudent method.');
return storage.deleteItem('student', id);
};

Student.readAllStudents = function() {
debug('Student constructor: getAllStudents method.');
return storage.readAllItems('student');
};
32 changes: 32 additions & 0 deletions lab-steven/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "lab-steven",
"version": "1.0.0",
"description": "",
"main": "index.js",
"directories": {
"test": "test"
},
"scripts": {
"start": "DEBUG='student*' node server.js",
"test": "DEBUG='student*' mocha"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"chai": "^3.5.0",
"gulp": "^3.9.1",
"gulp-mocha": "^3.0.1",
"mocha": "^3.2.0",
"superagent": "^3.3.1"
},
"dependencies": {
"bluebird": "^3.4.6",
"body-parser": "^1.15.2",
"debug": "^2.4.5",
"express": "^4.14.0",
"http-errors": "^1.5.1",
"morgan": "^1.7.0",
"node-uuid": "^1.4.7"
}
}
Loading