Describe the bug
graphql-codegen fails to load Schema when GraphQLSchema is provided via a custom loader.
However, what is more interesting is, the same configuration may sometimes work, and all seems to be go smooth. But, you will encounter this problem, as you come to it in a later time.
The error is reproducable, and I have provided a log of the error in error.log file. Please refer to the repository.
To Reproduce
Please Refer: https://gitlab.com/errors1/codegen-err
It is easily reproducable by executing npm run cgn on the given repository.
// Just for the purpose of providing root type Query
import gql from "graphql-tag";
export const gqlTypeDefs = gql`
type Query{
user: User!
}
type User {
id: ID
name: EmailAddress!
email: String!
}
`;
EmailAddress above, and remove 'test.js' from the codegen.ymlN/A
codegen.yml config file:overwrite: true
schema:
- "test.js"
- "sample_schema.ts"
documents: null
generates:
tsdefs.ts:
plugins:
- "typescript"
- "typescript-resolvers"
./graphql.schema.json:
plugins:
- "introspection"
const {typeDefs} = require("graphql-scalars");
const {makeExecutableSchema} = require("graphql-tools");
const schema = makeExecutableSchema({typeDefs});
console.log(schema);
module.exports = schema;
Expected behavior
The GraphQLSchema should work as a Schema Type as described in the docs.
Environment:
@graphql-codegen/...: 1.14.0Additional context
I tried reducing the typeDefs array returned by 'graphql-scalars' into a single string, and converting it to GraphQLSchema, it worked for a while. But, the error began to pop up again.
If you can't find the error after a while, try changing relaunching the shell, or your dev enviornment. The errors pops up again.
// custom loader
let {typeDefs} = require("graphql-scalars");
typeDefs = typeDefs.reduce((a, c) => a+c+' ', '');
module.exports = typeDefs;
Here, the type exported is string instead of GraphQLSchema, whereas GraphQLSchema work.
@pavittarx I tried your reproduction, and I noticed this:
test.js is not exporting an executable schema - it just exports types. So if your config file points only to it, you'll get: ✖ ./graphql.schema.json
Error: Query root type must be provided.
at assertValidSchema (/Users/dotansimha/Dev/temp/codegen-err/node_modules/graphql/type/validate.js:71:11)
at assertValidExecutionArguments (/Users/dotansimha/Dev/temp/codegen-err/node_modules/graphql/execution/execute.js:136:35)
at executeImpl (/Users/dotansimha/Dev/temp/codegen-err/node_modules/graphql/execution/execute.js:84:3)
at execute (/Users/dotansimha/Dev/temp/codegen-err/node_modules/graphql/execution/execute.js:62:35)
typeDefs from sample_schema - it will work, but if you are trying to export GraphQLSchema from that file, it will fail - because it tries to compile the schema within your file, without the types from test.js so it will fail.You configuration should include a single schema loader file, that loads the types from graphql-scalars, and builds the schema with those types and your custom types as GraphQLSchema object. If you export a GraphQLSchema object - it should contains everything and should be executable.
If you wish to expose typeDefs and let codegen merge and make your schema executable, you can do it with the same configuration you have in this reproduction.
I noticed a bug with the graphql-tools loaders, I guess we should allow telling the loaders that you prefer to use require over AST lookup, we'll try to fix that.
@dotansimha We have noPluck option for @graphql-tools/code-file-loader, so you can skip Tag Pluck and use require directly.
https://github.com/ardatan/graphql-tools/blob/master/packages/loaders/code-file/src/index.ts#L111
You are right @ardatan :) @pavittarx your custom loader file should look like that:
const { makeExecutableSchema } = require("graphql-tools");
const { typeDefs: scalarsTypeDefs } = require("graphql-scalars");
const gql = require('graphql-tag');
const gqlTypeDefs = gql`
${scalarsTypeDefs}
type Query{
user: User!
}
type User {
id: ID
name: EmailAddress!
email: String!
}
`;
module.exports = makeExecutableSchema({ typeDefs: gqlTypeDefs });
And the codegen config file:
schema:
- ./sample_schema.js:
noPluck: true
generates:
tsdefs.ts:
plugins:
- "typescript"
- "typescript-resolvers"
./graphql.schema.json:
plugins:
- "introspection"
I'll update the docs now!
Is there an equivalent fix to having string interpolation within a one of the documents files? I am currently getting the following error message:
GraphQLError: Syntax Error: Expected "$", found ")".
at syntaxError (/Users/alex/git/my-app/node_modules/graphql/error/syntaxError.js:15:10)
at Parser.expectToken (/Users/alex/git/my-app/node_modules/graphql/language/parser.js:1423:40)
at Parser.parseVariable (/Users/alex/git/my-app/node_modules/graphql/language/parser.js:249:10)
at Parser.parseVariableDefinition (/Users/alex/git/my-app/node_modules/graphql/language/parser.js:235:22)
at Parser.optionalMany (/Users/alex/git/my-app/node_modules/graphql/language/parser.js:1516:28)
at Parser.parseVariableDefinitions (/Users/alex/git/my-app/node_modules/graphql/language/parser.js:224:17)
at Parser.parseOperationDefinition (/Users/alex/git/my-app/node_modules/graphql/language/parser.js:191:33)
at Parser.parseDefinition (/Users/alex/git/my-app/node_modules/graphql/language/parser.js:131:23)
at Parser.many (/Users/alex/git/my-app/node_modules/graphql/language/parser.js:1537:26)
at Parser.parseDocument (/Users/alex/git/my-app/node_modules/graphql/language/parser.js:109:25)
at Object.parse (/Users/alex/git/my-app/node_modules/graphql/language/parser.js:36:17)
at Object.parseGraphQLSDL (/Users/alex/git/my-app/node_modules/@graphql-tools/utils/index.cjs.js:650:32)
at parseSDL (/Users/alex/git/my-app/node_modules/@graphql-tools/code-file-loader/index.cjs.js:283:18)
at CodeFileLoader.load (/Users/alex/git/my-app/node_modules/@graphql-tools/code-file-loader/index.cjs.js:217:28)
at async loadFile (/Users/alex/git/my-app/node_modules/@graphql-tools/load/index.cjs.js:48:24)
at async /Users/alex/git/my-app/node_modules/@graphql-tools/load/index.cjs.js:425:24
My code looks like this (I have also tried using the string interpolation function):
const myMutation = gql(`
mutation MyMutation( ${params.join(', ')} ) {
${aliases}
}
`)
@cancan101 you can use custom document loader, and use require in your custom loader to load it from your code file. This way you'll get the interpolated version of the documents and feed it to codegen.
See: https://graphql-code-generator.com/docs/getting-started/documents-field#custom-document-loader
I tried with this in yml + added a loader and don't see the custom loader being used:
schema:
- "schema.graphql"
documents:
- "./src/**/*.{ts,tsx}":
loader: "my-documents-loader.js"
@cancan101 can you please try like that? (YAML is very sensitive when it comes to indentation)
schema:
- "schema.graphql"
documents:
- "./src/**/*.{ts,tsx}":
loader: "my-documents-loader.js"
Ah okay, that fixed the issue with using the loader; however, I am getting the following error using the example loader from the linked docs:
GraphQLError: Syntax Error: Unexpected Name "import".
You need to add ts-node as well :) because NodeJS itself doesn't know how to load TS files.
Sure, that makes sense (and this is likely due to my ignorance) but after installing ts-node, how do I get the generate script to run / load using it?
Sure, that makes sense (and this is likely due to my ignorance) but after installing ts-node, how do I get the generate script to run / load using it?
You need to specify require config key, see: https://graphql-code-generator.com/docs/getting-started/require-field#typescript-support
Still not quite working. A couple questions:
documents or globally in the yml file? I have:overwrite: true
schema:
- "schema.graphql"
documents:
- "./src/**/*.{ts,tsx}":
loader: "./my-documents-loader.js"
generates:
src/generated/graphql.tsx:
plugins:
- "typescript"
- "typescript-operations"
- "typescript-react-apollo"
config:
skipTypename: true
withHooks: false
withHOC: false
withComponent: false
withMutationFn: false
namingConvention:
enumValues: keep
./graphql.schema.json:
plugins:
- "introspection"
require:
- ts-node/register
Error I am getting:
✖ Load GraphQL documents
→ Syntax Error: Unexpected Name "import".
Could you create a reproduction on CodeSandbox so we can help you better?
Most helpful comment
@dotansimha We have
noPluckoption for@graphql-tools/code-file-loader, so you can skip Tag Pluck and userequiredirectly.https://github.com/ardatan/graphql-tools/blob/master/packages/loaders/code-file/src/index.ts#L111