From 0bd15687a09daa4ceae872ab7d1d645dff42bd87 Mon Sep 17 00:00:00 2001 From: Angus Townsley Date: Tue, 18 Jun 2024 16:49:52 +0100 Subject: [PATCH 1/2] Inital endpoint creation --- src/controllers/books.js | 69 ++++++++++++++++++++++++++++++++++++++++ src/controllers/films.js | 69 ++++++++++++++++++++++++++++++++++++++++ src/controllers/users.js | 69 ++++++++++++++++++++++++++++++++++++++++ src/routers/books.js | 15 ++++++++- src/routers/films.js | 17 ++++++++++ src/routers/users.js | 17 ++++++++++ src/server.js | 22 +++++++------ 7 files changed, 268 insertions(+), 10 deletions(-) create mode 100644 src/controllers/books.js create mode 100644 src/controllers/films.js create mode 100644 src/controllers/users.js diff --git a/src/controllers/books.js b/src/controllers/books.js new file mode 100644 index 0000000..c5b6025 --- /dev/null +++ b/src/controllers/books.js @@ -0,0 +1,69 @@ +let { books } = require('../../data/index') + +let nextBookId = 5 + +const getAllBooks = (req, res) => { + res.status(200).send({ books: books }) +} + +const addBook = (req, res) => { + const newBook = { id: nextBookId, ...req.body } + nextBookId++ + books.push(newBook) + + res.status(201).send({ book: newBook }) +} + +const getBookById = (req, res) => { + const searchedBook = books.find((element) => { + return element.id === Number(req.params['id']) + }) + + if (!searchedBook) { + res.sendStatus(404) + } + + res.status(200).send({ book: searchedBook }) +} + +const deleteBookById = (req, res) => { + const searchedBook = books.find((element) => { + return element.id === Number(req.params['id']) + }) + + if (!searchedBook) { + res.sendStatus(404) + } + + books = books.filter((element) => { + return !(element.id === Number(req.params['id'])) + }) + + res.status(200).send({ book: searchedBook }) +} + +const updateBookById = (req, res) => { + const searchedBook = books.find((element) => { + return element.id === Number(req.params['id']) + }) + + if (!searchedBook) { + res.sendStatus(404) + } + + Object.keys(req.body).forEach((element) => { + if (searchedBook[element]) { + searchedBook[element] = req.body[element] + } + }) + + res.status(200).send({ book: searchedBook }) +} + +module.exports = { + getAllBooks, + addBook, + getBookById, + deleteBookById, + updateBookById, +} diff --git a/src/controllers/films.js b/src/controllers/films.js new file mode 100644 index 0000000..85d5274 --- /dev/null +++ b/src/controllers/films.js @@ -0,0 +1,69 @@ +let { films } = require('../../data/index') + +let nextFilmId = 5 + +const getAllFilms = (req, res) => { + res.status(200).send({ films: films }) +} + +const addFilm = (req, res) => { + const newFilm = { id: nextFilmId, ...req.body } + nextFilmId++ + films.push(newFilm) + + res.status(201).send({ film: newFilm }) +} + +const getFilmById = (req, res) => { + const searchedFilm = films.find((element) => { + return element.id === Number(req.params['id']) + }) + + if (!searchedFilm) { + res.sendStatus(404) + } + + res.status(200).send({ film: searchedFilm }) +} + +const deleteFilmById = (req, res) => { + const searchedFilm = films.find((element) => { + return element.id === Number(req.params['id']) + }) + + if (!searchedFilm) { + res.sendStatus(404) + } + + films = films.filter((element) => { + return !(element.id === Number(req.params['id'])) + }) + + res.status(200).send({ film: searchedFilm }) +} + +const updateFilmById = (req, res) => { + const searchedFilm = films.find((element) => { + return element.id === Number(req.params['id']) + }) + + if (!searchedFilm) { + res.sendStatus(404) + } + + Object.keys(req.body).forEach((element) => { + if (searchedFilm[element]) { + searchedFilm[element] = req.body[element] + } + }) + + res.status(200).send({ film: searchedFilm }) +} + +module.exports = { + getAllFilms, + addFilm, + getFilmById, + deleteFilmById, + updateFilmById, +} diff --git a/src/controllers/users.js b/src/controllers/users.js new file mode 100644 index 0000000..b680f99 --- /dev/null +++ b/src/controllers/users.js @@ -0,0 +1,69 @@ +let { users } = require('../../data/index') + +let nextUserId = 4 + +const getAllUsers = (req, res) => { + res.status(200).send({ users: users }) +} + +const addUser = (req, res) => { + const newUser = { id: nextUserId, ...req.body } + nextUserId++ + users.push(newUser) + + res.status(201).send({ user: newUser }) +} + +const getUserById = (req, res) => { + const searchedUser = users.find((element) => { + return element.id === Number(req.params['id']) + }) + + if (!searchedUser) { + res.sendStatus(404) + } + + res.status(200).send({ user: searchedUser }) +} + +const deleteUserById = (req, res) => { + const searchedUser = users.find((element) => { + return element.id === Number(req.params['id']) + }) + + if (!searchedUser) { + res.sendStatus(404) + } + + users = users.filter((element) => { + return !(element.id === Number(req.params['id'])) + }) + + res.status(200).send({ user: searchedUser }) +} + +const updateUserById = (req, res) => { + const searchedUser = users.find((element) => { + return element.id === Number(req.params['id']) + }) + + if (!searchedUser) { + res.sendStatus(404) + } + + Object.keys(req.body).forEach((element) => { + if (searchedUser[element]) { + searchedUser[element] = req.body[element] + } + }) + + res.status(200).send({ user: searchedUser }) +} + +module.exports = { + getAllUsers, + addUser, + getUserById, + deleteUserById, + updateUserById, +} diff --git a/src/routers/books.js b/src/routers/books.js index 18b9a7c..496e703 100644 --- a/src/routers/books.js +++ b/src/routers/books.js @@ -1,4 +1,17 @@ // Import data here... - +const express = require('express') +const router = express.Router() +const { getAllBooks, addBook, getBookById, deleteBookById, updateBookById } = require('../controllers/books') // Write routes here... +router.get('/', getAllBooks) + +router.post('/', addBook) + +router.get('/:id', getBookById) + +router.delete('/:id', deleteBookById) + +router.put('/:id', updateBookById) + +module.exports = router \ No newline at end of file diff --git a/src/routers/films.js b/src/routers/films.js index e69de29..292d914 100644 --- a/src/routers/films.js +++ b/src/routers/films.js @@ -0,0 +1,17 @@ +// Import data here... +const express = require('express') +const router = express.Router() +const { getAllFilms, addFilm, getFilmById, deleteFilmById, updateFilmById } = require('../controllers/films') + +// Write routes here... +router.get('/', getAllFilms) + +router.post('/', addFilm) + +router.get('/:id', getFilmById) + +router.delete('/:id', deleteFilmById) + +router.put('/:id', updateFilmById) + +module.exports = router \ No newline at end of file diff --git a/src/routers/users.js b/src/routers/users.js index e69de29..1fa465d 100644 --- a/src/routers/users.js +++ b/src/routers/users.js @@ -0,0 +1,17 @@ +// Import data here... +const express = require('express') +const router = express.Router() +const { getAllUsers, addUser, getUserById, deleteUserById, updateUserById } = require('../controllers/users') + +// Write routes here... +router.get('/', getAllUsers) + +router.post('/', addUser) + +router.get('/:id', getUserById) + +router.delete('/:id', deleteUserById) + +router.put('/:id', updateUserById) + +module.exports = router \ No newline at end of file diff --git a/src/server.js b/src/server.js index 715321f..744c3d6 100644 --- a/src/server.js +++ b/src/server.js @@ -1,18 +1,22 @@ -const express = require("express"); -const app = express(); +const express = require('express') +const app = express() -const cors = require("cors"); -const morgan = require("morgan"); +const cors = require('cors') +const morgan = require('morgan') // SETUP MIDDLEWARE -app.use(cors()); -app.use(express.json()); -app.use(morgan("dev")); +app.use(cors()) +app.use(express.json()) +app.use(morgan('dev')) // REQUIRE ROUTERS -const usersRouter = require("./routers/users"); +const usersRouter = require('./routers/users') +const booksRouter = require('./routers/books') +const filmsRouter = require('./routers/films') // ADD ROUTERS TO APP - +app.use('/users', usersRouter) +app.use('/books', booksRouter) +app.use('/films', filmsRouter) module.exports = app From 87154e7733e5b7b20f39ff7798672da739c6406a Mon Sep 17 00:00:00 2001 From: Angus Townsley Date: Tue, 18 Jun 2024 18:02:36 +0100 Subject: [PATCH 2/2] Complete extension error handling and endpoints --- src/controllers/books.js | 58 +++++++++++++++++++++++++++-- src/controllers/films.js | 80 ++++++++++++++++++++++++++++++++++++++-- src/controllers/users.js | 39 ++++++++++++++++++-- src/errors/errors.js | 7 ++++ src/routers/books.js | 13 ++++++- src/routers/films.js | 4 +- src/server.js | 18 +++++++++ 7 files changed, 206 insertions(+), 13 deletions(-) create mode 100644 src/errors/errors.js diff --git a/src/controllers/books.js b/src/controllers/books.js index c5b6025..e35e3c8 100644 --- a/src/controllers/books.js +++ b/src/controllers/books.js @@ -1,4 +1,5 @@ let { books } = require('../../data/index') +const {MissingFieldsError, NotFoundError, AlreadyExistsError} = require('../errors/errors') let nextBookId = 5 @@ -7,6 +8,18 @@ const getAllBooks = (req, res) => { } const addBook = (req, res) => { + if(!req.body.title || !req.body.type || !req.body.author) { + throw new MissingFieldsError('Missing fields in request body') + } + + const alreadyExists = books.find((element) => { + return element.title === req.body.title + }) + + if(alreadyExists) { + throw new AlreadyExistsError('A book with the provided title already exists') + } + const newBook = { id: nextBookId, ...req.body } nextBookId++ books.push(newBook) @@ -20,7 +33,7 @@ const getBookById = (req, res) => { }) if (!searchedBook) { - res.sendStatus(404) + throw new NotFoundError('A book the provided ID does not exist') } res.status(200).send({ book: searchedBook }) @@ -32,7 +45,7 @@ const deleteBookById = (req, res) => { }) if (!searchedBook) { - res.sendStatus(404) + throw new NotFoundError('A book the provided ID does not exist') } books = books.filter((element) => { @@ -43,12 +56,50 @@ const deleteBookById = (req, res) => { } const updateBookById = (req, res) => { + if(!req.body.title || !req.body.type || !req.body.author) { + throw new MissingFieldsError('Missing fields in request body') + } + const searchedBook = books.find((element) => { return element.id === Number(req.params['id']) }) if (!searchedBook) { - res.sendStatus(404) + throw new NotFoundError('A book the provided ID does not exist') + } + + const alreadyExists = books.find((element) => { + return element.title === req.body.title + }) + + if(alreadyExists) { + throw new AlreadyExistsError('A book with the provided title already exists') + } + + Object.keys(req.body).forEach((element) => { + if (searchedBook[element]) { + searchedBook[element] = req.body[element] + } + }) + + res.status(200).send({ book: searchedBook }) +} + +const patchBookById = (req, res) => { + const searchedBook = books.find((element) => { + return element.id === Number(req.params['id']) + }) + + if (!searchedBook) { + throw new NotFoundError('A book the provided ID does not exist') + } + + const alreadyExists = books.find((element) => { + return element.title === req.body.title + }) + + if(alreadyExists) { + throw new AlreadyExistsError('A book with the provided title already exists') } Object.keys(req.body).forEach((element) => { @@ -66,4 +117,5 @@ module.exports = { getBookById, deleteBookById, updateBookById, + patchBookById, } diff --git a/src/controllers/films.js b/src/controllers/films.js index 85d5274..cb0bb1f 100644 --- a/src/controllers/films.js +++ b/src/controllers/films.js @@ -1,12 +1,41 @@ let { films } = require('../../data/index') +const { + MissingFieldsError, + NotFoundError, + AlreadyExistsError, +} = require('../errors/errors') let nextFilmId = 5 const getAllFilms = (req, res) => { - res.status(200).send({ films: films }) + let filmsToSend + + if(req.query.director) { + filmsToSend = films.filter((element) => { + return element.director === req.query.director + }) + } else { + filmsToSend = films + } + + res.status(200).send({ films: filmsToSend }) } const addFilm = (req, res) => { + if (!req.body.title || !req.body.director) { + throw new MissingFieldsError('Missing fields in request body') + } + + const alreadyExists = films.find((element) => { + return element.title === req.body.title + }) + + if (alreadyExists) { + throw new AlreadyExistsError( + 'A film with the provided title already exists' + ) + } + const newFilm = { id: nextFilmId, ...req.body } nextFilmId++ films.push(newFilm) @@ -20,7 +49,7 @@ const getFilmById = (req, res) => { }) if (!searchedFilm) { - res.sendStatus(404) + throw new NotFoundError('A film with provided ID does not exist') } res.status(200).send({ film: searchedFilm }) @@ -32,7 +61,7 @@ const deleteFilmById = (req, res) => { }) if (!searchedFilm) { - res.sendStatus(404) + throw new NotFoundError('A film with provided ID does not exist') } films = films.filter((element) => { @@ -43,12 +72,54 @@ const deleteFilmById = (req, res) => { } const updateFilmById = (req, res) => { + if (!req.body.title || !req.body.director) { + throw new MissingFieldsError('Missing fields in request body') + } + const searchedFilm = films.find((element) => { return element.id === Number(req.params['id']) }) if (!searchedFilm) { - res.sendStatus(404) + throw new NotFoundError('A film with provided ID does not exist') + } + + const alreadyExists = films.find((element) => { + return element.title === req.body.title + }) + + if (alreadyExists) { + throw new AlreadyExistsError( + 'A film with the provided title already exists' + ) + } + + Object.keys(req.body).forEach((element) => { + if (searchedFilm[element]) { + searchedFilm[element] = req.body[element] + } + }) + + res.status(200).send({ film: searchedFilm }) +} + +const patchFilmById = (req, res) => { + const searchedFilm = films.find((element) => { + return element.id === Number(req.params['id']) + }) + + if (!searchedFilm) { + throw new NotFoundError('A film with provided ID does not exist') + } + + const alreadyExists = films.find((element) => { + return element.title === req.body.title + }) + + if (alreadyExists) { + throw new AlreadyExistsError( + 'A film with the provided title already exists' + ) } Object.keys(req.body).forEach((element) => { @@ -66,4 +137,5 @@ module.exports = { getFilmById, deleteFilmById, updateFilmById, + patchFilmById, } diff --git a/src/controllers/users.js b/src/controllers/users.js index b680f99..f662ac4 100644 --- a/src/controllers/users.js +++ b/src/controllers/users.js @@ -1,4 +1,9 @@ let { users } = require('../../data/index') +const { + MissingFieldsError, + NotFoundError, + AlreadyExistsError, +} = require('../errors/errors') let nextUserId = 4 @@ -7,6 +12,20 @@ const getAllUsers = (req, res) => { } const addUser = (req, res) => { + if (!req.body.email) { + throw new MissingFieldsError('Missing fields in request body') + } + + const alreadyExists = users.find((element) => { + return element.email === req.body.email + }) + + if (alreadyExists) { + throw new AlreadyExistsError( + 'A user with the provided email already exists' + ) + } + const newUser = { id: nextUserId, ...req.body } nextUserId++ users.push(newUser) @@ -20,7 +39,7 @@ const getUserById = (req, res) => { }) if (!searchedUser) { - res.sendStatus(404) + throw new NotFoundError('A user with the provided ID does not exist') } res.status(200).send({ user: searchedUser }) @@ -32,7 +51,7 @@ const deleteUserById = (req, res) => { }) if (!searchedUser) { - res.sendStatus(404) + throw new NotFoundError('A user with the provided ID does not exist') } users = users.filter((element) => { @@ -43,12 +62,26 @@ const deleteUserById = (req, res) => { } const updateUserById = (req, res) => { + if (!req.body.email) { + throw new MissingFieldsError('Missing fields in request body') + } + const searchedUser = users.find((element) => { return element.id === Number(req.params['id']) }) if (!searchedUser) { - res.sendStatus(404) + throw new NotFoundError('A user with the provided ID does not exist') + } + + const alreadyExists = users.find((element) => { + return element.email === req.body.email + }) + + if (alreadyExists) { + throw new AlreadyExistsError( + 'A user with the provided email already exists' + ) } Object.keys(req.body).forEach((element) => { diff --git a/src/errors/errors.js b/src/errors/errors.js new file mode 100644 index 0000000..3441d52 --- /dev/null +++ b/src/errors/errors.js @@ -0,0 +1,7 @@ +class MissingFieldsError extends Error{} + +class NotFoundError extends Error{} + +class AlreadyExistsError extends Error{} + +module.exports = {MissingFieldsError, NotFoundError, AlreadyExistsError} diff --git a/src/routers/books.js b/src/routers/books.js index 496e703..61ac43a 100644 --- a/src/routers/books.js +++ b/src/routers/books.js @@ -1,7 +1,14 @@ // Import data here... const express = require('express') const router = express.Router() -const { getAllBooks, addBook, getBookById, deleteBookById, updateBookById } = require('../controllers/books') +const { + getAllBooks, + addBook, + getBookById, + deleteBookById, + updateBookById, + patchBookById, +} = require('../controllers/books') // Write routes here... router.get('/', getAllBooks) @@ -14,4 +21,6 @@ router.delete('/:id', deleteBookById) router.put('/:id', updateBookById) -module.exports = router \ No newline at end of file +router.patch('/:id', patchBookById) + +module.exports = router diff --git a/src/routers/films.js b/src/routers/films.js index 292d914..5b5df5d 100644 --- a/src/routers/films.js +++ b/src/routers/films.js @@ -1,7 +1,7 @@ // Import data here... const express = require('express') const router = express.Router() -const { getAllFilms, addFilm, getFilmById, deleteFilmById, updateFilmById } = require('../controllers/films') +const { getAllFilms, addFilm, getFilmById, deleteFilmById, updateFilmById , patchFilmById} = require('../controllers/films') // Write routes here... router.get('/', getAllFilms) @@ -14,4 +14,6 @@ router.delete('/:id', deleteFilmById) router.put('/:id', updateFilmById) +router.patch('/:id', patchFilmById) + module.exports = router \ No newline at end of file diff --git a/src/server.js b/src/server.js index 744c3d6..c19af92 100644 --- a/src/server.js +++ b/src/server.js @@ -3,12 +3,19 @@ const app = express() const cors = require('cors') const morgan = require('morgan') +const { + MissingFieldsError, + NotFoundError, + AlreadyExistsError, +} = require('./errors/errors') // SETUP MIDDLEWARE app.use(cors()) app.use(express.json()) app.use(morgan('dev')) + + // REQUIRE ROUTERS const usersRouter = require('./routers/users') const booksRouter = require('./routers/books') @@ -18,5 +25,16 @@ const filmsRouter = require('./routers/films') app.use('/users', usersRouter) app.use('/books', booksRouter) app.use('/films', filmsRouter) +app.use((error, req, res, next) => { + if (error instanceof MissingFieldsError) { + return res.status(400).send({error:error.message}) + } + if (error instanceof NotFoundError) { + return res.status(404).send({error:error.message}) + } + if (error instanceof AlreadyExistsError) { + return res.status(409).send({error:error.message}) + } +}) module.exports = app