From 6237d9224f70332f396ccd90a7acd901d1da1f52 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 17 May 2022 11:38:20 +0200 Subject: [PATCH] fix: added a nice error message when `graphql-ws` is requested but not installed. Moved to a dynamic import instead. Signed-off-by: blam --- .changeset/four-mangos-warn.md | 5 +++++ .../src/create-fetcher/__tests__/lib.spec.ts | 15 +++++++++++++++ .../graphiql-toolkit/src/create-fetcher/lib.ts | 17 ++++++++++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 .changeset/four-mangos-warn.md diff --git a/.changeset/four-mangos-warn.md b/.changeset/four-mangos-warn.md new file mode 100644 index 00000000000..15ef73ccfa0 --- /dev/null +++ b/.changeset/four-mangos-warn.md @@ -0,0 +1,5 @@ +--- +'@graphiql/toolkit': patch +--- + +Move `graphql-ws` dependency to a dynamic import, and add a nice error message when it's not installed diff --git a/packages/graphiql-toolkit/src/create-fetcher/__tests__/lib.spec.ts b/packages/graphiql-toolkit/src/create-fetcher/__tests__/lib.spec.ts index 48d18a7c99b..bc1e5fd0401 100644 --- a/packages/graphiql-toolkit/src/create-fetcher/__tests__/lib.spec.ts +++ b/packages/graphiql-toolkit/src/create-fetcher/__tests__/lib.spec.ts @@ -102,3 +102,18 @@ describe('getWsFetcher', () => { expect(SubscriptionClient.mock.calls).toHaveLength(0); }); }); + +describe('missing graphql-ws dependency', () => { + it('should throw a nice error', () => { + jest.resetModules(); + jest.doMock('graphql-ws', () => { + throw { code: 'MODULE_NOT_FOUND' }; + }); + + expect(() => + createWebsocketsFetcherFromUrl('wss://example.com'), + ).toThrowError( + /You need to install the `graphql-ws` package to use websockets/, + ); + }); +}); diff --git a/packages/graphiql-toolkit/src/create-fetcher/lib.ts b/packages/graphiql-toolkit/src/create-fetcher/lib.ts index f88b385ca6d..1cf6ae4ad29 100644 --- a/packages/graphiql-toolkit/src/create-fetcher/lib.ts +++ b/packages/graphiql-toolkit/src/create-fetcher/lib.ts @@ -1,10 +1,10 @@ import { DocumentNode, visit, GraphQLError } from 'graphql'; import { meros } from 'meros'; import { - createClient, Client, ClientOptions, ExecutionResult, + createClient as createClientType, } from 'graphql-ws'; import { isAsyncIterable, @@ -19,6 +19,10 @@ import type { CreateFetcherOptions, } from './types'; +const errorHasCode = (err: unknown): err is { code: string } => { + return typeof err === 'object' && err !== null && 'code' in err; +}; + /** * Returns true if the name matches a subscription in the AST * @@ -76,6 +80,10 @@ export const createWebsocketsFetcherFromUrl = ( ) => { let wsClient; try { + const { createClient } = require('graphql-ws') as { + createClient: typeof createClientType; + }; + // TODO: defaults? wsClient = createClient({ url, @@ -83,6 +91,13 @@ export const createWebsocketsFetcherFromUrl = ( }); return createWebsocketsFetcherFromClient(wsClient); } catch (err) { + if (errorHasCode(err)) { + if (err.code === 'MODULE_NOT_FOUND') { + throw Error( + 'You need to install the `graphql-ws` package to use websockets', + ); + } + } console.error(`Error creating websocket client for:\n${url}\n\n${err}`); } };