简体   繁体   中英

GraphQL / Apollo Server Directives leading to schema error

I'm trying to add directives into our GraphQL API and am following this example, https://www.apollographql.com/docs/apollo-server/features/creating-directives.html#Uppercasing-strings , however, I keep getting the server error (without the directive the server works!):

** Uncaught Error: Duplicate schema type name Integer **
    at home/node_modules/apollo-server-core/node_modules/graphql-tools/dist/schemaVisitor.js:243:27
    at home/node_modules/apollo-server-core/node_modules/graphql-tools/dist/schemaVisitor.js:527:9
    at Array.forEach (<anonymous>)
    at each (home/node_modules/apollo-server-core/node_modules/graphql-tools/dist/schemaVisitor.js:526:32)
    at heal (home/node_modules/apollo-server-core/node_modules/graphql-tools/dist/schemaVisitor.js:234:13)
    at healSchema (home/node_modules/apollo-server-core/node_modules/graphql-tools/dist/schemaVisitor.js:225:5)
    at Function.SchemaDirectiveVisitor.visitSchemaDirectives (home/node_modules/apollo-server-core/node_modules/graphql-tools/dist/schemaVisitor.js:474:9)
    at Object.makeExecutableSchema (home/node_modules/apollo-server-core/node_modules/graphql-tools/dist/makeExecutableSchema.js:54:48)
    at new ApolloServerBase (home/node_modules/apollo-server-core/dist/ApolloServer.js:142:43)
    at new ApolloServer (home/node_modules/apollo-server-express/dist/ApolloServer.js:44:1)

The schema is very large so I can't post it here, however, the schema type 'Integer' has not been duplicated. I've followed multiple different guides but keep running into this error.

We are using Apollo Server 2.1.0 & GraphQL 14.0.2

Server setup:

class error_extension extends GraphQLExtension {
  willSendResponse(o) {
    const { context, graphqlResponse } = o;

    context.add_additional_error_reporting(graphqlResponse.errors);

    return o;
  }
}


// Create (or import) a custom schema directive
class UpperCaseDirective extends SchemaDirectiveVisitor {
  visitFieldDefinition(field) {
    const { resolve = defaultFieldResolver } = field;
    field.resolve = async function (...args) {
      const result = await resolve.apply(this, args);
      if (typeof result === 'string') {
        return result.toUpperCase();
      }
      return result;
    };
  }
}


// Server settings
const server = new ApolloServer({
  typeDefs,
  resolvers,
  schemaDirectives: {
    upper: UpperCaseDirective,
  },
  context: async ({ req, res }) => {
    // some auth logic here - removed for the purpose of this

    return {
      add_additional_error_reporting(errors) {
        if (!errors) return;

        errors = errors.map(item => {

          // add request data to the returned error
          if (`extensions` in item && item.extensions !== undefined)
            item.extensions.request_details = req.body;

          return item;
        });

        return errors;
      },
      req,
      res
    };
  },
  extensions: [() => new error_extension()],
  validationRules: [

    depthLimit(5),

    costAnalysis({ // GraphQL Query Cost 
      maximumCost: 100, // maximum cost of a single  query
      defaultCost: 1, // default cost of a field
      onComplete: (async request_cost => {
        // Callback function to retrieve the determined query cost. It will be invoked whether the query is rejected or not. 
        // This can be used for logging or to implement rate limiting (for example, to store the cost by session and define a max cost the user can have in a specific time).
        try { 
          cost_data = await helper.run_connector_cost_logic(request_cost);
        } catch (err) { throw err; }
      }),
      createError: (maximumCost, cost) => {
        // Function to create a custom error
        throw new ApolloError(`The maximum cost per request is ${maximumCost} however this request is greater than this limit, with a cost of ${cost}.`, `EXCEEDED_MAX_REQ_COST`);
      }
    })

  ],
  formatError: err => { 
    console.error(err); // eslint-disable-line
    return err; 
  },
  formatResponse: res => {
    res.extensions.cost = cost_data;

    // wipe the cost data for the next request
    cost_data = {};

    return res;
  },
  introspection: false,
  tracing: false,
  debug: false
});

Any help would be appreciated!

This was an issue with our Scalars which are generated using JS logic however one statement was flawed leading to multiple Scalars with the same name value.

For anyone else, as @Daniel Rearden said in the comments "The error is coming from graphql-tools. That validation logic doesn't get called unless you include directives" hence why the error has only just showen up ie it was nothing related to directives.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM