diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..88b65a6 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,22 @@ +{ + "env": { + "browser": true, + "es2021": true + }, + "extends": [ + "eslint:recommended", + "plugin:react/recommended" + ], + "parserOptions": { + "ecmaFeatures": { + "jsx": true + }, + "ecmaVersion": 12, + "sourceType": "module" + }, + "plugins": [ + "react" + ], + "rules": { + } +} diff --git a/.gitignore b/.gitignore index 254e3d4..b3fbd77 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ yarn.lock -node_modules \ No newline at end of file +node_modules +package-lock.json \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..65d54ca --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM node:alpine + +WORKDIR /usr/app + +COPY package.json ./ +COPY index.js ./ + +RUN npm install + +RUN cat package.json + +RUN npm start + +EXPOSE 3000 + +# CMD npm start \ No newline at end of file diff --git a/src/app.js b/index.js similarity index 52% rename from src/app.js rename to index.js index 7ed991e..2ac87c5 100644 --- a/src/app.js +++ b/index.js @@ -1,9 +1,14 @@ const express = require('express'); const bodyParser = require('body-parser'); +const mongoose = require('./src/database/index') + const app = express(); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); -app.listen(5000); \ No newline at end of file +require('./src/controllers/userController')(app); +require('./src/controllers/recipeController')(app); + +app.listen(3001); \ No newline at end of file diff --git a/package.json b/package.json index 86ccdf7..a71f3cb 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Um projeto sobre receitas", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "start": "nodemon index.js" }, "repository": { "type": "git", @@ -19,6 +20,12 @@ "homepage": "https://github.com/bsb-devs/recipes-api#readme", "dependencies": { "body-parse": "^0.1.0", - "express": "^4.17.1" + "express": "^4.17.1", + "mongoose": "^5.11.12", + "nodemon": "^2.0.7" + }, + "devDependencies": { + "eslint": "^7.17.0", + "eslint-plugin-react": "^7.22.0" } } diff --git a/src/controllers/recipeController.js b/src/controllers/recipeController.js new file mode 100644 index 0000000..cb2c302 --- /dev/null +++ b/src/controllers/recipeController.js @@ -0,0 +1,79 @@ +const express = require('express'); + +const Recipe = require('../models/recipeModel'); +const User = require('../models/userModel'); + +const RecipeController = express.Router(); + +RecipeController.post('/register/:userId', async (req, res) => { + try { + const user = await User.findById(req.params.userId); //Pegando Id do usuario da url + const recipe = await Recipe.create({ + ...req.body, + user : user, + }) + await recipe.save(); //Salvando a receita criada + user.recipes.push(recipe); //Adicionando a receita no array do usuario + await user.save(); //Salvando o usuario antes de devolver a receita + + return res.status(201).send(recipe) + } catch(err) { + return res.status(400).send({ error: `${err}` }) + } +}); + +RecipeController.get('/findById/:recipeId', async (req, res) => { + try { + const recipe = await Recipe.findById(req.params.recipeId).populate([ + { path: 'user' }, + ]); //Pegando Id da receita da url + + return res.status(200).send(recipe) + } catch(err) { + return res.status(400).send({ error: `${err}` }) + } +}); + +RecipeController.get('/findAll', async (req, res) => { + try { + const recipes = await Recipe.find().populate([ + { path: 'user' }, + ]); //Pegando Id da receita da url + + return res.status(200).send(recipes) + } catch(err) { + return res.status(400).send({ error: `${err}` }) + } +}); + +RecipeController.delete('/delete/:recipeId', async (req, res) => { + try { + const recipe = await Recipe.findByIdAndDelete(req.params.recipeId); //Pegando Id da receita da url + + return res.status(200).send(recipe._id) + } catch(err) { + return res.status(400).send({ error: `${err}` }) + } +}); + +RecipeController.put('/update/:recipeId', async (req, res) => { + try { + const recipe = req.params.recipeId + const update = req.body + const updatedRecipe = await Recipe.findByIdAndUpdate( + recipe, + update, + { + new: true, + useFindAndModify: true, + } + ); + + return res.status(200).send(updatedRecipe) + } catch(err) { + return res.status(400).send({ error: `${err}` }) + } +}); + + +module.exports = app => app.use('/recipe', RecipeController); diff --git a/src/controllers/userController.js b/src/controllers/userController.js new file mode 100644 index 0000000..725bf1a --- /dev/null +++ b/src/controllers/userController.js @@ -0,0 +1,70 @@ +const express = require('express'); + +const User = require('../models/userModel'); + +const AuthController = express.Router(); + +AuthController.post('/register', async (req, res) => { + try { + const user = await User.create(req.body) + + return res.status(201).send({ user }) + } catch(err) { + return res.status(400).send({ error: 'Registration failed' }) + } +}); + +AuthController.get('/findById/:userId', async (req, res) => { + try { + const user = await User.findById(req.params.userId).populate([ + { path: 'recipes' }, + ]); //Pegando Id da receita da url + + return res.status(200).send(user) + } catch(err) { + return res.status(400).send({ error: `${err}` }) + } +}); + +AuthController.get('/findAll', async (req, res) => { + try { + const users = await User.find(); //Pegando Id da receita da url + + return res.status(200).send(users) + } catch(err) { + return res.status(400).send({ error: `${err}` }) + } +}); + +AuthController.delete('/delete/:userId', async (req, res) => { + try { + const users = await User.findOneAndDelete(req.params.userId); //Pegando Id da receita da url + + return res.status(200).send({ message: `this user was deleted : ${users._id}`}) + } catch(err) { + return res.status(400).send({ error: `${err}` }) + } +}); + + +AuthController.put('/update/:userId', async (req, res) => { + try { + const user = req.params.userId + const update = req.body + const updatedUser = await User.findByIdAndUpdate( + user, + update, + { + new: true, + useFindAndModify: true, + } + ); + + return res.status(200).send(updatedUser) + } catch(err) { + return res.status(400).send({ error: `${err}` }) + } +}); + + +module.exports = app => app.use('/user', AuthController); diff --git a/src/database/index.js b/src/database/index.js new file mode 100644 index 0000000..eb0ac9f --- /dev/null +++ b/src/database/index.js @@ -0,0 +1,10 @@ +const mongoose = require('mongoose'); + +mongoose.connect( + 'mongodb+srv://dev:dev12345@recipescluster.m9dnr.mongodb.net/recipes?retryWrites=true&w=majority', + { useNewUrlParser: true }, + { useUnifiedTopology: true }, +); +mongoose.Promise = global.Promise; + +module.exports = mongoose; diff --git a/src/models/exemples b/src/models/exemples new file mode 100644 index 0000000..e0eefed --- /dev/null +++ b/src/models/exemples @@ -0,0 +1,30 @@ +//User +{ + "name":"admin", + "email": "admin@admin.com", + "password": "admin" +} +//Recipe +{ + "title": "Batata recheada", + "description": "Minha comida favorita", + "difficulty": 3, + "tags": [ + "salgado", + "batata", + "assado" + ], + "servings": 1, + "estimatedTime": "1 hora", + "ingredients": [ + { + "name":"batata grande", + "qty": "1" + }, + { + "name":"Strogonof", + "qty": "10 colheres" + } + ], + "directions":"Assar a batata e rechear" +} \ No newline at end of file diff --git a/src/models/recipeModel.js b/src/models/recipeModel.js new file mode 100644 index 0000000..2e0459e --- /dev/null +++ b/src/models/recipeModel.js @@ -0,0 +1,61 @@ +const mongoose = require('mongoose'); + +const RecipeSchema = new mongoose.Schema({ + title: { + type: String, + required: true, + }, + photo: { + type: String, + }, + description: { + type: String, + required: true, + }, + difficulty: { + type: Number, + required: true, + }, + tags: [ + { + type: String, + required: true, + }, + ], + servings: { + type: Number, + required: true, + }, + estimatedTime: { + type: String, + required: true, + }, + createdAt: { + type: Date, + default: Date.now, + }, + user: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + }, + ingredients: [ + { + name: { + type: String, + require: true, + }, + qty: { + type: String, + require: true, + } + }, + ], + directions: { + type: String, + required: true, + }, +}); + +const Recipe = mongoose.model('Recipe', RecipeSchema); + +module.exports = Recipe; diff --git a/src/models/userModel.js b/src/models/userModel.js new file mode 100644 index 0000000..aa1283e --- /dev/null +++ b/src/models/userModel.js @@ -0,0 +1,43 @@ +const mongoose = require('mongoose'); + +const UserSchema = new mongoose.Schema({ + name: { + type: String, + required: true, + }, + email: { + type: String, + required: true, + unique: true, + }, + password: { + type: String, + required: true, + }, + recipes: [ + { + type: mongoose.Schema.Types.ObjectId, + ref: 'Recipe', + }, + ], + favoriteRecipes: [ + { + type: mongoose.Schema.Types.ObjectId, + ref: 'Recipe', + }, + ], + recipesHistory: [ + { + type: mongoose.Schema.Types.ObjectId, + ref: 'Recipe', + }, + ], + createdAt: { + type: Date, + default: Date.now, + }, +}); + +const User = mongoose.model('User', UserSchema); + +module.exports = User; \ No newline at end of file diff --git a/src/routes/userRoutes.js b/src/routes/userRoutes.js new file mode 100644 index 0000000..bd55090 --- /dev/null +++ b/src/routes/userRoutes.js @@ -0,0 +1,11 @@ +const express = require('express'); +const userController = require('../controllers/userController'); + +const userRoutes = new express.Router(); + +userRoutes.get('/test', userController.test); + +userRoutes.post('/login', AuthController.login); + + +module.exports = userRoutes; \ No newline at end of file