part3c
# Saving data to MongoDB
Register and login
Choose organization on the top left options.
New project.
Create cluster.
Create Database username and password.
Add ip address: 0.0.0.0/0 (means from anywhere)
https://cloud.mongodb.com/v2/<Organization ID>#/overview?connectCluster=<Cluster Name>
Connect, Drivers, get the connection string.
mongodb+srv://<Database Username>:<db_password>@<Project Name>.aozyn.mongodb.net/?retryWrites=true&w=majority&appName=<Project Name>
In local backend folder
pnpm i mongodbpnpm i mongoose
new mongo.cjs file at backend root
const mongoose = require('mongoose')
if (process.argv.length < 3) { console.log('give password as argument') process.exit(1)}
const password = process.argv[2]
const url = // `mongodb+srv://fullstackopencn:${password}@fullstackopencn.aozyn.mongodb.net/noteApp?retryWrites=true&w=majority&appName=fullstackopencn` `mongodb://fullstackopencn:${password}@fullstackopencn-shard-00-00.aozyn.mongodb.net:27017,fullstackopencn-shard-00-01.aozyn.mongodb.net:27017,fullstackopencn-shard-00-02.aozyn.mongodb.net:27017/noteApp?ssl=true&replicaSet=atlas-10eei6-shard-0&authSource=admin&retryWrites=true&w=majority&appName=fullstackopencn`
mongoose.set('strictQuery', false)
mongoose.connect(url)
const noteSchema = new mongoose.Schema({ content: String, important: Boolean,})
const Note = mongoose.model('Note', noteSchema)
const note = new Note({ content: 'HTML is easy', important: true,})
note.save().then(result => { console.log('note saved!') mongoose.connection.close()})
run on cmd:
node mongo.cjs yourPassword
Got some DNS errors.
Tried to reboot, change DNS to 8.8.8.8, change internet connection(from wifi to mobile internet or vise verse).
Choose 2.2.12 and later version when getting the connect url.
Finally get the note saved result.
Check mongdb admin page, browse collections.
Comment save codes and try find:
// note.save().then(result => {// console.log('note saved!')// mongoose.connection.close()// })
Note.find({}).then(result => { result.forEach(note => { console.log(note) }) mongoose.connection.close()})
node mongo.cjs yourPassword
Exercise 3.12
3.12: Command-line database
node mongo.cjs yourpassword Anna 040-1234556node mongo.cjs yourpassword "Arto Vihavainen" 045-1232456
get
added Anna number 040-1234556 to phonebook
node mongo.cjs yourpassword
get all numbers:
phonebook:Anna 040-1234556Arto Vihavainen 045-1232456Ada Lovelace 040-1231236
My solutions
My solutions:
(Please complete your own solutions before click here.)
pnpm i mongodbpnpm i mongoose
backend mongo.cjs file
const mongoose = require('mongoose')
console.log("arg length", process.argv.length)
if (process.argv.length < 3) { console.log('give password as argument') console.log('to get all numbers: node mongo.cjs password') console.log('to add person and number: node mongo.cjs password name number') process.exit(1)}
const password = process.argv[2]
const url = `mongodb://fullstackopencn:${password}@fullstackopencn-shard-00-00.aozyn.mongodb.net:27017,fullstackopencn-shard-00-01.aozyn.mongodb.net:27017,fullstackopencn-shard-00-02.aozyn.mongodb.net:27017/phonebookApp?ssl=true&replicaSet=atlas-10eei6-shard-0&authSource=admin&retryWrites=true&w=majority&appName=fullstackopencn`
mongoose.set('strictQuery', false)
mongoose.connect(url)
const personSchema = new mongoose.Schema({ // id: String, name: String, number: String,})
const Person = mongoose.model('Person', personSchema)
if (process.argv.length === 3) { console.log("phonebook:") Person.find({}).then(result => { // console.log("printing") result.forEach(person => { console.log(person.name, person.number) }) mongoose.connection.close() })}
if (process.argv.length === 5) { // const name = process.argv[3] // const number = process.argv[4]
const person = new Person({ // name: 'Anna', // number: '040-1234556', // name: name, // number: number, name: process.argv[3], number: process.argv[4], })
person.save().then(result => { console.log(`Added ${process.argv[3]} ${process.argv[4]} to phonebook`) mongoose.connection.close() })}
if (process.argv.length > 5) { console.log('give password, name and number as arguments') process.exit(1)}
Connecting the backend to a database
revise index.js
// index.js in backend
const mongoose = require('mongoose')
const password = process.argv[2]
// DO NOT SAVE YOUR PASSWORD TO GITHUB!!const url = // `mongodb+srv://fullstack:${password}@cluster0.o1opl.mongodb.net/?retryWrites=true&w=majority` `mongodb://fullstackopencn:${password}@fullstackopencn-shard-00-00.aozyn.mongodb.net:27017,fullstackopencn-shard-00-01.aozyn.mongodb.net:27017,fullstackopencn-shard-00-02.aozyn.mongodb.net:27017/noteApp?ssl=true&replicaSet=atlas-10eei6-shard-0&authSource=admin&retryWrites=true&w=majority&appName=fullstackopencn`
mongoose.set('strictQuery',false)mongoose.connect(url)
const noteSchema = new mongoose.Schema({ content: String, important: Boolean,})
const Note = mongoose.model('Note', noteSchema)
revise get api/notes
// index.js in backend, section get api/notes
app.get('/api/notes', (request, response) => { Note.find({}).then(notes => { response.json(notes) })})
node index.js yourpassword
http://localhost:3001/
http://localhost:3001/api/notes
// index.js in backend
noteSchema.set('toJSON', { transform: (document, returnedObject) => { returnedObject.id = returnedObject._id.toString() delete returnedObject._id delete returnedObject.__v }})
Database configuration into its own module
new models/note.js file
const mongoose = require('mongoose')
mongoose.set('strictQuery', false)
const url = process.env.MONGODB_URI
console.log('connecting to', url)
mongoose.connect(url)
.then(result => { console.log('connected to MongoDB') }) .catch(error => { console.log('error connecting to MongoDB:', error.message) })
const noteSchema = new mongoose.Schema({ content: String, important: Boolean,})
noteSchema.set('toJSON', { transform: (document, returnedObject) => { returnedObject.id = returnedObject._id.toString() delete returnedObject._id delete returnedObject.__v }})
module.exports = mongoose.model('Note', noteSchema)
revise index.js
// index.js in backend
const Note = require('./models/note')
const url = process.env.MONGODB_URI
console.log('connecting to', url)
mongoose.connect(url) .then(result => { console.log('connected to MongoDB') }) .catch(error => { console.log('error connecting to MongoDB:', error.message) })
npm install dotenv
revise index.js
// index.js in backend
require('dotenv').config()const express = require('express')const app = express()
const Note = require('./models/note')
// ..
const PORT = process.env.PORTapp.listen(PORT, () => { console.log(`Server running on port ${PORT}`)})
Using database in route handlers
revise index.js
app.post('/api/notes', (request, response) => { const body = request.body
if (body.content === undefined) { return response.status(400).json({ error: 'content missing' }) }
const note = new Note({ content: body.content, important: body.important || false, })
note.save().then(savedNote => { response.json(savedNote) })})
app.get('/api/notes/:id', (request, response) => { Note.findById(request.params.id).then(note => { response.json(note) })})
Verifying frontend and backend integration
re-run backend, test on the rest client file:
GET http://localhost:3001/api/notes
###Delete http://localhost:3001/api/notes/2
###POST http://localhost:3001/api/notesContent-Type: application/json
{"content": "REST client is good in testing backend", "important": false}
Exercises 3.13.-3.14.
3.13: Phonebook database, step 1
Change the fetching of all phonebook entries so that the data is fetched from the database.
Verify that the frontend works
write all Mongoose-specific code into its own module
3.14: Phonebook database, step 2
Change the backend so that new numbers are saved to the database.
Verify frontend and backend both work.
My solutions
My solutions:
(Please complete your own solutions before click here.)
3.13 fetch phonebook entries from database
import { createRequire } from 'module';const require = createRequire(import.meta.url)const axios = require("axios");const morgan = require("morgan");const _ = require("lodash");const express = require("express");const cors = require("cors");const app = express();const mongoose = require('mongoose')const password = process.argv[2]const url = `mongodb://fullstackopencn:${password}@fullstackopencn-shard-00-00.aozyn.mongodb.net:27017,fullstackopencn-shard-00-01.aozyn.mongodb.net:27017,fullstackopencn-shard-00-02.aozyn.mongodb.net:27017/phonebookApp?ssl=true&replicaSet=atlas-10eei6-shard-0&authSource=admin&retryWrites=true&w=majority&appName=fullstackopencn`
mongoose.set('strictQuery', false)mongoose.connect(url)
const phonebookSchema = new mongoose.Schema({ name: String, number: String,})
const Person = mongoose.model('Person', phonebookSchema)
morgan.token('postBody', function getPostBody(req) { // console.log(req.method) // console.log(JSON.stringify(req.body) === JSON.stringify({})) // if (JSON.stringify(req.body) !== JSON.stringify({})) { if (req.method.toLowerCase() === "post".toLowerCase()) { return JSON.stringify(req.body) } return null})
app.use(cors());app.use(express.json());app.use(express.static('dist'))
// app.use(morgan("tiny"))app.use(morgan(':method :url :status :res[content-length] - :response-time ms :postBody'))
let persons = [ { id: "1", name: "Arto Hellas", number: "040-123456", }, { id: "2", name: "Ada Lovelace", number: "39-44-5323523", }, { id: "3", name: "Dan Abramov", number: "12-43-234345", }, { id: "4", name: "Mary Poppendieck", number: "39-23-6423122", },];
// app.get("/api/persons", (request, response) => {// response.json(persons);// });
app.get('/api/persons', (request, response) => { Person.find({}).then(persons => { response.json(persons) })})
app.get("/info", (request, response) => { let respPersons; axios.get("http://localhost:3001/api/persons") .then(resp => { // console.log(resp) respPersons = resp.data // console.log(respPersons)
response.send(` Phonebook has info for ${respPersons.length} ${respPersons.length === 1 ? "person" : "people"} <br /> ${new Date().toString()} `) })})
app.get("/api/persons/:id", (request, response) => { const id = request.params.id; const person = persons.find((person) => person.id === id)
if (person) { response.json(person) } else { response.status(404).end() }})
app.delete("/api/persons/:id", (request, response) => { const id = request.params.id; persons = persons.filter((person) => person.id !== id)
response.status(204).end()})
const generateId = () => { const maxId = persons.length > 0 ? Math.max(...persons.map((p) => Number(p.id))) : 0 return String(maxId + 1)}
app.post("/api/persons", (request, response) => { const body = request.body;
if (!body.name || !body.number) { return response.status(400).json({ error: "person name or number missing", }) }
const personsNameArray = persons.map((p) => p.name)
if (_.includes(personsNameArray, body.name)) { return response.status(400).json({ error: "name must be unique" }) }
const person = { name: body.name, number: body.number, id: generateId(), }
persons = persons.concat(person)
response.json(person)})
// const PORT = process.env.PORT;const PORT = process.env.PORT || 3001;app.listen(PORT, () => { console.log(`Server running on port ${PORT}`);});
http://localhost:3001/api/persons
Mongoose-specific code in mongoose.cjs
new file: models/person.js
const mongoose = require('mongoose')mongoose.set('strictQuery', false)
// const password = process.argv[2]// const url = `mongodb://fullstackopencn:${password}@fullstackopencn-shard-00-00.aozyn.mongodb.net:27017,fullstackopencn-shard-00-01.aozyn.mongodb.net:27017,fullstackopencn-shard-00-02.aozyn.mongodb.net:27017/phonebookApp?ssl=true&replicaSet=atlas-10eei6-shard-0&authSource=admin&retryWrites=true&w=majority&appName=fullstackopencn`const url = process.env.MONGODB_URI
console.log('connecting to', url)
// mongoose.connect(url)mongoose.connect(url) .then(result => { console.log('connected to MongoDB') }) .catch(error => { console.log('error connecting to MongoDB:', error.message) })
const phonebookSchema = new mongoose.Schema({ name: String, number: String,})
// const Person = mongoose.model('Person', phonebookSchema)
phonebookSchema.set('toJSON', { transform: (document, returnedObject) => { returnedObject.id = returnedObject._id.toString() delete returnedObject._id delete returnedObject.__v }})
module.exports = mongoose.model('Person', phonebookSchema)
pnpm i dotenv
new file .env
MONGODB_URI="mongodb://fullstackopencn:yourpassword@fullstackopencn-shard-00-00.aozyn.mongodb.net:27017,fullstackopencn-shard-00-01.aozyn.mongodb.net:27017,fullstackopencn-shard-00-02.aozyn.mongodb.net:27017/phonebookApp?ssl=true&replicaSet=atlas-10eei6-shard-0&authSource=admin&retryWrites=true&w=majority&appName=fullstackopencn"PORT=3001
revise index.js
import { createRequire } from 'module';const require = createRequire(import.meta.url)const axios = require("axios");const morgan = require("morgan");const _ = require("lodash");
require('dotenv').config()
const express = require("express");const cors = require("cors");const app = express();
const Person = require('./models/person')
morgan.token('postBody', function getPostBody(req) { // console.log(req.method) // console.log(JSON.stringify(req.body) === JSON.stringify({})) // if (JSON.stringify(req.body) !== JSON.stringify({})) { if (req.method.toLowerCase() === "post".toLowerCase()) { return JSON.stringify(req.body) } return null})
app.use(cors());app.use(express.json());app.use(express.static('dist'))
// app.use(morgan("tiny"))app.use(morgan(':method :url :status :res[content-length] - :response-time ms :postBody'))
let persons = [ { id: "1", name: "Arto Hellas", number: "040-123456", }, { id: "2", name: "Ada Lovelace", number: "39-44-5323523", }, { id: "3", name: "Dan Abramov", number: "12-43-234345", }, { id: "4", name: "Mary Poppendieck", number: "39-23-6423122", },];
// app.get("/api/persons", (request, response) => {// response.json(persons);// });
app.get('/api/persons', (request, response) => { Person.find({}).then(persons => { response.json(persons) })})
app.get("/info", (request, response) => { let respPersons; axios.get("http://localhost:3001/api/persons") .then(resp => { // console.log(resp) respPersons = resp.data // console.log(respPersons)
response.send(` Phonebook has info for ${respPersons.length} ${respPersons.length === 1 ? "person" : "people"} <br /> ${new Date().toString()} `) })})
app.get("/api/persons/:id", (request, response) => { const id = request.params.id; const person = persons.find((person) => person.id === id)
if (person) { response.json(person) } else { response.status(404).end() }})
app.delete("/api/persons/:id", (request, response) => { const id = request.params.id; persons = persons.filter((person) => person.id !== id)
response.status(204).end()})
const generateId = () => { const maxId = persons.length > 0 ? Math.max(...persons.map((p) => Number(p.id))) : 0 return String(maxId + 1)}
app.post("/api/persons", (request, response) => { const body = request.body;
if (!body.name || !body.number) { return response.status(400).json({ error: "person name or number missing", }) }
const personsNameArray = persons.map((p) => p.name)
if (_.includes(personsNameArray, body.name)) { return response.status(400).json({ error: "name must be unique" }) }
const person = { name: body.name, number: body.number, id: generateId(), }
persons = persons.concat(person)
response.json(person)})
const PORT = process.env.PORT;// const PORT = process.env.PORT || 3001;app.listen(PORT, () => { console.log(`Server running on port ${PORT}`);});
re-run backend
node index yourpassword
http://localhost:3001/api/persons
3.14: Phonebook database, step 2
Change the backend so that new numbers are saved to the database.
Verify frontend and backend both work.
index.js
import { createRequire } from 'module';const require = createRequire(import.meta.url)const axios = require("axios");const morgan = require("morgan");const _ = require("lodash");
require('dotenv').config()
const express = require("express");const cors = require("cors");const app = express();
const Person = require('./models/person.cjs')
morgan.token('postBody', function getPostBody(req) { // console.log(req.method) // console.log(JSON.stringify(req.body) === JSON.stringify({})) // if (JSON.stringify(req.body) !== JSON.stringify({})) { if (req.method.toLowerCase() === "post".toLowerCase()) { return JSON.stringify(req.body) } return null})
app.use(cors());app.use(express.json());app.use(express.static('dist'))
// app.use(morgan("tiny"))app.use(morgan(':method :url :status :res[content-length] - :response-time ms :postBody'))
let persons = [ { id: "1", name: "Arto Hellas", number: "040-123456", }, { id: "2", name: "Ada Lovelace", number: "39-44-5323523", }, { id: "3", name: "Dan Abramov", number: "12-43-234345", }, { id: "4", name: "Mary Poppendieck", number: "39-23-6423122", },];
// app.get("/api/persons", (request, response) => {// response.json(persons);// });
app.get('/api/persons', (request, response) => { Person.find({}).then(persons => { response.json(persons) })})
app.get("/info", (request, response) => { let respPersons; axios.get("http://localhost:3001/api/persons") .then(resp => { // console.log(resp) respPersons = resp.data // console.log(respPersons)
response.send(` Phonebook has info for ${respPersons.length} ${respPersons.length === 1 ? "person" : "people"} <br /> ${new Date().toString()} `) })})
// app.get("/api/persons/:id", (request, response) => {// const id = request.params.id;// const person = persons.find((person) => person.id === id)
// if (person) {// response.json(person)// } else {// response.status(404).end()// }// })
app.get('/api/persons/:id', (request, response) => { console.log("getting /api/persons/:id") try { Person.findById(request.params.id).then(person => { response.json(person) }) } catch (error) { console.log(error) }})
app.delete("/api/persons/:id", (request, response) => { const id = request.params.id; persons = persons.filter((person) => person.id !== id)
response.status(204).end()})
const generateId = () => { const maxId = persons.length > 0 ? Math.max(...persons.map((p) => Number(p.id))) : 0 return String(maxId + 1)}
// app.post("/api/persons", (request, response) => {// const body = request.body;
// if (!body.name || !body.number) {// return response.status(400).json({// error: "person name or number missing",// })// }
// const personsNameArray = persons.map((p) => p.name)
// if (_.includes(personsNameArray, body.name)) {// return response.status(400).json({// error: "name must be unique"// })// }
// const person = {// name: body.name,// number: body.number,// id: generateId(),// }
// persons = persons.concat(person)
// response.json(person)// })
app.post('/api/persons', (request, response) => { const body = request.body
if (body.name === undefined || body.number === undefined) { return response.status(400).json({ error: 'name or number missing' }) }
const person = new Person({ name: body.name, number: body.number, })
person.save().then(savedPerson => { response.json(savedPerson) })})
const PORT = process.env.PORT;// const PORT = process.env.PORT || 3001;app.listen(PORT, () => { console.log(`Server running on port ${PORT}`);});
requests/get_all_persons.rest
GET http://localhost:3001/api/persons
###GET http://localhost:3001/info
###GET http://localhost:3001/api/persons/66d2b0bc1d9e01022bd37b0e
###GET http://localhost:3001/api/persons/4
###GET http://localhost:3001/api/persons/5
###DELETE http://localhost:3001/api/persons/4
###POST http://localhost:3001/api/personsContent-Type: application/json
{ "name": "testname", "number": "000-000000"}
Error handling
visit http://localhost:3001/api/notes/5c41c90e84d891c15dfa3431
will get null, because the id is not exist.
// index.js backend
app.get('/api/notes/:id', (request, response) => { Note.findById(request.params.id) .then(note => {
if (note) { response.json(note) } else { response.status(404).end() } })
.catch(error => { console.log(error) response.status(500).end() })})
Now visit
http://localhost:3001/api/notes/asdf
will get 500, because of the string cast error from the server (it asks for the string to be 24 characters long)
http://localhost:3001/api/notes/asdfasdfasdfasdfasdfasdf
will get 404, because of note with the id is not found.
// revise index.js
// response.status(500).end() response.status(400).send({ error: 'malformatted id'})
set the response to 400 and send the error message.
Moving error handling into middleware
app.get('/api/notes/:id', (request, response, next) => { Note.findById(request.params.id) .then(note => { if (note) { response.json(note) } else { response.status(404).end() } })
.catch(error => next(error))})
const errorHandler = (error, request, response, next) => { console.error(error.message)
if (error.name === 'CastError') { return response.status(400).send({ error: 'malformatted id' }) }
next(error)}
// this has to be the last loaded middleware, also all the routes should be registered before this!app.use(errorHandler)
The order of middleware loading
The execution order of middleware is the same as the order that they are loaded into Express with the app.use function. For this reason, it is important to be careful when defining middleware.
app.use(express.static('dist'))app.use(express.json())// app.use(requestLogger)
// all route handlers
const unknownEndpoint = (request, response) => { response.status(404).send({ error: 'unknown endpoint' })}
// handler of requests with unknown endpointapp.use(unknownEndpoint)
const errorHandler = (error, request, response, next) => { // ...}
// handler of requests with result to errorsapp.use(errorHandler)
Other operations
app.delete('/api/notes/:id', (request, response, next) => { Note.findByIdAndDelete(request.params.id) .then(result => { response.status(204).end() }) .catch(error => next(error))})
app.put('/api/notes/:id', (request, response, next) => { const body = request.body
const note = { content: body.content, important: body.important, }
Note.findByIdAndUpdate(request.params.id, note, { new: true }) .then(updatedNote => { response.json(updatedNote) }) .catch(error => next(error))})
A true full stack developer’s oath
Full stack development is extremely hard, that is why I will use all the possible means to make it easier
- I will have my browser developer console open all the time
- I will use the network tab of the browser dev tools to ensure that frontend and backend are communicating as I expect
- I will constantly keep an eye on the state of the server to make sure that the data sent there by the frontend is saved there as I expect
- I will keep an eye on the database: does the backend save data there in the right format
- I progress with small steps
- I will write lots of console.log statements to make sure I understand how the code behaves and to help pinpoint problems
- If my code does not work, I will not write more code. Instead, I start deleting the code until it works or just return to a state when everything was still working
- When I ask for help in the course Discord channel or elsewhere I formulate my questions properly, see here how to ask for help
Exercises 3.15 - 3.18
3.15: Phonebook database, step 3
Change the backend so that deleting phonebook entries is reflected in the database.
Verify that the frontend still works after making the changes.
3.16: Phonebook database, step 4
Move the error handling of the application to a new error handler middleware.
3.17*: Phonebook database, step 5
If the user tries to create a new phonebook entry for a person whose name is already in the phonebook, the frontend will try to update the phone number of the existing entry by making an HTTP PUT request to the entry’s unique URL.
Modify the backend to support this request.
Verify that the frontend works after making your changes.
3.18*: Phonebook database step 6
Also update the handling of the api/persons/:id and info routes to use the database, and verify that they work directly with the browser, Postman, or VS Code REST client.
Inspecting an individual phonebook entry from the browser
My solutions
My solutions:
(Please complete your own solutions before click here.)
// 3.15 - 3.18 all in this file:
import { createRequire } from 'module';const require = createRequire(import.meta.url)const axios = require("axios");const morgan = require("morgan");const _ = require("lodash");
require('dotenv').config()
const express = require("express");const cors = require("cors");const app = express();
const Person = require('./models/person.cjs')
morgan.token('postBody', function getPostBody(req) { // console.log(req.method) // console.log(JSON.stringify(req.body) === JSON.stringify({})) // if (JSON.stringify(req.body) !== JSON.stringify({})) { if (req.method.toLowerCase() === "post".toLowerCase()) { return JSON.stringify(req.body) } return null})
app.use(cors());app.use(express.static('dist'))app.use(express.json());
// app.use(morgan("tiny"))app.use(morgan(':method :url :status :res[content-length] - :response-time ms :postBody'))
let persons = [ { id: "1", name: "Arto Hellas", number: "040-123456", }, { id: "2", name: "Ada Lovelace", number: "39-44-5323523", }, { id: "3", name: "Dan Abramov", number: "12-43-234345", }, { id: "4", name: "Mary Poppendieck", number: "39-23-6423122", },];
// app.get("/api/persons", (request, response) => {// response.json(persons);// });
app.get('/api/persons', (request, response) => { Person.find({}).then(persons => { response.json(persons) })})
app.get("/info", (request, response, next) => { let respPersons; // axios.get("http://localhost:3001/api/persons") // .then(resp => { // // console.log(resp) // respPersons = resp.data // // console.log(respPersons)
// response.send(` // Phonebook has info for ${respPersons.length} ${respPersons.length === 1 ? "person" : "people"} <br /> // ${new Date().toString()} // `) // }) // .catch(error => next(error)) Person.find({}) .then(respPersons => { // response.json(respPersons) // console.log(respPersons) response.send(` Phonebook has info for ${respPersons.length} ${respPersons.length === 1 ? "person" : "people"} <br /> ${new Date().toString()} `) }) .catch(error => next(error))})
// app.get("/api/persons/:id", (request, response) => {// const id = request.params.id;// const person = persons.find((person) => person.id === id)
// if (person) {// response.json(person)// } else {// response.status(404).end()// }// })
app.get('/api/persons/:id', (request, response, next) => { console.log("getting /api/persons/:id, id: ", request.params.id) // try { // Person.findById(request.params.id).then(person => { // response.json(person) // }) // } catch (error) { // console.log(error) // }
Person.findById(request.params.id) .then(person => { if (person) { response.json(person) } else { response.status(404).end() } }) .catch(error => next(error))})
app.delete("/api/persons/:id", (request, response, next) => { // const id = request.params.id; // persons = persons.filter((person) => person.id !== id)
// response.status(204).end()
Person.findByIdAndDelete(request.params.id) .then(result => { response.status(204).end() }) .catch(error => next(error))})
app.put("/api/persons/:id", (request, response, next) => { const body = request.body
// const person = { // name: body.name, // number: body.number, // }
Person.findByIdAndUpdate(request.params.id, person, { new: true }) .then(updatedPerson => { response.json(updatedPerson) }) .catch(error => next(error))})
// const generateId = () => {// const maxId = persons.length > 0 ? Math.max(...persons.map((p) => Number(p.id))) : 0// return String(maxId + 1)// }
// app.post("/api/persons", (request, response) => {// const body = request.body;
// if (!body.name || !body.number) {// return response.status(400).json({// error: "person name or number missing",// })// }
// const personsNameArray = persons.map((p) => p.name)
// if (_.includes(personsNameArray, body.name)) {// return response.status(400).json({// error: "name must be unique"// })// }
// const person = {// name: body.name,// number: body.number,// id: generateId(),// }
// persons = persons.concat(person)
// response.json(person)// })
app.post('/api/persons', async (request, response) => { const body = request.body
if (body.name === undefined || body.number === undefined) { return response.status(400).json({ error: 'name or number missing' }) }
const existPerson = await Person.findOne({ 'name': body.name }, 'name number id')
if (existPerson) { console.log(`Person with name ${body.name} exist, updating the number...`) // Update the existing person with the new information const updatedPerson = await Person.findByIdAndUpdate( existPerson.id, body, { new: true, runValidators: true, overwrit: true } );
return response.status(200).json(updatedPerson) }
const person = new Person({ name: body.name, number: body.number, })
person.save().then(savedPerson => { response.json(savedPerson) })})
const unknownEndpoint = (request, response) => { response.status(404).send({ error: 'unknown endpoint' })}
// handler of requests with unknown endpointapp.use(unknownEndpoint)
const errorHandler = (error, request, response, next) => { console.log(error.message)
if (error.name === "CastError") { return response.status(400).send({ error: 'malformed id' }) }
next(error)}
app.use(errorHandler)
const PORT = process.env.PORT;// const PORT = process.env.PORT || 3001;app.listen(PORT, () => { console.log(`Server running on port ${PORT}`);});