如何使用 openapi-to-graphql 在环回 4 中启用 graphql 订阅
Posted
技术标签:
【中文标题】如何使用 openapi-to-graphql 在环回 4 中启用 graphql 订阅【英文标题】:How to enable graphql subscription in loopback 4 with openapi-to-graphql 【发布时间】:2021-12-19 07:23:17 【问题描述】:根据标题,我在尝试在我的 loopback 4 应用程序中启用 graphql 订阅时遇到问题。
这是我到目前为止所做的代码。
index.ts
export async function main(options: ApplicationConfig = )
const app = new BackendLb4Application(options)
await app.boot()
await app.start()
const url = app.restServer.url;
const oas: Oas3 = <Oas3><unknown>await app.restServer.getApiSpec()
const schema = await createGraphQLSchema(oas,
operationIdFieldNames: true,
baseUrl: url,
createSubscriptionsFromCallbacks: true,
)
const handler = graphqlHTTP( (request:any, response:any, graphQLParams: any) => (
schema,
pretty: true,
graphiql: true
))
app.mountExpressRouter(graphqlPath, handler);
const pubsub = new PubSub()
const ws = createServer(app);
ws.listen(PORT, () =>
new SubscriptionServer(
execute,
subscribe,
schema,
onConnect: (params: any, socket: any, ctx: any) =>
console.log(params, 'here on onconnect')
// Add pubsub to context to be used by GraphQL subscribe field
return pubsub
,
server: ws,
path: '/subscriptions'
)
)
return app
这是我的架构
type Subscription
"""
Equivalent to PATCH onNotificationUpdate
"""
postRequestQueryCallbackUrlApiNotification(secondInputInput: SecondInputInput): String
"""
Equivalent to PATCH onNotificationUpdate
"""
postRequestQueryCallbackUrlOnNotificationUpdate(firstInputInput: FirstInputInput): String
这是我的控制器的示例
@patch('/notification-update',
operationId: 'notificationUpdate',
description: '**GraphQL notificationUpdate**',
callbacks:[
onNotificationUpdate:
//'$request.query.callbackUrl/onNotificationUpdate':
post:
requestBody:
operationId: 'notificationUpdateCallback',
description: 'rasjad',
content:
'application/json':
schema:
title: "firstInput",
type: 'object',
properties:
userData:
type: "string"
,
responses:
'200':
description: 'response to subscription',
,
//
],
responses:
'200':
description: 'Notification PATCH success count',
content: 'application/json': schema: CountSchema,
,
,
)
async updateAll(
@requestBody(
content:
'application/json':
schema: getModelSchemaRef(Notification, partial: true),
,
,
)
notification: Notification,
@param.where(Notification) where?: Where<Notification>,
): Promise<Count>
return this.notificationRepository.update(notification, where);
我已经在我的控制器中定义了回调对象,然后它将在我的模式中创建一个订阅。在 graphiql 上进行了测试,但没有成功。
我不知道从这里去哪里。我需要自定义解析器或其他东西吗?不确定。 如果有人可以提供帮助,不胜感激。
【问题讨论】:
【参考方案1】:以防万一其他人也想做同样的事情。
我用 Apollo Server 切换了 graphqlHTTP
来创建我的 graphql 服务器。
所以我的最终index.ts
看起来像这样。
export async function main(options: ApplicationConfig = )
const lb4Application = new BackendLb4Application(options)
await lb4Application.boot()
await lb4Application.migrateSchema()
await lb4Application.start()
const url = lb4Application.restServer.url;
const graphqlPath = '/graphql'
// Get the OpenApiSpec
const oas: Oas3 = <Oas3><unknown>await lb4Application.restServer.getApiSpec()
// Create GraphQl Schema from OpenApiSpec
const schema = await createGraphQLSchema(oas,
strict: false,
viewer: true,
baseUrl: url,
headers:
'X-Origin': 'GraphQL'
,
createSubscriptionsFromCallbacks: true,
customResolvers:
"lb4-title":
"your-path":
patch: (obj, args, context, info) =>
const num = Math.floor(Math.random() * 10);
pubsub.publish("something", yourMethodName: count: num ).catch((err: any) =>
console.log(err)
)
return count: 1
,
customSubscriptionResolvers:
"lb4-title" :
"yourMethodName":
post:
subscribe: () => pubsub.asyncIterator("something"),
resolve: (obj: any, args: any, context, info) =>
console.log(obj, 'obj')
)
const app = express();
const server = new ApolloServer(
schema,
plugins: [
async serverWillStart()
return
async drainServer()
subscriptionServers.close();
;
],
)
const subscriptionServers = SubscriptionServer.create(
// This is the `schema` we just created.
schema,
// These are imported from `graphql`.
execute,
subscribe,
,
server: lb4Application.restServer.httpServer?.server,
path: server.graphqlPath,
//path: server.graphqlPath,
);
await server.start();
server.applyMiddleware( app, path: "/" );
lb4Application.mountExpressRouter('/graphql', app);
return lb4Application
您还需要像这样在控制器中定义callbacks
对象。
@patch('/something-update',
operationId: 'somethingUpdate',
description: '**GraphQL somethingUpdate**',
callbacks:[
yourMethodName:
post:
responses:
'200':
description: 'response to subscription',
content: 'application/json': schema: CountSchema,
,
],
responses:
'200':
description: 'Something PATCH success count',
content: 'application/json': schema: CountSchema,
,
,
)
async updateAll(
@requestBody(
content:
'application/json':
schema: getModelSchemaRef(Something, partial: true),
,
,
)
something: Something,
@param.where(Something) where?: Where<Something>,
): Promise<Count>
return this.somethingRepository.updateAll(something, where);
就是这样。您可以在 GraphQL Playground 中对其进行测试并使用订阅。
目前,我可以定义 customResolvers
和 customSubscriptionResolvers
,但我很确定我可以从控制器自动化这两个对象。
干杯!
【讨论】:
以上是关于如何使用 openapi-to-graphql 在环回 4 中启用 graphql 订阅的主要内容,如果未能解决你的问题,请参考以下文章
看不到关系 - Loopback 4 + MongoDB + openapi-to-graphql