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
4 changes: 4 additions & 0 deletions config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
mongoUri: 'mongodb://node-exam:nodeexam123@ds017165.mlab.com:17165/node-exam',
mongoTestUri: 'mongodb://node-exam:nodeexam123@ds115022.mlab.com:15022/node-exam-test'
}
14 changes: 10 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@
"description": "Building a RESTful CRUD API with Node.js, Express/Koa and MongoDB.",
"main": "server.js",
"scripts": {
"start": "NODE_ENV=development node server.js",
"start": "NODE_ENV=development nodemon server.js",
"start:prod": "NODE_ENV=production node server.js",
"test": "echo \"Error: no test specified\" && exit 1"
"test": "NODE_ENV=test mocha --recursive --exit"
},
"dependencies": {
"body-parse": "^0.1.0",
"cors": "^2.8.5",
"express": "^4.16.4",
"mongoose": "^5.4.8"
"mongoose": "^5.8.3"
},
"devDependencies": {
"chai": "^4.2.0"
"chai": "^4.2.0",
"mocha": "^6.2.2",
"mockgoose": "^8.0.4",
"nodemon": "^2.0.2",
"supertest": "^4.0.2"
},
"engines": {
"node": ">=10.15.0"
Expand Down
32 changes: 29 additions & 3 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,37 @@
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const db = require('./swagger/db');
const PlayerRoutes = require('./swagger/api/player');
const Model = require('./swagger/db/models');

const app = express();

// use body parser middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// cors
app.use(cors());

// Router
app.get('/', (req, res) => {
res.json({"message": "Building a RESTful CRUD API with Node.js, Express/Koa and MongoDB."});
});
app.use('/player', PlayerRoutes)

// error handler

// db models
global.db = new Model().getDb();

// connect db and start the serve
const port = process.env.PORT || 3000
db.connect()
.then(() => {
app.listen(port, () => {
console.log(`Server is listening on port ${port}!!`);
});
})

app.listen(3000, () => {
console.log("Server is listening on port 3000");
});
module.exports = app
22 changes: 22 additions & 0 deletions swagger/api/player.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const express = require('express');
const router = express.Router();
const PlayController = require('../controllers/Player');

// create player
router.post('/', (res, req, next) => {
PlayController.addPlayer(res, req, next)
})
// delete player
router.delete('/:playerId', (res, req, next) => {
PlayController.deletePlayer(res, req, next)
})
// get player
router.get('/:playerId', (res, req, next) => {
PlayController.getPlayerById(res, req, next)
})
// update player
router.put('/', (res, req, next) => {
PlayController.updatePlayer(res, req, next)
})

module.exports = router
105 changes: 67 additions & 38 deletions swagger/controllers/Player.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,77 @@
'use strict';

var utils = require('../utils/writer.js');
var Player = require('../service/PlayerService');
// var utils = require('../utils/writer.js');
const Player = require('../service/PlayerService');
const validNameAndPosition = require('../utils/validate');

module.exports.addPlayer = function addPlayer (req, res, next) {
var body = req.swagger.params['body'].value;
Player.addPlayer(body)
.then(function (response) {
utils.writeJson(res, response);
})
.catch(function (response) {
utils.writeJson(res, response);
});
module.exports.addPlayer = async function addPlayer (req, res, next) {
const body = req.body;
// validate
if(validNameAndPosition(req.body)) {
res.status(405).json({ message: 'Invalid Input' })
} else {
// add id automatically
let dbPlayerId = await global.db.PlayerId.findOne({active: true})
if(!dbPlayerId) {
dbPlayerId = await new global.db.PlayerId({
number: 0,
active: true
}).save()
}
dbPlayerId.number += 1
await dbPlayerId.save()
await Player.addPlayer({ ...body, id: dbPlayerId.number });
res.status(200).json({ playerId: dbPlayerId.number });
}
};

module.exports.deletePlayer = function deletePlayer (req, res, next) {
var playerId = req.swagger.params['playerId'].value;
Player.deletePlayer(playerId)
.then(function (response) {
utils.writeJson(res, response);
})
.catch(function (response) {
utils.writeJson(res, response);
});
module.exports.deletePlayer = async function deletePlayer (req, res, next) {
const playerId = req.params.playerId
// validate: playerId must be number
if(!isNaN(parseInt(playerId))) {
const status = await Player.deletePlayer(playerId)
if(status === 404) {
res.status(404).json({ message: 'Player not found' })
} else {
res.status(200).end();
}
} else {
res.status(400).json({ message: 'Invalid ID supplied' })
}
};

module.exports.getPlayerById = function getPlayerById (req, res, next) {
var playerId = req.swagger.params['playerId'].value;
Player.getPlayerById(playerId)
.then(function (response) {
utils.writeJson(res, response);
})
.catch(function (response) {
utils.writeJson(res, response);
});
module.exports.getPlayerById = async function getPlayerById (req, res, next) {
const playerId = req.params.playerId
// validate: playerId must be number
if(!isNaN(parseInt(playerId))) {
const foundPlayer = await Player.getPlayerById(playerId)
if(foundPlayer === 404) {
res.status(404).json({ message: 'Player not found' })
} else {
res.status(200).json({
id: foundPlayer.id,
name: foundPlayer.name,
position: foundPlayer.position
});
}
} else {
res.status(400).json({ message: 'Invalid ID supplied' })
}
};

module.exports.updatePlayer = function updatePlayer (req, res, next) {
var body = req.swagger.params['body'].value;
Player.updatePlayer(body)
.then(function (response) {
utils.writeJson(res, response);
})
.catch(function (response) {
utils.writeJson(res, response);
});
module.exports.updatePlayer = async function updatePlayer (req, res, next) {
const body = req.body
// validate: body.id must be number
if(!isNaN(parseInt(body.id))) {
// validate name and position
if(validNameAndPosition(req.body)) {
res.status(405).json({ message: 'Validation exception' })
} else {
const status = await Player.updatePlayer(body)
if(status === 404) res.status(404).json({ message: 'Player not found' })
else res.status(200).end();
}
} else {
res.status(400).json({ message: 'Invalid ID supplied' })
}
};
23 changes: 23 additions & 0 deletions swagger/db/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const mongoose = require('mongoose')
const mongoUri = require('../../config').mongoUri
const mongoTestUri = require('../../config').mongoTestUri

async function connect() {
return new Promise((resolve, reject) => {
const URI = process.env.NODE_ENV === 'test'? mongoTestUri: mongoUri
mongoose.connect(URI, { useNewUrlParser: true, useCreateIndex: true })
.then((res, err) => {
if(err) return reject(err)
resolve()
})
})
}

function close() {
return mongoose.disconnect()
}

module.exports = {
connect,
close
}
25 changes: 25 additions & 0 deletions swagger/db/models/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const fs = require('fs')
const path = require('path')

module.exports = class Models {
constructor() {
let db = {}

fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== 'index.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))
// modelName
db[model.modelName] = model
})

this.db = db
}

getDb() {
return this.db
}
}
19 changes: 19 additions & 0 deletions swagger/db/models/player.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const mongoose = require('mongoose');

const playerShcema = new mongoose.Schema({
id: {
type: Number,
unique: true,
require: true
},
name: {
type: String,
require: true
},
position: {
type: String,
enum: ['C', 'PF', 'SF', 'PG', 'SG']
}
})

module.exports = mongoose.model('Player', playerShcema)
14 changes: 14 additions & 0 deletions swagger/db/models/player_id.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const mongoose = require('mongoose');

const playerIdShcema = new mongoose.Schema({
number: {
type: Number,
require: true
},
active: {
type: Boolean,
default: true
}
})

module.exports = mongoose.model('PlayerId', playerIdShcema)
48 changes: 22 additions & 26 deletions swagger/service/PlayerService.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
* body Player Player object
* no response value expected for this operation
**/
exports.addPlayer = function(body) {
return new Promise(function(resolve, reject) {
resolve();
});
exports.addPlayer = async function(body) {
const newPlayer = new global.db.Player({
id: body.id,
name: body.name,
position: body.position
})
return newPlayer.save()
}


Expand All @@ -22,10 +25,10 @@ exports.addPlayer = function(body) {
* playerId Long Player id to delete
* no response value expected for this operation
**/
exports.deletePlayer = function(playerId) {
return new Promise(function(resolve, reject) {
resolve();
});
exports.deletePlayer = async function(playerId) {
const result = await global.db.Player.deleteOne({id: playerId})
if(result.deletedCount === 0) return 404
return 200
}


Expand All @@ -36,20 +39,10 @@ exports.deletePlayer = function(playerId) {
* playerId Long ID of player to return
* returns Player
**/
exports.getPlayerById = function(playerId) {
return new Promise(function(resolve, reject) {
var examples = {};
examples['application/json'] = {
"name" : "LeBron",
"id" : 0,
"position" : "C"
};
if (Object.keys(examples).length > 0) {
resolve(examples[Object.keys(examples)[0]]);
} else {
resolve();
}
});
exports.getPlayerById = async function(playerId) {
const dbPlayer = await global.db.Player.findOne({id: playerId})
if(!dbPlayer) return 404
return dbPlayer
}


Expand All @@ -60,9 +53,12 @@ exports.getPlayerById = function(playerId) {
* body Player Player object that needs to be added to the team
* no response value expected for this operation
**/
exports.updatePlayer = function(body) {
return new Promise(function(resolve, reject) {
resolve();
});
exports.updatePlayer = async function(body) {
const dbPlayer = await global.db.Player.findOne({id: body.id})
if(!dbPlayer) return 404
dbPlayer.name = body.name || dbPlayer.name
dbPlayer.position = body.position || dbPlayer.position
await dbPlayer.save()
return 200
}

11 changes: 11 additions & 0 deletions swagger/utils/validate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = validNameAndPosition = (body) => {
// !req.body.name || typeof req.body.name !== 'string' ||foundIndex === -1
const noName = !body.name
const notStringName = body.name && typeof body.name !== 'string'
const notValidPosiiton = body.position && (
['C', 'PF', 'SF', 'PG', 'SG'].findIndex(position => (
position === body.position
))) === -1

return noName || notStringName || notValidPosiiton
}
Loading