Inversifyjs: How to use express-validator with inversify-express-utils

Created on 26 Jul 2019  路  7Comments  路  Source: inversify/InversifyJS

Context

Without inversify-express-utils i use express-validator (https://express-validator.github.io/docs/) like this:

const checkContext = [query('codusur').exists()];
router.get('/context', checkContext, (req: Request, res: Response, next: NextFunction) => {
  req.setTimeout(0, null);
  const errors = validationResult(req);

  if (!errors.isEmpty()) {
    next(new UnprocessableEntityException(errors.array()));
    return;
  }
  clientBusiness.getClientByVendor(req, res, next);
});

With inversify-express-utils i can't use express-validator

@httpGet('/', [query('id').exists()])
  @withException
  async getTenants(@response() res: Response) {
    const result = await this.tenantService.find({});
    res.status(OK).send(result);
  }

The code above throws a error:

Argument of type 'ValidationChain[]' is not assignable to parameter of type 'string | symbol | Newable | Abstract | RequestHandler'.
Type 'ValidationChain[]' is not assignable to type 'string'.

So the question is: how to use these type of middleware? I'm migrating some legacy code to inversifyjs and this is the last thing that i have to do

Your Environment

  • Versions used:
    "express-validator": "^5.2.0",
    "inversify": "^5.0.1",
    "inversify-express-utils": "^6.3.2"
    NodeJS: 10.15.3

Most helpful comment

Found a solution:

const _postTenantValidators = [body('tenantID').exists(), body('tenantName').exists()];
  @httpPost('/', ..._postTenantValidators)
  @withException // Custom decorator
  async postTenant(@request() req: Request, @response() res: Response, @requestBody() tenant: TenantInterface) {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      throw new UnprocessableEntityException(errors.array()); // Custom error
    }
    const newTenant = await this.tenantService.insert(tenant);
    res.status(CREATED).send(newTenant);
  }

I created the const outside the controller class because when using the validator as a private property, inversify-express-utils throws a error:

@httpPost('/', ...this._postTenantValidators)
^
TypeError: Cannot read property 'Symbol(Symbol.iterator)' of inversify_express_utils_1.httpPost

All 7 comments

Related #938

Found a solution:

const _postTenantValidators = [body('tenantID').exists(), body('tenantName').exists()];
  @httpPost('/', ..._postTenantValidators)
  @withException // Custom decorator
  async postTenant(@request() req: Request, @response() res: Response, @requestBody() tenant: TenantInterface) {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      throw new UnprocessableEntityException(errors.array()); // Custom error
    }
    const newTenant = await this.tenantService.insert(tenant);
    res.status(CREATED).send(newTenant);
  }

I created the const outside the controller class because when using the validator as a private property, inversify-express-utils throws a error:

@httpPost('/', ...this._postTenantValidators)
^
TypeError: Cannot read property 'Symbol(Symbol.iterator)' of inversify_express_utils_1.httpPost

Found a solution:

const _postTenantValidators = [body('tenantID').exists(), body('tenantName').exists()];
  @httpPost('/', ..._postTenantValidators)
  @withException // Custom decorator
  async postTenant(@request() req: Request, @response() res: Response, @requestBody() tenant: TenantInterface) {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      throw new UnprocessableEntityException(errors.array()); // Custom error
    }
    const newTenant = await this.tenantService.insert(tenant);
    res.status(CREATED).send(newTenant);
  }

Is this really working? On my side, it seems that validation chains conflict with each others and it depends on the order I declare my controllers...

Hi @Blockost it works for me!

image

I have multiple validators for differents requets

Hey @WandersonAlves , thanks for your reply. Actually, I was doing something really weird and guess Inversify got a little lost (was defining some @httpMethod in an abstract controller and in derived classes). I fixed that and it's working fine now!

By the way, your vs code theme looks so good! :+1:

Haha, nice to hear that @Blockost!

The theme is this: https://github.com/ayu-theme/vscode-ayu with Operator Mono font https://www.cufonfonts.com/font/operator-mono

Have a nice day

@WandersonAlves thanks so much for this

Found a solution:

const _postTenantValidators = [body('tenantID').exists(), body('tenantName').exists()];
  @httpPost('/', ..._postTenantValidators)
  @withException // Custom decorator
  async postTenant(@request() req: Request, @response() res: Response, @requestBody() tenant: TenantInterface) {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      throw new UnprocessableEntityException(errors.array()); // Custom error
    }
    const newTenant = await this.tenantService.insert(tenant);
    res.status(CREATED).send(newTenant);
  }

I created the const outside the controller class because when using the validator as a private property, inversify-express-utils throws a error:

@HttpPost('/', ...this._postTenantValidators)
^
TypeError: Cannot read property 'Symbol(Symbol.iterator)' of inversify_express_utils_1.httpPost

Was this page helpful?
0 / 5 - 0 ratings