Build A REST API With Node.js, Express, & MongoDB - Quick

Transcript of https://www.youtube.com/watch?v=fgTGADljAeg

Set up the environment

  1. Install and run npm: Downloading and installing Node.js and npm
  2. Run npm at the command line: run npm init.
  3. Press Enter to accept all the defaults to create package.json.
  4. Install mongoose: npm i express mongoose.
  5. Install dotenv and nodemon: npm i --save-dev dotenv nodemon. (This saves development dependencies that do not get built.)
  6. Within the scripts brackets, change to: {"devStart": "nodemon server.js"}
  7. Create server.js just below and at same level as package.js.
  8. Add .env and .gitignore under Current Project.
  9. In .gitignore, add these lines:
    .env
    node_modules
  10. Add these lines to server.js:
    const express = require('express')
    const app = express()
    app.listen(3000, () => console.log('Server has started'))
  11. Now run this file at cmd line: npm run devStart You should see Server has started

Configure mongoose

  1. Configure mongoose DB in server.js:
    const express = require('express')
    const app = express()
    const mongoose = require('mongoose')
    mongoose.connect('mongodb://localhost/subscribers')
    app.listen(3000, () => console.log('Server has started'))
  2. npm run devStart again and get an error so change server.js to this:
    const express = require('express')
    const app = express()
    const mongoose = require('mongoose')
    mongoose.connect('mongodb://localhost/subscribers', { userNewUrlParser: true})
    app.listen(3000, () => console.log('Server has started'))
  3. Run devStart again and get no errors. Now change server.js to this:
    const express = require('express')
    const app = express()
    const mongoose = require('mongoose')
    mongoose.connect('mongodb://localhost/subscribers', { userNewUrlParser: true})
    const db = mongoose.connection
    db.on('error', (error) => console.error(error))
    db.once('open', () => console.error('Connected to database'))
    app.listen(3000, () => console.log('Server has started'))
    Now when you run devStart again, you should see Connected to database
  4. In .env, add this line
    DATABASE_URL = mongodb://localhost/subscribers
  5. Change server.js to look like this:
    const express = require('express')
    const app = express()
    const mongoose = require('mongoose')
    mongoose.connect(process.env.DATABASE_URL, { userNewUrlParser: true})
    const db = mongoose.connection
    db.on('error', (error) => console.error(error))
    db.once('open', () => console.error('Connected to database'))
    app.listen(3000, () => console.log('Server has started'))
  6. When you run devStart now, you get an error. Change server.js to look like this:
    require('dotenv').config()
    const express = require('express')
    const app = express()
    const mongoose = require('mongoose')
    mongoose.connect(process.env.DATABASE_URL, { userNewUrlParser: true})
    const db = mongoose.connection
    db.on('error', (error) => console.error(error))
    db.once('open', () => console.error('Connected to database'))
    app.listen(3000, () => console.log('Server has started'))
  7. Run devStart again and you'll see Connected to database.

Set up the routes

  1. Set up server.js to accept JSON. Make these changes to server.js:
    require('dotenv').config()
    const express = require('express')
    const app = express()
    const mongoose = require('mongoose')
    mongoose.connect(process.env.DATABASE_URL, { userNewUrlParser: true})
    const db = mongoose.connection
    db.on('error', (error) => console.error(error))
    db.once('open', () => console.error('Connected to database'))
    const subscribersRouter = require ('./routes/subscribers')
    app.listen(3000, () => console.log('Server has started'))
  2. Create a folder named routes under Current Project, and inside that folder a file called subscribers.js
  3. Change server.js to look like this:
    require('dotenv').config()
    const express = require('express')
    const app = express()
    const mongoose = require('mongoose')
    mongoose.connect(process.env.DATABASE_URL, { userNewUrlParser: true})
    const db = mongoose.connection
    db.on('error', (error) => console.error(error))
    db.once('open', () => console.error('Connected to database'))
    app.use(express.json())
    const subscribersRouter = require ('./routes/subscribers')
    app.use('/subscribers', subscribersRouter)
    app.listen(3000, () => console.log('Server has started'))
  4. When you run this now, you get an error. Fixing this error requires "middleware". In subscribers.js, add these lines:
    const express = require('express')
    const router = express.Router()
    module.exports = router
  5. When you run now, no errors.
  6. Recommends his intro to RESTful: What Is Rest?. Now, set up the routes to be used in subscribers.js:
    const express = require('express')
    const router = express.Router()
    // Getting all
    router.get('/', (req, res) => {
    	res.send('Hello World')
    })
    // Getting one
    router.get('/:id', (req, res) => {
    })
    // Creating one
    router.post('/', (req, res) => {
    })
    // Updating one
    router.patch('/:id', (req, res) => {
    })
    // Deleting one
    router.delete('/:id', (req, res) => {
    })
    module.exports = router
  7. To make testing the code possible, get Rest Client for Visual Studio Code. Create a file called route.rest under package.js with this line (Send Request appears automatically):
     Send Request
    GET http://localhost:3000/subscribers
    
  8. Click Send Request and get Hello World back in the VSCode Response area.
  9. Back to subscribers.js, adds this to //Getting one :
    res.send(req.params.id)
    
  10. Now add this ID to route.rest:

    ###
    Send Request
    GET http://localhost:3000/subscribers/12
    Click Send Request and get 12 back.

Create the model for the application

  1. Now create a model: create a folder models and it a file called subscriber.js (no -s). To this, add these lines:
    const mongoose = require('mongoose')
    const subscriberSchema = new mongoose.Schema({
    	name: {
    		type: String,
    		required: true
    	},
    	subscriberToChannel:{
    		type: String,
    		required: true
    	},
    	subscribeDate: {
    		type: Date,
    		required: true,
    	default: Date.now
    	}
    })
    module.exports = mongoose.model('Subscriber', subscriberSchema)
    and save.
  2. Add these lines to subscribers.js:
    const express = require('express')
    const router = express.Router()
    const Subscriber = require('../models/subscriber')
    //Getting all
    router.get('/', (req, res) => {
    	try {
    		const subscribers = await Subscriber.find()
    		res.json(subscribers)
    	} catch (err) {
    		res.status(500).json({ message: err.message})
    	}
    })
    // Getting one
    router.get('/:id', (req, res) => {
    	res.send(req.params.id)
    })
    // Creating one
    router.post('/', async (req, res) => {
    	})
    	try {
    		const newSubscriber = await subscriber.save()
    		res.status(201).json(newSubscriber)
    	} catch (err) {
    	res.status(400).json({ message: err.message})
    	})
    }
    })
    // Updating one
    router.patch('/:id', (req, res) => {
    })
    // Deleting one
    router.delete('/:id', (req, res) => {
    })
    module.exports = router
    
  3. Now test this by clicking the Send Request just above GET http://localhost:3000/subscribers/12. You get [] nothing because there are no subscribers.
  4. Make these changes to //Creating one so that it looks like this:
    // Creating One
    router.post('/', async (req, res) => {
    	})
    	try {
    		const newSubscriber = await subscriber.save()
    		res.status(201).json(newSubscriber)
    	} catch (err) {
    	res.status(400).json({ message: err.message})
    })
  5. Add these lines route.rest just below Send Request
    POST http://localhost:3000/subscribers
    Content-Type: application/json
    {must skip line}
    {
    	"name": "Amazing Person",
    	"subscribedToChannel": "Web Dev Simplified"
    }
  6. Kyle tests an gets error because of Subscriber–Subscribed mixup in schema (already corrected above).
  7. Return and test the POST route in route.resdt and get the response expected, which include _id, name, subscribedToChannel, and subscribeDate.
  8. Remove name from POST in route.rest and get the expected error with 400.
  9. Because the remaining routes require an ID "/:id" which could create a lot of repetitive code, create middleware in subscribers.js just below //Deleting One block and just above module.exports = router:
    async function getSubscriber(req, res, next){
    	try {
    		subscriber = await Subscriber.findById(req.params.id)
    		if (subscriber == null) {
    			return.res.status(404).json({ message: 'Cannot find subscriber'})
    		}
    	} catch (err) {
    		return.res.status(500).json({ message: err.message})
    	}
    	res.subscriber = subscriber
    	next()
    	}
    }
  10. Change to subscribers.js under //Getting One:
    //Getting One
    router.get('/:id', getSubscriber, (req, res) => {
    	res.send(res.subscriber.name)
  11. To use this function add getSubscriber to //Getting one:
    // getting one
    router.get('/:id', getSubscriber, (req, res) => {
    	res.send(req.subscribers.name)
    })
  12. Return to route.rest and click the first Send Request (which is
    GET http://localhost:3000/subscribers
    ) in order to get current subscribers.
  13. Grab the ID that is return and paste it into the second Send Request so that it looks like this:
    GET http://localhost:3000/subscribers/{copied ID}
  14. Click on that 2nd request and get Amazing Person.
  15. Change ID in the second Send Request and get the message Cannot find subscriber
  16. Change the ID a bit and send, you'll get the expected error Cannot find subscriber.
  17. Apply getSubscriber to //Getting One:
    // Getting one
    router.get('/:id', (req, res) => {
    	res.json(res.subscriber)
    })
    
    Now try this on the 2nd Send Request in route.rest.
  18. Apply getSubscriber to //Deleting One:
    // Deleting one
    router.delete('/:id', getSubscriber, asyn(req, res) => {
    	try {
    		await res.subscriber.remove()
    		res.json({ message: 'Deleted subscriber'})
    	} catch (err) {
    		res.status(500).json({ message: err.message})
    	}
    })
  19. To test this, add these lines to route.rest:
    ###
    Send Request
    DELETE http://localhost:3000/subscribers
    {copied ID}
    }
  20. Run the delete and get the expected response Subscriber deleted; then run the delete again and gets the expected response Cannot find subscriber.. And if you try to get all subscribers, you get a [].
  21. Change //Updating One, add these lines (in subscribers.js):
    // Updating One
    router.patch('/:id', getSubscriber, async (req, res) => {
    	if (req.body.name != null) {
    		res.subscriber.name = req.body.name
    	}
    	if  (req.body.subscribedToChannel != null) {
    		res.subscriber.subscribedToChannel = req.body.subscribedToChannel
    	}
    	try {
    		const updatedSubscriber = await res.subscriber.save()
    	} catch (err) {
    		res.status(400).json({ message: err.message })
    	}
    })
    (Adds async as already inserted above.)
  22. Now back to route.rest, and add these lines:
    ###
    
    
    Send Request
    PATCH http://localhost:3000/subscribers/{copied ID}
    Content-Type: application/json
    {must skip line}
    {
    	"name": "New name",
    }
  23. The DELETE Send request won't work because the ID no longer exists. Generate a new ID as above, copy the ID and paste it into the Send Request for PATCH like this:
    Content-Type: application/json
    {must skip line}
    {
    	"name": "Amazing Person",
    	"subscribedToChannel": "Web Dev Simplified"
    }
    

Related information

What Is REST?. From Web Dev Simplified.

JavaScript Async Await. From Web Dev Simplified.

JavaScript Promises In 10 Minutes. From Web Dev Simplified.

NPM Crash Course. From Traversy Media.

Node.js Tutorial For Absolute Beginners. From Traversy Media.

Getting Started: Mongoose. mongoosejs.com.

MongoDB Crash Course. From Traversy Media.