Nest: Nest 5.0.0-rc.2 Swagger example not correct generate parameters

Created on 4 May 2018  路  13Comments  路  Source: nestjs/nest

I'm submitting a...


[ ] Regression 
[x ] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior


Swagger example not correct generate parameters

Expected behavior


parameters should generate correct.

Minimal reproduction of the problem with instructions

use example codes:
https://github.com/nestjs/nest/tree/master/sample/11-swagger

What is the motivation / use case for changing the behavior?

Environment


Nest version: 5.0.0-rc.2


{
    "@nestjs/microservices": "^5.0.0-rc.2",
    "@nestjs/common": "^5.0.0-rc.2",
    "@nestjs/core": "^5.0.0-rc.2",
    "@nestjs/passport": "^1.0.6",
    "@nestjs/swagger": "^1.2.2",
    "@nestjs/testing": "^5.0.0-rc.2",
    "@nestjs/typeorm": "^2.0.0",
    "@nestjs/websockets": "^5.0.0-rc.2",
    "class-transformer": "^0.1.7",
    "class-validator": "^0.7.2",
    "reflect-metadata": "^0.1.12",
    "rxjs": "^6.0.0",
    "rxjs-compat": "^6.0.0",
    "typescript": "^2.8.0"
  }

For Tooling issues:

  • Node version: XX
  • Platform:

Others:

3rd-party 馃殌 type todo 馃挌

Most helpful comment

@kamilmysliwiec I also have to specify ApiImplicitParam otherwise the params do not show up in the UI:

  @Get(':id/:id2')
  @ApiImplicitParam({ name: 'id2' })
  @ApiImplicitParam({ name: 'id' })
  findOne(@Param('id') id, @Param('id2') id2) {
    return `This action returns a #${id} cat #${id2}`;
  }

Is this expected? In addition, I installed nest (CLI) from scratch today and got these versions:

[System Information]
OS Version     : macOS High Sierra
NodeJS Version : v8.12.0
NPM Version    : 6.4.1
[Nest Information]
swagger version : 2.5.1
common version  : 5.1.0
core version    : 5.1.0

Isn't 5.4.0 the latest Nest version?

All 13 comments

image

After spent a whole day to trace, I found the issue caused by .
https://github.com/nestjs/nest/blob/master/packages/common/decorators/http/route-params.decorator.ts

const createRouteParamDecorator = (paramtype: RouteParamtypes) => {
  return (data?: ParamData): ParameterDecorator => (target, key, index) => {
    const args =
      Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {};
    Reflect.defineMetadata(
      ROUTE_ARGS_METADATA,
      assignMetadata(args, paramtype, index, data),
      target.constructor,
      key,
    );
  };
};

const createPipesRouteParamDecorator = (paramtype: RouteParamtypes) => (
  data?,
  ...pipes: (Type<PipeTransform> | PipeTransform)[],
): ParameterDecorator => (target, key, index) => {
  const args =
    Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {};
  const hasParamData = isNil(data) || isString(data);
  const paramData = hasParamData ? data : undefined;
  const paramPipes = hasParamData ? pipes : [data, ...pipes];

  Reflect.defineMetadata(
    ROUTE_ARGS_METADATA,
    assignMetadata(args, paramtype, index, paramData, ...paramPipes),
    target.constructor,
    key,
  );
};
the target changed to target.constructor

But I do not clearly understand why need this changes?

Thanks for reporting @vellengs. I'll take care of it soon.

The compatible version of the @nestjs/swagger has been published (v2.0.0).

@vellengs @kamilmysliwiec I also found that in Get(':id'), Put(':id'), Delete(':id') methods that id parameter does not exist in the swagger API.
in the swagger document, the API looks like /cat/{id}, which I suppose there will be an id parameter which is not.

@chj-damon you have to explicitly use @Param('id') in your code.

@kamilmysliwiec Thanks, but it's not @Param('id'), it actually is @ApiImplicitParam({ name: 'id' }).

Not exactly. If you don't use @Param('id') in your method signature, you have to use @ApiImplicitParam({ name: 'id' }). Otherwise, just @Param('id') should be enough.

@kamilmysliwiec I hardly think so.
way 1:

@Get(':id')
@Param('id')
async findById(@Param() params, @Res() res) {
const questionnaire = await this.service.findById(params.id);
return httpResult(res, true, '闂嵎鏌ヨ鎴愬姛', questionnaire);
}
it reports an error: (node:33063) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Cannot destructure propertyprototypeof 'undefined' or 'null'.

way 2:

@Get(':id')
async findById(@Param('id') params, @Res() res) {
const questionnaire = await this.service.findById(params.id);
return httpResult(res, true, '闂嵎鏌ヨ鎴愬姛', questionnaire);
}
in swagger, there's no 'id' paramter

way 3:

@Get(':id')
@ApiImplicitParam({ name: 'id' })
async findById(@Param() params, @Res() res) {
const questionnaire = await this.service.findById(params.id);
return httpResult(res, true, '闂嵎鏌ヨ鎴愬姛', questionnaire);
}
in swagger, it works.

@kamilmysliwiec I also have to specify ApiImplicitParam otherwise the params do not show up in the UI:

  @Get(':id/:id2')
  @ApiImplicitParam({ name: 'id2' })
  @ApiImplicitParam({ name: 'id' })
  findOne(@Param('id') id, @Param('id2') id2) {
    return `This action returns a #${id} cat #${id2}`;
  }

Is this expected? In addition, I installed nest (CLI) from scratch today and got these versions:

[System Information]
OS Version     : macOS High Sierra
NodeJS Version : v8.12.0
NPM Version    : 6.4.1
[Nest Information]
swagger version : 2.5.1
common version  : 5.1.0
core version    : 5.1.0

Isn't 5.4.0 the latest Nest version?

Hi @kamilmysliwiec

  @Get(':id')
  @ApiImplicitParam({ name: 'id' })
  public findById(@Param('id') id) {
    return `${id}`;
  }

UnhandledPromiseRejectionWarning: TypeError: Cannot read property '0' of undefined
at lodash_1.mapValues.param (@nestjs/swagger/dist/explorers/api-parameters.explorer.js:33:20)

[System Information]
OS Version     : macOS High Sierra
NodeJS Version : v8.15.0
[Nest Information]
swagger version : 2.5.1
common version  : 5.1.0
core version    : 5.1.0

Could you please, help me

@kamilmysliwiec @vellengs Not sure why this is happening, but from my investigation, you can fix this by adding a type of string to that function argument. for example:

This will NOT generate the swagger parameter:

  @Get('/raw/:username')
  getUser(@Param('username') username): string {
    return 'given user: ' + username;
  }

Screen Shot 2019-05-08 at 1 58 20 PM

But this WILL

  @Get('/raw/:username')
  getUser(@Param('username') username: string): string {
    return 'given user: ' + username;
  }

Screen Shot 2019-05-08 at 1 59 00 PM

the only difference is in this part: @Param('username') username: string where I set the username parameter to be a string.

Since most of the examples here didn't include types for the function arguments, I thought I might share this because this might solve the problem in the meanwhile for people.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tronginc picture tronginc  路  3Comments

menme95 picture menme95  路  3Comments

KamGor picture KamGor  路  3Comments

cojack picture cojack  路  3Comments

janckerchen picture janckerchen  路  3Comments