Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ApiModelProperty decorator on a ManyToOne relationship looses type on one side #63

Closed
synec opened this issue Mar 9, 2018 · 9 comments
Assignees

Comments

@synec
Copy link

synec commented Mar 9, 2018

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

When defining a @ManyToOne with @ApiModelProperty the relation type gets lost in swagger definition and is set as type: ''

UserEntity:
      ...
      app:
        type: ''
      ...

Expected behavior

Swagger definition contains right type on both ends of relation

UserEntity:
      ...
      app:
        type: object
        $ref: '#/definitions/AppEntity'
      ...

Minimal reproduction of the problem with instructions

@Entity()
export class AppEntity {
  @ApiModelPropertyOptional({ type: String })
  @PrimaryGeneratedColumn('uuid')
  id: string

  @ApiModelProperty()
  @Column({ length: 256, nullable: true, default: null })
  name: string

  @ApiModelProperty({ type: UserEntity, isArray: true })
  @OneToMany(type => UserEntity, user => user.app)
  users: UserEntity[]
}
@Entity()
export class UserEntity {
  @ApiModelPropertyOptional({ type: String })
  @PrimaryGeneratedColumn('uuid')
  id: string

  @ApiModelProperty()
  @Column()
  name: string

  @ApiModelProperty({ type: AppEntity })
  @ManyToOne(type => AppEntity, app => app.users)
  app: AppEntity
}

ends up with swagger definition

  UserEntity:
    type: object
    properties:
      id:
        type: string
      name:
        type: string
      app:
        type: ''
    required:
      - name
      - app
  AppEntity:
    type: object
    properties:
      id:
        type: string
      name:
        type: string
      users:
        type: array
        items:
          $ref: '#/definitions/UserEntity'
    required:
      - name
      - users

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

@ManyToOne / @OneToMany should create correct definition

Environment


    "@nestjs/common": "^4.6.5",
    "@nestjs/core": "^4.6.5",
    "@nestjs/microservices": "^4.6.5",
    "@nestjs/swagger": "^1.1.4",
    "@nestjs/testing": "^4.6.1",
    "@nestjs/typeorm": "^2.0.0",
    "@nestjs/websockets": "^4.6.5",
    "typeorm": "^0.1.16",
    "typescript": "^2.7.2" 
@pokkia
Copy link

pokkia commented Apr 12, 2018

+1

@milescui
Copy link

milescui commented Apr 12, 2018 via email

@kamilmysliwiec kamilmysliwiec self-assigned this May 7, 2018
@nodren
Copy link

nodren commented Jun 14, 2018

this is still present in 5.0.2, also this also affects @OnetoOne type relations as well. Manually specifying a type such as @ApiModelProperty({type: MyType}) has no affect.

@muyu66
Copy link

muyu66 commented Dec 27, 2018

I hope this issue can be improved.

@labibramadhan
Copy link
Contributor

+1

@Hless
Copy link
Contributor

Hless commented Feb 20, 2019

This happens because when you have two models that depend on each other, e.g. AccesToken -> User, User -> AccesToken, one of imports will be undefined when the file first runs. In order the resolve this you need to use a function in the same way the @OneToMany / @ManyToOne decorator does it.

This illustrates the problem:

// user.entity.ts
// Reference to AccessToken class will be 'undefined' at runtime 
// because User and AccessToken depend on each other
@import { AccessToken } from "./acces-token.enitity';
class User {
    ...
    
    @ApiModelProperty({ 
        // AccessToken is undefined, therefore this type resolves to an empty object
        type: AccessToken ,  
        isArray: true 
     })
    @OneToMany(type => AccessToken, accessTokens => accessTokens.user)
    accessTokens:AccessToken[]
}

---
// access-token.entity.ts

@import { User } from "./user.entity";

class AccessToken {
    ...
    @ApiModelProperty({
        // The User import can be resolved,
        // so this will actually resolve to the User enity type
        type: User, 
     }) 
     @ManyToOne(type => User, user => user.accesTokens)
     user:User
}

A proposed fix is to wrap the related Model in a callback, the same way that @OneToMany does this. E.g.:

  ...
 @ApiModelProperty({ 
        // Using a function that returns a reference to the class fixes the issue, 
        // since the AccesToken class will be resolved when the decorator runs
        type: type => AccessToken ,  
        isArray: true 
     })
    @OneToMany(type => AccessToken, accessTokens => accessTokens.user)
    accessTokens:AccessToken[]

I already requested a merge on this pull request: #179 (labibramadhan#1)

@kamilmysliwiec
Copy link
Member

Fixed in the next version (to install run npm i @nestjs/swagger@next). Note: remember to update @nestjs/common, @nestjs/core and typescript as well to ensure that you're using the latest versions.

Steps to migrate: #355 (comment)

@kamilmysliwiec
Copy link
Member

4.0.0 has been published

@lock
Copy link

lock bot commented Apr 25, 2020

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.

@lock lock bot locked as resolved and limited conversation to collaborators Apr 25, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

8 participants