【问题标题】:How to enable graphql subscription in loopback 4 with openapi-to-graphql如何使用 openapi-to-graphql 在环回 4 中启用 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 上进行了测试,但没有成功。

我不知道从这里去哪里。我需要自定义解析器或其他东西吗?不确定。 如果有人可以提供帮助,不胜感激。

【问题讨论】:

    标签: graphql loopback4 graphql-subscriptions


    【解决方案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 中对其进行测试并使用订阅。

    目前,我可以定义 customResolverscustomSubscriptionResolvers,但我很确定我可以从控制器自动化这两个对象。

    干杯!

    【讨论】:

      猜你喜欢
      • 2020-11-17
      • 2019-09-27
      • 2018-02-25
      • 1970-01-01
      • 2019-12-01
      • 2017-09-01
      • 2022-09-29
      • 2019-11-27
      • 2021-03-12
      相关资源
      最近更新 更多