Серверные директивы GraphQL / Apollo, приводящие к ошибке схемы - PullRequest
0 голосов
/ 09 ноября 2018

Я пытаюсь добавить директивы в наш API GraphQL и следую этому примеру, https://www.apollographql.com/docs/apollo-server/features/creating-directives.html#Uppercasing-strings, однако я получаю сообщение об ошибке сервера (без директивы сервер работает!):

** 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)

Схема очень большая, поэтому я не могу опубликовать ее здесь, однако тип схемы 'Integer' не был продублирован. Я следовал нескольким различным руководствам, но продолжаю сталкиваться с этой ошибкой.

Мы используем Apollo Server 2.1.0 и GraphQL 14.0.2

Настройка сервера:

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
});

Любая помощь будет оценена!

1 Ответ

0 голосов
/ 09 ноября 2018

Это была проблема с нашими скалярами, которые генерируются с использованием логики JS, однако одно утверждение было ошибочным, что привело к нескольким скалярам с одинаковым значением имени.

Для всех остальных, как сказал @Daniel Rearden в комментариях «Ошибка исходит от graphql-tools. Эта логика проверки не вызывается, если вы не включите директивы», поэтому причина ошибки только что обнаружилась, т.е. ничего не связано с директивами.

...