diff --git a/lib/plugin/visitors/controller-class.visitor.ts b/lib/plugin/visitors/controller-class.visitor.ts index f766e9f3d..b5f07ab53 100644 --- a/lib/plugin/visitors/controller-class.visitor.ts +++ b/lib/plugin/visitors/controller-class.visitor.ts @@ -87,9 +87,10 @@ export class ControllerClassVisitor extends AbstractFileVisitor { : decorators; // Support both >= v4.8 and v4.7 and lower - const modifiers = isInUpdatedAstContext - ? (ts as any).getModifiers(compilerNode) - : compilerNode.modifiers; + const modifiers = + (isInUpdatedAstContext + ? (ts as any).getModifiers(compilerNode) + : compilerNode.modifiers) ?? []; const updatedDecorators = [ ...apiOperationDecoratorsArray, diff --git a/test/plugin/controller-class-visitor.spec.ts b/test/plugin/controller-class-visitor.spec.ts index 6772b7c6c..0e372d847 100644 --- a/test/plugin/controller-class-visitor.spec.ts +++ b/test/plugin/controller-class-visitor.spec.ts @@ -8,6 +8,10 @@ import { appControllerWithTabsText, appControllerWithTabsTextTranspiled } from './fixtures/app.controller-tabs'; +import { + appControllerWithoutModifiersText, + appControllerWithoutModifiersTextTranspiled +} from './fixtures/app.controller-without-modifiers'; describe('Controller methods', () => { it('should add response based on the return value (spaces)', () => { @@ -59,4 +63,31 @@ describe('Controller methods', () => { }); expect(result.outputText).toEqual(appControllerWithTabsTextTranspiled); }); + + it('should add response based on the return value (without modifiers)', () => { + const options: ts.CompilerOptions = { + module: ts.ModuleKind.CommonJS, + target: ts.ScriptTarget.ESNext, + newLine: ts.NewLineKind.LineFeed, + noEmitHelpers: true + }; + const filename = 'app.controller.ts'; + const fakeProgram = ts.createProgram([filename], options); + + const result = ts.transpileModule(appControllerWithoutModifiersText, { + compilerOptions: options, + fileName: filename, + transformers: { + before: [ + before( + { controllerKeyOfComment: 'summary', introspectComments: true }, + fakeProgram + ) + ] + } + }); + expect(result.outputText).toEqual( + appControllerWithoutModifiersTextTranspiled + ); + }); }); diff --git a/test/plugin/fixtures/app.controller-without-modifiers.ts b/test/plugin/fixtures/app.controller-without-modifiers.ts new file mode 100644 index 000000000..d4c5dd249 --- /dev/null +++ b/test/plugin/fixtures/app.controller-without-modifiers.ts @@ -0,0 +1,136 @@ +export const appControllerWithoutModifiersText = `import { Controller, Post, HttpStatus } from '@nestjs/common'; +import { ApiOperation } from '@nestjs/swagger'; + +class Cat {} + +@Controller('cats') +export class AppController { + onApplicationBootstrap() {} + + /** + * create a Cat + * + * @returns {Promise} + * @memberof AppController + */ + @Post() + create(): Promise {} + + /** + * create a test Cat + * + * @deprecated Use create instead + * @returns {Promise} + * @memberof AppController + */ + @Post() + testCreate(): Promise {} + + /** + * create a test Cat, not actually deprecated + * + * @deprecated + * @returns {Promise} + * @memberof AppController + */ + @ApiOperation({ deprecated: false }) + @Post() + testCreate2(): Promise {} + + /** + * find a Cat + */ + @ApiOperation({}) + @Get() + findOne(): Promise {} + + /** + * find all Cats im comment + * + * @returns {Promise} + * @memberof AppController + */ + @ApiOperation({ + description: 'find all Cats', + }) + @Get() + @HttpCode(HttpStatus.NO_CONTENT) + findAll(): Promise {} +}`; + +export const appControllerWithoutModifiersTextTranspiled = `\"use strict\"; +Object.defineProperty(exports, \"__esModule\", { value: true }); +exports.AppController = void 0; +const openapi = require(\"@nestjs/swagger\"); +const common_1 = require(\"@nestjs/common\"); +const swagger_1 = require("@nestjs/swagger"); +class Cat { +} +let AppController = class AppController { + onApplicationBootstrap() { } + /** + * create a Cat + * + * @returns {Promise} + * @memberof AppController + */ + create() { } + /** + * create a test Cat + * + * @deprecated Use create instead + * @returns {Promise} + * @memberof AppController + */ + testCreate() { } + /** + * create a test Cat, not actually deprecated + * + * @deprecated + * @returns {Promise} + * @memberof AppController + */ + testCreate2() { } + /** + * find a Cat + */ + findOne() { } + /** + * find all Cats im comment + * + * @returns {Promise} + * @memberof AppController + */ + findAll() { } +}; +__decorate([ + openapi.ApiOperation({ summary: "create a Cat" }), + (0, common_1.Post)(), + openapi.ApiResponse({ status: 201, type: Cat }) +], AppController.prototype, \"create\", null); +__decorate([ + openapi.ApiOperation({ summary: "create a test Cat", deprecated: true }), + (0, common_1.Post)(), + openapi.ApiResponse({ status: 201, type: Cat }) +], AppController.prototype, \"testCreate\", null); +__decorate([ + (0, swagger_1.ApiOperation)({ summary: "create a test Cat, not actually deprecated", deprecated: false }), + (0, common_1.Post)(), + openapi.ApiResponse({ status: 201, type: Cat }) +], AppController.prototype, \"testCreate2\", null); +__decorate([ + (0, swagger_1.ApiOperation)({ summary: "find a Cat" }), + Get(), + openapi.ApiResponse({ status: 200, type: Cat }) +], AppController.prototype, \"findOne\", null); +__decorate([ + (0, swagger_1.ApiOperation)({ summary: "find all Cats im comment", description: 'find all Cats' }), + Get(), + HttpCode(common_1.HttpStatus.NO_CONTENT), + openapi.ApiResponse({ status: common_1.HttpStatus.NO_CONTENT, type: [Cat] }) +], AppController.prototype, \"findAll\", null); +AppController = __decorate([ + (0, common_1.Controller)('cats') +], AppController); +exports.AppController = AppController; +`;