使用 graphql-tools 打印远程模式时出现 getDirectives 错误
getDirectives error when printing remote schema with graphql-tools
我有两个节点服务器都通过 express-graphql
服务 graphql。
我希望我的第一台服务器将其模式与第二台服务器的模式拼接起来。
我已按照以下说明进行操作:https://www.apollographql.com/docs/graphql-tools/remote-schemas
因为我正在使用 graphql-tools。
我能够从我的第二个节点服务器检索模式,但是当我尝试打印它时(仅 console.log
)我得到这个错误:
Uncaught exception TypeError: schema.getDirectives is not a function
at printFilteredSchema (/Users/cchabert/git-repo/client-configuration-api/node_modules/graphql/utilities/schemaPrinter.js:61:27)
at Object.printSchema (/Users/cchabert/git-repo/client-configuration-api/node_modules/graphql/utilities/schemaPrinter.js:47:10)
at makeRemoteExecutableSchema (/Users/cchabert/git-repo/client-configuration-api/node_modules/graphql-tools/dist/stitching/makeRemoteExecutableSchema.js:60:30)
at schema (/Users/cchabert/git-repo/client-configuration-api/app/api/schema.js:68:24)
at module.exports (/Users/cchabert/git-repo/client-configuration-api/app/routes.js:102:13)
at Object.<anonymous> (/Users/cchabert/git-repo/client-configuration-api/app/index.js:15:20)
at Module._compile (internal/modules/cjs/loader.js:799:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:810:10)
at Module.load (internal/modules/cjs/loader.js:666:32)
at tryModuleLoad (internal/modules/cjs/loader.js:606:12)
at Function.Module._load (internal/modules/cjs/loader.js:598:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:862:12)
at internal/main/run_main_module.js:21:11
这会导致服务器死机,但我也能以某种方式看到模式:
received schema: {"_queryType":"Query","_mutationType":"Mutation",
"_subscriptionType":null,"_directives":["@skip","@include","@deprecated"],
"_typeMap":{"Query":"Query","String":"String","Client":"Client",
"ID":"ID","DateTime":"DateTime",[...]}
我确实在远程模式定义中看到了 _directives
字段,但文档并不清楚如何处理这个问题。
我也查看了 graphql-tools
回购的 github 个问题,但找不到任何东西。
这是一个代码片段:
const {
addMockFunctionsToSchema,
makeExecutableSchema,
makeRemoteExecutableSchema,
introspectSchema,
mergeSchemas
} = require('graphql-tools')
const _ = require('lodash)
const { createHttpLink } = require('apollo-link-http')
const fetch = require('node-fetch')
[..]
const customFetch = (uri, options = {}) => {
const httpOptions = _.merge(options, {
headers: {
'Content-type': 'application/json'
}
})
return fetch(uri, httpOptions)
}
function schema() {
const Query = `
type Query {
_empty: String
}
type Mutation {
_empty: String
}
`
const resolvers = {}
const mocks = {}
const localSchema = makeExecutableSchema({
typeDefs: [Query, [...]],
resolvers: [resolvers, [...]]
}) // by itself this schema works without any issues
const mergedMocks = _.merge(mocks, [...])
addMockFunctionsToSchema({
schema: localSchema,
mocks: mergedMocks,
preserveResolvers: true
})
const infoApiLink = createHttpLink({ uri, fetch: customFetch })
const remoteSchema = makeRemoteExecutableSchema({
schema: introspectSchema(infoApiLink).then(remoteSchema => {
console.log('received schema: ', JSON.stringify(remoteSchema))
return remoteSchema
}),
link: infoApiLink
})
return mergeSchemas({ schemas: [localSchema, remoteSchema] })
}
module.exports = {
schema
}
中提到的 Promises(没有 async/await)来完成这项工作
欢迎提出任何建议。
makeRemoteExecutableSchema
应该传递一个 GraphQLSchema
的实例,但你没有这样做——你正在做的是传递一个 Promise,它将解析为 GraphQLSchema
],这是行不通的。当您调用 introspectSchema
时,它必须进行自省调用,这是异步完成的。它 returns 一个解析为结果 GraphQLSchema
对象的 Promise。我们需要使用 await
或 then
来获取该值,然后我们可以根据需要使用它。
没有async/await的不必要的混乱方式:
function schema () {
// ... rest of your code
return introspectSchema(infoApiLink).then(schema => {
const remoteSchema = makeRemoteExecutableSchema({ schema, link: infoApiLink })
return mergeSchemas({ schemas: [localSchema, remoteSchema] })
})
}
或使用async/await:
async function schema () {
// ... rest of your code
const schema = await introspectSchema(infoApiLink)
const remoteSchema = makeRemoteExecutableSchema({ schema, link: infoApiLink })
return mergeSchemas({ schemas: [localSchema, remoteSchema] })
}
无论哪种方式,请记住,通过调用您的 schema
函数,您将返回一个 Promise,该 Promise 将解析为 mergeSchemas 返回的值。因此,在您可以导入函数、调用它并直接使用结果之前,您将不得不再次使用 then
或 await
来获取 Promise 首先解析的值:
import { schema } from './some-module'
schema()
.then(schema => {
const server = new ApolloServer({ schema })
server.listen()
})
.catch(error => {
// handle the Promise rejecting
})
我有两个节点服务器都通过 express-graphql
服务 graphql。
我希望我的第一台服务器将其模式与第二台服务器的模式拼接起来。
我已按照以下说明进行操作:https://www.apollographql.com/docs/graphql-tools/remote-schemas
因为我正在使用 graphql-tools。
我能够从我的第二个节点服务器检索模式,但是当我尝试打印它时(仅 console.log
)我得到这个错误:
Uncaught exception TypeError: schema.getDirectives is not a function
at printFilteredSchema (/Users/cchabert/git-repo/client-configuration-api/node_modules/graphql/utilities/schemaPrinter.js:61:27)
at Object.printSchema (/Users/cchabert/git-repo/client-configuration-api/node_modules/graphql/utilities/schemaPrinter.js:47:10)
at makeRemoteExecutableSchema (/Users/cchabert/git-repo/client-configuration-api/node_modules/graphql-tools/dist/stitching/makeRemoteExecutableSchema.js:60:30)
at schema (/Users/cchabert/git-repo/client-configuration-api/app/api/schema.js:68:24)
at module.exports (/Users/cchabert/git-repo/client-configuration-api/app/routes.js:102:13)
at Object.<anonymous> (/Users/cchabert/git-repo/client-configuration-api/app/index.js:15:20)
at Module._compile (internal/modules/cjs/loader.js:799:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:810:10)
at Module.load (internal/modules/cjs/loader.js:666:32)
at tryModuleLoad (internal/modules/cjs/loader.js:606:12)
at Function.Module._load (internal/modules/cjs/loader.js:598:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:862:12)
at internal/main/run_main_module.js:21:11
这会导致服务器死机,但我也能以某种方式看到模式:
received schema: {"_queryType":"Query","_mutationType":"Mutation",
"_subscriptionType":null,"_directives":["@skip","@include","@deprecated"],
"_typeMap":{"Query":"Query","String":"String","Client":"Client",
"ID":"ID","DateTime":"DateTime",[...]}
我确实在远程模式定义中看到了 _directives
字段,但文档并不清楚如何处理这个问题。
我也查看了 graphql-tools
回购的 github 个问题,但找不到任何东西。
这是一个代码片段:
const {
addMockFunctionsToSchema,
makeExecutableSchema,
makeRemoteExecutableSchema,
introspectSchema,
mergeSchemas
} = require('graphql-tools')
const _ = require('lodash)
const { createHttpLink } = require('apollo-link-http')
const fetch = require('node-fetch')
[..]
const customFetch = (uri, options = {}) => {
const httpOptions = _.merge(options, {
headers: {
'Content-type': 'application/json'
}
})
return fetch(uri, httpOptions)
}
function schema() {
const Query = `
type Query {
_empty: String
}
type Mutation {
_empty: String
}
`
const resolvers = {}
const mocks = {}
const localSchema = makeExecutableSchema({
typeDefs: [Query, [...]],
resolvers: [resolvers, [...]]
}) // by itself this schema works without any issues
const mergedMocks = _.merge(mocks, [...])
addMockFunctionsToSchema({
schema: localSchema,
mocks: mergedMocks,
preserveResolvers: true
})
const infoApiLink = createHttpLink({ uri, fetch: customFetch })
const remoteSchema = makeRemoteExecutableSchema({
schema: introspectSchema(infoApiLink).then(remoteSchema => {
console.log('received schema: ', JSON.stringify(remoteSchema))
return remoteSchema
}),
link: infoApiLink
})
return mergeSchemas({ schemas: [localSchema, remoteSchema] })
}
module.exports = {
schema
}
中提到的 Promises(没有 async/await)来完成这项工作
欢迎提出任何建议。
makeRemoteExecutableSchema
应该传递一个 GraphQLSchema
的实例,但你没有这样做——你正在做的是传递一个 Promise,它将解析为 GraphQLSchema
],这是行不通的。当您调用 introspectSchema
时,它必须进行自省调用,这是异步完成的。它 returns 一个解析为结果 GraphQLSchema
对象的 Promise。我们需要使用 await
或 then
来获取该值,然后我们可以根据需要使用它。
没有async/await的不必要的混乱方式:
function schema () {
// ... rest of your code
return introspectSchema(infoApiLink).then(schema => {
const remoteSchema = makeRemoteExecutableSchema({ schema, link: infoApiLink })
return mergeSchemas({ schemas: [localSchema, remoteSchema] })
})
}
或使用async/await:
async function schema () {
// ... rest of your code
const schema = await introspectSchema(infoApiLink)
const remoteSchema = makeRemoteExecutableSchema({ schema, link: infoApiLink })
return mergeSchemas({ schemas: [localSchema, remoteSchema] })
}
无论哪种方式,请记住,通过调用您的 schema
函数,您将返回一个 Promise,该 Promise 将解析为 mergeSchemas 返回的值。因此,在您可以导入函数、调用它并直接使用结果之前,您将不得不再次使用 then
或 await
来获取 Promise 首先解析的值:
import { schema } from './some-module'
schema()
.then(schema => {
const server = new ApolloServer({ schema })
server.listen()
})
.catch(error => {
// handle the Promise rejecting
})