Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot use GraphQLSchema from another module or realm #144

Closed
lal12 opened this issue Sep 3, 2018 · 29 comments
Closed

Cannot use GraphQLSchema from another module or realm #144

lal12 opened this issue Sep 3, 2018 · 29 comments
Labels
Community 👨‍👧 Something initiated by a community Discussion 💬 Brainstorm about the idea Question ❔ Not future request, proposal or bug issue Solved ✔️ The issue has been solved

Comments

@lal12
Copy link

lal12 commented Sep 3, 2018

Describe the bug
I installed express-graphql and typed-graphql, then I defined my entities and built the schema, when I pass the Schema to express-graphql and added it to my express app. As soon as I open grahpiql in my browser and run a query I get the error:


{
  "errors": [
    {
      "message": "Cannot use GraphQLSchema \"[object Object]\" from another module or realm.\n\nEnsure that there is only one instance of \"graphql\" in the node_modules\ndirectory. If different versions of \"graphql\" are the dependencies of other\nrelied on modules, use \"resolutions\" to ensure only one version is installed.\n\nhttps://yarnpkg.com/en/docs/selective-version-resolutions\n\nDuplicate \"graphql\" modules cannot be used at the same time since different\nversions may have different capabilities and behavior. The data from one\nversion used in the function from another could produce confusing and\nspurious results."
    }
  ]
}

Enviorment (please complete the following information):

  • OS: Ubuntu 18.04
  • Node 10.9.0
  • Package version 0.13.1
  • TypeScript version 3.0.1
@lal12
Copy link
Author

lal12 commented Sep 3, 2018

I got it to work, by explicitly specifying the same version in my package.json as needed by type-graphql. I also had to delete my node_modules and package-lock.json to make npm dedupe the graphql dependency.

But I guess it would be better if type-graphql would specify graphql as peerDependency, to prevent such problems.

@MichalLytek MichalLytek added the Question ❔ Not future request, proposal or bug issue label Sep 4, 2018
@MichalLytek
Copy link
Owner

But I guess it would be better if type-graphql would specify graphql as peerDependency, to prevent such problems.

It's not so simple. The main problem is that TypeGraphQL is tightly coupled to the version of graphql-js, so do the produced schema is. So I can't just put a wildcard ^0.12 || ^0.13 || >=14.0.
If I make it a peerDependency, you still might have incompatibilities between TypeGraphQL and ecosystem, like 0.13 vs 14.0. Also it's error prone as you need to remember to install it too, even if you're not using graphql-js directly anywhere in your code.

@capaj
Copy link
Contributor

capaj commented Sep 9, 2018

So I can't just put a wildcard ^0.12 || ^0.13 || >=14.0.

So don't. Just specify the versions you know are compatible at the time of writing. Everyone does it like this. If a new version comes and it is compatible, you can add it later.

Also it's error prone as you need to remember to install it too, even if you're not using graphql-js directly anywhere in your code.

I think you need to use it always-even apollo-server-core expects it at as peer dep.

Error: Cannot find module 'graphql'
    at Function.Module._resolveFilename (module.js:547:15)
    at Function.Module._load (module.js:474:25)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/home/capaj/git_projects/graphql-repos/ts-gql-objection-blog/node_modules/apollo-server-core/dist/runQuery.js:3:19)

running an apollo server without graphql installed.
To make it easier just put it in the readme.md. Everyone does it like that. Will open a PR.

@MichalLytek
Copy link
Owner

It's not that simple. I even asked Lee Byron for that:
https://medium.com/@leeb/presumably-if-youre-completely-hiding-away-the-graphql-js-api-then-your-users-will-not-be-using-97e1a683bc93

And that's what TypeGraphQL does - it's hidding graphql-js API with classes and decorators.

@capaj Could you tell me what will happen when I bump the type-graphql version with bumping peerDependency version? Will it automatically update it too or users will have strange errors due to incorrect version of graphql-js?

@capaj
Copy link
Contributor

capaj commented Sep 10, 2018

@19majkel94 I think npm exits with a warning telling them they have a mismatched peerDependency. Like for @marciobueno1 : apollographql/apollo-server#291 (comment)

@capaj
Copy link
Contributor

capaj commented Sep 10, 2018

You are hiding it away, but apollo doesn't. Apollo-server uses graphql as peer dependency. Which GraphQL server are we supposed to use? Even if there was one with graphql as a dependency it would still cause these issues with another realm.
I think it's simple. There's really no drawback to having it as peerDependency.

@MichalLytek
Copy link
Owner

@capaj It's not an error, only a warning, so it's easy to miss when you have other libs in project, like:

PS D:\Gorrion\Projekty\nurture agency\pagebox-react> npm i
npm WARN ajv-keywords@3.2.0 requires a peer of ajv@^6.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN react-addons-test-utils@15.6.2 requires a peer of react-dom@^15.4.2 but none is installed. You must install peer dependencies yourself.
npm WARN react-app-rewired@1.5.2 requires a peer of react-scripts@^1.0.14 but none is installed. You must install peer dependencies yourself.

audited 32315 packages in 38.785s
found 0 vulnerabilities

PS D:\Gorrion\Projekty\nurture agency\pagebox-react>

So assuming graphql should be a peerDependency, @types/graphql should be too? What about @types/node?

There's really no drawback to having it as peerDependency.

No, there are many:

  • it's more complicated to install (not only type-graphql but also graphql and @types-graphql
  • there's no way to force the update ofgraphql-js to specific version like now I can
  • it still doesn't solve the problem of missmatch version when other lib from the graphql ecosystem use different major version

If all ecosystem libraries have all the same semver setup, the only thing you have to do is call npm dedupe to flatten the deps to a single graphql-js instance in node_modules. I think it's simpler than forcing ALL users to install also graphql and @types/graphql and remember to keep them in sync on updates.

@capaj
Copy link
Contributor

capaj commented Sep 10, 2018

If all ecosystem libraries have all the same semver setup

that's a very big if. Mostly package authors specify their deps quite specific, so it might be impossible to get version of packages which require the right versions of graphql. I agree it's the same thing with peerDeps, but in my experience people specify peerDeps much more broadly than deps.

You're definately right about npm-it only warns which is a shame.

@lal12
Copy link
Author

lal12 commented Sep 10, 2018

I agree it's the same thing with peerDeps, but in my experience people specify peerDeps much more broadly than deps.

I noticed the same thing and it is plausible too. If I have a dependency it is automatically installed, so usually I would specify a single (mostly the newest) version, but if I have a peer dependency I specify all versions it would work with.

@MichalLytek
Copy link
Owner

Peer dependencies makes sense for things like plugins, e.g. https://github.com/19majkel94/class-transformer-validator. class-validator could be a peer dependency of TypeGraphQL too, because it only call validate() with validation option, so it doesn't change too much.

But with TypeGraphQL is really tightly coupled to graphql-js - I rely on so many things, API and behaviors. So I need to specify it's version very narrow, for example when new minor version comes out and I need to use the introduced feature.

Many packages from ecosystem, like graphql-query-complexity or even apollo-server only use the schema and call the execute function, so they can have this peer dependency set much more broadly than deps. So upgrading graphql-js version as peer dependency for graphql is a challange. I think that better is to document npm dedupe in docs rather than forcing everybody to install graphql and take care about updates.

@MichalLytek MichalLytek added Community 👨‍👧 Something initiated by a community Discussion 💬 Brainstorm about the idea labels Sep 11, 2018
@floross
Copy link

floross commented Sep 14, 2018

Apollo-server uses graphql as peer dependency.

The simple fact that apollo-server use graphql as a peer dependency make impossible to use type-graphql to configure it (with the option param schema: GraphQLSchema) because GraphQLSchema returned by TypeGraphQL.buildSchema is out of date compare to GraphQLSchemaused with apollo-server.

So you are building a GraphQLSchema that will never be usable by other module using latest graphql version. Let the devs configure what version of graphql they want to use is for me the better option.

Edit: type-graphql doesn't broke with graphql-js version 14.x.x

@MichalLytek
Copy link
Owner

The simple fact that apollo-server use graphql as a peer dependency make impossible to use type-graphql to configure it (with the option param schema: GraphQLSchema) because GraphQLSchema returned by TypeGraphQL.buildSchema is out of date compare to GraphQLSchemaused with apollo-server.

The simple fact means that npm during install of apollo-server will not install new graphql module but just use the one bundled with type-graphql 😉

To demonstrate how npm is deduplicating packages - tak a look at graphql-yoga that has graphql defined as a dependency, which is much stronger than peer dependencies:
https://github.com/prisma/graphql-yoga/blob/1dd9c12c166067eeeac8f28de0525dfbb6dc010f/package.json#L48
So graphql-yoga has own graphql package defined, so has type-graphql - but suddenly they work together without any problem as npm reuse the graphql module when they have common semver set up.

So basically this comes down to this dilemma:

  • run npm dedupe when you have GraphQLSchema conflict (only by some people)
  • run npm i graphql on install and npm upgrade graphql or npm i graphql@latest when type-graphql bumps the package version requirement (by everybody)

I think that in this situation it's better to cure with dedupe than preventing with peer dependency 😉

@floross
Copy link

floross commented Sep 14, 2018

So this package is meant to work with graphql yoga out of the box only ?

Your package work with graphql@14.x.x the major version, you should at least bump the version in your dependencies to ^14.x.x || ^0.13.x

Edit: npm dedupe don't fix the problem by the way

@MichalLytek
Copy link
Owner

See #140 - it's a major release with breaking changes, so it does't work with with 14.x.x.

And no, it works with other packages too. The type error that you receive:

[ts]
Argument of type '{ schema: GraphQLSchema; }' is not assignable to parameter of type 'Config & { cors?: boolean | CorsOptions | undefined; }'.
  Type '{ schema: GraphQLSchema; }' is not assignable to type 'Config'.
    Types of property 'schema' are incompatible.
      Type 'import("e:/#Programowanie/#GitHub/apollo-type-graphql/node_modules/type-graphql/node_modules/@types/graphql/type/schema").GraphQLSchema' is not assignable to type 'import("e:/#Programowanie/#GitHub/apollo-type-graphql/node_modules/@types/graphql/type/schema").GraphQLSchema'.
        Types of property 'astNode' are incompatible.
          Type 'Maybe<SchemaDefinitionNode>' is not assignable to type 'SchemaDefinitionNode | undefined'.
            Type 'null' is not assignable to type 'SchemaDefinitionNode | undefined'.

Comes from apollo-link that is a part of apollo-server:

"apollo-link": {
  "version": "1.2.2",
  "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.2.tgz",
  "integrity": "sha512-Uk/BC09dm61DZRDSu52nGq0nFhq7mcBPTjy5EEH1eunJndtCaNXQhQz/BjkI2NdrfGI+B+i5he6YSoRBhYizdw==",
  "requires": {
    "@types/graphql": "0.12.6",
    "apollo-utilities": "^1.0.0",
    "zen-observable-ts": "^0.8.9"
  }
},

As you can see, 0.12.6 is not compatible with ^0.13.4 defined by type-graphql. So as apollo-server version took precedence over type-graphql one, all you need is npm i @types/graphql@0.13. Here is a gist that you can clone, install and run 😉
https://gist.github.com/19majkel94/8f502b2c5de418695d33c675c9c64726

Peer dependency on type-graphql side won't fix the error with two incompatible version of the package, they would still use their own version to define types. Just like the newest apollo-server would be designed for v14, and type-graphql is for 0.13 - they won't work, you have to downgrade apollo-server to earlier version until type-graphql 0.15 comes live 😉

@floross floross mentioned this issue Sep 17, 2018
5 tasks
@MichalLytek
Copy link
Owner

apollo-server 2.1.0 has been released, now everything works out of the box with type-graphql 0.14.0 😉

However there's still an error with graphql-yoga that hasn't been upgraded to v14.
Switching to peerDependency wouldn't help in that case as type-graphql 0.15 would demand v14.0.

As Lee Byron said:

Presumably if you’re completely hiding away the graphql-js API, then your users will not be using graphql-js in any other way so it’s probably safe to continue to use a normal dependency. peerDependencies is useful when the peer package is used directly by many others in an ecosystem of software, which is typically true for GraphQL.js

I will come back later to this discussion, depending on how the ecosystem packages will behave. Maybe a section in FAQ about Cannot use GraphQLSchema and GraphQLSchema is not assignable to type errors will prevent this kind of issues 😉

@caseyduquettesc
Copy link

caseyduquettesc commented Sep 27, 2018

I got it to work by removing node_modules/type-graphql/node_modules/graphql, but this isn't really feasible in a production environment. Helps unblock local development until all maintainers get onboard with GQL 14

package.json

{
  "scripts": {
    "postinstall": "rm -rf node_modules/{type-graphql}/node_modules/{@types/graphql,graphql}"
  }
}

@davidboom95
Copy link

@caseyduquettesc Is a temporal Solution, it works for me.

@davidboom95
Copy link

Temporal messy solution for me:

on package.json

"resolutions":{
    "type-graphql/graphql": "^14.0.2"
  },

yarn install

@MichalLytek
Copy link
Owner

To make it a bit clear for newcomers that are looking for a solution in this issue - there's a little guide in FAQ for this problem:
https://19majkel94.github.io/type-graphql/docs/faq.html#i-got-error-like-cannot-use-graphqlschema-object-object-from-another-module-or-realm-how-to-fix-that

@ramonpm
Copy link

ramonpm commented Jun 21, 2019

Don't know what's happening I have this same problem and only 1 version of graphql resulting from npm ls graphql

It's even weirder if I tell you it works for the first request and starts having Error: Cannot use GraphQLSchema "[object GraphQLSchema]" from another module or realm. from the second request.

@MichalLytek
Copy link
Owner

@ramonpm TypeGraphQL now comes with graphql-js as a peer dependency so it's not a source of problem anymore.

@ramonpm
Copy link

ramonpm commented Jun 21, 2019

@19majkel94 could you please suggest me some way to identify the problem?

@ramonpm
Copy link

ramonpm commented Jun 21, 2019

fixed now. What helped me was update serverless cli npm update -g serverless.

@ozyman42
Copy link

I ran into another circumstance which caused this error due to symlinking. I'm using a (kind of) fork of Lerna to manage a project such that my project ended up being structured like this:

my_project_package_1
└───node_modules
│   └─── type-graphql
│   │   │   ...
│   └─── graphql
│   │   │   ...
│   └───my_project_package_2
│       └─── node_modules
│       │   └─── graphql --> ../../graphql/
│       │   ...
│   ...

even though there is only one actual copy of the graphql library on disk, the module is being loaded by node twice, once when type-graphql requires graphql and another time when my_project_package_2 requires graphql, because I guess node looks at the path when determining whether a module has been loaded before or not. Since the module is loaded twice the instanceOf check in graphql js fails.

My solution here will be to rewrite a portion of how my Lerna fork works. RIP.

@manavm1990
Copy link

To make it a bit clear for newcomers that are looking for a solution in this issue - there's a little guide in FAQ for this problem:
https://19majkel94.github.io/type-graphql/docs/faq.html#i-got-error-like-cannot-use-graphqlschema-object-object-from-another-module-or-realm-how-to-fix-that

404 😞

@MichalLytek
Copy link
Owner

@manavm1990
Copy link

manavm1990 commented Oct 9, 2020

I switched from npm to yarn (deleting 'node_modules' and 'package-lock.json' and 'rebuilding') and then added this to 'package.json':

"resolutions": {
    "graphql": "^15.3.0"
  }

It's all working again! 😌

@aimamisa
Copy link

In my case, realized I was using graphql v15.x.x in my application package.json while graphql-yoga was using graphql v14.x.x. Deleted the v15.x.x and replaced it with v14.x.x works. That created a single graphql v14.x.x to be used.

Hope this helps.

@JaapWeijland
Copy link

I work in a monorepo with 2 layers of package.jsons, one on the root and one on project level. My graphql-codegen was using a plugin from the root level, while the graphql-tag was used from the project level, hence two different realms. I fixed it by installing the codegen plugin on project level as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Community 👨‍👧 Something initiated by a community Discussion 💬 Brainstorm about the idea Question ❔ Not future request, proposal or bug issue Solved ✔️ The issue has been solved
Projects
None yet
Development

Successfully merging a pull request may close this issue.