In this tutorial, we are making API for a Movie Portal. Here we use NodeJs, Express-5.0, and other necessary Packages. We are Trying to Follow the MVC Pattern.
Step 1 : Scaffolding
Open your terminal and type
npm init
Fill up your required field. Then open your visual studio or any kind of editor. Create .env file type this-
PORT= 8000
DATABASE_URL = "mongodb://localhost:27017"
IMAGE_BASE_URL = "http://127.0.0.1:8000"
DBNAME = "exress_movie_api"
Then create the following folders-
- controllers
- db
- routes
- helpers
- middleware
- public / uploads
- category
- movie
Now install this app-
- express
- cors
- dotenv
- joi
- bcryptjs
- jsonwebtoken
- mongoose
- multer
- nodemon
- uuid
And here, in your package.json file add “type”: “module” because we are using express-5.0. if you don’t do that in your .js file import is not work.
After That, create an app.js file in your root folder. Here you type this –
import cors from 'cors';
import dotenv from 'dotenv';
import express from 'express';
import connectiondb from './db/connectiondb.js';
dotenv.config();
const app = express();
const port = process.env.PORT || 8000;
const DATABASE_URL = process.env.DATABASE_URL || "mongodb:://localhost:27017";
//connection database
connectiondb(DATABASE_URL);
//app use for different purpose
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended:true}))
app.listen(port, ()=>{
console.log(`server listening at http://localhost:${port}`)
})
Now create db folder inside connectiondb.js file and type this-
import mongoose from 'mongoose';
//database connection
const connectiondb = async(DATABASE_URL)=>{
try{
const options = {
dbName: process.env.DBNAME
}
const connectionResult = await mongoose.connect(DATABASE_URL, options);
console.log(`connection to mongoDB on database: ${connectionResult.connections[0].name} at ${new Date().toDateString()}`);
}catch(err){
console.log(err);
}
}
export default connectiondb;
Now last. Open your MongoDB and Create a Database. Database Name will be “express_movie_api” and Collection Name is “movies”;
Now open your terminal and type npm run dev. You can see this-
If you see your database name and current date then your connection will be ok. You are now going to the next step.
Step-2 : Model Defined
In your models folder make these files.
- User.js
- Category.js
- Movie.js
And Type this.
User.js
import mongoose from "mongoose";
const DataSchema = new mongoose.Schema({
name: {
type: String,
trim: true,
required: true,
maxlength: 32,
},
email: {
type: String,
trim: true,
required: true,
unique: true,
},
password: {
type: String,
required: true
},
},{ timestamps: true, versionKey:false })
const User = mongoose.model('User', DataSchema);
export default User;
Category.js
import mongoose from "mongoose";
const DataSchema = new mongoose.Schema({
name: {
type: String,
required: [true, 'Please enter name'],
trim: true,
maxLength: [100, 'Category name cannot exceed 100 characters']
},
image: {
type: Object,
},
},{ timestamps: true, versionKey:false })
const Category = mongoose.model('Category', DataSchema);
export default Category;
Movie.js
import mongoose from "mongoose";
const DataSchema = new mongoose.Schema({
title: {
type: String,
required: [true, 'Please enter name'],
trim: true,
maxLength: [100, 'Category name cannot exceed 100 characters']
},
category_id: {
type: mongoose.Types.ObjectId,
ref: "Category",
required: true
},
descriptin: {
type: String,
trim: true,
},
image: {
type: String,
required: true
},
},{ timestamps: true, versionKey:false })
const Movie = mongoose.model('Movie', DataSchema);
export default Movie;
Step-3 : Helpers Function define
Now you create some auxiliary function. This functions as some kind of middleware. Create this-
- bcryp.js
- jwt.js
bcryp.js Function Helping client password encoded and decoded.
import bcrypt from 'bcryptjs';
export const hashMaker = (str)=> {
const salt = bcrypt.genSaltSync(10);
return bcrypt.hashSync(str, salt);
}
export const matchData = (str, hash)=> {
return bcrypt.compareSync(str, hash);
}
jwt.js function helping Jwt token create and decoded this token.
import jwt from 'jsonwebtoken';
const secret = "@#$%^&*&*"
export const createToken = (payload)=> {
return jwt.sign(payload, secret, { expiresIn: '1d' }); //1day
}
export const decodeToken = (payload)=> {
return jwt.verify(payload, secret);
}
Step-4: Making Some Middleware.
In your middleware folder create some middleware file. Like this-
- auth.js
- fileFolderName.js
- fileUpload.js
auth.js
import { decodeToken } from '../helpers/jwt.js';
const auth = (req, res, next)=> {
try {
const token = req.headers.authorization.split(' ')[1];
req.user = decodeToken(token);
//console.log(req.user)
next();
} catch (err) {
res.status(400).send('Authentication Failed')
}
}
export default auth;
fileFolderName.js
const fileFloderName = (folderName) =>{
return ( req, res, next)=>{
req.folderName = folderName;
next();
}
}
export default fileFloderName
fileUpload.js
import multer from 'multer';
const storage = multer({
storage: multer.diskStorage({
destination: function (req, file, cb) {
const folderName = req.folderName ?? file.fieldname;
cb(null, `public/uploads/${folderName}`);
},
filename: function (req, file, cb) {
cb(null, `${Date.now()}-${file.originalname}`);
},
}),
fileFilter: function (req, file, cb) {
const allowedMimeTypes = ['image/jpeg', 'image/png']; // Specify the allowed image file types
if (allowedMimeTypes.includes(file.mimetype)) {
cb(null, true); // Accept the file
} else {
cb(new Error('Invalid file type. Only JPEG and PNG files are allowed.')); // Reject the file
}
},
limits: {
fileSize: 2 * 1024 * 1024, // Set the maximum file size (2MB in this example)
},
});
export default storage;
After that Create validation folder for validation field and then create this file
- userSingupValidator.js
- categoryStoreValidator.js
- movieStoreValidator.js
userSingupValidator.js
import Joi from 'joi';
export const userSignupValidator = (req, res, next) => {
const schema = Joi.object({
name: Joi.string().required().messages({
'any.required': 'Name is required',
}),
email: Joi.string().email().required().messages({
'string.email': 'Email must be a valid email address',
'any.required': 'Email is required',
}),
password: Joi.string()
.min(6)
.required()
.pattern(new RegExp('^[a-zA-Z0-9]{3,30}$'))
.messages({
'string.min': 'Password must be at least 6 characters',
'any.required': 'Password is required',
'string.pattern.base': 'Password must contain only alphanumeric characters',
}),
password_confirmation: Joi.string()
.valid(Joi.ref('password'))
.required()
.messages({
'any.only': 'Password confirmation must match the password',
'any.required': 'Password confirmation is required',
}),
job: Joi.string().optional(),
});
const { error } = schema.validate(req.body);
if (error) {
const errorMessage = error.details[0].message;
return res.status(400).json({ error: errorMessage });
}
next();
};
categoryStoreValidator.js
import Joi from 'joi';
export const categoryStoreValidator = (req, res, next) => {
const schema = Joi.object({
name: Joi.string()
.required().
messages({
'string.name': 'Name is required'
}),
});
const { error } = schema.validate(req.body);
if (error) {
const errorMessage = error.details[0].message;
return res.status(400).json({ error: errorMessage });
}
next();
};
movieStoreValidator.js
import Joi from 'joi';
export const movieStoreValidator = (req, res, next) => {
const schema = Joi.object({
title: Joi.string()
.required().
messages({
'string.name': 'Name is required'
}),
category_id: Joi.string()
.required().
messages({
'string.category_id': 'Category Name is required'
}),
image: Joi.string()
.required().
messages({
'string.image': 'image is required'
}),
});
const { error } = schema.validate(req.body);
if (error) {
const errorMessage = error.details[0].message;
return res.status(400).json({ error: errorMessage });
}
next();
};
Step-5 : Route define
In your routes folder create this file-
- rootRoute.js
- authRoute.js
- categoryRoute.js
- movieRoute.js
rootRoute.js
In this file you add this code-
import express from 'express';
import multer from 'multer';
import CategoryRoute from './CategoryRoute.js';
import authRoute from './authRoute.js';
import movieRoute from './movieRoute.js';
const route = (app)=>{
app.use(express.static("public/uploads/category"));
app.use(express.static("public/uploads/movie"));
app.use("/api", authRoute);
app.use("/api", CategoryRoute);
app.use("/api", movieRoute);
//Multer Error File Handling
app.use((err, req, res, next) => {
if (err instanceof multer.MulterError) {
// Multer-specific errors
return res.status(418).json({
err_code: err.code,
err_message: err.message,
});
} else {
// Handling errors for any other cases from whole application
return res.status(500).json({
err_code: 409,
err_message: "Something went wrong!",
});
}
});
//unknown route
app.use('*', (req, res)=>{
res.status(404).json({status:"fail", data:"Route does not exists"})
})
}
export default route;
here first we define static folder for save image.
app.use(express.static("public/uploads/category"));
app.use(express.static("public/uploads/movie"));
Like category image and movie image. Then write error handling image function-
//Multer Error File Handling
app.use((err, req, res, next) => {
if (err instanceof multer.MulterError) {
// Multer-specific errors
return res.status(418).json({
err_code: err.code,
err_message: err.message,
});
} else {
// Handling errors for any other cases from whole application
return res.status(500).json({
err_code: 409,
err_message: "Something went wrong!",
});
}
});
At the end we write unknown route handler function. If user didn’t write proper url then show message “Route does not exists”
//unknown route
app.use('*', (req, res)=>{
res.status(404).json({status:"fail", data:"Route does not exists"})
})
Now go to app.js file and add this line-
import rootRoute from './routes/rootRoute.js';
rootRoute(app);
like this way-
import cors from 'cors';
import dotenv from 'dotenv';
import express from 'express';
import connectiondb from './db/connectiondb.js';
import rootRoute from './routes/rootRoute.js';
dotenv.config();
const app = express();
const port = process.env.PORT || 8000;
const DATABASE_URL = process.env.DATABASE_URL || "mongodb:://localhost:27017";
//connection database
connectiondb(DATABASE_URL);
//app use for different purpose
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended:true}))
rootRoute(app);
app.listen(port, ()=>{
console.log(`server listening at http://localhost:${port}`)
})
Again we go to rootRoute.js file. Here we first discuss about authRoute which we are importing from this
import authRoute from './authRoute.js';
so, create authRoute.js file in the routes folder and write this code-
import express from 'express';
import AuthController from '../controllers/AuthController.js';
import auth from '../middleware/auth.js';
import { userSignupValidator } from '../middleware/validation/userSingupValidator.js';
const router = express.Router();
router.post('/register', userSignupValidator, AuthController.registration);
router.post('/login', AuthController.login);
router.post('/logout', AuthController.logout);
router.post('/change-password', auth, AuthController.changePassword);
export default router;
Then go to the controllers folder create AuthController.js file and write this-
import { hashMaker, matchData } from "../helpers/bcryp.js";
import { createToken } from "../helpers/jwt.js";
import User from "../models/User.js";
class UserController {
static registration = async (req, res) => {
try {
const { name, email, password, password_confirmation } = req.body;
const existEmail = await User.findOne({ email }).lean().exec();
if (existEmail) {
return res.status(413).json({
code: 201,
message: "This Email is already used.",
});
}
const hashPassword = hashMaker(password);
const registerUser = await new User({
name: name,
email: email,
password: hashPassword,
}).save();
console.log("userEmail", hashPassword);
res.status(201).json({
code: 201,
message: "User registration Successfully.",
payload: registerUser,
});
} catch (err) {
console.log(err);
res.status(500).json({
code: 500,
message: "Internal server error.",
});
}
}
static login = async (req, res) =>{
try {
const { email, password } = req.body;
const existEmail = await User.findOne({ email }).lean().exec();
//mail check
if (!existEmail) {
return res.status(413).json({
code: 201,
message: "crediential didn't match",
});
}
const hashPassword = matchData(password, existEmail.password);
//password check
if(!hashPassword){
return res.status(413).json({
code: 201,
message: "crediential didn't match",
});
}
const {_id, name} = existEmail
const payload ={
name,
email,
token: "Bearer " + createToken({ _id, email })
}
res.status(200).json({
code: 200,
message: "User Login Successfully.",
payload
});
} catch (err) {
console.log(err);
res.status(500).json({
code: 500,
message: "Internal server error.",
});
}
}
static logout = (req, res)=>{
try {
// Clear the token from the cookie
res.clearCookie('token');
res.status(200).json({
code: 200,
message: 'User logged out successfully.',
});
} catch (err) {
console.log(err);
res.status(500).json({
code: 500,
message: "Internal server error.",
});
}
}
static changePassword = async(req, res)=>{
const {password, password_confirmation } = req.body;
try{
const {_id} = req.user;
if (password !== password_confirmation) {
return res.status(413).json({
code: 201,
message: "crediential didn't match",
});
}
const userInfo = await User.findById(_id);
const hashPassword = hashMaker(password);
userInfo.password = hashPassword;
await userInfo.save();
console.log(userInfo)
//await User.updateOne({ _id: _id }, { $set: payload }, { upsert: false });
res.status(200).json({
code: 200,
message: "passwrod Change Successfully.",
});
}catch(err){
console.log(err);
res.status(500).json({
code: 500,
message: "Internal server error.",
});
}
}
}
export default UserController;
Is your output similar to this congratulation, you have successfully user registration. Now we are testing the login route.
If you log in successfully then we can see the token. This token is a jwt token. We can now use this token as an authentication.
Now we go to again rootRoute.js and this time we are talking about CategoryRoute.js. So create this file and write this
CategoryRoute.js
import express from 'express';
import CategoryController from '../controllers/CategoryController.js';
import fileFolderName from '../middleware/fileFolderName.js';
import storage from '../middleware/fileUpload.js';
import { categoryStoreValidator } from "../middleware/validation/categoryStoreValidator.js";
const router = express.Router();
router.get("/all-category", CategoryController.allCategory);
router.get("/category-wise-movies", CategoryController.categoryWiseMovie);
router.get("/single-category/:categoryId", CategoryController.singleCategory);
router.post(
"/category-store",
//auth,
categoryStoreValidator,
fileFolderName("category"),
storage.fields([{ name: "image", maxCount: 1 }]),
CategoryController.store
);
router.put(
"/category-update/:categoryId",
//auth,
categoryStoreValidator,
fileFolderName("category"),
storage.fields([{ name: "image", maxCount: 1 }]),
CategoryController.update
);
router.delete(
"/category-delete/:categoryId",
//auth,
//categoryStoreValidator,
fileFolderName("category"),
storage.fields([{ name: "image", maxCount: 1 }]),
CategoryController.delete
);
// //find product by id
router.param("categoryId", CategoryController.categoryById);
export default router;
Here you see, we write router.param("categoryId", CategoryController.categoryById). This route is a special route, like when we call single route –
router.get("/single-category/:categoryId", CategoryController.singleCategory);
here this route we passed categoryId param. So this param first calls router. param route and after that call single-category route. It helps for reduce query.
Now we go to the controllers folder create CategoryController.js and write this
import fs from "fs";
import Category from "../models/Category.js";
import Movie from "../models/Movie.js";
class CategoryController {
//find a Category by id
static categoryById = async (req, res, next, id) => {
const category = await Category.findById(id);
if (!category) {
return res.status(404).json({
code: 404,
message: "Category not found.",
});
}
req.category = category;
// console.log('cat result', req.category)
next();
};
//all Category
static allCategory = async (req, res) => {
try {
const imageBaseURL = process.env.IMAGE_BASE_URL;
const allCategory = await Category.find();
// Update the image URL for each category
const updatedCategoryList = allCategory.map((category) => {
return {
...category._doc,
image: `${imageBaseURL}/${category.image}`,
};
});
res.status(200).json({
message: "All Category",
data: updatedCategoryList,
});
} catch (err) {
console.log(err);
res.status(500).json({
code: 500,
message: "Internal server error.",
});
}
};
//Category wise movies
static categoryWiseMovie = async (req, res) => {
try {
const imageBaseURL = process.env.IMAGE_BASE_URL;
const allCategories = await Category.find();
// Update the image URL for each category
const updatedCategoryList = await Promise.all(allCategories.map(async (category) => {
// Find all movies related to this category
const movies = await Movie.find({ category_id: category._id });
// Update the image URL for each movie
const updatedMovies = movies.map((movie) => {
return {
...movie._doc,
image: `${imageBaseURL}/${movie.image}`,
};
});
return {
...category._doc,
image: category.image ? `${imageBaseURL}/${category.image}` : null,
movies: updatedMovies,
};
}));
res.status(200).json({
message: "Category-wise Movies",
data: updatedCategoryList,
});
} catch (err) {
console.log(err);
res.status(500).json({
code: 500,
message: "Internal server error.",
});
}
};
//singel Category
static singleCategory = async (req, res) => {
const imageBaseURL = process.env.IMAGE_BASE_URL;
const category = req.category;
category.image = `${imageBaseURL}/${category.image}`;
res.status(200).json({
message: "Single Category",
data: category,
});
};
//store category
static store = async (req, res) => {
const { name } = req.body;
const image = req.files.image[0].filename;
try {
// const categoryInfo = await new Category({
// name,
// image: image ?? ''
// }).save()
console.log("controller req", image);
const categoryInfo = await Category.create({
name,
image: image,
});
res.status(200).json({
message: "Category Create Successfully",
data: categoryInfo,
});
} catch (err) {
res.status(500).json({
code: 500,
message: "Internal server error.",
});
}
};
//Category update or edit
static update = async (req, res) => {
const { name } = req.body;
const imageBaseURL = process.env.IMAGE_BASE_URL;
let image = null; // Initialize image as null
let existingCategory = req.category;
try {
if (req.files && req.files.image) {
// If a new image then delete the old image
if (existingCategory && existingCategory.image) {
fs.unlinkSync(`public/uploads/category/${existingCategory.image}`);
}
// Save the new image
image = req.files.image[0].filename;
}
existingCategory.name = name ? name : existingCategory.name;
existingCategory.image = image ? image : existingCategory.image;
existingCategory.save();
// Update the image URL with the base URL
const updateCategory = await Category.findById(existingCategory._id);
updateCategory.image = `${imageBaseURL}/${updateCategory.image}`;
res.status(200).json({
message: "Category updated successfully.",
data: updateCategory,
});
} catch (err) {
console.log(err);
res.status(500).json({
code: 500,
message: "Internal server error.",
});
}
};
//delete category
static delete = async (req, res) => {
try {
// Find the category by ID
const category = req.category;
// Delete the category's image file if it exists
if (category.image) {
fs.unlinkSync(`public/uploads/category/${category.image}`);
}
// Delete the category from the database
await Category.deleteOne({ _id: category._id });
res.status(200).json({
message: "Category deleted successfully.",
});
} catch (err) {
console.log(err);
res.status(500).json({
code: 500,
message: "Internal server error.",
});
}
};
}
export default CategoryController;
Now again open your postman and test this api like this way
Now we are discussing movie route. So go to routes folder and create this-
movieRoute.js
import express from "express";
import MovieController from "../controllers/MovieController.js";
import fileFolderName from "../middleware/fileFolderName.js";
import storage from "../middleware/fileUpload.js";
import { movieStoreValidator } from "../middleware/validation/movieStoreValidator.js";
import auth from '../middleware/auth.js';
const router = express.Router();
router.get("/all-movies", MovieController.allMovie);
router.get("/top-movies", MovieController.topMovie);
router.get("/single-movie/:movieId", MovieController.singleMovie);
router.post(
"/movie-store",
//auth,
movieStoreValidator,
fileFolderName("movie"),
storage.fields([{ name: "image", maxCount: 1 }]),
MovieController.store
);
router.post(
"/ai-movie-store",
//auth,
fileFolderName("movie"),
storage.fields([{ name: "image", maxCount: 1 }]),
MovieController.aiStore
);
router.put(
"/movie-update/:movieId",
//auth,
fileFolderName("movie"),
storage.fields([{ name: "image", maxCount: 1 }]),
MovieController.update
);
router.delete(
"/movie-delete/:movieId",
//auth,
MovieController.delete
);
// //find product by id
router.param("movieId", MovieController.movieById);
export default router;
and then go to controllers folder and create this-
MovieController.js
import fs from "fs";
import { v4 } from "uuid";
import Movie from '../models/Movie.js';
class MovieController{
//find a movie by id
static movieById = async (req, res, next, id) => {
const movie = await Movie.findById(id);
console.log('movie info', movie)
if (!movie) {
return res.status(404).json({
code: 404,
message: "Movie not found.",
});
}
req.movie = movie;
// console.log('cat result', req.category)
next();
};
//all Movie
static allMovie = async (req, res) => {
try {
const imageBaseURL = process.env.IMAGE_BASE_URL;
const allMovie = await Movie.find().populate('category_id');
// Update the image URL for each category
const updatedMovieList = allMovie.map((movie) => {
return {
...movie._doc,
image: `${imageBaseURL}/${movie.image}`,
category_id: {
...movie.category_id._doc,
image: `${imageBaseURL}/${movie.category_id.image}`,
},
};
});
res.status(200).json({
message: "All Movie",
data: updatedMovieList,
});
} catch (err) {
console.log(err);
res.status(500).json({
code: 500,
message: "Internal server error.",
});
}
};
//Top Movie
static topMovie = async (req, res) => {
try {
const imageBaseURL = process.env.IMAGE_BASE_URL;
const topMovies = await Movie.find()
.sort({ createdAt: -1 })
.populate('category_id')
.limit(8);
// Update the image URL for each movie
const updatedTopMovies = topMovies.map((movie) => {
return {
...movie._doc,
image: `${imageBaseURL}/${movie.image}`,
category_id: {
...movie.category_id._doc,
image: `${imageBaseURL}/${movie.category_id.image}`,
},
};
});
res.status(200).json({
message: "Top 8 Movies",
data: updatedTopMovies,
});
} catch (err) {
console.log(err);
res.status(500).json({
code: 500,
message: "Internal server error.",
});
}
};
//singel Category
static singleMovie = async (req, res) => {
const imageBaseURL = process.env.IMAGE_BASE_URL;
const movie = req.movie;
await movie.populate('category_id');
movie.image = `${imageBaseURL}/${movie.image}`;
movie.category_id.image = `${imageBaseURL}/${movie.category_id.image}`;
res.status(200).json({
message: "Single movie",
data: movie,
});
};
//store Movie
static store = async (req, res) => {
const { title, discription, category_id } = req.body;
const image = req.files.image[0].filename;
try {
const movieInfo = await Movie.create({
title,
discription,
category_id,
image: image,
});
res.status(200).json({
message: "Movie Create Successfully",
data: movieInfo,
});
} catch (err) {
res.status(500).json({
code: 500,
message: "Internal server error.",
});
}
};
//Ai movie store
static aiStore = async (req, res) => {
const { title, category_id, description, image } = req.body;
console.log('node-1', req.body)
// Convert the base64 image data to a buffer
const imageBuffer = Buffer.from(image, 'base64');
// Generate a unique filename for the image using UUID
const imageName = `${v4()}.jpg`;
try {
// Save the image to a directory (you can change the path as needed)
fs.writeFileSync(`./public/uploads/movie/${imageName}`, imageBuffer);
// Save the movie information to the database
const movieInfo = await Movie.create({
title,
description,
category_id,
image: imageName,
});
res.status(200).json({
message: "Movie Create Successfully",
data: movieInfo,
});
} catch (err) {
res.status(500).json({
code: 500,
message: "Internal server error.",
});
}
};
//Category update or edit
static update = async (req, res) => {
const { title, discription, category_id } = req.body;
const imageBaseURL = process.env.IMAGE_BASE_URL;
let image = null; // Initialize image as null
let existingMovie = req.movie;
try {
if (req.files && req.files.image) {
// If a new image then delete the old image
if (existingMovie && existingMovie.image) {
fs.unlinkSync(`public/uploads/movie/${existingMovie.image}`);
}
// Save the new image
image = req.files.image[0].filename;
}
console.log('movie data', title, discription, category_id)
existingMovie.title = title ? title : existingMovie.title;
existingMovie.discription = discription ? discription : existingMovie.discription;
existingMovie.category_id = category_id ? category_id : existingMovie.category_id;
existingMovie.image = image ? image : existingMovie.image;
existingMovie.save();
console.log("existingMovie", existingMovie)
// Update the image URL with the base URL
const updateMovie = await Movie.findById(existingMovie._id);
updateMovie.image = `${imageBaseURL}/${updateMovie.image}`;
res.status(200).json({
message: "Movie updated successfully.",
data: updateMovie,
});
} catch (err) {
console.log(err);
res.status(500).json({
code: 500,
message: "Internal server error.",
});
}
};
//delete category
static delete = async (req, res) => {
try {
// Find the category by ID
const movie = req.movie;
// Delete the category's image file if it exists
if (movie.image) {
fs.unlinkSync(`public/uploads/movie/${movie.image}`);
}
// Delete the category from the database
await movie.deleteOne({ _id: movie._id });
res.status(200).json({
message: "movie deleted successfully.",
});
} catch (err) {
console.log(err);
res.status(500).json({
code: 500,
message: "Internal server error.",
});
}
};
}
export default MovieController
Now we do finish touch. Open postman and test it, like this-
So, our 1st part is done. Now we will do 2nd part
Scaffolding redux-toolkit in NextJs. Link
full Project github
Node
https://github.com/kamruzzamanripon/node-movie-api
NextJs
https://github.com/kamruzzamanripon/next-movie-ui-with-node-api
NextJs UI
https://github.com/kamruzzamanripon/next-movie-ui
Top comments (0)