Проблемы с переходом с 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, но старый требует):
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(), чтобы они снова продолжали работать!
Я просматривал документацию и видел другие библиотеки, и до сих пор я не останавливаюсь, любые советы или рекомендации очень ценятся
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
route, вы сможете применить директивы к своей схеме после ее загрузки:
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);
Я пробовал этот способ, но не смог решить проблему. Уникальное решение, в котором реализован следующий подход:
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,
})
У меня была та же проблема, через которую я загрузил схему, и я хочу добавить директиву graphql-constraint . Мое решение состояло в том, чтобы загрузить схему с помощью
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()]
})