typeorm icon indicating copy to clipboard operation
typeorm copied to clipboard

0.3.20 regression with NestJS, TypeORM and Swagger

Open OSA413 opened this issue 5 months ago • 5 comments

Issue description

Upgrading to 0.3.20 broke NestJS + Swagger integration, downgrading to 0.3.19 fixes the issue

Expected Behavior

not regression

Actual Behavior

regression

Steps to reproduce

https://github.com/OSA413/nestjs-bug-swagger-api-property

My Environment

Dependency Version
Operating System Windows 10
Node.js version 18.17.1
Typescript version not applicable i think
TypeORM version 0.3.20

Additional Context

Reposted from NestJS' Discord So, I recently updated packages and Swagger started to throw errors related to @ApiProperty (Optional) and circular dependency though a week ago it was just fine. I've managed to make an MRE from the whole project, here it is: https://github.com/OSA413/nestjs-bug-swagger-api-property

The DTO looks like this:

export class Testttttttttt {
    @ApiProperty()
    public id: string;
}

It's very interesting, because 1) it doesn't specify any type in the annotation, 2) it's a scalar type

Some other investigations:

  1. The bug goes away if I remove TypeORM import from the AppModule
  2. The bug may disappear if I leave only one controller by combining two of them
  3. The bug may disappear if I move DTO into the same file as controller

For easier reproduction of the example I provided you'll need a Docker (because you need to connect to DB)

Package versions are listed in the repository, package.lock is provided

Here's the log

[14:50:50] Starting compilation in watch mode...

[14:50:52] Found 0 errors. Watching for file changes.

[Nest] 12856  - 31.01.2024, 14:50:53     LOG [NestFactory] Starting Nest application...
[Nest] 12856  - 31.01.2024, 14:50:53     LOG [InstanceLoader] TypeOrmModule dependencies initialized +46ms
[Nest] 12856  - 31.01.2024, 14:50:53     LOG [InstanceLoader] AppModule dependencies initialized +0ms
[Nest] 12856  - 31.01.2024, 14:50:53     LOG [InstanceLoader] TypeOrmCoreModule dependencies initialized +22ms

C:\Users\Oleg.Sokolov\Documents\GitHub\nestjs-bug-swagger-api-property\node_modules\@nestjs\swagger\dist\services\schema-object-factory.js:187
            throw new Error(`A circular dependency has been detected (property key: "${key}"). Please, make sure that each side of a bidirectional relationships are using lazy resolvers ("type: () => ClassType").`);
                  ^
Error: A circular dependency has been detected (property key: "id"). Please, make sure that each side of a bidirectional relationships are using lazy resolvers ("type: () => ClassType").
    at SchemaObjectFactory.createNotBuiltInTypeReference (C:\Users\Oleg.Sokolov\Documents\GitHub\nestjs-bug-swagger-api-property\node_modules\@nestjs\swagger\dist\services\schema-object-factory.js:187:19)
    at SchemaObjectFactory.createSchemaMetadata (C:\Users\Oleg.Sokolov\Documents\GitHub\nestjs-bug-swagger-api-property\node_modules\@nestjs\swagger\dist\services\schema-object-factory.js:297:25)
    at SchemaObjectFactory.mergePropertyWithMetadata (C:\Users\Oleg.Sokolov\Documents\GitHub\nestjs-bug-swagger-api-property\node_modules\@nestjs\swagger\dist\services\schema-object-factory.js:131:21)
    at C:\Users\Oleg.Sokolov\Documents\GitHub\nestjs-bug-swagger-api-property\node_modules\@nestjs\swagger\dist\services\schema-object-factory.js:82:35
    at Array.map (<anonymous>)
    at SchemaObjectFactory.extractPropertiesFromType (C:\Users\Oleg.Sokolov\Documents\GitHub\nestjs-bug-swagger-api-property\node_modules\@nestjs\swagger\dist\services\schema-object-factory.js:81:52)
    at SchemaObjectFactory.exploreModelSchema (C:\Users\Oleg.Sokolov\Documents\GitHub\nestjs-bug-swagger-api-property\node_modules\@nestjs\swagger\dist\services\schema-object-factory.js:103:41)
    at C:\Users\Oleg.Sokolov\Documents\GitHub\nestjs-bug-swagger-api-property\node_modules\@nestjs\swagger\dist\services\schema-object-factory.js:36:36
    at Array.map (<anonymous>)
    at SchemaObjectFactory.createFromModel (C:\Users\Oleg.Sokolov\Documents\GitHub\nestjs-bug-swagger-api-property\node_modules\@nestjs\swagger\dist\services\schema-object-factory.js:20:45)

After investigation I figured out that downgrading typeorm from 0.3.20 to 0.3.19 fixes the issue.

Relevant Database Driver(s)

  • [ ] aurora-mysql
  • [ ] aurora-postgres
  • [ ] better-sqlite3
  • [ ] cockroachdb
  • [ ] cordova
  • [ ] expo
  • [ ] mongodb
  • [ ] mysql
  • [ ] nativescript
  • [ ] oracle
  • [ ] postgres
  • [ ] react-native
  • [ ] sap
  • [ ] spanner
  • [ ] sqlite
  • [ ] sqlite-abstract
  • [ ] sqljs
  • [ ] sqlserver

Are you willing to resolve this issue by submitting a Pull Request?

No, I don’t have the time and I’m okay to wait for the community / maintainers to resolve this issue.

OSA413 avatar Jan 31 '24 11:01 OSA413

that's due to reflect-metadata being upgraded to 0.2 while others packages from nestjs are using 0.1

A quick solution is to pin the version of typeorm to v0.3.19

image

micalevisk avatar Feb 01 '24 11:02 micalevisk

So, this bug is not related to typeorm, closing this.

Dev response: https://github.com/nestjs/nest/issues/13107#issuecomment-1921234278

Explanation and temporal fix: https://github.com/nestjs/nest/issues/13107#issuecomment-1921364281

OSA413 avatar Feb 04 '24 14:02 OSA413

@OSA413 just a quick note that after walking through changes introduced in the latest version of reflect-metadata I believe typeorm should consider setting reflect-metadata as a peer dependency (otherwise similar issues might keep occurring in the future)

For example, this issue could be solved without affecting any projects using TypeORM in combination with any other libs that rely on reflect-metadata by setting reflect-metadata as a peer dependency with "^0.1.14 || ^0.2.0" constraint and removing it from deps array

kamilmysliwiec avatar Feb 07 '24 09:02 kamilmysliwiec

I believe typeorm should consider setting reflect-metadata as a peer dependency (otherwise similar issues might keep occurring in the future)

In this case I'll keep this issue open for the maintainers to decide if they want this change or not

OSA413 avatar Feb 07 '24 10:02 OSA413

I can confirm that this is fixed after version update (and clean package install)

"@nestjs/common": "^10.3.2",
"@nestjs/core": "^10.3.2",

Source: https://github.com/nestjs/swagger/issues/2821#issuecomment-1931766882

OSA413 avatar Feb 08 '24 15:02 OSA413

is there any chance this is going to be reconsidered (https://github.com/typeorm/typeorm/issues/10671#issuecomment-1931628948)? We're getting more and more complaints regarding this issue (and the solution is far from obvious)

kamilmysliwiec avatar Mar 15 '24 07:03 kamilmysliwiec

@pleerock @AlexMesser

OSA413 avatar Mar 15 '24 07:03 OSA413

If TypeORM remove reflect-metadata as a dependency and set a peer-dependency instead, it means we will have to remove "reflect-metadata" from the code imports. It will lead our users to manually install and import reflect-metadata. Those users who didn't do manual imports of reflect-metadata in their projects currently will have issues. This can be a serious breaking change for such users.

If nestjs did the upgrade to the latest version of reflect-metadata, then what can be issue?

pleerock avatar Mar 15 '24 09:03 pleerock

it means we will have to remove "reflect-metadata" from the code imports.

You could still have reflect-metadata imports - peer dependencies are, by default, marked as required.

It will lead our users to manually install and import reflect-metadata.

Both npm and yarn automatically install peer dependencies now

Technically the only thing that would change is that now package managers, be it npm or yarn, would know that reflect-metadata should be automatically "hoisted" as it's supposed to be shared between packages that also rely on reflect-metadata. Currently, it's installed as an internal dependency and hoisted only in case installed versions match (deduped)

If nestjs did the upgrade to the latest version of reflect-metadata, then what can be issue?

Unfortunately, some folks still have old reflect-metadata leftovers in their lock files even after upgrading which leads to duplicated copies of reflect-metadata in the codebase (and the only solution is to remove it manually or just remove node_modules entirely and the lock file itself and reinstall packages).

Not to mention anyone who's had "^0.3.19" in their package.json and didn't change anything but reinstalled dependencies would sadly see their projects broken (as 0.3.20 matches that criterion)

Some refs:

  • https://github.com/nestjs/nest/issues/13297
  • https://github.com/nestjs/nest/issues/13322
  • https://github.com/nestjs/nest/issues/13293
  • https://github.com/nestjs/swagger/issues/2821
  • https://github.com/nestjs/swagger/issues/2811

kamilmysliwiec avatar Mar 15 '24 09:03 kamilmysliwiec

Both npm and yarn automatically install peer dependencies now

the way peer deps work changed so many times that I'm not really sure how they currently work.

Technically the only thing that would change is that now package managers, be it npm or yarn, would know that reflect-metadata should be automatically "hoisted" as it's supposed to be shared between packages that also rely on reflect-metadata. Currently, it's installed as an internal dependency and hoisted only in case installed versions match (deduped)

If nothing will be broken and it's that much of the issue right now, I can apply suggested changes.

I'll wait for somebody to create a PR.

pleerock avatar Mar 15 '24 10:03 pleerock

Thank you @pleerock!

kamilmysliwiec avatar Mar 15 '24 10:03 kamilmysliwiec

I'm not clear on the issue the latest update to reflect-metadata caused, and I'd like to address it if possible. In the recent changes to reflect-metadata I was trying to make it so that the package is more reliable when different versions are installed by having them share a central metadata store. If that is breaking, I'd love to get more details as to why and a suitable repro so that I can try to address it.

rbuckton avatar Mar 15 '24 13:03 rbuckton

Here's a pretty basic reproduction repository with instructions in the README file https://github.com/phuffer/controller-broken-example/

kamilmysliwiec avatar Mar 15 '24 13:03 kamilmysliwiec

I've done what kamilmysliwiec suggested in this PR https://github.com/typeorm/typeorm/pull/10779

OSA413 avatar Mar 17 '24 10:03 OSA413

Any progress? A roadmap? What's current progress with the issue? Maybe it would be helpful to release a beta version of packages for testing.

OSA413 avatar Mar 28 '24 15:03 OSA413

@OSA413 I have merged your PR, but release will be later next month. You can use beta release (made automatically after PR is merged) for now.

pleerock avatar Mar 28 '24 15:03 pleerock

Ideally, we would love to see this fixed upstream in the reflect-metadata package. @rbuckton did you have a chance to investigate what caused this regression?

kamilmysliwiec avatar Mar 28 '24 15:03 kamilmysliwiec

Installing lates dev version of the package fixed the issue in the repo I provided

OSA413 avatar Mar 28 '24 16:03 OSA413

Any progress? A roadmap? What's current progress with the issue? Maybe it would be helpful to release a beta version of packages for testing.

I'm still looking into this, but don't yet know the cause. It does seem like NestJS is using reflect-metadata completely incorrectly, but I don't believe that's the underlying cause.

rbuckton avatar Mar 29 '24 00:03 rbuckton

I think I have discovered the cause. I should have a fix up for reflect-metadata shortly.

rbuckton avatar Mar 29 '24 00:03 rbuckton

This should be fixed in [email protected] and it now should be able to load side-by-side with [email protected]

rbuckton avatar Mar 29 '24 01:03 rbuckton

Thank you @rbuckton. I just did a quick test and it seems to work as expected now (needs confirmation though).

In this case, upgrading the reflect-metadata dependency to the latest version in typeorm may be sufficient to fix this issue (without even moving it from deps to peer deps) @pleerock

kamilmysliwiec avatar Mar 29 '24 07:03 kamilmysliwiec