@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.
- package/lib/authModeStrategies/defaultAuthStrategy.js +1 -1
- package/lib/authModeStrategies/multiAuthStrategy.js +29 -105
- package/lib/datastore/datastore.js +887 -1370
- package/lib/index.js +1 -1
- package/lib/predicates/index.js +53 -102
- package/lib/predicates/next.js +310 -557
- package/lib/predicates/sort.js +24 -27
- package/lib/ssr/index.js +1 -1
- package/lib/storage/adapter/AsyncStorageAdapter.js +115 -449
- package/lib/storage/adapter/AsyncStorageDatabase.js +215 -480
- package/lib/storage/adapter/InMemoryStore.js +27 -101
- package/lib/storage/adapter/InMemoryStore.native.js +1 -1
- package/lib/storage/adapter/IndexedDBAdapter.js +441 -1002
- package/lib/storage/adapter/StorageAdapterBase.js +177 -396
- package/lib/storage/adapter/getDefaultAdapter/index.js +5 -6
- package/lib/storage/adapter/getDefaultAdapter/index.native.js +2 -2
- package/lib/storage/relationship.js +174 -260
- package/lib/storage/storage.js +244 -507
- package/lib/sync/datastoreConnectivity.js +29 -84
- package/lib/sync/datastoreReachability/index.js +1 -1
- package/lib/sync/datastoreReachability/index.native.js +2 -2
- package/lib/sync/index.js +512 -885
- package/lib/sync/merger.js +30 -133
- package/lib/sync/outbox.js +147 -302
- package/lib/sync/processors/errorMaps.js +30 -80
- package/lib/sync/processors/mutation.js +331 -579
- package/lib/sync/processors/subscription.js +268 -428
- package/lib/sync/processors/sync.js +276 -464
- package/lib/sync/utils.js +248 -393
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types.js +16 -58
- package/lib/util.js +335 -575
- package/lib-esm/authModeStrategies/defaultAuthStrategy.js +1 -1
- package/lib-esm/authModeStrategies/multiAuthStrategy.js +27 -103
- package/lib-esm/datastore/datastore.js +874 -1359
- package/lib-esm/index.js +6 -6
- package/lib-esm/predicates/index.js +54 -104
- package/lib-esm/predicates/next.js +306 -555
- package/lib-esm/predicates/sort.js +24 -27
- package/lib-esm/ssr/index.js +1 -1
- package/lib-esm/storage/adapter/AsyncStorageAdapter.js +111 -446
- package/lib-esm/storage/adapter/AsyncStorageDatabase.js +212 -477
- package/lib-esm/storage/adapter/InMemoryStore.js +27 -102
- package/lib-esm/storage/adapter/IndexedDBAdapter.js +436 -997
- package/lib-esm/storage/adapter/StorageAdapterBase.js +172 -392
- package/lib-esm/storage/adapter/getDefaultAdapter/index.js +2 -3
- package/lib-esm/storage/adapter/getDefaultAdapter/index.native.js +1 -1
- package/lib-esm/storage/relationship.js +173 -260
- package/lib-esm/storage/storage.js +236 -499
- package/lib-esm/sync/datastoreConnectivity.js +26 -82
- package/lib-esm/sync/datastoreReachability/index.js +1 -1
- package/lib-esm/sync/datastoreReachability/index.native.js +1 -1
- package/lib-esm/sync/index.js +498 -872
- package/lib-esm/sync/merger.js +28 -131
- package/lib-esm/sync/outbox.js +143 -298
- package/lib-esm/sync/processors/errorMaps.js +32 -82
- package/lib-esm/sync/processors/mutation.js +324 -572
- package/lib-esm/sync/processors/subscription.js +258 -418
- package/lib-esm/sync/processors/sync.js +269 -457
- package/lib-esm/sync/utils.js +245 -390
- package/lib-esm/tsconfig.tsbuildinfo +1 -1
- package/lib-esm/types.js +16 -59
- package/lib-esm/util.js +335 -577
- package/package.json +12 -12
- package/src/datastore/datastore.ts +4 -3
- package/src/storage/adapter/getDefaultAdapter/index.ts +1 -3
- package/src/sync/processors/mutation.ts +1 -1
- package/src/sync/processors/sync.ts +1 -1
- package/src/sync/utils.ts +1 -1
- package/src/util.ts +44 -6
package/lib-esm/sync/outbox.js
CHANGED
|
@@ -1,314 +1,161 @@
|
|
|
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
1
|
import { ModelPredicateCreator } from '../predicates';
|
|
76
2
|
import { QueryOne, } from '../types';
|
|
77
3
|
import { USER, SYNC, valuesEqual } from '../util';
|
|
78
4
|
import { getIdentifierValue, TransformerMutationType } from './utils';
|
|
79
5
|
// TODO: Persist deleted ids
|
|
80
6
|
// https://github.com/aws-amplify/amplify-js/blob/datastore-docs/packages/datastore/docs/sync-engine.md#outbox
|
|
81
|
-
|
|
82
|
-
|
|
7
|
+
class MutationEventOutbox {
|
|
8
|
+
constructor(schema, MutationEvent, modelInstanceCreator, ownSymbol) {
|
|
83
9
|
this.schema = schema;
|
|
84
10
|
this.MutationEvent = MutationEvent;
|
|
85
11
|
this.modelInstanceCreator = modelInstanceCreator;
|
|
86
12
|
this.ownSymbol = ownSymbol;
|
|
87
13
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
mutationEventModelDefinition = this.schema.namespaces[SYNC].models['MutationEvent'];
|
|
99
|
-
predicate = ModelPredicateCreator.createFromAST(mutationEventModelDefinition, {
|
|
100
|
-
and: [
|
|
101
|
-
{ modelId: { eq: mutationEvent.modelId } },
|
|
102
|
-
{ id: { ne: this.inProgressMutationEventId } },
|
|
103
|
-
],
|
|
104
|
-
});
|
|
105
|
-
return [4 /*yield*/, s.query(this.MutationEvent, predicate)];
|
|
106
|
-
case 1:
|
|
107
|
-
_a = __read.apply(void 0, [_b.sent(), 1]), first = _a[0];
|
|
108
|
-
if (!(first === undefined)) return [3 /*break*/, 3];
|
|
109
|
-
return [4 /*yield*/, s.save(mutationEvent, undefined, this.ownSymbol)];
|
|
110
|
-
case 2:
|
|
111
|
-
_b.sent();
|
|
112
|
-
return [2 /*return*/];
|
|
113
|
-
case 3:
|
|
114
|
-
incomingMutationType = mutationEvent.operation;
|
|
115
|
-
if (!(first.operation === TransformerMutationType.CREATE)) return [3 /*break*/, 8];
|
|
116
|
-
if (!(incomingMutationType === TransformerMutationType.DELETE)) return [3 /*break*/, 5];
|
|
117
|
-
return [4 /*yield*/, s.delete(this.MutationEvent, predicate)];
|
|
118
|
-
case 4:
|
|
119
|
-
_b.sent();
|
|
120
|
-
return [3 /*break*/, 7];
|
|
121
|
-
case 5:
|
|
122
|
-
merged_1 = this.mergeUserFields(first, mutationEvent);
|
|
123
|
-
return [4 /*yield*/, s.save(this.MutationEvent.copyOf(first, function (draft) {
|
|
124
|
-
draft.data = merged_1.data;
|
|
125
|
-
}), undefined, this.ownSymbol)];
|
|
126
|
-
case 6:
|
|
127
|
-
_b.sent();
|
|
128
|
-
_b.label = 7;
|
|
129
|
-
case 7: return [3 /*break*/, 12];
|
|
130
|
-
case 8:
|
|
131
|
-
incomingConditionJSON = mutationEvent.condition;
|
|
132
|
-
incomingCondition = JSON.parse(incomingConditionJSON);
|
|
133
|
-
merged = void 0;
|
|
134
|
-
if (!(Object.keys(incomingCondition).length === 0)) return [3 /*break*/, 10];
|
|
135
|
-
merged = this.mergeUserFields(first, mutationEvent);
|
|
136
|
-
// delete all for model
|
|
137
|
-
return [4 /*yield*/, s.delete(this.MutationEvent, predicate)];
|
|
138
|
-
case 9:
|
|
139
|
-
// delete all for model
|
|
140
|
-
_b.sent();
|
|
141
|
-
_b.label = 10;
|
|
142
|
-
case 10:
|
|
143
|
-
merged = merged || mutationEvent;
|
|
144
|
-
// Enqueue new one
|
|
145
|
-
return [4 /*yield*/, s.save(merged, undefined, this.ownSymbol)];
|
|
146
|
-
case 11:
|
|
147
|
-
// Enqueue new one
|
|
148
|
-
_b.sent();
|
|
149
|
-
_b.label = 12;
|
|
150
|
-
case 12: return [2 /*return*/];
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
}); })];
|
|
154
|
-
case 1:
|
|
155
|
-
_a.sent();
|
|
156
|
-
return [2 /*return*/];
|
|
157
|
-
}
|
|
14
|
+
async enqueue(storage, mutationEvent) {
|
|
15
|
+
await storage.runExclusive(async (s) => {
|
|
16
|
+
const mutationEventModelDefinition = this.schema.namespaces[SYNC].models['MutationEvent'];
|
|
17
|
+
// `id` is the key for the record in the mutationEvent;
|
|
18
|
+
// `modelId` is the key for the actual record that was mutated
|
|
19
|
+
const predicate = ModelPredicateCreator.createFromAST(mutationEventModelDefinition, {
|
|
20
|
+
and: [
|
|
21
|
+
{ modelId: { eq: mutationEvent.modelId } },
|
|
22
|
+
{ id: { ne: this.inProgressMutationEventId } },
|
|
23
|
+
],
|
|
158
24
|
});
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
case 2:
|
|
172
|
-
_a.sent();
|
|
173
|
-
_a.label = 3;
|
|
174
|
-
case 3: return [4 /*yield*/, storage.delete(head)];
|
|
175
|
-
case 4:
|
|
176
|
-
_a.sent();
|
|
177
|
-
this.inProgressMutationEventId = undefined;
|
|
178
|
-
return [2 /*return*/, head];
|
|
25
|
+
// Check if there are any other records with same id
|
|
26
|
+
const [first] = await s.query(this.MutationEvent, predicate);
|
|
27
|
+
// No other record with same modelId, so enqueue
|
|
28
|
+
if (first === undefined) {
|
|
29
|
+
await s.save(mutationEvent, undefined, this.ownSymbol);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// There was an enqueued mutation for the modelId, so continue
|
|
33
|
+
const { operation: incomingMutationType } = mutationEvent;
|
|
34
|
+
if (first.operation === TransformerMutationType.CREATE) {
|
|
35
|
+
if (incomingMutationType === TransformerMutationType.DELETE) {
|
|
36
|
+
await s.delete(this.MutationEvent, predicate);
|
|
179
37
|
}
|
|
180
|
-
|
|
38
|
+
else {
|
|
39
|
+
// first gets updated with the incoming mutation's data, condition intentionally skipped
|
|
40
|
+
// we need to merge the fields for a create and update mutation to prevent
|
|
41
|
+
// data loss, since update mutations only include changed fields
|
|
42
|
+
const merged = this.mergeUserFields(first, mutationEvent);
|
|
43
|
+
await s.save(this.MutationEvent.copyOf(first, draft => {
|
|
44
|
+
draft.data = merged.data;
|
|
45
|
+
}), undefined, this.ownSymbol);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const { condition: incomingConditionJSON } = mutationEvent;
|
|
50
|
+
const incomingCondition = JSON.parse(incomingConditionJSON);
|
|
51
|
+
let merged;
|
|
52
|
+
// If no condition
|
|
53
|
+
if (Object.keys(incomingCondition).length === 0) {
|
|
54
|
+
merged = this.mergeUserFields(first, mutationEvent);
|
|
55
|
+
// delete all for model
|
|
56
|
+
await s.delete(this.MutationEvent, predicate);
|
|
57
|
+
}
|
|
58
|
+
merged = merged || mutationEvent;
|
|
59
|
+
// Enqueue new one
|
|
60
|
+
await s.save(merged, undefined, this.ownSymbol);
|
|
61
|
+
}
|
|
181
62
|
});
|
|
182
|
-
}
|
|
63
|
+
}
|
|
64
|
+
async dequeue(storage, record, recordOp) {
|
|
65
|
+
const head = await this.peek(storage);
|
|
66
|
+
if (record) {
|
|
67
|
+
await this.syncOutboxVersionsOnDequeue(storage, record, head, recordOp);
|
|
68
|
+
}
|
|
69
|
+
await storage.delete(head);
|
|
70
|
+
this.inProgressMutationEventId = undefined;
|
|
71
|
+
return head;
|
|
72
|
+
}
|
|
183
73
|
/**
|
|
184
74
|
* Doing a peek() implies that the mutation goes "inProgress"
|
|
185
75
|
*
|
|
186
76
|
* @param storage
|
|
187
77
|
*/
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
case 0:
|
|
208
|
-
mutationEventModelDefinition = this.schema.namespaces[SYNC].models.MutationEvent;
|
|
209
|
-
modelId = getIdentifierValue(userModelDefinition, model);
|
|
210
|
-
return [4 /*yield*/, storage.query(this.MutationEvent, ModelPredicateCreator.createFromAST(mutationEventModelDefinition, {
|
|
211
|
-
and: { modelId: { eq: modelId } },
|
|
212
|
-
}))];
|
|
213
|
-
case 1:
|
|
214
|
-
mutationEvents = _a.sent();
|
|
215
|
-
return [2 /*return*/, mutationEvents];
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
});
|
|
219
|
-
};
|
|
220
|
-
MutationEventOutbox.prototype.getModelIds = function (storage) {
|
|
221
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
222
|
-
var mutationEvents, result;
|
|
223
|
-
return __generator(this, function (_a) {
|
|
224
|
-
switch (_a.label) {
|
|
225
|
-
case 0: return [4 /*yield*/, storage.query(this.MutationEvent)];
|
|
226
|
-
case 1:
|
|
227
|
-
mutationEvents = _a.sent();
|
|
228
|
-
result = new Set();
|
|
229
|
-
mutationEvents.forEach(function (_a) {
|
|
230
|
-
var modelId = _a.modelId;
|
|
231
|
-
return result.add(modelId);
|
|
232
|
-
});
|
|
233
|
-
return [2 /*return*/, result];
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
};
|
|
78
|
+
async peek(storage) {
|
|
79
|
+
const head = await storage.queryOne(this.MutationEvent, QueryOne.FIRST);
|
|
80
|
+
this.inProgressMutationEventId = head ? head.id : undefined;
|
|
81
|
+
return head;
|
|
82
|
+
}
|
|
83
|
+
async getForModel(storage, model, userModelDefinition) {
|
|
84
|
+
const mutationEventModelDefinition = this.schema.namespaces[SYNC].models.MutationEvent;
|
|
85
|
+
const modelId = getIdentifierValue(userModelDefinition, model);
|
|
86
|
+
const mutationEvents = await storage.query(this.MutationEvent, ModelPredicateCreator.createFromAST(mutationEventModelDefinition, {
|
|
87
|
+
and: { modelId: { eq: modelId } },
|
|
88
|
+
}));
|
|
89
|
+
return mutationEvents;
|
|
90
|
+
}
|
|
91
|
+
async getModelIds(storage) {
|
|
92
|
+
const mutationEvents = await storage.query(this.MutationEvent);
|
|
93
|
+
const result = new Set();
|
|
94
|
+
mutationEvents.forEach(({ modelId }) => result.add(modelId));
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
238
97
|
// applies _version from the AppSync mutation response to other items
|
|
239
98
|
// in the mutation queue with the same id
|
|
240
99
|
// see https://github.com/aws-amplify/amplify-js/pull/7354 for more details
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
if (!outdatedMutations.length) {
|
|
281
|
-
return [2 /*return*/];
|
|
282
|
-
}
|
|
283
|
-
reconciledMutations = outdatedMutations.map(function (m) {
|
|
284
|
-
var oldData = JSON.parse(m.data);
|
|
285
|
-
var newData = __assign(__assign({}, oldData), { _version: _version, _lastChangedAt: _lastChangedAt });
|
|
286
|
-
return _this.MutationEvent.copyOf(m, function (draft) {
|
|
287
|
-
draft.data = JSON.stringify(newData);
|
|
288
|
-
});
|
|
289
|
-
});
|
|
290
|
-
return [4 /*yield*/, storage.delete(this.MutationEvent, predicate)];
|
|
291
|
-
case 2:
|
|
292
|
-
_a.sent();
|
|
293
|
-
return [4 /*yield*/, Promise.all(reconciledMutations.map(function (m) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
294
|
-
switch (_a.label) {
|
|
295
|
-
case 0: return [4 /*yield*/, storage.save(m, undefined, this.ownSymbol)];
|
|
296
|
-
case 1: return [2 /*return*/, _a.sent()];
|
|
297
|
-
}
|
|
298
|
-
}); }); }))];
|
|
299
|
-
case 3:
|
|
300
|
-
_a.sent();
|
|
301
|
-
return [2 /*return*/];
|
|
302
|
-
}
|
|
100
|
+
async syncOutboxVersionsOnDequeue(storage, record, head, recordOp) {
|
|
101
|
+
if (head.operation !== recordOp) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const { _version, _lastChangedAt, _deleted, ..._incomingData } = record;
|
|
105
|
+
const incomingData = this.removeTimestampFields(head.model, _incomingData);
|
|
106
|
+
const data = JSON.parse(head.data);
|
|
107
|
+
if (!data) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const { _version: __version, _lastChangedAt: __lastChangedAt, _deleted: __deleted, ..._outgoingData } = data;
|
|
111
|
+
const outgoingData = this.removeTimestampFields(head.model, _outgoingData);
|
|
112
|
+
// Don't sync the version when the data in the response does not match the data
|
|
113
|
+
// in the request, i.e., when there's a handled conflict
|
|
114
|
+
//
|
|
115
|
+
// NOTE: `incomingData` contains all the fields in the record, and `outgoingData`
|
|
116
|
+
// only contains updated fields, resulting in an error when doing a comparison
|
|
117
|
+
// of two equal mutations. Fix this, or mitigate otherwise.
|
|
118
|
+
if (!valuesEqual(incomingData, outgoingData, true)) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const mutationEventModelDefinition = this.schema.namespaces[SYNC].models['MutationEvent'];
|
|
122
|
+
const userModelDefinition = this.schema.namespaces['user'].models[head.model];
|
|
123
|
+
const recordId = getIdentifierValue(userModelDefinition, record);
|
|
124
|
+
const predicate = ModelPredicateCreator.createFromAST(mutationEventModelDefinition, {
|
|
125
|
+
and: [
|
|
126
|
+
{ modelId: { eq: recordId } },
|
|
127
|
+
{ id: { ne: this.inProgressMutationEventId } },
|
|
128
|
+
],
|
|
129
|
+
});
|
|
130
|
+
const outdatedMutations = await storage.query(this.MutationEvent, predicate);
|
|
131
|
+
if (!outdatedMutations.length) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const reconciledMutations = outdatedMutations.map(m => {
|
|
135
|
+
const oldData = JSON.parse(m.data);
|
|
136
|
+
const newData = { ...oldData, _version, _lastChangedAt };
|
|
137
|
+
return this.MutationEvent.copyOf(m, draft => {
|
|
138
|
+
draft.data = JSON.stringify(newData);
|
|
303
139
|
});
|
|
304
140
|
});
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
141
|
+
await storage.delete(this.MutationEvent, predicate);
|
|
142
|
+
await Promise.all(reconciledMutations.map(async (m) => await storage.save(m, undefined, this.ownSymbol)));
|
|
143
|
+
}
|
|
144
|
+
mergeUserFields(previous, current) {
|
|
145
|
+
const { _version, _lastChangedAt, _deleted, ...previousData } = JSON.parse(previous.data);
|
|
146
|
+
const { _version: __version, _lastChangedAt: __lastChangedAt, _deleted: __deleted, ...currentData } = JSON.parse(current.data);
|
|
147
|
+
const data = JSON.stringify({
|
|
148
|
+
_version,
|
|
149
|
+
_lastChangedAt,
|
|
150
|
+
_deleted,
|
|
151
|
+
...previousData,
|
|
152
|
+
...currentData,
|
|
153
|
+
});
|
|
154
|
+
return this.modelInstanceCreator(this.MutationEvent, {
|
|
155
|
+
...current,
|
|
156
|
+
data,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
312
159
|
/*
|
|
313
160
|
if a model is using custom timestamp fields
|
|
314
161
|
the custom field names will be stored in the model attributes
|
|
@@ -326,14 +173,13 @@ var MutationEventOutbox = /** @class */ (function () {
|
|
|
326
173
|
}
|
|
327
174
|
]
|
|
328
175
|
*/
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
var timestampFieldsMap = (_b = modelAttributes === null || modelAttributes === void 0 ? void 0 : modelAttributes.properties) === null || _b === void 0 ? void 0 : _b.timestamps;
|
|
176
|
+
removeTimestampFields(model, record) {
|
|
177
|
+
const CREATED_AT_DEFAULT_KEY = 'createdAt';
|
|
178
|
+
const UPDATED_AT_DEFAULT_KEY = 'updatedAt';
|
|
179
|
+
let createdTimestampKey = CREATED_AT_DEFAULT_KEY;
|
|
180
|
+
let updatedTimestampKey = UPDATED_AT_DEFAULT_KEY;
|
|
181
|
+
const modelAttributes = this.schema.namespaces[USER].models[model].attributes?.find(attr => attr.type === 'model');
|
|
182
|
+
const timestampFieldsMap = modelAttributes?.properties?.timestamps;
|
|
337
183
|
if (timestampFieldsMap) {
|
|
338
184
|
createdTimestampKey = timestampFieldsMap[CREATED_AT_DEFAULT_KEY];
|
|
339
185
|
updatedTimestampKey = timestampFieldsMap[UPDATED_AT_DEFAULT_KEY];
|
|
@@ -341,7 +187,6 @@ var MutationEventOutbox = /** @class */ (function () {
|
|
|
341
187
|
delete record[createdTimestampKey];
|
|
342
188
|
delete record[updatedTimestampKey];
|
|
343
189
|
return record;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
}());
|
|
190
|
+
}
|
|
191
|
+
}
|
|
347
192
|
export { MutationEventOutbox };
|
|
@@ -1,77 +1,37 @@
|
|
|
1
|
-
var __read = (this && this.__read) || function (o, n) {
|
|
2
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
3
|
-
if (!m) return o;
|
|
4
|
-
var i = m.call(o), r, ar = [], e;
|
|
5
|
-
try {
|
|
6
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
7
|
-
}
|
|
8
|
-
catch (error) { e = { error: error }; }
|
|
9
|
-
finally {
|
|
10
|
-
try {
|
|
11
|
-
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
12
|
-
}
|
|
13
|
-
finally { if (e) throw e.error; }
|
|
14
|
-
}
|
|
15
|
-
return ar;
|
|
16
|
-
};
|
|
17
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
18
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
19
|
-
if (ar || !(i in from)) {
|
|
20
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
21
|
-
ar[i] = from[i];
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
25
|
-
};
|
|
26
|
-
var __values = (this && this.__values) || function(o) {
|
|
27
|
-
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
28
|
-
if (m) return m.call(o);
|
|
29
|
-
if (o && typeof o.length === "number") return {
|
|
30
|
-
next: function () {
|
|
31
|
-
if (o && i >= o.length) o = void 0;
|
|
32
|
-
return { value: o && o[i++], done: !o };
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
36
|
-
};
|
|
37
1
|
import { resolveServiceErrorStatusCode } from '../utils';
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
BadRecord: function (error) {
|
|
45
|
-
var message = error.message;
|
|
2
|
+
const connectionTimeout = error => /^Connection failed: Connection Timeout/.test(error.message);
|
|
3
|
+
const serverError = error => resolveServiceErrorStatusCode(error) >= 500;
|
|
4
|
+
export const mutationErrorMap = {
|
|
5
|
+
BadModel: () => false,
|
|
6
|
+
BadRecord: error => {
|
|
7
|
+
const { message } = error;
|
|
46
8
|
return (/^Cannot return \w+ for [\w-_]+ type/.test(message) ||
|
|
47
9
|
/^Variable '.+' has coerced Null value for NonNull type/.test(message)); // newly required field, out of date client
|
|
48
10
|
},
|
|
49
|
-
ConfigError:
|
|
50
|
-
Transient:
|
|
51
|
-
Unauthorized:
|
|
52
|
-
|
|
53
|
-
resolveServiceErrorStatusCode(error) === 401;
|
|
54
|
-
},
|
|
11
|
+
ConfigError: () => false,
|
|
12
|
+
Transient: error => connectionTimeout(error) || serverError(error),
|
|
13
|
+
Unauthorized: error => error.message === 'Unauthorized' ||
|
|
14
|
+
resolveServiceErrorStatusCode(error) === 401,
|
|
55
15
|
};
|
|
56
|
-
export
|
|
57
|
-
BadModel:
|
|
58
|
-
BadRecord:
|
|
59
|
-
ConfigError:
|
|
60
|
-
Transient:
|
|
61
|
-
|
|
16
|
+
export const subscriptionErrorMap = {
|
|
17
|
+
BadModel: () => false,
|
|
18
|
+
BadRecord: () => false,
|
|
19
|
+
ConfigError: () => false,
|
|
20
|
+
Transient: observableError => {
|
|
21
|
+
const error = unwrapObservableError(observableError);
|
|
62
22
|
return connectionTimeout(error) || serverError(error);
|
|
63
23
|
},
|
|
64
|
-
Unauthorized:
|
|
65
|
-
|
|
24
|
+
Unauthorized: observableError => {
|
|
25
|
+
const error = unwrapObservableError(observableError);
|
|
66
26
|
return /Connection failed.+Unauthorized/.test(error.message);
|
|
67
27
|
},
|
|
68
28
|
};
|
|
69
|
-
export
|
|
70
|
-
BadModel:
|
|
71
|
-
BadRecord:
|
|
72
|
-
ConfigError:
|
|
73
|
-
Transient:
|
|
74
|
-
Unauthorized:
|
|
29
|
+
export const syncErrorMap = {
|
|
30
|
+
BadModel: () => false,
|
|
31
|
+
BadRecord: error => /^Cannot return \w+ for [\w-_]+ type/.test(error.message),
|
|
32
|
+
ConfigError: () => false,
|
|
33
|
+
Transient: error => connectionTimeout(error) || serverError(error),
|
|
34
|
+
Unauthorized: error => error.errorType === 'Unauthorized',
|
|
75
35
|
};
|
|
76
36
|
/**
|
|
77
37
|
* Get the first error reason of an observable.
|
|
@@ -80,8 +40,9 @@ export var syncErrorMap = {
|
|
|
80
40
|
* @param observableError an error from ZenObservable subscribe error callback
|
|
81
41
|
*/
|
|
82
42
|
function unwrapObservableError(observableError) {
|
|
83
|
-
|
|
84
|
-
|
|
43
|
+
const { errors: [error], } = ({
|
|
44
|
+
errors: [],
|
|
45
|
+
} = observableError);
|
|
85
46
|
return error;
|
|
86
47
|
}
|
|
87
48
|
export function getMutationErrorType(error) {
|
|
@@ -100,23 +61,12 @@ export function getSyncErrorType(error) {
|
|
|
100
61
|
* @param error The underying error to categorize.
|
|
101
62
|
*/
|
|
102
63
|
export function mapErrorToType(errorMap, error) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
var matcher = errorMap[errorType];
|
|
109
|
-
if (matcher === null || matcher === void 0 ? void 0 : matcher(error)) {
|
|
110
|
-
return errorType;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
115
|
-
finally {
|
|
116
|
-
try {
|
|
117
|
-
if (errorTypes_1_1 && !errorTypes_1_1.done && (_a = errorTypes_1.return)) _a.call(errorTypes_1);
|
|
64
|
+
const errorTypes = [...Object.keys(errorMap)];
|
|
65
|
+
for (const errorType of errorTypes) {
|
|
66
|
+
const matcher = errorMap[errorType];
|
|
67
|
+
if (matcher?.(error)) {
|
|
68
|
+
return errorType;
|
|
118
69
|
}
|
|
119
|
-
finally { if (e_1) throw e_1.error; }
|
|
120
70
|
}
|
|
121
71
|
return 'Unknown';
|
|
122
72
|
}
|