Brakebein / prisma-generator-nestjs-dto

Generates NestJS DTO classes from Prisma Schema
Apache License 2.0
45 stars 24 forks source link

Add ApiProperty({type: () => T}) to Create/Connect DTOs #6

Closed ChristopherCapito closed 1 year ago

ChristopherCapito commented 1 year ago

I suggest adding the ApiProperty field decorator to the RelationInputDtos to improve the Swagger documentation and request examples.

Example:

export class CreateProductVariantsRelationInputDto { @ApiProperty({ type: () => [CreateVariantDto] }) create: CreateVariantDto[]; }

Brakebein commented 1 year ago

Can please again provide a short, complete example with input schema and expected output data?

ChristopherCapito commented 1 year ago

Sorry for the late response. I was a little under the water with work.

Here is a partial example of my schema. The example here would be the Product-Media Connection

model Product {
  id String @id @default(uuid())

  brand String

  description String

  productUrl String

  title String

  subtitle String?

  additionalInfo Json?

  ///@DtoRelationCanConnectOnCreate
  ///@DtoRelationCanCreateOnCreate
  bikes Bike[]

  ///@DtoRelationCanCreateOnCreate
  media Media[]

  options String[]

  tags String[]

  ///@DtoRelationCanCreateOnCreate
  ///@DtoRelationRequired
  variants Variant[]

  ///@DtoRelationCanConnectOnCreate
  vendor Vendor @relation(fields: [vendorId], references: [id], onDelete: Restrict)

  ///@DtoRelationCanConnectOnCreate
  category Category @relation(fields: [categoryId], references: [id], onDelete: Restrict)

  categoryId String

  vendorId String

  ///@DtoRelationCanCreateOnCreate
  seo Seo? @relation(fields: [seoId], references: [id], onDelete: Cascade)

  seoId String?

  @@unique([title])
}

model Media {
  id String @id @default(uuid())

  name String

  originalSource String?

  source String?

  storageId String?

  order Int?

  altText String?

  type MediaTypes

  ///@DtoRelationCanConnectOnCreate
  Variant Variant? @relation(fields: [variantId], references: [id], onDelete: Cascade, onUpdate: Cascade)

  variantId String?

  ///@DtoRelationCanConnectOnCreate
  Product Product? @relation(fields: [productId], references: [id], onDelete: Cascade, onUpdate: Cascade)

  productId String?
}

This should return the following output

Import statements removed for legibility

This is the example for the media DTO connection. This way, the swagger documentation correctly shows how the create SubObject should look like. Else it will just show an empty object.

export class CreateProductBikesRelationInputDto {
  @ApiProperty({} type: () => [CreateVariantDto])
  create?: CreateBikeDto[];

  Ignore the connect for now, I am focusing on the create for the example
  connect?: ConnectBikeDto[];
}

You can ignore the stuff below

export class CreateProductMediaRelationInputDto {
  create: CreateMediaDto[];
}
export class CreateProductVariantsRelationInputDto {
  create: CreateVariantDto[];
}
export class CreateProductVendorRelationInputDto {
  connect: ConnectVendorDto;
}
export class CreateProductCategoryRelationInputDto {
  connect: ConnectCategoryDto;
}
export class CreateProductSeoRelationInputDto {
  create: CreateSeoDto;
}

@ApiExtraModels(
  CreateBikeDto,
  ConnectBikeDto,
  CreateProductBikesRelationInputDto,
  CreateMediaDto,
  CreateProductMediaRelationInputDto,
  CreateVariantDto,
  CreateProductVariantsRelationInputDto,
  ConnectVendorDto,
  CreateProductVendorRelationInputDto,
  ConnectCategoryDto,
  CreateProductCategoryRelationInputDto,
  CreateSeoDto,
  CreateProductSeoRelationInputDto,
)
export class CreateProductDto {
  @ApiProperty()
  @IsNotEmpty()
  @IsString()
  brand: string;
  @ApiProperty()
  @IsNotEmpty()
  @IsString()
  description: string;
  @ApiProperty()
  @IsNotEmpty()
  @IsString()
  productUrl: string;
  @ApiProperty()
  @IsNotEmpty()
  @IsString()
  title: string;
  @ApiProperty({
    required: false,
    nullable: true,
  })
  @IsOptional()
  @IsString()
  subtitle?: string;
  @ApiProperty({
    required: false,
    nullable: true,
  })
  @IsOptional()
  additionalInfo?: Prisma.InputJsonValue;
  @ApiProperty()
  @IsOptional()
  bikes?: CreateProductBikesRelationInputDto;
  @ApiProperty()
  @IsOptional()
  media?: CreateProductMediaRelationInputDto;
  @ApiProperty()
  @IsNotEmpty()
  @IsArray()
  @IsString({ each: true })
  options: string[];
  @ApiProperty()
  @IsNotEmpty()
  @IsArray()
  @IsString({ each: true })
  tags: string[];
  @ApiProperty()
  @IsOptional()
  variants?: CreateProductVariantsRelationInputDto;
  @ApiProperty()
  @IsNotEmpty()
  vendor: CreateProductVendorRelationInputDto;
  @ApiProperty()
  @IsNotEmpty()
  category: CreateProductCategoryRelationInputDto;
  @ApiProperty({
    required: false,
    nullable: true,
  })
  @IsOptional()
  seo?: CreateProductSeoRelationInputDto;
}
Brakebein commented 1 year ago

I added this feature including class validation. You can checkout and test if everything is generated as expected. https://www.npmjs.com/package/@brakebein/prisma-generator-nestjs-dto/v/1.14.0-beta.0

ChristopherCapito commented 1 year ago

Works great! The generated API is much more informative now. Thank you!