Invalid or incomplete schema is created when directives are defined and used.
See original GitHub issueGraphQL Playground as well as GraphQL code generator are throwing the following error:
Uncaught Error: Invalid or incomplete schema, unknown type: DirScalarType. Ensure that a full introspection query is used in order to build a client schema.
Code:
import { GraphQLNonNull, GraphQLScalarType, GraphQLInputField, GraphQLInputObjectType, GraphQLArgument, GraphQLInterfaceType, GraphQLField, GraphQLObjectType } from "graphql";
import { Kind } from "graphql";
import { ApolloServer, gql, SchemaDirectiveVisitor } from "apollo-server-express";
import express from "express";
export const app = express();
class MyDirective extends SchemaDirectiveVisitor {
visitInputFieldDefinition(field: GraphQLInputField, details: {
objectType: GraphQLInputObjectType;
}): GraphQLInputField | void | null {
this.wrapType(field);
}
visitArgumentDefinition(argument: GraphQLArgument, details: {
field: GraphQLField<any, any>;
objectType: GraphQLObjectType | GraphQLInterfaceType;
}): GraphQLArgument | void | null {
this.wrapType(argument);
}
wrapType(field: GraphQLInputField | GraphQLArgument) {
if (
field.type instanceof GraphQLNonNull &&
field.type.ofType instanceof GraphQLScalarType
) {
field.type = new GraphQLNonNull(new Type(field.type.ofType, field.name));
return;
}
if (field.type instanceof GraphQLScalarType) {
field.type = new Type(field.type, field.name);
return;
}
}
}
class Type extends GraphQLScalarType {
constructor(type: GraphQLScalarType, name: string) {
console.log("Directive constructor runs!");
super({
name: `DirScalarType`,
// For more information about GraphQLScalar type (de)serialization,
// see the graphql-js implementation:
// https://github.com/graphql/graphql-js/blob/31ae8a8e8312/src/type/definition.js#L425-L446
// to client
serialize(value) {
console.log("Directive runs!");
return value;
},
// by client in variable
parseValue(value) {
console.log("Directive runs!");
return value;
},
// by client in parameter
parseLiteral(ast) {
console.log("Directive runs!");
switch (ast.kind) {
case Kind.STRING:
return ast.value;
default: {
return undefined;
}
}
}
});
}
}
// Construct a schema, using GraphQL schema language
const typeDefs = gql`
# scalar DirScalarType
directive @dir on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
input MyType {
name: String @dir
}
type Query {
hello(name: String @dir): String
}
`;
// Provide resolver functions for your schema fields
const resolvers = {
Query: {
hello: () => "Hello world!"
}
};
const graphQLServer = new ApolloServer({
typeDefs,
resolvers,
schemaDirectives: { dir: MyDirective }
});
graphQLServer.applyMiddleware({ app });
app.listen(4000).on("listening", () => {
console.log(`listening on server: http://localhost:4000/graphql`);
});
If a scalar type scalar DirScalarType
is added in the schema, the error goes away, but the directive fails to run without error.
package.json:
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "ts-node index.ts",
"test": "echo \"Error: no test specified\" && exit 1",
"codegen": "graphql-codegen --config codegen.yml --watch"
},
"author": "",
"license": "ISC",
"dependencies": {
"@graphql-codegen/cli": "1.12.2",
"@graphql-codegen/introspection": "1.12.2",
"@graphql-codegen/typescript": "1.12.2",
"@graphql-codegen/typescript-document-nodes": "1.12.2",
"@graphql-codegen/typescript-resolvers": "1.12.2",
"apollo-server-express": "2.10.1",
"express": "4.17.1",
"graphql": "14.6.0",
"ts-node": "8.6.2",
"typescript": "3.7.5"
}
}
The expected behavior.
run npm run codegen
without error.
run graphql playground without error.
The actual behavior.
Running npm run codegen
throws an error complaining that the schema is invalid or incomplete.
Running GraphQL Playground will run with error in DevTools Console and query completion will not work in editor.
A simple, runnable reproduction!
Issue Analytics
- State:
- Created 4 years ago
- Reactions:5
- Comments:5 (2 by maintainers)
Top Results From Across the Web
How can I avoid federation schema mismatch during ...
1 supergraph: Invalid definition for directive "@key": argument "fields" should have type "_FieldSet!" but found type "federation__FieldSet!
Read more >16.20 - TPT04041 Error: %s: Invalid USING directive: expected ...
The USING directive must be in one of two valid forms... ... Cannot finalize schema definition, status = %s · TPT02236 Error: Cannot...
Read more >Directives - Lighthouse PHP
Returns an aggregate of a column in a given relationship or model. Requires Laravel 8+. """ directive @aggregate( """ The column to aggregate....
Read more >Spring Boot GraphQL can't load schema - Stack Overflow
You need to create your own object with properties query, operationName and arg. public class Data { private String query; public String ...
Read more >graphql-tools/schema
assertResolversPresent( schema , resolverValidationOptions? ): void ... The type definitions are written using Schema Definition Language (SDL).
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Related issue here: https://github.com/ardatan/graphql-tools/issues/842 And another one here: https://github.com/ardatan/graphql-tools/issues/789
The consensus appears to be that custom GraphQL scalars should not be used for validation going forward but to use alternative solutions like
What will Apollo’s recommended approach to validation be? I think at least the docs at https://www.apollographql.com/docs/graphql-tools/schema-directives/#enforcing-value-restrictions should be updated to reflect the problems with the suggested solution.
Right now we are planning to remove support for
schemaDirectives
in Apollo Server 3, because the project that implements it (graphql-tools) considers it to be a legacy API. Folks who want to useschemaDirectives
or its non-legacy replacementschemaTransforms
can use@graphql-tools/schema
directly to create a schema passed in withnew ApolloServer({schema})
; issues relating to these options should probably be opened in the graphql-tools repo.