@aws-amplify/api-graphql 3.4.12-api-v6-models.b3abc9b.0 → 4.0.0

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 (118) hide show
  1. package/README.md +3 -0
  2. package/lib/GraphQLAPI.d.ts +17 -4
  3. package/lib/GraphQLAPI.js +33 -27
  4. package/lib/Providers/AWSAppSyncRealTimeProvider/index.d.ts +64 -0
  5. package/lib/Providers/AWSAppSyncRealTimeProvider/index.js +690 -0
  6. package/lib/Providers/constants.d.ts +95 -0
  7. package/lib/Providers/constants.js +103 -0
  8. package/lib/index.d.ts +1 -3
  9. package/lib/index.js +6 -10
  10. package/lib/internals/InternalGraphQLAPI.d.ts +11 -34
  11. package/lib/internals/InternalGraphQLAPI.js +219 -345
  12. package/lib/internals/index.d.ts +1 -1
  13. package/lib/internals/index.js +2 -1
  14. package/lib/internals/v6.d.ts +14 -2
  15. package/lib/internals/v6.js +21 -3
  16. package/lib/tsconfig.tsbuildinfo +6813 -0
  17. package/lib/types/PubSub.d.ts +27 -0
  18. package/lib/types/PubSub.js +46 -0
  19. package/lib/types/index.d.ts +119 -12
  20. package/lib/types/index.js +4 -3
  21. package/lib/utils/ConnectionStateMonitor.d.ts +41 -0
  22. package/lib/utils/ConnectionStateMonitor.js +131 -0
  23. package/lib/utils/ReachabilityMonitor/index.d.ts +1 -0
  24. package/lib/utils/ReachabilityMonitor/index.js +6 -0
  25. package/lib/utils/ReachabilityMonitor/index.native.d.ts +1 -0
  26. package/lib/utils/ReachabilityMonitor/index.native.js +8 -0
  27. package/lib/utils/ReconnectionMonitor.d.ts +29 -0
  28. package/lib/utils/ReconnectionMonitor.js +68 -0
  29. package/lib/utils/errors/APIError.d.ts +7 -0
  30. package/lib/utils/errors/APIError.js +18 -0
  31. package/lib/utils/errors/assertValidationError.d.ts +5 -0
  32. package/lib/utils/errors/assertValidationError.js +16 -0
  33. package/lib/utils/errors/index.d.ts +3 -0
  34. package/lib/utils/errors/index.js +11 -0
  35. package/lib/utils/errors/validation.d.ts +7 -0
  36. package/lib/utils/errors/validation.js +25 -0
  37. package/lib/utils/index.d.ts +2 -0
  38. package/lib/utils/index.js +8 -0
  39. package/lib/utils/resolveConfig.d.ts +12 -0
  40. package/lib/utils/resolveConfig.js +22 -0
  41. package/lib/utils/resolveLibraryOptions.d.ts +11 -0
  42. package/lib/utils/resolveLibraryOptions.js +12 -0
  43. package/lib-esm/GraphQLAPI.d.ts +17 -4
  44. package/lib-esm/GraphQLAPI.js +33 -28
  45. package/lib-esm/Providers/AWSAppSyncRealTimeProvider/index.d.ts +64 -0
  46. package/lib-esm/Providers/AWSAppSyncRealTimeProvider/index.js +687 -0
  47. package/lib-esm/Providers/constants.d.ts +95 -0
  48. package/lib-esm/Providers/constants.js +100 -0
  49. package/lib-esm/index.d.ts +1 -3
  50. package/lib-esm/index.js +1 -4
  51. package/lib-esm/internals/InternalGraphQLAPI.d.ts +11 -34
  52. package/lib-esm/internals/InternalGraphQLAPI.js +218 -345
  53. package/lib-esm/internals/index.d.ts +1 -1
  54. package/lib-esm/internals/index.js +1 -2
  55. package/lib-esm/internals/v6.d.ts +14 -2
  56. package/lib-esm/internals/v6.js +18 -2
  57. package/lib-esm/tsconfig.tsbuildinfo +6813 -0
  58. package/lib-esm/types/PubSub.d.ts +27 -0
  59. package/lib-esm/types/PubSub.js +44 -0
  60. package/lib-esm/types/index.d.ts +119 -12
  61. package/lib-esm/types/index.js +2 -3
  62. package/lib-esm/utils/ConnectionStateMonitor.d.ts +41 -0
  63. package/lib-esm/utils/ConnectionStateMonitor.js +128 -0
  64. package/lib-esm/utils/ReachabilityMonitor/index.d.ts +1 -0
  65. package/lib-esm/utils/ReachabilityMonitor/index.js +4 -0
  66. package/lib-esm/utils/ReachabilityMonitor/index.native.d.ts +1 -0
  67. package/lib-esm/utils/ReachabilityMonitor/index.native.js +5 -0
  68. package/lib-esm/utils/ReconnectionMonitor.d.ts +29 -0
  69. package/lib-esm/utils/ReconnectionMonitor.js +65 -0
  70. package/lib-esm/utils/errors/APIError.d.ts +7 -0
  71. package/lib-esm/utils/errors/APIError.js +15 -0
  72. package/lib-esm/utils/errors/assertValidationError.d.ts +5 -0
  73. package/lib-esm/utils/errors/assertValidationError.js +13 -0
  74. package/lib-esm/utils/errors/index.d.ts +3 -0
  75. package/lib-esm/utils/errors/index.js +5 -0
  76. package/lib-esm/utils/errors/validation.d.ts +7 -0
  77. package/lib-esm/utils/errors/validation.js +23 -0
  78. package/lib-esm/utils/index.d.ts +2 -0
  79. package/lib-esm/utils/index.js +4 -0
  80. package/lib-esm/utils/resolveConfig.d.ts +12 -0
  81. package/lib-esm/utils/resolveConfig.js +20 -0
  82. package/lib-esm/utils/resolveLibraryOptions.d.ts +11 -0
  83. package/lib-esm/utils/resolveLibraryOptions.js +10 -0
  84. package/package.json +122 -118
  85. package/src/GraphQLAPI.ts +26 -4
  86. package/src/Providers/AWSAppSyncRealTimeProvider/index.ts +998 -0
  87. package/src/Providers/constants.ts +110 -0
  88. package/src/index.ts +2 -3
  89. package/src/internals/InternalGraphQLAPI.ts +181 -218
  90. package/src/internals/index.ts +1 -1
  91. package/src/internals/v6.ts +34 -2
  92. package/src/types/PubSub.ts +56 -0
  93. package/src/types/index.ts +175 -15
  94. package/src/utils/ConnectionStateMonitor.ts +199 -0
  95. package/src/utils/ReachabilityMonitor/index.native.ts +7 -0
  96. package/src/utils/ReachabilityMonitor/index.ts +4 -0
  97. package/src/utils/ReconnectionMonitor.ts +76 -0
  98. package/src/utils/errors/APIError.ts +21 -0
  99. package/src/utils/errors/assertValidationError.ts +19 -0
  100. package/src/utils/errors/index.ts +6 -0
  101. package/src/utils/errors/validation.ts +26 -0
  102. package/src/utils/index.ts +5 -0
  103. package/src/utils/resolveConfig.ts +35 -0
  104. package/src/utils/resolveLibraryOptions.ts +13 -0
  105. package/lib/.tsbuildinfo +0 -3
  106. package/lib/GraphQLAPI.js.map +0 -1
  107. package/lib/index.js.map +0 -1
  108. package/lib/internals/InternalGraphQLAPI.js.map +0 -1
  109. package/lib/internals/index.js.map +0 -1
  110. package/lib/internals/v6.js.map +0 -1
  111. package/lib/types/index.js.map +0 -1
  112. package/lib-esm/.tsbuildinfo +0 -3
  113. package/lib-esm/GraphQLAPI.js.map +0 -1
  114. package/lib-esm/index.js.map +0 -1
  115. package/lib-esm/internals/InternalGraphQLAPI.js.map +0 -1
  116. package/lib-esm/internals/index.js.map +0 -1
  117. package/lib-esm/internals/v6.js.map +0 -1
  118. package/lib-esm/types/index.js.map +0 -1
@@ -1,7 +1,12 @@
1
1
  // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
  import { GraphQLAPI } from '../GraphQLAPI';
4
- import { GraphQLOptionsV6, GraphQLResponseV6 } from '../types';
4
+ import {
5
+ __amplify,
6
+ V6Client,
7
+ GraphQLOptionsV6,
8
+ GraphQLResponseV6,
9
+ } from '../types';
5
10
 
6
11
  /**
7
12
  * Invokes graphql operations against a graphql service, providing correct input and
@@ -91,6 +96,7 @@ export function graphql<
91
96
  FALLBACK_TYPES = unknown,
92
97
  TYPED_GQL_STRING extends string = string
93
98
  >(
99
+ this: V6Client,
94
100
  options: GraphQLOptionsV6<FALLBACK_TYPES, TYPED_GQL_STRING>,
95
101
  additionalHeaders?: { [key: string]: string }
96
102
  ): GraphQLResponseV6<FALLBACK_TYPES, TYPED_GQL_STRING> {
@@ -99,8 +105,34 @@ export function graphql<
99
105
  * Neither of these can actually be validated at runtime. Hence, we don't perform
100
106
  * any validation or type-guarding here.
101
107
  */
102
- const result = GraphQLAPI.graphql(options, additionalHeaders);
108
+ const result = GraphQLAPI.graphql(
109
+ this[__amplify],
110
+ options,
111
+ additionalHeaders
112
+ );
103
113
  return result as any;
104
114
  }
105
115
 
116
+ /**
117
+ * Cancels an inflight request. Only applicable for graphql queries and mutations
118
+ * @param {any} request - request to cancel
119
+ * @returns - A boolean indicating if the request was cancelled
120
+ */
121
+ export function cancel(
122
+ this: V6Client,
123
+ promise: Promise<any>,
124
+ message?: string
125
+ ): boolean {
126
+ return GraphQLAPI.cancel(promise, message);
127
+ }
128
+
129
+ /**
130
+ * Checks to see if an error thrown is from an api request cancellation
131
+ * @param {any} error - Any error
132
+ * @returns - A boolean indicating if the error was from an api request cancellation
133
+ */
134
+ export function isCancelError(this: V6Client, error: any): boolean {
135
+ return GraphQLAPI.isCancelError(error);
136
+ }
137
+
106
138
  export { GraphQLOptionsV6, GraphQLResponseV6 };
@@ -0,0 +1,56 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Observer } from 'rxjs';
4
+ export interface SubscriptionObserver<T> {
5
+ closed: boolean;
6
+ next(value: T): void;
7
+ error(errorValue: any): void;
8
+ complete(): void;
9
+ }
10
+
11
+ export enum CONTROL_MSG {
12
+ CONNECTION_CLOSED = 'Connection closed',
13
+ CONNECTION_FAILED = 'Connection failed',
14
+ REALTIME_SUBSCRIPTION_INIT_ERROR = 'AppSync Realtime subscription init error',
15
+ SUBSCRIPTION_ACK = 'Subscription ack',
16
+ TIMEOUT_DISCONNECT = 'Timeout disconnect',
17
+ }
18
+
19
+ /** @enum {string} */
20
+ export enum ConnectionState {
21
+ /*
22
+ * The connection is alive and healthy
23
+ */
24
+ Connected = 'Connected',
25
+ /*
26
+ * The connection is alive, but the connection is offline
27
+ */
28
+ ConnectedPendingNetwork = 'ConnectedPendingNetwork',
29
+ /*
30
+ * The connection has been disconnected while in use
31
+ */
32
+ ConnectionDisrupted = 'ConnectionDisrupted',
33
+ /*
34
+ * The connection has been disconnected and the network is offline
35
+ */
36
+ ConnectionDisruptedPendingNetwork = 'ConnectionDisruptedPendingNetwork',
37
+ /*
38
+ * The connection is in the process of connecting
39
+ */
40
+ Connecting = 'Connecting',
41
+ /*
42
+ * The connection is not in use and is being disconnected
43
+ */
44
+ ConnectedPendingDisconnect = 'ConnectedPendingDisconnect',
45
+ /*
46
+ * The connection is not in use and has been disconnected
47
+ */
48
+ Disconnected = 'Disconnected',
49
+ /*
50
+ * The connection is alive, but a keep alive message has been missed
51
+ */
52
+ ConnectedPendingKeepAlive = 'ConnectedPendingKeepAlive',
53
+ }
54
+
55
+ export type PubSubContent = Record<string, unknown>;
56
+ export type PubSubContentObserver = Observer<PubSubContent>;
@@ -1,28 +1,33 @@
1
1
  // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
+ import { AmplifyClassV6, ResourcesConfig } from '@aws-amplify/core';
3
4
  import { Source, DocumentNode, GraphQLError } from 'graphql';
4
5
  export { OperationTypeNode } from 'graphql';
5
- import { GRAPHQL_AUTH_MODE } from '@aws-amplify/auth';
6
- export { GRAPHQL_AUTH_MODE };
7
- import { Observable } from 'zen-observable-ts';
8
- import { AWSAppSyncRealTimeProvider } from '@aws-amplify/pubsub';
6
+ import { Observable } from 'rxjs';
9
7
 
8
+ import {
9
+ GraphQLAuthMode,
10
+ DocumentType,
11
+ } from '@aws-amplify/core/internals/utils';
12
+ import { AmplifyServer } from '@aws-amplify/core/internals/adapter-core';
13
+
14
+ export { CONTROL_MSG, ConnectionState } from './PubSub';
10
15
  /**
11
16
  * Loose/Unknown options for raw GraphQLAPICategory `graphql()`.
12
17
  */
13
18
  export interface GraphQLOptions {
14
19
  query: string | DocumentNode;
15
- variables?: object;
16
- authMode?: keyof typeof GRAPHQL_AUTH_MODE;
20
+ variables?: Record<string, DocumentType>;
21
+ authMode?: GraphQLAuthMode;
17
22
  authToken?: string;
18
23
  /**
19
24
  * @deprecated This property should not be used
20
25
  */
21
- userAgentSuffix?: string; // TODO: remove in v6
26
+ userAgentSuffix?: string;
22
27
  }
23
28
 
24
29
  export interface GraphQLResult<T = object> {
25
- data?: T;
30
+ data: T;
26
31
  errors?: GraphQLError[];
27
32
  extensions?: {
28
33
  [key: string]: any;
@@ -37,6 +42,82 @@ export type GraphQLSubscription<T> = T & {
37
42
  readonly [queryType]: 'subscription';
38
43
  };
39
44
 
45
+ /**
46
+ * Accepts a code generated model type and returns a supertype that
47
+ * can accept return values from the relevant graphql operations.
48
+ *
49
+ * For example:
50
+ *
51
+ * ```typescript
52
+ * import { GraphQLReturnType } from 'aws-amplify/api';
53
+ * import { MyModel } from './API';
54
+ * import { getMyModel } from './graphql/queries';
55
+ *
56
+ * const [item, setItem] = useState<GraphQLReturnType<MyModel>>();
57
+ * setItem(await client.graphql({ query: getMyModel }).data.getMyModel!)
58
+ * ```
59
+ *
60
+ * Trying to assign the result of a `getMyModel` operation directly to a
61
+ * `MyModel` variables won't necessarily work, because normally-required related
62
+ * models might not be part of the selection set.
63
+ *
64
+ * This util simply makes related model properties optional recursively.
65
+ */
66
+ export type GraphQLReturnType<T> = T extends {}
67
+ ? {
68
+ [K in keyof T]?: GraphQLReturnType<T[K]>;
69
+ }
70
+ : T;
71
+
72
+ /**
73
+ * Describes a paged list result from AppSync, which can either
74
+ * live at the top query or property (e.g., related model) level.
75
+ */
76
+ type PagedList<T, TYPENAME> = {
77
+ __typename: TYPENAME;
78
+ nextToken?: string | null | undefined;
79
+ items: Array<T>;
80
+ };
81
+
82
+ /**
83
+ * Recursively looks through a result type and removes nulls and
84
+ * and undefined from `PagedList` types.
85
+ *
86
+ * Although a graphql response might contain empty values in an
87
+ * array, this will only be the case when we also have errors,
88
+ * which will then be *thrown*.
89
+ */
90
+ type WithListsFixed<T> = T extends PagedList<infer IT, infer NAME>
91
+ ? PagedList<Exclude<IT, null | undefined>, NAME>
92
+ : T extends {}
93
+ ? {
94
+ [K in keyof T]: WithListsFixed<T[K]>;
95
+ }
96
+ : T;
97
+
98
+ /**
99
+ * Returns an updated response type to always return a value.
100
+ */
101
+ type NeverEmpty<T> = {
102
+ [K in keyof T]-?: Exclude<WithListsFixed<T[K]>, undefined | null>;
103
+ };
104
+
105
+ /**
106
+ * Replaces all list result types in a query result with types to exclude
107
+ * nulls and undefined from list member unions.
108
+ *
109
+ * If empty members are present, there will also be errors present,
110
+ * and the response will instead be *thrown*.
111
+ */
112
+ type FixedQueryResult<T> = Exclude<
113
+ T[keyof T],
114
+ null | undefined
115
+ > extends PagedList<any, any>
116
+ ? {
117
+ [K in keyof T]-?: WithListsFixed<Exclude<T[K], null | undefined>>;
118
+ }
119
+ : T;
120
+
40
121
  /**
41
122
  * The return value from a `graphql({query})` call when `query` is a subscription.
42
123
  *
@@ -78,8 +159,24 @@ export type GraphqlSubscriptionResult<T> = Observable<
78
159
  * ```
79
160
  */
80
161
  export type GraphqlSubscriptionMessage<T> = {
81
- provider: AWSAppSyncRealTimeProvider;
82
- value: { data?: T };
162
+ data: T;
163
+ };
164
+
165
+ export interface AWSAppSyncRealTimeProviderOptions {
166
+ appSyncGraphqlEndpoint?: string;
167
+ authenticationType?: GraphQLAuthMode;
168
+ query?: string;
169
+ variables?: Record<string, unknown>;
170
+ apiKey?: string;
171
+ region?: string;
172
+ graphql_headers?: () => {} | (() => Promise<{}>);
173
+ additionalHeaders?: { [key: string]: string };
174
+ }
175
+
176
+ export type AWSAppSyncRealTimeProvider = {
177
+ subscribe(
178
+ options?: AWSAppSyncRealTimeProviderOptions
179
+ ): Observable<Record<string, unknown>>;
83
180
  };
84
181
 
85
182
  export enum GraphQLAuthError {
@@ -106,12 +203,12 @@ export interface GraphQLOptionsV6<
106
203
  > {
107
204
  query: TYPED_GQL_STRING | DocumentNode;
108
205
  variables?: GraphQLVariablesV6<FALLBACK_TYPES, TYPED_GQL_STRING>;
109
- authMode?: keyof typeof GRAPHQL_AUTH_MODE;
206
+ authMode?: GraphQLAuthMode;
110
207
  authToken?: string;
111
208
  /**
112
209
  * @deprecated This property should not be used
113
210
  */
114
- userAgentSuffix?: string; // TODO: remove in v6
211
+ userAgentSuffix?: string;
115
212
  }
116
213
 
117
214
  /**
@@ -150,11 +247,11 @@ export type GraphQLResponseV6<
150
247
  FALLBACK_TYPE = unknown,
151
248
  TYPED_GQL_STRING extends string = string
152
249
  > = TYPED_GQL_STRING extends GeneratedQuery<infer IN, infer QUERY_OUT>
153
- ? Promise<GraphQLResult<QUERY_OUT>>
250
+ ? Promise<GraphQLResult<FixedQueryResult<QUERY_OUT>>>
154
251
  : TYPED_GQL_STRING extends GeneratedMutation<infer IN, infer MUTATION_OUT>
155
- ? Promise<GraphQLResult<MUTATION_OUT>>
252
+ ? Promise<GraphQLResult<NeverEmpty<MUTATION_OUT>>>
156
253
  : TYPED_GQL_STRING extends GeneratedSubscription<infer IN, infer SUB_OUT>
157
- ? GraphqlSubscriptionResult<SUB_OUT>
254
+ ? GraphqlSubscriptionResult<NeverEmpty<SUB_OUT>>
158
255
  : FALLBACK_TYPE extends GraphQLQuery<infer T>
159
256
  ? Promise<GraphQLResult<FALLBACK_TYPE>>
160
257
  : FALLBACK_TYPE extends GraphQLSubscription<infer T>
@@ -248,3 +345,66 @@ export type GeneratedSubscription<InputType, OutputType> = string & {
248
345
  __generatedSubscriptionInput: InputType;
249
346
  __generatedSubscriptionOutput: OutputType;
250
347
  };
348
+
349
+ type FilteredKeys<T> = {
350
+ [P in keyof T]: T[P] extends never ? never : P;
351
+ }[keyof T];
352
+ type ExcludeNeverFields<O> = {
353
+ [K in FilteredKeys<O>]: O[K];
354
+ };
355
+
356
+ export const __amplify = Symbol('amplify');
357
+
358
+ export type V6Client<T extends Record<any, any> = never> = ExcludeNeverFields<{
359
+ [__amplify]: AmplifyClassV6;
360
+ graphql: GraphQLMethod;
361
+ cancel: (promise: Promise<any>, message?: string) => boolean;
362
+ isCancelError: (error: any) => boolean;
363
+ }>;
364
+
365
+ export type V6ClientSSR<T extends Record<any, any> = never> =
366
+ ExcludeNeverFields<{
367
+ [__amplify]: AmplifyClassV6;
368
+ graphql: GraphQLMethodSSR;
369
+ cancel: (promise: Promise<any>, message?: string) => boolean;
370
+ isCancelError: (error: any) => boolean;
371
+ }>;
372
+
373
+ export type GraphQLMethod = <
374
+ FALLBACK_TYPES = unknown,
375
+ TYPED_GQL_STRING extends string = string
376
+ >(
377
+ options: GraphQLOptionsV6<FALLBACK_TYPES, TYPED_GQL_STRING>,
378
+ additionalHeaders?:
379
+ | {
380
+ [key: string]: string;
381
+ }
382
+ | undefined
383
+ ) => GraphQLResponseV6<FALLBACK_TYPES, TYPED_GQL_STRING>;
384
+
385
+ export type GraphQLMethodSSR = <
386
+ FALLBACK_TYPES = unknown,
387
+ TYPED_GQL_STRING extends string = string
388
+ >(
389
+ contextSpec: AmplifyServer.ContextSpec,
390
+ options: GraphQLOptionsV6<FALLBACK_TYPES, TYPED_GQL_STRING>,
391
+ additionalHeaders?:
392
+ | {
393
+ [key: string]: string;
394
+ }
395
+ | undefined
396
+ ) => GraphQLResponseV6<FALLBACK_TYPES, TYPED_GQL_STRING>;
397
+
398
+ /**
399
+ * @private
400
+ *
401
+ * The knobs available for configuring `server/generateClient` internally.
402
+ */
403
+ export type ServerClientGenerationParams = {
404
+ amplify:
405
+ | null // null expected when used with `generateServerClient`
406
+ // closure expected with `generateServerClientUsingCookies`
407
+ | ((fn: (amplify: any) => Promise<any>) => Promise<AmplifyClassV6>);
408
+ // global env-sourced config use for retrieving modelIntro
409
+ config: ResourcesConfig;
410
+ };
@@ -0,0 +1,199 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { Observable, Observer, SubscriptionLike, map, filter } from 'rxjs';
5
+ import { ConnectionState } from '../types/PubSub';
6
+ import { ReachabilityMonitor } from './ReachabilityMonitor';
7
+
8
+ // Internal types for tracking different connection states
9
+ type LinkedConnectionState = 'connected' | 'disconnected';
10
+ type LinkedHealthState = 'healthy' | 'unhealthy';
11
+ type LinkedConnectionStates = {
12
+ networkState: LinkedConnectionState;
13
+ connectionState: LinkedConnectionState | 'connecting';
14
+ intendedConnectionState: LinkedConnectionState;
15
+ keepAliveState: LinkedHealthState;
16
+ };
17
+
18
+ export const CONNECTION_CHANGE: {
19
+ [key in
20
+ | 'KEEP_ALIVE_MISSED'
21
+ | 'KEEP_ALIVE'
22
+ | 'CONNECTION_ESTABLISHED'
23
+ | 'CONNECTION_FAILED'
24
+ | 'CLOSING_CONNECTION'
25
+ | 'OPENING_CONNECTION'
26
+ | 'CLOSED'
27
+ | 'ONLINE'
28
+ | 'OFFLINE']: Partial<LinkedConnectionStates>;
29
+ } = {
30
+ KEEP_ALIVE_MISSED: { keepAliveState: 'unhealthy' },
31
+ KEEP_ALIVE: { keepAliveState: 'healthy' },
32
+ CONNECTION_ESTABLISHED: { connectionState: 'connected' },
33
+ CONNECTION_FAILED: {
34
+ intendedConnectionState: 'disconnected',
35
+ connectionState: 'disconnected',
36
+ },
37
+ CLOSING_CONNECTION: { intendedConnectionState: 'disconnected' },
38
+ OPENING_CONNECTION: {
39
+ intendedConnectionState: 'connected',
40
+ connectionState: 'connecting',
41
+ },
42
+ CLOSED: { connectionState: 'disconnected' },
43
+ ONLINE: { networkState: 'connected' },
44
+ OFFLINE: { networkState: 'disconnected' },
45
+ };
46
+
47
+ export class ConnectionStateMonitor {
48
+ /**
49
+ * @private
50
+ */
51
+ private _linkedConnectionState: LinkedConnectionStates;
52
+ private _linkedConnectionStateObservable: Observable<LinkedConnectionStates>;
53
+ private _linkedConnectionStateObserver: Observer<LinkedConnectionStates>;
54
+ private _networkMonitoringSubscription?: SubscriptionLike;
55
+ private _initialNetworkStateSubscription?: SubscriptionLike;
56
+
57
+ constructor() {
58
+ this._networkMonitoringSubscription = undefined;
59
+ this._linkedConnectionState = {
60
+ networkState: 'connected',
61
+ connectionState: 'disconnected',
62
+ intendedConnectionState: 'disconnected',
63
+ keepAliveState: 'healthy',
64
+ };
65
+
66
+ // Attempt to update the state with the current actual network state
67
+ this._initialNetworkStateSubscription = ReachabilityMonitor().subscribe(
68
+ ({ online }) => {
69
+ this.record(
70
+ online ? CONNECTION_CHANGE.ONLINE : CONNECTION_CHANGE.OFFLINE
71
+ );
72
+ this._initialNetworkStateSubscription?.unsubscribe();
73
+ }
74
+ );
75
+
76
+ this._linkedConnectionStateObservable =
77
+ new Observable<LinkedConnectionStates>(connectionStateObserver => {
78
+ connectionStateObserver.next(this._linkedConnectionState);
79
+ this._linkedConnectionStateObserver = connectionStateObserver;
80
+ });
81
+ }
82
+
83
+ /**
84
+ * Turn network state monitoring on if it isn't on already
85
+ */
86
+ private enableNetworkMonitoring() {
87
+ // If no initial network state was discovered, stop trying
88
+ this._initialNetworkStateSubscription?.unsubscribe();
89
+
90
+ // Maintain the network state based on the reachability monitor
91
+ if (this._networkMonitoringSubscription === undefined) {
92
+ this._networkMonitoringSubscription = ReachabilityMonitor().subscribe(
93
+ ({ online }) => {
94
+ this.record(
95
+ online ? CONNECTION_CHANGE.ONLINE : CONNECTION_CHANGE.OFFLINE
96
+ );
97
+ }
98
+ );
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Turn network state monitoring off if it isn't off already
104
+ */
105
+ private disableNetworkMonitoring() {
106
+ this._networkMonitoringSubscription?.unsubscribe();
107
+ this._networkMonitoringSubscription = undefined;
108
+ }
109
+
110
+ /**
111
+ * Get the observable that allows us to monitor the connection state
112
+ *
113
+ * @returns {Observable<ConnectionState>} - The observable that emits ConnectionState updates
114
+ */
115
+ public get connectionStateObservable(): Observable<ConnectionState> {
116
+ let previous: ConnectionState;
117
+
118
+ // The linked state aggregates state changes to any of the network, connection,
119
+ // intendedConnection and keepAliveHealth. Some states will change these independent
120
+ // states without changing the overall connection state.
121
+
122
+ // After translating from linked states to ConnectionState, then remove any duplicates
123
+ return this._linkedConnectionStateObservable
124
+ .pipe(
125
+ map(value => {
126
+ return this.connectionStatesTranslator(value);
127
+ })
128
+ )
129
+ .pipe(
130
+ filter(current => {
131
+ const toInclude = current !== previous;
132
+ previous = current;
133
+ return toInclude;
134
+ })
135
+ );
136
+ }
137
+
138
+ /*
139
+ * Updates local connection state and emits the full state to the observer.
140
+ */
141
+ record(statusUpdates: Partial<LinkedConnectionStates>) {
142
+ // Maintain the network monitor
143
+ if (statusUpdates.intendedConnectionState === 'connected') {
144
+ this.enableNetworkMonitoring();
145
+ } else if (statusUpdates.intendedConnectionState === 'disconnected') {
146
+ this.disableNetworkMonitoring();
147
+ }
148
+
149
+ // Maintain the socket state
150
+ const newSocketStatus = {
151
+ ...this._linkedConnectionState,
152
+ ...statusUpdates,
153
+ };
154
+
155
+ this._linkedConnectionState = { ...newSocketStatus };
156
+
157
+ this._linkedConnectionStateObserver?.next(this._linkedConnectionState);
158
+ }
159
+
160
+ /*
161
+ * Translate the ConnectionState structure into a specific ConnectionState string literal union
162
+ */
163
+ private connectionStatesTranslator({
164
+ connectionState,
165
+ networkState,
166
+ intendedConnectionState,
167
+ keepAliveState,
168
+ }: LinkedConnectionStates): ConnectionState {
169
+ if (connectionState === 'connected' && networkState === 'disconnected')
170
+ return ConnectionState.ConnectedPendingNetwork;
171
+
172
+ if (
173
+ connectionState === 'connected' &&
174
+ intendedConnectionState === 'disconnected'
175
+ )
176
+ return ConnectionState.ConnectedPendingDisconnect;
177
+
178
+ if (
179
+ connectionState === 'disconnected' &&
180
+ intendedConnectionState === 'connected' &&
181
+ networkState === 'disconnected'
182
+ )
183
+ return ConnectionState.ConnectionDisruptedPendingNetwork;
184
+
185
+ if (
186
+ connectionState === 'disconnected' &&
187
+ intendedConnectionState === 'connected'
188
+ )
189
+ return ConnectionState.ConnectionDisrupted;
190
+
191
+ if (connectionState === 'connected' && keepAliveState === 'unhealthy')
192
+ return ConnectionState.ConnectedPendingKeepAlive;
193
+
194
+ // All remaining states directly correspond to the connection state
195
+ if (connectionState === 'connecting') return ConnectionState.Connecting;
196
+ if (connectionState === 'disconnected') return ConnectionState.Disconnected;
197
+ return ConnectionState.Connected;
198
+ }
199
+ }
@@ -0,0 +1,7 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Reachability } from '@aws-amplify/core/internals/utils';
4
+ import { default as NetInfo } from '@react-native-community/netinfo';
5
+
6
+ export const ReachabilityMonitor = () =>
7
+ new Reachability().networkMonitor(NetInfo);
@@ -0,0 +1,4 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Reachability } from '@aws-amplify/core/internals/utils';
4
+ export const ReachabilityMonitor = () => new Reachability().networkMonitor();
@@ -0,0 +1,76 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Observer } from 'rxjs';
4
+ import { RECONNECT_DELAY, RECONNECT_INTERVAL } from '../Providers/constants';
5
+
6
+ export enum ReconnectEvent {
7
+ START_RECONNECT = 'START_RECONNECT',
8
+ HALT_RECONNECT = 'HALT_RECONNECT',
9
+ }
10
+
11
+ /**
12
+ * Captures the reconnect event logic used to determine when to reconnect to PubSub providers.
13
+ * Reconnnect attempts are delayed by 5 seconds to let the interface settle.
14
+ * Attempting to reconnect only once creates unrecoverable states when the network state isn't
15
+ * supported by the browser, so this keeps retrying every minute until halted.
16
+ */
17
+ export class ReconnectionMonitor {
18
+ private reconnectObservers: Observer<void>[] = [];
19
+ private reconnectIntervalId?: ReturnType<typeof setInterval>;
20
+ private reconnectSetTimeoutId?: ReturnType<typeof setTimeout>;
21
+
22
+ /**
23
+ * Add reconnect observer to the list of observers to alert on reconnect
24
+ */
25
+ addObserver(reconnectObserver: Observer<void>) {
26
+ this.reconnectObservers.push(reconnectObserver);
27
+ }
28
+
29
+ /**
30
+ * Given a reconnect event, start the appropriate behavior
31
+ */
32
+ record(event: ReconnectEvent) {
33
+ if (event === ReconnectEvent.START_RECONNECT) {
34
+ // If the reconnection hasn't been started
35
+ if (
36
+ this.reconnectSetTimeoutId === undefined &&
37
+ this.reconnectIntervalId === undefined
38
+ ) {
39
+ this.reconnectSetTimeoutId = setTimeout(() => {
40
+ // Reconnect now
41
+ this._triggerReconnect();
42
+ // Retry reconnect every periodically until it works
43
+ this.reconnectIntervalId = setInterval(() => {
44
+ this._triggerReconnect();
45
+ }, RECONNECT_INTERVAL);
46
+ }, RECONNECT_DELAY);
47
+ }
48
+ }
49
+
50
+ if (event === ReconnectEvent.HALT_RECONNECT) {
51
+ if (this.reconnectIntervalId) {
52
+ clearInterval(this.reconnectIntervalId);
53
+ this.reconnectIntervalId = undefined;
54
+ }
55
+ if (this.reconnectSetTimeoutId) {
56
+ clearTimeout(this.reconnectSetTimeoutId);
57
+ this.reconnectSetTimeoutId = undefined;
58
+ }
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Complete all reconnect observers
64
+ */
65
+ close() {
66
+ this.reconnectObservers.forEach(reconnectObserver => {
67
+ reconnectObserver.complete?.();
68
+ });
69
+ }
70
+
71
+ private _triggerReconnect() {
72
+ this.reconnectObservers.forEach(reconnectObserver => {
73
+ reconnectObserver.next?.();
74
+ });
75
+ }
76
+ }
@@ -0,0 +1,21 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import {
5
+ AmplifyError,
6
+ AmplifyErrorParams,
7
+ } from '@aws-amplify/core/internals/utils';
8
+
9
+ /**
10
+ * @internal
11
+ */
12
+ export class APIError extends AmplifyError {
13
+ constructor(params: AmplifyErrorParams) {
14
+ super(params);
15
+
16
+ // Hack for making the custom error class work when transpiled to es5
17
+ // TODO: Delete the following 2 lines after we change the build target to >= es2015
18
+ this.constructor = APIError;
19
+ Object.setPrototypeOf(this, APIError.prototype);
20
+ }
21
+ }
@@ -0,0 +1,19 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { APIError } from './APIError';
5
+ import { APIValidationErrorCode, validationErrorMap } from './validation';
6
+
7
+ /**
8
+ * @internal
9
+ */
10
+ export function assertValidationError(
11
+ assertion: boolean,
12
+ name: APIValidationErrorCode
13
+ ): asserts assertion {
14
+ const { message, recoverySuggestion } = validationErrorMap[name];
15
+
16
+ if (!assertion) {
17
+ throw new APIError({ name, message, recoverySuggestion });
18
+ }
19
+ }