swc: Problems with decorators when using class validator

Describe the bug

I’m trying to use Nest.js with Class Validator for body validation. I’ve created an E2E test using ts-jest that passes, and I’m using the same test with @swc/jest but it’s returning a 400 as if the fields weren’t being assigned.

Input code

In this link is the repository with the tests that reproduces the error. Run yarn test:e2e for running the tests with ts-jest and test:e2e:swc for @swc/jest.

The problem is at src/app.controller.ts:17.

Another problem, is that the import * as request from 'supertest' is working with ts-jest but not with @swc/jest. The error is TypeError: request is not a function

Config

Check the .swcrc file at the repo.

{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": false,
      "decorators": true
    },
    "transform": {
      "legacyDecorator": true,
      "decoratorMetadata": true
    },
    "target": "es2018"
  },
  "module": {
    "type": "commonjs"
  }
}

Expected behavior

  • I would expect that import * as request from 'supertest'; works with @swc/jest (here).
  • I would expect that Nest.js assigns the attributes to the User class instance (here).

Version The version of @swc/core: 1.2.46

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 10
  • Comments: 19 (7 by maintainers)

Commits related to this issue

Most upvoted comments

Hey, I can confirm that class-transformer is not working well either.

I have following setup

{
  "jsc": {
    "target": "es2017",
    "parser": {
      "syntax": "typescript",
      "decorators": true,
      "dynamicImport": false
    },
    "transform": {
      "legacyDecorator": true,
      "decoratorMetadata": true
    },
    "keepClassNames": true
  },
  "module": {
    "type": "commonjs",
    "noInterop": true
  }
}

But, unfortunately when I do plainToClass on such an entity

export class GetUsersOptionsInput {
  @IsString()
  @IsOptional()
  public query?: string

  @ValidateNested()
  public pagination: PaginationInput
}

export class PaginationInput {
  @IsInt()
  @IsOptional()
  public skip = 0

  @IsInt()
  @IsOptional()
  public limit = 39
}

Passing down { query: '', pagination: { skip:0, limit: 20 } } it fails to convert returning empty object of GetUsersOptionsInput input. E.g. logging this to console console.log(input) -> GetUsersOptionsInput {}

If decorators will start to work as expected SWC will be a way to go. Ah, also unsure what’s wrong but for IntelliJ debugging with node -r @swc/register ./src/index.ts half broke and doesn’t stop in certain files. Mind that in most of the files there are lots of lots decorators, so that’s maybe why.

Thanks, but seems like lots of investigation is still required to reduce the test case and spot the error.

Hello @kdy1, thanks a lot for your comment and great work! The noModuleInterop option worked for me. The thing is, that the main issue, still persist. I think that decorators are still not working.

These are the outputs from the example repository I gave at the top:

Unitary tests:

› yarn test; yarn test:swc
yarn run v1.22.5
$ jest
 PASS  src/dtos/CreateUserDto.spec.ts
  CreateUserDto
    √ accepts a valid user (6 ms)
    √ rejects a user with wrong email (3 ms)
    √ rejects a user without password
    √ rejects a user without password and email (1 ms)

Test Suites: 1 passed, 1 total
Tests:       4 passed, 4 total
Snapshots:   0 total
Time:        0.876 s, estimated 1 s
Ran all test suites.
Done in 1.49s.
yarn run v1.22.5
$ jest --config ./test/jest-swc.json
 FAIL  src/dtos/CreateUserDto.spec.ts
  ● Test suite failed to run

    TypeError: decorator is not a function



      at dtos/CreateUserDto.ts:19:16
          at Array.reduce (<anonymous>)
      at _applyDecoratedDescriptor (dtos/CreateUserDto.ts:18:41)
      at Object.<anonymous> (dtos/CreateUserDto.ts:50:31)
      at Object.<anonymous> (dtos/CreateUserDto.spec.ts:3:22)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.63 s
Ran all test suites.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

And also, the e2e tests are not working with swc:

› yarn test:e2e; yarn test:e2e:swc
yarn run v1.22.5
$ jest --config ./test/jest-e2e.json
 PASS  test/app.e2e-spec.ts
  AppController (e2e)
    √ / (GET) (459 ms)
    √ / (POST) (34 ms)

  console.log
    I have the user!

      at AppService.getHello (../src/app.service.ts:16:15)

  console.log
    User { name: 'Sam 1' }

      at AppService.getHello (../src/app.service.ts:17:15)

  console.log
    createUserDto { email: 'danielramosacosta@hotmail.com', password: 'hello' }

      at AppController.create (../src/app.controller.ts:18:13)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        2.119 s
Ran all test suites.
Done in 2.78s.
yarn run v1.22.5
$ jest --config ./test/jest-e2e-swc.json
 FAIL  test/app.e2e-spec.ts
  AppController (e2e)
    √ / (GET) (360 ms)
    × / (POST) (26 ms)

  ● AppController (e2e) › / (POST)

    expected 201 "Created", got 400 "Bad Request"

      26 |     return request(app.getHttpServer())
      27 |       .post('/')
    > 28 |       .send({
         |            ^
      29 |         email: "danielramosacosta@hotmail.com",
      30 |         password: "hello"
      31 |       })

      at Object.<anonymous> (app.e2e-spec.ts:28:12)
      ----
      at Test.Object.<anonymous>.Test._assertStatus (../node_modules/supertest/lib/test.js:296:12)
      at ../node_modules/supertest/lib/test.js:80:15
      at Test.Object.<anonymous>.Test._assertFunction (../node_modules/supertest/lib/test.js:311:11)
      at Test.Object.<anonymous>.Test.assert (../node_modules/supertest/lib/test.js:201:21)
      at Server.localAssert (../node_modules/supertest/lib/test.js:159:12)

  console.log
    I have the user!

      at AppService1.getHello (../src/app.service.ts:19:25)

  console.log
    User { name: 'Sam 1' }

      at AppService1.getHello (../src/app.service.ts:20:25)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 passed, 2 total
Snapshots:   0 total
Time:        1.686 s, estimated 11 s
Ran all test suites.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

I think there might be a problem with de decorators because when I remove the decorators from the CreateUserDto it works.

I’ve updated all the dependencies of the example repository so you can try it out.

Thanks a lot again!

I tried fixing this, but babel also emits error for

import * as request from 'supertest';

and it’s logically correct.

You need to set jsc.module.noInterop to true lke

{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": false,
      "decorators": true
    },
    "transform": {
      "legacyDecorator": true,
      "decoratorMetadata": true
    },
    "target": "es2018"
  },
  "module": {
    "type": "commonjs",
    "noInterop": true
  }
}

If so, swc works.