Ahsan Hasan
Ahsan Hasan

Reputation: 67

Couldn't call controller method from route - Node.js and Express.js

I have an AuthenticationController which has the method signupWithCredentials. I have another controller called TestController that works correctly though.

While making a route, I am getting this error:

router.post('/user/signup',
AuthenticationController.signupWithCredentials)

These are my routes:

'use strict'

const { Router } = require('express')
const { TestController } = require('./../controllers/TestController')
const { AuthenticationController } = require('./../controllers/AuthenticationController')
const { AuthMiddleware } = require('./../middleware/AuthMiddleware')

const router = new Router()

router.get('/test', TestController.test)

router.post('/user/signup', AuthenticationController.signupWithCredentials)

module.exports = router

This is my Controller class

'use strict'
const uuid = require('uuid/v4')
const bcrypt = require('bcrypt')
const config = require('./../config')

const { promiseEjs } = require('./../utils/promiseEjs')
const { mailSender } = require('./../utils/mailSender')
const { errorHandler } = require('./../utils/errorHandler')
const { User } = require('./../schema/user')
const { authMiddleWare } = require('./../middleware/AuthMiddleware')

class AuthenticationController {
    /**
     * API 1.0 | POST
     * @example {
        *      firstName: String,
        *      lastName: String,
        *      email: String,
        *      password: String
        *       }
        * @param {*} req
        * @param {*} res
        */
    static async signupWithCredentials (req, res) {
        try {
            let email = req.body.email
            let user = await User.findOne({ email: email })
            if (user) {
                throw {
                    code: 400, message: 'User already exist'
                }
            }
            else {
                let emailVerificationToken = uuid()
                user = new User({
                    firstName: req.body.firstName,
                    lastName: req.body.lastName,
                    email: req.body.email,
                    password: bcrypt.hashSync(req.body.password, 8),
                    emailVerificationToken: emailVerificationToken
                })
                await user.save()
                try {
                    let emailVerificationLink = `${config.SERVER_DEV_URL}/authentication/verify?token=${emailVerificationToken}&user=${user._id}`
                    if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'staging') { emailVerificationLink = `${config.SERVER_PRODUCTION_URL}/authentication/verify?token=${emailVerificationToken}&user=${user._id}` }
                    let html = await promiseEjs.renderFile('./emails/signup.ejs', { user: user, emailVerificationLink: emailVerificationLink })
                    await mailSender.sendMail(user.email, 'Welcome to HandyGems', html)
                }
                catch (error) {
                    console.log(error)
                }
                let authToken = authMiddleWare.createJWT(user)
                await User.findOneAndUpdate({ _id: user._id }, { $set: { authToken: authToken } })
                res.send({ authToken: authToken })
            }
        }
        catch (error) {
            errorHandler.sendError(res, error)
        }
    }
}

const authenticationController = new AuthenticationController()
module.exports = { authenticationController }

Upvotes: 2

Views: 5478

Answers (1)

Ashok
Ashok

Reputation: 2932

Export your class instead of making an object of it

class AuthenticationController {
    static async signupWithCredentials (req, res) {
        console.log('you are just calling static method')
    }
    withoutStaticMethod(req, res) {
        console.log('you are just calling non static method using object')
    }
}
module.exports = AuthenticationController

If you have static method please don't make object and call it direactly using class Name like below code in your routes file

const AuthenticationController  = require('./AuthenticationController')
router.get('/signup', AuthenticationController.signupWithCredentials) 

if You want to call non static method like withoutStaticMethod then you must have to make object of class to get functionality of class

const obj  = new AuthenticationController()
router.get('/testing2', obj.withoutStaticMethod)

Static method calls are made directly on the class and are not callable on instances of the class. Static methods are often used to create utility functions.

You need to call them using the class name: CLASSNAME.STATIC_METHOD_NAME() or by calling the method as a property of the constructor: this.constructor.STATIC_METHOD_NAME().

Upvotes: 3

Related Questions