@aws-amplify/datastore 5.0.32 → 5.0.33-s-auth.30d0cd2.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/dist/cjs/authModeStrategies/multiAuthStrategy.js +1 -1
- package/dist/cjs/authModeStrategies/multiAuthStrategy.js.map +1 -1
- package/dist/cjs/datastore/datastore.js +46 -41
- package/dist/cjs/datastore/datastore.js.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/predicates/index.js +1 -0
- package/dist/cjs/predicates/index.js.map +1 -1
- package/dist/cjs/predicates/next.js +13 -12
- package/dist/cjs/predicates/next.js.map +1 -1
- package/dist/cjs/predicates/sort.js +2 -2
- package/dist/cjs/predicates/sort.js.map +1 -1
- package/dist/cjs/storage/adapter/AsyncStorageAdapter.js +21 -18
- package/dist/cjs/storage/adapter/AsyncStorageAdapter.js.map +1 -1
- package/dist/cjs/storage/adapter/AsyncStorageDatabase.js +10 -9
- package/dist/cjs/storage/adapter/AsyncStorageDatabase.js.map +1 -1
- package/dist/cjs/storage/adapter/InMemoryStore.js +4 -1
- package/dist/cjs/storage/adapter/InMemoryStore.js.map +1 -1
- package/dist/cjs/storage/adapter/IndexedDBAdapter.js +21 -23
- package/dist/cjs/storage/adapter/IndexedDBAdapter.js.map +1 -1
- package/dist/cjs/storage/adapter/StorageAdapterBase.js +7 -7
- package/dist/cjs/storage/adapter/StorageAdapterBase.js.map +1 -1
- package/dist/cjs/storage/adapter/getDefaultAdapter/index.js +4 -1
- package/dist/cjs/storage/adapter/getDefaultAdapter/index.js.map +1 -1
- package/dist/cjs/storage/adapter/getDefaultAdapter/index.native.js +1 -0
- package/dist/cjs/storage/adapter/getDefaultAdapter/index.native.js.map +1 -1
- package/dist/cjs/storage/relationship.js +1 -0
- package/dist/cjs/storage/relationship.js.map +1 -1
- package/dist/cjs/storage/storage.js +14 -14
- package/dist/cjs/storage/storage.js.map +1 -1
- package/dist/cjs/sync/datastoreConnectivity.js +0 -3
- package/dist/cjs/sync/datastoreConnectivity.js.map +1 -1
- package/dist/cjs/sync/index.js +47 -43
- package/dist/cjs/sync/index.js.map +1 -1
- package/dist/cjs/sync/merger.js +1 -1
- package/dist/cjs/sync/merger.js.map +1 -1
- package/dist/cjs/sync/outbox.js +19 -17
- package/dist/cjs/sync/outbox.js.map +1 -1
- package/dist/cjs/sync/processors/errorMaps.js.map +1 -1
- package/dist/cjs/sync/processors/mutation.js +31 -28
- package/dist/cjs/sync/processors/mutation.js.map +1 -1
- package/dist/cjs/sync/processors/subscription.js +21 -12
- package/dist/cjs/sync/processors/subscription.js.map +1 -1
- package/dist/cjs/sync/processors/sync.js +25 -21
- package/dist/cjs/sync/processors/sync.js.map +1 -1
- package/dist/cjs/sync/utils.js +20 -21
- package/dist/cjs/sync/utils.js.map +1 -1
- package/dist/cjs/types.js +1 -0
- package/dist/cjs/types.js.map +1 -1
- package/dist/cjs/util.js +46 -25
- package/dist/cjs/util.js.map +1 -1
- package/dist/esm/authModeStrategies/multiAuthStrategy.d.ts +1 -1
- package/dist/esm/authModeStrategies/multiAuthStrategy.mjs +1 -1
- package/dist/esm/authModeStrategies/multiAuthStrategy.mjs.map +1 -1
- package/dist/esm/datastore/datastore.d.ts +4 -6
- package/dist/esm/datastore/datastore.mjs +42 -34
- package/dist/esm/datastore/datastore.mjs.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.mjs +2 -2
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/predicates/index.mjs +1 -0
- package/dist/esm/predicates/index.mjs.map +1 -1
- package/dist/esm/predicates/next.d.ts +7 -7
- package/dist/esm/predicates/next.mjs +13 -12
- package/dist/esm/predicates/next.mjs.map +1 -1
- package/dist/esm/predicates/sort.d.ts +1 -1
- package/dist/esm/predicates/sort.mjs +2 -2
- package/dist/esm/predicates/sort.mjs.map +1 -1
- package/dist/esm/storage/adapter/AsyncStorageAdapter.d.ts +1 -1
- package/dist/esm/storage/adapter/AsyncStorageAdapter.mjs +21 -18
- package/dist/esm/storage/adapter/AsyncStorageAdapter.mjs.map +1 -1
- package/dist/esm/storage/adapter/AsyncStorageDatabase.mjs +10 -9
- package/dist/esm/storage/adapter/AsyncStorageDatabase.mjs.map +1 -1
- package/dist/esm/storage/adapter/InMemoryStore.mjs +4 -1
- package/dist/esm/storage/adapter/InMemoryStore.mjs.map +1 -1
- package/dist/esm/storage/adapter/IndexedDBAdapter.mjs +21 -23
- package/dist/esm/storage/adapter/IndexedDBAdapter.mjs.map +1 -1
- package/dist/esm/storage/adapter/StorageAdapterBase.d.ts +2 -2
- package/dist/esm/storage/adapter/StorageAdapterBase.mjs +7 -7
- package/dist/esm/storage/adapter/StorageAdapterBase.mjs.map +1 -1
- package/dist/esm/storage/adapter/getDefaultAdapter/index.mjs +3 -1
- package/dist/esm/storage/adapter/getDefaultAdapter/index.mjs.map +1 -1
- package/dist/esm/storage/adapter/getDefaultAdapter/index.native.mjs +1 -0
- package/dist/esm/storage/adapter/getDefaultAdapter/index.native.mjs.map +1 -1
- package/dist/esm/storage/adapter/index.d.ts +1 -1
- package/dist/esm/storage/relationship.mjs +1 -0
- package/dist/esm/storage/relationship.mjs.map +1 -1
- package/dist/esm/storage/storage.d.ts +11 -11
- package/dist/esm/storage/storage.mjs +10 -10
- package/dist/esm/storage/storage.mjs.map +1 -1
- package/dist/esm/sync/datastoreConnectivity.d.ts +2 -2
- package/dist/esm/sync/datastoreConnectivity.mjs +0 -3
- package/dist/esm/sync/datastoreConnectivity.mjs.map +1 -1
- package/dist/esm/sync/index.d.ts +3 -3
- package/dist/esm/sync/index.mjs +47 -43
- package/dist/esm/sync/index.mjs.map +1 -1
- package/dist/esm/sync/merger.d.ts +1 -1
- package/dist/esm/sync/merger.mjs +1 -1
- package/dist/esm/sync/merger.mjs.map +1 -1
- package/dist/esm/sync/outbox.d.ts +4 -4
- package/dist/esm/sync/outbox.mjs +19 -17
- package/dist/esm/sync/outbox.mjs.map +1 -1
- package/dist/esm/sync/processors/errorMaps.mjs.map +1 -1
- package/dist/esm/sync/processors/mutation.d.ts +5 -5
- package/dist/esm/sync/processors/mutation.mjs +31 -28
- package/dist/esm/sync/processors/mutation.mjs.map +1 -1
- package/dist/esm/sync/processors/subscription.d.ts +1 -1
- package/dist/esm/sync/processors/subscription.mjs +21 -12
- package/dist/esm/sync/processors/subscription.mjs.map +1 -1
- package/dist/esm/sync/processors/sync.d.ts +3 -3
- package/dist/esm/sync/processors/sync.mjs +13 -9
- package/dist/esm/sync/processors/sync.mjs.map +1 -1
- package/dist/esm/sync/utils.d.ts +11 -13
- package/dist/esm/sync/utils.mjs +20 -21
- package/dist/esm/sync/utils.mjs.map +1 -1
- package/dist/esm/types.d.ts +121 -131
- package/dist/esm/types.mjs +3 -2
- package/dist/esm/types.mjs.map +1 -1
- package/dist/esm/util.d.ts +5 -5
- package/dist/esm/util.mjs +46 -25
- package/dist/esm/util.mjs.map +1 -1
- package/package.json +74 -73
- package/src/authModeStrategies/multiAuthStrategy.ts +8 -4
- package/src/datastore/datastore.ts +145 -123
- package/src/index.ts +10 -8
- package/src/predicates/index.ts +10 -2
- package/src/predicates/next.ts +39 -28
- package/src/predicates/sort.ts +23 -26
- package/src/storage/adapter/AsyncStorageAdapter.ts +43 -25
- package/src/storage/adapter/AsyncStorageDatabase.ts +18 -10
- package/src/storage/adapter/InMemoryStore.ts +5 -1
- package/src/storage/adapter/IndexedDBAdapter.ts +50 -37
- package/src/storage/adapter/StorageAdapterBase.ts +24 -18
- package/src/storage/adapter/getDefaultAdapter/index.native.ts +1 -0
- package/src/storage/adapter/getDefaultAdapter/index.ts +4 -1
- package/src/storage/adapter/index.ts +2 -2
- package/src/storage/relationship.ts +5 -1
- package/src/storage/storage.ts +38 -30
- package/src/sync/datastoreConnectivity.ts +4 -6
- package/src/sync/index.ts +228 -230
- package/src/sync/merger.ts +4 -3
- package/src/sync/outbox.ts +26 -24
- package/src/sync/processors/errorMaps.ts +5 -0
- package/src/sync/processors/mutation.ts +80 -72
- package/src/sync/processors/subscription.ts +69 -53
- package/src/sync/processors/sync.ts +49 -37
- package/src/sync/utils.ts +60 -41
- package/src/types.ts +165 -165
- package/src/util.ts +89 -53
package/src/sync/merger.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
PersistentModelConstructor,
|
|
8
8
|
SchemaModel,
|
|
9
9
|
} from '../types';
|
|
10
|
+
|
|
10
11
|
import { MutationEventOutbox } from './outbox';
|
|
11
12
|
import { getIdentifierValue } from './utils';
|
|
12
13
|
|
|
@@ -14,7 +15,7 @@ import { getIdentifierValue } from './utils';
|
|
|
14
15
|
class ModelMerger {
|
|
15
16
|
constructor(
|
|
16
17
|
private readonly outbox: MutationEventOutbox,
|
|
17
|
-
private readonly ownSymbol:
|
|
18
|
+
private readonly ownSymbol: symbol,
|
|
18
19
|
) {}
|
|
19
20
|
|
|
20
21
|
/**
|
|
@@ -55,7 +56,7 @@ class ModelMerger {
|
|
|
55
56
|
items: ModelInstanceMetadata[],
|
|
56
57
|
modelDefinition: SchemaModel,
|
|
57
58
|
): Promise<[ModelInstanceMetadata, OpType][]> {
|
|
58
|
-
const itemsMap
|
|
59
|
+
const itemsMap = new Map<string, ModelInstanceMetadata>();
|
|
59
60
|
|
|
60
61
|
for (const item of items) {
|
|
61
62
|
// merge items by model id. Latest record for a given id remains.
|
|
@@ -66,7 +67,7 @@ class ModelMerger {
|
|
|
66
67
|
|
|
67
68
|
const page = [...itemsMap.values()];
|
|
68
69
|
|
|
69
|
-
return
|
|
70
|
+
return storage.batchSave(modelConstructor, page, this.ownSymbol);
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
|
package/src/sync/outbox.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import { MutationEvent } from './index';
|
|
4
3
|
import { ModelPredicateCreator } from '../predicates';
|
|
5
4
|
import {
|
|
6
5
|
ExclusiveStorage as Storage,
|
|
7
|
-
StorageFacade,
|
|
8
6
|
Storage as StorageClass,
|
|
7
|
+
StorageFacade,
|
|
9
8
|
} from '../storage/storage';
|
|
10
9
|
import { ModelInstanceCreator } from '../datastore/datastore';
|
|
11
10
|
import {
|
|
@@ -15,8 +14,11 @@ import {
|
|
|
15
14
|
QueryOne,
|
|
16
15
|
SchemaModel,
|
|
17
16
|
} from '../types';
|
|
18
|
-
import {
|
|
19
|
-
|
|
17
|
+
import { SYNC, USER, directedValueEquality } from '../util';
|
|
18
|
+
|
|
19
|
+
import { TransformerMutationType, getIdentifierValue } from './utils';
|
|
20
|
+
|
|
21
|
+
import { MutationEvent } from './index';
|
|
20
22
|
|
|
21
23
|
// TODO: Persist deleted ids
|
|
22
24
|
// https://github.com/aws-amplify/amplify-js/blob/datastore-docs/packages/datastore/docs/sync-engine.md#outbox
|
|
@@ -25,9 +27,9 @@ class MutationEventOutbox {
|
|
|
25
27
|
|
|
26
28
|
constructor(
|
|
27
29
|
private readonly schema: InternalSchema,
|
|
28
|
-
private readonly
|
|
30
|
+
private readonly _MutationEvent: PersistentModelConstructor<MutationEvent>,
|
|
29
31
|
private readonly modelInstanceCreator: ModelInstanceCreator,
|
|
30
|
-
private readonly ownSymbol:
|
|
32
|
+
private readonly ownSymbol: symbol,
|
|
31
33
|
) {}
|
|
32
34
|
|
|
33
35
|
public async enqueue(
|
|
@@ -36,7 +38,7 @@ class MutationEventOutbox {
|
|
|
36
38
|
): Promise<void> {
|
|
37
39
|
await storage.runExclusive(async s => {
|
|
38
40
|
const mutationEventModelDefinition =
|
|
39
|
-
this.schema.namespaces[SYNC].models
|
|
41
|
+
this.schema.namespaces[SYNC].models.MutationEvent;
|
|
40
42
|
|
|
41
43
|
// `id` is the key for the record in the mutationEvent;
|
|
42
44
|
// `modelId` is the key for the actual record that was mutated
|
|
@@ -51,11 +53,12 @@ class MutationEventOutbox {
|
|
|
51
53
|
);
|
|
52
54
|
|
|
53
55
|
// Check if there are any other records with same id
|
|
54
|
-
const [first] = await s.query(this.
|
|
56
|
+
const [first] = await s.query(this._MutationEvent, predicate);
|
|
55
57
|
|
|
56
58
|
// No other record with same modelId, so enqueue
|
|
57
59
|
if (first === undefined) {
|
|
58
60
|
await s.save(mutationEvent, undefined, this.ownSymbol);
|
|
61
|
+
|
|
59
62
|
return;
|
|
60
63
|
}
|
|
61
64
|
|
|
@@ -64,7 +67,7 @@ class MutationEventOutbox {
|
|
|
64
67
|
|
|
65
68
|
if (first.operation === TransformerMutationType.CREATE) {
|
|
66
69
|
if (incomingMutationType === TransformerMutationType.DELETE) {
|
|
67
|
-
await s.delete(this.
|
|
70
|
+
await s.delete(this._MutationEvent, predicate);
|
|
68
71
|
} else {
|
|
69
72
|
// first gets updated with the incoming mutation's data, condition intentionally skipped
|
|
70
73
|
|
|
@@ -72,7 +75,7 @@ class MutationEventOutbox {
|
|
|
72
75
|
// data loss, since update mutations only include changed fields
|
|
73
76
|
const merged = this.mergeUserFields(first, mutationEvent);
|
|
74
77
|
await s.save(
|
|
75
|
-
this.
|
|
78
|
+
this._MutationEvent.copyOf(first, draft => {
|
|
76
79
|
draft.data = merged.data;
|
|
77
80
|
}),
|
|
78
81
|
undefined,
|
|
@@ -89,7 +92,7 @@ class MutationEventOutbox {
|
|
|
89
92
|
merged = this.mergeUserFields(first, mutationEvent);
|
|
90
93
|
|
|
91
94
|
// delete all for model
|
|
92
|
-
await s.delete(this.
|
|
95
|
+
await s.delete(this._MutationEvent, predicate);
|
|
93
96
|
}
|
|
94
97
|
|
|
95
98
|
merged = merged! || mutationEvent;
|
|
@@ -125,7 +128,7 @@ class MutationEventOutbox {
|
|
|
125
128
|
* @param storage
|
|
126
129
|
*/
|
|
127
130
|
public async peek(storage: StorageFacade): Promise<MutationEvent> {
|
|
128
|
-
const head = await storage.queryOne(this.
|
|
131
|
+
const head = await storage.queryOne(this._MutationEvent, QueryOne.FIRST);
|
|
129
132
|
|
|
130
133
|
this.inProgressMutationEventId = head ? head.id : undefined!;
|
|
131
134
|
|
|
@@ -143,7 +146,7 @@ class MutationEventOutbox {
|
|
|
143
146
|
const modelId = getIdentifierValue(userModelDefinition, model);
|
|
144
147
|
|
|
145
148
|
const mutationEvents = await storage.query(
|
|
146
|
-
this.
|
|
149
|
+
this._MutationEvent,
|
|
147
150
|
ModelPredicateCreator.createFromAST(mutationEventModelDefinition, {
|
|
148
151
|
and: { modelId: { eq: modelId } },
|
|
149
152
|
}),
|
|
@@ -153,7 +156,7 @@ class MutationEventOutbox {
|
|
|
153
156
|
}
|
|
154
157
|
|
|
155
158
|
public async getModelIds(storage: StorageFacade): Promise<Set<string>> {
|
|
156
|
-
const mutationEvents = await storage.query(this.
|
|
159
|
+
const mutationEvents = await storage.query(this._MutationEvent);
|
|
157
160
|
|
|
158
161
|
const result = new Set<string>();
|
|
159
162
|
|
|
@@ -205,10 +208,9 @@ class MutationEventOutbox {
|
|
|
205
208
|
}
|
|
206
209
|
|
|
207
210
|
const mutationEventModelDefinition =
|
|
208
|
-
this.schema.namespaces[SYNC].models
|
|
211
|
+
this.schema.namespaces[SYNC].models.MutationEvent;
|
|
209
212
|
|
|
210
|
-
const userModelDefinition =
|
|
211
|
-
this.schema.namespaces['user'].models[head.model];
|
|
213
|
+
const userModelDefinition = this.schema.namespaces.user.models[head.model];
|
|
212
214
|
|
|
213
215
|
const recordId = getIdentifierValue(userModelDefinition, record);
|
|
214
216
|
|
|
@@ -223,7 +225,7 @@ class MutationEventOutbox {
|
|
|
223
225
|
);
|
|
224
226
|
|
|
225
227
|
const outdatedMutations = await storage.query(
|
|
226
|
-
this.
|
|
228
|
+
this._MutationEvent,
|
|
227
229
|
predicate,
|
|
228
230
|
);
|
|
229
231
|
|
|
@@ -236,16 +238,16 @@ class MutationEventOutbox {
|
|
|
236
238
|
|
|
237
239
|
const newData = { ...oldData, _version, _lastChangedAt };
|
|
238
240
|
|
|
239
|
-
return this.
|
|
241
|
+
return this._MutationEvent.copyOf(m, draft => {
|
|
240
242
|
draft.data = JSON.stringify(newData);
|
|
241
243
|
});
|
|
242
244
|
});
|
|
243
245
|
|
|
244
|
-
await storage.delete(this.
|
|
246
|
+
await storage.delete(this._MutationEvent, predicate);
|
|
245
247
|
|
|
246
248
|
await Promise.all(
|
|
247
|
-
reconciledMutations.map(
|
|
248
|
-
|
|
249
|
+
reconciledMutations.map(async m =>
|
|
250
|
+
storage.save(m, undefined, this.ownSymbol),
|
|
249
251
|
),
|
|
250
252
|
);
|
|
251
253
|
}
|
|
@@ -273,13 +275,13 @@ class MutationEventOutbox {
|
|
|
273
275
|
...currentData,
|
|
274
276
|
});
|
|
275
277
|
|
|
276
|
-
return this.modelInstanceCreator(this.
|
|
278
|
+
return this.modelInstanceCreator(this._MutationEvent, {
|
|
277
279
|
...current,
|
|
278
280
|
data,
|
|
279
281
|
});
|
|
280
282
|
}
|
|
281
283
|
|
|
282
|
-
/*
|
|
284
|
+
/*
|
|
283
285
|
if a model is using custom timestamp fields
|
|
284
286
|
the custom field names will be stored in the model attributes
|
|
285
287
|
|
|
@@ -16,6 +16,7 @@ export const mutationErrorMap: ErrorMap = {
|
|
|
16
16
|
BadModel: () => false,
|
|
17
17
|
BadRecord: error => {
|
|
18
18
|
const { message } = error;
|
|
19
|
+
|
|
19
20
|
return (
|
|
20
21
|
/^Cannot return \w+ for [\w-_]+ type/.test(message) ||
|
|
21
22
|
/^Variable '.+' has coerced Null value for NonNull type/.test(message)
|
|
@@ -34,10 +35,12 @@ export const subscriptionErrorMap: ErrorMap = {
|
|
|
34
35
|
ConfigError: () => false,
|
|
35
36
|
Transient: observableError => {
|
|
36
37
|
const error = unwrapObservableError(observableError);
|
|
38
|
+
|
|
37
39
|
return connectionTimeout(error) || serverError(error);
|
|
38
40
|
},
|
|
39
41
|
Unauthorized: observableError => {
|
|
40
42
|
const error = unwrapObservableError(observableError);
|
|
43
|
+
|
|
41
44
|
return /Connection failed.+Unauthorized/.test(error.message);
|
|
42
45
|
},
|
|
43
46
|
};
|
|
@@ -60,6 +63,7 @@ function unwrapObservableError(observableError: any) {
|
|
|
60
63
|
const {
|
|
61
64
|
errors: [error],
|
|
62
65
|
} = ({
|
|
66
|
+
// eslint-disable-next-line no-empty-pattern
|
|
63
67
|
errors: [],
|
|
64
68
|
} = observableError);
|
|
65
69
|
|
|
@@ -92,5 +96,6 @@ export function mapErrorToType(errorMap: ErrorMap, error: Error): ErrorType {
|
|
|
92
96
|
return errorType;
|
|
93
97
|
}
|
|
94
98
|
}
|
|
99
|
+
|
|
95
100
|
return 'Unknown';
|
|
96
101
|
}
|
|
@@ -3,61 +3,61 @@
|
|
|
3
3
|
import { GraphQLResult } from '@aws-amplify/api';
|
|
4
4
|
import { InternalAPI } from '@aws-amplify/api/internals';
|
|
5
5
|
import {
|
|
6
|
+
BackgroundProcessManager,
|
|
6
7
|
Category,
|
|
7
8
|
CustomUserAgentDetails,
|
|
8
9
|
DataStoreAction,
|
|
9
|
-
|
|
10
|
+
GraphQLAuthMode,
|
|
10
11
|
NonRetryableError,
|
|
12
|
+
jitteredBackoff,
|
|
11
13
|
retry,
|
|
12
|
-
BackgroundProcessManager,
|
|
13
|
-
GraphQLAuthMode,
|
|
14
|
-
AmplifyError,
|
|
15
14
|
} from '@aws-amplify/core/internals/utils';
|
|
16
|
-
|
|
17
15
|
import { Observable, Observer } from 'rxjs';
|
|
16
|
+
import { ConsoleLogger } from '@aws-amplify/core';
|
|
17
|
+
|
|
18
18
|
import { MutationEvent } from '../';
|
|
19
19
|
import { ModelInstanceCreator } from '../../datastore/datastore';
|
|
20
20
|
import { ExclusiveStorage as Storage } from '../../storage/storage';
|
|
21
21
|
import {
|
|
22
|
+
AmplifyContext,
|
|
22
23
|
AuthModeStrategy,
|
|
23
24
|
ConflictHandler,
|
|
24
25
|
DISCARD,
|
|
25
26
|
ErrorHandler,
|
|
26
27
|
GraphQLCondition,
|
|
27
28
|
InternalSchema,
|
|
28
|
-
isModelFieldType,
|
|
29
|
-
isTargetNameAssociation,
|
|
30
29
|
ModelInstanceMetadata,
|
|
31
30
|
OpType,
|
|
32
31
|
PersistentModel,
|
|
33
32
|
PersistentModelConstructor,
|
|
33
|
+
ProcessName,
|
|
34
34
|
SchemaModel,
|
|
35
35
|
TypeConstructorMap,
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
isModelFieldType,
|
|
37
|
+
isTargetNameAssociation,
|
|
38
38
|
} from '../../types';
|
|
39
|
-
import {
|
|
39
|
+
import { ID, USER, extractTargetNamesFromSrc } from '../../util';
|
|
40
40
|
import { MutationEventOutbox } from '../outbox';
|
|
41
41
|
import {
|
|
42
|
+
TransformerMutationType,
|
|
42
43
|
buildGraphQLOperation,
|
|
43
44
|
createMutationInstanceFromModelOperation,
|
|
44
45
|
getModelAuthModes,
|
|
45
|
-
TransformerMutationType,
|
|
46
46
|
getTokenForCustomAuth,
|
|
47
47
|
} from '../utils';
|
|
48
|
+
|
|
48
49
|
import { getMutationErrorType } from './errorMaps';
|
|
49
|
-
import { ConsoleLogger } from '@aws-amplify/core';
|
|
50
50
|
|
|
51
51
|
const MAX_ATTEMPTS = 10;
|
|
52
52
|
|
|
53
53
|
const logger = new ConsoleLogger('DataStore');
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
interface MutationProcessorEvent {
|
|
56
56
|
operation: TransformerMutationType;
|
|
57
57
|
modelDefinition: SchemaModel;
|
|
58
58
|
model: PersistentModel;
|
|
59
59
|
hasMore: boolean;
|
|
60
|
-
}
|
|
60
|
+
}
|
|
61
61
|
|
|
62
62
|
class MutationProcessor {
|
|
63
63
|
/**
|
|
@@ -73,7 +73,8 @@ class MutationProcessor {
|
|
|
73
73
|
SchemaModel,
|
|
74
74
|
[TransformerMutationType, string, string][]
|
|
75
75
|
>();
|
|
76
|
-
|
|
76
|
+
|
|
77
|
+
private processing = false;
|
|
77
78
|
|
|
78
79
|
private runningProcesses = new BackgroundProcessManager();
|
|
79
80
|
|
|
@@ -83,7 +84,7 @@ class MutationProcessor {
|
|
|
83
84
|
private readonly userClasses: TypeConstructorMap,
|
|
84
85
|
private readonly outbox: MutationEventOutbox,
|
|
85
86
|
private readonly modelInstanceCreator: ModelInstanceCreator,
|
|
86
|
-
private readonly
|
|
87
|
+
private readonly _MutationEvent: PersistentModelConstructor<MutationEvent>,
|
|
87
88
|
private readonly amplifyConfig: Record<string, any> = {},
|
|
88
89
|
private readonly authModeStrategy: AuthModeStrategy,
|
|
89
90
|
private readonly errorHandler: ErrorHandler,
|
|
@@ -216,7 +217,7 @@ class MutationProcessor {
|
|
|
216
217
|
data,
|
|
217
218
|
condition,
|
|
218
219
|
modelConstructor,
|
|
219
|
-
this.
|
|
220
|
+
this._MutationEvent,
|
|
220
221
|
head,
|
|
221
222
|
operationAuthModes[authModeAttempts],
|
|
222
223
|
onTerminate,
|
|
@@ -236,6 +237,7 @@ class MutationProcessor {
|
|
|
236
237
|
}`,
|
|
237
238
|
);
|
|
238
239
|
try {
|
|
240
|
+
// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
|
|
239
241
|
await this.errorHandler({
|
|
240
242
|
recoverySuggestion:
|
|
241
243
|
'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',
|
|
@@ -260,7 +262,8 @@ class MutationProcessor {
|
|
|
260
262
|
operationAuthModes[authModeAttempts]
|
|
261
263
|
}`,
|
|
262
264
|
);
|
|
263
|
-
|
|
265
|
+
|
|
266
|
+
return authModeRetry();
|
|
264
267
|
}
|
|
265
268
|
};
|
|
266
269
|
|
|
@@ -313,30 +316,30 @@ class MutationProcessor {
|
|
|
313
316
|
data: string,
|
|
314
317
|
condition: string,
|
|
315
318
|
modelConstructor: PersistentModelConstructor<PersistentModel>,
|
|
316
|
-
|
|
319
|
+
MutationEventCtor: PersistentModelConstructor<MutationEvent>,
|
|
317
320
|
mutationEvent: MutationEvent,
|
|
318
321
|
authMode: GraphQLAuthMode,
|
|
319
322
|
onTerminate: Promise<void>,
|
|
320
323
|
): Promise<
|
|
321
324
|
[GraphQLResult<Record<string, PersistentModel>>, string, SchemaModel]
|
|
322
325
|
> {
|
|
323
|
-
return
|
|
326
|
+
return retry(
|
|
324
327
|
async (
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
328
|
+
retriedModel: string,
|
|
329
|
+
retriedOperation: TransformerMutationType,
|
|
330
|
+
retriedData: string,
|
|
331
|
+
retriedCondition: string,
|
|
332
|
+
retriedModelConstructor: PersistentModelConstructor<PersistentModel>,
|
|
333
|
+
retiredMutationEventCtor: PersistentModelConstructor<MutationEvent>,
|
|
334
|
+
retiredMutationEvent: MutationEvent,
|
|
332
335
|
) => {
|
|
333
336
|
const [query, variables, graphQLCondition, opName, modelDefinition] =
|
|
334
337
|
this.createQueryVariables(
|
|
335
338
|
namespaceName,
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
339
|
+
retriedModel,
|
|
340
|
+
retriedOperation,
|
|
341
|
+
retriedData,
|
|
342
|
+
retriedCondition,
|
|
340
343
|
);
|
|
341
344
|
|
|
342
345
|
const authToken = await getTokenForCustomAuth(
|
|
@@ -352,7 +355,7 @@ class MutationProcessor {
|
|
|
352
355
|
};
|
|
353
356
|
let attempt = 0;
|
|
354
357
|
|
|
355
|
-
const opType = this.opTypeFromTransformerOperation(
|
|
358
|
+
const opType = this.opTypeFromTransformerOperation(retriedOperation);
|
|
356
359
|
|
|
357
360
|
const customUserAgentDetails: CustomUserAgentDetails = {
|
|
358
361
|
category: Category.DataStore,
|
|
@@ -361,13 +364,11 @@ class MutationProcessor {
|
|
|
361
364
|
|
|
362
365
|
do {
|
|
363
366
|
try {
|
|
364
|
-
const result =
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
)
|
|
370
|
-
);
|
|
367
|
+
const result = (await this.amplifyContext.InternalAPI.graphql(
|
|
368
|
+
tryWith,
|
|
369
|
+
undefined,
|
|
370
|
+
customUserAgentDetails,
|
|
371
|
+
)) as GraphQLResult<Record<string, PersistentModel>>;
|
|
371
372
|
|
|
372
373
|
// Use `as any` because TypeScript doesn't seem to like passing tuples
|
|
373
374
|
// through generic params.
|
|
@@ -402,20 +403,20 @@ class MutationProcessor {
|
|
|
402
403
|
} else {
|
|
403
404
|
try {
|
|
404
405
|
retryWith = await this.conflictHandler!({
|
|
405
|
-
modelConstructor,
|
|
406
|
+
modelConstructor: retriedModelConstructor,
|
|
406
407
|
localModel: this.modelInstanceCreator(
|
|
407
|
-
|
|
408
|
+
retriedModelConstructor,
|
|
408
409
|
variables.input,
|
|
409
410
|
),
|
|
410
411
|
remoteModel: this.modelInstanceCreator(
|
|
411
|
-
|
|
412
|
+
retriedModelConstructor,
|
|
412
413
|
error.data,
|
|
413
414
|
),
|
|
414
415
|
operation: opType,
|
|
415
416
|
attempts: attempt,
|
|
416
417
|
});
|
|
417
|
-
} catch (
|
|
418
|
-
logger.warn('conflict trycatch',
|
|
418
|
+
} catch (caughtErr) {
|
|
419
|
+
logger.warn('conflict trycatch', caughtErr);
|
|
419
420
|
continue;
|
|
420
421
|
}
|
|
421
422
|
}
|
|
@@ -423,33 +424,32 @@ class MutationProcessor {
|
|
|
423
424
|
if (retryWith === DISCARD) {
|
|
424
425
|
// Query latest from server and notify merger
|
|
425
426
|
|
|
426
|
-
const [[,
|
|
427
|
+
const [[, builtOpName, builtQuery]] = buildGraphQLOperation(
|
|
427
428
|
this.schema.namespaces[namespaceName],
|
|
428
429
|
modelDefinition,
|
|
429
430
|
'GET',
|
|
430
431
|
);
|
|
431
432
|
|
|
432
|
-
const
|
|
433
|
+
const newAuthToken = await getTokenForCustomAuth(
|
|
433
434
|
authMode,
|
|
434
435
|
this.amplifyConfig,
|
|
435
436
|
);
|
|
436
437
|
|
|
437
|
-
const serverData =
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
);
|
|
438
|
+
const serverData =
|
|
439
|
+
(await this.amplifyContext.InternalAPI.graphql(
|
|
440
|
+
{
|
|
441
|
+
query: builtQuery,
|
|
442
|
+
variables: { id: variables.input.id },
|
|
443
|
+
authMode,
|
|
444
|
+
authToken: newAuthToken,
|
|
445
|
+
},
|
|
446
|
+
undefined,
|
|
447
|
+
customUserAgentDetails,
|
|
448
|
+
)) as GraphQLResult<Record<string, PersistentModel>>;
|
|
449
449
|
|
|
450
450
|
// onTerminate cancel graphql()
|
|
451
451
|
|
|
452
|
-
return [serverData,
|
|
452
|
+
return [serverData, builtOpName, modelDefinition];
|
|
453
453
|
}
|
|
454
454
|
|
|
455
455
|
const namespace = this.schema.namespaces[namespaceName];
|
|
@@ -460,12 +460,12 @@ class MutationProcessor {
|
|
|
460
460
|
namespace.relationships!,
|
|
461
461
|
modelDefinition,
|
|
462
462
|
opType,
|
|
463
|
-
|
|
463
|
+
retriedModelConstructor,
|
|
464
464
|
retryWith,
|
|
465
465
|
graphQLCondition,
|
|
466
|
-
|
|
466
|
+
retiredMutationEventCtor,
|
|
467
467
|
this.modelInstanceCreator,
|
|
468
|
-
|
|
468
|
+
retiredMutationEvent.id,
|
|
469
469
|
);
|
|
470
470
|
|
|
471
471
|
await this.storage.save(updatedMutation);
|
|
@@ -478,19 +478,23 @@ class MutationProcessor {
|
|
|
478
478
|
'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',
|
|
479
479
|
localModel: variables.input,
|
|
480
480
|
message: error.message,
|
|
481
|
-
operation,
|
|
481
|
+
operation: retriedOperation,
|
|
482
482
|
errorType: getMutationErrorType(error),
|
|
483
483
|
errorInfo: error.errorInfo,
|
|
484
484
|
process: ProcessName.mutate,
|
|
485
485
|
cause: error,
|
|
486
486
|
remoteModel: error.data
|
|
487
|
-
? this.modelInstanceCreator(
|
|
487
|
+
? this.modelInstanceCreator(
|
|
488
|
+
retriedModelConstructor,
|
|
489
|
+
error.data,
|
|
490
|
+
)
|
|
488
491
|
: null!,
|
|
489
492
|
});
|
|
490
|
-
} catch (
|
|
491
|
-
logger.warn('Mutation error handler failed with:',
|
|
493
|
+
} catch (caughtErr) {
|
|
494
|
+
logger.warn('Mutation error handler failed with:', caughtErr);
|
|
492
495
|
} finally {
|
|
493
496
|
// Return empty tuple, dequeues the mutation
|
|
497
|
+
// eslint-disable-next-line no-unsafe-finally
|
|
494
498
|
return error.data
|
|
495
499
|
? [
|
|
496
500
|
{ data: { [opName]: error.data } },
|
|
@@ -506,6 +510,7 @@ class MutationProcessor {
|
|
|
506
510
|
throw new NonRetryableError(err);
|
|
507
511
|
}
|
|
508
512
|
}
|
|
513
|
+
// eslint-disable-next-line no-unmodified-loop-condition
|
|
509
514
|
} while (tryWith);
|
|
510
515
|
},
|
|
511
516
|
[
|
|
@@ -514,7 +519,7 @@ class MutationProcessor {
|
|
|
514
519
|
data,
|
|
515
520
|
condition,
|
|
516
521
|
modelConstructor,
|
|
517
|
-
|
|
522
|
+
MutationEventCtor,
|
|
518
523
|
mutationEvent,
|
|
519
524
|
],
|
|
520
525
|
safeJitteredBackoff,
|
|
@@ -543,7 +548,9 @@ class MutationProcessor {
|
|
|
543
548
|
([transformerMutationType]) => transformerMutationType === operation,
|
|
544
549
|
)!;
|
|
545
550
|
|
|
546
|
-
const { _version, ...parsedData } =
|
|
551
|
+
const { _version, ...parsedData } = JSON.parse(
|
|
552
|
+
data,
|
|
553
|
+
) as ModelInstanceMetadata;
|
|
547
554
|
|
|
548
555
|
// include all the fields that comprise a custom PK if one is specified
|
|
549
556
|
const deleteInput = {};
|
|
@@ -552,14 +559,14 @@ class MutationProcessor {
|
|
|
552
559
|
deleteInput[pkField] = parsedData[pkField];
|
|
553
560
|
}
|
|
554
561
|
} else {
|
|
555
|
-
deleteInput[ID] = (
|
|
562
|
+
deleteInput[ID] = (parsedData as any).id;
|
|
556
563
|
}
|
|
557
564
|
|
|
558
565
|
let mutationInput;
|
|
559
566
|
|
|
560
567
|
if (operation === TransformerMutationType.DELETE) {
|
|
561
568
|
// For DELETE mutations, only the key(s) are included in the input
|
|
562
|
-
mutationInput =
|
|
569
|
+
mutationInput = deleteInput as ModelInstanceMetadata;
|
|
563
570
|
} else {
|
|
564
571
|
// Otherwise, we construct the mutation input with the following logic
|
|
565
572
|
mutationInput = {};
|
|
@@ -598,7 +605,7 @@ class MutationProcessor {
|
|
|
598
605
|
// scalar fields / non-model types
|
|
599
606
|
|
|
600
607
|
if (operation === TransformerMutationType.UPDATE) {
|
|
601
|
-
if (!
|
|
608
|
+
if (!Object.prototype.hasOwnProperty.call(parsedData, name)) {
|
|
602
609
|
// for update mutations - strip out a field if it's unchanged
|
|
603
610
|
continue;
|
|
604
611
|
}
|
|
@@ -615,7 +622,7 @@ class MutationProcessor {
|
|
|
615
622
|
_version,
|
|
616
623
|
};
|
|
617
624
|
|
|
618
|
-
const graphQLCondition =
|
|
625
|
+
const graphQLCondition = JSON.parse(condition) as GraphQLCondition;
|
|
619
626
|
|
|
620
627
|
const variables = {
|
|
621
628
|
input,
|
|
@@ -628,6 +635,7 @@ class MutationProcessor {
|
|
|
628
635
|
: null,
|
|
629
636
|
}),
|
|
630
637
|
};
|
|
638
|
+
|
|
631
639
|
return [query, variables, graphQLCondition, opName, modelDefinition];
|
|
632
640
|
}
|
|
633
641
|
|