如何使用 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 中对其进行测试并使用订阅。

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

干杯!

【讨论】:

以上是关于如何使用 openapi-to-graphql 在环回 4 中启用 graphql 订阅的主要内容,如果未能解决你的问题,请参考以下文章

看不到关系 - Loopback 4 + MongoDB + openapi-to-graphql

如何在你的库中使用 Spring-Data 以及如何在你的项目中使用这个库?

在 Avkit 中如何使用这三行代码,以及如何将音乐静音”

如何在发布管道中使用输出变量

如何在Hive&Impala中使用UDF

如何使用 Firebase 在 Web 上托管 Flutter?它的效果如何?