Пользовательская директива GraphQL без явного объявления в схеме - PullRequest
0 голосов
/ 16 октября 2018

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

, потому чтоAuthDirective реализует getDirectiveDeclaration, больше не нужно, чтобы автор схемы включал объявление директивы @auth ... явно в схему.Возвращенный объект GraphQLDirective будет использоваться для принудительного применения типов аргументов и значений по умолчанию, а также для включения таких инструментов, как GraphiQL, для обнаружения директивы с помощью самоанализа схемы.Кроме того, если класс AuthDirective не сможет реализовать visitObject или visitFieldDefinition, будет выдана полезная ошибка.

Источник: https://blog.apollographql.com/reusable-graphql-schema-directives-131fb3a177d1

и

Однако, если вы реализуете повторно используемый SchemaDirectiveVisitor для публичного использования, вы, вероятно, не будете тем, кто пишет синтаксис SDL, поэтому у вас может не быть контроля над тем, какие директивы автор решает объявить и как.Вот почему хорошо реализованный, многократно используемый SchemaDirectiveVisitor должен рассмотреть возможность переопределения метода getDirectiveDeclaration

Источник: 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.log("inside getDirectiveDeclaration", directiveName)
    return new GraphQLDirective({
      name: directiveName,
      locations: [
        DirectiveLocation.FIELD_DEFINITION,
      ],
      args: {}
    });
  }

  visitFieldDefinition(field) {
    console.log("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.log(`?  Server ready at ${url}`);
});

1 Ответ

0 голосов
/ 22 октября 2018

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

Из changelog :

ПРИМЕЧАНИЕ. В Graphql 14 внесены критические изменения.Мы выпускаем основную версию GraphQl-инструментов, чтобы приспособиться к этим серьезным изменениям.Если вы планируете использовать graphql 14 с graphql-tools 4.0.0, убедитесь, что вы просмотрели список критических изменений graphql.

Вероятно, это связано с тем, что graphql-jsтеперь требует, чтобы вы определили свои директивы в своей схеме, прежде чем пытаться их использовать.Например:

directive @upper on FIELD_DEFINITION

type TestObject {
  hello: String @upper
}

Скорее всего, вы можете обойти это, предварительно определив свои директивы в своей схеме, но я хотел бы подтвердить это.Если это работает, нам нужно обновить документы.

...