{"id":21361069,"url":"https://github.com/igrek8/nestjs-typed-responses","last_synced_at":"2025-07-13T02:32:02.495Z","repository":{"id":61550108,"uuid":"552389104","full_name":"igrek8/nestjs-typed-responses","owner":"igrek8","description":"Allows implementation of polymorphism in OAS and exports nest.js exceptions as swagger schemes","archived":false,"fork":false,"pushed_at":"2024-04-19T20:43:55.000Z","size":2783,"stargazers_count":2,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-17T11:37:35.428Z","etag":null,"topics":["nestjs","openapi","openapi3","swagger"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/igrek8.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-16T13:39:35.000Z","updated_at":"2023-06-15T13:09:53.000Z","dependencies_parsed_at":"2024-04-19T21:43:00.339Z","dependency_job_id":"3800fb28-734f-4c5c-aac1-981d93646717","html_url":"https://github.com/igrek8/nestjs-typed-responses","commit_stats":{"total_commits":422,"total_committers":3,"mean_commits":"140.66666666666666","dds":"0.028436018957345932","last_synced_commit":"ed9978e271132198fe8b3303adfcbef28145950e"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrek8%2Fnestjs-typed-responses","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrek8%2Fnestjs-typed-responses/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrek8%2Fnestjs-typed-responses/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrek8%2Fnestjs-typed-responses/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/igrek8","download_url":"https://codeload.github.com/igrek8/nestjs-typed-responses/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225646980,"owners_count":17501964,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nestjs","openapi","openapi3","swagger"],"created_at":"2024-11-22T06:08:22.767Z","updated_at":"2024-11-22T06:08:23.336Z","avatar_url":"https://github.com/igrek8.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# [Handle polymorphic responses](https://swagger.io/docs/specification/data-models/inheritance-and-polymorphism) in Nest.js OpenAPI\n\nEnables OpenAPI v3 polymorphism using `__type` metafield to resolve different exceptions or responses within the same HTTP code response group.\n\n[![NPM](https://badgen.net/npm/v/nestjs-typed-responses)](https://www.npmjs.com/nestjs-typed-responses)\n[![Coverage](https://codecov.io/gh/igrek8/nestjs-typed-responses/branch/main/graph/badge.svg)](https://codecov.io/gh/igrek8/nestjs-typed-responses)\n![Release](https://badgen.net/github/checks/igrek8/nestjs-typed-responses)\n![License](https://badgen.net/github/license/igrek8/nestjs-typed-responses)\n\n## Installation\n\n```bash\nnpm install --save nestjs-typed-responses\n\nyarn add nestjs-typed-responses\n```\n\n## OpenAPI\n\n![Swagger](./media/swagger.png)\n\n## Usage\n\n```ts\nimport { ConsoleLogger, Controller, HttpCode, HttpStatus, Module, Post, ValidationPipe } from '@nestjs/common';\nimport { APP_PIPE, NestFactory } from '@nestjs/core';\nimport {\n  ApiBadRequestResponse,\n  ApiExtraModels,\n  ApiForbiddenResponse,\n  ApiOkResponse,\n  ApiProperty,\n  DocumentBuilder,\n  refs,\n  SwaggerModule,\n} from '@nestjs/swagger';\nimport { Expose } from 'class-transformer';\nimport { IsDateString, IsString } from 'class-validator';\nimport {\n  ApiTypeMetafield,\n  BadRequestException,\n  ServiceUnavailableException,\n  TypedDataTransferObject,\n  TypedResponseModule,\n  ValidationException,\n} from 'nestjs-typed-responses';\n\nclass MyResponse implements TypedDataTransferObject {\n  // ApiTypeMetafield must be defined to specify serializable type\n  @ApiTypeMetafield('MyResponse')\n  __type = 'MyResponse';\n\n  // It is not required to apply @Expose decorator (per configuration)\n  @ApiProperty()\n  @IsString()\n  data!: string;\n\n  constructor(props: Omit\u003cMyResponse, '__type'\u003e) {\n    Object.assign(this, props);\n  }\n}\n\nclass MaintenanceException extends ServiceUnavailableException implements TypedDataTransferObject {\n  // ApiTypeMetafield must be defined to specify serializable type\n  @ApiTypeMetafield('MaintenanceException')\n  override __type = 'MaintenanceException';\n\n  // @Expose must be used explicitly in error classes as only such fields will be exposed\n  @Expose()\n  @ApiProperty({\n    example: '2022-12-31T11:00:00.000Z',\n    description: 'There is a maintenance on the server',\n  })\n  @IsDateString()\n  operationalAt!: Date;\n}\n\n@Controller()\n@ApiExtraModels(ValidationException, BadRequestException)\nclass AppController {\n  @Post()\n  @HttpCode(HttpStatus.OK)\n  @ApiOkResponse({ type: MyResponse })\n  @ApiForbiddenResponse({ type: MaintenanceException })\n  // Polymorphism https://swagger.io/docs/specification/data-models/inheritance-and-polymorphism/\n  @ApiBadRequestResponse({ schema: { oneOf: refs(ValidationException, BadRequestException) } })\n  demo(): MyResponse {\n    return new MyResponse({\n      data: 'Hello!',\n    });\n  }\n}\n\n@Module({\n  providers: [\n    {\n      provide: APP_PIPE,\n      useValue: new ValidationPipe({\n        exceptionFactory: ValidationException.exceptionFactory,\n      }),\n    },\n  ],\n  imports: [TypedResponseModule],\n  controllers: [AppController],\n})\nclass AppModule {}\n\nasync function bootstrap() {\n  const app = await NestFactory.create(AppModule);\n  const config = new DocumentBuilder().build();\n  const document = SwaggerModule.createDocument(app, config);\n  SwaggerModule.setup('/', app, document);\n  await app.listen(3000);\n}\nbootstrap();\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figrek8%2Fnestjs-typed-responses","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Figrek8%2Fnestjs-typed-responses","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figrek8%2Fnestjs-typed-responses/lists"}