0

I recently filed an issue on GitHub but the project doesn’t seem to be very active so I am unsure if it will reach many fellow developers.

Here is the link to the issue: https://github.com/Urigo/graphql-modules/issues/2337.

To give a bit of context, I am currently working on a GraphQL API written in TypeScript and using the graphql-modules library calling instanceof within one of its functions.

Here is the code of the said function (altered to add some logging):

function isScalarResolver(obj) {
    console.log('obj:', obj, '\nisScalarResolver(obj):', obj instanceof GraphQLScalarType, '\n');
    return obj instanceof GraphQLScalarType;
}

After running pnpm run test, here is the output displayed in the terminal:

obj: { now: [Function: now] }
isScalarResolver(obj): false

obj: GraphQLScalarType {
  name: 'DateTime',
  description: 'DateTime scalar type',
  specifiedByURL: undefined,
  serialize: [Function: serialize],
  parseValue: [Function: parseValue],
  parseLiteral: [Function: parseLiteral],
  extensions: [Object: null prototype] {},
  astNode: undefined,
  extensionASTNodes: []
}
isScalarResolver(obj): false

It does appear to me that obj is an instance of GraphQLScalarType so obj instanceof GraphQLScalarType should return true (which is actually the case when running pnpm run dev).

For those who would want to look into the issue, there is a reproduction on StackBlitz: https://stackblitz.com/github/devatina11yb/graphql-modules.

Reproduction steps:

  1. Open the code on StackBlitz.
  2. Run the command open /home/projects/qgnikzovb.github/node_modules/.pnpm/graphql-modules@2.1.2_graphql@16.6.0/node_modules/graphql-modules/index.mjs in the terminal (it will open the file in the editor).
  3. Alter the function isScalarResolver at line 1859 by adding console.log('obj:', obj, '\nisScalarResolver(obj):', obj instanceof GraphQLScalarType, '\n');.
  4. Run the command pnpm run test in the terminal.
  5. You will get the output mentioned above.

You can also confirm that the code does run without errors by running the command pnpm run dev in the terminal.

Here is the output after running pnpm run dev:

obj: { now: [Function: now] }
isScalarResolver(obj): false

obj: GraphQLScalarType {
  name: 'DateTime',
  description: 'DateTime scalar type',
  specifiedByURL: undefined,
  serialize: [Function: serialize],
  parseValue: [Function: parseValue],
  parseLiteral: [Function: parseLiteral],
  extensions: [Object: null prototype] {},
  astNode: undefined,
  extensionASTNodes: []
}
isScalarResolver(obj): true

obj: {
  now: [Function: now] { [Symbol(metadata)]: { moduleId: 'scalars' } }
}
isScalarResolver(obj): false

obj: GraphQLScalarType {
  name: 'DateTime',
  description: 'DateTime scalar type',
  specifiedByURL: undefined,
  serialize: [Function: serialize] { [Symbol(metadata)]: { moduleId: 'scalars' } },
  parseValue: [Function: parseValue] { [Symbol(metadata)]: { moduleId: 'scalars' } },
  parseLiteral: [Function: parseLiteral] {
    [Symbol(metadata)]: { moduleId: 'scalars' }
  },
  extensions: [Object: null prototype] {},
  astNode: undefined,
  extensionASTNodes: []
}
isScalarResolver(obj): true

EDIT 1

After further investigations with the debugger, it appears that GraphQLScalarType classes are loaded from different files: node_modules/.pnpm/graphql@16.6.0/node_modules/graphql/type/definition.js and node_modules/.pnpm/graphql@16.6.0/node_modules/graphql/type/definition.mjs causing instanceof to return false.

This is actually known as the dual package hazard having both CJS and ESM packages loaded at the same time. So graphql-js is the source of this issue and it has already been reported multiple times on GitHub.

  • 1
    Without seeing the source code for GraphQLScalarType, it is a little hard to tell. The prototype chain needs to be set up properly. It might be that the console logger can infer the correct type, but `instanceof` doesn't. Can you post the code for GraphQLScalarType or at least provide a link to the source code? – Greg Burghardt May 23 '23 at 17:47
  • 2
    The question should be self-contained: so it should explain how to reproduce the issue. – trincot May 23 '23 at 17:49
  • @GregBurghardt Not sure how this would help but here is a link to the source code of `GraphQLScalarType` for `graphql` 16.6.0 (version used in the project): https://github.com/graphql/graphql-js/blob/3a51ecade74a0198847e8b1ab1bcdc129485b79b/src/type/definition.ts#L589. Now what is actually weird is that the code does run without errors when running `pnpm run dev`. – devatina11yb May 23 '23 at 18:30
  • @trincot Just added reproduction steps. – devatina11yb May 23 '23 at 18:31
  • 1
    *"line 1859"*: so that is the minimal code to reproduce the problem? Sorry, I'm out. – trincot May 23 '23 at 18:38
  • How do you use a debugger with this slackblitz thing? Otherwise this is ridiculous to debug for anyone that does not have intimate knowledge with those thirty dependencies you have AND this stackblitz thing... Also, more to the subject, the fact that we see `GraphQLScalarType` logged does not mean it's the same object instance, just one with the same name probably. Since you've got ten different layers of abstraction behind your modules which most people have no experience with it's going to be very hard to isolate this. – Sergiu Paraschiv May 23 '23 at 18:46
  • @trincot Maybe the issue is still unclear? Can you provide more details about what would be missing? All the code needed for reproduction is hosted on GitHub and is accessible in a live environment on StackBlitz. Running the command `pnpm run test` would reproduce the issue. The sole purpose of logging line I suggest adding to the function `isScalarResolver` is to get an output to the terminal to have a better visualization of what is going inside the function. – devatina11yb May 23 '23 at 18:51
  • `pnpm run test` fails saying that ` FAIL tests/modules/scalars.spec.ts [ tests/modules/scalars.spec.ts ] TypeError: Cannot read properties of undefined (reading 'resolve')` – Sergiu Paraschiv May 23 '23 at 19:00
  • @SergiuParaschiv I may be wrong but it looks like it isn’t possible to debug on StackBlitz so it would require to clone the repository and open the code in an actual code editor like VS Code. I do understand that there are a few dependencies and it may make it harder to debug but this is actually a somewhat minimal reproduction given the fact that the function `isScalarResolver` is part of `graphql-modules`. – devatina11yb May 23 '23 at 19:04
  • @SergiuParaschiv Climbing up the stack trace shows that the function `mergeResolvers` calls the function `addObject` instead of the function `addScalar` because the function `isScalarResolver` (called by `mergeResolvers`) returns `false` (instead of `true`), eventually leading to this runtime error. I did some debugging on my own, I will add more details about it. – devatina11yb May 23 '23 at 19:16

1 Answers1

1

This usually happens when you have the same package installed multiple times (at different paths). Make sure that your code, and all of your dependencies, import the exact same module from the same location.

One reason might be that you have multiple dependencies installed that depend on different version of the same package (graphql-js in this case). Use a lockfile to ensure there is only a single version used.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 1
    Thank you for the suggestion, I did think about it but it was actually related to the *dual package hazard* as mentioned in EDIT 1. – devatina11yb May 25 '23 at 11:56