diff --git a/src/controllers/books/booksController.js b/src/controllers/books/booksController.js new file mode 100644 index 0000000..45a5d42 --- /dev/null +++ b/src/controllers/books/booksController.js @@ -0,0 +1,67 @@ +const { getAllBooks, newBook, getBookById, deleteBookById, updateBookById, patchBookById } = require("../../domain/books/booksRepository") + +let idCounter = 5 + +const getAll = (req, res) => { + const books = getAllBooks() + + res.json({books}) +} + +const createBook = (req, res) => { + const book = req.body + + book.id = idCounter + newBook(book) + + idCounter++ + + res.status(201).json({book}) +} + +const findBook = (req, res) => { + const bookID = Number(req.params.id) + const book = getBookById(bookID) + + res.json({book}) +} + +const deleteBook = (req, res) => { + const bookID = Number(req.params.id) + const book = getBookById(bookID) + + deleteBookById(bookID) + + res.json({book}) +} + +const updateBook = (req, res) => { + const newBookInfo = req.body + const bookID = Number(req.params.id) + + newBookInfo.id = bookID + + updateBookById(bookID, newBookInfo) + + res.json({book: newBookInfo}) +} + +const update = (req, res) => { + const newBookInfo = req.body + const bookID = Number(req.params.id) + + newBookInfo.id = bookID + + const patchedBook = patchBookById(bookID, newBookInfo) + + res.json({book: patchedBook}) +} + +module.exports = { + getAll, + createBook, + findBook, + deleteBook, + updateBook, + update +} \ No newline at end of file diff --git a/src/controllers/films/filmsController.js b/src/controllers/films/filmsController.js new file mode 100644 index 0000000..2c96e54 --- /dev/null +++ b/src/controllers/films/filmsController.js @@ -0,0 +1,75 @@ +const { getAllFilms, newFilm, getFilmById, deleteFilmById, updateFilmById, patchFilmById } = require("../../domain/films/filmsRepository") + +let idCounter = 5 + +const getAll = (req, res) => { + const director = req.query.director + + if (director) { + const filteredFilms = getAllFilms(director) + + return res.json({films: filteredFilms}) + } + + const films = getAllFilms() + + res.json({films}) +} + +const createFilm = (req, res) => { + const film = req.body + + film.id = idCounter + newFilm(film) + + idCounter++ + + res.status(201).json({film}) +} + +const findFilm = (req, res) => { + const filmID = Number(req.params.id) + const film = getFilmById(filmID) + + res.json({film}) +} + +const deleteFilm = (req, res) => { + const filmID = Number(req.params.id) + const film = getFilmById(filmID) + + deleteFilmById(filmID) + + res.json({film}) +} + +const updateFilm = (req, res) => { + const newFilmInfo = req.body + const filmID = Number(req.params.id) + + newFilmInfo.id = filmID + + updateFilmById(filmID, newFilmInfo) + + res.json({film: newFilmInfo}) +} + +const update = (req, res) => { + const newFilmInfo = req.body + const filmID = Number(req.params.id) + + newFilmInfo.id = filmID + + const patchedFilm = patchFilmById(filmID, newFilmInfo) + + res.json({film: patchedFilm}) +} + +module.exports = { + getAll, + createFilm, + findFilm, + deleteFilm, + updateFilm, + update +} \ No newline at end of file diff --git a/src/controllers/users/usersController.js b/src/controllers/users/usersController.js new file mode 100644 index 0000000..cd1e8c7 --- /dev/null +++ b/src/controllers/users/usersController.js @@ -0,0 +1,55 @@ +const { getAllUsers, newUser, getUserById, deleteUserById, updateUserById } = require("../../domain/users/usersRepository") + +let idCounter = 4 + +const getAll = (req, res) => { + const users = getAllUsers() + + res.json({users}) +} + +const createUser = (req, res) => { + const user = req.body + + user.id = idCounter + newUser(user) + + idCounter++ + + res.status(201).json({user}) +} + +const findUser = (req, res) => { + const userID = Number(req.params.id) + const user = getUserById(userID) + + res.json({user}) +} + +const deleteUser = (req, res) => { + const userID = Number(req.params.id) + const user = getUserById(userID) + + deleteUserById(userID) + + res.json({user}) +} + +const updateUser = (req, res) => { + const newUserInfo = req.body + const userID = Number(req.params.id) + + newUserInfo.id = userID + + updateUserById(userID, newUserInfo) + + res.json({user: newUserInfo}) +} + +module.exports = { + getAll, + createUser, + findUser, + deleteUser, + updateUser +} \ No newline at end of file diff --git a/src/domain/books/booksRepository.js b/src/domain/books/booksRepository.js new file mode 100644 index 0000000..7df9546 --- /dev/null +++ b/src/domain/books/booksRepository.js @@ -0,0 +1,106 @@ +let { books } = require("../../../data/index.js") +const AlreadyExistsError = require("../../errors/alreadyExistsError.js") +const MissingFieldsError = require("../../errors/missingFieldsError.js") +const NotFoundError = require("../../errors/notFoundError.js") + +function getAllBooks() { + return books +} + +function newBook(book) { + if (!verifyBookProperties(book)) { + throw new MissingFieldsError('Missing fields in request body') + } + + if (verifyBook(book)) { + throw new AlreadyExistsError('A book with the provided title already exists') + } + + books.push(book) +} + +function getBookById(id) { + const found = books.find((book) => book.id === id) + + if (!found) { + throw new NotFoundError('A book the provided ID does not exist') + } + + return found +} + +function deleteBookById(id) { + const found = getBookById(id) + + if (!found) { + throw new NotFoundError('A book the provided ID does not exist') + } + + books = books.filter((book) => book.id !== id) +} + +function updateBookById(id, updatedBook) { + if (!verifyBookProperties(updatedBook)) { + throw new MissingFieldsError('Missing fields in request body') + } + + const found = getBookById(id) + + if (!found) { + throw new NotFoundError('A book the provided ID does not exist') + } + + if (verifyBook(updatedBook)) { + throw new AlreadyExistsError('A book with the provided title already exists') + } + + Object.assign(books, updatedBook) +} + +function patchBookById(id, updatedBook) { + const found = books.find((book) => book.id === id) + const foundIndex = books.indexOf(found) + + if (!found) { + throw new NotFoundError('A book the provided ID does not exist') + } + + if (verifyBook(updatedBook)) { + throw new AlreadyExistsError('A book with the provided title already exists') + } + + Object.assign(books[foundIndex], updatedBook) + + return books[foundIndex] +} + +function verifyBookProperties(object) { + const neededProperties = ['title', 'type', 'author'] + + for (const item of neededProperties) { + if (object[item] === undefined) { + return false + } + } + + return true +} + +function verifyBook(object) { + const foundBook = books.find((book) => book.title === object.title) + + if (foundBook) { + return true + } + + return false +} + +module.exports = { + getAllBooks, + newBook, + getBookById, + deleteBookById, + updateBookById, + patchBookById +} \ No newline at end of file diff --git a/src/domain/films/filmsRepository.js b/src/domain/films/filmsRepository.js new file mode 100644 index 0000000..0142899 --- /dev/null +++ b/src/domain/films/filmsRepository.js @@ -0,0 +1,111 @@ +let { films } = require("../../../data/index.js") +const AlreadyExistsError = require("../../errors/alreadyExistsError.js") +const MissingFieldsError = require("../../errors/missingFieldsError.js") +const NotFoundError = require("../../errors/notFoundError.js") + +function getAllFilms(director) { + if (director) { + const filteredFilms = films.filter((film) => film.director === director) + return filteredFilms + } + + return films +} + +function newFilm(film) { + if (!verifyFilmProperties(film)) { + throw new MissingFieldsError('Missing fields in request body') + } + + if (verifyFilm(film)) { + throw new AlreadyExistsError('A film with the provided title already exists') + } + + films.push(film) +} + +function getFilmById(id) { + const found = films.find((film) => film.id === id) + + if (!found) { + throw new NotFoundError('A film with provided ID does not exist') + } + + return found +} + +function deleteFilmById(id) { + const found = films.find((film) => film.id === id) + + if (!found) { + throw new NotFoundError('A film with provided ID does not exist') + } + + films = films.filter((film) => film.id !== id) +} + +function updateFilmById(id, updatedFilm) { + const found = films.find((film) => film.id === id) + + if (!found) { + throw new NotFoundError('A film with provided ID does not exist') + } + + if (!verifyFilmProperties(updatedFilm)) { + throw new MissingFieldsError('Missing fields in request body') + } + + if (verifyFilm(updatedFilm)) { + throw new AlreadyExistsError('A film with the provided title already exists') + } + + Object.assign(films, updatedFilm) +} + +function patchFilmById(id, updatedFilm) { + const found = films.find((film) => film.id === id) + const foundIndex = films.indexOf(found) + + if (!found) { + throw new NotFoundError('A film with provided ID does not exist') + } + + if (verifyFilm(updatedFilm)) { + throw new AlreadyExistsError('A film with the provided title already exists') + } + + Object.assign(films[foundIndex], updatedFilm) + + return films[foundIndex] +} + +function verifyFilmProperties(object) { + const neededProperties = ['title', 'director'] + + for (const item of neededProperties) { + if (object[item] === undefined) { + return false + } + } + + return true +} + +function verifyFilm(object) { + const foundFilm = films.find((film) => film.title === object.title) + + if (foundFilm) { + return true + } + + return false +} + +module.exports = { + getAllFilms, + newFilm, + getFilmById, + deleteFilmById, + updateFilmById, + patchFilmById +} \ No newline at end of file diff --git a/src/domain/users/usersRepository.js b/src/domain/users/usersRepository.js new file mode 100644 index 0000000..a6a4aa0 --- /dev/null +++ b/src/domain/users/usersRepository.js @@ -0,0 +1,86 @@ +let { users } = require("../../../data/index.js") +const MissingFieldsError = require("../../errors/missingFieldsError.js") +const NotFoundError = require("../../errors/notFoundError.js") +const AlreadyExistsError = require("../../errors/alreadyExistsError.js") + +function getAllUsers() { + return users +} + +function newUser(user) { + if (!verifyUserProperties(user)) { + throw new MissingFieldsError('Missing fields in request body') + } + + if (verifyEmail(user)) { + throw new AlreadyExistsError('A user with the provided email already exists') + } + + users.push(user) +} + +function getUserById(id) { + const found = users.find((user) => user.id === id) + + if (!found) { + throw new NotFoundError('A user with the provided ID does not exist') + } + + return found +} + +function deleteUserById(id) { + const found = users.find((user) => user.id === id) + + if (!found) { + throw new NotFoundError('A user with the provided ID does not exist') + } + + users = users.filter((user) => user.id !== id) +} + +function updateUserById(id, updatedUser) { + const found = users.find((user) => user.id === id) + + if (!found) { + throw new NotFoundError('A user with the provided ID does not exist') + } + + if (!verifyUserProperties(updatedUser)) { + throw new MissingFieldsError('Missing fields in request body') + } + + if (verifyEmail(updatedUser)) { + throw new AlreadyExistsError('A user with the provided email already exists') + } + + Object.assign(users, updatedUser) +} + +function verifyUserProperties(object) { + const neededProperties = 'email' + + if (object[neededProperties] === undefined) { + return false + } + + return true +} + +function verifyEmail(object) { + const foundEmail = users.find((user) => user.email === object.email) + + if (foundEmail) { + return true + } + + return false +} + +module.exports = { + getAllUsers, + newUser, + getUserById, + deleteUserById, + updateUserById +} \ No newline at end of file diff --git a/src/errors/alreadyExistsError.js b/src/errors/alreadyExistsError.js new file mode 100644 index 0000000..42518a8 --- /dev/null +++ b/src/errors/alreadyExistsError.js @@ -0,0 +1,5 @@ +class AlreadyExistsError extends Error { + +} + +module.exports = AlreadyExistsError \ No newline at end of file diff --git a/src/errors/missingFieldsError.js b/src/errors/missingFieldsError.js new file mode 100644 index 0000000..7359cc1 --- /dev/null +++ b/src/errors/missingFieldsError.js @@ -0,0 +1,5 @@ +class MissingFieldsError extends Error { + +} + +module.exports = MissingFieldsError \ No newline at end of file diff --git a/src/errors/notFoundError.js b/src/errors/notFoundError.js new file mode 100644 index 0000000..0a1f7ab --- /dev/null +++ b/src/errors/notFoundError.js @@ -0,0 +1,5 @@ +class NotFoundError extends Error { + +} + +module.exports = NotFoundError \ No newline at end of file diff --git a/src/routers/books.js b/src/routers/books.js index 18b9a7c..7784a83 100644 --- a/src/routers/books.js +++ b/src/routers/books.js @@ -1,4 +1,18 @@ -// Import data here... +const express = require('express') +const { getAll, createBook, findBook, deleteBook, updateBook, update } = require('../controllers/books/booksController') +const router = express.Router() -// Write routes here... +router.get('/', getAll) + +router.post('/', createBook) + +router.get('/:id', findBook) + +router.delete('/:id', deleteBook) + +router.put('/:id', updateBook) + +router.patch('/:id', update) + +module.exports = router \ No newline at end of file diff --git a/src/routers/films.js b/src/routers/films.js index e69de29..338c186 100644 --- a/src/routers/films.js +++ b/src/routers/films.js @@ -0,0 +1,18 @@ +const express = require('express') +const { getAll, createFilm, findFilm, deleteFilm, updateFilm, update } = require('../controllers/films/filmsController') + +const router = express.Router() + +router.get('/', getAll) + +router.post('/', createFilm) + +router.get('/:id', findFilm) + +router.delete('/:id', deleteFilm) + +router.put('/:id', updateFilm) + +router.patch('/:id', update) + +module.exports = router \ No newline at end of file diff --git a/src/routers/users.js b/src/routers/users.js index e69de29..5b0e9f7 100644 --- a/src/routers/users.js +++ b/src/routers/users.js @@ -0,0 +1,15 @@ +const express = require('express') +const { getAll, createUser, findUser, deleteUser, updateUser } = require('../controllers/users/usersController') +const router = express.Router() + +router.get('/', getAll) + +router.post('/', createUser) + +router.get('/:id', findUser) + +router.delete('/:id', deleteUser) + +router.put('/:id', updateUser) + +module.exports = router \ No newline at end of file diff --git a/src/server.js b/src/server.js index 715321f..d933946 100644 --- a/src/server.js +++ b/src/server.js @@ -1,18 +1,49 @@ -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 filmsRouter = require('./routers/films') +const booksRouter = require('./routers/books') +const NotFoundError = require("./errors/notFoundError") +const MissingFieldsError = require("./errors/missingFieldsError") +const AlreadyExistsError = require("./errors/alreadyExistsError") // ADD ROUTERS TO APP +app.use('/users', usersRouter) +app.use('/films', filmsRouter) +app.use('/books', booksRouter) +app.use((error, req, res, next) => { + if (error instanceof MissingFieldsError) { + return res.status(400).json({ + error: error.message + }) + } + + if (error instanceof NotFoundError) { + return res.status(404).json({ + error: error.message + }) + } + + if (error instanceof AlreadyExistsError) { + return res.status(409).json({ + error: error.message + }) + } + + res.status(500).json({ + message: 'Something went wrong' + }) +}) module.exports = app diff --git a/test/api/extensions/books.spec.js b/test/api/extensions/books.spec.js index 4889b8f..66bd88f 100644 --- a/test/api/extensions/books.spec.js +++ b/test/api/extensions/books.spec.js @@ -70,7 +70,7 @@ describe("Books Extension Endpoint", () => { describe("PATCH /books", () => { it("will return 404 when updating a book that does not exist", async () => { - const response = await supertest(app).put("/books/999").send({ + const response = await supertest(app).patch("/books/999").send({ title: "test1", type: "test1", author: "test1", @@ -80,7 +80,7 @@ describe("Books Extension Endpoint", () => { expect(response.body.error).toEqual('A book the provided ID does not exist') }) it("will return 409 when updating a book with title that already exists", async () => { - const response = await supertest(app).put("/books/1").send({ + const response = await supertest(app).patch("/books/1").send({ title: "1984", type: "test1", author: "test1",