RESTful Node.js: A Structured Approach
  • Book Cover
  • About the Author
  • Links and Resources
  • Part I: The Why
    • Foreword
    • Preface
    • Chapter 1: Introduction
      • The Rise of REST and Distributed Systems
      • Problem #1: Structureless Design, Structureless REST
      • The Emergence of JavaScript and Node.js
      • Problem #2: Structureless JavaScript, Structureless Node.js
      • Behold, the Solution: A Structured Approach
      • Summary
  • Part 2: The Theory
    • Chapter 2: REST Origins
      • A Brief History of the Web and the Birth of REST
      • REST vs. HTTP
      • REST - The Abstract Web Architecture
      • HTTP - A Peak at REST's Concrete Implementation
      • What does it mean for an API to be RESTful?
      • Measuring "RESTfulness" with Richardson Maturity Model
      • Pragmatic REST vs Dogmatic REST
      • Summary
    • Chapter 3: RESTful API Design Guidelines and "Best Practices"
      • Theories vs. Principles vs. Guidelines
      • URI Design
      • Method Verbs
      • Status Codes
      • Representational Design
      • Metadata Design
      • Versioning Strategies
      • Security Considerations
      • Documentation
      • Case Study: GitHub
      • Summary
    • Chapter 4: Structured JavaScript Architecture
      • The Monstrous Monolith and Its Downfall
      • Layered/N-Tier Architecture: The Unpopular Proven Way
      • Microservices and Distributed Computing: A Popular Misdirection
      • Summary
    • Chapter 5: The 8 Step Recipe
      • Route Name (URI)
      • Input Request
      • Middleware
      • Validation
      • Domain
      • Events
      • Output Response
      • Test, Refactor, Document
      • Summary
  • Part 3: The Code
    • Chapter 6: Introduction to the Bookstore API
      • The Bookstore API Endpoint Specifications
      • API Design and Code Structure
      • Project Setup
      • Summary
    • Chapter 7: Retrieving Books from our API
      • Retrieving All Books - Planning
      • Retrieving All Books - Implementation
      • Retrieving A Book By ID - Planning
      • Retrieving A Book By ID - Implementation
      • Summary
    • Chapter 8: Adding Authentication to our API
      • Registering the User - Planning
      • Registering the User - Implementation
      • Logging the User In - Planning
      • Logging the User In - Implementation
      • Getting Authenticated User - Planning
      • Getting Authenticated User - Implementation
      • Summary
    • Chapter 9: Adding the Create, Update, and Delete Operations to our API
      • Creating A Book Listing - Planning
      • Creating A Book Listing - Implementation
      • Updating A Book Listing By ID - Planning
      • Updating A Book Listing By ID - Implementation
      • Deleting A Book Listing By ID - Planning
      • Deleting A Book Listing By ID - Implementation
      • Summary
    • Chapter 10: Testing our API
      • Testing the Request
      • Testing the Middleware
      • Testing the Validation
      • Testing the Domain
      • Testing the Event
      • Testing the Response
      • Testing the Controller
      • Integration Test
      • Summary
  • Conclusion
    • Final Words
  • Bonus!
    • Refactoring to HATEOAS
  • Appendix
    • Sources & References
Powered by GitBook
On this page
  • 1 - Route Name
  • 2 - Input Request
  • 3 - Middleware
  • 4 - Validation
  • 5 - Domain
  • 6 - Events
  • 7 - Response
Edit on GitHub
  1. Part 3: The Code
  2. Chapter 9: Adding the Create, Update, and Delete Operations to our API

Deleting A Book Listing By ID - Implementation

1 - Route Name

This will be our final API endpoint!

DELETE /api/v1/books/:id

Just like we planned, let's add in the route and our controller.

File: src/routes/book.route.js

const express = require('express')
const router = express.Router()

const {
  getAllBooks,
  getBookById,
  createABook,
  updateABook
} = require('../controllers/book')

router.get('/', getAllBooks)
router.get('/:id', getBookById)
router.post('/', createABook)
router.put('/:id', updateABook)

// This is the new route we are adding in
router.delete('/:id', deleteABook)

File: src/controllers/book/deleteABook.js

const catchException = require('../../utils/catchExceptions')

/**
 * Deletes an existing new book listing.
 */
const deleteABook = catchException(async (req, res) => {
  // Our code goes here
})

2 - Input Request

None.

3 - Middleware

As mentioned before, we will be reusing our isAuthenticated and bookPermission middleware.

If we plug those in, our route should look something like this.

File: src/routes/book.route.js

const express = require('express')
const router = express.Router()

const { deleteABook } = require('../controllers/book')

const isAuthenticated = require('../middleware/auth.middleware')
const bookPermission = require('../middleware/bookPermission.middleware')

router.delete('/:id', isAuthenticated, bookPermission, deleteABook)

module.exports = router

4 - Validation

None.

5 - Domain

If you've followed along till this point, then the following will be of no surprise to you. Do note that because we are deleting a book, the deleteOne method from mongoose will either return a 1 for successful deletion or a 0 for a failed deletion. For a failed deletion to happen, it will have been an invalid bookId was inputted. Recall that we have already taken care of that in our bookPermission middleware, so no error handling is necessary here.

File: src/domain/repositories/book.repository.js

const Model = require('../models/book.model')

// Delete
const deleteById = async (id) => {
  return await Model.deleteOne({ _id: id })
}

module.exports = {
  deleteById
}

File: src/domain/services/book.service.js

const mongoose = require('mongoose')
const ApiException = require('../../utils/ApiException')
const bookRepository = require('../repositories/book.repository')
const checkBookId = require('../../utils/checkBookId')

// Delete a book
const deleteBookById = async (bookId) => {
  return await bookRepository.deleteById(bookId)
}

module.exports = {
  deleteBookById
}

6 - Events

None.

7 - Response

Once all our error handling will be taken care of by the isAuthenticated and bookPermission middleware. If there are no errors, we should show a success message like the following.

const globalResponseDto = require('../../responses/globalResponseDto')
const catchException = require('../../utils/catchExceptions')
const bookService = require('../../domain/services/book.service')

/**
 * Deletes an existing new book listing.
 */
const deleteABook = catchException(async (req, res) => {
  const book = await bookService.deleteBookById(req.params.id)

  res.json(
    globalResponseDto({
      status: 'success',
      code: 200,
      message: `The book with the id: ${book.id} was successfully deleted.`,
      data: null,
      errors: null
    })
  )
})

module.exports = deleteABook
PreviousDeleting A Book Listing By ID - PlanningNextSummary

Last updated 3 years ago