diff --git a/lib/decorators/api-response.decorator.ts b/lib/decorators/api-response.decorator.ts index 092c0b761..c30224a98 100644 --- a/lib/decorators/api-response.decorator.ts +++ b/lib/decorators/api-response.decorator.ts @@ -14,6 +14,7 @@ export interface ApiResponseMetadata type?: Type | Function | [Function] | string; isArray?: boolean; description?: string; + example?: any; } export interface ApiResponseSchemaHost diff --git a/lib/services/mimetype-content-wrapper.ts b/lib/services/mimetype-content-wrapper.ts index 545d0444c..0f5054068 100644 --- a/lib/services/mimetype-content-wrapper.ts +++ b/lib/services/mimetype-content-wrapper.ts @@ -1,12 +1,21 @@ import { ContentObject } from '../interfaces/open-api-spec.interface'; +function removeUndefinedKeys(obj: { [x: string]: any }) { + Object.entries(obj).forEach(([key, value]) => { + if (value === undefined) { + delete obj[key]; + } + }); + return obj; +} + export class MimetypeContentWrapper { wrap( mimetype: string[], obj: Record ): Record<'content', ContentObject> { const content = mimetype.reduce( - (acc, item) => ({ ...acc, [item]: obj }), + (acc, item) => ({ ...acc, [item]: removeUndefinedKeys(obj) }), {} ); return { content }; diff --git a/lib/services/response-object-mapper.ts b/lib/services/response-object-mapper.ts index 48889da02..82d0dcc83 100644 --- a/lib/services/response-object-mapper.ts +++ b/lib/services/response-object-mapper.ts @@ -1,5 +1,5 @@ import { omit } from 'lodash'; -import { ApiResponseSchemaHost } from '../decorators'; +import { ApiResponseMetadata, ApiResponseSchemaHost } from '../decorators'; import { getSchemaPath } from '../utils'; import { MimetypeContentWrapper } from './mimetype-content-wrapper'; @@ -19,7 +19,8 @@ export class ResponseObjectMapper { items: { $ref: getSchemaPath(name) } - } + }, + example: response.example }) }; } @@ -30,20 +31,25 @@ export class ResponseObjectMapper { ...this.mimetypeContentWrapper.wrap(produces, { schema: { $ref: getSchemaPath(name) - } + }, + example: response.example }) }; } - wrapSchemaWithContent(response: ApiResponseSchemaHost, produces: string[]) { - if (!response.schema) { + wrapSchemaWithContent( + response: ApiResponseSchemaHost & ApiResponseMetadata, + produces: string[] + ) { + if (!response.schema && !response.example) { return response; } const content = this.mimetypeContentWrapper.wrap(produces, { - schema: response.schema + schema: response.schema, + example: response.example }); return { - ...omit(response, 'schema'), + ...omit(response, ['schema', 'example']), ...content }; } diff --git a/test/explorer/swagger-explorer.spec.ts b/test/explorer/swagger-explorer.spec.ts index 2870f7923..fc1c46e01 100644 --- a/test/explorer/swagger-explorer.spec.ts +++ b/test/explorer/swagger-explorer.spec.ts @@ -97,7 +97,11 @@ describe('SwaggerExplorer', () => { @ApiOperation({ summary: 'Create foo' }) @ApiCreatedResponse({ type: Foo, - description: 'Newly created Foo object' + description: 'Newly created Foo object', + example: { + id: 'foo', + name: 'Foo' + } }) create( @Body() createFoo: CreateFoo, @@ -138,7 +142,11 @@ describe('SwaggerExplorer', () => { @Post('foos') @ApiCreatedResponse({ type: Foo, - description: 'Newly created Foo object' + description: 'Newly created Foo object', + example: { + id: 'foo', + name: 'Foo' + } }) create( @Body() createFoo: CreateFoo, @@ -158,7 +166,11 @@ describe('SwaggerExplorer', () => { static [METADATA_FACTORY_NAME]() { return { create: { - summary: 'Create foo' + summary: 'Create foo', + example: { + id: 'foo', + name: 'Foo' + } }, find: { summary: 'List all Foos', @@ -301,7 +313,8 @@ describe('SwaggerExplorer', () => { ).toEqual({ schema: { $ref: '#/components/schemas/Foo' - } + }, + example: { id: 'foo', name: 'Foo' } }); // GET