Проблемы с переходом с graphql-import на только graphql-tools с ApolloServer, директивы перестают работать

Мое тяжелое положение началось с простого желания расширить мою схему graphql с одного файла .graphql до нескольких файлов, чтобы я мог лучше организовать схему и чтобы она не вырастала до одного огромного файла из-под контроля.

Мой исходный макет был очень простым, и у меня была рабочая схема в файле schema.graphql. Я мог бы преобразовать его в строку, используя importSchema('server/schema.graphql') из библиотеки graphql-import, которая теперь устарела https://github.com/ardatan/graphql-import

Они упоминают, что он был объединен с graphql-tools в последней версии, и предоставляют руководство по миграции здесь https://www.graphql-tools.com/docs/migration-from-import Учебное пособие кажется очень простым, поскольку их первый пример в значительной степени иллюстрирует, как именно выглядит мой код (за исключением того, что я не использую импорт es6 но старый fashoined требует):

import { importSchema } from 'graphql-import';
import { makeExecutableSchema } from 'graphql-tools';

const typeDefs = importSchema(join(__dirname, 'schema.graphql'));
const resolvers = {
  Query: {...}
};
const schema = makeExecutableSchema({ typeDefs, resolvers });

А потом они говорят, что нужно его изменить, просто внесите эти изменения

import { loadSchemaSync } from '@graphql-tools/load';
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
import { addResolversToSchema } from '@graphql-tools/schema';

const schema = loadSchemaSync(join(__dirname, 'schema.graphql'), { loaders: [new GraphQLFileLoader()] });
const resolvers = { Query: {...} };

const schemaWithResolvers = addResolversToSchema({
  schema,
  resolvers,
});

Я внес эти изменения, но существенная разница в том, что они больше не используют makeExecutableSchema() в своем примере, что для меня очень важно, поскольку мне нужно включить директивы. Что мне теперь делать со схемой? Как объявить директивы? в их документации для директив по-прежнему используется makeExecutableSchema, но я больше не могу его использовать, поскольку новая функция loadSchemaSync возвращает объект вместо строкового литерала, который мне нужно было бы передать typeDefs в makeExecutableSchema

Я использую apollo-server, поэтому казалось возможным обходным путем просто объявить директивы в конструкторе apollo-server и просто передать этот новый schemaWithResolvers как схему как таковую

const server = new ApolloServer({
    schema, //this includes now the returned value of using addResolversToSchema()
    schemaDirectives : {
        auth:AuthDirective,
        authRole: AuthRoleDirective
    }
    context : ({req}) => //dostuff,

});

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

Мне нужен способ импортировать мой файл .graphql и разобрать его в строку, чтобы я мог использовать его внутри typeDefs, как я использовал, с importSchema () или способ объявить мои директивы без использования makeExecutableSchema (), чтобы они продолжали работать снова !

Я просматривал документацию и видел другие библиотеки, и до сих пор я не останавливаюсь, любые советы или рекомендации очень ценятся.


person xunux    schedule 18.06.2020    source источник


Ответы (3)


makeExecutableSchema по-прежнему является частью graphql-tools, и вы можете продолжать использовать его, как показано здесь в документах. Проблема с примером, показанным в документации, заключается в том, что он не эквивалентен тому, что вы делали раньше. Вместо этого вы должны использовать loadTypedefsSync:

import { loadTypedefsSync } from '@graphql-tools/load';
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
import { addResolversToSchema } from '@graphql-tools/schema';

const sources = loadTypedefsSync(join(__dirname, 'schema.graphql'), { loaders: [new GraphQLFileLoader()] });
const documentNodes = sources.map(source => source.document);
const resolvers = { Query: {...} };

const schema = makeExecutableSchema({ typeDefs, resolvers });

В качестве альтернативы, если вы выберете путь loadSchema, вы сможете применить директивы к своей схеме после ее загрузки:

import { SchemaDirectiveVisitor } from "@graphql-tools/utils";
import { loadSchemaSync } from '@graphql-tools/load';
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
import { addResolversToSchema } from '@graphql-tools/schema';

const schema = loadSchemaSync(join(__dirname, 'schema.graphql'), { loaders: [new GraphQLFileLoader()] });
const resolvers = { Query: {...} };

const schemaWithResolvers = addResolversToSchema({
  schema,
  resolvers,
});

SchemaDirectiveVisitor.visitSchemaDirectives(schemaWithResolvers, schemaDirectives);
person Daniel Rearden    schedule 18.06.2020
comment
Я нигде не могу найти loadTypedefsSync в документации, поэтому не знаю, откуда вы об этом узнали, но спасибо! это решение сработало для меня! - person xunux; 19.06.2020
comment
Итак, оба решения сработали для меня, поэтому спасибо, однако, первое решение с использованием loadTypedefsSync не позволило мне импортировать несколько файлов .graphql и использовать функцию #import в файлах, но второй подход сработал. Есть ли у вас подход к использованию вашего первого решения, но при этом вы все еще можете импортировать несколько файлов .graphql и использовать функцию #import в файлах? - person xunux; 19.06.2020
comment
loadSchema использует loadTypedefs под капотом, поэтому я ожидаю, что поведение будет таким же в отношении синтаксиса импорта. Возможно, вы захотите открыть проблему с репо с этим вопросом. - person Daniel Rearden; 19.06.2020
comment
как узнать об этих функциях? loadTypedefs, который я не могу найти в документации для graphql-tools, а репозиторий для graphql-tools / load дал мне 404, вы прямо посмотрите на исходный код? - person xunux; 19.06.2020
comment
Если кто-то споткнулся, пытаясь решить № 1, переходя от documentNodes к typeDefs, вам нужно импортировать {concatAST} из graphql, а затем typeDefs = concatAST (documentNodes) - person G Gallegos; 21.06.2020
comment
До сих пор я не использовал makeExcecutableSchema, поскольку мне кажется, что я мог бы этого избежать. Вот моя настройка для запуска Apollo: typeDefs = sources.map (source = ›source.document); новый ApolloServer ({typeDefs, resolvers, ...}) - person lapponiandevil; 23.06.2020
comment
documentNodes в первом решении должно быть typeDefs - person J. Titus; 29.01.2021
comment
При использовании второго подхода, как мне создать schemaDirectives var из объекта DocumentNode, содержащего объявления директив? - person Dmitry Klochkov; 20.06.2021

Я пробовал этот способ, но не смог решить проблему. Уникальное решение, в котором реализован следующий подход:

const { ApolloServer, makeExecutableSchema, gql} = require('apollo-server-express')
const { loadTypedefsSync }  = require('@graphql-tools/load')
const { GraphQLFileLoader } = require('@graphql-tools/graphql-file-loader')
const path = require('path')

const sources = loadTypedefsSync(
    path.resolve(__dirname, '../schema/root.graphql'),
    { loaders: [new GraphQLFileLoader()] }
)
const typeDefs = sources.map(source => source.document)
const schema = makeExecutableSchema({
    typeDefs: gql`${typeDefs[0]}`,
    resolvers,
})
person Marcus Couto    schedule 05.07.2020

У меня была та же проблема, что и при загрузке схемы через .graphql, и я хочу добавить директиву graphql-constraint-directive. Мое решение заключалось в том, чтобы загрузить схему с loadSchemaSync, а затем использовать wrapSchema для использования функций преобразования, вам также необходимо добавить директивы в один из ваших .graphql файлов:

import { addResolversToSchema, wrapSchema } from 'graphql-tools';
import { GraphQLSchema } from 'graphql';
import resolvers from './resolver';

schema = loadSchemaSync('./**/*.graphql', {
  loaders: [new GraphQLFileLoader()],
});

const schemaWithResolver = addResolversToSchema({
    schema,
    resolvers
  });

const { constraintDirective } = require('graphql-constraint-directive')
  
const schemaConstrain = wrapSchema({
  schema: schemaWithResolver,
  transforms: [constraintDirective()]
})

Документация по упаковке схемы

person Rafael    schedule 28.04.2021