@aws-amplify/datastore 5.0.1-api-v6-models.c1977f8.0 → 5.0.1-api-v6-models.891fe0d.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 (70) hide show
  1. package/lib/authModeStrategies/defaultAuthStrategy.js +1 -1
  2. package/lib/authModeStrategies/multiAuthStrategy.js +29 -105
  3. package/lib/datastore/datastore.js +887 -1370
  4. package/lib/index.js +1 -1
  5. package/lib/predicates/index.js +53 -102
  6. package/lib/predicates/next.js +310 -557
  7. package/lib/predicates/sort.js +24 -27
  8. package/lib/ssr/index.js +1 -1
  9. package/lib/storage/adapter/AsyncStorageAdapter.js +115 -449
  10. package/lib/storage/adapter/AsyncStorageDatabase.js +215 -480
  11. package/lib/storage/adapter/InMemoryStore.js +27 -101
  12. package/lib/storage/adapter/InMemoryStore.native.js +1 -1
  13. package/lib/storage/adapter/IndexedDBAdapter.js +441 -1002
  14. package/lib/storage/adapter/StorageAdapterBase.js +177 -396
  15. package/lib/storage/adapter/getDefaultAdapter/index.js +5 -6
  16. package/lib/storage/adapter/getDefaultAdapter/index.native.js +2 -2
  17. package/lib/storage/relationship.js +174 -260
  18. package/lib/storage/storage.js +244 -507
  19. package/lib/sync/datastoreConnectivity.js +29 -84
  20. package/lib/sync/datastoreReachability/index.js +1 -1
  21. package/lib/sync/datastoreReachability/index.native.js +2 -2
  22. package/lib/sync/index.js +512 -885
  23. package/lib/sync/merger.js +30 -133
  24. package/lib/sync/outbox.js +147 -302
  25. package/lib/sync/processors/errorMaps.js +30 -80
  26. package/lib/sync/processors/mutation.js +331 -579
  27. package/lib/sync/processors/subscription.js +268 -428
  28. package/lib/sync/processors/sync.js +276 -464
  29. package/lib/sync/utils.js +248 -393
  30. package/lib/tsconfig.tsbuildinfo +1 -1
  31. package/lib/types.js +16 -58
  32. package/lib/util.js +335 -575
  33. package/lib-esm/authModeStrategies/defaultAuthStrategy.js +1 -1
  34. package/lib-esm/authModeStrategies/multiAuthStrategy.js +27 -103
  35. package/lib-esm/datastore/datastore.js +874 -1359
  36. package/lib-esm/index.js +6 -6
  37. package/lib-esm/predicates/index.js +54 -104
  38. package/lib-esm/predicates/next.js +306 -555
  39. package/lib-esm/predicates/sort.js +24 -27
  40. package/lib-esm/ssr/index.js +1 -1
  41. package/lib-esm/storage/adapter/AsyncStorageAdapter.js +111 -446
  42. package/lib-esm/storage/adapter/AsyncStorageDatabase.js +212 -477
  43. package/lib-esm/storage/adapter/InMemoryStore.js +27 -102
  44. package/lib-esm/storage/adapter/IndexedDBAdapter.js +436 -997
  45. package/lib-esm/storage/adapter/StorageAdapterBase.js +172 -392
  46. package/lib-esm/storage/adapter/getDefaultAdapter/index.js +2 -3
  47. package/lib-esm/storage/adapter/getDefaultAdapter/index.native.js +1 -1
  48. package/lib-esm/storage/relationship.js +173 -260
  49. package/lib-esm/storage/storage.js +236 -499
  50. package/lib-esm/sync/datastoreConnectivity.js +26 -82
  51. package/lib-esm/sync/datastoreReachability/index.js +1 -1
  52. package/lib-esm/sync/datastoreReachability/index.native.js +1 -1
  53. package/lib-esm/sync/index.js +498 -872
  54. package/lib-esm/sync/merger.js +28 -131
  55. package/lib-esm/sync/outbox.js +143 -298
  56. package/lib-esm/sync/processors/errorMaps.js +32 -82
  57. package/lib-esm/sync/processors/mutation.js +324 -572
  58. package/lib-esm/sync/processors/subscription.js +258 -418
  59. package/lib-esm/sync/processors/sync.js +269 -457
  60. package/lib-esm/sync/utils.js +245 -390
  61. package/lib-esm/tsconfig.tsbuildinfo +1 -1
  62. package/lib-esm/types.js +16 -59
  63. package/lib-esm/util.js +335 -577
  64. package/package.json +12 -12
  65. package/src/datastore/datastore.ts +4 -3
  66. package/src/storage/adapter/getDefaultAdapter/index.ts +1 -3
  67. package/src/sync/processors/mutation.ts +1 -1
  68. package/src/sync/processors/sync.ts +1 -1
  69. package/src/sync/utils.ts +1 -1
  70. package/src/util.ts +44 -6
@@ -1,101 +1,15 @@
1
- var __assign = (this && this.__assign) || function () {
2
- __assign = Object.assign || function(t) {
3
- for (var s, i = 1, n = arguments.length; i < n; i++) {
4
- s = arguments[i];
5
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
- t[p] = s[p];
7
- }
8
- return t;
9
- };
10
- return __assign.apply(this, arguments);
11
- };
12
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
- return new (P || (P = Promise))(function (resolve, reject) {
15
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
- step((generator = generator.apply(thisArg, _arguments || [])).next());
19
- });
20
- };
21
- var __generator = (this && this.__generator) || function (thisArg, body) {
22
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
23
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
24
- function verb(n) { return function (v) { return step([n, v]); }; }
25
- function step(op) {
26
- if (f) throw new TypeError("Generator is already executing.");
27
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
28
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
29
- if (y = 0, t) op = [op[0] & 2, t.value];
30
- switch (op[0]) {
31
- case 0: case 1: t = op; break;
32
- case 4: _.label++; return { value: op[1], done: false };
33
- case 5: _.label++; y = op[1]; op = [0]; continue;
34
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
35
- default:
36
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
37
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
38
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
39
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
40
- if (t[2]) _.ops.pop();
41
- _.trys.pop(); continue;
42
- }
43
- op = body.call(thisArg, _);
44
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
45
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
- }
47
- };
48
- var __rest = (this && this.__rest) || function (s, e) {
49
- var t = {};
50
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
51
- t[p] = s[p];
52
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
53
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
54
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
55
- t[p[i]] = s[p[i]];
56
- }
57
- return t;
58
- };
59
- var __read = (this && this.__read) || function (o, n) {
60
- var m = typeof Symbol === "function" && o[Symbol.iterator];
61
- if (!m) return o;
62
- var i = m.call(o), r, ar = [], e;
63
- try {
64
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
65
- }
66
- catch (error) { e = { error: error }; }
67
- finally {
68
- try {
69
- if (r && !r.done && (m = i["return"])) m.call(i);
70
- }
71
- finally { if (e) throw e.error; }
72
- }
73
- return ar;
74
- };
75
- var __values = (this && this.__values) || function(o) {
76
- var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
77
- if (m) return m.call(o);
78
- if (o && typeof o.length === "number") return {
79
- next: function () {
80
- if (o && i >= o.length) o = void 0;
81
- return { value: o && o[i++], done: !o };
82
- }
83
- };
84
- throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
85
- };
86
1
  import { InternalAPI } from '@aws-amplify/api/internals';
87
2
  import { Category, DataStoreAction, jitteredBackoff, NonRetryableError, retry, BackgroundProcessManager, } from '@aws-amplify/core/internals/utils';
88
- import { ConsoleLogger } from '@aws-amplify/core';
89
3
  import { Observable } from 'rxjs';
90
4
  import { DISCARD, isModelFieldType, isTargetNameAssociation, OpType, ProcessName, } from '../../types';
91
5
  import { extractTargetNamesFromSrc, USER, ID } from '../../util';
92
6
  import { buildGraphQLOperation, createMutationInstanceFromModelOperation, getModelAuthModes, TransformerMutationType, getTokenForCustomAuth, } from '../utils';
93
7
  import { getMutationErrorType } from './errorMaps';
94
- var MAX_ATTEMPTS = 10;
95
- var logger = new ConsoleLogger('DataStore');
96
- var MutationProcessor = /** @class */ (function () {
97
- function MutationProcessor(schema, storage, userClasses, outbox, modelInstanceCreator, MutationEvent, amplifyConfig, authModeStrategy, errorHandler, conflictHandler, amplifyContext) {
98
- if (amplifyConfig === void 0) { amplifyConfig = {}; }
8
+ import { ConsoleLogger } from '@aws-amplify/core';
9
+ const MAX_ATTEMPTS = 10;
10
+ const logger = new ConsoleLogger('DataStore');
11
+ class MutationProcessor {
12
+ constructor(schema, storage, userClasses, outbox, modelInstanceCreator, MutationEvent, amplifyConfig = {}, authModeStrategy, errorHandler, conflictHandler, amplifyContext) {
99
13
  this.schema = schema;
100
14
  this.storage = storage;
101
15
  this.userClasses = userClasses;
@@ -114,446 +28,299 @@ var MutationProcessor = /** @class */ (function () {
114
28
  this.amplifyContext.InternalAPI || InternalAPI;
115
29
  this.generateQueries();
116
30
  }
117
- MutationProcessor.prototype.generateQueries = function () {
118
- var _this = this;
119
- Object.values(this.schema.namespaces).forEach(function (namespace) {
31
+ generateQueries() {
32
+ Object.values(this.schema.namespaces).forEach(namespace => {
120
33
  Object.values(namespace.models)
121
- .filter(function (_a) {
122
- var syncable = _a.syncable;
123
- return syncable;
124
- })
125
- .forEach(function (model) {
126
- var _a = __read(buildGraphQLOperation(namespace, model, 'CREATE'), 1), createMutation = _a[0];
127
- var _b = __read(buildGraphQLOperation(namespace, model, 'UPDATE'), 1), updateMutation = _b[0];
128
- var _c = __read(buildGraphQLOperation(namespace, model, 'DELETE'), 1), deleteMutation = _c[0];
129
- _this.typeQuery.set(model, [
34
+ .filter(({ syncable }) => syncable)
35
+ .forEach(model => {
36
+ const [createMutation] = buildGraphQLOperation(namespace, model, 'CREATE');
37
+ const [updateMutation] = buildGraphQLOperation(namespace, model, 'UPDATE');
38
+ const [deleteMutation] = buildGraphQLOperation(namespace, model, 'DELETE');
39
+ this.typeQuery.set(model, [
130
40
  createMutation,
131
41
  updateMutation,
132
42
  deleteMutation,
133
43
  ]);
134
44
  });
135
45
  });
136
- };
137
- MutationProcessor.prototype.isReady = function () {
46
+ }
47
+ isReady() {
138
48
  return this.observer !== undefined;
139
- };
140
- MutationProcessor.prototype.start = function () {
141
- var _this = this;
49
+ }
50
+ start() {
142
51
  this.runningProcesses = new BackgroundProcessManager();
143
- var observable = new Observable(function (observer) {
144
- _this.observer = observer;
52
+ const observable = new Observable(observer => {
53
+ this.observer = observer;
145
54
  try {
146
- _this.resume();
55
+ this.resume();
147
56
  }
148
57
  catch (error) {
149
58
  logger.error('mutations processor start error', error);
150
59
  throw error;
151
60
  }
152
- return _this.runningProcesses.addCleaner(function () { return __awaiter(_this, void 0, void 0, function () {
153
- return __generator(this, function (_a) {
154
- // The observer has unsubscribed and/or `stop()` has been called.
155
- this.removeObserver();
156
- this.pause();
157
- return [2 /*return*/];
158
- });
159
- }); });
160
- });
161
- return observable;
162
- };
163
- MutationProcessor.prototype.stop = function () {
164
- return __awaiter(this, void 0, void 0, function () {
165
- return __generator(this, function (_a) {
166
- switch (_a.label) {
167
- case 0:
168
- this.removeObserver();
169
- return [4 /*yield*/, this.runningProcesses.close()];
170
- case 1:
171
- _a.sent();
172
- return [4 /*yield*/, this.runningProcesses.open()];
173
- case 2:
174
- _a.sent();
175
- return [2 /*return*/];
176
- }
61
+ return this.runningProcesses.addCleaner(async () => {
62
+ // The observer has unsubscribed and/or `stop()` has been called.
63
+ this.removeObserver();
64
+ this.pause();
177
65
  });
178
66
  });
179
- };
180
- MutationProcessor.prototype.removeObserver = function () {
181
- var _a, _b;
182
- (_b = (_a = this.observer) === null || _a === void 0 ? void 0 : _a.complete) === null || _b === void 0 ? void 0 : _b.call(_a);
67
+ return observable;
68
+ }
69
+ async stop() {
70
+ this.removeObserver();
71
+ await this.runningProcesses.close();
72
+ await this.runningProcesses.open();
73
+ }
74
+ removeObserver() {
75
+ this.observer?.complete?.();
183
76
  this.observer = undefined;
184
- };
185
- MutationProcessor.prototype.resume = function () {
186
- return __awaiter(this, void 0, void 0, function () {
187
- var _this = this;
188
- return __generator(this, function (_a) {
189
- switch (_a.label) {
190
- case 0:
191
- if (!this.runningProcesses.isOpen) return [3 /*break*/, 2];
192
- return [4 /*yield*/, this.runningProcesses.add(function (onTerminate) { return __awaiter(_this, void 0, void 0, function () {
193
- var head, namespaceName, _loop_1, this_1, _a;
194
- var _this = this;
195
- var _b, _c;
196
- return __generator(this, function (_d) {
197
- switch (_d.label) {
198
- case 0:
199
- if (this.processing ||
200
- !this.isReady() ||
201
- !this.runningProcesses.isOpen) {
202
- return [2 /*return*/];
203
- }
204
- this.processing = true;
205
- namespaceName = USER;
206
- _loop_1 = function () {
207
- var model, operation, data, condition, modelConstructor, result, opName, modelDefinition, modelAuthModes, operationAuthModes_1, authModeAttempts_1, authModeRetry_1, error_1, record, hasMore;
208
- var _e;
209
- return __generator(this, function (_f) {
210
- switch (_f.label) {
211
- case 0:
212
- model = head.model, operation = head.operation, data = head.data, condition = head.condition;
213
- modelConstructor = this_1.userClasses[model];
214
- result = undefined;
215
- opName = undefined;
216
- modelDefinition = undefined;
217
- _f.label = 1;
218
- case 1:
219
- _f.trys.push([1, 4, , 5]);
220
- return [4 /*yield*/, getModelAuthModes({
221
- authModeStrategy: this_1.authModeStrategy,
222
- defaultAuthMode: this_1.amplifyConfig.aws_appsync_authenticationType,
223
- modelName: model,
224
- schema: this_1.schema,
225
- })];
226
- case 2:
227
- modelAuthModes = _f.sent();
228
- operationAuthModes_1 = modelAuthModes[operation.toUpperCase()];
229
- authModeAttempts_1 = 0;
230
- authModeRetry_1 = function () { return __awaiter(_this, void 0, void 0, function () {
231
- var response, error_2, e_1;
232
- return __generator(this, function (_a) {
233
- switch (_a.label) {
234
- case 0:
235
- _a.trys.push([0, 2, , 9]);
236
- logger.debug("Attempting mutation with authMode: ".concat(operationAuthModes_1[authModeAttempts_1]));
237
- return [4 /*yield*/, this.jitteredRetry(namespaceName, model, operation, data, condition, modelConstructor, this.MutationEvent, head, operationAuthModes_1[authModeAttempts_1], onTerminate)];
238
- case 1:
239
- response = _a.sent();
240
- logger.debug("Mutation sent successfully with authMode: ".concat(operationAuthModes_1[authModeAttempts_1]));
241
- return [2 /*return*/, response];
242
- case 2:
243
- error_2 = _a.sent();
244
- authModeAttempts_1++;
245
- if (!(authModeAttempts_1 >= operationAuthModes_1.length)) return [3 /*break*/, 7];
246
- logger.debug("Mutation failed with authMode: ".concat(operationAuthModes_1[authModeAttempts_1 - 1]));
247
- _a.label = 3;
248
- case 3:
249
- _a.trys.push([3, 5, , 6]);
250
- return [4 /*yield*/, this.errorHandler({
251
- recoverySuggestion: 'Ensure app code is up to date, auth directives exist and are correct on each model, and that server-side data has not been invalidated by a schema change. If the problem persists, search for or create an issue: https://github.com/aws-amplify/amplify-js/issues',
252
- localModel: null,
253
- message: error_2.message,
254
- model: modelConstructor.name,
255
- operation: opName,
256
- errorType: getMutationErrorType(error_2),
257
- process: ProcessName.sync,
258
- remoteModel: null,
259
- cause: error_2,
260
- })];
261
- case 4:
262
- _a.sent();
263
- return [3 /*break*/, 6];
264
- case 5:
265
- e_1 = _a.sent();
266
- logger.error('Mutation error handler failed with:', e_1);
267
- return [3 /*break*/, 6];
268
- case 6: throw error_2;
269
- case 7:
270
- logger.debug("Mutation failed with authMode: ".concat(operationAuthModes_1[authModeAttempts_1 - 1], ". Retrying with authMode: ").concat(operationAuthModes_1[authModeAttempts_1]));
271
- return [4 /*yield*/, authModeRetry_1()];
272
- case 8: return [2 /*return*/, _a.sent()];
273
- case 9: return [2 /*return*/];
274
- }
275
- });
276
- }); };
277
- return [4 /*yield*/, authModeRetry_1()];
278
- case 3:
279
- _e = __read.apply(void 0, [_f.sent(), 3]), result = _e[0], opName = _e[1], modelDefinition = _e[2];
280
- return [3 /*break*/, 5];
281
- case 4:
282
- error_1 = _f.sent();
283
- if (error_1.message === 'Offline' ||
284
- error_1.message === 'RetryMutation') {
285
- return [2 /*return*/, "continue"];
286
- }
287
- return [3 /*break*/, 5];
288
- case 5:
289
- if (!(result === undefined)) return [3 /*break*/, 7];
290
- logger.debug('done retrying');
291
- return [4 /*yield*/, this_1.storage.runExclusive(function (storage) { return __awaiter(_this, void 0, void 0, function () {
292
- return __generator(this, function (_a) {
293
- switch (_a.label) {
294
- case 0: return [4 /*yield*/, this.outbox.dequeue(storage)];
295
- case 1:
296
- _a.sent();
297
- return [2 /*return*/];
298
- }
299
- });
300
- }); })];
301
- case 6:
302
- _f.sent();
303
- return [2 /*return*/, "continue"];
304
- case 7:
305
- record = result.data[opName];
306
- hasMore = false;
307
- return [4 /*yield*/, this_1.storage.runExclusive(function (storage) { return __awaiter(_this, void 0, void 0, function () {
308
- return __generator(this, function (_a) {
309
- switch (_a.label) {
310
- case 0:
311
- // using runExclusive to prevent possible race condition
312
- // when another record gets enqueued between dequeue and peek
313
- return [4 /*yield*/, this.outbox.dequeue(storage, record, operation)];
314
- case 1:
315
- // using runExclusive to prevent possible race condition
316
- // when another record gets enqueued between dequeue and peek
317
- _a.sent();
318
- return [4 /*yield*/, this.outbox.peek(storage)];
319
- case 2:
320
- hasMore = (_a.sent()) !== undefined;
321
- return [2 /*return*/];
322
- }
323
- });
324
- }); })];
325
- case 8:
326
- _f.sent();
327
- (_c = (_b = this_1.observer) === null || _b === void 0 ? void 0 : _b.next) === null || _c === void 0 ? void 0 : _c.call(_b, {
328
- operation: operation,
329
- modelDefinition: modelDefinition,
330
- model: record,
331
- hasMore: hasMore,
332
- });
333
- return [2 /*return*/];
334
- }
335
- });
336
- };
337
- this_1 = this;
338
- _d.label = 1;
339
- case 1:
340
- _a = this.processing &&
341
- this.runningProcesses.isOpen;
342
- if (!_a) return [3 /*break*/, 3];
343
- return [4 /*yield*/, this.outbox.peek(this.storage)];
344
- case 2:
345
- _a = (head = _d.sent()) !== undefined;
346
- _d.label = 3;
347
- case 3:
348
- if (!_a) return [3 /*break*/, 5];
349
- return [5 /*yield**/, _loop_1()];
350
- case 4:
351
- _d.sent();
352
- return [3 /*break*/, 1];
353
- case 5:
354
- // pauses itself
355
- this.pause();
356
- return [2 /*return*/];
77
+ }
78
+ async resume() {
79
+ if (this.runningProcesses.isOpen) {
80
+ await this.runningProcesses.add(async (onTerminate) => {
81
+ if (this.processing ||
82
+ !this.isReady() ||
83
+ !this.runningProcesses.isOpen) {
84
+ return;
85
+ }
86
+ this.processing = true;
87
+ let head;
88
+ const namespaceName = USER;
89
+ // start to drain outbox
90
+ while (this.processing &&
91
+ this.runningProcesses.isOpen &&
92
+ (head = await this.outbox.peek(this.storage)) !== undefined) {
93
+ const { model, operation, data, condition } = head;
94
+ const modelConstructor = this.userClasses[model];
95
+ let result = undefined;
96
+ let opName = undefined;
97
+ let modelDefinition = undefined;
98
+ try {
99
+ const modelAuthModes = await getModelAuthModes({
100
+ authModeStrategy: this.authModeStrategy,
101
+ defaultAuthMode: this.amplifyConfig.aws_appsync_authenticationType,
102
+ modelName: model,
103
+ schema: this.schema,
104
+ });
105
+ const operationAuthModes = modelAuthModes[operation.toUpperCase()];
106
+ let authModeAttempts = 0;
107
+ const authModeRetry = async () => {
108
+ try {
109
+ logger.debug(`Attempting mutation with authMode: ${operationAuthModes[authModeAttempts]}`);
110
+ const response = await this.jitteredRetry(namespaceName, model, operation, data, condition, modelConstructor, this.MutationEvent, head, operationAuthModes[authModeAttempts], onTerminate);
111
+ logger.debug(`Mutation sent successfully with authMode: ${operationAuthModes[authModeAttempts]}`);
112
+ return response;
113
+ }
114
+ catch (error) {
115
+ authModeAttempts++;
116
+ if (authModeAttempts >= operationAuthModes.length) {
117
+ logger.debug(`Mutation failed with authMode: ${operationAuthModes[authModeAttempts - 1]}`);
118
+ try {
119
+ await this.errorHandler({
120
+ recoverySuggestion: 'Ensure app code is up to date, auth directives exist and are correct on each model, and that server-side data has not been invalidated by a schema change. If the problem persists, search for or create an issue: https://github.com/aws-amplify/amplify-js/issues',
121
+ localModel: null,
122
+ message: error.message,
123
+ model: modelConstructor.name,
124
+ operation: opName,
125
+ errorType: getMutationErrorType(error),
126
+ process: ProcessName.sync,
127
+ remoteModel: null,
128
+ cause: error,
129
+ });
357
130
  }
358
- });
359
- }); }, 'mutation resume loop')];
360
- case 1:
361
- _a.sent();
362
- _a.label = 2;
363
- case 2: return [2 /*return*/];
131
+ catch (e) {
132
+ logger.error('Mutation error handler failed with:', e);
133
+ }
134
+ throw error;
135
+ }
136
+ logger.debug(`Mutation failed with authMode: ${operationAuthModes[authModeAttempts - 1]}. Retrying with authMode: ${operationAuthModes[authModeAttempts]}`);
137
+ return await authModeRetry();
138
+ }
139
+ };
140
+ [result, opName, modelDefinition] = await authModeRetry();
141
+ }
142
+ catch (error) {
143
+ if (error.message === 'Offline' ||
144
+ error.message === 'RetryMutation') {
145
+ continue;
146
+ }
147
+ }
148
+ if (result === undefined) {
149
+ logger.debug('done retrying');
150
+ await this.storage.runExclusive(async (storage) => {
151
+ await this.outbox.dequeue(storage);
152
+ });
153
+ continue;
154
+ }
155
+ const record = result.data[opName];
156
+ let hasMore = false;
157
+ await this.storage.runExclusive(async (storage) => {
158
+ // using runExclusive to prevent possible race condition
159
+ // when another record gets enqueued between dequeue and peek
160
+ await this.outbox.dequeue(storage, record, operation);
161
+ hasMore = (await this.outbox.peek(storage)) !== undefined;
162
+ });
163
+ this.observer?.next?.({
164
+ operation,
165
+ modelDefinition,
166
+ model: record,
167
+ hasMore,
168
+ });
364
169
  }
365
- });
366
- });
367
- };
368
- MutationProcessor.prototype.jitteredRetry = function (namespaceName, model, operation, data, condition, modelConstructor, MutationEvent, mutationEvent, authMode, onTerminate) {
369
- return __awaiter(this, void 0, void 0, function () {
370
- var _this = this;
371
- return __generator(this, function (_a) {
372
- switch (_a.label) {
373
- case 0: return [4 /*yield*/, retry(function (model, operation, data, condition, modelConstructor, MutationEvent, mutationEvent) { return __awaiter(_this, void 0, void 0, function () {
374
- var _a, query, variables, graphQLCondition, opName, modelDefinition, authToken, tryWith, attempt, opType, customUserAgentDetails, result, err_1, _b, error, _c, _d, _e, code, retryWith, err_2, _f, _g, opName_1, query_1, authToken_1, serverData, namespace, updatedMutation;
375
- var _h;
376
- return __generator(this, function (_j) {
377
- switch (_j.label) {
378
- case 0:
379
- _a = __read(this.createQueryVariables(namespaceName, model, operation, data, condition), 5), query = _a[0], variables = _a[1], graphQLCondition = _a[2], opName = _a[3], modelDefinition = _a[4];
380
- return [4 /*yield*/, getTokenForCustomAuth(authMode, this.amplifyConfig)];
381
- case 1:
382
- authToken = _j.sent();
383
- tryWith = {
384
- query: query,
385
- variables: variables,
386
- authMode: authMode,
387
- authToken: authToken,
388
- };
389
- attempt = 0;
390
- opType = this.opTypeFromTransformerOperation(operation);
391
- customUserAgentDetails = {
392
- category: Category.DataStore,
393
- action: DataStoreAction.GraphQl,
394
- };
395
- _j.label = 2;
396
- case 2:
397
- _j.trys.push([2, 4, , 17]);
398
- return [4 /*yield*/, this.amplifyContext.InternalAPI.graphql(tryWith, undefined, customUserAgentDetails)];
399
- case 3:
400
- result = (_j.sent());
401
- // Use `as any` because TypeScript doesn't seem to like passing tuples
402
- // through generic params.
403
- return [2 /*return*/, [result, opName, modelDefinition]];
404
- case 4:
405
- err_1 = _j.sent();
406
- if (!(err_1.errors && err_1.errors.length > 0)) return [3 /*break*/, 15];
407
- _b = __read(err_1.errors, 1), error = _b[0];
408
- _c = error.originalError, _d = _c === void 0 ? {} : _c, _e = _d.code, code = _e === void 0 ? null : _e;
409
- if (error.errorType === 'Unauthorized') {
410
- throw new NonRetryableError('Unauthorized');
411
- }
412
- if (error.message === 'Network Error' ||
413
- code === 'ECONNABORTED' // refers to axios timeout error caused by device's bad network condition
414
- ) {
415
- if (!this.processing) {
416
- throw new NonRetryableError('Offline');
417
- }
418
- // TODO: Check errors on different env (react-native or other browsers)
419
- throw new Error('Network Error');
420
- }
421
- if (!(error.errorType === 'ConflictUnhandled')) return [3 /*break*/, 13];
422
- // TODO: add on ConflictConditionalCheck error query last from server
423
- attempt++;
424
- retryWith = void 0;
425
- if (!(attempt > MAX_ATTEMPTS)) return [3 /*break*/, 5];
426
- retryWith = DISCARD;
427
- return [3 /*break*/, 8];
428
- case 5:
429
- _j.trys.push([5, 7, , 8]);
430
- return [4 /*yield*/, this.conflictHandler({
431
- modelConstructor: modelConstructor,
432
- localModel: this.modelInstanceCreator(modelConstructor, variables.input),
433
- remoteModel: this.modelInstanceCreator(modelConstructor, error.data),
434
- operation: opType,
435
- attempts: attempt,
436
- })];
437
- case 6:
438
- retryWith = _j.sent();
439
- return [3 /*break*/, 8];
440
- case 7:
441
- err_2 = _j.sent();
442
- logger.warn('conflict trycatch', err_2);
443
- return [3 /*break*/, 17];
444
- case 8:
445
- if (!(retryWith === DISCARD)) return [3 /*break*/, 11];
446
- _f = __read(buildGraphQLOperation(this.schema.namespaces[namespaceName], modelDefinition, 'GET'), 1), _g = __read(_f[0], 3), opName_1 = _g[1], query_1 = _g[2];
447
- return [4 /*yield*/, getTokenForCustomAuth(authMode, this.amplifyConfig)];
448
- case 9:
449
- authToken_1 = _j.sent();
450
- return [4 /*yield*/, this.amplifyContext.InternalAPI.graphql({
451
- query: query_1,
452
- variables: { id: variables.input.id },
453
- authMode: authMode,
454
- authToken: authToken_1,
455
- }, undefined, customUserAgentDetails)];
456
- case 10:
457
- serverData = _j.sent();
458
- // onTerminate cancel graphql()
459
- return [2 /*return*/, [serverData, opName_1, modelDefinition]];
460
- case 11:
461
- namespace = this.schema.namespaces[namespaceName];
462
- updatedMutation = createMutationInstanceFromModelOperation(namespace.relationships, modelDefinition, opType, modelConstructor, retryWith, graphQLCondition, MutationEvent, this.modelInstanceCreator, mutationEvent.id);
463
- return [4 /*yield*/, this.storage.save(updatedMutation)];
464
- case 12:
465
- _j.sent();
466
- throw new NonRetryableError('RetryMutation');
467
- case 13:
468
- try {
469
- this.errorHandler({
470
- recoverySuggestion: 'Ensure app code is up to date, auth directives exist and are correct on each model, and that server-side data has not been invalidated by a schema change. If the problem persists, search for or create an issue: https://github.com/aws-amplify/amplify-js/issues',
471
- localModel: variables.input,
472
- message: error.message,
473
- operation: operation,
474
- errorType: getMutationErrorType(error),
475
- errorInfo: error.errorInfo,
476
- process: ProcessName.mutate,
477
- cause: error,
478
- remoteModel: error.data
479
- ? this.modelInstanceCreator(modelConstructor, error.data)
480
- : null,
481
- });
482
- }
483
- catch (err) {
484
- logger.warn('Mutation error handler failed with:', err);
485
- }
486
- finally {
487
- // Return empty tuple, dequeues the mutation
488
- return [2 /*return*/, error.data
489
- ? [
490
- { data: (_h = {}, _h[opName] = error.data, _h) },
491
- opName,
492
- modelDefinition,
493
- ]
494
- : []];
495
- }
496
- _j.label = 14;
497
- case 14: return [3 /*break*/, 16];
498
- case 15:
499
- // Catch-all for client-side errors that don't come back in the `GraphQLError` format.
500
- // These errors should not be retried.
501
- throw new NonRetryableError(err_1);
502
- case 16: return [3 /*break*/, 17];
503
- case 17:
504
- if (tryWith) return [3 /*break*/, 2];
505
- _j.label = 18;
506
- case 18: return [2 /*return*/];
170
+ // pauses itself
171
+ this.pause();
172
+ }, 'mutation resume loop');
173
+ }
174
+ }
175
+ async jitteredRetry(namespaceName, model, operation, data, condition, modelConstructor, MutationEvent, mutationEvent, authMode, onTerminate) {
176
+ return await retry(async (model, operation, data, condition, modelConstructor, MutationEvent, mutationEvent) => {
177
+ const [query, variables, graphQLCondition, opName, modelDefinition] = this.createQueryVariables(namespaceName, model, operation, data, condition);
178
+ const authToken = await getTokenForCustomAuth(authMode, this.amplifyConfig);
179
+ const tryWith = {
180
+ query,
181
+ variables,
182
+ authMode,
183
+ authToken,
184
+ };
185
+ let attempt = 0;
186
+ const opType = this.opTypeFromTransformerOperation(operation);
187
+ const customUserAgentDetails = {
188
+ category: Category.DataStore,
189
+ action: DataStoreAction.GraphQl,
190
+ };
191
+ do {
192
+ try {
193
+ const result = (await this.amplifyContext.InternalAPI.graphql(tryWith, undefined, customUserAgentDetails));
194
+ // Use `as any` because TypeScript doesn't seem to like passing tuples
195
+ // through generic params.
196
+ return [result, opName, modelDefinition];
197
+ }
198
+ catch (err) {
199
+ if (err.errors && err.errors.length > 0) {
200
+ const [error] = err.errors;
201
+ const { originalError: { code = null } = {} } = error;
202
+ if (error.errorType === 'Unauthorized') {
203
+ throw new NonRetryableError('Unauthorized');
204
+ }
205
+ if (error.message === 'Network Error' ||
206
+ code === 'ECONNABORTED' // refers to axios timeout error caused by device's bad network condition
207
+ ) {
208
+ if (!this.processing) {
209
+ throw new NonRetryableError('Offline');
210
+ }
211
+ // TODO: Check errors on different env (react-native or other browsers)
212
+ throw new Error('Network Error');
213
+ }
214
+ if (error.errorType === 'ConflictUnhandled') {
215
+ // TODO: add on ConflictConditionalCheck error query last from server
216
+ attempt++;
217
+ let retryWith;
218
+ if (attempt > MAX_ATTEMPTS) {
219
+ retryWith = DISCARD;
220
+ }
221
+ else {
222
+ try {
223
+ retryWith = await this.conflictHandler({
224
+ modelConstructor,
225
+ localModel: this.modelInstanceCreator(modelConstructor, variables.input),
226
+ remoteModel: this.modelInstanceCreator(modelConstructor, error.data),
227
+ operation: opType,
228
+ attempts: attempt,
229
+ });
507
230
  }
508
- });
509
- }); }, [
510
- model,
511
- operation,
512
- data,
513
- condition,
514
- modelConstructor,
515
- MutationEvent,
516
- mutationEvent,
517
- ], safeJitteredBackoff, onTerminate)];
518
- case 1: return [2 /*return*/, _a.sent()];
231
+ catch (err) {
232
+ logger.warn('conflict trycatch', err);
233
+ continue;
234
+ }
235
+ }
236
+ if (retryWith === DISCARD) {
237
+ // Query latest from server and notify merger
238
+ const [[, opName, query]] = buildGraphQLOperation(this.schema.namespaces[namespaceName], modelDefinition, 'GET');
239
+ const authToken = await getTokenForCustomAuth(authMode, this.amplifyConfig);
240
+ const serverData = await this.amplifyContext.InternalAPI.graphql({
241
+ query,
242
+ variables: { id: variables.input.id },
243
+ authMode,
244
+ authToken,
245
+ }, undefined, customUserAgentDetails);
246
+ // onTerminate cancel graphql()
247
+ return [serverData, opName, modelDefinition];
248
+ }
249
+ const namespace = this.schema.namespaces[namespaceName];
250
+ // convert retry with to tryWith
251
+ const updatedMutation = createMutationInstanceFromModelOperation(namespace.relationships, modelDefinition, opType, modelConstructor, retryWith, graphQLCondition, MutationEvent, this.modelInstanceCreator, mutationEvent.id);
252
+ await this.storage.save(updatedMutation);
253
+ throw new NonRetryableError('RetryMutation');
254
+ }
255
+ else {
256
+ try {
257
+ this.errorHandler({
258
+ recoverySuggestion: 'Ensure app code is up to date, auth directives exist and are correct on each model, and that server-side data has not been invalidated by a schema change. If the problem persists, search for or create an issue: https://github.com/aws-amplify/amplify-js/issues',
259
+ localModel: variables.input,
260
+ message: error.message,
261
+ operation,
262
+ errorType: getMutationErrorType(error),
263
+ errorInfo: error.errorInfo,
264
+ process: ProcessName.mutate,
265
+ cause: error,
266
+ remoteModel: error.data
267
+ ? this.modelInstanceCreator(modelConstructor, error.data)
268
+ : null,
269
+ });
270
+ }
271
+ catch (err) {
272
+ logger.warn('Mutation error handler failed with:', err);
273
+ }
274
+ finally {
275
+ // Return empty tuple, dequeues the mutation
276
+ return error.data
277
+ ? [
278
+ { data: { [opName]: error.data } },
279
+ opName,
280
+ modelDefinition,
281
+ ]
282
+ : [];
283
+ }
284
+ }
285
+ }
286
+ else {
287
+ // Catch-all for client-side errors that don't come back in the `GraphQLError` format.
288
+ // These errors should not be retried.
289
+ throw new NonRetryableError(err);
290
+ }
519
291
  }
520
- });
521
- });
522
- };
523
- MutationProcessor.prototype.createQueryVariables = function (namespaceName, model, operation, data, condition) {
524
- var e_2, _a, e_3, _b, e_4, _c;
525
- var _d, _e;
526
- var modelDefinition = this.schema.namespaces[namespaceName].models[model];
527
- var primaryKey = this.schema.namespaces[namespaceName].keys[model].primaryKey;
528
- var auth = (_d = modelDefinition.attributes) === null || _d === void 0 ? void 0 : _d.find(function (a) { return a.type === 'auth'; });
529
- var ownerFields = ((_e = auth === null || auth === void 0 ? void 0 : auth.properties) === null || _e === void 0 ? void 0 : _e.rules.map(function (rule) { return rule.ownerField; }).filter(function (f) { return f; })) || ['owner'];
530
- var queriesTuples = this.typeQuery.get(modelDefinition);
531
- var _f = __read(queriesTuples.find(function (_a) {
532
- var _b = __read(_a, 1), transformerMutationType = _b[0];
533
- return transformerMutationType === operation;
534
- }), 3), opName = _f[1], query = _f[2];
535
- var _g = JSON.parse(data), _version = _g._version, parsedData = __rest(_g, ["_version"]);
292
+ } while (tryWith);
293
+ }, [
294
+ model,
295
+ operation,
296
+ data,
297
+ condition,
298
+ modelConstructor,
299
+ MutationEvent,
300
+ mutationEvent,
301
+ ], safeJitteredBackoff, onTerminate);
302
+ }
303
+ createQueryVariables(namespaceName, model, operation, data, condition) {
304
+ const modelDefinition = this.schema.namespaces[namespaceName].models[model];
305
+ const { primaryKey } = this.schema.namespaces[namespaceName].keys[model];
306
+ const auth = modelDefinition.attributes?.find(a => a.type === 'auth');
307
+ const ownerFields = auth?.properties?.rules
308
+ .map(rule => rule.ownerField)
309
+ .filter(f => f) || ['owner'];
310
+ const queriesTuples = this.typeQuery.get(modelDefinition);
311
+ const [, opName, query] = queriesTuples.find(([transformerMutationType]) => transformerMutationType === operation);
312
+ const { _version, ...parsedData } = JSON.parse(data);
536
313
  // include all the fields that comprise a custom PK if one is specified
537
- var deleteInput = {};
314
+ const deleteInput = {};
538
315
  if (primaryKey && primaryKey.length) {
539
- try {
540
- for (var primaryKey_1 = __values(primaryKey), primaryKey_1_1 = primaryKey_1.next(); !primaryKey_1_1.done; primaryKey_1_1 = primaryKey_1.next()) {
541
- var pkField = primaryKey_1_1.value;
542
- deleteInput[pkField] = parsedData[pkField];
543
- }
544
- }
545
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
546
- finally {
547
- try {
548
- if (primaryKey_1_1 && !primaryKey_1_1.done && (_a = primaryKey_1.return)) _a.call(primaryKey_1);
549
- }
550
- finally { if (e_2) throw e_2.error; }
316
+ for (const pkField of primaryKey) {
317
+ deleteInput[pkField] = parsedData[pkField];
551
318
  }
552
319
  }
553
320
  else {
554
321
  deleteInput[ID] = parsedData.id;
555
322
  }
556
- var mutationInput;
323
+ let mutationInput;
557
324
  if (operation === TransformerMutationType.DELETE) {
558
325
  // For DELETE mutations, only the key(s) are included in the input
559
326
  mutationInput = deleteInput;
@@ -561,75 +328,61 @@ var MutationProcessor = /** @class */ (function () {
561
328
  else {
562
329
  // Otherwise, we construct the mutation input with the following logic
563
330
  mutationInput = {};
564
- var modelFields = Object.values(modelDefinition.fields);
565
- try {
566
- for (var modelFields_1 = __values(modelFields), modelFields_1_1 = modelFields_1.next(); !modelFields_1_1.done; modelFields_1_1 = modelFields_1.next()) {
567
- var _h = modelFields_1_1.value, name_1 = _h.name, type = _h.type, association = _h.association, isReadOnly = _h.isReadOnly;
568
- // omit readonly fields. cloud storage doesn't need them and won't take them!
569
- if (isReadOnly) {
570
- continue;
571
- }
572
- // omit owner fields if it's `null`. cloud storage doesn't allow it.
573
- if (ownerFields.includes(name_1) && parsedData[name_1] === null) {
574
- continue;
575
- }
576
- // model fields should be stripped out from the input
577
- if (isModelFieldType(type)) {
578
- // except for belongs to relations - we need to replace them with the correct foreign key(s)
579
- if (isTargetNameAssociation(association) &&
580
- association.connectionType === 'BELONGS_TO') {
581
- var targetNames = extractTargetNamesFromSrc(association);
582
- if (targetNames) {
583
- try {
584
- // instead of including the connected model itself, we add its key(s) to the mutation input
585
- for (var targetNames_1 = (e_4 = void 0, __values(targetNames)), targetNames_1_1 = targetNames_1.next(); !targetNames_1_1.done; targetNames_1_1 = targetNames_1.next()) {
586
- var targetName = targetNames_1_1.value;
587
- mutationInput[targetName] = parsedData[targetName];
588
- }
589
- }
590
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
591
- finally {
592
- try {
593
- if (targetNames_1_1 && !targetNames_1_1.done && (_c = targetNames_1.return)) _c.call(targetNames_1);
594
- }
595
- finally { if (e_4) throw e_4.error; }
596
- }
331
+ const modelFields = Object.values(modelDefinition.fields);
332
+ for (const { name, type, association, isReadOnly } of modelFields) {
333
+ // omit readonly fields. cloud storage doesn't need them and won't take them!
334
+ if (isReadOnly) {
335
+ continue;
336
+ }
337
+ // omit owner fields if it's `null`. cloud storage doesn't allow it.
338
+ if (ownerFields.includes(name) && parsedData[name] === null) {
339
+ continue;
340
+ }
341
+ // model fields should be stripped out from the input
342
+ if (isModelFieldType(type)) {
343
+ // except for belongs to relations - we need to replace them with the correct foreign key(s)
344
+ if (isTargetNameAssociation(association) &&
345
+ association.connectionType === 'BELONGS_TO') {
346
+ const targetNames = extractTargetNamesFromSrc(association);
347
+ if (targetNames) {
348
+ // instead of including the connected model itself, we add its key(s) to the mutation input
349
+ for (const targetName of targetNames) {
350
+ mutationInput[targetName] = parsedData[targetName];
597
351
  }
598
352
  }
599
- continue;
600
- }
601
- // scalar fields / non-model types
602
- if (operation === TransformerMutationType.UPDATE) {
603
- if (!parsedData.hasOwnProperty(name_1)) {
604
- // for update mutations - strip out a field if it's unchanged
605
- continue;
606
- }
607
353
  }
608
- // all other fields are added to the input object
609
- mutationInput[name_1] = parsedData[name_1];
354
+ continue;
610
355
  }
611
- }
612
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
613
- finally {
614
- try {
615
- if (modelFields_1_1 && !modelFields_1_1.done && (_b = modelFields_1.return)) _b.call(modelFields_1);
356
+ // scalar fields / non-model types
357
+ if (operation === TransformerMutationType.UPDATE) {
358
+ if (!parsedData.hasOwnProperty(name)) {
359
+ // for update mutations - strip out a field if it's unchanged
360
+ continue;
361
+ }
616
362
  }
617
- finally { if (e_3) throw e_3.error; }
363
+ // all other fields are added to the input object
364
+ mutationInput[name] = parsedData[name];
618
365
  }
619
366
  }
620
367
  // Build mutation variables input object
621
- var input = __assign(__assign({}, mutationInput), { _version: _version });
622
- var graphQLCondition = JSON.parse(condition);
623
- var variables = __assign({ input: input }, (operation === TransformerMutationType.CREATE
624
- ? {}
625
- : {
626
- condition: Object.keys(graphQLCondition).length > 0
627
- ? graphQLCondition
628
- : null,
629
- }));
368
+ const input = {
369
+ ...mutationInput,
370
+ _version,
371
+ };
372
+ const graphQLCondition = JSON.parse(condition);
373
+ const variables = {
374
+ input,
375
+ ...(operation === TransformerMutationType.CREATE
376
+ ? {}
377
+ : {
378
+ condition: Object.keys(graphQLCondition).length > 0
379
+ ? graphQLCondition
380
+ : null,
381
+ }),
382
+ };
630
383
  return [query, variables, graphQLCondition, opName, modelDefinition];
631
- };
632
- MutationProcessor.prototype.opTypeFromTransformerOperation = function (operation) {
384
+ }
385
+ opTypeFromTransformerOperation(operation) {
633
386
  switch (operation) {
634
387
  case TransformerMutationType.CREATE:
635
388
  return OpType.INSERT;
@@ -640,18 +393,17 @@ var MutationProcessor = /** @class */ (function () {
640
393
  case TransformerMutationType.GET: // Intentionally blank
641
394
  break;
642
395
  default:
643
- throw new Error("Invalid operation ".concat(operation));
396
+ throw new Error(`Invalid operation ${operation}`);
644
397
  }
645
398
  // because it makes TS happy ...
646
399
  return undefined;
647
- };
648
- MutationProcessor.prototype.pause = function () {
400
+ }
401
+ pause() {
649
402
  this.processing = false;
650
- };
651
- return MutationProcessor;
652
- }());
653
- var MAX_RETRY_DELAY_MS = 5 * 60 * 1000;
654
- var originalJitteredBackoff = jitteredBackoff(MAX_RETRY_DELAY_MS);
403
+ }
404
+ }
405
+ const MAX_RETRY_DELAY_MS = 5 * 60 * 1000;
406
+ const originalJitteredBackoff = jitteredBackoff(MAX_RETRY_DELAY_MS);
655
407
  /**
656
408
  * @private
657
409
  * Internal use of Amplify only.
@@ -667,8 +419,8 @@ var originalJitteredBackoff = jitteredBackoff(MAX_RETRY_DELAY_MS);
667
419
  * @param error tested to see if `.message` is 'Network Error'
668
420
  * @returns number | false :
669
421
  */
670
- export var safeJitteredBackoff = function (attempt, _args, error) {
671
- var attemptResult = originalJitteredBackoff(attempt);
422
+ export const safeJitteredBackoff = (attempt, _args, error) => {
423
+ const attemptResult = originalJitteredBackoff(attempt);
672
424
  // If this is the last attempt and it is a network error, we retry indefinitively every 5 minutes
673
425
  if (attemptResult === false &&
674
426
  (error || {}).message === 'Network Error') {