@aws-amplify/core 4.6.2-next.13 → 4.6.2-next.32

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 (209) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/lib/.tsbuildinfo +3 -0
  3. package/lib/Amplify.js +3 -21
  4. package/lib/Amplify.js.map +1 -1
  5. package/lib/ClientDevice/index.js +0 -4
  6. package/lib/ClientDevice/index.js.map +1 -1
  7. package/lib/ClientDevice/reactnative.js +0 -4
  8. package/lib/ClientDevice/reactnative.js.map +1 -1
  9. package/lib/Credentials.js +31 -81
  10. package/lib/Credentials.js.map +1 -1
  11. package/lib/Hub.js +39 -45
  12. package/lib/Hub.js.map +1 -1
  13. package/lib/I18n/index.js +0 -4
  14. package/lib/I18n/index.js.map +1 -1
  15. package/lib/JS.js +2 -27
  16. package/lib/JS.js.map +1 -1
  17. package/lib/Logger/ConsoleLogger.js +8 -38
  18. package/lib/Logger/ConsoleLogger.js.map +1 -1
  19. package/lib/Logger/index.js +2 -4
  20. package/lib/Logger/index.js.map +1 -1
  21. package/lib/OAuthHelper/FacebookOAuth.js +3 -42
  22. package/lib/OAuthHelper/FacebookOAuth.js.map +1 -1
  23. package/lib/OAuthHelper/GoogleOAuth.js +3 -42
  24. package/lib/OAuthHelper/GoogleOAuth.js.map +1 -1
  25. package/lib/Platform/index.js +0 -4
  26. package/lib/Platform/index.js.map +1 -1
  27. package/lib/Platform/version.js +1 -1
  28. package/lib/Platform/version.js.map +1 -1
  29. package/lib/Providers/AWSCloudWatchProvider.js +30 -85
  30. package/lib/Providers/AWSCloudWatchProvider.js.map +1 -1
  31. package/lib/Providers/index.js +2 -4
  32. package/lib/Providers/index.js.map +1 -1
  33. package/lib/RNComponents/reactnative.js +2 -4
  34. package/lib/RNComponents/reactnative.js.map +1 -1
  35. package/lib/ServiceWorker/ServiceWorker.js +0 -4
  36. package/lib/ServiceWorker/ServiceWorker.js.map +1 -1
  37. package/lib/Signer.js +6 -31
  38. package/lib/Signer.js.map +1 -1
  39. package/lib/StorageHelper/index.js +0 -4
  40. package/lib/StorageHelper/index.js.map +1 -1
  41. package/lib/StorageHelper/reactnative.js +2 -8
  42. package/lib/StorageHelper/reactnative.js.map +1 -1
  43. package/lib/UniversalStorage/index.js +2 -4
  44. package/lib/UniversalStorage/index.js.map +1 -1
  45. package/lib/Util/BackgroundProcessManager.js +385 -0
  46. package/lib/Util/BackgroundProcessManager.js.map +1 -0
  47. package/lib/Util/DateUtils.js +2 -17
  48. package/lib/Util/DateUtils.js.map +1 -1
  49. package/lib/Util/Reachability.js +3 -16
  50. package/lib/Util/Reachability.js.map +1 -1
  51. package/lib/Util/Reachability.native.js +2 -4
  52. package/lib/Util/Reachability.native.js.map +1 -1
  53. package/lib/Util/Retry.js +80 -106
  54. package/lib/Util/Retry.js.map +1 -1
  55. package/lib/Util/index.js +6 -7
  56. package/lib/Util/index.js.map +1 -1
  57. package/lib/index.js +12 -13
  58. package/lib/index.js.map +1 -1
  59. package/lib/{Parser.js → parseAWSExports.js} +4 -28
  60. package/lib/parseAWSExports.js.map +1 -0
  61. package/lib-esm/.tsbuildinfo +3 -0
  62. package/lib-esm/Amplify.d.ts +1 -4
  63. package/lib-esm/Amplify.js +2 -20
  64. package/lib-esm/Amplify.js.map +1 -1
  65. package/lib-esm/ClientDevice/index.d.ts +0 -4
  66. package/lib-esm/ClientDevice/index.js +0 -4
  67. package/lib-esm/ClientDevice/index.js.map +1 -1
  68. package/lib-esm/ClientDevice/reactnative.d.ts +0 -7
  69. package/lib-esm/ClientDevice/reactnative.js +0 -4
  70. package/lib-esm/ClientDevice/reactnative.js.map +1 -1
  71. package/lib-esm/Credentials.d.ts +1 -5
  72. package/lib-esm/Credentials.js +2 -52
  73. package/lib-esm/Credentials.js.map +1 -1
  74. package/lib-esm/Hub.d.ts +28 -4
  75. package/lib-esm/Hub.js +34 -40
  76. package/lib-esm/Hub.js.map +1 -1
  77. package/lib-esm/I18n/index.d.ts +0 -4
  78. package/lib-esm/I18n/index.js +0 -4
  79. package/lib-esm/I18n/index.js.map +1 -1
  80. package/lib-esm/JS.d.ts +0 -24
  81. package/lib-esm/JS.js +2 -27
  82. package/lib-esm/JS.js.map +1 -1
  83. package/lib-esm/Logger/ConsoleLogger.js +1 -31
  84. package/lib-esm/Logger/ConsoleLogger.js.map +1 -1
  85. package/lib-esm/Logger/logger-interface.d.ts +0 -4
  86. package/lib-esm/OAuthHelper/FacebookOAuth.d.ts +0 -4
  87. package/lib-esm/OAuthHelper/FacebookOAuth.js +1 -40
  88. package/lib-esm/OAuthHelper/FacebookOAuth.js.map +1 -1
  89. package/lib-esm/OAuthHelper/GoogleOAuth.d.ts +0 -4
  90. package/lib-esm/OAuthHelper/GoogleOAuth.js +1 -40
  91. package/lib-esm/OAuthHelper/GoogleOAuth.js.map +1 -1
  92. package/lib-esm/Platform/index.d.ts +0 -4
  93. package/lib-esm/Platform/index.js +0 -4
  94. package/lib-esm/Platform/index.js.map +1 -1
  95. package/lib-esm/Platform/version.d.ts +1 -1
  96. package/lib-esm/Platform/version.js +1 -1
  97. package/lib-esm/Platform/version.js.map +1 -1
  98. package/lib-esm/Providers/AWSCloudWatchProvider.js +3 -58
  99. package/lib-esm/Providers/AWSCloudWatchProvider.js.map +1 -1
  100. package/lib-esm/ServiceWorker/ServiceWorker.d.ts +0 -4
  101. package/lib-esm/ServiceWorker/ServiceWorker.js +0 -4
  102. package/lib-esm/ServiceWorker/ServiceWorker.js.map +1 -1
  103. package/lib-esm/Signer.d.ts +0 -4
  104. package/lib-esm/Signer.js +1 -26
  105. package/lib-esm/Signer.js.map +1 -1
  106. package/lib-esm/StorageHelper/index.d.ts +0 -4
  107. package/lib-esm/StorageHelper/index.js +0 -4
  108. package/lib-esm/StorageHelper/index.js.map +1 -1
  109. package/lib-esm/StorageHelper/reactnative.d.ts +0 -4
  110. package/lib-esm/StorageHelper/reactnative.js +0 -4
  111. package/lib-esm/StorageHelper/reactnative.js.map +1 -1
  112. package/lib-esm/Util/BackgroundProcessManager.d.ts +204 -0
  113. package/lib-esm/Util/BackgroundProcessManager.js +383 -0
  114. package/lib-esm/Util/BackgroundProcessManager.js.map +1 -0
  115. package/lib-esm/Util/DateUtils.js +1 -16
  116. package/lib-esm/Util/DateUtils.js.map +1 -1
  117. package/lib-esm/Util/Reachability.js +1 -11
  118. package/lib-esm/Util/Reachability.js.map +1 -1
  119. package/lib-esm/Util/Retry.d.ts +2 -2
  120. package/lib-esm/Util/Retry.js +77 -103
  121. package/lib-esm/Util/Retry.js.map +1 -1
  122. package/lib-esm/Util/index.d.ts +1 -0
  123. package/lib-esm/Util/index.js +1 -0
  124. package/lib-esm/Util/index.js.map +1 -1
  125. package/lib-esm/index.d.ts +2 -2
  126. package/lib-esm/index.js +2 -2
  127. package/lib-esm/index.js.map +1 -1
  128. package/lib-esm/parseAWSExports.d.ts +2 -0
  129. package/lib-esm/{Parser.js → parseAWSExports.js} +3 -27
  130. package/lib-esm/parseAWSExports.js.map +1 -0
  131. package/lib-esm/types/types.d.ts +3 -0
  132. package/package.json +10 -3
  133. package/src/Amplify.ts +1 -5
  134. package/src/ClientDevice/index.ts +0 -5
  135. package/src/ClientDevice/reactnative.ts +0 -5
  136. package/src/Credentials.ts +13 -19
  137. package/src/Hub.ts +38 -11
  138. package/src/I18n/index.ts +0 -5
  139. package/src/JS.ts +4 -25
  140. package/src/Logger/logger-interface.ts +0 -5
  141. package/src/OAuthHelper/FacebookOAuth.ts +0 -5
  142. package/src/OAuthHelper/GoogleOAuth.ts +0 -5
  143. package/src/Platform/index.ts +0 -5
  144. package/src/Platform/version.ts +1 -1
  145. package/src/Providers/AWSCloudWatchProvider.ts +2 -2
  146. package/src/ServiceWorker/ServiceWorker.ts +1 -6
  147. package/src/Signer.ts +0 -5
  148. package/src/StorageHelper/index.ts +0 -5
  149. package/src/StorageHelper/reactnative.ts +0 -5
  150. package/src/Util/BackgroundProcessManager.ts +449 -0
  151. package/src/Util/Retry.ts +66 -31
  152. package/src/Util/index.ts +1 -0
  153. package/src/index.ts +2 -2
  154. package/src/{Parser.ts → parseAWSExports.ts} +1 -13
  155. package/src/types/types.ts +3 -0
  156. package/build.js +0 -5
  157. package/dist/aws-amplify-core.js +0 -43156
  158. package/dist/aws-amplify-core.js.map +0 -1
  159. package/dist/aws-amplify-core.min.js +0 -32
  160. package/dist/aws-amplify-core.min.js.map +0 -1
  161. package/index.js +0 -7
  162. package/lib/Amplify.d.ts +0 -31
  163. package/lib/ClientDevice/android.d.ts +0 -5
  164. package/lib/ClientDevice/browser.d.ts +0 -25
  165. package/lib/ClientDevice/index.d.ts +0 -27
  166. package/lib/ClientDevice/ios.d.ts +0 -7
  167. package/lib/ClientDevice/reactnative.d.ts +0 -14
  168. package/lib/Credentials.d.ts +0 -51
  169. package/lib/Errors.d.ts +0 -2
  170. package/lib/Hub.d.ts +0 -31
  171. package/lib/I18n/I18n.d.ts +0 -59
  172. package/lib/I18n/index.d.ts +0 -53
  173. package/lib/I18n/types.d.ts +0 -3
  174. package/lib/JS.d.ts +0 -56
  175. package/lib/Logger/ConsoleLogger.d.ts +0 -80
  176. package/lib/Logger/index.d.ts +0 -1
  177. package/lib/Logger/logger-interface.d.ts +0 -12
  178. package/lib/OAuthHelper/FacebookOAuth.d.ts +0 -10
  179. package/lib/OAuthHelper/GoogleOAuth.d.ts +0 -10
  180. package/lib/OAuthHelper/index.d.ts +0 -4
  181. package/lib/Parser.d.ts +0 -12
  182. package/lib/Parser.js.map +0 -1
  183. package/lib/Platform/index.d.ts +0 -11
  184. package/lib/Platform/version.d.ts +0 -1
  185. package/lib/Providers/AWSCloudWatchProvider.d.ts +0 -34
  186. package/lib/Providers/index.d.ts +0 -1
  187. package/lib/RNComponents/index.d.ts +0 -5
  188. package/lib/RNComponents/reactnative.d.ts +0 -3
  189. package/lib/ServiceWorker/ServiceWorker.d.ts +0 -72
  190. package/lib/ServiceWorker/index.d.ts +0 -13
  191. package/lib/Signer.d.ts +0 -45
  192. package/lib/StorageHelper/index.d.ts +0 -45
  193. package/lib/StorageHelper/reactnative.d.ts +0 -17
  194. package/lib/UniversalStorage/index.d.ts +0 -23
  195. package/lib/Util/Constants.d.ts +0 -8
  196. package/lib/Util/DateUtils.d.ts +0 -7
  197. package/lib/Util/Mutex.d.ts +0 -45
  198. package/lib/Util/Reachability.d.ts +0 -13
  199. package/lib/Util/Reachability.native.d.ts +0 -11
  200. package/lib/Util/Retry.d.ts +0 -21
  201. package/lib/Util/StringUtils.d.ts +0 -2
  202. package/lib/Util/index.d.ts +0 -6
  203. package/lib/constants.d.ts +0 -6
  204. package/lib/index.d.ts +0 -30
  205. package/lib/types/index.d.ts +0 -1
  206. package/lib/types/types.d.ts +0 -43
  207. package/lib-esm/Parser.d.ts +0 -12
  208. package/lib-esm/Parser.js.map +0 -1
  209. package/webpack.config.dev.js +0 -6
@@ -91,8 +91,3 @@ export class FacebookOAuth {
91
91
  });
92
92
  }
93
93
  }
94
-
95
- /**
96
- * @deprecated use named import
97
- */
98
- export default FacebookOAuth;
@@ -102,8 +102,3 @@ export class GoogleOAuth {
102
102
  });
103
103
  }
104
104
  }
105
-
106
- /**
107
- * @deprecated use named import
108
- */
109
- export default GoogleOAuth;
@@ -38,8 +38,3 @@ if (typeof navigator !== 'undefined' && navigator.product) {
38
38
  export const getAmplifyUserAgent = (content?: string) => {
39
39
  return `${Platform.userAgent}${content ? content : ''}`;
40
40
  };
41
-
42
- /**
43
- * @deprecated use named import
44
- */
45
- export default Platform;
@@ -1,2 +1,2 @@
1
1
  // generated by genversion
2
- export const version = '4.7.6';
2
+ export const version = '4.7.10';
@@ -43,7 +43,7 @@ import {
43
43
  import { Credentials } from '../..';
44
44
  import { ConsoleLogger as Logger } from '../Logger';
45
45
  import { getAmplifyUserAgent } from '../Platform';
46
- import { parseMobileHubConfig } from '../Parser';
46
+ import { parseAWSExports } from '../parseAWSExports';
47
47
  import {
48
48
  AWS_CLOUDWATCH_BASE_BUFFER_SIZE,
49
49
  AWS_CLOUDWATCH_CATEGORY,
@@ -96,7 +96,7 @@ class AWSCloudWatchProvider implements LoggingProvider {
96
96
  const conf = Object.assign(
97
97
  {},
98
98
  this._config,
99
- parseMobileHubConfig(config).Logging,
99
+ parseAWSExports(config).Logging,
100
100
  config
101
101
  );
102
102
  this._config = conf;
@@ -42,7 +42,7 @@ export class ServiceWorkerClass {
42
42
  // The AWS Amplify logger
43
43
  private _logger: Logger = new Logger('ServiceWorker');
44
44
 
45
- constructor() { }
45
+ constructor() {}
46
46
 
47
47
  /**
48
48
  * Get the currently active service worker
@@ -202,8 +202,3 @@ export class ServiceWorkerClass {
202
202
  });
203
203
  }
204
204
  }
205
-
206
- /**
207
- * @deprecated use named import
208
- */
209
- export default ServiceWorkerClass;
package/src/Signer.ts CHANGED
@@ -439,8 +439,3 @@ export class Signer {
439
439
  return result;
440
440
  }
441
441
  }
442
-
443
- /**
444
- * @deprecated use per-function import
445
- */
446
- export default Signer;
@@ -81,8 +81,3 @@ export class StorageHelper {
81
81
  return this.storageWindow;
82
82
  }
83
83
  }
84
-
85
- /**
86
- * @deprecated use named import
87
- */
88
- export default StorageHelper;
@@ -110,8 +110,3 @@ export class StorageHelper {
110
110
  return this.storageWindow;
111
111
  }
112
112
  }
113
-
114
- /**
115
- * @deprecated use named import
116
- */
117
- export default StorageHelper;
@@ -0,0 +1,449 @@
1
+ /**
2
+ * @private For internal Amplify use.
3
+ *
4
+ * Creates a new scope for promises, observables, and other types of work or
5
+ * processes that may be running in the background. This manager provides
6
+ * an singular entrypoint to request termination and await completion.
7
+ *
8
+ * As work completes on its own prior to close, the manager removes them
9
+ * from the registry to avoid holding references to completed jobs.
10
+ */
11
+ export class BackgroundProcessManager {
12
+ /**
13
+ * A string indicating whether the manager is accepting new work ("Open"),
14
+ * waiting for work to complete ("Closing"), or fully done with all
15
+ * submitted work and *not* accepting new jobs ("Closed").
16
+ */
17
+ private _state = BackgroundProcessManagerState.Open;
18
+
19
+ private _closingPromise: Promise<PromiseSettledResult<any>[]> | undefined;
20
+
21
+ /**
22
+ * The list of outstanding jobs we'll need to wait for upon `close()`
23
+ */
24
+ private jobs = new Set<JobEntry>();
25
+
26
+ /**
27
+ * Creates a new manager for promises, observables, and other types
28
+ * of work that may be running in the background. This manager provides
29
+ * a centralized mechanism to request termination and await completion.
30
+ */
31
+ constructor() {}
32
+
33
+ /**
34
+ * Executes an async `job` function, passing the return value through to
35
+ * the caller, registering it as a running job in the manager. When the
36
+ * manager *closes*, it will `await` the job.
37
+ *
38
+ * @param job The function to execute.
39
+ * @param description Optional description to help identify pending jobs.
40
+ * @returns The return value from the given function.
41
+ */
42
+ add<T>(job: () => Promise<T>, description?: string): Promise<T>;
43
+
44
+ /**
45
+ * Executes an async `job` function, passing the return value through to
46
+ * the caller, registering it as a running job in the manager. When the
47
+ * manager *closes*, it will request termination by resolving the
48
+ * provided `onTerminate` promise. It will then `await` the job, so it is
49
+ * important that the job still `resolve()` or `reject()` when responding
50
+ * to a termination request.
51
+ *
52
+ * @param job The function to execute.
53
+ * @param description Optional description to help identify pending jobs.
54
+ * @returns The return value from the given function.
55
+ */
56
+ add<T>(
57
+ job: (onTerminate: Promise<void>) => Promise<T>,
58
+ description?: string
59
+ ): Promise<T>;
60
+
61
+ /**
62
+ * Create a no-op job, registers it with the manager, and returns hooks
63
+ * to the caller to signal the job's completion and respond to termination
64
+ * requests.
65
+ *
66
+ * When the manager closes, the no-op job will be `await`-ed, so its
67
+ * important to always `resolve()` or `reject()` when done responding to an
68
+ * `onTerminate` signal.
69
+ * @param description Optional description to help identify pending jobs.
70
+ * @returns Job promise hooks + onTerminate signaling promise
71
+ */
72
+ add(description?: string): {
73
+ resolve: (value?: unknown) => void;
74
+ reject: (reason?: any) => void;
75
+ onTerminate: Promise<void>;
76
+ };
77
+
78
+ /**
79
+ * Adds another job manager to await on at the time of closing. the inner
80
+ * manager's termination is signaled when this manager's `close()` is
81
+ * called for.
82
+ *
83
+ * @param job The inner job manager to await.
84
+ * @param description Optional description to help identify pending jobs.
85
+ */
86
+ add(job: BackgroundProcessManager, description?: string);
87
+
88
+ add(jobOrDescription?, optionalDescription?) {
89
+ let job;
90
+ let description: string;
91
+
92
+ if (typeof jobOrDescription === 'string') {
93
+ job = undefined;
94
+ description = jobOrDescription;
95
+ } else {
96
+ job = jobOrDescription;
97
+ description = optionalDescription;
98
+ }
99
+
100
+ const error = this.closedFailure(description);
101
+ if (error) return error;
102
+
103
+ if (job === undefined) {
104
+ return this.addHook(description);
105
+ } else if (typeof job === 'function') {
106
+ return this.addFunction(job, description);
107
+ } else if (job instanceof BackgroundProcessManager) {
108
+ return this.addManager(job, description);
109
+ } else {
110
+ throw new Error(
111
+ 'If `job` is provided, it must be an Observable, Function, or BackgroundProcessManager.'
112
+ );
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Adds a **cleaner** function that doesn't immediately get executed.
118
+ * Instead, the caller gets a **terminate** function back. The *cleaner* is
119
+ * invoked only once the mananger *closes* or the returned **terminate**
120
+ * function is called.
121
+ *
122
+ * @param clean The cleanup function.
123
+ * @param description Optional description to help identify pending jobs.
124
+ * @returns A terminate function.
125
+ */
126
+ addCleaner<T>(
127
+ clean: () => Promise<T>,
128
+ description?: string
129
+ ): () => Promise<void> {
130
+ const { resolve, onTerminate } = this.addHook(description);
131
+
132
+ const proxy = async () => {
133
+ await clean();
134
+ resolve();
135
+ };
136
+
137
+ onTerminate.then(proxy);
138
+
139
+ return proxy;
140
+ }
141
+
142
+ private addFunction<T>(
143
+ job: () => Promise<T>,
144
+ description?: string
145
+ ): Promise<T>;
146
+ private addFunction<T>(
147
+ job: (onTerminate: Promise<void>) => Promise<T>,
148
+ description?: string
149
+ ): Promise<T>;
150
+ private addFunction(job, description) {
151
+ // the function we call when we want to try to terminate this job.
152
+ let terminate;
153
+
154
+ // the promise the job can opt into listening to for termination.
155
+ const onTerminate = new Promise(resolve => {
156
+ terminate = resolve;
157
+ });
158
+
159
+ // finally! start the job.
160
+ const jobResult = job(onTerminate);
161
+
162
+ // depending on what the job gives back, register the result
163
+ // so we can monitor for completion.
164
+ if (typeof jobResult?.then === 'function') {
165
+ this.registerPromise(jobResult, terminate, description);
166
+ }
167
+
168
+ // At the end of the day, or you know, method call, it doesn't matter
169
+ // what the return value is at all; we just pass it through to the
170
+ // caller.
171
+ return jobResult;
172
+ }
173
+
174
+ private addManager(manager: BackgroundProcessManager, description?: string) {
175
+ this.addCleaner(async () => await manager.close(), description);
176
+ }
177
+
178
+ /**
179
+ * Creates and registers a fabricated job for processes that need to operate
180
+ * with callbacks/hooks. The returned `resolve` and `reject`
181
+ * functions can be used to signal the job is done successfully or not.
182
+ * The returned `onTerminate` is a promise that will resolve when the
183
+ * manager is requesting the termination of the job.
184
+ *
185
+ * @param description Optional description to help identify pending jobs.
186
+ * @returns `{ resolve, reject, onTerminate }`
187
+ */
188
+ private addHook(description?: string) {
189
+ // the resolve/reject functions we'll provide to the caller to signal
190
+ // the state of the job.
191
+ let resolve!: (value?: unknown) => void;
192
+ let reject!: (reason?: any) => void;
193
+
194
+ // the underlying promise we'll use to manage it, pretty much like
195
+ // any other promise.
196
+ const promise = new Promise((res, rej) => {
197
+ resolve = res;
198
+ reject = rej;
199
+ });
200
+
201
+ // the function we call when we want to try to terminate this job.
202
+ let terminate;
203
+
204
+ // the promise the job can opt into listening to for termination.
205
+ const onTerminate = new Promise(resolveTerminate => {
206
+ terminate = resolveTerminate;
207
+ });
208
+
209
+ this.registerPromise(promise, terminate, description);
210
+
211
+ return {
212
+ resolve,
213
+ reject,
214
+ onTerminate,
215
+ };
216
+ }
217
+
218
+ /**
219
+ * Adds a Promise based job to the list of jobs for monitoring and listens
220
+ * for either a success or failure, upon which the job is considered "done"
221
+ * and removed from the registry.
222
+ *
223
+ * @param promise A promise that is on its way to being returned to a
224
+ * caller, which needs to be tracked as a background job.
225
+ * @param terminate The termination function to register, which can be
226
+ * invoked to request the job stop.
227
+ * @param description Optional description to help identify pending jobs.
228
+ */
229
+ private registerPromise<T extends Promise<any>>(
230
+ promise: T,
231
+ terminate: () => void,
232
+ description?: string
233
+ ) {
234
+ const jobEntry = { promise, terminate, description };
235
+ this.jobs.add(jobEntry);
236
+
237
+ // in all of my testing, it is safe to multi-subscribe to a promise.
238
+ // so, rather than create another layer of promising, we're just going
239
+ // to hook into the promise we already have, and when it's done
240
+ // (successfully or not), we no longer need to wait for it upon close.
241
+
242
+ //
243
+ // sorry this is a bit hand-wavy:
244
+ //
245
+ // i believe we use `.then` and `.catch` instead of `.finally` because
246
+ // `.finally` is invoked in a different order in the sequence, and this
247
+ // breaks assumptions throughout and causes failures.
248
+ promise
249
+ .then(() => {
250
+ this.jobs.delete(jobEntry);
251
+ })
252
+ .catch(() => {
253
+ this.jobs.delete(jobEntry);
254
+ });
255
+ }
256
+
257
+ /**
258
+ * The number of jobs being waited on.
259
+ *
260
+ * We don't use this for anything. It's just informational for the caller,
261
+ * and can be used in logging and testing.
262
+ *
263
+ * @returns the number of jobs.
264
+ */
265
+ get length() {
266
+ return this.jobs.size;
267
+ }
268
+
269
+ /**
270
+ * The execution state of the manager. One of:
271
+ *
272
+ * 1. "Open" -> Accepting new jobs
273
+ * 1. "Closing" -> Not accepting new work. Waiting for jobs to complete.
274
+ * 1. "Closed" -> Not accepting new work. All submitted jobs are complete.
275
+ */
276
+ get state() {
277
+ return this._state;
278
+ }
279
+
280
+ /**
281
+ * The registered `description` of all still-pending jobs.
282
+ *
283
+ * @returns descriptions as an array.
284
+ */
285
+ get pending() {
286
+ return Array.from(this.jobs).map(job => job.description);
287
+ }
288
+
289
+ /**
290
+ * Whether the manager is accepting new jobs.
291
+ */
292
+ get isOpen() {
293
+ return this._state === BackgroundProcessManagerState.Open;
294
+ }
295
+
296
+ /**
297
+ * Whether the manager is rejecting new work, but still waiting for
298
+ * submitted work to complete.
299
+ */
300
+ get isClosing() {
301
+ return this._state === BackgroundProcessManagerState.Closing;
302
+ }
303
+
304
+ /**
305
+ * Whether the manager is rejecting work and done waiting for submitted
306
+ * work to complete.
307
+ */
308
+ get isClosed() {
309
+ return this._state === BackgroundProcessManagerState.Closed;
310
+ }
311
+
312
+ private closedFailure(description: string) {
313
+ if (!this.isOpen) {
314
+ return Promise.reject(
315
+ new BackgroundManagerNotOpenError(
316
+ [
317
+ `The manager is ${this.state}.`,
318
+ `You tried to add "${description}".`,
319
+ `Pending jobs: [\n${this.pending
320
+ .map(t => ' ' + t)
321
+ .join(',\n')}\n]`,
322
+ ].join('\n')
323
+ )
324
+ );
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Signals jobs to stop (for those that accept interruptions) and waits
330
+ * for confirmation that jobs have stopped.
331
+ *
332
+ * This immediately puts the manager into a closing state and just begins
333
+ * to reject new work. After all work in the manager is complete, the
334
+ * manager goes into a `Completed` state and `close()` returns.
335
+ *
336
+ * This call is idempotent.
337
+ *
338
+ * If the manager is already closing or closed, `finalCleaup` is not executed.
339
+ *
340
+ * @param onClosed
341
+ * @returns The settled results of each still-running job's promise. If the
342
+ * manager is already closed, this will contain the results as of when the
343
+ * manager's `close()` was called in an `Open` state.
344
+ */
345
+ async close() {
346
+ if (this.isOpen) {
347
+ this._state = BackgroundProcessManagerState.Closing;
348
+ for (const job of Array.from(this.jobs)) {
349
+ try {
350
+ job.terminate();
351
+ } catch (error) {
352
+ // Due to potential races with a job's natural completion, it's
353
+ // reasonable to expect the termination call to fail. Hence,
354
+ // not logging as an error.
355
+ console.warn(
356
+ `Failed to send termination signal to job. Error: ${error.message}`,
357
+ job
358
+ );
359
+ }
360
+ }
361
+
362
+ // Use `allSettled()` because we want to wait for all to finish. We do
363
+ // not want to stop waiting if there is a failure.
364
+ this._closingPromise = Promise.allSettled(
365
+ Array.from(this.jobs).map(j => j.promise)
366
+ );
367
+
368
+ await this._closingPromise;
369
+ this._state = BackgroundProcessManagerState.Closed;
370
+ }
371
+
372
+ return this._closingPromise as any;
373
+ }
374
+
375
+ /**
376
+ * Signals the manager to start accepting work (again) and returns once
377
+ * the manager is ready to do so.
378
+ *
379
+ * If the state is already `Open`, this call is a no-op.
380
+ *
381
+ * If the state is `Closed`, this call simply updates state and returns.
382
+ *
383
+ * If the state is `Closing`, this call waits for completion before it
384
+ * updates the state and returns.
385
+ */
386
+ async open() {
387
+ if (this.isClosing) {
388
+ await this.close();
389
+ }
390
+
391
+ this._state = BackgroundProcessManagerState.Open;
392
+ }
393
+ }
394
+
395
+ /**
396
+ *
397
+ */
398
+ export class BackgroundManagerNotOpenError extends Error {
399
+ constructor(message: string) {
400
+ super(`BackgroundManagerNotOpenError: ${message}`);
401
+ }
402
+ }
403
+
404
+ /**
405
+ * All possible states a `BackgroundProcessManager` instance can be in.
406
+ */
407
+ export enum BackgroundProcessManagerState {
408
+ /**
409
+ * Accepting new jobs.
410
+ */
411
+ Open = 'Open',
412
+
413
+ /**
414
+ * Not accepting new jobs. Waiting for submitted jobs to complete.
415
+ */
416
+ Closing = 'Closing',
417
+
418
+ /**
419
+ * Not accepting new jobs. All submitted jobs are complete.
420
+ */
421
+ Closed = 'Closed',
422
+ }
423
+
424
+ /**
425
+ * Completely internal to `BackgroundProcessManager`, and describes the structure of
426
+ * an entry in the jobs registry.
427
+ */
428
+ type JobEntry = {
429
+ /**
430
+ * The underlying promise provided by the job function to wait for.
431
+ */
432
+ promise: Promise<any>;
433
+
434
+ /**
435
+ * Request the termination of the job.
436
+ */
437
+ terminate: () => void;
438
+
439
+ /**
440
+ * An object provided by the caller that can be used to identify the description
441
+ * of the job, which can otherwise be unclear from the `promise` and
442
+ * `terminate` function. The `description` can be a string. (May be extended
443
+ * later to also support object refs.)
444
+ *
445
+ * Useful for troubleshooting why a manager is waiting for long periods of time
446
+ * on `close()`.
447
+ */
448
+ description?: string;
449
+ };
package/src/Util/Retry.ts CHANGED
@@ -18,41 +18,74 @@ export const isNonRetryableError = (obj: any): obj is NonRetryableError => {
18
18
  * @private
19
19
  * Internal use of Amplify only
20
20
  */
21
- export async function retry(
22
- functionToRetry: Function,
21
+ export async function retry<T>(
22
+ functionToRetry: (...args: any[]) => T,
23
23
  args: any[],
24
24
  delayFn: DelayFunction,
25
- attempt: number = 1
26
- ) {
25
+ onTerminate?: Promise<void>
26
+ ): Promise<T> {
27
27
  if (typeof functionToRetry !== 'function') {
28
28
  throw Error('functionToRetry must be a function');
29
29
  }
30
- logger.debug(
31
- `${
32
- functionToRetry.name
33
- } attempt #${attempt} with this vars: ${JSON.stringify(args)}`
34
- );
35
-
36
- try {
37
- return await functionToRetry(...args);
38
- } catch (err) {
39
- logger.debug(`error on ${functionToRetry.name}`, err);
40
-
41
- if (isNonRetryableError(err)) {
42
- logger.debug(`${functionToRetry.name} non retryable error`, err);
43
- throw err;
44
- }
45
30
 
46
- const retryIn = delayFn(attempt, args, err);
47
- logger.debug(`${functionToRetry.name} retrying in ${retryIn} ms`);
31
+ return new Promise(async (resolve, reject) => {
32
+ let attempt = 0;
33
+ let terminated = false;
34
+ let timeout: any;
35
+ let wakeUp: any = () => {}; // will be replaced with a resolver()
36
+
37
+ // used after the loop if terminated while waiting for a timer.
38
+ let lastError: Error;
39
+
40
+ onTerminate &&
41
+ onTerminate.then(() => {
42
+ // signal not to try anymore.
43
+ terminated = true;
44
+
45
+ // stop sleeping if we're sleeping.
46
+ clearTimeout(timeout);
47
+ wakeUp();
48
+ });
49
+
50
+ while (!terminated) {
51
+ attempt++;
52
+
53
+ logger.debug(
54
+ `${
55
+ functionToRetry.name
56
+ } attempt #${attempt} with this vars: ${JSON.stringify(args)}`
57
+ );
48
58
 
49
- if (retryIn !== false) {
50
- await new Promise(res => setTimeout(res, retryIn));
51
- return await retry(functionToRetry, args, delayFn, attempt + 1);
52
- } else {
53
- throw err;
59
+ try {
60
+ return resolve(await functionToRetry(...args));
61
+ } catch (err) {
62
+ lastError = err;
63
+ logger.debug(`error on ${functionToRetry.name}`, err);
64
+
65
+ if (isNonRetryableError(err)) {
66
+ logger.debug(`${functionToRetry.name} non retryable error`, err);
67
+ return reject(err);
68
+ }
69
+
70
+ const retryIn = delayFn(attempt, args, err);
71
+ logger.debug(`${functionToRetry.name} retrying in ${retryIn} ms`);
72
+
73
+ // we check `terminated` again here because it could have flipped
74
+ // in the time it took `functionToRetry` to return.
75
+ if (retryIn === false || terminated) {
76
+ return reject(err);
77
+ } else {
78
+ await new Promise(r => {
79
+ wakeUp = r; // export wakeUp for onTerminate handling
80
+ timeout = setTimeout(wakeUp, retryIn);
81
+ });
82
+ }
83
+ }
54
84
  }
55
- }
85
+
86
+ // reached if terminated while waiting for a timer.
87
+ reject(lastError);
88
+ });
56
89
  }
57
90
 
58
91
  const MAX_DELAY_MS = 5 * 60 * 1000;
@@ -77,8 +110,10 @@ export function jitteredBackoff(
77
110
  * @private
78
111
  * Internal use of Amplify only
79
112
  */
80
- export const jitteredExponentialRetry = (
81
- functionToRetry: Function,
113
+ export const jitteredExponentialRetry = <T>(
114
+ functionToRetry: (...args: any[]) => T,
82
115
  args: any[],
83
- maxDelayMs: number = MAX_DELAY_MS
84
- ) => retry(functionToRetry, args, jitteredBackoff(maxDelayMs));
116
+ maxDelayMs: number = MAX_DELAY_MS,
117
+ onTerminate?: Promise<void>
118
+ ): Promise<T> =>
119
+ retry(functionToRetry, args, jitteredBackoff(maxDelayMs), onTerminate);
package/src/Util/index.ts CHANGED
@@ -4,3 +4,4 @@ export { default as Reachability } from './Reachability';
4
4
  export * from './DateUtils';
5
5
  export * from './StringUtils';
6
6
  export * from './Constants';
7
+ export * from './BackgroundProcessManager';
package/src/index.ts CHANGED
@@ -14,6 +14,7 @@
14
14
  import { Amplify } from './Amplify';
15
15
  import { Platform } from './Platform';
16
16
 
17
+ export { Amplify } from './Amplify';
17
18
  export { AmplifyClass } from './Amplify';
18
19
  export { ClientDevice } from './ClientDevice';
19
20
  export { ConsoleLogger, ConsoleLogger as Logger } from './Logger';
@@ -22,7 +23,7 @@ export { Hub, HubCapsule, HubCallback, HubPayload } from './Hub';
22
23
  export { I18n } from './I18n';
23
24
  export * from './JS';
24
25
  export { Signer } from './Signer';
25
- export * from './Parser';
26
+ export * from './parseAWSExports';
26
27
  export * from './Providers';
27
28
  export { FacebookOAuth, GoogleOAuth } from './OAuthHelper';
28
29
  export * from './RNComponents';
@@ -41,7 +42,6 @@ export const Constants = {
41
42
  export * from './constants';
42
43
  export * from './Util';
43
44
 
44
- export { Amplify };
45
45
  /**
46
46
  * @deprecated use named import
47
47
  */