@aws-amplify/datastore 4.7.6-api-v6-models.b3abc9b.0 → 5.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.
- package/README.md +4 -0
- package/lib/authModeStrategies/defaultAuthStrategy.js +3 -2
- package/lib/authModeStrategies/index.js +3 -3
- package/lib/authModeStrategies/multiAuthStrategy.js +38 -53
- package/lib/datastore/datastore.d.ts +4 -5
- package/lib/datastore/datastore.js +929 -1284
- package/lib/index.d.ts +1 -1
- package/lib/index.js +26 -13
- package/lib/predicates/index.js +54 -69
- package/lib/predicates/next.d.ts +2 -2
- package/lib/predicates/next.js +313 -462
- package/lib/predicates/sort.js +24 -28
- package/lib/ssr/index.js +2 -2
- package/lib/storage/adapter/AsyncStorageAdapter.js +120 -342
- package/lib/storage/adapter/AsyncStorageDatabase.js +217 -421
- package/lib/storage/adapter/InMemoryStore.js +28 -51
- package/lib/storage/adapter/InMemoryStore.native.js +5 -3
- package/lib/storage/adapter/IndexedDBAdapter.js +466 -871
- package/lib/storage/adapter/StorageAdapterBase.js +180 -330
- package/lib/storage/adapter/getDefaultAdapter/index.js +8 -10
- package/lib/storage/adapter/getDefaultAdapter/index.native.js +5 -4
- package/lib/storage/adapter/index.js +0 -1
- package/lib/storage/relationship.js +177 -253
- package/lib/storage/storage.d.ts +4 -4
- package/lib/storage/storage.js +255 -433
- package/lib/sync/datastoreConnectivity.d.ts +2 -2
- package/lib/sync/datastoreConnectivity.js +29 -39
- package/lib/sync/datastoreReachability/index.d.ts +1 -3
- package/lib/sync/datastoreReachability/index.js +3 -3
- package/lib/sync/datastoreReachability/index.native.d.ts +1 -3
- package/lib/sync/datastoreReachability/index.native.js +4 -5
- package/lib/sync/index.d.ts +2 -2
- package/lib/sync/index.js +522 -827
- package/lib/sync/merger.js +31 -63
- package/lib/sync/outbox.js +148 -232
- package/lib/sync/processors/errorMaps.d.ts +1 -1
- package/lib/sync/processors/errorMaps.js +30 -47
- package/lib/sync/processors/mutation.d.ts +2 -2
- package/lib/sync/processors/mutation.js +343 -502
- package/lib/sync/processors/subscription.d.ts +5 -2
- package/lib/sync/processors/subscription.js +283 -437
- package/lib/sync/processors/sync.d.ts +2 -2
- package/lib/sync/processors/sync.js +279 -404
- package/lib/sync/utils.d.ts +5 -4
- package/lib/sync/utils.js +267 -320
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/lib/types.d.ts +138 -140
- package/lib/types.js +17 -24
- package/lib/util.d.ts +9 -17
- package/lib/util.js +387 -511
- package/lib-esm/authModeStrategies/defaultAuthStrategy.js +1 -2
- package/lib-esm/authModeStrategies/index.js +0 -1
- package/lib-esm/authModeStrategies/multiAuthStrategy.js +35 -52
- package/lib-esm/datastore/datastore.d.ts +4 -5
- package/lib-esm/datastore/datastore.js +888 -1247
- package/lib-esm/index.d.ts +1 -1
- package/lib-esm/index.js +6 -7
- package/lib-esm/predicates/index.js +53 -70
- package/lib-esm/predicates/next.d.ts +2 -2
- package/lib-esm/predicates/next.js +306 -459
- package/lib-esm/predicates/sort.js +23 -28
- package/lib-esm/ssr/index.js +1 -2
- package/lib-esm/storage/adapter/AsyncStorageAdapter.js +111 -338
- package/lib-esm/storage/adapter/AsyncStorageDatabase.js +212 -416
- package/lib-esm/storage/adapter/InMemoryStore.js +27 -52
- package/lib-esm/storage/adapter/InMemoryStore.native.js +0 -1
- package/lib-esm/storage/adapter/IndexedDBAdapter.js +438 -866
- package/lib-esm/storage/adapter/StorageAdapterBase.js +173 -325
- package/lib-esm/storage/adapter/getDefaultAdapter/index.js +2 -6
- package/lib-esm/storage/adapter/getDefaultAdapter/index.native.js +1 -2
- package/lib-esm/storage/adapter/index.js +1 -1
- package/lib-esm/storage/relationship.js +173 -251
- package/lib-esm/storage/storage.d.ts +4 -4
- package/lib-esm/storage/storage.js +242 -424
- package/lib-esm/sync/datastoreConnectivity.d.ts +2 -2
- package/lib-esm/sync/datastoreConnectivity.js +28 -39
- package/lib-esm/sync/datastoreReachability/index.d.ts +1 -3
- package/lib-esm/sync/datastoreReachability/index.js +2 -3
- package/lib-esm/sync/datastoreReachability/index.native.d.ts +1 -3
- package/lib-esm/sync/datastoreReachability/index.native.js +3 -4
- package/lib-esm/sync/index.d.ts +2 -2
- package/lib-esm/sync/index.js +502 -812
- package/lib-esm/sync/merger.js +28 -61
- package/lib-esm/sync/outbox.js +143 -228
- package/lib-esm/sync/processors/errorMaps.d.ts +1 -1
- package/lib-esm/sync/processors/errorMaps.js +32 -50
- package/lib-esm/sync/processors/mutation.d.ts +2 -2
- package/lib-esm/sync/processors/mutation.js +329 -490
- package/lib-esm/sync/processors/subscription.d.ts +5 -2
- package/lib-esm/sync/processors/subscription.js +266 -421
- package/lib-esm/sync/processors/sync.d.ts +2 -2
- package/lib-esm/sync/processors/sync.js +271 -397
- package/lib-esm/sync/utils.d.ts +5 -4
- package/lib-esm/sync/utils.js +252 -307
- package/lib-esm/tsconfig.tsbuildinfo +1 -0
- package/lib-esm/types.d.ts +138 -140
- package/lib-esm/types.js +16 -25
- package/lib-esm/util.d.ts +9 -17
- package/lib-esm/util.js +335 -497
- package/package.json +31 -26
- package/src/authModeStrategies/multiAuthStrategy.ts +15 -12
- package/src/datastore/datastore.ts +36 -35
- package/src/predicates/sort.ts +3 -1
- package/src/storage/adapter/InMemoryStore.ts +1 -1
- package/src/storage/adapter/IndexedDBAdapter.ts +2 -2
- package/src/storage/adapter/StorageAdapterBase.ts +2 -2
- package/src/storage/adapter/getDefaultAdapter/index.ts +1 -4
- package/src/storage/storage.ts +29 -24
- package/src/sync/datastoreConnectivity.ts +6 -6
- package/src/sync/datastoreReachability/index.native.ts +5 -3
- package/src/sync/datastoreReachability/index.ts +1 -1
- package/src/sync/index.ts +79 -89
- package/src/sync/processors/errorMaps.ts +7 -7
- package/src/sync/processors/mutation.ts +19 -13
- package/src/sync/processors/subscription.ts +221 -295
- package/src/sync/processors/sync.ts +11 -8
- package/src/sync/utils.ts +30 -15
- package/src/types.ts +4 -8
- package/src/util.ts +46 -9
- package/lib/.tsbuildinfo +0 -3
- package/lib/authModeStrategies/defaultAuthStrategy.js.map +0 -1
- package/lib/authModeStrategies/index.js.map +0 -1
- package/lib/authModeStrategies/multiAuthStrategy.js.map +0 -1
- package/lib/datastore/datastore.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/predicates/index.js.map +0 -1
- package/lib/predicates/next.js.map +0 -1
- package/lib/predicates/sort.js.map +0 -1
- package/lib/ssr/index.js.map +0 -1
- package/lib/storage/adapter/AsyncStorageAdapter.js.map +0 -1
- package/lib/storage/adapter/AsyncStorageDatabase.js.map +0 -1
- package/lib/storage/adapter/InMemoryStore.js.map +0 -1
- package/lib/storage/adapter/InMemoryStore.native.js.map +0 -1
- package/lib/storage/adapter/IndexedDBAdapter.js.map +0 -1
- package/lib/storage/adapter/StorageAdapterBase.js.map +0 -1
- package/lib/storage/adapter/getDefaultAdapter/index.js.map +0 -1
- package/lib/storage/adapter/getDefaultAdapter/index.native.js.map +0 -1
- package/lib/storage/adapter/index.js.map +0 -1
- package/lib/storage/relationship.js.map +0 -1
- package/lib/storage/storage.js.map +0 -1
- package/lib/sync/datastoreConnectivity.js.map +0 -1
- package/lib/sync/datastoreReachability/index.js.map +0 -1
- package/lib/sync/datastoreReachability/index.native.js.map +0 -1
- package/lib/sync/index.js.map +0 -1
- package/lib/sync/merger.js.map +0 -1
- package/lib/sync/outbox.js.map +0 -1
- package/lib/sync/processors/errorMaps.js.map +0 -1
- package/lib/sync/processors/mutation.js.map +0 -1
- package/lib/sync/processors/subscription.js.map +0 -1
- package/lib/sync/processors/sync.js.map +0 -1
- package/lib/sync/utils.js.map +0 -1
- package/lib/types.js.map +0 -1
- package/lib/util.js.map +0 -1
- package/lib-esm/.tsbuildinfo +0 -3
- package/lib-esm/authModeStrategies/defaultAuthStrategy.js.map +0 -1
- package/lib-esm/authModeStrategies/index.js.map +0 -1
- package/lib-esm/authModeStrategies/multiAuthStrategy.js.map +0 -1
- package/lib-esm/datastore/datastore.js.map +0 -1
- package/lib-esm/index.js.map +0 -1
- package/lib-esm/predicates/index.js.map +0 -1
- package/lib-esm/predicates/next.js.map +0 -1
- package/lib-esm/predicates/sort.js.map +0 -1
- package/lib-esm/ssr/index.js.map +0 -1
- package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +0 -1
- package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +0 -1
- package/lib-esm/storage/adapter/InMemoryStore.js.map +0 -1
- package/lib-esm/storage/adapter/InMemoryStore.native.js.map +0 -1
- package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +0 -1
- package/lib-esm/storage/adapter/StorageAdapterBase.js.map +0 -1
- package/lib-esm/storage/adapter/getDefaultAdapter/index.js.map +0 -1
- package/lib-esm/storage/adapter/getDefaultAdapter/index.native.js.map +0 -1
- package/lib-esm/storage/adapter/index.js.map +0 -1
- package/lib-esm/storage/relationship.js.map +0 -1
- package/lib-esm/storage/storage.js.map +0 -1
- package/lib-esm/sync/datastoreConnectivity.js.map +0 -1
- package/lib-esm/sync/datastoreReachability/index.js.map +0 -1
- package/lib-esm/sync/datastoreReachability/index.native.js.map +0 -1
- package/lib-esm/sync/index.js.map +0 -1
- package/lib-esm/sync/merger.js.map +0 -1
- package/lib-esm/sync/outbox.js.map +0 -1
- package/lib-esm/sync/processors/errorMaps.js.map +0 -1
- package/lib-esm/sync/processors/mutation.js.map +0 -1
- package/lib-esm/sync/processors/subscription.js.map +0 -1
- package/lib-esm/sync/processors/sync.js.map +0 -1
- package/lib-esm/sync/utils.js.map +0 -1
- package/lib-esm/types.js.map +0 -1
- package/lib-esm/util.js.map +0 -1
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
import { __awaiter, __generator, __read, __values } from "tslib";
|
|
2
1
|
import { InternalAPI } from '@aws-amplify/api/internals';
|
|
3
|
-
import Observable from '
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
4
3
|
import { ProcessName, } from '../../types';
|
|
5
4
|
import { buildGraphQLOperation, getModelAuthModes, getClientSideAuthError, getForbiddenError, predicateToGraphQLFilter, getTokenForCustomAuth, } from '../utils';
|
|
6
|
-
import { jitteredExponentialRetry, Category,
|
|
5
|
+
import { jitteredExponentialRetry, Category, DataStoreAction, NonRetryableError, BackgroundProcessManager, } from '@aws-amplify/core/internals/utils';
|
|
6
|
+
import { ConsoleLogger, Hub } from '@aws-amplify/core';
|
|
7
7
|
import { ModelPredicateCreator } from '../../predicates';
|
|
8
8
|
import { getSyncErrorType } from './errorMaps';
|
|
9
|
-
|
|
9
|
+
const opResultDefaults = {
|
|
10
10
|
items: [],
|
|
11
11
|
nextToken: null,
|
|
12
12
|
startedAt: null,
|
|
13
13
|
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (amplifyConfig === void 0) { amplifyConfig = {}; }
|
|
14
|
+
const logger = new ConsoleLogger('DataStore');
|
|
15
|
+
class SyncProcessor {
|
|
16
|
+
constructor(schema, syncPredicates, amplifyConfig = {}, authModeStrategy, errorHandler, amplifyContext) {
|
|
18
17
|
this.schema = schema;
|
|
19
18
|
this.syncPredicates = syncPredicates;
|
|
20
19
|
this.amplifyConfig = amplifyConfig;
|
|
@@ -26,417 +25,292 @@ var SyncProcessor = /** @class */ (function () {
|
|
|
26
25
|
amplifyContext.InternalAPI = amplifyContext.InternalAPI || InternalAPI;
|
|
27
26
|
this.generateQueries();
|
|
28
27
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
Object.values(this.schema.namespaces).forEach(function (namespace) {
|
|
28
|
+
generateQueries() {
|
|
29
|
+
Object.values(this.schema.namespaces).forEach(namespace => {
|
|
32
30
|
Object.values(namespace.models)
|
|
33
|
-
.filter(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
.forEach(function (model) {
|
|
38
|
-
var _a = __read(buildGraphQLOperation(namespace, model, 'LIST'), 1), _b = __read(_a[0]), opNameQuery = _b.slice(1);
|
|
39
|
-
_this.typeQuery.set(model, opNameQuery);
|
|
31
|
+
.filter(({ syncable }) => syncable)
|
|
32
|
+
.forEach(model => {
|
|
33
|
+
const [[, ...opNameQuery]] = buildGraphQLOperation(namespace, model, 'LIST');
|
|
34
|
+
this.typeQuery.set(model, opNameQuery);
|
|
40
35
|
});
|
|
41
36
|
});
|
|
42
|
-
}
|
|
43
|
-
|
|
37
|
+
}
|
|
38
|
+
graphqlFilterFromPredicate(model) {
|
|
44
39
|
if (!this.syncPredicates) {
|
|
45
40
|
return null;
|
|
46
41
|
}
|
|
47
|
-
|
|
42
|
+
const predicatesGroup = ModelPredicateCreator.getPredicates(this.syncPredicates.get(model), false);
|
|
48
43
|
if (!predicatesGroup) {
|
|
49
44
|
return null;
|
|
50
45
|
}
|
|
51
46
|
return predicateToGraphQLFilter(predicatesGroup);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
47
|
+
}
|
|
48
|
+
async retrievePage(modelDefinition, lastSync, nextToken, limit = null, filter, onTerminate) {
|
|
49
|
+
const [opName, query] = this.typeQuery.get(modelDefinition);
|
|
50
|
+
const variables = {
|
|
51
|
+
limit,
|
|
52
|
+
nextToken,
|
|
53
|
+
lastSync,
|
|
54
|
+
filter,
|
|
55
|
+
};
|
|
56
|
+
const modelAuthModes = await getModelAuthModes({
|
|
57
|
+
authModeStrategy: this.authModeStrategy,
|
|
58
|
+
defaultAuthMode: this.amplifyConfig.aws_appsync_authenticationType,
|
|
59
|
+
modelName: modelDefinition.name,
|
|
60
|
+
schema: this.schema,
|
|
61
|
+
});
|
|
62
|
+
// sync only needs the READ auth mode(s)
|
|
63
|
+
const readAuthModes = modelAuthModes.READ;
|
|
64
|
+
let authModeAttempts = 0;
|
|
65
|
+
const authModeRetry = async () => {
|
|
66
|
+
if (!this.runningProcesses.isOpen) {
|
|
67
|
+
throw new Error('sync.retreievePage termination was requested. Exiting.');
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
logger.debug(`Attempting sync with authMode: ${readAuthModes[authModeAttempts]}`);
|
|
71
|
+
const response = await this.jitteredRetry({
|
|
72
|
+
query,
|
|
73
|
+
variables,
|
|
74
|
+
opName,
|
|
75
|
+
modelDefinition,
|
|
76
|
+
authMode: readAuthModes[authModeAttempts],
|
|
77
|
+
onTerminate,
|
|
78
|
+
});
|
|
79
|
+
logger.debug(`Sync successful with authMode: ${readAuthModes[authModeAttempts]}`);
|
|
80
|
+
return response;
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
authModeAttempts++;
|
|
84
|
+
if (authModeAttempts >= readAuthModes.length) {
|
|
85
|
+
const authMode = readAuthModes[authModeAttempts - 1];
|
|
86
|
+
logger.debug(`Sync failed with authMode: ${authMode}`, error);
|
|
87
|
+
if (getClientSideAuthError(error) || getForbiddenError(error)) {
|
|
88
|
+
// return empty list of data so DataStore will continue to sync other models
|
|
89
|
+
logger.warn(`User is unauthorized to query ${opName} with auth mode ${authMode}. No data could be returned.`);
|
|
90
|
+
return {
|
|
91
|
+
data: {
|
|
92
|
+
[opName]: opResultDefaults,
|
|
93
|
+
},
|
|
67
94
|
};
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
defaultAuthMode: this.amplifyConfig.aws_appsync_authenticationType,
|
|
71
|
-
modelName: modelDefinition.name,
|
|
72
|
-
schema: this.schema,
|
|
73
|
-
})];
|
|
74
|
-
case 1:
|
|
75
|
-
modelAuthModes = _d.sent();
|
|
76
|
-
readAuthModes = modelAuthModes.READ;
|
|
77
|
-
authModeAttempts = 0;
|
|
78
|
-
authModeRetry = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
79
|
-
var response, error_1, authMode;
|
|
80
|
-
var _a;
|
|
81
|
-
return __generator(this, function (_b) {
|
|
82
|
-
switch (_b.label) {
|
|
83
|
-
case 0:
|
|
84
|
-
if (!this.runningProcesses.isOpen) {
|
|
85
|
-
throw new Error('sync.retreievePage termination was requested. Exiting.');
|
|
86
|
-
}
|
|
87
|
-
_b.label = 1;
|
|
88
|
-
case 1:
|
|
89
|
-
_b.trys.push([1, 3, , 5]);
|
|
90
|
-
logger.debug("Attempting sync with authMode: " + readAuthModes[authModeAttempts]);
|
|
91
|
-
return [4 /*yield*/, this.jitteredRetry({
|
|
92
|
-
query: query,
|
|
93
|
-
variables: variables,
|
|
94
|
-
opName: opName,
|
|
95
|
-
modelDefinition: modelDefinition,
|
|
96
|
-
authMode: readAuthModes[authModeAttempts],
|
|
97
|
-
onTerminate: onTerminate,
|
|
98
|
-
})];
|
|
99
|
-
case 2:
|
|
100
|
-
response = _b.sent();
|
|
101
|
-
logger.debug("Sync successful with authMode: " + readAuthModes[authModeAttempts]);
|
|
102
|
-
return [2 /*return*/, response];
|
|
103
|
-
case 3:
|
|
104
|
-
error_1 = _b.sent();
|
|
105
|
-
authModeAttempts++;
|
|
106
|
-
if (authModeAttempts >= readAuthModes.length) {
|
|
107
|
-
authMode = readAuthModes[authModeAttempts - 1];
|
|
108
|
-
logger.debug("Sync failed with authMode: " + authMode, error_1);
|
|
109
|
-
if (getClientSideAuthError(error_1) || getForbiddenError(error_1)) {
|
|
110
|
-
// return empty list of data so DataStore will continue to sync other models
|
|
111
|
-
logger.warn("User is unauthorized to query " + opName + " with auth mode " + authMode + ". No data could be returned.");
|
|
112
|
-
return [2 /*return*/, {
|
|
113
|
-
data: (_a = {},
|
|
114
|
-
_a[opName] = opResultDefaults,
|
|
115
|
-
_a),
|
|
116
|
-
}];
|
|
117
|
-
}
|
|
118
|
-
throw error_1;
|
|
119
|
-
}
|
|
120
|
-
logger.debug("Sync failed with authMode: " + readAuthModes[authModeAttempts - 1] + ". Retrying with authMode: " + readAuthModes[authModeAttempts]);
|
|
121
|
-
return [4 /*yield*/, authModeRetry()];
|
|
122
|
-
case 4: return [2 /*return*/, _b.sent()];
|
|
123
|
-
case 5: return [2 /*return*/];
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
}); };
|
|
127
|
-
return [4 /*yield*/, authModeRetry()];
|
|
128
|
-
case 2:
|
|
129
|
-
data = (_d.sent()).data;
|
|
130
|
-
_b = data, _c = opName, opResult = _b[_c];
|
|
131
|
-
items = opResult.items, newNextToken = opResult.nextToken, startedAt = opResult.startedAt;
|
|
132
|
-
return [2 /*return*/, {
|
|
133
|
-
nextToken: newNextToken,
|
|
134
|
-
startedAt: startedAt,
|
|
135
|
-
items: items,
|
|
136
|
-
}];
|
|
95
|
+
}
|
|
96
|
+
throw error;
|
|
137
97
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
model: modelDefinition.name,
|
|
197
|
-
operation: opName,
|
|
198
|
-
errorType: getSyncErrorType(err),
|
|
199
|
-
process: ProcessName.sync,
|
|
200
|
-
remoteModel: null,
|
|
201
|
-
cause: err,
|
|
202
|
-
})];
|
|
203
|
-
case 1:
|
|
204
|
-
_a.sent();
|
|
205
|
-
return [3 /*break*/, 3];
|
|
206
|
-
case 2:
|
|
207
|
-
e_1 = _a.sent();
|
|
208
|
-
logger.error('Sync error handler failed with:', e_1);
|
|
209
|
-
return [3 /*break*/, 3];
|
|
210
|
-
case 3: return [2 /*return*/];
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
}); }))];
|
|
214
|
-
case 4:
|
|
215
|
-
_e.sent();
|
|
216
|
-
Hub.dispatch('datastore', {
|
|
217
|
-
event: 'nonApplicableDataReceived',
|
|
218
|
-
data: {
|
|
219
|
-
errors: otherErrors,
|
|
220
|
-
modelName: modelDefinition.name,
|
|
221
|
-
},
|
|
222
|
-
});
|
|
223
|
-
_e.label = 5;
|
|
224
|
-
case 5:
|
|
225
|
-
/**
|
|
226
|
-
* Handle $util.unauthorized() in resolver request mapper, which responses with something
|
|
227
|
-
* like this:
|
|
228
|
-
*
|
|
229
|
-
* ```
|
|
230
|
-
* {
|
|
231
|
-
* data: { syncYourModel: null },
|
|
232
|
-
* errors: [
|
|
233
|
-
* {
|
|
234
|
-
* path: ['syncLegacyJSONComments'],
|
|
235
|
-
* data: null,
|
|
236
|
-
* errorType: 'Unauthorized',
|
|
237
|
-
* errorInfo: null,
|
|
238
|
-
* locations: [{ line: 2, column: 3, sourceName: null }],
|
|
239
|
-
* message:
|
|
240
|
-
* 'Not Authorized to access syncYourModel on type Query',
|
|
241
|
-
* },
|
|
242
|
-
* ],
|
|
243
|
-
* }
|
|
244
|
-
* ```
|
|
245
|
-
*
|
|
246
|
-
* The correct handling for this is to signal that we've encountered a non-retryable error,
|
|
247
|
-
* since the server has responded with an auth error and *NO DATA* at this point.
|
|
248
|
-
*/
|
|
249
|
-
if (unauthorized) {
|
|
250
|
-
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: modelDefinition.name,
|
|
255
|
-
operation: opName,
|
|
256
|
-
errorType: getSyncErrorType(error_2.errors[0]),
|
|
257
|
-
process: ProcessName.sync,
|
|
258
|
-
remoteModel: null,
|
|
259
|
-
cause: error_2,
|
|
260
|
-
});
|
|
261
|
-
throw new NonRetryableError(error_2);
|
|
262
|
-
}
|
|
263
|
-
if ((_d = (_c = result.data) === null || _c === void 0 ? void 0 : _c[opName].items) === null || _d === void 0 ? void 0 : _d.length) {
|
|
264
|
-
return [2 /*return*/, result];
|
|
265
|
-
}
|
|
266
|
-
throw error_2;
|
|
267
|
-
case 6: return [2 /*return*/];
|
|
268
|
-
}
|
|
98
|
+
logger.debug(`Sync failed with authMode: ${readAuthModes[authModeAttempts - 1]}. Retrying with authMode: ${readAuthModes[authModeAttempts]}`);
|
|
99
|
+
return await authModeRetry();
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const { data } = await authModeRetry();
|
|
103
|
+
const { [opName]: opResult } = data;
|
|
104
|
+
const { items, nextToken: newNextToken, startedAt } = opResult;
|
|
105
|
+
return {
|
|
106
|
+
nextToken: newNextToken,
|
|
107
|
+
startedAt,
|
|
108
|
+
items,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
async jitteredRetry({ query, variables, opName, modelDefinition, authMode, onTerminate, }) {
|
|
112
|
+
return await jitteredExponentialRetry(async (query, variables) => {
|
|
113
|
+
try {
|
|
114
|
+
const authToken = await getTokenForCustomAuth(authMode, this.amplifyConfig);
|
|
115
|
+
const customUserAgentDetails = {
|
|
116
|
+
category: Category.DataStore,
|
|
117
|
+
action: DataStoreAction.GraphQl,
|
|
118
|
+
};
|
|
119
|
+
return await this.amplifyContext.InternalAPI.graphql({
|
|
120
|
+
query,
|
|
121
|
+
variables,
|
|
122
|
+
authMode,
|
|
123
|
+
authToken,
|
|
124
|
+
}, undefined, customUserAgentDetails);
|
|
125
|
+
// TODO: onTerminate.then(() => API.cancel(...))
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
// Catch client-side (GraphQLAuthError) & 401/403 errors here so that we don't continue to retry
|
|
129
|
+
const clientOrForbiddenErrorMessage = getClientSideAuthError(error) || getForbiddenError(error);
|
|
130
|
+
if (clientOrForbiddenErrorMessage) {
|
|
131
|
+
logger.error('Sync processor retry error:', error);
|
|
132
|
+
throw new NonRetryableError(clientOrForbiddenErrorMessage);
|
|
133
|
+
}
|
|
134
|
+
const hasItems = Boolean(error?.data?.[opName]?.items);
|
|
135
|
+
const unauthorized = error?.errors &&
|
|
136
|
+
error.errors.some(err => err.errorType === 'Unauthorized');
|
|
137
|
+
const otherErrors = error?.errors &&
|
|
138
|
+
error.errors.filter(err => err.errorType !== 'Unauthorized');
|
|
139
|
+
const result = error;
|
|
140
|
+
if (hasItems) {
|
|
141
|
+
result.data[opName].items = result.data[opName].items.filter(item => item !== null);
|
|
142
|
+
}
|
|
143
|
+
if (hasItems && otherErrors?.length) {
|
|
144
|
+
await Promise.all(otherErrors.map(async (err) => {
|
|
145
|
+
try {
|
|
146
|
+
await this.errorHandler({
|
|
147
|
+
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',
|
|
148
|
+
localModel: null,
|
|
149
|
+
message: err.message,
|
|
150
|
+
model: modelDefinition.name,
|
|
151
|
+
operation: opName,
|
|
152
|
+
errorType: getSyncErrorType(err),
|
|
153
|
+
process: ProcessName.sync,
|
|
154
|
+
remoteModel: null,
|
|
155
|
+
cause: err,
|
|
269
156
|
});
|
|
270
|
-
}
|
|
271
|
-
|
|
157
|
+
}
|
|
158
|
+
catch (e) {
|
|
159
|
+
logger.error('Sync error handler failed with:', e);
|
|
160
|
+
}
|
|
161
|
+
}));
|
|
162
|
+
Hub.dispatch('datastore', {
|
|
163
|
+
event: 'nonApplicableDataReceived',
|
|
164
|
+
data: {
|
|
165
|
+
errors: otherErrors,
|
|
166
|
+
modelName: modelDefinition.name,
|
|
167
|
+
},
|
|
168
|
+
});
|
|
272
169
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
170
|
+
/**
|
|
171
|
+
* Handle $util.unauthorized() in resolver request mapper, which responses with something
|
|
172
|
+
* like this:
|
|
173
|
+
*
|
|
174
|
+
* ```
|
|
175
|
+
* {
|
|
176
|
+
* data: { syncYourModel: null },
|
|
177
|
+
* errors: [
|
|
178
|
+
* {
|
|
179
|
+
* path: ['syncLegacyJSONComments'],
|
|
180
|
+
* data: null,
|
|
181
|
+
* errorType: 'Unauthorized',
|
|
182
|
+
* errorInfo: null,
|
|
183
|
+
* locations: [{ line: 2, column: 3, sourceName: null }],
|
|
184
|
+
* message:
|
|
185
|
+
* 'Not Authorized to access syncYourModel on type Query',
|
|
186
|
+
* },
|
|
187
|
+
* ],
|
|
188
|
+
* }
|
|
189
|
+
* ```
|
|
190
|
+
*
|
|
191
|
+
* The correct handling for this is to signal that we've encountered a non-retryable error,
|
|
192
|
+
* since the server has responded with an auth error and *NO DATA* at this point.
|
|
193
|
+
*/
|
|
194
|
+
if (unauthorized) {
|
|
195
|
+
this.errorHandler({
|
|
196
|
+
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',
|
|
197
|
+
localModel: null,
|
|
198
|
+
message: error.message,
|
|
199
|
+
model: modelDefinition.name,
|
|
200
|
+
operation: opName,
|
|
201
|
+
errorType: getSyncErrorType(error.errors[0]),
|
|
202
|
+
process: ProcessName.sync,
|
|
203
|
+
remoteModel: null,
|
|
204
|
+
cause: error,
|
|
205
|
+
});
|
|
206
|
+
throw new NonRetryableError(error);
|
|
289
207
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
208
|
+
if (result.data?.[opName]?.items?.length) {
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
throw error;
|
|
212
|
+
}
|
|
213
|
+
}, [query, variables], undefined, onTerminate);
|
|
214
|
+
}
|
|
215
|
+
start(typesLastSync) {
|
|
216
|
+
const { maxRecordsToSync, syncPageSize } = this.amplifyConfig;
|
|
217
|
+
const parentPromises = new Map();
|
|
218
|
+
const observable = new Observable(observer => {
|
|
219
|
+
const sortedTypesLastSyncs = Object.values(this.schema.namespaces).reduce((map, namespace) => {
|
|
220
|
+
for (const modelName of Array.from(namespace.modelTopologicalOrdering.keys())) {
|
|
221
|
+
const typeLastSync = typesLastSync.get(namespace.models[modelName]);
|
|
222
|
+
map.set(namespace.models[modelName], typeLastSync);
|
|
296
223
|
}
|
|
297
224
|
return map;
|
|
298
225
|
}, new Map());
|
|
299
|
-
|
|
300
|
-
.filter(
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
226
|
+
const allModelsReady = Array.from(sortedTypesLastSyncs.entries())
|
|
227
|
+
.filter(([{ syncable }]) => syncable)
|
|
228
|
+
.map(([modelDefinition, [namespace, lastSync]]) => this.runningProcesses.isOpen &&
|
|
229
|
+
this.runningProcesses.add(async (onTerminate) => {
|
|
230
|
+
let done = false;
|
|
231
|
+
let nextToken = null;
|
|
232
|
+
let startedAt = null;
|
|
233
|
+
let items = null;
|
|
234
|
+
let recordsReceived = 0;
|
|
235
|
+
const filter = this.graphqlFilterFromPredicate(modelDefinition);
|
|
236
|
+
const parents = this.schema.namespaces[namespace].modelTopologicalOrdering.get(modelDefinition.name);
|
|
237
|
+
const promises = parents.map(parent => parentPromises.get(`${namespace}_${parent}`));
|
|
238
|
+
const promise = new Promise(async (res) => {
|
|
239
|
+
await Promise.all(promises);
|
|
240
|
+
do {
|
|
241
|
+
/**
|
|
242
|
+
* If `runningProcesses` is not open, it means that the sync processor has been
|
|
243
|
+
* stopped (for example by calling `DataStore.clear()` upstream) and has not yet
|
|
244
|
+
* finished terminating and/or waiting for its background processes to complete.
|
|
245
|
+
*/
|
|
246
|
+
if (!this.runningProcesses.isOpen) {
|
|
247
|
+
logger.debug(`Sync processor has been stopped, terminating sync for ${modelDefinition.name}`);
|
|
248
|
+
return res();
|
|
249
|
+
}
|
|
250
|
+
const limit = Math.min(maxRecordsToSync - recordsReceived, syncPageSize);
|
|
251
|
+
/**
|
|
252
|
+
* It's possible that `retrievePage` will fail.
|
|
253
|
+
* If it does fail, continue merging the rest of the data,
|
|
254
|
+
* and invoke the error handler for non-applicable data.
|
|
255
|
+
*/
|
|
256
|
+
try {
|
|
257
|
+
({ items, nextToken, startedAt } = await this.retrievePage(modelDefinition, lastSync, nextToken, limit, filter, onTerminate));
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
try {
|
|
261
|
+
await this.errorHandler({
|
|
262
|
+
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',
|
|
263
|
+
localModel: null,
|
|
264
|
+
message: error.message,
|
|
265
|
+
model: modelDefinition.name,
|
|
266
|
+
operation: null,
|
|
267
|
+
errorType: getSyncErrorType(error),
|
|
268
|
+
process: ProcessName.sync,
|
|
269
|
+
remoteModel: null,
|
|
270
|
+
cause: error,
|
|
322
271
|
});
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
* finished terminating and/or waiting for its background processes to complete.
|
|
337
|
-
*/
|
|
338
|
-
if (!this.runningProcesses.isOpen) {
|
|
339
|
-
logger.debug("Sync processor has been stopped, terminating sync for " + modelDefinition.name);
|
|
340
|
-
return [2 /*return*/, res()];
|
|
341
|
-
}
|
|
342
|
-
limit = Math.min(maxRecordsToSync - recordsReceived, syncPageSize);
|
|
343
|
-
_b.label = 3;
|
|
344
|
-
case 3:
|
|
345
|
-
_b.trys.push([3, 5, , 10]);
|
|
346
|
-
return [4 /*yield*/, this.retrievePage(modelDefinition, lastSync, nextToken, limit, filter, onTerminate)];
|
|
347
|
-
case 4:
|
|
348
|
-
(_a = _b.sent(), items = _a.items, nextToken = _a.nextToken, startedAt = _a.startedAt);
|
|
349
|
-
return [3 /*break*/, 10];
|
|
350
|
-
case 5:
|
|
351
|
-
error_3 = _b.sent();
|
|
352
|
-
_b.label = 6;
|
|
353
|
-
case 6:
|
|
354
|
-
_b.trys.push([6, 8, , 9]);
|
|
355
|
-
return [4 /*yield*/, this.errorHandler({
|
|
356
|
-
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',
|
|
357
|
-
localModel: null,
|
|
358
|
-
message: error_3.message,
|
|
359
|
-
model: modelDefinition.name,
|
|
360
|
-
operation: null,
|
|
361
|
-
errorType: getSyncErrorType(error_3),
|
|
362
|
-
process: ProcessName.sync,
|
|
363
|
-
remoteModel: null,
|
|
364
|
-
cause: error_3,
|
|
365
|
-
})];
|
|
366
|
-
case 7:
|
|
367
|
-
_b.sent();
|
|
368
|
-
return [3 /*break*/, 9];
|
|
369
|
-
case 8:
|
|
370
|
-
e_3 = _b.sent();
|
|
371
|
-
logger.error('Sync error handler failed with:', e_3);
|
|
372
|
-
return [3 /*break*/, 9];
|
|
373
|
-
case 9:
|
|
374
|
-
/**
|
|
375
|
-
* If there's an error, this model fails, but the rest of the sync should
|
|
376
|
-
* continue. To facilitate this, we explicitly mark this model as `done`
|
|
377
|
-
* with no items and allow the loop to continue organically. This ensures
|
|
378
|
-
* all callbacks (subscription messages) happen as normal, so anything
|
|
379
|
-
* waiting on them knows the model is as done as it can be.
|
|
380
|
-
*/
|
|
381
|
-
done = true;
|
|
382
|
-
items = [];
|
|
383
|
-
return [3 /*break*/, 10];
|
|
384
|
-
case 10:
|
|
385
|
-
recordsReceived += items.length;
|
|
386
|
-
done =
|
|
387
|
-
nextToken === null || recordsReceived >= maxRecordsToSync;
|
|
388
|
-
observer.next({
|
|
389
|
-
namespace: namespace,
|
|
390
|
-
modelDefinition: modelDefinition,
|
|
391
|
-
items: items,
|
|
392
|
-
done: done,
|
|
393
|
-
startedAt: startedAt,
|
|
394
|
-
isFullSync: !lastSync,
|
|
395
|
-
});
|
|
396
|
-
_b.label = 11;
|
|
397
|
-
case 11:
|
|
398
|
-
if (!done) return [3 /*break*/, 2];
|
|
399
|
-
_b.label = 12;
|
|
400
|
-
case 12:
|
|
401
|
-
res();
|
|
402
|
-
return [2 /*return*/];
|
|
403
|
-
}
|
|
404
|
-
});
|
|
405
|
-
}); });
|
|
406
|
-
parentPromises.set(namespace + "_" + modelDefinition.name, promise);
|
|
407
|
-
return [4 /*yield*/, promise];
|
|
408
|
-
case 1:
|
|
409
|
-
_a.sent();
|
|
410
|
-
return [2 /*return*/];
|
|
272
|
+
}
|
|
273
|
+
catch (e) {
|
|
274
|
+
logger.error('Sync error handler failed with:', e);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* If there's an error, this model fails, but the rest of the sync should
|
|
278
|
+
* continue. To facilitate this, we explicitly mark this model as `done`
|
|
279
|
+
* with no items and allow the loop to continue organically. This ensures
|
|
280
|
+
* all callbacks (subscription messages) happen as normal, so anything
|
|
281
|
+
* waiting on them knows the model is as done as it can be.
|
|
282
|
+
*/
|
|
283
|
+
done = true;
|
|
284
|
+
items = [];
|
|
411
285
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
286
|
+
recordsReceived += items.length;
|
|
287
|
+
done =
|
|
288
|
+
nextToken === null || recordsReceived >= maxRecordsToSync;
|
|
289
|
+
observer.next({
|
|
290
|
+
namespace,
|
|
291
|
+
modelDefinition,
|
|
292
|
+
items,
|
|
293
|
+
done,
|
|
294
|
+
startedAt,
|
|
295
|
+
isFullSync: !lastSync,
|
|
296
|
+
});
|
|
297
|
+
} while (!done);
|
|
298
|
+
res();
|
|
299
|
+
});
|
|
300
|
+
parentPromises.set(`${namespace}_${modelDefinition.name}`, promise);
|
|
301
|
+
await promise;
|
|
302
|
+
}, `adding model ${modelDefinition.name}`));
|
|
303
|
+
Promise.all(allModelsReady).then(() => {
|
|
416
304
|
observer.complete();
|
|
417
305
|
});
|
|
418
306
|
});
|
|
419
307
|
return observable;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
case 1:
|
|
429
|
-
_a.sent();
|
|
430
|
-
return [4 /*yield*/, this.runningProcesses.open()];
|
|
431
|
-
case 2:
|
|
432
|
-
_a.sent();
|
|
433
|
-
logger.debug('sync processor stopped');
|
|
434
|
-
return [2 /*return*/];
|
|
435
|
-
}
|
|
436
|
-
});
|
|
437
|
-
});
|
|
438
|
-
};
|
|
439
|
-
return SyncProcessor;
|
|
440
|
-
}());
|
|
308
|
+
}
|
|
309
|
+
async stop() {
|
|
310
|
+
logger.debug('stopping sync processor');
|
|
311
|
+
await this.runningProcesses.close();
|
|
312
|
+
await this.runningProcesses.open();
|
|
313
|
+
logger.debug('sync processor stopped');
|
|
314
|
+
}
|
|
315
|
+
}
|
|
441
316
|
export { SyncProcessor };
|
|
442
|
-
//# sourceMappingURL=sync.js.map
|