From 6ae753b71e30e9f341b875e9e40e218ad507f7c5 Mon Sep 17 00:00:00 2001 From: junmin_liu Date: Mon, 25 Jan 2021 10:27:06 -0500 Subject: [PATCH 1/6] FEAT: support graph-ws client for GraphiQL --- package-lock.json | 78 +++-------------------------------- package.json | 1 + src/__tests__/http-test.ts | 30 ++++++++++++++ src/renderGraphiQL.ts | 84 ++++++++++++++++++++++++++++++-------- 4 files changed, 104 insertions(+), 89 deletions(-) diff --git a/package-lock.json b/package-lock.json index 001f567c..222d225f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1003,41 +1003,6 @@ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true }, - "babel-plugin-emotion": { - "version": "10.0.33", - "resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-10.0.33.tgz", - "integrity": "sha512-bxZbTTGz0AJQDHm8k6Rf3RQJ8tX2scsfsRyKVgAbiUPUNIRtlK+7JxP+TAd1kRLABFxe0CFm2VdK4ePkoA9FxQ==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@emotion/hash": "0.8.0", - "@emotion/memoize": "0.7.4", - "@emotion/serialize": "^0.11.16", - "babel-plugin-macros": "^2.0.0", - "babel-plugin-syntax-jsx": "^6.18.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^1.0.5", - "find-root": "^1.1.0", - "source-map": "^0.5.7" - } - }, - "babel-plugin-macros": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", - "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "cosmiconfig": "^6.0.0", - "resolve": "^1.12.0" - } - }, - "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", - "dev": true - }, "backo2": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", @@ -3155,6 +3120,12 @@ "integrity": "sha1-ers6j9nzQV0HFjMU7SNwYceFt1k=", "dev": true }, + "graphql-ws": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-4.1.2.tgz", + "integrity": "sha512-c/iOE4kGW6J5h9hmHWaYvgsjAQacioae3ZXvq3JDuVw8uXo3Tbmky71Fzn0+emSKRaRNL1jQuzYtRqFKge2PIw==", + "dev": true + }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -3608,22 +3579,6 @@ "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==", "dev": true }, - "iterate-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz", - "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==", - "dev": true - }, - "iterate-value": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", - "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", - "dev": true, - "requires": { - "es-get-iterator": "^1.0.2", - "iterate-iterator": "^1.0.1" - } - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5571,27 +5526,6 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, - "styled-system": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/styled-system/-/styled-system-5.1.5.tgz", - "integrity": "sha512-7VoD0o2R3RKzOzPK0jYrVnS8iJdfkKsQJNiLRDjikOpQVqQHns/DXWaPZOH4tIKkhAT7I6wIsy9FWTWh2X3q+A==", - "dev": true, - "requires": { - "@styled-system/background": "^5.1.2", - "@styled-system/border": "^5.1.5", - "@styled-system/color": "^5.1.2", - "@styled-system/core": "^5.1.2", - "@styled-system/flexbox": "^5.1.2", - "@styled-system/grid": "^5.1.2", - "@styled-system/layout": "^5.1.2", - "@styled-system/position": "^5.1.2", - "@styled-system/shadow": "^5.1.2", - "@styled-system/space": "^5.1.2", - "@styled-system/typography": "^5.1.2", - "@styled-system/variant": "^5.1.5", - "object-assign": "^4.1.1" - } - }, "subscriptions-transport-ws": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.5.4.tgz", diff --git a/package.json b/package.json index ef48d894..b01546c7 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "graphiql": "1.0.6", "graphiql-subscriptions-fetcher": "0.0.2", "graphql": "15.4.0", + "graphql-ws": "4.1.2", "mocha": "8.2.1", "multer": "1.4.2", "nyc": "15.1.0", diff --git a/src/__tests__/http-test.ts b/src/__tests__/http-test.ts index 6a2b3218..fc10df70 100644 --- a/src/__tests__/http-test.ts +++ b/src/__tests__/http-test.ts @@ -2015,6 +2015,36 @@ function runTests(server: Server) { // should contain the subscriptionEndpoint url expect(response.text).to.include('ws:\\/\\/localhost'); }); + + it('contains subscriptionEndpoint within GraphiQL with websocketClient option', async () => { + const app = server(); + + app.get( + urlString(), + graphqlHTTP({ + schema: TestSchema, + graphiql: { + subscriptionEndpoint: 'ws://localhost', + websocketClient: 'v1', + }, + }), + ); + + const response = await app + .request() + .get(urlString()) + .set('Accept', 'text/html'); + + expect(response.status).to.equal(200); + expect(response.type).to.equal('text/html'); + // should contain the function to make fetcher using graphql-ws for subscription or non-subscription + expect(response.text).to.include('makeSubscriptionFetcher'); + // should contain graphql-ws browser client + expect(response.text).to.include('graphql-transport-ws'); + + // should contain the subscriptionEndpoint url + expect(response.text).to.include('ws:\\/\\/localhost'); + }); }); describe('Custom validate function', () => { diff --git a/src/renderGraphiQL.ts b/src/renderGraphiQL.ts index df5b0a0c..f870c69c 100644 --- a/src/renderGraphiQL.ts +++ b/src/renderGraphiQL.ts @@ -25,6 +25,13 @@ export interface GraphiQLOptions { * A websocket endpoint for subscription */ subscriptionEndpoint?: string; + + /** + * websocket client option for subscription, defaults to v0 + * v0: subscriptions-transport-ws + * v1: graphql-ws + */ + websocketClient?: string; } // Ensures string values are safe to be used within a - - `; + if (websocketClient === 'v1') { + subscriptionScripts = ` + + `; + } else { + subscriptionScripts = ` + + + `; + } } return `