Type-graphql: HMR update generate multiple type infos

Created on 31 Aug 2018  路  5Comments  路  Source: MichalLytek/type-graphql

Describe the bug
Metadata will be duplicated on HMR, probably due to require cache invalidation so that decorators are re-applied, damaging the global metadata storage.

To Reproduce
Simply change some resolver code on the HMR attached Node app.

Expected behavior
Metadata cleared and rebuilt without duplicated entries.

Logs
Example log:

[HMR] Cannot apply update.
[HMR] Error: Aborted because ./packages/server/user/user.entity.ts is not accepted
Update propagation: ./packages/server/user/user.entity.ts -> ./packages/server/database/authChecker.ts -> ./packages/server/database/module.ts -> ./packages/server/main.ts
    at hotApply (E:\typescript-starter\dist\webpack:\webpack\bootstrap:434:1)
    at E:\typescript-starter\dist\webpack:\webpack\bootstrap:272:1
[HMR] You need to restart the application!
Error: Schema must contain unique named types but contains multiple types named "User".
    at invariant (E:\typescript-starter\node_modules\graphql\jsutils\invariant.js:19:11)
    at typeMapReducer (E:\typescript-starter\node_modules\graphql\type\schema.js:216:58)
    at Array.reduce (<anonymous>)
    at new GraphQLSchema (E:\typescript-starter\node_modules\graphql\type\schema.js:122:28)
    at Function.generateFromMetadataSync (E:\typescript-starter\node_modules\type-graphql\schema\schema-generator.js:28:24)
    at Object.buildSchemaSync (E:\typescript-starter\node_modules\type-graphql\utils\buildSchema.js:12:47)
    at GraphQlBridge.buildSchema (E:\typescript-starter\node_modules\nestjs-type-graphql\dist\graphql-bridge.service.js:26:31)
    at DatabaseModule.configureGraphQL (E:\typescript-starter\dist\webpack:\packages\server\database\module.ts:32:1)
    at bootstrap (E:\typescript-starter\dist\webpack:\packages\server\main.ts:10:33)

Enviorment (please complete the following information):

  • OS: Microsoft Windows [Version 10.0.17134.228]
  • Node: v10.9.0
  • Package version: latest
  • TypeScript: 3.0.3

Additional context
Last known TypeGraphQL related code is this:
https://github.com/19majkel94/type-graphql/blob/7c534eac95d24b53cd40929b1101e2a35b893e37/src/schema/schema-generator.ts#L80-L95

There's also the same problem with TypeORM馃槬It seems like global metadata storages are not good friends with HMR.

Out of scope

All 5 comments

Unfortunately, I'm afraid I can't do anything about it. That's how decorators work, they are evaluated on module loading (require), so all subsequent imports in runtime results in such errors.

Global metadata storage is the only way to support multiple packages (monorepo) project that shares classes between frontend app and the backend.

I would love too have support for HMR and replacing GraphQL schema on live, without relaunching HTTP server but it's too complex and out of scope for now 馃槥

馃槕Out of scope.

I have an idea, what if we could detect duplicated fields on collectXXX methods in metadata-storage?
https://github.com/19majkel94/type-graphql/blob/7c534eac95d24b53cd40929b1101e2a35b893e37/src/metadata/metadata-storage.ts#L47-L97

Although dangerous in nature, I think this is a way to go.

Detect and do what? Omit? Silent error when someone have duplicated name in his schema classes. Replace? Again silent error. Raise error? Again problems with HMR.

It's not so easy to solve that and there are 8361 more important things to do right now. Sorry 馃槬

Feel free to fork the repo and figure out a way that works for you 馃槈

@stevefan1999
Wait a minute... you are doing module.hot.accept and then running buildSchema inside callback? Maybe you should try to call getMetadataStorage().clear() to clear the storage an allow for registering types and fields again? Or HMR evaluate again only changed files?

@19majkel94 No I just leave the metadata alone, so I didn't clear them anyhow during module.hot.dispose, but it seems like HMR preserves global state...And I also did try the 'clear the metadata storage' combination but it does no help, so I have to resort to a live reload solution that uses nodemon under the hood. Anyway many thanks for trying to address my problem.

Was this page helpful?
0 / 5 - 0 ratings