From bf2618314e2b1c53503b58fa6facba21acce8ea3 Mon Sep 17 00:00:00 2001 From: Hamada Abdelaal Date: Wed, 19 Jun 2024 08:42:24 +0200 Subject: [PATCH 1/3] standard --- package-lock.json | 58 +++++++++++++++++++++++ package.json | 1 + src/controllers/booksController.js | 75 ++++++++++++++++++++++++++++++ src/controllers/filmsController.js | 72 ++++++++++++++++++++++++++++ src/controllers/usersController.js | 69 +++++++++++++++++++++++++++ src/routers/books.js | 15 +++++- src/routers/films.js | 15 ++++++ src/routers/users.js | 15 ++++++ src/server.js | 18 +++---- 9 files changed, 328 insertions(+), 10 deletions(-) create mode 100644 src/controllers/booksController.js create mode 100644 src/controllers/filmsController.js create mode 100644 src/controllers/usersController.js diff --git a/package-lock.json b/package-lock.json index fc9d54a..b0cc715 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "cors": "^2.8.5", "express": "^4.18.2", + "joi": "^13.1.0", "morgan": "^1.10.0" }, "devDependencies": { @@ -2341,6 +2342,15 @@ "node": ">=8" } }, + "node_modules/hoek": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.4.tgz", + "integrity": "sha512-Alr4ZQgoMlnere5FZJsIyfIjORBqZll5POhDsF4q64dPuJR6rNxXdDxtHSQq8OXRurhmx+PWYEE8bXRROY8h0w==", + "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", + "engines": { + "node": ">=8.9.0" + } + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -2529,6 +2539,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/isemail": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", + "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==", + "dependencies": { + "punycode": "2.x.x" + }, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3212,6 +3233,20 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/joi": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-13.1.0.tgz", + "integrity": "sha512-x6pGmDYI6hwNi3skP6irQqRaJntzeaWmZ4rsnjc/NTlf6P5Gp3Aw/O8REe8oLJ6wPhrzd9K3RW1m3Yz/Hx4Weg==", + "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", + "dependencies": { + "hoek": "5.x.x", + "isemail": "3.x.x", + "topo": "3.x.x" + }, + "engines": { + "node": ">=8.9.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3891,6 +3926,14 @@ "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", "dev": true }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -4504,6 +4547,21 @@ "node": ">=0.6" } }, + "node_modules/topo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz", + "integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==", + "deprecated": "This module has moved and is now available at @hapi/topo. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.", + "dependencies": { + "hoek": "6.x.x" + } + }, + "node_modules/topo/node_modules/hoek": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", + "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==", + "deprecated": "This module has moved and is now available at @hapi/hoek. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues." + }, "node_modules/touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", diff --git a/package.json b/package.json index c63bc01..78dc601 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "dependencies": { "cors": "^2.8.5", "express": "^4.18.2", + "joi": "^13.1.0", "morgan": "^1.10.0" }, "devDependencies": { diff --git a/src/controllers/booksController.js b/src/controllers/booksController.js new file mode 100644 index 0000000..66a691a --- /dev/null +++ b/src/controllers/booksController.js @@ -0,0 +1,75 @@ +const Joi = require("Joi"); +const { books } = require("../../data/index"); + +function findBook(req, res) { + const id = Number.parseInt(req.params.id, 10); + const book = books.find((book) => book.id === id); + + return { book, id }; +} + +function validateBook(req, res) { + const schema = { + title: Joi.string().required(), + type: Joi.string().required(), + author: Joi.string().required(), + }; + + return Joi.validate(req.body, schema); +} + +exports.getAllBooks = (req, res) => { + res.status(200).json({ books }); +}; + +exports.createBook = (req, res) => { + const isExisted = books.find((book) => book.title === req.body.title); + if (isExisted) + return res.status(409).send("A book with provided title already exists"); + + const { error } = validateBook(req, res); + if (error) return res.status(400).send(error.details[0].message); + + const id = books[books.length - 1].id + 1; + const newBook = { id, ...req.body }; + + books.push(newBook); + res.status(201).json({ book: newBook }); +}; + +exports.getBook = (req, res) => { + const { book, id } = findBook(req, res); + if (!book) + return res.status(404).send(`The book with ID ${id} is not found.`); + + res.status(200).json({ book }); +}; + +exports.deleteBook = (req, res) => { + const { book, id } = findBook(req, res); + if (!book) + return res.status(404).send(`The book with ID ${id} is not found.`); + + books.splice(books.indexOf(book), 1); + + res.status(200).json({ book }); +}; + +exports.updateBook = (req, res) => { + const { book, id } = findBook(req, res); + if (!book) + return res.status(404).send(`The book with ID ${id} is not found.`); + + const isExisted = books.find((book) => book.title === req.body.title); + if (isExisted) + return res.status(409).send("A book with provided title already exists"); + + const { error } = validateBook(req, res); + if (error) return res.status(400).send(error.details[0].message); + + book.title = req.body.title; + book.type = req.body.type; + book.author = req.body.type; + + res.status(200).json({ book }); +}; diff --git a/src/controllers/filmsController.js b/src/controllers/filmsController.js new file mode 100644 index 0000000..8bb199e --- /dev/null +++ b/src/controllers/filmsController.js @@ -0,0 +1,72 @@ +const Joi = require("Joi"); +const { films } = require("../../data/index"); + +function findFilm(req, res) { + const id = Number.parseInt(req.params.id, 10); + const film = films.find((film) => film.id === id); + + return { film, id }; +} + +function validateFilm(req, res) { + const schema = { + title: Joi.string().required(), + director: Joi.string().required(), + }; + + return Joi.validate(req.body, schema); +} + +exports.getAllFilms = (req, res) => { + res.status(200).json({ films }); +}; + +exports.createFilm = (req, res) => { + const isExisted = films.find((film) => film.title === req.body.title); + if (isExisted) + return res.status(409).send("A film with provided title already exists"); + + const { error } = validateFilm(req, res); + if (error) return res.status(400).send(error.details[0].message); + + const id = films[films.length - 1].id + 1; + const newFilm = { id, ...req.body }; + + films.push(newFilm); + res.status(201).json({ film: newFilm }); +}; + +exports.getFilm = (req, res) => { + const { film, id } = findFilm(req, res); + if (!film) + return res.status(404).send(`The film with ID ${id} is not found.`); + + res.status(200).json({ film }); +}; + +exports.deleteFilm = (req, res) => { + const { film, id } = findFilm(req, res); + if (!film) + return res.status(404).send(`The film with ID ${id} is not found.`); + + films.splice(films.indexOf(film), 1); + + res.status(200).json({ film }); +}; + +exports.updateFilm = (req, res) => { + const { film, id } = findFilm(req, res); + if (!film) + return res.status(404).send(`The film with ID ${id} is not found.`); + + const isExisted = films.find((film) => film.title === req.body.title); + if (isExisted) + return res.status(409).send("A film with provided title already exists"); + + const { error } = validateFilm(req, res); + if (error) return res.status(400).send(error.details[0].message); + + film.title = req.body.title; + film.director = req.body.director; + res.status(200).json({ film }); +}; diff --git a/src/controllers/usersController.js b/src/controllers/usersController.js new file mode 100644 index 0000000..e724acc --- /dev/null +++ b/src/controllers/usersController.js @@ -0,0 +1,69 @@ +const Joi = require("Joi"); +const { users } = require("../../data/index"); + +const findUser = (req, res) => { + const id = Number.parseInt(req.params.id, 10); + const user = users.find((user) => user.id === id); + return { user, id }; +}; + +const validateUser = (req, res) => { + const schema = { + email: Joi.string().required(), + }; + + return Joi.validate(req.body, schema); +}; + +exports.getAllUsers = (req, res) => { + res.status(200).json({ users }); +}; + +exports.createUser = (req, res) => { + const isExisted = users.find((user) => user.email === req.body.email); + if (isExisted) + return res.status(409).send("A user with provided email already exists"); + + const { error } = validateUser(req, res); + if (error) return res.status(400).send(error.details[0].message); + + const id = users[users.length - 1].id + 1; + const newUser = { id, ...req.body }; + + users.push(newUser); + res.status(201).json({ user: newUser }); +}; + +exports.getUser = (req, res) => { + const { user, id } = findUser(req, res); + + if (!user) + return res.status(404).send(`The user with ID ${id} is not found.`); + + res.status(200).json({ user }); +}; + +exports.deleteUser = (req, res) => { + const { user, id } = findUser(req, res); + if (!user) + return res.status(404).send(`The user with ID ${id} is not found.`); + + users.splice(users.indexOf(user), 1); + res.status(200).json({ user }); +}; + +exports.updateUser = (req, res) => { + const { user, id } = findUser(req, res); + if (!user) + return res.status(404).send(`The user with ID ${id} is not found.`); + + const isExisted = users.find((user) => user.email === req.body.email); + if (isExisted) + return res.status(409).send("A user with provided email already exists"); + + const { error } = validateUser(req, res); + if (error) return res.status(400).send(error.details[0].message); + + user.email = req.body.email; + res.status(200).json({ user }); +}; diff --git a/src/routers/books.js b/src/routers/books.js index 18b9a7c..5e12d6b 100644 --- a/src/routers/books.js +++ b/src/routers/books.js @@ -1,4 +1,15 @@ -// Import data here... +const express = require("express"); +const booksController = require("../controllers/booksController"); +const router = express.Router(); +router + .route("/") + .get(booksController.getAllBooks) + .post(booksController.createBook); +router + .route("/:id") + .get(booksController.getBook) + .delete(booksController.deleteBook) + .put(booksController.updateBook); -// Write routes here... +module.exports = router; diff --git a/src/routers/films.js b/src/routers/films.js index e69de29..245e4c3 100644 --- a/src/routers/films.js +++ b/src/routers/films.js @@ -0,0 +1,15 @@ +const express = require("express"); +const filmsController = require("../controllers/filmsController"); +const router = express.Router(); + +router + .route("/") + .get(filmsController.getAllFilms) + .post(filmsController.createFilm); +router + .route("/:id") + .get(filmsController.getFilm) + .delete(filmsController.deleteFilm) + .put(filmsController.updateFilm); + +module.exports = router; diff --git a/src/routers/users.js b/src/routers/users.js index e69de29..9e31ff6 100644 --- a/src/routers/users.js +++ b/src/routers/users.js @@ -0,0 +1,15 @@ +const express = require("express"); +const usersController = require("../controllers/usersController"); +const router = express.Router(); + +router + .route("/") + .get(usersController.getAllUsers) + .post(usersController.createUser); +router + .route("/:id") + .get(usersController.getUser) + .delete(usersController.deleteUser) + .put(usersController.updateUser); + +module.exports = router; diff --git a/src/server.js b/src/server.js index 715321f..d08cbcd 100644 --- a/src/server.js +++ b/src/server.js @@ -1,18 +1,20 @@ const express = require("express"); -const app = express(); - const cors = require("cors"); const morgan = require("morgan"); +const usersRouter = require("./routers/users"); +const filmsRouter = require("./routers/films"); +const booksRouter = require("./routers/books"); + +const app = express(); + // SETUP MIDDLEWARE app.use(cors()); app.use(express.json()); app.use(morgan("dev")); -// REQUIRE ROUTERS -const usersRouter = require("./routers/users"); - -// ADD ROUTERS TO APP - +app.use("/users", usersRouter); +app.use("/films", filmsRouter); +app.use("/books", booksRouter); -module.exports = app +module.exports = app; From 2acf10926adca09a9ebbd6d75a911445c4765899 Mon Sep 17 00:00:00 2001 From: Hamada Abdelaal Date: Wed, 19 Jun 2024 18:14:26 +0200 Subject: [PATCH 2/3] joi --- src/server.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server.js b/src/server.js index d08cbcd..3046941 100644 --- a/src/server.js +++ b/src/server.js @@ -1,3 +1,4 @@ +const Joi = require("Joi"); const express = require("express"); const cors = require("cors"); const morgan = require("morgan"); From 9f9131d3bac44fcabba4de6e5256fe13cacf4ffe Mon Sep 17 00:00:00 2001 From: Hamada Abdelaal Date: Thu, 20 Jun 2024 15:19:26 +0200 Subject: [PATCH 3/3] change Joi to joi --- src/controllers/booksController.js | 2 +- src/controllers/filmsController.js | 2 +- src/controllers/usersController.js | 2 +- src/server.js | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/controllers/booksController.js b/src/controllers/booksController.js index 66a691a..81b9bde 100644 --- a/src/controllers/booksController.js +++ b/src/controllers/booksController.js @@ -1,4 +1,4 @@ -const Joi = require("Joi"); +const Joi = require("joi"); const { books } = require("../../data/index"); function findBook(req, res) { diff --git a/src/controllers/filmsController.js b/src/controllers/filmsController.js index 8bb199e..8e64cbf 100644 --- a/src/controllers/filmsController.js +++ b/src/controllers/filmsController.js @@ -1,4 +1,4 @@ -const Joi = require("Joi"); +const Joi = require("joi"); const { films } = require("../../data/index"); function findFilm(req, res) { diff --git a/src/controllers/usersController.js b/src/controllers/usersController.js index e724acc..429359e 100644 --- a/src/controllers/usersController.js +++ b/src/controllers/usersController.js @@ -1,4 +1,4 @@ -const Joi = require("Joi"); +const Joi = require("joi"); const { users } = require("../../data/index"); const findUser = (req, res) => { diff --git a/src/server.js b/src/server.js index 3046941..d08cbcd 100644 --- a/src/server.js +++ b/src/server.js @@ -1,4 +1,3 @@ -const Joi = require("Joi"); const express = require("express"); const cors = require("cors"); const morgan = require("morgan");