1
1
/* eslint-disable no-case-declarations */
2
2
/// <reference lib="dom" />
3
- import { print , IntrospectionOptions , DocumentNode , GraphQLResolveInfo , Kind , parse , buildASTSchema } from 'graphql' ;
3
+ import {
4
+ print ,
5
+ IntrospectionOptions ,
6
+ DocumentNode ,
7
+ GraphQLResolveInfo ,
8
+ Kind ,
9
+ parse ,
10
+ buildASTSchema ,
11
+ ExecutionResult ,
12
+ } from 'graphql' ;
4
13
import {
5
14
AsyncExecutor ,
6
15
Executor ,
@@ -17,7 +26,7 @@ import { isWebUri } from 'valid-url';
17
26
import { fetch as crossFetch } from 'cross-fetch' ;
18
27
import { SubschemaConfig } from '@graphql-tools/delegate' ;
19
28
import { introspectSchema , wrapSchema } from '@graphql-tools/wrap' ;
20
- import { createClient } from 'graphql-ws' ;
29
+ import { ClientOptions , createClient } from 'graphql-ws' ;
21
30
import WebSocket from 'isomorphic-ws' ;
22
31
import syncFetch from 'sync-fetch' ;
23
32
import isPromise from 'is-promise' ;
@@ -26,6 +35,7 @@ import FormData from 'form-data';
26
35
import 'eventsource/lib/eventsource-polyfill' ;
27
36
import { Subscription , SubscriptionOptions } from 'sse-z' ;
28
37
import { URL } from 'url' ;
38
+ import { ConnectionParamsOptions , SubscriptionClient as LegacySubscriptionClient } from 'subscriptions-transport-ws' ;
29
39
30
40
export type AsyncFetchFn = typeof import ( 'cross-fetch' ) . fetch ;
31
41
export type SyncFetchFn = ( input : RequestInfo , init ?: RequestInit ) => SyncResponse ;
@@ -86,6 +96,10 @@ export interface LoadFromUrlOptions extends SingleFileOptions, Partial<Introspec
86
96
* Use SSE for subscription instead of WebSocket
87
97
*/
88
98
useSSEForSubscription ?: boolean ;
99
+ /**
100
+ * Use legacy web socket protocol `graphql-ws` instead of the more current standard `graphql-transport-ws`
101
+ */
102
+ useWebSocketLegacyProtocol ?: boolean ;
89
103
/**
90
104
* Additional options to pass to the constructor of the underlying EventSource instance.
91
105
*/
@@ -254,14 +268,19 @@ export class UrlLoader implements DocumentLoader<LoadFromUrlOptions> {
254
268
return executor ;
255
269
}
256
270
257
- buildWSSubscriber ( pointer : string , webSocketImpl : typeof WebSocket ) : Subscriber {
271
+ buildWSSubscriber (
272
+ pointer : string ,
273
+ webSocketImpl : typeof WebSocket ,
274
+ connectionParams : ClientOptions [ 'connectionParams' ]
275
+ ) : Subscriber {
258
276
const WS_URL = switchProtocols ( pointer , {
259
277
https : 'wss' ,
260
278
http : 'ws' ,
261
279
} ) ;
262
280
const subscriptionClient = createClient ( {
263
281
url : WS_URL ,
264
282
webSocketImpl,
283
+ connectionParams,
265
284
} ) ;
266
285
return async ( { document, variables } : { document : DocumentNode ; variables : any } ) => {
267
286
const query = print ( document ) ;
@@ -282,6 +301,33 @@ export class UrlLoader implements DocumentLoader<LoadFromUrlOptions> {
282
301
} ;
283
302
}
284
303
304
+ buildWSLegacySubscriber (
305
+ pointer : string ,
306
+ webSocketImpl : typeof WebSocket ,
307
+ connectionParams : ConnectionParamsOptions
308
+ ) : Subscriber {
309
+ const WS_URL = switchProtocols ( pointer , {
310
+ https : 'wss' ,
311
+ http : 'ws' ,
312
+ } ) ;
313
+ const subscriptionClient = new LegacySubscriptionClient (
314
+ WS_URL ,
315
+ {
316
+ connectionParams,
317
+ } ,
318
+ webSocketImpl
319
+ ) ;
320
+
321
+ return async < TReturn , TArgs > ( { document, variables } : { document : DocumentNode ; variables : TArgs } ) => {
322
+ return observableToAsyncIterable (
323
+ subscriptionClient . request ( {
324
+ query : document ,
325
+ variables,
326
+ } )
327
+ ) as AsyncIterator < ExecutionResult < TReturn > > ;
328
+ } ;
329
+ }
330
+
285
331
buildSSESubscriber ( pointer : string , eventSourceOptions ?: SubscriptionOptions [ 'eventSourceOptions' ] ) : Subscriber {
286
332
return async ( { document, variables } : { document : DocumentNode ; variables : any } ) => {
287
333
const query = print ( document ) ;
@@ -413,7 +459,12 @@ export class UrlLoader implements DocumentLoader<LoadFromUrlOptions> {
413
459
subscriber = this . buildSSESubscriber ( pointer , options . eventSourceOptions ) ;
414
460
} else {
415
461
const webSocketImpl = await this . getWebSocketImpl ( options , asyncImport ) ;
416
- subscriber = this . buildWSSubscriber ( pointer , webSocketImpl ) ;
462
+
463
+ if ( options . useWebSocketLegacyProtocol ) {
464
+ subscriber = this . buildWSLegacySubscriber ( pointer , webSocketImpl , { headers } ) ;
465
+ } else {
466
+ subscriber = this . buildWSSubscriber ( pointer , webSocketImpl , { headers } ) ;
467
+ }
417
468
}
418
469
419
470
return {
@@ -448,7 +499,11 @@ export class UrlLoader implements DocumentLoader<LoadFromUrlOptions> {
448
499
subscriber = this . buildSSESubscriber ( pointer , options . eventSourceOptions ) ;
449
500
} else {
450
501
const webSocketImpl = this . getWebSocketImpl ( options , syncImport ) ;
451
- subscriber = this . buildWSSubscriber ( pointer , webSocketImpl ) ;
502
+ if ( options . useWebSocketLegacyProtocol ) {
503
+ subscriber = this . buildWSLegacySubscriber ( pointer , webSocketImpl , { headers } ) ;
504
+ } else {
505
+ subscriber = this . buildWSSubscriber ( pointer , webSocketImpl , { headers } ) ;
506
+ }
452
507
}
453
508
454
509
return {
0 commit comments