AndrewKeig / express-validation

express-validation is an express middleware that validates a request and returns a response with errors; if any of the configured validation rules fail.
MIT License
393 stars 85 forks source link

TypeError: schema[parameter].validateAsync when running API call? #122

Closed TechRova closed 2 years ago

TechRova commented 4 years ago

When I call any route in my express server , I am getting this error

TypeError: schema[parameter].validateAsync is not a function

    at validate (/home/techrova/Videos/VideoStream/node_modules/express-validation/lib/index.js:18:55)
    at /home/techrova/Videos/VideoStream/node_modules/express-validation/lib/index.js:26:25
    at Array.map (<anonymous>)
    at /home/techrova/Videos/VideoStream/node_modules/express-validation/lib/index.js:26:8
    at Layer.handle [as handle_request] (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/layer.js:95:5)
    at next (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/layer.js:95:5)
    at /home/techrova/Videos/VideoStream/node_modules/express/lib/router/index.js:281:22
    at Function.process_params (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/index.js:335:12)
    at next (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/index.js:275:10)
    at Function.handle (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/index.js:174:3)
    at router (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/index.js:47:12)
    at Layer.handle [as handle_request] (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/index.js:317:13)
    at /home/techrova/Videos/VideoStream/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/index.js:335:12)
    at next (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/index.js:275:10)
    at Function.handle (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/index.js:174:3)
    at router (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/index.js:47:12)
    at Layer.handle [as handle_request] (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/index.js:317:13)
    at /home/techrova/Videos/VideoStream/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/index.js:335:12)
    at next (/home/techrova/Videos/VideoStream/node_modules/express/lib/router/index.js:275:10)
    at cors (/home/techrova/Videos/VideoStream/node_modules/cors/lib/index.js:188:7)
    at /home/techrova/Videos/VideoStream/node_modules/cors/lib/index.js:224:17
    at originCallback (/home/techrova/Videos/VideoStream/node_modules/cors/lib/index.js:214:15)

I cannot understand what happening ?

Please explain me ?

Even I can't add details to this question , since I have no clue !!

I cant find out where this error occurs since the error message not showing the exact location and the function validateAsync not found in the code

ParamValidation.js

import Joi from 'joi';

export default {
  createUser: {
    body: {
      userName: Joi.string().required(),
      dob: Joi.string().required(),
      email: Joi.string().regex(/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/).required().error(new Error('must be valid')).label('Email'),
      gender: Joi.string().required(),
      password: Joi.string().regex(/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&_*-]).{8,}$/).required().error(new Error('should be atleast 8, having One Caps, One Number, and One special character')).label('password format'),
    }
  },

  updateUser: {
    params: {
      userId: Joi.string().hex().required()
    }
  },

  login: {
    body: {
      username: Joi.string().required(),
      password: Joi.string().required()
    }
  },

  resetPassword: {
    body: {
      otp: Joi.string().required(),
      newPassword: Joi.string().required().regex(/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&_*-]).{8,}$/).error(new Error('should be atleast 8, having One Caps, One Number, and One special character')),
      confirmPassword: Joi.any().valid(Joi.ref('newPassword')).error(new Error('must match password')).label('password format')
    }
  },

  changePassword: {
    body: {
      oldPassword: Joi.string().required(),
      newPassword: Joi.string().required().regex(/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&_*-]).{8,}$/).error(new Error('should be atleast 8, having One Caps, One Number, and One special character')),
      confirmPassword: Joi.any().valid(Joi.ref('newPassword')).error(new Error('should be atleast 8, having One Caps, One Number, and One special character')).label('password confirm')
    }
  },

  activateUser: {
    query: {
      otp: Joi.string().hex().required()
    }
  },

  forgetUser: {
    query: {
      email: Joi.string().regex(/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/).required().error(new Error('must be valid')).label('Email')
    }
  },

  following: {
    query: {
      userId: Joi.string().required().label('userId'),

    }
  },

  createCategory: {
    body: {
      name: Joi.string().required().label('name'),
      discription: Joi.string().optional().label('discription'),
      category_img: Joi.string().required().label('category_img')
    }
  },

  contactUs: {
    body: {
      createdBy: Joi.string().optional(),
      fullName: Joi.string().required(),
      email: Joi.string().required(),
      message: Joi.string().required(),
    }
  },

  createPost: {
    body: {
      title: Joi.string().required().label('title'),
      discription: Joi.string().required().label('discription'),
      videoUrl: Joi.string().required().label('videoUrl'),
      isPaid: Joi.string().required().label('isPaid'),
      price: Joi.string().optional().label('price'),
      categoryId: Joi.string().required().label('categoryId'),

    }
  },

  createImagePost: {
    body: {
      title: Joi.string().required().label('title'),
      discription: Joi.string().optional().label('discription'),
      imageUrl: Joi.string().optional().label('imageUrl'),
      categoryId: Joi.string().required().label('categoryId'),

    }
  },

  getPost: {
    query: {
      userId: Joi.string().optional().label('userId'),
      isAll: Joi.string().required().label('isAll'),
      page: Joi.string().optional().label('page'),
      limit: Joi.string().optional().label('limit'),
      search: Joi.string().optional().label('search'),
      isPaid: Joi.string().optional().label('isPaid'),
      categoryId: Joi.string().optional().label('categoryId')
    }
  },

  getImagePost: {
    query: {
      userId: Joi.string().optional().label('userId'),
      isAll: Joi.string().required().label('isAll'),
      page: Joi.string().optional().label('page'),
      limit: Joi.string().optional().label('limit'),
      search: Joi.string().optional().label('search'),
      categoryId: Joi.string().optional().label('categoryId')
    }
  },

  handleLike: {
    query: {
      postId: Joi.string().required().label('postId'),
      isLike: Joi.string().required().label('isLike')
    }
  },

  views: {
    query: {
      postId: Joi.string().required().label('postId')
    }
  },
  createChat: {
    body: {
      receiverId: Joi.string().required().label('receiverId'),
      message: Joi.string().optional().label('message')
    }
  },
  createRoom: {
    body: {
      receiverId: Joi.string().required().label('receiverId')
    }
  },
  getChat: {
    query: {
      roomId: Joi.string().required().label('roomId')
    }
  },
  userChatRoom: {
    query: {
      userId: Joi.string().required().label('userId')
    }
  },
  payment: {
    body: {
      postId: Joi.string().required().label('postId'),
      tokenId: Joi.string().required().label('tokenId')
    }
  },
  blockUser: {
    query: {
      userId: Joi.string().required().label('userId'),
      isBlock: Joi.string().required().label('isBlock')
    }
  }

};

auth.route.js

import express from 'express';
import pkj from 'express-validation';
const {validate} =  pkj;
import expressJwt from 'express-jwt';
import paramValidation from '../../config/param-validation';
import authCtrl from '../controllers/auth.controller';

const router = express.Router(); // eslint-disable-line new-cap

router.route('/login')
  .post(validate(paramValidation.login), authCtrl.login);

router.route('/forgot-password')
  .get(validate(paramValidation.forgetUser), authCtrl.forgotPassword);

router.route('/reset-password')
  .post(validate(paramValidation.resetPassword), authCtrl.resetPassword);

router.route('/verify-otp')
  .get(authCtrl.verifyOTP);

router.route('/testotp')
  .post(authCtrl.testTwilio);

router.route('/checkprofilelink')
  .get(authCtrl.checkprofilelink);

router.route('/contactus')
  .post(validate(paramValidation.contactUs), authCtrl.addContactUs);

export default router;

Please help me ?

raphasil commented 4 years ago

I am having the same problem :(

alibeknow commented 4 years ago

i'm too

AndrewKeig commented 4 years ago

@TechRova , hey did you manage to resolve this? Can you tell me which of the routes is failing?

viktorfa commented 4 years ago

Wrap your request paramater, i.e. body, params, query, etc. in a Joi.object to fix this. See how the validate() function in /lib/index.js works to understand why.

Example solution for a simple route with an :echo param: Before

const { Joi, validate } = require("express-validation");
const validation = {
  params: { message: Joi.string().required().min(2) },
};
router.get("/echo/:message", validate(validation), (req, res) =>
  res.send(req.params.message),
);

After

const { Joi, validate } = require("express-validation");
const validation = {
  params: Joi.object({ message: Joi.string().required().min(2) }),
};
router.get("/echo/:message", validate(validation), (req, res) =>
  res.send(req.params.message),
);
nilkanth987 commented 4 years ago

I solved the problem by Replacing

import Joi from 'Joi'

with

import {Joi} from 'express-validation'

papandreou commented 2 years ago

If this is still a problem, please try to golf all of that code down to a minimal reproduction. Chances are you'll figure out what the problem is as part of that exercise :)

papandreou commented 2 years ago

I think this will help: https://github.com/AndrewKeig/express-validation/pull/160