Repository: mercurius-js/mercurius
Pull request #389 (2021-02-11 17:34:43)

docs: Add apollo registry plugin to plugin list
This PR adds the Mercurius Apollo Registry Plugin to the documented list of available plugins as well as some basic usage. 


Patch:
diff --git a/docs/plugins.md b/docs/plugins.md
index 6e3ac8f..09cc56f 100644
--- a/docs/plugins.md
+++ b/docs/plugins.md
@@ -41,3 +41,37 @@ app.listen(3000)
 And it will be available at `http://localhost:3000/altair` 🎉
 
 Check [here](https://github.com/imolorhe/altair/tree/staging/packages/altair-fastify-plugin) for more information.
+
+## mercurius-apollo-registry
+
+A Mercurius plugin for schema reporting to Apollo Studio.
+
+Check [https://github.com/nearform/mercurius-apollo-registry](https://github.com/nearform/mercurius-apollo-registry) for usage and readme.
+
+```bash
+npm install mercurius-apollo-registry
+```
+
+```js
+const app = Fastify()
+const mercurius = require('mercurius')
+const mercuriusApolloRegistry = require('mercurius-apollo-registry')
+
+const schema = `define schema here`
+const resolvers = { 
+  // ... 
+}
+
+app.register(mercurius, {
+  schema,
+  resolvers,
+  graphiql: true
+})
+
+app.register(mercuriusApolloRegistry, {
+  schema,
+  apiKey: 'REPLACE-THIS-VALUE-WITH-APOLLO-API-KEY'
+})
+
+app.listen(3000)
+```
diff --git a/lib/subscription-connection.js b/lib/subscription-connection.js
index 51740bf..09cf1a7 100644
--- a/lib/subscription-connection.js
+++ b/lib/subscription-connection.js
@@ -37,6 +37,7 @@ module.exports = class SubscriptionConnection {
     this.onConnect = onConnect
     this.onDisconnect = onDisconnect
     this.subscriptionContexts = new Map()
+    this.subscriptionIters = new Map()
     this.context = context
     this.isReady = false
     this.resolveContext = resolveContext
@@ -165,12 +166,12 @@ module.exports = class SubscriptionConnection {
       fastify: this.fastify,
       pubsub: this.subscriber
     })
-    this.subscriptionContexts.set(id, sc)
 
     const document = typeof query !== 'string' ? query : parse(query)
     const schema = this.fastify ? this.fastify.graphql.schema : undefined
+    this.subscriptionContexts.set(id, sc)
 
-    const result = await subscribe(
+    const subIter = await subscribe(
       schema,
       document,
       {}, // rootValue
@@ -186,14 +187,15 @@ module.exports = class SubscriptionConnection {
       variables,
       operationName
     )
+    this.subscriptionIters.set(id, subIter)
 
-    if (result.errors) {
-      this.fastify.log.error(result.errors)
-      throw result.errors[0]
+    if (subIter.errors) {
+      this.fastify.log.error(subIter.errors)
+      throw subIter.errors[0]
     }
 
     // TODO implement backpressure
-    for await (const value of result) {
+    for await (const value of subIter) {
       this.sendMessage(GQL_DATA, data.id, value)
     }
 
@@ -201,20 +203,25 @@ module.exports = class SubscriptionConnection {
   }
 
   handleGQLStop (data) {
-    const subscriptionContextToRemove = this.subscriptionContexts.get(data.id)
-    if (!subscriptionContextToRemove) {
-      return
+    const sc = this.subscriptionContexts.get(data.id)
+    if (sc) {
+      sc.close && sc.close()
+      this.subscriptionContexts.delete(data.id)
+    }
+    const subIter = this.subscriptionIters.get(data.id)
+    if (subIter) {
+      subIter.return && subIter.return()
+      this.subscriptionIters.delete(data.id)
     }
-
-    subscriptionContextToRemove.close()
-    this.subscriptionContexts.delete(data.id)
   }
 
   handleConnectionClose () {
     Array
       .from(this.subscriptionContexts.values())
-      .map(subscriptionContext =>
-        subscriptionContext.close())
+      .map((sc) => sc.close())
+    Array
+      .from(this.subscriptionIters.values())
+      .map((subIter) => subIter.return && subIter.return())
     this.socket.close()
 
     if (typeof this.onDisconnect === 'function') {


Test patch:
diff --git a/test/subscription-connection.js b/test/subscription-connection.js
index 2c493b3..01a5811 100644
--- a/test/subscription-connection.js
+++ b/test/subscription-connection.js
@@ -92,7 +92,7 @@ test('subscription connection handles GQL_CONNECTION_TERMINATE message correctly
   }))
 })
 
-test('subscription connection handles GQL_STOP message correctly', async (t) => {
+test('subscription connection closes context on GQL_STOP message correctly', async (t) => {
   t.plan(2)
   const sc = new SubscriptionConnection({
     on () {},
@@ -115,6 +115,29 @@ test('subscription connection handles GQL_STOP message correctly', async (t) =>
   t.equal(sc.subscriptionContexts.size, 0)
 })
 
+test('subscription connection completes resolver iterator on GQL_STOP message correctly', async (t) => {
+  t.plan(2)
+  const sc = new SubscriptionConnection({
+    on () {},
+    close () {},
+    send (message) {}
+  }, {})
+
+  sc.subscriptionIters = new Map()
+  sc.subscriptionIters.set(1, {
+    return () {
+      t.pass()
+    }
+  })
+
+  await sc.handleMessage(JSON.stringify({
+    id: 1,
+    type: 'stop'
+  }))
+
+  t.equal(sc.subscriptionIters.size, 0)
+})
+
 test('handles error in send and closes connection', async t => {
   t.plan(1)