我正在将apollo-server-express用于graphql后端。我将仅在此处处理突变,但是我想通过使用内省的模式缝合来重定向hasura上的查询和订阅。通过apollo服务器对hasura的查询工作正常,并返回了预期的数据。
但是订阅无法正常工作,并且出现以下错误:“预期可迭代,但未为字段subscription_root.users找到一个”。
此外,服务器hasura正在接收事件:
但是,阿波罗伺服器讨厌hasura的答案。这不是我受苦的第一天,我无法理解问题所在。
在编辑器中hasura订阅工作。
如果您需要任何其他信息,我们将很乐意为您提供。
import {
introspectSchema,
makeExecutableSchema,
makeRemoteExecutableSchema,
mergeSchemas,
transformSchema,
FilterRootFields
} from 'graphql-tools';
import { HttpLink } from 'apollo-link-http';
import nodeFetch from 'node-fetch';
import { resolvers } from './resolvers';
import { hasRoleResolver } from './directives';
import { typeDefs } from './types';
import { WebSocketLink } from 'apollo-link-ws';
import { split } from 'apollo-link';
import { getMainDefinition } from 'apollo-utilities';
import { SubscriptionClient } from 'subscriptions-transport-ws';
import * as ws from 'ws';
import { OperationTypeNode } from 'graphql';
interface IDefinitionsParams {
operation?: OperationTypeNode,
kind: 'OperationDefinition' | 'FragmentDefinition'
}
const wsurl = 'ws://graphql-engine:8080/v1alpha1/graphql';
const getWsClient = function (wsurl: string) {
const client = new SubscriptionClient(wsurl, {
reconnect: true,
lazy: true
}, ws);
return client;
};
const wsLink = new WebSocketLink(getWsClient(wsurl));
const createRemoteSchema = async () => {
const httpLink = new HttpLink({
uri: 'http://graphql-engine:8080/v1alpha1/graphql',
fetch: (nodeFetch as any)
});
const link = split(
({ query }) => {
const { kind, operation }: IDefinitionsParams = getMainDefinition(query);
console.log('kind = ', kind, 'operation = ', operation);
return kind === 'OperationDefinition' && operation === 'subscription';
},
wsLink,
httpLink,
);
const remoteSchema = await introspectSchema(link);
const remoteExecutableSchema = makeRemoteExecutableSchema({
link,
schema: remoteSchema
});
const renamedSchema = transformSchema(
remoteExecutableSchema,
[
new FilterRootFields((operation, fieldName) => {
return (operation === 'Mutation') ? false : true; // && fieldName === 'password'
})
]
);
return renamedSchema;
};
export const createNewSchema = async () => {
const hasuraExecutableSchema = await createRemoteSchema();
const apolloSchema = makeExecutableSchema({
typeDefs,
resolvers,
directiveResolvers: {
hasRole: hasRoleResolver
}
});
return mergeSchemas({
schemas: [
hasuraExecutableSchema,
apolloSchema
]
});
};
答案 0 :(得分:0)
通过安装graphql-tools 4th版本修复。它淘汰了编辑器,甚至没有注意到我没有此依赖关系,只是选择了node_modules的版本,该版本是由其他软件包安装的。问题出在3.x版本上。 Pull request是修复错误的地方。
答案 1 :(得分:0)
我遇到了同样的问题,原因和解决方法不同。
我的订阅运行良好,直到我在其中引入了'resolve'键 我的订阅解析器:
这是我的解析器的“订阅”部分:
Subscription: {
mySubName: {
resolve: (payload) => {
console.log('In mySubName resolver, payload:',payload)
return payload;
},
subscribe:() => pubSub.asyncIterator(['requestsIncomplete']),
// )
},
console.log证明使用结构良好的有效负载(形状与我的Schema定义相同)调用了resolve()函数-特别是具有以graphQL Subscriber命名的键的对象,该对象指向数组(array为迭代):
In mySubName resolver, payload: { mySubName:
[ { id: 41,
...,
},
{...},
{...}
...
...
]
即使我返回了相同的纯净对象,它也会导致错误expected Iterable, but did not find one for field "Subscription.mySubName"
当我将所有解析功能都注释掉时,订阅工作正常,这进一步证明了我的有效负载结构合理,右键指向可迭代。
我一定是在滥用resolve字段。来自https://www.apollographql.com/docs/graphql-subscriptions/subscriptions-to-schema/
使用订阅字段时,也可以操纵事件 有效负载,然后再通过GraphQL执行引擎运行有效负载。
在您的订阅附近添加解决方法,并根据需要更改有效负载
所以我不确定如何正确使用该函数,特别是不知道从该函数返回什么形状对象,但是如上所述使用它会破坏您按照问题描述的方式进行订阅。
我已经在使用graphql-tools 4.0.0,我升级到4.0.8,但没什么区别。