@aws-amplify/pubsub 4.2.9-unstable.9 → 4.2.10-cloud-logging.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +27 -44
  2. package/dist/aws-amplify-pubsub.js +258 -209
  3. package/dist/aws-amplify-pubsub.js.map +1 -1
  4. package/dist/aws-amplify-pubsub.min.js +2 -2
  5. package/dist/aws-amplify-pubsub.min.js.map +1 -1
  6. package/lib/Providers/AWSAppSyncProvider.d.ts +3 -0
  7. package/lib/Providers/AWSAppSyncProvider.js +3 -0
  8. package/lib/Providers/AWSAppSyncProvider.js.map +1 -1
  9. package/lib/Providers/AWSAppSyncRealTimeProvider.d.ts +19 -4
  10. package/lib/Providers/AWSAppSyncRealTimeProvider.js +192 -159
  11. package/lib/Providers/AWSAppSyncRealTimeProvider.js.map +1 -1
  12. package/lib/Providers/AWSIotProvider.d.ts +6 -1
  13. package/lib/Providers/AWSIotProvider.js +3 -2
  14. package/lib/Providers/AWSIotProvider.js.map +1 -1
  15. package/lib/Providers/MqttOverWSProvider.d.ts +14 -11
  16. package/lib/Providers/MqttOverWSProvider.js +17 -10
  17. package/lib/Providers/MqttOverWSProvider.js.map +1 -1
  18. package/lib/Providers/PubSubProvider.d.ts +7 -7
  19. package/lib/Providers/PubSubProvider.js.map +1 -1
  20. package/lib/PubSub.d.ts +6 -6
  21. package/lib/PubSub.js +2 -2
  22. package/lib/PubSub.js.map +1 -1
  23. package/lib/types/Provider.d.ts +3 -3
  24. package/lib/types/PubSub.d.ts +5 -1
  25. package/lib-esm/Providers/AWSAppSyncProvider.d.ts +3 -0
  26. package/lib-esm/Providers/AWSAppSyncProvider.js +3 -0
  27. package/lib-esm/Providers/AWSAppSyncProvider.js.map +1 -1
  28. package/lib-esm/Providers/AWSAppSyncRealTimeProvider.d.ts +19 -4
  29. package/lib-esm/Providers/AWSAppSyncRealTimeProvider.js +192 -159
  30. package/lib-esm/Providers/AWSAppSyncRealTimeProvider.js.map +1 -1
  31. package/lib-esm/Providers/AWSIotProvider.d.ts +6 -1
  32. package/lib-esm/Providers/AWSIotProvider.js +3 -2
  33. package/lib-esm/Providers/AWSIotProvider.js.map +1 -1
  34. package/lib-esm/Providers/MqttOverWSProvider.d.ts +14 -11
  35. package/lib-esm/Providers/MqttOverWSProvider.js +17 -10
  36. package/lib-esm/Providers/MqttOverWSProvider.js.map +1 -1
  37. package/lib-esm/Providers/PubSubProvider.d.ts +7 -7
  38. package/lib-esm/Providers/PubSubProvider.js.map +1 -1
  39. package/lib-esm/PubSub.d.ts +6 -6
  40. package/lib-esm/PubSub.js +2 -2
  41. package/lib-esm/PubSub.js.map +1 -1
  42. package/lib-esm/types/Provider.d.ts +3 -3
  43. package/lib-esm/types/PubSub.d.ts +5 -1
  44. package/package.json +5 -5
  45. package/src/Providers/AWSAppSyncProvider.ts +27 -26
  46. package/src/Providers/AWSAppSyncRealTimeProvider.ts +276 -214
  47. package/src/Providers/AWSIotProvider.ts +10 -1
  48. package/src/Providers/MqttOverWSProvider.ts +52 -33
  49. package/src/Providers/PubSubProvider.ts +8 -8
  50. package/src/PubSub.ts +10 -10
  51. package/src/types/Provider.ts +3 -7
  52. package/src/types/PubSub.ts +6 -1
@@ -15,7 +15,7 @@ import { GraphQLError } from 'graphql';
15
15
  import * as url from 'url';
16
16
  import { v4 as uuid } from 'uuid';
17
17
  import { Buffer } from 'buffer';
18
- import { ProvidertOptions } from '../types';
18
+ import { ProviderOptions } from '../types';
19
19
  import {
20
20
  Logger,
21
21
  Credentials,
@@ -25,18 +25,20 @@ import {
25
25
  USER_AGENT_HEADER,
26
26
  jitteredExponentialRetry,
27
27
  NonRetryableError,
28
+ ICredentials,
28
29
  } from '@aws-amplify/core';
29
30
  import Cache from '@aws-amplify/cache';
30
- import Auth from '@aws-amplify/auth';
31
+ import Auth, { GRAPHQL_AUTH_MODE } from '@aws-amplify/auth';
31
32
  import { AbstractPubSubProvider } from './PubSubProvider';
32
33
  import { CONTROL_MSG } from '../index';
33
34
 
34
35
  const logger = new Logger('AWSAppSyncRealTimeProvider');
35
36
 
36
- const AMPLIFY_SYMBOL = (typeof Symbol !== 'undefined' &&
37
- typeof Symbol.for === 'function'
38
- ? Symbol.for('amplify_default')
39
- : '@@amplify_default') as Symbol;
37
+ const AMPLIFY_SYMBOL = (
38
+ typeof Symbol !== 'undefined' && typeof Symbol.for === 'function'
39
+ ? Symbol.for('amplify_default')
40
+ : '@@amplify_default'
41
+ ) as Symbol;
40
42
 
41
43
  const dispatchApiEvent = (event: string, data: any, message: string) => {
42
44
  Hub.dispatch('api', { event, data, message }, 'PubSub', AMPLIFY_SYMBOL);
@@ -53,7 +55,7 @@ type ObserverQuery = {
53
55
  subscriptionState: SUBSCRIPTION_STATUS;
54
56
  subscriptionReadyCallback?: Function;
55
57
  subscriptionFailedCallback?: Function;
56
- startAckTimeoutId?;
58
+ startAckTimeoutId?: ReturnType<typeof setTimeout>;
57
59
  };
58
60
 
59
61
  enum MESSAGE_TYPES {
@@ -142,14 +144,34 @@ const START_ACK_TIMEOUT = 15000;
142
144
  */
143
145
  const DEFAULT_KEEP_ALIVE_TIMEOUT = 5 * 60 * 1000;
144
146
 
145
- const standardDomainPattern = /^https:\/\/\w{26}\.appsync\-api\.\w{2}(?:(?:\-\w{2,})+)\-\d\.amazonaws.com\/graphql$/i;
147
+ const standardDomainPattern =
148
+ /^https:\/\/\w{26}\.appsync\-api\.\w{2}(?:(?:\-\w{2,})+)\-\d\.amazonaws.com\/graphql$/i;
146
149
 
147
150
  const customDomainPath = '/realtime';
148
151
 
152
+ type GraphqlAuthModes = keyof typeof GRAPHQL_AUTH_MODE;
153
+
154
+ export interface AWSAppSyncRealTimeProviderOptions extends ProviderOptions {
155
+ appSyncGraphqlEndpoint?: string;
156
+ authenticationType?: GraphqlAuthModes;
157
+ query?: string;
158
+ variables?: object;
159
+ apiKey?: string;
160
+ region?: string;
161
+ graphql_headers?: () => {} | (() => Promise<{}>);
162
+ additionalHeaders?: { [key: string]: string };
163
+ }
164
+
165
+ type AWSAppSyncRealTimeAuthInput =
166
+ Partial<AWSAppSyncRealTimeProviderOptions> & {
167
+ canonicalUri: string;
168
+ payload: string;
169
+ };
170
+
149
171
  export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
150
- private awsRealTimeSocket: WebSocket;
172
+ private awsRealTimeSocket?: WebSocket;
151
173
  private socketStatus: SOCKET_STATUS = SOCKET_STATUS.CLOSED;
152
- private keepAliveTimeoutId;
174
+ private keepAliveTimeoutId?: ReturnType<typeof setTimeout>;
153
175
  private keepAliveTimeout = DEFAULT_KEEP_ALIVE_TIMEOUT;
154
176
  private subscriptionObserverMap: Map<string, ObserverQuery> = new Map();
155
177
  private promiseArray: Array<{ res: Function; rej: Function }> = [];
@@ -173,12 +195,12 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
173
195
 
174
196
  subscribe(
175
197
  _topics: string[] | string,
176
- options?: ProvidertOptions
198
+ options?: AWSAppSyncRealTimeProviderOptions
177
199
  ): Observable<any> {
178
- const { appSyncGraphqlEndpoint } = options;
200
+ const appSyncGraphqlEndpoint = options?.appSyncGraphqlEndpoint;
179
201
 
180
202
  return new Observable(observer => {
181
- if (!appSyncGraphqlEndpoint) {
203
+ if (!options || !appSyncGraphqlEndpoint) {
182
204
  observer.error({
183
205
  errors: [
184
206
  {
@@ -195,7 +217,7 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
195
217
  options,
196
218
  observer,
197
219
  subscriptionId,
198
- }).catch(err => {
220
+ }).catch<any>(err => {
199
221
  observer.error({
200
222
  errors: [
201
223
  {
@@ -241,10 +263,15 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
241
263
  return !this.options
242
264
  .aws_appsync_dangerously_connect_to_http_endpoint_for_testing;
243
265
  }
266
+
244
267
  private async _startSubscriptionWithAWSAppSyncRealTime({
245
268
  options,
246
269
  observer,
247
270
  subscriptionId,
271
+ }: {
272
+ options: AWSAppSyncRealTimeProviderOptions;
273
+ observer: ZenObservable.SubscriptionObserver<any>;
274
+ subscriptionId: string;
248
275
  }) {
249
276
  const {
250
277
  appSyncGraphqlEndpoint,
@@ -265,10 +292,10 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
265
292
  // Having a subscription id map will make it simple to forward messages received
266
293
  this.subscriptionObserverMap.set(subscriptionId, {
267
294
  observer,
268
- query,
269
- variables,
295
+ query: query ?? '',
296
+ variables: variables ?? {},
270
297
  subscriptionState,
271
- startAckTimeoutId: null,
298
+ startAckTimeoutId: undefined,
272
299
  });
273
300
 
274
301
  // Preparing payload for subscription message
@@ -314,7 +341,7 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
314
341
  });
315
342
  } catch (err) {
316
343
  logger.debug({ err });
317
- const { message = '' } = err;
344
+ const message = err['message'] ?? '';
318
345
  observer.error({
319
346
  errors: [
320
347
  {
@@ -323,7 +350,6 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
323
350
  ],
324
351
  });
325
352
  observer.complete();
326
-
327
353
  const { subscriptionFailedCallback } =
328
354
  this.subscriptionObserverMap.get(subscriptionId) || {};
329
355
 
@@ -338,17 +364,15 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
338
364
  // E.g.unsubscribe gets invoked prior to finishing WebSocket handshake or START_ACK.
339
365
  // Both subscriptionFailedCallback and subscriptionReadyCallback are used to synchronized this.
340
366
 
341
- const {
342
- subscriptionFailedCallback,
343
- subscriptionReadyCallback,
344
- } = this.subscriptionObserverMap.get(subscriptionId);
367
+ const { subscriptionFailedCallback, subscriptionReadyCallback } =
368
+ this.subscriptionObserverMap.get(subscriptionId) ?? {};
345
369
 
346
370
  // This must be done before sending the message in order to be listening immediately
347
371
  this.subscriptionObserverMap.set(subscriptionId, {
348
372
  observer,
349
373
  subscriptionState,
350
- variables,
351
- query,
374
+ query: query ?? '',
375
+ variables: variables ?? {},
352
376
  subscriptionReadyCallback,
353
377
  subscriptionFailedCallback,
354
378
  startAckTimeoutId: setTimeout(() => {
@@ -361,32 +385,30 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
361
385
  }
362
386
 
363
387
  // Waiting that subscription has been connected before trying to unsubscribe
364
- private async _waitForSubscriptionToBeConnected(subscriptionId) {
365
- const { subscriptionState } = this.subscriptionObserverMap.get(
366
- subscriptionId
367
- );
368
- // This in case unsubscribe is invoked before sending start subscription message
369
- if (subscriptionState === SUBSCRIPTION_STATUS.PENDING) {
370
- return new Promise((res, rej) => {
371
- const {
372
- observer,
373
- subscriptionState,
374
- variables,
375
- query,
376
- } = this.subscriptionObserverMap.get(subscriptionId);
377
- this.subscriptionObserverMap.set(subscriptionId, {
378
- observer,
379
- subscriptionState,
380
- variables,
381
- query,
382
- subscriptionReadyCallback: res,
383
- subscriptionFailedCallback: rej,
388
+ private async _waitForSubscriptionToBeConnected(subscriptionId: string) {
389
+ const subscriptionObserver =
390
+ this.subscriptionObserverMap.get(subscriptionId);
391
+ if (subscriptionObserver) {
392
+ const { subscriptionState } = subscriptionObserver;
393
+ // This in case unsubscribe is invoked before sending start subscription message
394
+ if (subscriptionState === SUBSCRIPTION_STATUS.PENDING) {
395
+ return new Promise((res, rej) => {
396
+ const { observer, subscriptionState, variables, query } =
397
+ subscriptionObserver;
398
+ this.subscriptionObserverMap.set(subscriptionId, {
399
+ observer,
400
+ subscriptionState,
401
+ variables,
402
+ query,
403
+ subscriptionReadyCallback: res,
404
+ subscriptionFailedCallback: rej,
405
+ });
384
406
  });
385
- });
407
+ }
386
408
  }
387
409
  }
388
410
 
389
- private _sendUnsubscriptionMessage(subscriptionId) {
411
+ private _sendUnsubscriptionMessage(subscriptionId: string) {
390
412
  try {
391
413
  if (
392
414
  this.awsRealTimeSocket &&
@@ -407,7 +429,7 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
407
429
  }
408
430
  }
409
431
 
410
- private _removeSubscriptionObserver(subscriptionId) {
432
+ private _removeSubscriptionObserver(subscriptionId: string) {
411
433
  this.subscriptionObserverMap.delete(subscriptionId);
412
434
 
413
435
  // Verifying 1000ms after removing subscription in case there are new subscription unmount/mount
@@ -429,21 +451,28 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
429
451
  setTimeout(this._closeSocketIfRequired.bind(this), 1000);
430
452
  } else {
431
453
  logger.debug('closing WebSocket...');
432
- clearTimeout(this.keepAliveTimeoutId);
454
+ if (this.keepAliveTimeoutId) clearTimeout(this.keepAliveTimeoutId);
433
455
  const tempSocket = this.awsRealTimeSocket;
434
456
  // Cleaning callbacks to avoid race condition, socket still exists
435
- tempSocket.onclose = undefined;
436
- tempSocket.onerror = undefined;
457
+ tempSocket.onclose = null;
458
+ tempSocket.onerror = null;
437
459
  tempSocket.close(1000);
438
- this.awsRealTimeSocket = null;
460
+ this.awsRealTimeSocket = undefined;
439
461
  this.socketStatus = SOCKET_STATUS.CLOSED;
440
462
  }
441
463
  }
442
464
 
443
465
  private _handleIncomingSubscriptionMessage(message: MessageEvent) {
444
- logger.debug(
445
- `subscription message from AWS AppSync RealTime: ${message.data}`
446
- );
466
+ if (message.data && message.data === '{"type":"ka"}') {
467
+ logger.verbose(
468
+ `subscription message from AWS AppSync RealTime: ${message.data}`
469
+ );
470
+ } else {
471
+ logger.debug(
472
+ `subscription message from AWS AppSync RealTime: ${message.data}`
473
+ );
474
+ }
475
+
447
476
  const { id = '', payload, type } = JSON.parse(message.data);
448
477
  const {
449
478
  observer = null,
@@ -454,7 +483,11 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
454
483
  subscriptionFailedCallback,
455
484
  } = this.subscriptionObserverMap.get(id) || {};
456
485
 
457
- logger.debug({ id, observer, query, variables });
486
+ if (!id && !observer && !query && Object.keys(variables).length === 0) {
487
+ logger.verbose({ id, observer, query, variables });
488
+ } else {
489
+ logger.debug({ id, observer, query, variables });
490
+ }
458
491
 
459
492
  if (type === MESSAGE_TYPES.GQL_DATA && payload && payload.data) {
460
493
  if (observer) {
@@ -472,29 +505,31 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
472
505
  if (typeof subscriptionReadyCallback === 'function') {
473
506
  subscriptionReadyCallback();
474
507
  }
475
- clearTimeout(startAckTimeoutId);
508
+ if (startAckTimeoutId) clearTimeout(startAckTimeoutId);
476
509
  dispatchApiEvent(
477
510
  CONTROL_MSG.SUBSCRIPTION_ACK,
478
511
  { query, variables },
479
512
  'Connection established for subscription'
480
513
  );
481
514
  const subscriptionState = SUBSCRIPTION_STATUS.CONNECTED;
482
- this.subscriptionObserverMap.set(id, {
483
- observer,
484
- query,
485
- variables,
486
- startAckTimeoutId: null,
487
- subscriptionState,
488
- subscriptionReadyCallback,
489
- subscriptionFailedCallback,
490
- });
515
+ if (observer) {
516
+ this.subscriptionObserverMap.set(id, {
517
+ observer,
518
+ query,
519
+ variables,
520
+ startAckTimeoutId: undefined,
521
+ subscriptionState,
522
+ subscriptionReadyCallback,
523
+ subscriptionFailedCallback,
524
+ });
525
+ }
491
526
 
492
527
  // TODO: emit event on hub but it requires to store the id first
493
528
  return;
494
529
  }
495
530
 
496
531
  if (type === MESSAGE_TYPES.GQL_CONNECTION_KEEP_ALIVE) {
497
- clearTimeout(this.keepAliveTimeoutId);
532
+ if (this.keepAliveTimeoutId) clearTimeout(this.keepAliveTimeoutId);
498
533
  this.keepAliveTimeoutId = setTimeout(
499
534
  this._errorDisconnect.bind(this, CONTROL_MSG.TIMEOUT_DISCONNECT),
500
535
  this.keepAliveTimeout
@@ -504,30 +539,32 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
504
539
 
505
540
  if (type === MESSAGE_TYPES.GQL_ERROR) {
506
541
  const subscriptionState = SUBSCRIPTION_STATUS.FAILED;
507
- this.subscriptionObserverMap.set(id, {
508
- observer,
509
- query,
510
- variables,
511
- startAckTimeoutId,
512
- subscriptionReadyCallback,
513
- subscriptionFailedCallback,
514
- subscriptionState,
515
- });
542
+ if (observer) {
543
+ this.subscriptionObserverMap.set(id, {
544
+ observer,
545
+ query,
546
+ variables,
547
+ startAckTimeoutId,
548
+ subscriptionReadyCallback,
549
+ subscriptionFailedCallback,
550
+ subscriptionState,
551
+ });
516
552
 
517
- observer.error({
518
- errors: [
519
- {
520
- ...new GraphQLError(
521
- `${CONTROL_MSG.CONNECTION_FAILED}: ${JSON.stringify(payload)}`
522
- ),
523
- },
524
- ],
525
- });
526
- clearTimeout(startAckTimeoutId);
553
+ observer.error({
554
+ errors: [
555
+ {
556
+ ...new GraphQLError(
557
+ `${CONTROL_MSG.CONNECTION_FAILED}: ${JSON.stringify(payload)}`
558
+ ),
559
+ },
560
+ ],
561
+ });
562
+ if (startAckTimeoutId) clearTimeout(startAckTimeoutId);
527
563
 
528
- observer.complete();
529
- if (typeof subscriptionFailedCallback === 'function') {
530
- subscriptionFailedCallback();
564
+ observer.complete();
565
+ if (typeof subscriptionFailedCallback === 'function') {
566
+ subscriptionFailedCallback();
567
+ }
531
568
  }
532
569
  }
533
570
  }
@@ -549,39 +586,42 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
549
586
  this.socketStatus = SOCKET_STATUS.CLOSED;
550
587
  }
551
588
 
552
- private _timeoutStartSubscriptionAck(subscriptionId) {
553
- const { observer, query, variables } =
554
- this.subscriptionObserverMap.get(subscriptionId) || {};
555
- if (!observer) {
556
- return;
557
- }
558
- this.subscriptionObserverMap.set(subscriptionId, {
559
- observer,
560
- query,
561
- variables,
562
- subscriptionState: SUBSCRIPTION_STATUS.FAILED,
563
- });
564
-
565
- if (observer && !observer.closed) {
566
- observer.error({
567
- errors: [
568
- {
569
- ...new GraphQLError(
570
- `Subscription timeout ${JSON.stringify({
571
- query,
572
- variables,
573
- })}`
574
- ),
575
- },
576
- ],
589
+ private _timeoutStartSubscriptionAck(subscriptionId: string) {
590
+ const subscriptionObserver =
591
+ this.subscriptionObserverMap.get(subscriptionId);
592
+ if (subscriptionObserver) {
593
+ const { observer, query, variables } = subscriptionObserver;
594
+ if (!observer) {
595
+ return;
596
+ }
597
+ this.subscriptionObserverMap.set(subscriptionId, {
598
+ observer,
599
+ query,
600
+ variables,
601
+ subscriptionState: SUBSCRIPTION_STATUS.FAILED,
577
602
  });
578
- // Cleanup will be automatically executed
579
- observer.complete();
603
+
604
+ if (observer && !observer.closed) {
605
+ observer.error({
606
+ errors: [
607
+ {
608
+ ...new GraphQLError(
609
+ `Subscription timeout ${JSON.stringify({
610
+ query,
611
+ variables,
612
+ })}`
613
+ ),
614
+ },
615
+ ],
616
+ });
617
+ // Cleanup will be automatically executed
618
+ observer.complete();
619
+ }
620
+ logger.debug(
621
+ 'timeoutStartSubscription',
622
+ JSON.stringify({ query, variables })
623
+ );
580
624
  }
581
- logger.debug(
582
- 'timeoutStartSubscription',
583
- JSON.stringify({ query, variables })
584
- );
585
625
  }
586
626
 
587
627
  private _initializeWebSocketConnection({
@@ -590,7 +630,7 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
590
630
  apiKey,
591
631
  region,
592
632
  additionalHeaders,
593
- }) {
633
+ }: AWSAppSyncRealTimeProviderOptions) {
594
634
  if (this.socketStatus === SOCKET_STATUS.READY) {
595
635
  return;
596
636
  }
@@ -617,17 +657,18 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
617
657
 
618
658
  const payloadQs = Buffer.from(payloadString).toString('base64');
619
659
 
620
- let discoverableEndpoint = appSyncGraphqlEndpoint;
660
+ let discoverableEndpoint = appSyncGraphqlEndpoint ?? '';
621
661
 
622
662
  if (this.isCustomDomain(discoverableEndpoint)) {
623
- discoverableEndpoint = discoverableEndpoint.concat(
624
- customDomainPath
625
- );
663
+ discoverableEndpoint =
664
+ discoverableEndpoint.concat(customDomainPath);
626
665
  } else {
627
- discoverableEndpoint = discoverableEndpoint.replace('appsync-api', 'appsync-realtime-api').replace('gogi-beta', 'grt-beta');
666
+ discoverableEndpoint = discoverableEndpoint
667
+ .replace('appsync-api', 'appsync-realtime-api')
668
+ .replace('gogi-beta', 'grt-beta');
628
669
  }
629
670
 
630
- // Creating websocket url with required query strings
671
+ // Creating websocket url with required query strings
631
672
  const protocol = this.isSSLEnabled ? 'wss://' : 'ws://';
632
673
  discoverableEndpoint = discoverableEndpoint
633
674
  .replace('https://', protocol)
@@ -635,7 +676,7 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
635
676
 
636
677
  const awsRealTimeUrl = `${discoverableEndpoint}?header=${headerQs}&payload=${payloadQs}`;
637
678
 
638
- await this._initializeRetryableHandshake({ awsRealTimeUrl });
679
+ await this._initializeRetryableHandshake(awsRealTimeUrl);
639
680
 
640
681
  this.promiseArray.forEach(({ res }) => {
641
682
  logger.debug('Notifying connection successful');
@@ -652,23 +693,23 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
652
693
  ) {
653
694
  this.awsRealTimeSocket.close(3001);
654
695
  }
655
- this.awsRealTimeSocket = null;
696
+ this.awsRealTimeSocket = undefined;
656
697
  this.socketStatus = SOCKET_STATUS.CLOSED;
657
698
  }
658
699
  }
659
700
  });
660
701
  }
661
702
 
662
- private async _initializeRetryableHandshake({ awsRealTimeUrl }) {
703
+ private async _initializeRetryableHandshake(awsRealTimeUrl: string) {
663
704
  logger.debug(`Initializaling retryable Handshake`);
664
705
  await jitteredExponentialRetry(
665
706
  this._initializeHandshake.bind(this),
666
- [{ awsRealTimeUrl }],
707
+ [awsRealTimeUrl],
667
708
  MAX_DELAY_MS
668
709
  );
669
710
  }
670
711
 
671
- private async _initializeHandshake({ awsRealTimeUrl }) {
712
+ private async _initializeHandshake(awsRealTimeUrl: string) {
672
713
  logger.debug(`Initializing handshake ${awsRealTimeUrl}`);
673
714
  // Because connecting the socket is async, is waiting until connection is open
674
715
  // Step 1: connect websocket
@@ -692,61 +733,66 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
692
733
  // Step 2: wait for ack from AWS AppSyncReaTime after sending init
693
734
  await (() => {
694
735
  return new Promise((res, rej) => {
695
- let ackOk = false;
696
- this.awsRealTimeSocket.onerror = error => {
697
- logger.debug(`WebSocket error ${JSON.stringify(error)}`);
698
- };
699
- this.awsRealTimeSocket.onclose = event => {
700
- logger.debug(`WebSocket closed ${event.reason}`);
701
- rej(new Error(JSON.stringify(event)));
702
- };
703
-
704
- this.awsRealTimeSocket.onmessage = (message: MessageEvent) => {
705
- logger.debug(
706
- `subscription message from AWS AppSyncRealTime: ${message.data} `
707
- );
708
- const data = JSON.parse(message.data);
709
- const {
710
- type,
711
- payload: {
712
- connectionTimeoutMs = DEFAULT_KEEP_ALIVE_TIMEOUT,
713
- } = {},
714
- } = data;
715
- if (type === MESSAGE_TYPES.GQL_CONNECTION_ACK) {
716
- ackOk = true;
717
- this.keepAliveTimeout = connectionTimeoutMs;
718
- this.awsRealTimeSocket.onmessage = this._handleIncomingSubscriptionMessage.bind(
719
- this
736
+ if (this.awsRealTimeSocket) {
737
+ let ackOk = false;
738
+ this.awsRealTimeSocket.onerror = error => {
739
+ logger.debug(`WebSocket error ${JSON.stringify(error)}`);
740
+ };
741
+ this.awsRealTimeSocket.onclose = event => {
742
+ logger.debug(`WebSocket closed ${event.reason}`);
743
+ rej(new Error(JSON.stringify(event)));
744
+ };
745
+
746
+ this.awsRealTimeSocket.onmessage = (message: MessageEvent) => {
747
+ logger.debug(
748
+ `subscription message from AWS AppSyncRealTime: ${message.data} `
720
749
  );
721
- this.awsRealTimeSocket.onerror = err => {
722
- logger.debug(err);
723
- this._errorDisconnect(CONTROL_MSG.CONNECTION_CLOSED);
724
- };
725
- this.awsRealTimeSocket.onclose = event => {
726
- logger.debug(`WebSocket closed ${event.reason}`);
727
- this._errorDisconnect(CONTROL_MSG.CONNECTION_CLOSED);
728
- };
729
- res('Cool, connected to AWS AppSyncRealTime');
730
- return;
731
- }
732
-
733
- if (type === MESSAGE_TYPES.GQL_CONNECTION_ERROR) {
750
+ const data = JSON.parse(message.data);
734
751
  const {
752
+ type,
735
753
  payload: {
736
- errors: [{ errorType = '', errorCode = 0 } = {}] = [],
754
+ connectionTimeoutMs = DEFAULT_KEEP_ALIVE_TIMEOUT,
737
755
  } = {},
738
756
  } = data;
757
+ if (type === MESSAGE_TYPES.GQL_CONNECTION_ACK) {
758
+ ackOk = true;
759
+ if (this.awsRealTimeSocket) {
760
+ this.keepAliveTimeout = connectionTimeoutMs;
761
+ this.awsRealTimeSocket.onmessage =
762
+ this._handleIncomingSubscriptionMessage.bind(this);
763
+ this.awsRealTimeSocket.onerror = err => {
764
+ logger.debug(err);
765
+ this._errorDisconnect(CONTROL_MSG.CONNECTION_CLOSED);
766
+ };
767
+ this.awsRealTimeSocket.onclose = event => {
768
+ logger.debug(`WebSocket closed ${event.reason}`);
769
+ this._errorDisconnect(CONTROL_MSG.CONNECTION_CLOSED);
770
+ };
771
+ }
772
+ res('Cool, connected to AWS AppSyncRealTime');
773
+ return;
774
+ }
775
+
776
+ if (type === MESSAGE_TYPES.GQL_CONNECTION_ERROR) {
777
+ const {
778
+ payload: {
779
+ errors: [{ errorType = '', errorCode = 0 } = {}] = [],
780
+ } = {},
781
+ } = data;
782
+
783
+ rej({ errorType, errorCode });
784
+ }
785
+ };
786
+
787
+ const gqlInit = {
788
+ type: MESSAGE_TYPES.GQL_CONNECTION_INIT,
789
+ };
790
+ this.awsRealTimeSocket.send(JSON.stringify(gqlInit));
791
+
792
+ setTimeout(checkAckOk.bind(this, ackOk), CONNECTION_INIT_TIMEOUT);
793
+ }
739
794
 
740
- rej({ errorType, errorCode });
741
- }
742
- };
743
-
744
- const gqlInit = {
745
- type: MESSAGE_TYPES.GQL_CONNECTION_INIT,
746
- };
747
- this.awsRealTimeSocket.send(JSON.stringify(gqlInit));
748
-
749
- function checkAckOk() {
795
+ function checkAckOk(ackOk: boolean) {
750
796
  if (!ackOk) {
751
797
  rej(
752
798
  new Error(
@@ -755,12 +801,13 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
755
801
  );
756
802
  }
757
803
  }
758
-
759
- setTimeout(checkAckOk.bind(this), CONNECTION_INIT_TIMEOUT);
760
804
  });
761
805
  })();
762
806
  } catch (err) {
763
- const { errorType, errorCode } = err;
807
+ const { errorType, errorCode } = err as {
808
+ errorType: string;
809
+ errorCode: number;
810
+ };
764
811
 
765
812
  if (NON_RETRYABLE_CODES.includes(errorCode)) {
766
813
  throw new NonRetryableError(errorType);
@@ -780,8 +827,10 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
780
827
  apiKey,
781
828
  region,
782
829
  additionalHeaders,
783
- }): Promise<any> {
784
- const headerHandler = {
830
+ }: AWSAppSyncRealTimeProviderOptions): Promise<any> {
831
+ const headerHandler: {
832
+ [key in GraphqlAuthModes]: (AWSAppSyncRealTimeAuthInput) => {};
833
+ } = {
785
834
  API_KEY: this._awsRealTimeApiKeyHeader.bind(this),
786
835
  AWS_IAM: this._awsRealTimeIAMHeader.bind(this),
787
836
  OPENID_CONNECT: this._awsRealTimeOPENIDHeader.bind(this),
@@ -789,29 +838,29 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
789
838
  AWS_LAMBDA: this._customAuthHeader,
790
839
  };
791
840
 
792
- const handler = headerHandler[authenticationType];
793
-
794
- if (typeof handler !== 'function') {
841
+ if (!authenticationType || !headerHandler[authenticationType]) {
795
842
  logger.debug(`Authentication type ${authenticationType} not supported`);
796
843
  return '';
797
- }
844
+ } else {
845
+ const handler = headerHandler[authenticationType];
798
846
 
799
- const { host } = url.parse(appSyncGraphqlEndpoint);
847
+ const { host } = url.parse(appSyncGraphqlEndpoint ?? '');
800
848
 
801
- const result = await handler({
802
- payload,
803
- canonicalUri,
804
- appSyncGraphqlEndpoint,
805
- apiKey,
806
- region,
807
- host,
808
- additionalHeaders,
809
- });
849
+ const result = await handler({
850
+ payload,
851
+ canonicalUri,
852
+ appSyncGraphqlEndpoint,
853
+ apiKey,
854
+ region,
855
+ host,
856
+ additionalHeaders,
857
+ });
810
858
 
811
- return result;
859
+ return result;
860
+ }
812
861
  }
813
862
 
814
- private async _awsRealTimeCUPHeader({ host }) {
863
+ private async _awsRealTimeCUPHeader({ host }: AWSAppSyncRealTimeAuthInput) {
815
864
  const session = await Auth.currentSession();
816
865
  return {
817
866
  Authorization: session.getAccessToken().getJwtToken(),
@@ -819,7 +868,9 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
819
868
  };
820
869
  }
821
870
 
822
- private async _awsRealTimeOPENIDHeader({ host }) {
871
+ private async _awsRealTimeOPENIDHeader({
872
+ host,
873
+ }: AWSAppSyncRealTimeAuthInput) {
823
874
  let token;
824
875
  // backwards compatibility
825
876
  const federatedInfo = await Cache.getItem('federatedInfo');
@@ -840,7 +891,10 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
840
891
  };
841
892
  }
842
893
 
843
- private async _awsRealTimeApiKeyHeader({ apiKey, host }) {
894
+ private async _awsRealTimeApiKeyHeader({
895
+ apiKey,
896
+ host,
897
+ }: AWSAppSyncRealTimeAuthInput) {
844
898
  const dt = new Date();
845
899
  const dtStr = dt.toISOString().replace(/[:\-]|\.\d{3}/g, '');
846
900
 
@@ -856,7 +910,7 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
856
910
  canonicalUri,
857
911
  appSyncGraphqlEndpoint,
858
912
  region,
859
- }) {
913
+ }: AWSAppSyncRealTimeAuthInput) {
860
914
  const endpointInfo = {
861
915
  region,
862
916
  service: 'appsync',
@@ -866,11 +920,16 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
866
920
  if (!credentialsOK) {
867
921
  throw new Error('No credentials');
868
922
  }
869
- const creds = await Credentials.get().then(credentials => ({
870
- secret_key: credentials.secretAccessKey,
871
- access_key: credentials.accessKeyId,
872
- session_token: credentials.sessionToken,
873
- }));
923
+ const creds = await Credentials.get().then((credentials: any) => {
924
+ const { secretAccessKey, accessKeyId, sessionToken } =
925
+ credentials as ICredentials;
926
+
927
+ return {
928
+ secret_key: secretAccessKey,
929
+ access_key: accessKeyId,
930
+ session_token: sessionToken,
931
+ };
932
+ });
874
933
 
875
934
  const request = {
876
935
  url: `${appSyncGraphqlEndpoint}${canonicalUri}`,
@@ -883,8 +942,11 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
883
942
  return signed_params.headers;
884
943
  }
885
944
 
886
- private _customAuthHeader({ host, additionalHeaders }) {
887
- if (!additionalHeaders.Authorization) {
945
+ private _customAuthHeader({
946
+ host,
947
+ additionalHeaders,
948
+ }: AWSAppSyncRealTimeAuthInput) {
949
+ if (!additionalHeaders || !additionalHeaders['Authorization']) {
888
950
  throw new Error('No auth token specified');
889
951
  }
890
952
 
@@ -899,14 +961,14 @@ export class AWSAppSyncRealTimeProvider extends AbstractPubSubProvider {
899
961
  */
900
962
  _ensureCredentials() {
901
963
  return Credentials.get()
902
- .then(credentials => {
964
+ .then((credentials: any) => {
903
965
  if (!credentials) return false;
904
966
  const cred = Credentials.shear(credentials);
905
967
  logger.debug('set credentials for AWSAppSyncRealTimeProvider', cred);
906
968
 
907
969
  return true;
908
970
  })
909
- .catch(err => {
971
+ .catch((err: any) => {
910
972
  logger.warn('ensure credentials error', err);
911
973
  return false;
912
974
  });