Пользовательская директива GraphQL без явного объявления в схеме

Я пытаюсь реализовать специальную директиву GraphQL. Насколько я понимаю, если мой подкласс SchemaDirectiveVisitor реализует static getDirectiveDeclaration(directiveName, schema), тогда мне не придется вручную объявить директиву в моем SDL (языке определения схемы).

Because AuthDirective implements getDirectiveDeclaration, it’s no longer necessary for the schema author to include the directive @auth ... declaration explicitly in the schema. The returned GraphQLDirective object will be used to enforce the argument types and default values, as well as enabling tools like GraphiQL to discover the directive using schema introspection. Additionally, if the AuthDirective class fails to implement visitObject or visitFieldDefinition, a helpful error will be thrown.

Source: https://blog.apollographql.com/reusable-graphql-schema-directives-131fb3a177d1

а также

However, if you’re implementing a reusable SchemaDirectiveVisitor for public consumption, you will probably not be the person writing the SDL syntax, so you may not have control over which directives the schema author decides to declare, and how. That’s why a well-implemented, reusable SchemaDirectiveVisitor should consider overriding the getDirectiveDeclaration method

Source: https://www.apollographql.com/docs/apollo-server/features/creating-directives.html

В моем коде, несмотря на то, что я реализовал static getDirectiveDeclaration(directiveName, schema), мне все же нужно объявить директиву в SDL.

Разве это не должно работать без ручного объявления в SDL?

Полный пример кода:

const { ApolloServer, gql, SchemaDirectiveVisitor } = require('apollo-server');
const { DirectiveLocation, GraphQLDirective, defaultFieldResolver } = require("graphql");

class UpperCaseDirective extends SchemaDirectiveVisitor {
  static getDirectiveDeclaration(directiveName, schema) {
    console.info("inside getDirectiveDeclaration", directiveName)
    return new GraphQLDirective({
      name: directiveName,
      locations: [
        DirectiveLocation.FIELD_DEFINITION,
      ],
      args: {}
    });
  }

  visitFieldDefinition(field) {
    console.info("inside visitFieldDefinition")
    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;
    };
  }
}

const books = [
  {
    title: 'Harry Potter and the Chamber of Secrets',
    author: 'J.K. Rowling',
  },
  {
    title: 'Jurassic Park',
    author: 'Michael Crichton',
  },
];

const typeDefs = gql`

  #########################################
  # ONLY WORKS WITH THIS LINE UNCOMMENTED #
  #########################################
  directive @upper on FIELD_DEFINITION

  type Book {
    title: String
    author: String @upper
  }

  type Query {
    books: [Book]
  }
`;

const resolvers = {
  Query: {
    books: () => books,
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
  schemaDirectives: {
    upper: UpperCaseDirective
  }
});

server.listen().then(({ url }) => {
  console.info(`?  Server ready at ${url}`);
});
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
2 175
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

У меня такая же проблема, и я смог найти этот комментарий от Проблема с graphql-tools # 957..

From the changelog:

NOTE: graphql 14 includes breaking changes. We're bumping the major version of graphql-tools to accommodate those breaking changes. If you're planning on using graphql 14 with graphql-tools 4.0.0, please make sure you've reviewed the graphql breaking changes list.

This is likely caused by the fact that graphql-js now requires you to define your directives in your schema, before you attempt to use them. For example:

directive @upper on FIELD_DEFINITION

type TestObject {
  hello: String @upper
}

You can likely work around this by pre-defining your directives in your schema, but I'd like to confirm this. If this works, we'll need to update the docs.

Если я правильно понимаю, это означает, что теперь невозможно иметь объявления директив вне typeDefs?

Pascal Martineau 26.04.2019 23:13

Другие вопросы по теме