@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
|
@@ -1,125 +1,9 @@
|
|
|
1
|
-
var __extends = (this && this.__extends) || (function () {
|
|
2
|
-
var extendStatics = function (d, b) {
|
|
3
|
-
extendStatics = Object.setPrototypeOf ||
|
|
4
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
5
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
6
|
-
return extendStatics(d, b);
|
|
7
|
-
};
|
|
8
|
-
return function (d, b) {
|
|
9
|
-
if (typeof b !== "function" && b !== null)
|
|
10
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
11
|
-
extendStatics(d, b);
|
|
12
|
-
function __() { this.constructor = d; }
|
|
13
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
14
|
-
};
|
|
15
|
-
})();
|
|
16
|
-
var __assign = (this && this.__assign) || function () {
|
|
17
|
-
__assign = Object.assign || function(t) {
|
|
18
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
19
|
-
s = arguments[i];
|
|
20
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
21
|
-
t[p] = s[p];
|
|
22
|
-
}
|
|
23
|
-
return t;
|
|
24
|
-
};
|
|
25
|
-
return __assign.apply(this, arguments);
|
|
26
|
-
};
|
|
27
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
28
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
29
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
30
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
31
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
32
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
33
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
34
|
-
});
|
|
35
|
-
};
|
|
36
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
37
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
38
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
39
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
40
|
-
function step(op) {
|
|
41
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
42
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
43
|
-
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;
|
|
44
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
45
|
-
switch (op[0]) {
|
|
46
|
-
case 0: case 1: t = op; break;
|
|
47
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
48
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
49
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
50
|
-
default:
|
|
51
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
52
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
53
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
54
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
55
|
-
if (t[2]) _.ops.pop();
|
|
56
|
-
_.trys.pop(); continue;
|
|
57
|
-
}
|
|
58
|
-
op = body.call(thisArg, _);
|
|
59
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
60
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
64
|
-
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
65
|
-
var m = o[Symbol.asyncIterator], i;
|
|
66
|
-
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
67
|
-
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
68
|
-
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
69
|
-
};
|
|
70
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
71
|
-
var t = {};
|
|
72
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
73
|
-
t[p] = s[p];
|
|
74
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
75
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
76
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
77
|
-
t[p[i]] = s[p[i]];
|
|
78
|
-
}
|
|
79
|
-
return t;
|
|
80
|
-
};
|
|
81
|
-
var __read = (this && this.__read) || function (o, n) {
|
|
82
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
83
|
-
if (!m) return o;
|
|
84
|
-
var i = m.call(o), r, ar = [], e;
|
|
85
|
-
try {
|
|
86
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
87
|
-
}
|
|
88
|
-
catch (error) { e = { error: error }; }
|
|
89
|
-
finally {
|
|
90
|
-
try {
|
|
91
|
-
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
92
|
-
}
|
|
93
|
-
finally { if (e) throw e.error; }
|
|
94
|
-
}
|
|
95
|
-
return ar;
|
|
96
|
-
};
|
|
97
|
-
var __values = (this && this.__values) || function(o) {
|
|
98
|
-
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
99
|
-
if (m) return m.call(o);
|
|
100
|
-
if (o && typeof o.length === "number") return {
|
|
101
|
-
next: function () {
|
|
102
|
-
if (o && i >= o.length) o = void 0;
|
|
103
|
-
return { value: o && o[i++], done: !o };
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
107
|
-
};
|
|
108
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
109
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
110
|
-
if (ar || !(i in from)) {
|
|
111
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
112
|
-
ar[i] = from[i];
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
116
|
-
};
|
|
117
1
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
118
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
119
3
|
import { InternalAPI } from '@aws-amplify/api/internals';
|
|
120
4
|
import { Amplify, Hub, Cache, ConsoleLogger } from '@aws-amplify/core';
|
|
121
5
|
import { immerable, produce, setAutoFreeze, enablePatches, } from 'immer';
|
|
122
|
-
import { amplifyUuid } from '@aws-amplify/core/internals/utils';
|
|
6
|
+
import { amplifyUuid, isBrowser } from '@aws-amplify/core/internals/utils';
|
|
123
7
|
import { Observable, filter } from 'rxjs';
|
|
124
8
|
import { defaultAuthStrategy, multiAuthStrategy } from '../authModeStrategies';
|
|
125
9
|
import { isPredicatesAll, ModelPredicateCreator, ModelSortPredicateCreator, } from '../predicates';
|
|
@@ -133,21 +17,21 @@ import { getIdentifierValue } from '../sync/utils';
|
|
|
133
17
|
import { BackgroundProcessManager } from '@aws-amplify/core/internals/utils';
|
|
134
18
|
setAutoFreeze(true);
|
|
135
19
|
enablePatches();
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
20
|
+
const logger = new ConsoleLogger('DataStore');
|
|
21
|
+
const ulid = monotonicUlidFactory(Date.now());
|
|
22
|
+
const SETTING_SCHEMA_VERSION = 'schemaVersion';
|
|
23
|
+
let schema;
|
|
24
|
+
const modelNamespaceMap = new WeakMap();
|
|
141
25
|
/**
|
|
142
26
|
* Stores data for crafting the correct update mutation input for a model.
|
|
143
27
|
*
|
|
144
28
|
* - `Patch[]` - array of changed fields and metadata.
|
|
145
29
|
* - `PersistentModel` - the source model, used for diffing object-type fields.
|
|
146
30
|
*/
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
31
|
+
const modelPatchesMap = new WeakMap();
|
|
32
|
+
const getModelDefinition = (modelConstructor) => {
|
|
33
|
+
const namespace = modelNamespaceMap.get(modelConstructor);
|
|
34
|
+
const definition = namespace
|
|
151
35
|
? schema.namespaces[namespace].models[modelConstructor.name]
|
|
152
36
|
: undefined;
|
|
153
37
|
return definition;
|
|
@@ -158,13 +42,13 @@ var getModelDefinition = function (modelConstructor) {
|
|
|
158
42
|
*
|
|
159
43
|
* @param obj The object to test.
|
|
160
44
|
*/
|
|
161
|
-
|
|
45
|
+
const isValidModelConstructor = (obj) => {
|
|
162
46
|
return isModelConstructor(obj) && modelNamespaceMap.has(obj);
|
|
163
47
|
};
|
|
164
|
-
|
|
165
|
-
|
|
48
|
+
const namespaceResolver = modelConstructor => {
|
|
49
|
+
const resolver = modelNamespaceMap.get(modelConstructor);
|
|
166
50
|
if (!resolver) {
|
|
167
|
-
throw new Error(
|
|
51
|
+
throw new Error(`Namespace Resolver for '${modelConstructor.name}' not found! This is probably a bug in '@amplify-js/datastore'.`);
|
|
168
52
|
}
|
|
169
53
|
return resolver;
|
|
170
54
|
};
|
|
@@ -187,13 +71,13 @@ var namespaceResolver = function (modelConstructor) {
|
|
|
187
71
|
*
|
|
188
72
|
* @param modelConstructor The model the predicate will query.
|
|
189
73
|
*/
|
|
190
|
-
|
|
74
|
+
const buildSeedPredicate = (modelConstructor) => {
|
|
191
75
|
if (!modelConstructor)
|
|
192
76
|
throw new Error('Missing modelConstructor');
|
|
193
|
-
|
|
77
|
+
const modelSchema = getModelDefinition(modelConstructor);
|
|
194
78
|
if (!modelSchema)
|
|
195
79
|
throw new Error('Missing modelSchema');
|
|
196
|
-
|
|
80
|
+
const pks = extractPrimaryKeyFieldNames(modelSchema);
|
|
197
81
|
if (!pks)
|
|
198
82
|
throw new Error('Could not determine PK');
|
|
199
83
|
return recursivePredicateFor({
|
|
@@ -203,14 +87,14 @@ var buildSeedPredicate = function (modelConstructor) {
|
|
|
203
87
|
});
|
|
204
88
|
};
|
|
205
89
|
// exporting syncClasses for testing outbox.test.ts
|
|
206
|
-
export
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
90
|
+
export let syncClasses;
|
|
91
|
+
let userClasses;
|
|
92
|
+
let dataStoreClasses;
|
|
93
|
+
let storageClasses;
|
|
210
94
|
/**
|
|
211
95
|
* Maps a model to its related models for memoization/immutability.
|
|
212
96
|
*/
|
|
213
|
-
|
|
97
|
+
const modelInstanceAssociationsMap = new WeakMap();
|
|
214
98
|
/**
|
|
215
99
|
* Describes whether and to what a model is attached for lazy loading purposes.
|
|
216
100
|
*/
|
|
@@ -238,7 +122,7 @@ var ModelAttachment;
|
|
|
238
122
|
* If `Deatched`, the model's lazy properties will only ever return properties
|
|
239
123
|
* from memory provided at construction time.
|
|
240
124
|
*/
|
|
241
|
-
|
|
125
|
+
const attachedModelInstances = new WeakMap();
|
|
242
126
|
/**
|
|
243
127
|
* Registers a model instance against a data source (DataStore, API, or
|
|
244
128
|
* Detached/None).
|
|
@@ -252,7 +136,7 @@ var attachedModelInstances = new WeakMap();
|
|
|
252
136
|
*/
|
|
253
137
|
export function attached(result, attachment) {
|
|
254
138
|
if (Array.isArray(result)) {
|
|
255
|
-
result.map(
|
|
139
|
+
result.map(record => attached(record, attachment));
|
|
256
140
|
}
|
|
257
141
|
else {
|
|
258
142
|
result && attachedModelInstances.set(result, attachment);
|
|
@@ -266,69 +150,65 @@ export function attached(result, attachment) {
|
|
|
266
150
|
*
|
|
267
151
|
* @param instance A model instance
|
|
268
152
|
*/
|
|
269
|
-
export
|
|
153
|
+
export const getAttachment = (instance) => {
|
|
270
154
|
return attachedModelInstances.has(instance)
|
|
271
155
|
? attachedModelInstances.get(instance)
|
|
272
156
|
: ModelAttachment.Detached;
|
|
273
157
|
};
|
|
274
|
-
|
|
275
|
-
var _a;
|
|
158
|
+
const initSchema = (userSchema) => {
|
|
276
159
|
if (schema !== undefined) {
|
|
277
160
|
console.warn('The schema has already been initialized');
|
|
278
161
|
return userClasses;
|
|
279
162
|
}
|
|
280
163
|
logger.log('validating schema', { schema: userSchema });
|
|
281
164
|
checkSchemaCodegenVersion(userSchema.codegenVersion);
|
|
282
|
-
|
|
165
|
+
const internalUserNamespace = {
|
|
166
|
+
name: USER,
|
|
167
|
+
...userSchema,
|
|
168
|
+
};
|
|
283
169
|
logger.log('DataStore', 'Init models');
|
|
284
170
|
userClasses = createTypeClasses(internalUserNamespace);
|
|
285
171
|
logger.log('DataStore', 'Models initialized');
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
172
|
+
const dataStoreNamespace = getNamespace();
|
|
173
|
+
const storageNamespace = Storage.getNamespace();
|
|
174
|
+
const syncNamespace = SyncEngine.getNamespace();
|
|
289
175
|
dataStoreClasses = createTypeClasses(dataStoreNamespace);
|
|
290
176
|
storageClasses = createTypeClasses(storageNamespace);
|
|
291
177
|
syncClasses = createTypeClasses(syncNamespace);
|
|
292
178
|
schema = {
|
|
293
|
-
namespaces:
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
179
|
+
namespaces: {
|
|
180
|
+
[dataStoreNamespace.name]: dataStoreNamespace,
|
|
181
|
+
[internalUserNamespace.name]: internalUserNamespace,
|
|
182
|
+
[storageNamespace.name]: storageNamespace,
|
|
183
|
+
[syncNamespace.name]: syncNamespace,
|
|
184
|
+
},
|
|
299
185
|
version: userSchema.version,
|
|
300
186
|
codegenVersion: userSchema.codegenVersion,
|
|
301
187
|
};
|
|
302
|
-
Object.keys(schema.namespaces).forEach(
|
|
303
|
-
|
|
304
|
-
var _b = __read(establishRelationAndKeys(schema.namespaces[namespace]), 2), relations = _b[0], keys = _b[1];
|
|
188
|
+
Object.keys(schema.namespaces).forEach(namespace => {
|
|
189
|
+
const [relations, keys] = establishRelationAndKeys(schema.namespaces[namespace]);
|
|
305
190
|
schema.namespaces[namespace].relationships = relations;
|
|
306
191
|
schema.namespaces[namespace].keys = keys;
|
|
307
|
-
|
|
308
|
-
Object.values(schema.namespaces[namespace].models).forEach(
|
|
309
|
-
|
|
310
|
-
var connectedModels = [];
|
|
192
|
+
const modelAssociations = new Map();
|
|
193
|
+
Object.values(schema.namespaces[namespace].models).forEach(model => {
|
|
194
|
+
const connectedModels = [];
|
|
311
195
|
Object.values(model.fields)
|
|
312
|
-
.filter(
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
})
|
|
317
|
-
.forEach(function (field) {
|
|
318
|
-
return connectedModels.push(field.type.model);
|
|
319
|
-
});
|
|
196
|
+
.filter(field => field.association &&
|
|
197
|
+
field.association.connectionType === 'BELONGS_TO' &&
|
|
198
|
+
field.type.model !== model.name)
|
|
199
|
+
.forEach(field => connectedModels.push(field.type.model));
|
|
320
200
|
modelAssociations.set(model.name, connectedModels);
|
|
321
201
|
// Precompute model info (such as pk fields) so that downstream schema consumers
|
|
322
202
|
// (such as predicate builders) don't have to reach back into "DataStore" space
|
|
323
203
|
// to go looking for it.
|
|
324
|
-
Object.values(model.fields).forEach(
|
|
325
|
-
|
|
204
|
+
Object.values(model.fields).forEach(field => {
|
|
205
|
+
const relatedModel = userClasses[field.type.model];
|
|
326
206
|
if (isModelConstructor(relatedModel)) {
|
|
327
207
|
Object.defineProperty(field.type, 'modelConstructor', {
|
|
328
|
-
get:
|
|
329
|
-
|
|
208
|
+
get: () => {
|
|
209
|
+
const relatedModelDefinition = getModelDefinition(relatedModel);
|
|
330
210
|
if (!relatedModelDefinition)
|
|
331
|
-
throw new Error(
|
|
211
|
+
throw new Error(`Could not find model definition for ${relatedModel.name}`);
|
|
332
212
|
return {
|
|
333
213
|
builder: relatedModel,
|
|
334
214
|
schema: relatedModelDefinition,
|
|
@@ -341,44 +221,27 @@ var initSchema = function (userSchema) {
|
|
|
341
221
|
// compatibility with legacy/pre-PK codegen for lazy loading to inject
|
|
342
222
|
// index fields into the model definition.
|
|
343
223
|
// definition.cloudFields = { ...definition.fields };
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
for (
|
|
348
|
-
|
|
349
|
-
try {
|
|
350
|
-
for (var _c = (e_3 = void 0, __values(index[1])), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
351
|
-
var indexField = _d.value;
|
|
352
|
-
indexFields.add(indexField);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
356
|
-
finally {
|
|
357
|
-
try {
|
|
358
|
-
if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
|
|
359
|
-
}
|
|
360
|
-
finally { if (e_3) throw e_3.error; }
|
|
361
|
-
}
|
|
224
|
+
const indexes = schema.namespaces[namespace].relationships[model.name].indexes;
|
|
225
|
+
const indexFields = new Set();
|
|
226
|
+
for (const index of indexes) {
|
|
227
|
+
for (const indexField of index[1]) {
|
|
228
|
+
indexFields.add(indexField);
|
|
362
229
|
}
|
|
363
230
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
type: 'ID',
|
|
376
|
-
isArray: false,
|
|
377
|
-
},
|
|
378
|
-
]; }))), model.fields);
|
|
231
|
+
model.allFields = {
|
|
232
|
+
...Object.fromEntries([...indexFields.values()].map(name => [
|
|
233
|
+
name,
|
|
234
|
+
{
|
|
235
|
+
name,
|
|
236
|
+
type: 'ID',
|
|
237
|
+
isArray: false,
|
|
238
|
+
},
|
|
239
|
+
])),
|
|
240
|
+
...model.fields,
|
|
241
|
+
};
|
|
379
242
|
});
|
|
380
|
-
|
|
381
|
-
|
|
243
|
+
const result = new Map();
|
|
244
|
+
let count = 1000;
|
|
382
245
|
while (true && count > 0) {
|
|
383
246
|
if (modelAssociations.size === 0) {
|
|
384
247
|
break;
|
|
@@ -387,23 +250,13 @@ var initSchema = function (userSchema) {
|
|
|
387
250
|
if (count === 0) {
|
|
388
251
|
throw new Error('Models are not topologically sortable. Please verify your schema.');
|
|
389
252
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
if (parents === null || parents === void 0 ? void 0 : parents.every(function (x) { return result.has(x); })) {
|
|
395
|
-
result.set(modelName, parents);
|
|
396
|
-
}
|
|
253
|
+
for (const modelName of Array.from(modelAssociations.keys())) {
|
|
254
|
+
const parents = modelAssociations.get(modelName);
|
|
255
|
+
if (parents?.every(x => result.has(x))) {
|
|
256
|
+
result.set(modelName, parents);
|
|
397
257
|
}
|
|
398
258
|
}
|
|
399
|
-
|
|
400
|
-
finally {
|
|
401
|
-
try {
|
|
402
|
-
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
|
|
403
|
-
}
|
|
404
|
-
finally { if (e_1) throw e_1.error; }
|
|
405
|
-
}
|
|
406
|
-
Array.from(result.keys()).forEach(function (x) { return modelAssociations.delete(x); });
|
|
259
|
+
Array.from(result.keys()).forEach(x => modelAssociations.delete(x));
|
|
407
260
|
}
|
|
408
261
|
schema.namespaces[namespace].modelTopologicalOrdering = result;
|
|
409
262
|
});
|
|
@@ -418,9 +271,9 @@ var initSchema = function (userSchema) {
|
|
|
418
271
|
* Currently this only needs to be called in `start()` and `clear()` because
|
|
419
272
|
* all other functions will call start first.
|
|
420
273
|
*/
|
|
421
|
-
|
|
274
|
+
const checkSchemaInitialized = () => {
|
|
422
275
|
if (schema === undefined) {
|
|
423
|
-
|
|
276
|
+
const message = 'Schema is not initialized. DataStore will not function as expected. This could happen if you have multiple versions of DataStore installed. Please see https://docs.amplify.aws/lib/troubleshooting/upgrading/q/platform/js/#check-for-duplicate-versions';
|
|
424
277
|
logger.error(message);
|
|
425
278
|
throw new Error(message);
|
|
426
279
|
}
|
|
@@ -443,36 +296,34 @@ var checkSchemaInitialized = function () {
|
|
|
443
296
|
*
|
|
444
297
|
* @param codegenVersion schema codegenVersion
|
|
445
298
|
*/
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
299
|
+
const checkSchemaCodegenVersion = (codegenVersion) => {
|
|
300
|
+
const majorVersion = 3;
|
|
301
|
+
const minorVersion = 2;
|
|
302
|
+
let isValid = false;
|
|
450
303
|
try {
|
|
451
|
-
|
|
452
|
-
|
|
304
|
+
const versionParts = codegenVersion.split('.');
|
|
305
|
+
const [major, minor, patch, patchrevision] = versionParts;
|
|
453
306
|
isValid = Number(major) === majorVersion && Number(minor) >= minorVersion;
|
|
454
307
|
}
|
|
455
308
|
catch (err) {
|
|
456
|
-
console.log(
|
|
309
|
+
console.log(`Error parsing codegen version: ${codegenVersion}\n${err}`);
|
|
457
310
|
}
|
|
458
311
|
if (!isValid) {
|
|
459
|
-
|
|
312
|
+
const message = `Models were generated with an unsupported version of codegen. Codegen artifacts are from ${codegenVersion || 'an unknown version'}, whereas ^${majorVersion}.${minorVersion}.0 is required. ` +
|
|
460
313
|
"Update to the latest CLI and run 'amplify codegen models'.";
|
|
461
314
|
logger.error(message);
|
|
462
315
|
throw new Error(message);
|
|
463
316
|
}
|
|
464
317
|
};
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
Object.entries(namespace.models).forEach(
|
|
468
|
-
|
|
469
|
-
var clazz = createModelClass(modelDefinition);
|
|
318
|
+
const createTypeClasses = namespace => {
|
|
319
|
+
const classes = {};
|
|
320
|
+
Object.entries(namespace.models).forEach(([modelName, modelDefinition]) => {
|
|
321
|
+
const clazz = createModelClass(modelDefinition);
|
|
470
322
|
classes[modelName] = clazz;
|
|
471
323
|
modelNamespaceMap.set(clazz, namespace.name);
|
|
472
324
|
});
|
|
473
|
-
Object.entries(namespace.nonModels || {}).forEach(
|
|
474
|
-
|
|
475
|
-
var clazz = createNonModelClass(typeDefinition);
|
|
325
|
+
Object.entries(namespace.nonModels || {}).forEach(([typeName, typeDefinition]) => {
|
|
326
|
+
const clazz = createNonModelClass(typeDefinition);
|
|
476
327
|
classes[typeName] = clazz;
|
|
477
328
|
});
|
|
478
329
|
return classes;
|
|
@@ -482,37 +333,37 @@ var createTypeClasses = function (namespace) {
|
|
|
482
333
|
* the model visible to the consuming app -- in case the app doesn't have
|
|
483
334
|
* metadata fields (_version, _deleted, etc.) exposed on the model itself.
|
|
484
335
|
*/
|
|
485
|
-
|
|
336
|
+
const instancesMetadata = new WeakSet();
|
|
486
337
|
function modelInstanceCreator(modelConstructor, init) {
|
|
487
338
|
instancesMetadata.add(init);
|
|
488
339
|
return new modelConstructor(init);
|
|
489
340
|
}
|
|
490
|
-
|
|
491
|
-
|
|
341
|
+
const validateModelFields = (modelDefinition) => (k, v) => {
|
|
342
|
+
const fieldDefinition = modelDefinition.fields[k];
|
|
492
343
|
if (fieldDefinition !== undefined) {
|
|
493
|
-
|
|
494
|
-
|
|
344
|
+
const { type, isRequired, isArrayNullable, name, isArray } = fieldDefinition;
|
|
345
|
+
const timestamps = isSchemaModelWithAttributes(modelDefinition)
|
|
495
346
|
? getTimestampFields(modelDefinition)
|
|
496
347
|
: {};
|
|
497
|
-
|
|
498
|
-
if (((!isArray &&
|
|
348
|
+
const isTimestampField = !!timestamps[name];
|
|
349
|
+
if (((!isArray && isRequired) || (isArray && !isArrayNullable)) &&
|
|
499
350
|
!isTimestampField &&
|
|
500
351
|
(v === null || v === undefined)) {
|
|
501
|
-
throw new Error(
|
|
352
|
+
throw new Error(`Field ${name} is required`);
|
|
502
353
|
}
|
|
503
354
|
if (isSchemaModelWithAttributes(modelDefinition) &&
|
|
504
355
|
!isIdManaged(modelDefinition)) {
|
|
505
|
-
|
|
356
|
+
const keys = extractPrimaryKeyFieldNames(modelDefinition);
|
|
506
357
|
if (keys.includes(k) && v === '') {
|
|
507
|
-
logger.error(errorMessages.idEmptyString, { k
|
|
358
|
+
logger.error(errorMessages.idEmptyString, { k, value: v });
|
|
508
359
|
throw new Error(errorMessages.idEmptyString);
|
|
509
360
|
}
|
|
510
361
|
}
|
|
511
|
-
if (isGraphQLScalarType(
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
if (
|
|
515
|
-
if (typeof v ===
|
|
362
|
+
if (isGraphQLScalarType(type)) {
|
|
363
|
+
const jsType = GraphQLScalarType.getJSType(type);
|
|
364
|
+
const validateScalar = GraphQLScalarType.getValidationFunction(type);
|
|
365
|
+
if (type === 'AWSJSON') {
|
|
366
|
+
if (typeof v === jsType) {
|
|
516
367
|
return;
|
|
517
368
|
}
|
|
518
369
|
if (typeof v === 'string') {
|
|
@@ -521,96 +372,94 @@ var validateModelFields = function (modelDefinition) { return function (k, v) {
|
|
|
521
372
|
return;
|
|
522
373
|
}
|
|
523
374
|
catch (error) {
|
|
524
|
-
throw new Error(
|
|
375
|
+
throw new Error(`Field ${name} is an invalid JSON object. ${v}`);
|
|
525
376
|
}
|
|
526
377
|
}
|
|
527
378
|
}
|
|
528
379
|
if (isArray) {
|
|
529
|
-
|
|
530
|
-
if (!
|
|
531
|
-
errorTypeText =
|
|
380
|
+
let errorTypeText = jsType;
|
|
381
|
+
if (!isRequired) {
|
|
382
|
+
errorTypeText = `${jsType} | null | undefined`;
|
|
532
383
|
}
|
|
533
384
|
if (!Array.isArray(v) && !isArrayNullable) {
|
|
534
|
-
throw new Error(
|
|
385
|
+
throw new Error(`Field ${name} should be of type [${errorTypeText}], ${typeof v} received. ${v}`);
|
|
535
386
|
}
|
|
536
387
|
if (!isNullOrUndefined(v) &&
|
|
537
|
-
v.some(
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
var elemTypes = v
|
|
541
|
-
.map(function (e) { return (e === null ? 'null' : typeof e); })
|
|
388
|
+
v.some(e => isNullOrUndefined(e) ? isRequired : typeof e !== jsType)) {
|
|
389
|
+
const elemTypes = v
|
|
390
|
+
.map(e => (e === null ? 'null' : typeof e))
|
|
542
391
|
.join(',');
|
|
543
|
-
throw new Error(
|
|
392
|
+
throw new Error(`All elements in the ${name} array should be of type ${errorTypeText}, [${elemTypes}] received. ${v}`);
|
|
544
393
|
}
|
|
545
|
-
if (
|
|
546
|
-
|
|
394
|
+
if (validateScalar && !isNullOrUndefined(v)) {
|
|
395
|
+
const validationStatus = v.map(e => {
|
|
547
396
|
if (!isNullOrUndefined(e)) {
|
|
548
|
-
return
|
|
397
|
+
return validateScalar(e);
|
|
549
398
|
}
|
|
550
|
-
else if (isNullOrUndefined(e) && !
|
|
399
|
+
else if (isNullOrUndefined(e) && !isRequired) {
|
|
551
400
|
return true;
|
|
552
401
|
}
|
|
553
402
|
else {
|
|
554
403
|
return false;
|
|
555
404
|
}
|
|
556
405
|
});
|
|
557
|
-
if (!validationStatus.every(
|
|
558
|
-
throw new Error(
|
|
406
|
+
if (!validationStatus.every(s => s)) {
|
|
407
|
+
throw new Error(`All elements in the ${name} array should be of type ${type}, validation failed for one or more elements. ${v}`);
|
|
559
408
|
}
|
|
560
409
|
}
|
|
561
410
|
}
|
|
562
|
-
else if (!
|
|
411
|
+
else if (!isRequired && v === undefined) {
|
|
563
412
|
return;
|
|
564
413
|
}
|
|
565
|
-
else if (typeof v !==
|
|
566
|
-
throw new Error(
|
|
414
|
+
else if (typeof v !== jsType && v !== null) {
|
|
415
|
+
throw new Error(`Field ${name} should be of type ${jsType}, ${typeof v} received. ${v}`);
|
|
567
416
|
}
|
|
568
417
|
else if (!isNullOrUndefined(v) &&
|
|
569
|
-
|
|
570
|
-
!
|
|
418
|
+
validateScalar &&
|
|
419
|
+
!validateScalar(v) // TODO: why never, TS ... why ...
|
|
571
420
|
) {
|
|
572
|
-
throw new Error(
|
|
421
|
+
throw new Error(`Field ${name} should be of type ${type}, validation failed. ${v}`);
|
|
573
422
|
}
|
|
574
423
|
}
|
|
575
|
-
else if (isNonModelFieldType(
|
|
424
|
+
else if (isNonModelFieldType(type)) {
|
|
576
425
|
// do not check non model fields if undefined or null
|
|
577
426
|
if (!isNullOrUndefined(v)) {
|
|
578
|
-
|
|
579
|
-
|
|
427
|
+
const subNonModelDefinition = schema.namespaces.user.nonModels[type.nonModel];
|
|
428
|
+
const modelValidator = validateModelFields(subNonModelDefinition);
|
|
580
429
|
if (isArray) {
|
|
581
|
-
|
|
582
|
-
if (!
|
|
583
|
-
errorTypeText =
|
|
430
|
+
let errorTypeText = type.nonModel;
|
|
431
|
+
if (!isRequired) {
|
|
432
|
+
errorTypeText = `${type.nonModel} | null | undefined`;
|
|
584
433
|
}
|
|
585
434
|
if (!Array.isArray(v)) {
|
|
586
|
-
throw new Error(
|
|
435
|
+
throw new Error(`Field ${name} should be of type [${errorTypeText}], ${typeof v} received. ${v}`);
|
|
587
436
|
}
|
|
588
|
-
v.forEach(
|
|
589
|
-
if ((isNullOrUndefined(item) &&
|
|
437
|
+
v.forEach(item => {
|
|
438
|
+
if ((isNullOrUndefined(item) && isRequired) ||
|
|
590
439
|
(typeof item !== 'object' && typeof item !== 'undefined')) {
|
|
591
|
-
throw new Error(
|
|
440
|
+
throw new Error(`All elements in the ${name} array should be of type ${type.nonModel}, [${typeof item}] received. ${item}`);
|
|
592
441
|
}
|
|
593
442
|
if (!isNullOrUndefined(item)) {
|
|
594
|
-
Object.keys(
|
|
595
|
-
|
|
443
|
+
Object.keys(subNonModelDefinition.fields).forEach(subKey => {
|
|
444
|
+
modelValidator(subKey, item[subKey]);
|
|
596
445
|
});
|
|
597
446
|
}
|
|
598
447
|
});
|
|
599
448
|
}
|
|
600
449
|
else {
|
|
601
450
|
if (typeof v !== 'object') {
|
|
602
|
-
throw new Error(
|
|
451
|
+
throw new Error(`Field ${name} should be of type ${type.nonModel}, ${typeof v} recieved. ${v}`);
|
|
603
452
|
}
|
|
604
|
-
Object.keys(
|
|
605
|
-
|
|
453
|
+
Object.keys(subNonModelDefinition.fields).forEach(subKey => {
|
|
454
|
+
modelValidator(subKey, v[subKey]);
|
|
606
455
|
});
|
|
607
456
|
}
|
|
608
457
|
}
|
|
609
458
|
}
|
|
610
459
|
}
|
|
611
|
-
};
|
|
612
|
-
|
|
613
|
-
|
|
460
|
+
};
|
|
461
|
+
const castInstanceType = (modelDefinition, k, v) => {
|
|
462
|
+
const { isArray, type } = modelDefinition.fields[k] || {};
|
|
614
463
|
// attempt to parse stringified JSON
|
|
615
464
|
if (typeof v === 'string' &&
|
|
616
465
|
(isArray ||
|
|
@@ -620,7 +469,7 @@ var castInstanceType = function (modelDefinition, k, v) {
|
|
|
620
469
|
try {
|
|
621
470
|
return JSON.parse(v);
|
|
622
471
|
}
|
|
623
|
-
catch
|
|
472
|
+
catch {
|
|
624
473
|
// if JSON is invalid, don't throw and let modelValidator handle it
|
|
625
474
|
}
|
|
626
475
|
}
|
|
@@ -635,7 +484,7 @@ var castInstanceType = function (modelDefinition, k, v) {
|
|
|
635
484
|
* an instance of a Model. This can be used for determining which fields to
|
|
636
485
|
* send to the cloud durnig a CREATE mutation.
|
|
637
486
|
*/
|
|
638
|
-
|
|
487
|
+
const initPatches = new WeakMap();
|
|
639
488
|
/**
|
|
640
489
|
* Attempts to apply type-aware, casted field values from a given `init`
|
|
641
490
|
* object to the given `draft`.
|
|
@@ -644,11 +493,10 @@ var initPatches = new WeakMap();
|
|
|
644
493
|
* @param modelDefinition The definition describing the target object shape.
|
|
645
494
|
* @param draft The draft to apply field values to.
|
|
646
495
|
*/
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
Object.entries(init).forEach(
|
|
650
|
-
|
|
651
|
-
var parsedValue = castInstanceType(modelDefinition, k, v);
|
|
496
|
+
const initializeInstance = (init, modelDefinition, draft) => {
|
|
497
|
+
const modelValidator = validateModelFields(modelDefinition);
|
|
498
|
+
Object.entries(init).forEach(([k, v]) => {
|
|
499
|
+
const parsedValue = castInstanceType(modelDefinition, k, v);
|
|
652
500
|
modelValidator(k, parsedValue);
|
|
653
501
|
draft[k] = parsedValue;
|
|
654
502
|
});
|
|
@@ -672,42 +520,30 @@ var initializeInstance = function (init, modelDefinition, draft) {
|
|
|
672
520
|
* @param modelDefinition Definition for the draft. Used to discover all fields.
|
|
673
521
|
* @param draft The instance draft to apply normalizations to.
|
|
674
522
|
*/
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
var k = _c.value;
|
|
680
|
-
if (draft[k] === undefined)
|
|
681
|
-
draft[k] = null;
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
685
|
-
finally {
|
|
686
|
-
try {
|
|
687
|
-
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
688
|
-
}
|
|
689
|
-
finally { if (e_4) throw e_4.error; }
|
|
523
|
+
const normalize = (modelDefinition, draft) => {
|
|
524
|
+
for (const k of Object.keys(modelDefinition.fields)) {
|
|
525
|
+
if (draft[k] === undefined)
|
|
526
|
+
draft[k] = null;
|
|
690
527
|
}
|
|
691
528
|
};
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
function Model(init) {
|
|
529
|
+
const createModelClass = (modelDefinition) => {
|
|
530
|
+
const clazz = class Model {
|
|
531
|
+
constructor(init) {
|
|
696
532
|
// we create a base instance first so we can distinguish which fields were explicitly
|
|
697
533
|
// set by customer code versus those set by normalization. only those fields
|
|
698
534
|
// which are explicitly set by customers should be part of create mutations.
|
|
699
|
-
|
|
700
|
-
|
|
535
|
+
let patches = [];
|
|
536
|
+
const baseInstance = produce(this, (draft) => {
|
|
701
537
|
initializeInstance(init, modelDefinition, draft);
|
|
702
538
|
// model is initialized inside a DataStore component (e.g. by Sync Engine, Storage Engine, etc.)
|
|
703
|
-
|
|
704
|
-
|
|
539
|
+
const isInternallyInitialized = instancesMetadata.has(init);
|
|
540
|
+
const modelInstanceMetadata = isInternallyInitialized
|
|
705
541
|
? init
|
|
706
542
|
: {};
|
|
707
|
-
|
|
543
|
+
const { id: _id } = modelInstanceMetadata;
|
|
708
544
|
if (isIdManaged(modelDefinition)) {
|
|
709
|
-
|
|
710
|
-
|
|
545
|
+
const isInternalModel = _id !== null && _id !== undefined;
|
|
546
|
+
const id = isInternalModel
|
|
711
547
|
? _id
|
|
712
548
|
: modelDefinition.syncable
|
|
713
549
|
? amplifyUuid()
|
|
@@ -722,55 +558,52 @@ var createModelClass = function (modelDefinition) {
|
|
|
722
558
|
if (!isInternallyInitialized) {
|
|
723
559
|
checkReadOnlyPropertyOnCreate(draft, modelDefinition);
|
|
724
560
|
}
|
|
725
|
-
|
|
561
|
+
const { _version, _lastChangedAt, _deleted } = modelInstanceMetadata;
|
|
726
562
|
if (modelDefinition.syncable) {
|
|
727
563
|
draft._version = _version;
|
|
728
564
|
draft._lastChangedAt = _lastChangedAt;
|
|
729
565
|
draft._deleted = _deleted;
|
|
730
566
|
}
|
|
731
|
-
},
|
|
567
|
+
}, p => (patches = p));
|
|
732
568
|
// now that we have a list of patches that encapsulate the explicit, customer-provided
|
|
733
569
|
// fields, we can normalize. patches from normalization are ignored, because the changes
|
|
734
570
|
// are only create to provide a consistent view of the data for fields pre/post sync
|
|
735
571
|
// where possible. (not all fields can be normalized pre-sync, because they're generally
|
|
736
572
|
// "cloud managed" fields, like createdAt and updatedAt.)
|
|
737
|
-
|
|
738
|
-
return normalize(modelDefinition, draft);
|
|
739
|
-
});
|
|
573
|
+
const normalized = produce(baseInstance, (draft) => normalize(modelDefinition, draft));
|
|
740
574
|
initPatches.set(normalized, patches);
|
|
741
575
|
return normalized;
|
|
742
576
|
}
|
|
743
|
-
|
|
744
|
-
|
|
577
|
+
static copyOf(source, fn) {
|
|
578
|
+
const modelConstructor = Object.getPrototypeOf(source || {}).constructor;
|
|
745
579
|
if (!isValidModelConstructor(modelConstructor)) {
|
|
746
|
-
|
|
747
|
-
logger.error(msg, { source
|
|
580
|
+
const msg = 'The source object is not a valid model';
|
|
581
|
+
logger.error(msg, { source });
|
|
748
582
|
throw new Error(msg);
|
|
749
583
|
}
|
|
750
|
-
|
|
751
|
-
|
|
584
|
+
let patches = [];
|
|
585
|
+
const model = produce(source, draft => {
|
|
752
586
|
fn(draft);
|
|
753
|
-
|
|
587
|
+
const keyNames = extractPrimaryKeyFieldNames(modelDefinition);
|
|
754
588
|
// Keys are immutable
|
|
755
|
-
keyNames.forEach(
|
|
589
|
+
keyNames.forEach(key => {
|
|
756
590
|
if (draft[key] !== source[key]) {
|
|
757
|
-
logger.warn(
|
|
591
|
+
logger.warn(`copyOf() does not update PK fields. The '${key}' update is being ignored.`, { source });
|
|
758
592
|
}
|
|
759
593
|
draft[key] = source[key];
|
|
760
594
|
});
|
|
761
|
-
|
|
762
|
-
Object.entries(draft).forEach(
|
|
763
|
-
|
|
764
|
-
var parsedValue = castInstanceType(modelDefinition, k, v);
|
|
595
|
+
const modelValidator = validateModelFields(modelDefinition);
|
|
596
|
+
Object.entries(draft).forEach(([k, v]) => {
|
|
597
|
+
const parsedValue = castInstanceType(modelDefinition, k, v);
|
|
765
598
|
modelValidator(k, parsedValue);
|
|
766
599
|
});
|
|
767
600
|
normalize(modelDefinition, draft);
|
|
768
|
-
},
|
|
769
|
-
|
|
601
|
+
}, p => (patches = p));
|
|
602
|
+
const hasExistingPatches = modelPatchesMap.has(source);
|
|
770
603
|
if (patches.length || hasExistingPatches) {
|
|
771
604
|
if (hasExistingPatches) {
|
|
772
|
-
|
|
773
|
-
|
|
605
|
+
const [existingPatches, existingSource] = modelPatchesMap.get(source);
|
|
606
|
+
const mergedPatches = mergePatches(existingSource, existingPatches, patches);
|
|
774
607
|
modelPatchesMap.set(model, [mergedPatches, existingSource]);
|
|
775
608
|
checkReadOnlyPropertyOnUpdate(mergedPatches, modelDefinition);
|
|
776
609
|
}
|
|
@@ -789,38 +622,35 @@ var createModelClass = function (modelDefinition) {
|
|
|
789
622
|
modelPatchesMap.set(model, [[], source]);
|
|
790
623
|
}
|
|
791
624
|
return attached(model, ModelAttachment.DataStore);
|
|
792
|
-
}
|
|
625
|
+
}
|
|
793
626
|
// "private" method (that's hidden via `Setting`) for `withSSRContext` to use
|
|
794
627
|
// to gain access to `modelInstanceCreator` and `clazz` for persisting IDs from server to client.
|
|
795
|
-
|
|
796
|
-
var _this = this;
|
|
628
|
+
static fromJSON(json) {
|
|
797
629
|
if (Array.isArray(json)) {
|
|
798
|
-
return json.map(
|
|
630
|
+
return json.map(init => this.fromJSON(init));
|
|
799
631
|
}
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
Object.entries(instance).forEach(
|
|
803
|
-
var _b = __read(_a, 2), k = _b[0], v = _b[1];
|
|
632
|
+
const instance = modelInstanceCreator(clazz, json);
|
|
633
|
+
const modelValidator = validateModelFields(modelDefinition);
|
|
634
|
+
Object.entries(instance).forEach(([k, v]) => {
|
|
804
635
|
modelValidator(k, v);
|
|
805
636
|
});
|
|
806
637
|
return attached(instance, ModelAttachment.DataStore);
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
}());
|
|
638
|
+
}
|
|
639
|
+
};
|
|
810
640
|
clazz[immerable] = true;
|
|
811
641
|
Object.defineProperty(clazz, 'name', { value: modelDefinition.name });
|
|
812
642
|
// Add getters/setters for relationship fields.
|
|
813
643
|
// getter - for lazy loading
|
|
814
644
|
// setter - for FK management
|
|
815
|
-
|
|
645
|
+
const allModelRelationships = ModelRelationship.allFrom({
|
|
816
646
|
builder: clazz,
|
|
817
647
|
schema: modelDefinition,
|
|
818
648
|
pkField: extractPrimaryKeyFieldNames(modelDefinition),
|
|
819
649
|
});
|
|
820
|
-
|
|
821
|
-
|
|
650
|
+
for (const relationship of allModelRelationships) {
|
|
651
|
+
const field = relationship.field;
|
|
822
652
|
Object.defineProperty(clazz.prototype, modelDefinition.fields[field].name, {
|
|
823
|
-
set
|
|
653
|
+
set(model) {
|
|
824
654
|
if (!(typeof model === 'object' || typeof model === 'undefined'))
|
|
825
655
|
return;
|
|
826
656
|
// if model is undefined or null, the connection should be removed
|
|
@@ -829,39 +659,38 @@ var createModelClass = function (modelDefinition) {
|
|
|
829
659
|
// selection set. Nested entitites lack version field and can not be validated
|
|
830
660
|
// TODO: explore a more reliable method to solve this
|
|
831
661
|
if (model.hasOwnProperty('_version')) {
|
|
832
|
-
|
|
662
|
+
const modelConstructor = Object.getPrototypeOf(model || {})
|
|
833
663
|
.constructor;
|
|
834
664
|
if (!isValidModelConstructor(modelConstructor)) {
|
|
835
|
-
|
|
836
|
-
logger.error(msg, { model
|
|
665
|
+
const msg = `Value passed to ${modelDefinition.name}.${field} is not a valid instance of a model`;
|
|
666
|
+
logger.error(msg, { model });
|
|
837
667
|
throw new Error(msg);
|
|
838
668
|
}
|
|
839
669
|
if (modelConstructor.name.toLowerCase() !==
|
|
840
670
|
relationship.remoteModelConstructor.name.toLowerCase()) {
|
|
841
|
-
|
|
842
|
-
logger.error(msg, { model
|
|
671
|
+
const msg = `Value passed to ${modelDefinition.name}.${field} is not an instance of ${relationship.remoteModelConstructor.name}`;
|
|
672
|
+
logger.error(msg, { model });
|
|
843
673
|
throw new Error(msg);
|
|
844
674
|
}
|
|
845
675
|
}
|
|
846
676
|
}
|
|
847
677
|
// if the relationship can be managed automagically, set the FK's
|
|
848
678
|
if (relationship.isComplete) {
|
|
849
|
-
for (
|
|
679
|
+
for (let i = 0; i < relationship.localJoinFields.length; i++) {
|
|
850
680
|
this[relationship.localJoinFields[i]] =
|
|
851
|
-
model
|
|
681
|
+
model?.[relationship.remoteJoinFields[i]];
|
|
852
682
|
}
|
|
853
|
-
|
|
683
|
+
const instanceMemos = modelInstanceAssociationsMap.has(this)
|
|
854
684
|
? modelInstanceAssociationsMap.get(this)
|
|
855
685
|
: modelInstanceAssociationsMap.set(this, {}).get(this);
|
|
856
686
|
instanceMemos[field] = model || undefined;
|
|
857
687
|
}
|
|
858
688
|
},
|
|
859
|
-
get
|
|
860
|
-
var _this = this;
|
|
689
|
+
get() {
|
|
861
690
|
/**
|
|
862
691
|
* Bucket for holding related models instances specific to `this` instance.
|
|
863
692
|
*/
|
|
864
|
-
|
|
693
|
+
const instanceMemos = modelInstanceAssociationsMap.has(this)
|
|
865
694
|
? modelInstanceAssociationsMap.get(this)
|
|
866
695
|
: modelInstanceAssociationsMap.set(this, {}).get(this);
|
|
867
696
|
// if the memos already has a result for this field, we'll use it.
|
|
@@ -875,14 +704,12 @@ var createModelClass = function (modelDefinition) {
|
|
|
875
704
|
// of the relationship metadata, we DO NOT AWAIT resolution. we want to
|
|
876
705
|
// drop the promise into the memo's synchronously, eliminating the chance
|
|
877
706
|
// for a race.
|
|
878
|
-
|
|
879
|
-
return
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
return q[field].eq(_this[relationship.localJoinFields[index]]);
|
|
883
|
-
});
|
|
707
|
+
const resultPromise = instance.query(relationship.remoteModelConstructor, base => base.and(q => {
|
|
708
|
+
return relationship.remoteJoinFields.map((field, index) => {
|
|
709
|
+
// TODO: anything we can use instead of `any` here?
|
|
710
|
+
return q[field].eq(this[relationship.localJoinFields[index]]);
|
|
884
711
|
});
|
|
885
|
-
});
|
|
712
|
+
}));
|
|
886
713
|
// results in hand, how we return them to the caller depends on the relationship type.
|
|
887
714
|
if (relationship.type === 'HAS_MANY') {
|
|
888
715
|
// collections should support async iteration, even though we don't
|
|
@@ -893,10 +720,13 @@ var createModelClass = function (modelDefinition) {
|
|
|
893
720
|
// non-collections should only ever return 1 value *or nothing*.
|
|
894
721
|
// if we have more than 1 record, something's amiss. it's not our job
|
|
895
722
|
// pick a result for the customer. it's our job to say "something's wrong."
|
|
896
|
-
instanceMemos[field] = resultPromise.then(
|
|
723
|
+
instanceMemos[field] = resultPromise.then(rows => {
|
|
897
724
|
if (rows.length > 1) {
|
|
898
725
|
// should never happen for a HAS_ONE or BELONGS_TO.
|
|
899
|
-
|
|
726
|
+
const err = new Error(`
|
|
727
|
+
Data integrity error.
|
|
728
|
+
Too many records found for a HAS_ONE/BELONGS_TO field '${modelDefinition.name}.${field}'
|
|
729
|
+
`);
|
|
900
730
|
console.error(err);
|
|
901
731
|
throw err;
|
|
902
732
|
}
|
|
@@ -921,40 +751,21 @@ var createModelClass = function (modelDefinition) {
|
|
|
921
751
|
return instanceMemos[field];
|
|
922
752
|
},
|
|
923
753
|
});
|
|
924
|
-
};
|
|
925
|
-
try {
|
|
926
|
-
for (var allModelRelationships_1 = __values(allModelRelationships), allModelRelationships_1_1 = allModelRelationships_1.next(); !allModelRelationships_1_1.done; allModelRelationships_1_1 = allModelRelationships_1.next()) {
|
|
927
|
-
var relationship = allModelRelationships_1_1.value;
|
|
928
|
-
_loop_1(relationship);
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
932
|
-
finally {
|
|
933
|
-
try {
|
|
934
|
-
if (allModelRelationships_1_1 && !allModelRelationships_1_1.done && (_a = allModelRelationships_1.return)) _a.call(allModelRelationships_1);
|
|
935
|
-
}
|
|
936
|
-
finally { if (e_5) throw e_5.error; }
|
|
937
754
|
}
|
|
938
755
|
return clazz;
|
|
939
756
|
};
|
|
940
757
|
/**
|
|
941
758
|
* An eventually loaded related model instance.
|
|
942
759
|
*/
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
function AsyncItem() {
|
|
946
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
947
|
-
}
|
|
948
|
-
return AsyncItem;
|
|
949
|
-
}(Promise));
|
|
950
|
-
export { AsyncItem };
|
|
760
|
+
export class AsyncItem extends Promise {
|
|
761
|
+
}
|
|
951
762
|
/**
|
|
952
763
|
* A collection of related model instances.
|
|
953
764
|
*
|
|
954
765
|
* This collection can be async-iterated or turned directly into an array using `toArray()`.
|
|
955
766
|
*/
|
|
956
|
-
|
|
957
|
-
|
|
767
|
+
export class AsyncCollection {
|
|
768
|
+
constructor(values) {
|
|
958
769
|
this.values = values;
|
|
959
770
|
}
|
|
960
771
|
/**
|
|
@@ -968,39 +779,28 @@ var AsyncCollection = /** @class */ (function () {
|
|
|
968
779
|
*
|
|
969
780
|
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of
|
|
970
781
|
*/
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
var index = 0;
|
|
782
|
+
[Symbol.asyncIterator]() {
|
|
783
|
+
let values;
|
|
784
|
+
let index = 0;
|
|
975
785
|
return {
|
|
976
|
-
next:
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
index++;
|
|
993
|
-
return [2 /*return*/, result];
|
|
994
|
-
}
|
|
995
|
-
return [2 /*return*/, {
|
|
996
|
-
value: null,
|
|
997
|
-
done: true,
|
|
998
|
-
}];
|
|
999
|
-
}
|
|
1000
|
-
});
|
|
1001
|
-
}); },
|
|
786
|
+
next: async () => {
|
|
787
|
+
if (!values)
|
|
788
|
+
values = await this.values;
|
|
789
|
+
if (index < values.length) {
|
|
790
|
+
const result = {
|
|
791
|
+
value: values[index],
|
|
792
|
+
done: false,
|
|
793
|
+
};
|
|
794
|
+
index++;
|
|
795
|
+
return result;
|
|
796
|
+
}
|
|
797
|
+
return {
|
|
798
|
+
value: null,
|
|
799
|
+
done: true,
|
|
800
|
+
};
|
|
801
|
+
},
|
|
1002
802
|
};
|
|
1003
|
-
}
|
|
803
|
+
}
|
|
1004
804
|
/**
|
|
1005
805
|
* Turns the collection into an array, up to the amount specified in `max` param.
|
|
1006
806
|
*
|
|
@@ -1009,97 +809,50 @@ var AsyncCollection = /** @class */ (function () {
|
|
|
1009
809
|
* const first100 = await collection.toArray({max: 100});
|
|
1010
810
|
* ```
|
|
1011
811
|
*/
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
_g = false;
|
|
1032
|
-
try {
|
|
1033
|
-
element = _d;
|
|
1034
|
-
if (i < max) {
|
|
1035
|
-
output.push(element);
|
|
1036
|
-
i++;
|
|
1037
|
-
}
|
|
1038
|
-
else {
|
|
1039
|
-
return [3 /*break*/, 5];
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
finally {
|
|
1043
|
-
_g = true;
|
|
1044
|
-
}
|
|
1045
|
-
_k.label = 4;
|
|
1046
|
-
case 4: return [3 /*break*/, 2];
|
|
1047
|
-
case 5: return [3 /*break*/, 12];
|
|
1048
|
-
case 6:
|
|
1049
|
-
e_6_1 = _k.sent();
|
|
1050
|
-
e_6 = { error: e_6_1 };
|
|
1051
|
-
return [3 /*break*/, 12];
|
|
1052
|
-
case 7:
|
|
1053
|
-
_k.trys.push([7, , 10, 11]);
|
|
1054
|
-
if (!(!_g && !_b && (_c = _h.return))) return [3 /*break*/, 9];
|
|
1055
|
-
return [4 /*yield*/, _c.call(_h)];
|
|
1056
|
-
case 8:
|
|
1057
|
-
_k.sent();
|
|
1058
|
-
_k.label = 9;
|
|
1059
|
-
case 9: return [3 /*break*/, 11];
|
|
1060
|
-
case 10:
|
|
1061
|
-
if (e_6) throw e_6.error;
|
|
1062
|
-
return [7 /*endfinally*/];
|
|
1063
|
-
case 11: return [7 /*endfinally*/];
|
|
1064
|
-
case 12: return [2 /*return*/, output];
|
|
1065
|
-
}
|
|
1066
|
-
});
|
|
1067
|
-
});
|
|
1068
|
-
};
|
|
1069
|
-
return AsyncCollection;
|
|
1070
|
-
}());
|
|
1071
|
-
export { AsyncCollection };
|
|
1072
|
-
var checkReadOnlyPropertyOnCreate = function (draft, modelDefinition) {
|
|
1073
|
-
var modelKeys = Object.keys(draft);
|
|
1074
|
-
var fields = modelDefinition.fields;
|
|
1075
|
-
modelKeys.forEach(function (key) {
|
|
812
|
+
async toArray({ max = Number.MAX_SAFE_INTEGER, } = {}) {
|
|
813
|
+
const output = [];
|
|
814
|
+
let i = 0;
|
|
815
|
+
for await (const element of this) {
|
|
816
|
+
if (i < max) {
|
|
817
|
+
output.push(element);
|
|
818
|
+
i++;
|
|
819
|
+
}
|
|
820
|
+
else {
|
|
821
|
+
break;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
return output;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
const checkReadOnlyPropertyOnCreate = (draft, modelDefinition) => {
|
|
828
|
+
const modelKeys = Object.keys(draft);
|
|
829
|
+
const { fields } = modelDefinition;
|
|
830
|
+
modelKeys.forEach(key => {
|
|
1076
831
|
if (fields[key] && fields[key].isReadOnly) {
|
|
1077
|
-
throw new Error(
|
|
832
|
+
throw new Error(`${key} is read-only.`);
|
|
1078
833
|
}
|
|
1079
834
|
});
|
|
1080
835
|
};
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
patchArray.forEach(
|
|
1085
|
-
var _b = __read(_a, 2), key = _b[0], val = _b[1];
|
|
836
|
+
const checkReadOnlyPropertyOnUpdate = (patches, modelDefinition) => {
|
|
837
|
+
const patchArray = patches.map(p => [p.path[0], p.value]);
|
|
838
|
+
const { fields } = modelDefinition;
|
|
839
|
+
patchArray.forEach(([key, val]) => {
|
|
1086
840
|
if (!val || !fields[key])
|
|
1087
841
|
return;
|
|
1088
842
|
if (fields[key].isReadOnly) {
|
|
1089
|
-
throw new Error(
|
|
843
|
+
throw new Error(`${key} is read-only.`);
|
|
1090
844
|
}
|
|
1091
845
|
});
|
|
1092
846
|
};
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
847
|
+
const createNonModelClass = (typeDefinition) => {
|
|
848
|
+
const clazz = class Model {
|
|
849
|
+
constructor(init) {
|
|
850
|
+
const instance = produce(this, (draft) => {
|
|
1097
851
|
initializeInstance(init, typeDefinition, draft);
|
|
1098
852
|
});
|
|
1099
853
|
return instance;
|
|
1100
854
|
}
|
|
1101
|
-
|
|
1102
|
-
}());
|
|
855
|
+
};
|
|
1103
856
|
clazz[immerable] = true;
|
|
1104
857
|
Object.defineProperty(clazz, 'name', { value: typeDefinition.name });
|
|
1105
858
|
registerNonModelClass(clazz);
|
|
@@ -1109,15 +862,15 @@ function isQueryOne(obj) {
|
|
|
1109
862
|
return typeof obj === 'string';
|
|
1110
863
|
}
|
|
1111
864
|
function defaultConflictHandler(conflictData) {
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
return modelInstanceCreator(modelConstructor,
|
|
865
|
+
const { localModel, modelConstructor, remoteModel } = conflictData;
|
|
866
|
+
const { _version } = remoteModel;
|
|
867
|
+
return modelInstanceCreator(modelConstructor, { ...localModel, _version });
|
|
1115
868
|
}
|
|
1116
869
|
function defaultErrorHandler(error) {
|
|
1117
870
|
logger.warn(error);
|
|
1118
871
|
}
|
|
1119
872
|
function getModelConstructorByModelName(namespaceName, modelName) {
|
|
1120
|
-
|
|
873
|
+
let result;
|
|
1121
874
|
switch (namespaceName) {
|
|
1122
875
|
case DATASTORE:
|
|
1123
876
|
result = dataStoreClasses[modelName];
|
|
@@ -1132,13 +885,13 @@ function getModelConstructorByModelName(namespaceName, modelName) {
|
|
|
1132
885
|
result = storageClasses[modelName];
|
|
1133
886
|
break;
|
|
1134
887
|
default:
|
|
1135
|
-
throw new Error(
|
|
888
|
+
throw new Error(`Invalid namespace: ${namespaceName}`);
|
|
1136
889
|
}
|
|
1137
890
|
if (isValidModelConstructor(result)) {
|
|
1138
891
|
return result;
|
|
1139
892
|
}
|
|
1140
893
|
else {
|
|
1141
|
-
|
|
894
|
+
const msg = `Model name is not valid for namespace. modelName: ${modelName}, namespace: ${namespaceName}`;
|
|
1142
895
|
logger.error(msg);
|
|
1143
896
|
throw new Error(msg);
|
|
1144
897
|
}
|
|
@@ -1155,54 +908,31 @@ function getModelConstructorByModelName(namespaceName, modelName) {
|
|
|
1155
908
|
* @param storage Storage adapter containing the metadata.
|
|
1156
909
|
* @param version The expected schema version.
|
|
1157
910
|
*/
|
|
1158
|
-
function checkSchemaVersion(storage, version) {
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
switch (_b.label) {
|
|
1171
|
-
case 0: return [4 /*yield*/, s.query(Setting, ModelPredicateCreator.createFromAST(modelDefinition, {
|
|
1172
|
-
and: { key: { eq: SETTING_SCHEMA_VERSION } },
|
|
1173
|
-
}), { page: 0, limit: 1 })];
|
|
1174
|
-
case 1:
|
|
1175
|
-
_a = __read.apply(void 0, [_b.sent(), 1]), schemaVersionSetting = _a[0];
|
|
1176
|
-
if (!(schemaVersionSetting !== undefined &&
|
|
1177
|
-
schemaVersionSetting.value !== undefined)) return [3 /*break*/, 4];
|
|
1178
|
-
storedValue = JSON.parse(schemaVersionSetting.value);
|
|
1179
|
-
if (!(storedValue !== version)) return [3 /*break*/, 3];
|
|
1180
|
-
return [4 /*yield*/, s.clear(false)];
|
|
1181
|
-
case 2:
|
|
1182
|
-
_b.sent();
|
|
1183
|
-
_b.label = 3;
|
|
1184
|
-
case 3: return [3 /*break*/, 6];
|
|
1185
|
-
case 4: return [4 /*yield*/, s.save(modelInstanceCreator(Setting, {
|
|
1186
|
-
key: SETTING_SCHEMA_VERSION,
|
|
1187
|
-
value: JSON.stringify(version),
|
|
1188
|
-
}))];
|
|
1189
|
-
case 5:
|
|
1190
|
-
_b.sent();
|
|
1191
|
-
_b.label = 6;
|
|
1192
|
-
case 6: return [2 /*return*/];
|
|
1193
|
-
}
|
|
1194
|
-
});
|
|
1195
|
-
}); })];
|
|
1196
|
-
case 1:
|
|
1197
|
-
_a.sent();
|
|
1198
|
-
return [2 /*return*/];
|
|
911
|
+
async function checkSchemaVersion(storage, version) {
|
|
912
|
+
const Setting = dataStoreClasses.Setting;
|
|
913
|
+
const modelDefinition = schema.namespaces[DATASTORE].models.Setting;
|
|
914
|
+
await storage.runExclusive(async (s) => {
|
|
915
|
+
const [schemaVersionSetting] = await s.query(Setting, ModelPredicateCreator.createFromAST(modelDefinition, {
|
|
916
|
+
and: { key: { eq: SETTING_SCHEMA_VERSION } },
|
|
917
|
+
}), { page: 0, limit: 1 });
|
|
918
|
+
if (schemaVersionSetting !== undefined &&
|
|
919
|
+
schemaVersionSetting.value !== undefined) {
|
|
920
|
+
const storedValue = JSON.parse(schemaVersionSetting.value);
|
|
921
|
+
if (storedValue !== version) {
|
|
922
|
+
await s.clear(false);
|
|
1199
923
|
}
|
|
1200
|
-
}
|
|
924
|
+
}
|
|
925
|
+
else {
|
|
926
|
+
await s.save(modelInstanceCreator(Setting, {
|
|
927
|
+
key: SETTING_SCHEMA_VERSION,
|
|
928
|
+
value: JSON.stringify(version),
|
|
929
|
+
}));
|
|
930
|
+
}
|
|
1201
931
|
});
|
|
1202
932
|
}
|
|
1203
|
-
|
|
933
|
+
let syncSubscription;
|
|
1204
934
|
function getNamespace() {
|
|
1205
|
-
|
|
935
|
+
const namespace = {
|
|
1206
936
|
name: DATASTORE,
|
|
1207
937
|
relationships: {},
|
|
1208
938
|
enums: {},
|
|
@@ -1247,9 +977,8 @@ var DataStoreState;
|
|
|
1247
977
|
})(DataStoreState || (DataStoreState = {}));
|
|
1248
978
|
// TODO: How can we get rid of the non-null assertions?
|
|
1249
979
|
// https://github.com/aws-amplify/amplify-js/pull/10477/files#r1007363485
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
var _this = this;
|
|
980
|
+
class DataStore {
|
|
981
|
+
constructor() {
|
|
1253
982
|
// reference to configured category instances. Used for preserving SSR context
|
|
1254
983
|
this.InternalAPI = InternalAPI;
|
|
1255
984
|
this.Cache = Cache;
|
|
@@ -1311,419 +1040,322 @@ var DataStore = /** @class */ (function () {
|
|
|
1311
1040
|
* 3. If `this.amplifyConfig.aws_appsync_graphqlEndpoint` contains a URL,
|
|
1312
1041
|
* attaches a sync engine, starts it, and subscribes.
|
|
1313
1042
|
*/
|
|
1314
|
-
this.start =
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
return [4 /*yield*/, this.processSyncExpressions()];
|
|
1350
|
-
case 6:
|
|
1351
|
-
_a.syncPredicates = _b.sent();
|
|
1352
|
-
this.sync = new SyncEngine(schema, namespaceResolver, syncClasses, userClasses, this.storage, modelInstanceCreator, this.conflictHandler, this.errorHandler, this.syncPredicates, this.amplifyConfig, this.authModeStrategy, this.amplifyContext, this.connectivityMonitor);
|
|
1353
|
-
fullSyncIntervalInMilliseconds = this.fullSyncInterval * 1000 * 60;
|
|
1354
|
-
syncSubscription = this.sync
|
|
1355
|
-
.start({ fullSyncInterval: fullSyncIntervalInMilliseconds })
|
|
1356
|
-
.subscribe({
|
|
1357
|
-
next: function (_a) {
|
|
1358
|
-
var type = _a.type, data = _a.data;
|
|
1359
|
-
// In the Browser, we can begin returning data once subscriptions are in place.
|
|
1360
|
-
var readyType = ControlMessage.SYNC_ENGINE_STORAGE_SUBSCRIBED;
|
|
1361
|
-
if (type === readyType) {
|
|
1362
|
-
_this.initResolve();
|
|
1363
|
-
}
|
|
1364
|
-
Hub.dispatch('datastore', {
|
|
1365
|
-
event: type,
|
|
1366
|
-
data: data,
|
|
1367
|
-
});
|
|
1368
|
-
},
|
|
1369
|
-
error: function (err) {
|
|
1370
|
-
logger.warn('Sync error', err);
|
|
1371
|
-
_this.initReject();
|
|
1372
|
-
},
|
|
1373
|
-
});
|
|
1374
|
-
return [3 /*break*/, 8];
|
|
1375
|
-
case 7:
|
|
1376
|
-
logger.warn("Data won't be synchronized. No GraphQL endpoint configured. Did you forget `Amplify.configure(awsconfig)`?", {
|
|
1377
|
-
config: this.amplifyConfig,
|
|
1378
|
-
});
|
|
1379
|
-
this.initResolve();
|
|
1380
|
-
_b.label = 8;
|
|
1381
|
-
case 8: return [4 /*yield*/, this.initialized];
|
|
1382
|
-
case 9:
|
|
1383
|
-
_b.sent();
|
|
1384
|
-
this.state = DataStoreState.Running;
|
|
1385
|
-
return [2 /*return*/];
|
|
1386
|
-
}
|
|
1387
|
-
});
|
|
1388
|
-
}); }, 'datastore start')
|
|
1389
|
-
.catch(this.handleAddProcError('DataStore.start()'))];
|
|
1390
|
-
});
|
|
1391
|
-
}); };
|
|
1392
|
-
this.query = function (modelConstructor, identifierOrCriteria, paginationProducer) { return __awaiter(_this, void 0, void 0, function () {
|
|
1393
|
-
var _this = this;
|
|
1394
|
-
return __generator(this, function (_a) {
|
|
1395
|
-
return [2 /*return*/, this.runningProcesses
|
|
1396
|
-
.add(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
1397
|
-
var result, msg, modelDefinition, pagination, keyFields, msg, predicate, predicate, seedPredicate, predicate, returnOne;
|
|
1398
|
-
var _a;
|
|
1399
|
-
var _b;
|
|
1400
|
-
return __generator(this, function (_c) {
|
|
1401
|
-
switch (_c.label) {
|
|
1402
|
-
case 0: return [4 /*yield*/, this.start()];
|
|
1403
|
-
case 1:
|
|
1404
|
-
_c.sent();
|
|
1405
|
-
if (!this.storage) {
|
|
1406
|
-
throw new Error('No storage to query');
|
|
1407
|
-
}
|
|
1408
|
-
//#region Input validation
|
|
1409
|
-
if (!isValidModelConstructor(modelConstructor)) {
|
|
1410
|
-
msg = 'Constructor is not for a valid model';
|
|
1411
|
-
logger.error(msg, { modelConstructor: modelConstructor });
|
|
1412
|
-
throw new Error(msg);
|
|
1413
|
-
}
|
|
1414
|
-
if (typeof identifierOrCriteria === 'string') {
|
|
1415
|
-
if (paginationProducer !== undefined) {
|
|
1416
|
-
logger.warn('Pagination is ignored when querying by id');
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
1419
|
-
modelDefinition = getModelDefinition(modelConstructor);
|
|
1420
|
-
if (!modelDefinition) {
|
|
1421
|
-
throw new Error('Invalid model definition provided!');
|
|
1422
|
-
}
|
|
1423
|
-
pagination = this.processPagination(modelDefinition, paginationProducer);
|
|
1424
|
-
keyFields = extractPrimaryKeyFieldNames(modelDefinition);
|
|
1425
|
-
if (!isQueryOne(identifierOrCriteria)) return [3 /*break*/, 3];
|
|
1426
|
-
if (keyFields.length > 1) {
|
|
1427
|
-
msg = errorMessages.queryByPkWithCompositeKeyPresent;
|
|
1428
|
-
logger.error(msg, { keyFields: keyFields });
|
|
1429
|
-
throw new Error(msg);
|
|
1430
|
-
}
|
|
1431
|
-
predicate = ModelPredicateCreator.createFromFlatEqualities(modelDefinition, (_a = {}, _a[keyFields[0]] = identifierOrCriteria, _a));
|
|
1432
|
-
return [4 /*yield*/, this.storage.query(modelConstructor, predicate, pagination)];
|
|
1433
|
-
case 2:
|
|
1434
|
-
result = _c.sent();
|
|
1435
|
-
return [3 /*break*/, 9];
|
|
1436
|
-
case 3:
|
|
1437
|
-
if (!isIdentifierObject(identifierOrCriteria, modelDefinition)) return [3 /*break*/, 5];
|
|
1438
|
-
predicate = ModelPredicateCreator.createForPk(modelDefinition, identifierOrCriteria);
|
|
1439
|
-
return [4 /*yield*/, this.storage.query(modelConstructor, predicate, pagination)];
|
|
1440
|
-
case 4:
|
|
1441
|
-
result = _c.sent();
|
|
1442
|
-
return [3 /*break*/, 9];
|
|
1443
|
-
case 5:
|
|
1444
|
-
if (!(!identifierOrCriteria ||
|
|
1445
|
-
isPredicatesAll(identifierOrCriteria))) return [3 /*break*/, 7];
|
|
1446
|
-
return [4 /*yield*/, ((_b = this.storage) === null || _b === void 0 ? void 0 : _b.query(modelConstructor, undefined, pagination))];
|
|
1447
|
-
case 6:
|
|
1448
|
-
result = _c.sent();
|
|
1449
|
-
return [3 /*break*/, 9];
|
|
1450
|
-
case 7:
|
|
1451
|
-
seedPredicate = recursivePredicateFor({
|
|
1452
|
-
builder: modelConstructor,
|
|
1453
|
-
schema: modelDefinition,
|
|
1454
|
-
pkField: extractPrimaryKeyFieldNames(modelDefinition),
|
|
1455
|
-
});
|
|
1456
|
-
predicate = internals(identifierOrCriteria(seedPredicate));
|
|
1457
|
-
return [4 /*yield*/, predicate.fetch(this.storage)];
|
|
1458
|
-
case 8:
|
|
1459
|
-
result = (_c.sent());
|
|
1460
|
-
result = inMemoryPagination(result, pagination);
|
|
1461
|
-
_c.label = 9;
|
|
1462
|
-
case 9:
|
|
1463
|
-
returnOne = isQueryOne(identifierOrCriteria) ||
|
|
1464
|
-
isIdentifierObject(identifierOrCriteria, modelDefinition);
|
|
1465
|
-
return [2 /*return*/, attached(returnOne ? result[0] : result, ModelAttachment.DataStore)];
|
|
1043
|
+
this.start = async () => {
|
|
1044
|
+
return this.runningProcesses
|
|
1045
|
+
.add(async () => {
|
|
1046
|
+
this.state = DataStoreState.Starting;
|
|
1047
|
+
if (this.initialized === undefined) {
|
|
1048
|
+
logger.debug('Starting DataStore');
|
|
1049
|
+
this.initialized = new Promise((res, rej) => {
|
|
1050
|
+
this.initResolve = res;
|
|
1051
|
+
this.initReject = rej;
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
1054
|
+
else {
|
|
1055
|
+
await this.initialized;
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
1058
|
+
this.storage = new Storage(schema, namespaceResolver, getModelConstructorByModelName, modelInstanceCreator, this.storageAdapter, this.sessionId);
|
|
1059
|
+
await this.storage.init();
|
|
1060
|
+
checkSchemaInitialized();
|
|
1061
|
+
await checkSchemaVersion(this.storage, schema.version);
|
|
1062
|
+
const { aws_appsync_graphqlEndpoint } = this.amplifyConfig;
|
|
1063
|
+
if (aws_appsync_graphqlEndpoint) {
|
|
1064
|
+
logger.debug('GraphQL endpoint available', aws_appsync_graphqlEndpoint);
|
|
1065
|
+
this.syncPredicates = await this.processSyncExpressions();
|
|
1066
|
+
this.sync = new SyncEngine(schema, namespaceResolver, syncClasses, userClasses, this.storage, modelInstanceCreator, this.conflictHandler, this.errorHandler, this.syncPredicates, this.amplifyConfig, this.authModeStrategy, this.amplifyContext, this.connectivityMonitor);
|
|
1067
|
+
const fullSyncIntervalInMilliseconds = this.fullSyncInterval * 1000 * 60; // fullSyncInterval from param is in minutes
|
|
1068
|
+
syncSubscription = this.sync
|
|
1069
|
+
.start({ fullSyncInterval: fullSyncIntervalInMilliseconds })
|
|
1070
|
+
.subscribe({
|
|
1071
|
+
next: ({ type, data }) => {
|
|
1072
|
+
// In the Browser, we can begin returning data once subscriptions are in place.
|
|
1073
|
+
const readyType = isBrowser()
|
|
1074
|
+
? ControlMessage.SYNC_ENGINE_STORAGE_SUBSCRIBED
|
|
1075
|
+
: ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY;
|
|
1076
|
+
if (type === readyType) {
|
|
1077
|
+
this.initResolve();
|
|
1466
1078
|
}
|
|
1079
|
+
Hub.dispatch('datastore', {
|
|
1080
|
+
event: type,
|
|
1081
|
+
data,
|
|
1082
|
+
});
|
|
1083
|
+
},
|
|
1084
|
+
error: err => {
|
|
1085
|
+
logger.warn('Sync error', err);
|
|
1086
|
+
this.initReject();
|
|
1087
|
+
},
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
else {
|
|
1091
|
+
logger.warn("Data won't be synchronized. No GraphQL endpoint configured. Did you forget `Amplify.configure(awsconfig)`?", {
|
|
1092
|
+
config: this.amplifyConfig,
|
|
1093
|
+
});
|
|
1094
|
+
this.initResolve();
|
|
1095
|
+
}
|
|
1096
|
+
await this.initialized;
|
|
1097
|
+
this.state = DataStoreState.Running;
|
|
1098
|
+
}, 'datastore start')
|
|
1099
|
+
.catch(this.handleAddProcError('DataStore.start()'));
|
|
1100
|
+
};
|
|
1101
|
+
this.query = async (modelConstructor, identifierOrCriteria, paginationProducer) => {
|
|
1102
|
+
return this.runningProcesses
|
|
1103
|
+
.add(async () => {
|
|
1104
|
+
await this.start();
|
|
1105
|
+
let result;
|
|
1106
|
+
if (!this.storage) {
|
|
1107
|
+
throw new Error('No storage to query');
|
|
1108
|
+
}
|
|
1109
|
+
//#region Input validation
|
|
1110
|
+
if (!isValidModelConstructor(modelConstructor)) {
|
|
1111
|
+
const msg = 'Constructor is not for a valid model';
|
|
1112
|
+
logger.error(msg, { modelConstructor });
|
|
1113
|
+
throw new Error(msg);
|
|
1114
|
+
}
|
|
1115
|
+
if (typeof identifierOrCriteria === 'string') {
|
|
1116
|
+
if (paginationProducer !== undefined) {
|
|
1117
|
+
logger.warn('Pagination is ignored when querying by id');
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
const modelDefinition = getModelDefinition(modelConstructor);
|
|
1121
|
+
if (!modelDefinition) {
|
|
1122
|
+
throw new Error('Invalid model definition provided!');
|
|
1123
|
+
}
|
|
1124
|
+
const pagination = this.processPagination(modelDefinition, paginationProducer);
|
|
1125
|
+
const keyFields = extractPrimaryKeyFieldNames(modelDefinition);
|
|
1126
|
+
if (isQueryOne(identifierOrCriteria)) {
|
|
1127
|
+
if (keyFields.length > 1) {
|
|
1128
|
+
const msg = errorMessages.queryByPkWithCompositeKeyPresent;
|
|
1129
|
+
logger.error(msg, { keyFields });
|
|
1130
|
+
throw new Error(msg);
|
|
1131
|
+
}
|
|
1132
|
+
const predicate = ModelPredicateCreator.createFromFlatEqualities(modelDefinition, { [keyFields[0]]: identifierOrCriteria });
|
|
1133
|
+
result = await this.storage.query(modelConstructor, predicate, pagination);
|
|
1134
|
+
}
|
|
1135
|
+
else {
|
|
1136
|
+
// Object is being queried using object literal syntax
|
|
1137
|
+
if (isIdentifierObject(identifierOrCriteria, modelDefinition)) {
|
|
1138
|
+
const predicate = ModelPredicateCreator.createForPk(modelDefinition, identifierOrCriteria);
|
|
1139
|
+
result = await this.storage.query(modelConstructor, predicate, pagination);
|
|
1140
|
+
}
|
|
1141
|
+
else if (!identifierOrCriteria ||
|
|
1142
|
+
isPredicatesAll(identifierOrCriteria)) {
|
|
1143
|
+
result = await this.storage?.query(modelConstructor, undefined, pagination);
|
|
1144
|
+
}
|
|
1145
|
+
else {
|
|
1146
|
+
const seedPredicate = recursivePredicateFor({
|
|
1147
|
+
builder: modelConstructor,
|
|
1148
|
+
schema: modelDefinition,
|
|
1149
|
+
pkField: extractPrimaryKeyFieldNames(modelDefinition),
|
|
1467
1150
|
});
|
|
1468
|
-
|
|
1469
|
-
.
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
"Data integrity error. You tried to save a ".concat(modelDefinition.name, " (").concat(JSON.stringify(model), ")"),
|
|
1531
|
-
"but the instance assigned to the \"".concat(relationship.field, "\" property"),
|
|
1532
|
-
"does not exist in the local database. If you're trying to create the related",
|
|
1533
|
-
"\"".concat((_b = relationship.remoteDefinition) === null || _b === void 0 ? void 0 : _b.name, "\", you must save it independently first."),
|
|
1534
|
-
].join(' '));
|
|
1535
|
-
}
|
|
1536
|
-
_c.label = 4;
|
|
1537
|
-
case 4:
|
|
1538
|
-
nonHasManyRelationships_1_1 = nonHasManyRelationships_1.next();
|
|
1539
|
-
return [3 /*break*/, 2];
|
|
1540
|
-
case 5: return [3 /*break*/, 8];
|
|
1541
|
-
case 6:
|
|
1542
|
-
e_7_1 = _c.sent();
|
|
1543
|
-
e_7 = { error: e_7_1 };
|
|
1544
|
-
return [3 /*break*/, 8];
|
|
1545
|
-
case 7:
|
|
1546
|
-
try {
|
|
1547
|
-
if (nonHasManyRelationships_1_1 && !nonHasManyRelationships_1_1.done && (_a = nonHasManyRelationships_1.return)) _a.call(nonHasManyRelationships_1);
|
|
1548
|
-
}
|
|
1549
|
-
finally { if (e_7) throw e_7.error; }
|
|
1550
|
-
return [7 /*endfinally*/];
|
|
1551
|
-
case 8: return [2 /*return*/];
|
|
1552
|
-
}
|
|
1553
|
-
});
|
|
1554
|
-
}); })];
|
|
1555
|
-
case 2:
|
|
1556
|
-
_b.sent();
|
|
1557
|
-
producedCondition = condition
|
|
1558
|
-
? internals(condition(predicateFor(modelMeta))).toStoragePredicate()
|
|
1559
|
-
: undefined;
|
|
1560
|
-
return [4 /*yield*/, this.storage.runExclusive(function (s) { return __awaiter(_this, void 0, void 0, function () {
|
|
1561
|
-
var saved;
|
|
1562
|
-
return __generator(this, function (_a) {
|
|
1563
|
-
switch (_a.label) {
|
|
1564
|
-
case 0: return [4 /*yield*/, s.save(model, producedCondition, undefined, patchesTuple)];
|
|
1565
|
-
case 1:
|
|
1566
|
-
saved = _a.sent();
|
|
1567
|
-
return [2 /*return*/, s.query(modelConstructor, ModelPredicateCreator.createForPk(modelDefinition, model))];
|
|
1568
|
-
}
|
|
1569
|
-
});
|
|
1570
|
-
}); })];
|
|
1571
|
-
case 3:
|
|
1572
|
-
_a = __read.apply(void 0, [_b.sent(), 1]), savedModel = _a[0];
|
|
1573
|
-
return [2 /*return*/, attached(savedModel, ModelAttachment.DataStore)];
|
|
1151
|
+
const predicate = internals(identifierOrCriteria(seedPredicate));
|
|
1152
|
+
result = (await predicate.fetch(this.storage));
|
|
1153
|
+
result = inMemoryPagination(result, pagination);
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
//#endregion
|
|
1157
|
+
const returnOne = isQueryOne(identifierOrCriteria) ||
|
|
1158
|
+
isIdentifierObject(identifierOrCriteria, modelDefinition);
|
|
1159
|
+
return attached(returnOne ? result[0] : result, ModelAttachment.DataStore);
|
|
1160
|
+
}, 'datastore query')
|
|
1161
|
+
.catch(this.handleAddProcError('DataStore.query()'));
|
|
1162
|
+
};
|
|
1163
|
+
this.save = async (model, condition) => {
|
|
1164
|
+
return this.runningProcesses
|
|
1165
|
+
.add(async () => {
|
|
1166
|
+
await this.start();
|
|
1167
|
+
if (!this.storage) {
|
|
1168
|
+
throw new Error('No storage to save to');
|
|
1169
|
+
}
|
|
1170
|
+
// Immer patches for constructing a correct update mutation input
|
|
1171
|
+
// Allows us to only include changed fields for updates
|
|
1172
|
+
const updatedPatchesTuple = modelPatchesMap.get(model);
|
|
1173
|
+
// Immer patches for initial object construction. These are used if
|
|
1174
|
+
// there are no `update` patches under the assumption we're performing
|
|
1175
|
+
// a CREATE and wish to send only explicitly specified fields to the cloud.
|
|
1176
|
+
const initPatchesTuple = initPatches.has(model)
|
|
1177
|
+
? [initPatches.get(model), {}]
|
|
1178
|
+
: undefined;
|
|
1179
|
+
// favor update patches over init/create patches, because init patches
|
|
1180
|
+
// are ALWAYS present, whereas update patches are only present if copyOf
|
|
1181
|
+
// was used to create the instance.
|
|
1182
|
+
const patchesTuple = updatedPatchesTuple || initPatchesTuple;
|
|
1183
|
+
const modelConstructor = model ? model.constructor : undefined;
|
|
1184
|
+
if (!isValidModelConstructor(modelConstructor)) {
|
|
1185
|
+
const msg = 'Object is not an instance of a valid model';
|
|
1186
|
+
logger.error(msg, { model });
|
|
1187
|
+
throw new Error(msg);
|
|
1188
|
+
}
|
|
1189
|
+
const modelDefinition = getModelDefinition(modelConstructor);
|
|
1190
|
+
if (!modelDefinition) {
|
|
1191
|
+
throw new Error('Model Definition could not be found for model');
|
|
1192
|
+
}
|
|
1193
|
+
const modelMeta = {
|
|
1194
|
+
builder: modelConstructor,
|
|
1195
|
+
schema: modelDefinition,
|
|
1196
|
+
pkField: extractPrimaryKeyFieldNames(modelDefinition),
|
|
1197
|
+
};
|
|
1198
|
+
await this.storage.runExclusive(async (s) => {
|
|
1199
|
+
// no enforcement for HAS_MANY on save, because the ~related~ entities
|
|
1200
|
+
// hold the FK in that case.
|
|
1201
|
+
const nonHasManyRelationships = ModelRelationship.allFrom(modelMeta).filter(r => r.type === 'BELONGS_TO');
|
|
1202
|
+
for (const relationship of nonHasManyRelationships) {
|
|
1203
|
+
const queryObject = relationship.createRemoteQueryObject(model);
|
|
1204
|
+
if (queryObject !== null) {
|
|
1205
|
+
const related = await s.query(relationship.remoteModelConstructor, ModelPredicateCreator.createFromFlatEqualities(relationship.remoteDefinition, queryObject));
|
|
1206
|
+
if (related.length === 0) {
|
|
1207
|
+
throw new Error([
|
|
1208
|
+
`Data integrity error. You tried to save a ${modelDefinition.name} (${JSON.stringify(model)})`,
|
|
1209
|
+
`but the instance assigned to the "${relationship.field}" property`,
|
|
1210
|
+
`does not exist in the local database. If you're trying to create the related`,
|
|
1211
|
+
`"${relationship.remoteDefinition?.name}", you must save it independently first.`,
|
|
1212
|
+
].join(' '));
|
|
1574
1213
|
}
|
|
1575
|
-
}
|
|
1576
|
-
}
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
});
|
|
1217
|
+
const producedCondition = condition
|
|
1218
|
+
? internals(condition(predicateFor(modelMeta))).toStoragePredicate()
|
|
1219
|
+
: undefined;
|
|
1220
|
+
const [savedModel] = await this.storage.runExclusive(async (s) => {
|
|
1221
|
+
const saved = await s.save(model, producedCondition, undefined, patchesTuple);
|
|
1222
|
+
return s.query(modelConstructor, ModelPredicateCreator.createForPk(modelDefinition, model));
|
|
1223
|
+
});
|
|
1224
|
+
return attached(savedModel, ModelAttachment.DataStore);
|
|
1225
|
+
}, 'datastore save')
|
|
1226
|
+
.catch(this.handleAddProcError('DataStore.save()'));
|
|
1227
|
+
};
|
|
1228
|
+
this.setConflictHandler = (config) => {
|
|
1229
|
+
const { DataStore: configDataStore } = config;
|
|
1230
|
+
const conflictHandlerIsDefault = () => this.conflictHandler === defaultConflictHandler;
|
|
1585
1231
|
if (configDataStore && configDataStore.conflictHandler) {
|
|
1586
1232
|
return configDataStore.conflictHandler;
|
|
1587
1233
|
}
|
|
1588
1234
|
if (conflictHandlerIsDefault() && config.conflictHandler) {
|
|
1589
1235
|
return config.conflictHandler;
|
|
1590
1236
|
}
|
|
1591
|
-
return
|
|
1237
|
+
return this.conflictHandler || defaultConflictHandler;
|
|
1592
1238
|
};
|
|
1593
|
-
this.setErrorHandler =
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
return _this.errorHandler === defaultErrorHandler;
|
|
1597
|
-
};
|
|
1239
|
+
this.setErrorHandler = (config) => {
|
|
1240
|
+
const { DataStore: configDataStore } = config;
|
|
1241
|
+
const errorHandlerIsDefault = () => this.errorHandler === defaultErrorHandler;
|
|
1598
1242
|
if (configDataStore && configDataStore.errorHandler) {
|
|
1599
1243
|
return configDataStore.errorHandler;
|
|
1600
1244
|
}
|
|
1601
1245
|
if (errorHandlerIsDefault() && config.errorHandler) {
|
|
1602
1246
|
return config.errorHandler;
|
|
1603
1247
|
}
|
|
1604
|
-
return
|
|
1248
|
+
return this.errorHandler || defaultErrorHandler;
|
|
1605
1249
|
};
|
|
1606
|
-
this.delete =
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
case 4:
|
|
1699
|
-
_b = __read.apply(void 0, [_e.sent(), 1]), _c = __read(_b[0], 1), deleted = _c[0];
|
|
1700
|
-
return [2 /*return*/, attached(deleted, ModelAttachment.DataStore)];
|
|
1701
|
-
}
|
|
1702
|
-
});
|
|
1703
|
-
}); }, 'datastore delete')
|
|
1704
|
-
.catch(this.handleAddProcError('DataStore.delete()'))];
|
|
1705
|
-
});
|
|
1706
|
-
}); };
|
|
1707
|
-
this.observe = function (modelOrConstructor, identifierOrCriteria) {
|
|
1708
|
-
var executivePredicate;
|
|
1709
|
-
var modelConstructor = modelOrConstructor && isValidModelConstructor(modelOrConstructor)
|
|
1250
|
+
this.delete = async (modelOrConstructor, identifierOrCriteria) => {
|
|
1251
|
+
return this.runningProcesses
|
|
1252
|
+
.add(async () => {
|
|
1253
|
+
await this.start();
|
|
1254
|
+
if (!this.storage) {
|
|
1255
|
+
throw new Error('No storage to delete from');
|
|
1256
|
+
}
|
|
1257
|
+
let condition;
|
|
1258
|
+
if (!modelOrConstructor) {
|
|
1259
|
+
const msg = 'Model or Model Constructor required';
|
|
1260
|
+
logger.error(msg, { modelOrConstructor });
|
|
1261
|
+
throw new Error(msg);
|
|
1262
|
+
}
|
|
1263
|
+
if (isValidModelConstructor(modelOrConstructor)) {
|
|
1264
|
+
const modelConstructor = modelOrConstructor;
|
|
1265
|
+
if (!identifierOrCriteria) {
|
|
1266
|
+
const msg = 'Id to delete or criteria required. Do you want to delete all? Pass Predicates.ALL';
|
|
1267
|
+
logger.error(msg, { identifierOrCriteria });
|
|
1268
|
+
throw new Error(msg);
|
|
1269
|
+
}
|
|
1270
|
+
const modelDefinition = getModelDefinition(modelConstructor);
|
|
1271
|
+
if (!modelDefinition) {
|
|
1272
|
+
throw new Error('Could not find model definition for modelConstructor.');
|
|
1273
|
+
}
|
|
1274
|
+
if (typeof identifierOrCriteria === 'string') {
|
|
1275
|
+
const keyFields = extractPrimaryKeyFieldNames(modelDefinition);
|
|
1276
|
+
if (keyFields.length > 1) {
|
|
1277
|
+
const msg = errorMessages.deleteByPkWithCompositeKeyPresent;
|
|
1278
|
+
logger.error(msg, { keyFields });
|
|
1279
|
+
throw new Error(msg);
|
|
1280
|
+
}
|
|
1281
|
+
condition = ModelPredicateCreator.createFromFlatEqualities(modelDefinition, { [keyFields[0]]: identifierOrCriteria });
|
|
1282
|
+
}
|
|
1283
|
+
else {
|
|
1284
|
+
if (isIdentifierObject(identifierOrCriteria, modelDefinition)) {
|
|
1285
|
+
condition = ModelPredicateCreator.createForPk(modelDefinition, identifierOrCriteria);
|
|
1286
|
+
}
|
|
1287
|
+
else {
|
|
1288
|
+
condition = internals(identifierOrCriteria(predicateFor({
|
|
1289
|
+
builder: modelConstructor,
|
|
1290
|
+
schema: modelDefinition,
|
|
1291
|
+
pkField: extractPrimaryKeyFieldNames(modelDefinition),
|
|
1292
|
+
}))).toStoragePredicate();
|
|
1293
|
+
}
|
|
1294
|
+
if (!condition ||
|
|
1295
|
+
!ModelPredicateCreator.isValidPredicate(condition)) {
|
|
1296
|
+
const msg = 'Criteria required. Do you want to delete all? Pass Predicates.ALL';
|
|
1297
|
+
logger.error(msg, { condition });
|
|
1298
|
+
throw new Error(msg);
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
const [deleted] = await this.storage.delete(modelConstructor, condition);
|
|
1302
|
+
return attached(deleted, ModelAttachment.DataStore);
|
|
1303
|
+
}
|
|
1304
|
+
else {
|
|
1305
|
+
const model = modelOrConstructor;
|
|
1306
|
+
const modelConstructor = Object.getPrototypeOf(model || {})
|
|
1307
|
+
.constructor;
|
|
1308
|
+
if (!isValidModelConstructor(modelConstructor)) {
|
|
1309
|
+
const msg = 'Object is not an instance of a valid model';
|
|
1310
|
+
logger.error(msg, { model });
|
|
1311
|
+
throw new Error(msg);
|
|
1312
|
+
}
|
|
1313
|
+
const modelDefinition = getModelDefinition(modelConstructor);
|
|
1314
|
+
if (!modelDefinition) {
|
|
1315
|
+
throw new Error('Could not find model definition for modelConstructor.');
|
|
1316
|
+
}
|
|
1317
|
+
const pkPredicate = ModelPredicateCreator.createForPk(modelDefinition, model);
|
|
1318
|
+
if (identifierOrCriteria) {
|
|
1319
|
+
if (typeof identifierOrCriteria !== 'function') {
|
|
1320
|
+
const msg = 'Invalid criteria';
|
|
1321
|
+
logger.error(msg, { identifierOrCriteria });
|
|
1322
|
+
throw new Error(msg);
|
|
1323
|
+
}
|
|
1324
|
+
condition = internals(identifierOrCriteria(predicateFor({
|
|
1325
|
+
builder: modelConstructor,
|
|
1326
|
+
schema: modelDefinition,
|
|
1327
|
+
pkField: extractPrimaryKeyFieldNames(modelDefinition),
|
|
1328
|
+
}))).toStoragePredicate();
|
|
1329
|
+
}
|
|
1330
|
+
else {
|
|
1331
|
+
condition = pkPredicate;
|
|
1332
|
+
}
|
|
1333
|
+
const [[deleted]] = await this.storage.delete(model, condition);
|
|
1334
|
+
return attached(deleted, ModelAttachment.DataStore);
|
|
1335
|
+
}
|
|
1336
|
+
}, 'datastore delete')
|
|
1337
|
+
.catch(this.handleAddProcError('DataStore.delete()'));
|
|
1338
|
+
};
|
|
1339
|
+
this.observe = (modelOrConstructor, identifierOrCriteria) => {
|
|
1340
|
+
let executivePredicate;
|
|
1341
|
+
const modelConstructor = modelOrConstructor && isValidModelConstructor(modelOrConstructor)
|
|
1710
1342
|
? modelOrConstructor
|
|
1711
1343
|
: undefined;
|
|
1712
1344
|
if (modelOrConstructor && modelConstructor === undefined) {
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
if (isValidModelConstructor(
|
|
1345
|
+
const model = modelOrConstructor;
|
|
1346
|
+
const modelConstructor = model && Object.getPrototypeOf(model).constructor;
|
|
1347
|
+
if (isValidModelConstructor(modelConstructor)) {
|
|
1716
1348
|
if (identifierOrCriteria) {
|
|
1717
1349
|
logger.warn('idOrCriteria is ignored when using a model instance', {
|
|
1718
|
-
model
|
|
1719
|
-
identifierOrCriteria
|
|
1350
|
+
model,
|
|
1351
|
+
identifierOrCriteria,
|
|
1720
1352
|
});
|
|
1721
1353
|
}
|
|
1722
|
-
return
|
|
1354
|
+
return this.observe(modelConstructor, model.id);
|
|
1723
1355
|
}
|
|
1724
1356
|
else {
|
|
1725
|
-
|
|
1726
|
-
logger.error(msg, { model
|
|
1357
|
+
const msg = 'The model is not an instance of a PersistentModelConstructor';
|
|
1358
|
+
logger.error(msg, { model });
|
|
1727
1359
|
throw new Error(msg);
|
|
1728
1360
|
}
|
|
1729
1361
|
}
|
|
@@ -1731,110 +1363,86 @@ var DataStore = /** @class */ (function () {
|
|
|
1731
1363
|
if (identifierOrCriteria &&
|
|
1732
1364
|
modelConstructor &&
|
|
1733
1365
|
isIdentifierObject(identifierOrCriteria, getModelDefinition(modelConstructor))) {
|
|
1734
|
-
|
|
1366
|
+
const msg = errorMessages.observeWithObjectLiteral;
|
|
1735
1367
|
logger.error(msg, { objectLiteral: identifierOrCriteria });
|
|
1736
1368
|
throw new Error(msg);
|
|
1737
1369
|
}
|
|
1738
1370
|
if (identifierOrCriteria !== undefined && modelConstructor === undefined) {
|
|
1739
|
-
|
|
1371
|
+
const msg = 'Cannot provide criteria without a modelConstructor';
|
|
1740
1372
|
logger.error(msg, identifierOrCriteria);
|
|
1741
1373
|
throw new Error(msg);
|
|
1742
1374
|
}
|
|
1743
1375
|
if (modelConstructor && !isValidModelConstructor(modelConstructor)) {
|
|
1744
|
-
|
|
1745
|
-
logger.error(msg, { modelConstructor
|
|
1376
|
+
const msg = 'Constructor is not for a valid model';
|
|
1377
|
+
logger.error(msg, { modelConstructor });
|
|
1746
1378
|
throw new Error(msg);
|
|
1747
1379
|
}
|
|
1748
1380
|
if (modelConstructor && typeof identifierOrCriteria === 'string') {
|
|
1749
|
-
|
|
1381
|
+
const buildIdPredicate = seed => seed.id.eq(identifierOrCriteria);
|
|
1750
1382
|
executivePredicate = internals(buildIdPredicate(buildSeedPredicate(modelConstructor)));
|
|
1751
1383
|
}
|
|
1752
1384
|
else if (modelConstructor && typeof identifierOrCriteria === 'function') {
|
|
1753
1385
|
executivePredicate = internals(identifierOrCriteria(buildSeedPredicate(modelConstructor)));
|
|
1754
1386
|
}
|
|
1755
|
-
return new Observable(
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
.add(
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
case 2:
|
|
1791
|
-
_a = !executivePredicate;
|
|
1792
|
-
if (_a) return [3 /*break*/, 4];
|
|
1793
|
-
return [4 /*yield*/, executivePredicate.matches(message.element)];
|
|
1794
|
-
case 3:
|
|
1795
|
-
_a = (_b.sent());
|
|
1796
|
-
_b.label = 4;
|
|
1797
|
-
case 4:
|
|
1798
|
-
if (_a) {
|
|
1799
|
-
observer.next(message);
|
|
1800
|
-
}
|
|
1801
|
-
return [2 /*return*/];
|
|
1802
|
-
}
|
|
1803
|
-
});
|
|
1804
|
-
}); }, 'datastore observe message handler');
|
|
1805
|
-
},
|
|
1806
|
-
error: function (err) { return observer.error(err); },
|
|
1807
|
-
complete: function () { return observer.complete(); },
|
|
1808
|
-
});
|
|
1809
|
-
return [2 /*return*/];
|
|
1810
|
-
}
|
|
1387
|
+
return new Observable(observer => {
|
|
1388
|
+
let source;
|
|
1389
|
+
this.runningProcesses
|
|
1390
|
+
.add(async () => {
|
|
1391
|
+
await this.start();
|
|
1392
|
+
// Filter the events returned by Storage according to namespace,
|
|
1393
|
+
// append original element data, and subscribe to the observable
|
|
1394
|
+
source = this.storage.observe(modelConstructor)
|
|
1395
|
+
.pipe(filter(({ model }) => namespaceResolver(model) === USER))
|
|
1396
|
+
.subscribe({
|
|
1397
|
+
next: item => this.runningProcesses.isOpen &&
|
|
1398
|
+
this.runningProcesses.add(async () => {
|
|
1399
|
+
// the `element` doesn't necessarily contain all item details or
|
|
1400
|
+
// have related records attached consistently with that of a query()
|
|
1401
|
+
// result item. for consistency, we attach them here.
|
|
1402
|
+
let message = item;
|
|
1403
|
+
// as long as we're not dealing with a DELETE, we need to fetch a fresh
|
|
1404
|
+
// item from storage to ensure it's fully populated.
|
|
1405
|
+
if (item.opType !== 'DELETE') {
|
|
1406
|
+
const modelDefinition = getModelDefinition(item.model);
|
|
1407
|
+
const keyFields = extractPrimaryKeyFieldNames(modelDefinition);
|
|
1408
|
+
const primaryKeysAndValues = extractPrimaryKeysAndValues(item.element, keyFields);
|
|
1409
|
+
const freshElement = await this.query(item.model, primaryKeysAndValues);
|
|
1410
|
+
message = {
|
|
1411
|
+
...message,
|
|
1412
|
+
element: freshElement,
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
1415
|
+
if (!executivePredicate ||
|
|
1416
|
+
(await executivePredicate.matches(message.element))) {
|
|
1417
|
+
observer.next(message);
|
|
1418
|
+
}
|
|
1419
|
+
}, 'datastore observe message handler'),
|
|
1420
|
+
error: err => observer.error(err),
|
|
1421
|
+
complete: () => observer.complete(),
|
|
1811
1422
|
});
|
|
1812
|
-
}
|
|
1813
|
-
.catch(
|
|
1814
|
-
.catch(
|
|
1423
|
+
}, 'datastore observe observable initialization')
|
|
1424
|
+
.catch(this.handleAddProcError('DataStore.observe()'))
|
|
1425
|
+
.catch(error => {
|
|
1815
1426
|
observer.error(error);
|
|
1816
1427
|
});
|
|
1817
1428
|
// better than no cleaner, but if the subscriber is handling the
|
|
1818
1429
|
// complete() message async and not registering with the context,
|
|
1819
1430
|
// this will still be problematic.
|
|
1820
|
-
return
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
return [2 /*return*/];
|
|
1826
|
-
});
|
|
1827
|
-
}); }, 'DataStore.observe() cleanup');
|
|
1431
|
+
return this.runningProcesses.addCleaner(async () => {
|
|
1432
|
+
if (source) {
|
|
1433
|
+
source.unsubscribe();
|
|
1434
|
+
}
|
|
1435
|
+
}, 'DataStore.observe() cleanup');
|
|
1828
1436
|
});
|
|
1829
1437
|
};
|
|
1830
|
-
this.observeQuery =
|
|
1831
|
-
return new Observable(
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1438
|
+
this.observeQuery = (model, criteria, options) => {
|
|
1439
|
+
return new Observable(observer => {
|
|
1440
|
+
const items = new Map();
|
|
1441
|
+
const itemsChanged = new Map();
|
|
1442
|
+
let deletedItemIds = [];
|
|
1443
|
+
let handle;
|
|
1836
1444
|
// let predicate: ModelPredicate<T> | undefined;
|
|
1837
|
-
|
|
1445
|
+
let executivePredicate;
|
|
1838
1446
|
/**
|
|
1839
1447
|
* As the name suggests, this geneates a snapshot in the form of
|
|
1840
1448
|
* `{items: T[], isSynced: boolean}`
|
|
@@ -1845,20 +1453,20 @@ var DataStore = /** @class */ (function () {
|
|
|
1845
1453
|
*
|
|
1846
1454
|
* Refer to `generateSnapshot` and `emitSnapshot` for more details.
|
|
1847
1455
|
*/
|
|
1848
|
-
|
|
1849
|
-
|
|
1456
|
+
const generateAndEmitSnapshot = () => {
|
|
1457
|
+
const snapshot = generateSnapshot();
|
|
1850
1458
|
emitSnapshot(snapshot);
|
|
1851
1459
|
};
|
|
1852
1460
|
// a mechanism to return data after X amount of seconds OR after the
|
|
1853
1461
|
// "limit" (itemsChanged >= this.syncPageSize) has been reached, whichever comes first
|
|
1854
|
-
|
|
1462
|
+
const limitTimerRace = new DeferredCallbackResolver({
|
|
1855
1463
|
callback: generateAndEmitSnapshot,
|
|
1856
1464
|
errorHandler: observer.error,
|
|
1857
1465
|
maxInterval: 2000,
|
|
1858
1466
|
});
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1467
|
+
const { sort } = options || {};
|
|
1468
|
+
const sortOptions = sort ? { sort } : undefined;
|
|
1469
|
+
const modelDefinition = getModelDefinition(model);
|
|
1862
1470
|
if (!modelDefinition) {
|
|
1863
1471
|
throw new Error('Could not find model definition.');
|
|
1864
1472
|
}
|
|
@@ -1868,94 +1476,66 @@ var DataStore = /** @class */ (function () {
|
|
|
1868
1476
|
else if (isPredicatesAll(criteria)) {
|
|
1869
1477
|
executivePredicate = undefined;
|
|
1870
1478
|
}
|
|
1871
|
-
|
|
1872
|
-
.add(
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
itemsChanged.set(idOrPk, element);
|
|
1932
|
-
}
|
|
1933
|
-
isSynced = (_c = (_b = this.sync) === null || _b === void 0 ? void 0 : _b.getModelSyncedStatus(model)) !== null && _c !== void 0 ? _c : false;
|
|
1934
|
-
limit = itemsChanged.size - deletedItemIds.length >=
|
|
1935
|
-
this.syncPageSize;
|
|
1936
|
-
if (limit || isSynced) {
|
|
1937
|
-
limitTimerRace.resolve();
|
|
1938
|
-
}
|
|
1939
|
-
// kicks off every subsequent race as results sync down
|
|
1940
|
-
limitTimerRace.start();
|
|
1941
|
-
return [2 /*return*/];
|
|
1942
|
-
}
|
|
1943
|
-
});
|
|
1944
|
-
}); }, 'handle observeQuery observed event');
|
|
1945
|
-
});
|
|
1946
|
-
// returns a set of initial/locally-available results
|
|
1947
|
-
generateAndEmitSnapshot();
|
|
1948
|
-
return [3 /*break*/, 3];
|
|
1949
|
-
case 2:
|
|
1950
|
-
err_1 = _a.sent();
|
|
1951
|
-
observer.error(err_1);
|
|
1952
|
-
return [3 /*break*/, 3];
|
|
1953
|
-
case 3: return [2 /*return*/];
|
|
1954
|
-
}
|
|
1955
|
-
});
|
|
1956
|
-
}); }, 'datastore observequery startup')
|
|
1957
|
-
.catch(_this.handleAddProcError('DataStore.observeQuery()'))
|
|
1958
|
-
.catch(function (error) {
|
|
1479
|
+
this.runningProcesses
|
|
1480
|
+
.add(async () => {
|
|
1481
|
+
try {
|
|
1482
|
+
// first, query and return any locally-available records
|
|
1483
|
+
(await this.query(model, criteria, sortOptions)).forEach(item => {
|
|
1484
|
+
const itemModelDefinition = getModelDefinition(model);
|
|
1485
|
+
const idOrPk = getIdentifierValue(itemModelDefinition, item);
|
|
1486
|
+
items.set(idOrPk, item);
|
|
1487
|
+
});
|
|
1488
|
+
// Observe the model and send a stream of updates (debounced).
|
|
1489
|
+
// We need to post-filter results instead of passing criteria through
|
|
1490
|
+
// to have visibility into items that move from in-set to out-of-set.
|
|
1491
|
+
// We need to explicitly remove those items from the existing snapshot.
|
|
1492
|
+
handle = this.observe(model).subscribe(({ element, model, opType }) => this.runningProcesses.isOpen &&
|
|
1493
|
+
this.runningProcesses.add(async () => {
|
|
1494
|
+
const itemModelDefinition = getModelDefinition(model);
|
|
1495
|
+
const idOrPk = getIdentifierValue(itemModelDefinition, element);
|
|
1496
|
+
if (executivePredicate &&
|
|
1497
|
+
!(await executivePredicate.matches(element))) {
|
|
1498
|
+
if (opType === 'UPDATE' &&
|
|
1499
|
+
(items.has(idOrPk) || itemsChanged.has(idOrPk))) {
|
|
1500
|
+
// tracking as a "deleted item" will include the item in
|
|
1501
|
+
// page limit calculations and ensure it is removed from the
|
|
1502
|
+
// final items collection, regardless of which collection(s)
|
|
1503
|
+
// it is currently in. (I mean, it could be in both, right!?)
|
|
1504
|
+
deletedItemIds.push(idOrPk);
|
|
1505
|
+
}
|
|
1506
|
+
else {
|
|
1507
|
+
// ignore updates for irrelevant/filtered items.
|
|
1508
|
+
return;
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
// Flag items which have been recently deleted
|
|
1512
|
+
// NOTE: Merging of separate operations to the same model instance is handled upstream
|
|
1513
|
+
// in the `mergePage` method within src/sync/merger.ts. The final state of a model instance
|
|
1514
|
+
// depends on the LATEST record (for a given id).
|
|
1515
|
+
if (opType === 'DELETE') {
|
|
1516
|
+
deletedItemIds.push(idOrPk);
|
|
1517
|
+
}
|
|
1518
|
+
else {
|
|
1519
|
+
itemsChanged.set(idOrPk, element);
|
|
1520
|
+
}
|
|
1521
|
+
const isSynced = this.sync?.getModelSyncedStatus(model) ?? false;
|
|
1522
|
+
const limit = itemsChanged.size - deletedItemIds.length >=
|
|
1523
|
+
this.syncPageSize;
|
|
1524
|
+
if (limit || isSynced) {
|
|
1525
|
+
limitTimerRace.resolve();
|
|
1526
|
+
}
|
|
1527
|
+
// kicks off every subsequent race as results sync down
|
|
1528
|
+
limitTimerRace.start();
|
|
1529
|
+
}, 'handle observeQuery observed event'));
|
|
1530
|
+
// returns a set of initial/locally-available results
|
|
1531
|
+
generateAndEmitSnapshot();
|
|
1532
|
+
}
|
|
1533
|
+
catch (err) {
|
|
1534
|
+
observer.error(err);
|
|
1535
|
+
}
|
|
1536
|
+
}, 'datastore observequery startup')
|
|
1537
|
+
.catch(this.handleAddProcError('DataStore.observeQuery()'))
|
|
1538
|
+
.catch(error => {
|
|
1959
1539
|
observer.error(error);
|
|
1960
1540
|
});
|
|
1961
1541
|
/**
|
|
@@ -1964,27 +1544,29 @@ var DataStore = /** @class */ (function () {
|
|
|
1964
1544
|
*
|
|
1965
1545
|
* SIDE EFFECT: The shared `items` collection is recreated.
|
|
1966
1546
|
*/
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1547
|
+
const generateSnapshot = () => {
|
|
1548
|
+
const isSynced = this.sync?.getModelSyncedStatus(model) ?? false;
|
|
1549
|
+
const itemsArray = [
|
|
1550
|
+
...Array.from(items.values()),
|
|
1551
|
+
...Array.from(itemsChanged.values()),
|
|
1552
|
+
];
|
|
1971
1553
|
items.clear();
|
|
1972
|
-
itemsArray.forEach(
|
|
1973
|
-
|
|
1974
|
-
|
|
1554
|
+
itemsArray.forEach(item => {
|
|
1555
|
+
const itemModelDefinition = getModelDefinition(model);
|
|
1556
|
+
const idOrPk = getIdentifierValue(itemModelDefinition, item);
|
|
1975
1557
|
items.set(idOrPk, item);
|
|
1976
1558
|
});
|
|
1977
1559
|
// remove deleted items from the final result set
|
|
1978
|
-
deletedItemIds.forEach(
|
|
1979
|
-
|
|
1560
|
+
deletedItemIds.forEach(idOrPk => items.delete(idOrPk));
|
|
1561
|
+
const snapshot = Array.from(items.values());
|
|
1980
1562
|
// we sort after we merge the snapshots (items, itemsChanged)
|
|
1981
1563
|
// otherwise, the merge may not
|
|
1982
|
-
if (options
|
|
1564
|
+
if (options?.sort) {
|
|
1983
1565
|
sortItems(snapshot);
|
|
1984
1566
|
}
|
|
1985
1567
|
return {
|
|
1986
1568
|
items: snapshot,
|
|
1987
|
-
isSynced
|
|
1569
|
+
isSynced,
|
|
1988
1570
|
};
|
|
1989
1571
|
};
|
|
1990
1572
|
/**
|
|
@@ -1995,7 +1577,7 @@ var DataStore = /** @class */ (function () {
|
|
|
1995
1577
|
*
|
|
1996
1578
|
* @param snapshot The generated items data to emit.
|
|
1997
1579
|
*/
|
|
1998
|
-
|
|
1580
|
+
const emitSnapshot = (snapshot) => {
|
|
1999
1581
|
// send the generated snapshot to the primary subscription.
|
|
2000
1582
|
// NOTE: This observer's handler *could* be async ...
|
|
2001
1583
|
observer.next(snapshot);
|
|
@@ -2009,12 +1591,12 @@ var DataStore = /** @class */ (function () {
|
|
|
2009
1591
|
*
|
|
2010
1592
|
* @param itemsToSort A array of model type.
|
|
2011
1593
|
*/
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
1594
|
+
const sortItems = (itemsToSort) => {
|
|
1595
|
+
const modelDefinition = getModelDefinition(model);
|
|
1596
|
+
const pagination = this.processPagination(modelDefinition, options);
|
|
1597
|
+
const sortPredicates = ModelSortPredicateCreator.getPredicates(pagination.sort);
|
|
2016
1598
|
if (sortPredicates.length) {
|
|
2017
|
-
|
|
1599
|
+
const compareFn = sortCompareFunction(sortPredicates);
|
|
2018
1600
|
itemsToSort.sort(compareFn);
|
|
2019
1601
|
}
|
|
2020
1602
|
};
|
|
@@ -2026,93 +1608,90 @@ var DataStore = /** @class */ (function () {
|
|
|
2026
1608
|
*
|
|
2027
1609
|
* @param payload The payload from the Hub event.
|
|
2028
1610
|
*/
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
var payload = _a.payload;
|
|
2032
|
-
var event = payload.event, data = payload.data;
|
|
1611
|
+
const hubCallback = ({ payload }) => {
|
|
1612
|
+
const { event, data } = payload;
|
|
2033
1613
|
if (event === ControlMessage.SYNC_ENGINE_MODEL_SYNCED &&
|
|
2034
|
-
|
|
1614
|
+
data?.model?.name === model.name) {
|
|
2035
1615
|
generateAndEmitSnapshot();
|
|
2036
1616
|
hubRemove();
|
|
2037
1617
|
}
|
|
2038
1618
|
};
|
|
2039
|
-
|
|
2040
|
-
return
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
return [2 /*return*/];
|
|
2046
|
-
});
|
|
2047
|
-
}); }, 'datastore observequery cleaner');
|
|
1619
|
+
const hubRemove = Hub.listen('datastore', hubCallback);
|
|
1620
|
+
return this.runningProcesses.addCleaner(async () => {
|
|
1621
|
+
if (handle) {
|
|
1622
|
+
handle.unsubscribe();
|
|
1623
|
+
}
|
|
1624
|
+
}, 'datastore observequery cleaner');
|
|
2048
1625
|
});
|
|
2049
1626
|
};
|
|
2050
|
-
this.configure =
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
1627
|
+
this.configure = (config = {}) => {
|
|
1628
|
+
this.amplifyContext.InternalAPI = this.InternalAPI;
|
|
1629
|
+
const { DataStore: configDataStore, authModeStrategyType: configAuthModeStrategyType, conflictHandler: configConflictHandler, errorHandler: configErrorHandler, maxRecordsToSync: configMaxRecordsToSync, syncPageSize: configSyncPageSize, fullSyncInterval: configFullSyncInterval, syncExpressions: configSyncExpressions, authProviders: configAuthProviders, storageAdapter: configStorageAdapter, ...configFromAmplify } = config;
|
|
1630
|
+
const currentAppSyncConfig = Amplify.getConfig().API?.GraphQL;
|
|
1631
|
+
const appSyncConfig = {
|
|
1632
|
+
aws_appsync_graphqlEndpoint: currentAppSyncConfig?.endpoint,
|
|
1633
|
+
aws_appsync_authenticationType: currentAppSyncConfig?.defaultAuthMode,
|
|
1634
|
+
aws_appsync_region: currentAppSyncConfig?.region,
|
|
1635
|
+
aws_appsync_apiKey: currentAppSyncConfig?.apiKey,
|
|
1636
|
+
};
|
|
1637
|
+
this.amplifyConfig = {
|
|
1638
|
+
...this.amplifyConfig,
|
|
1639
|
+
...configFromAmplify,
|
|
1640
|
+
...(currentAppSyncConfig && appSyncConfig),
|
|
2061
1641
|
};
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
var authModeStrategyType = (configDataStore && configDataStore.authModeStrategyType) ||
|
|
1642
|
+
this.conflictHandler = this.setConflictHandler(config);
|
|
1643
|
+
this.errorHandler = this.setErrorHandler(config);
|
|
1644
|
+
const authModeStrategyType = (configDataStore && configDataStore.authModeStrategyType) ||
|
|
2066
1645
|
configAuthModeStrategyType ||
|
|
2067
1646
|
AuthModeStrategyType.DEFAULT;
|
|
2068
1647
|
switch (authModeStrategyType) {
|
|
2069
1648
|
case AuthModeStrategyType.MULTI_AUTH:
|
|
2070
|
-
|
|
1649
|
+
this.authModeStrategy = multiAuthStrategy(this.amplifyContext);
|
|
2071
1650
|
break;
|
|
2072
1651
|
case AuthModeStrategyType.DEFAULT:
|
|
2073
|
-
|
|
1652
|
+
this.authModeStrategy = defaultAuthStrategy;
|
|
2074
1653
|
break;
|
|
2075
1654
|
default:
|
|
2076
|
-
|
|
1655
|
+
this.authModeStrategy = defaultAuthStrategy;
|
|
2077
1656
|
break;
|
|
2078
1657
|
}
|
|
2079
1658
|
// store on config object, so that Sync, Subscription, and Mutation processors can have access
|
|
2080
|
-
|
|
1659
|
+
this.amplifyConfig.authProviders =
|
|
2081
1660
|
(configDataStore && configDataStore.authProviders) || configAuthProviders;
|
|
2082
|
-
|
|
1661
|
+
this.syncExpressions =
|
|
2083
1662
|
(configDataStore && configDataStore.syncExpressions) ||
|
|
2084
1663
|
configSyncExpressions ||
|
|
2085
|
-
|
|
2086
|
-
|
|
1664
|
+
this.syncExpressions;
|
|
1665
|
+
this.maxRecordsToSync =
|
|
2087
1666
|
(configDataStore && configDataStore.maxRecordsToSync) ||
|
|
2088
1667
|
configMaxRecordsToSync ||
|
|
2089
|
-
|
|
1668
|
+
this.maxRecordsToSync ||
|
|
2090
1669
|
10000;
|
|
2091
1670
|
// store on config object, so that Sync, Subscription, and Mutation processors can have access
|
|
2092
|
-
|
|
2093
|
-
|
|
1671
|
+
this.amplifyConfig.maxRecordsToSync = this.maxRecordsToSync;
|
|
1672
|
+
this.syncPageSize =
|
|
2094
1673
|
(configDataStore && configDataStore.syncPageSize) ||
|
|
2095
1674
|
configSyncPageSize ||
|
|
2096
|
-
|
|
1675
|
+
this.syncPageSize ||
|
|
2097
1676
|
1000;
|
|
2098
1677
|
// store on config object, so that Sync, Subscription, and Mutation processors can have access
|
|
2099
|
-
|
|
2100
|
-
|
|
1678
|
+
this.amplifyConfig.syncPageSize = this.syncPageSize;
|
|
1679
|
+
this.fullSyncInterval =
|
|
2101
1680
|
(configDataStore && configDataStore.fullSyncInterval) ||
|
|
2102
1681
|
configFullSyncInterval ||
|
|
2103
|
-
|
|
1682
|
+
this.fullSyncInterval ||
|
|
2104
1683
|
24 * 60; // 1 day
|
|
2105
|
-
|
|
1684
|
+
this.storageAdapter =
|
|
2106
1685
|
(configDataStore && configDataStore.storageAdapter) ||
|
|
2107
1686
|
configStorageAdapter ||
|
|
2108
|
-
|
|
1687
|
+
this.storageAdapter ||
|
|
2109
1688
|
undefined;
|
|
2110
|
-
|
|
1689
|
+
this.sessionId = this.retrieveSessionId();
|
|
2111
1690
|
};
|
|
2112
1691
|
}
|
|
2113
|
-
|
|
1692
|
+
getModuleName() {
|
|
2114
1693
|
return 'DataStore';
|
|
2115
|
-
}
|
|
1694
|
+
}
|
|
2116
1695
|
/**
|
|
2117
1696
|
* Builds a function to capture `BackgroundManagerNotOpenError`'s to produce friendlier,
|
|
2118
1697
|
* more instructive errors for customers.
|
|
@@ -2120,19 +1699,18 @@ var DataStore = /** @class */ (function () {
|
|
|
2120
1699
|
* @param operation The name of the operation (usually a Datastore method) the customer
|
|
2121
1700
|
* tried to call.
|
|
2122
1701
|
*/
|
|
2123
|
-
|
|
2124
|
-
var _this = this;
|
|
1702
|
+
handleAddProcError(operation) {
|
|
2125
1703
|
/**
|
|
2126
1704
|
* If the tested error is a `BackgroundManagerNotOpenError`, it will be captured
|
|
2127
1705
|
* and replaced with a friendlier message that instructs the App Developer.
|
|
2128
1706
|
*
|
|
2129
1707
|
* @param err An error to test.
|
|
2130
1708
|
*/
|
|
2131
|
-
|
|
1709
|
+
const handler = (err) => {
|
|
2132
1710
|
if (err.message.startsWith('BackgroundManagerNotOpenError')) {
|
|
2133
1711
|
throw new Error([
|
|
2134
|
-
|
|
2135
|
-
|
|
1712
|
+
`DataStoreStateError: Tried to execute \`${operation}\` while DataStore was "${this.state}".`,
|
|
1713
|
+
`This can only be done while DataStore is "Started" or "Stopped". To remedy:`,
|
|
2136
1714
|
'Ensure all calls to `stop()` and `clear()` have completed first.',
|
|
2137
1715
|
'If this is not possible, retry the operation until it succeeds.',
|
|
2138
1716
|
].join('\n'));
|
|
@@ -2142,7 +1720,7 @@ var DataStore = /** @class */ (function () {
|
|
|
2142
1720
|
}
|
|
2143
1721
|
};
|
|
2144
1722
|
return handler;
|
|
2145
|
-
}
|
|
1723
|
+
}
|
|
2146
1724
|
/**
|
|
2147
1725
|
* Clears all data from storage and removes all data, schema info, other
|
|
2148
1726
|
* initialization details, and then stops DataStore.
|
|
@@ -2151,83 +1729,49 @@ var DataStore = /** @class */ (function () {
|
|
|
2151
1729
|
* by explicitiliy calling `start()` or any method that implicitly starts
|
|
2152
1730
|
* DataStore, such as `query()`, `save()`, or `delete()`.
|
|
2153
1731
|
*/
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
case 4:
|
|
2178
|
-
_a.sent();
|
|
2179
|
-
_a.label = 5;
|
|
2180
|
-
case 5: return [4 /*yield*/, this.storage.clear()];
|
|
2181
|
-
case 6:
|
|
2182
|
-
_a.sent();
|
|
2183
|
-
this.initialized = undefined; // Should re-initialize when start() is called.
|
|
2184
|
-
this.storage = undefined;
|
|
2185
|
-
this.sync = undefined;
|
|
2186
|
-
this.syncPredicates = new WeakMap();
|
|
2187
|
-
return [4 /*yield*/, this.runningProcesses.open()];
|
|
2188
|
-
case 7:
|
|
2189
|
-
_a.sent();
|
|
2190
|
-
this.state = DataStoreState.NotRunning;
|
|
2191
|
-
return [2 /*return*/];
|
|
2192
|
-
}
|
|
2193
|
-
});
|
|
2194
|
-
});
|
|
2195
|
-
};
|
|
1732
|
+
async clear() {
|
|
1733
|
+
checkSchemaInitialized();
|
|
1734
|
+
this.state = DataStoreState.Clearing;
|
|
1735
|
+
await this.runningProcesses.close();
|
|
1736
|
+
if (this.storage === undefined) {
|
|
1737
|
+
// connect to storage so that it can be cleared without fully starting DataStore
|
|
1738
|
+
this.storage = new Storage(schema, namespaceResolver, getModelConstructorByModelName, modelInstanceCreator, this.storageAdapter, this.sessionId);
|
|
1739
|
+
await this.storage.init();
|
|
1740
|
+
}
|
|
1741
|
+
if (syncSubscription && !syncSubscription.closed) {
|
|
1742
|
+
syncSubscription.unsubscribe();
|
|
1743
|
+
}
|
|
1744
|
+
if (this.sync) {
|
|
1745
|
+
await this.sync.stop();
|
|
1746
|
+
}
|
|
1747
|
+
await this.storage.clear();
|
|
1748
|
+
this.initialized = undefined; // Should re-initialize when start() is called.
|
|
1749
|
+
this.storage = undefined;
|
|
1750
|
+
this.sync = undefined;
|
|
1751
|
+
this.syncPredicates = new WeakMap();
|
|
1752
|
+
await this.runningProcesses.open();
|
|
1753
|
+
this.state = DataStoreState.NotRunning;
|
|
1754
|
+
}
|
|
2196
1755
|
/**
|
|
2197
1756
|
* Stops all DataStore sync activities.
|
|
2198
1757
|
*
|
|
2199
1758
|
* TODO: "Waits for graceful termination of
|
|
2200
1759
|
* running queries and terminates subscriptions."
|
|
2201
1760
|
*/
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
case 2:
|
|
2217
|
-
_a.sent();
|
|
2218
|
-
_a.label = 3;
|
|
2219
|
-
case 3:
|
|
2220
|
-
this.initialized = undefined; // Should re-initialize when start() is called.
|
|
2221
|
-
this.sync = undefined;
|
|
2222
|
-
return [4 /*yield*/, this.runningProcesses.open()];
|
|
2223
|
-
case 4:
|
|
2224
|
-
_a.sent();
|
|
2225
|
-
this.state = DataStoreState.NotRunning;
|
|
2226
|
-
return [2 /*return*/];
|
|
2227
|
-
}
|
|
2228
|
-
});
|
|
2229
|
-
});
|
|
2230
|
-
};
|
|
1761
|
+
async stop() {
|
|
1762
|
+
this.state = DataStoreState.Stopping;
|
|
1763
|
+
await this.runningProcesses.close();
|
|
1764
|
+
if (syncSubscription && !syncSubscription.closed) {
|
|
1765
|
+
syncSubscription.unsubscribe();
|
|
1766
|
+
}
|
|
1767
|
+
if (this.sync) {
|
|
1768
|
+
await this.sync.stop();
|
|
1769
|
+
}
|
|
1770
|
+
this.initialized = undefined; // Should re-initialize when start() is called.
|
|
1771
|
+
this.sync = undefined;
|
|
1772
|
+
await this.runningProcesses.open();
|
|
1773
|
+
this.state = DataStoreState.NotRunning;
|
|
1774
|
+
}
|
|
2231
1775
|
/**
|
|
2232
1776
|
* Validates given pagination input from a query and creates a pagination
|
|
2233
1777
|
* argument for use against the storage layer.
|
|
@@ -2235,9 +1779,9 @@ var DataStore = /** @class */ (function () {
|
|
|
2235
1779
|
* @param modelDefinition
|
|
2236
1780
|
* @param paginationProducer
|
|
2237
1781
|
*/
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
1782
|
+
processPagination(modelDefinition, paginationProducer) {
|
|
1783
|
+
let sortPredicate;
|
|
1784
|
+
const { limit, page, sort } = paginationProducer || {};
|
|
2241
1785
|
if (limit === undefined && page === undefined && sort === undefined) {
|
|
2242
1786
|
return undefined;
|
|
2243
1787
|
}
|
|
@@ -2264,83 +1808,55 @@ var DataStore = /** @class */ (function () {
|
|
|
2264
1808
|
sortPredicate = ModelSortPredicateCreator.createFromExisting(modelDefinition, sort);
|
|
2265
1809
|
}
|
|
2266
1810
|
return {
|
|
2267
|
-
limit
|
|
2268
|
-
page
|
|
1811
|
+
limit,
|
|
1812
|
+
page,
|
|
2269
1813
|
sort: sortPredicate,
|
|
2270
1814
|
};
|
|
2271
|
-
}
|
|
1815
|
+
}
|
|
2272
1816
|
/**
|
|
2273
1817
|
* Examines the configured `syncExpressions` and produces a WeakMap of
|
|
2274
1818
|
* SchemaModel -> predicate to use during sync.
|
|
2275
1819
|
*/
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
}
|
|
2313
|
-
});
|
|
2314
|
-
});
|
|
2315
|
-
};
|
|
2316
|
-
DataStore.prototype.unwrapPromise = function (conditionProducer) {
|
|
2317
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
2318
|
-
var condition, error_1;
|
|
2319
|
-
return __generator(this, function (_a) {
|
|
2320
|
-
switch (_a.label) {
|
|
2321
|
-
case 0:
|
|
2322
|
-
_a.trys.push([0, 2, , 3]);
|
|
2323
|
-
return [4 /*yield*/, conditionProducer()];
|
|
2324
|
-
case 1:
|
|
2325
|
-
condition = _a.sent();
|
|
2326
|
-
return [2 /*return*/, condition || conditionProducer];
|
|
2327
|
-
case 2:
|
|
2328
|
-
error_1 = _a.sent();
|
|
2329
|
-
if (error_1 instanceof TypeError) {
|
|
2330
|
-
return [2 /*return*/, conditionProducer];
|
|
2331
|
-
}
|
|
2332
|
-
throw error_1;
|
|
2333
|
-
case 3: return [2 /*return*/];
|
|
2334
|
-
}
|
|
2335
|
-
});
|
|
2336
|
-
});
|
|
2337
|
-
};
|
|
2338
|
-
DataStore.prototype.weakMapFromEntries = function (entries) {
|
|
2339
|
-
return entries.reduce(function (map, _a) {
|
|
2340
|
-
var _b = __read(_a, 2), modelDefinition = _b[0], predicate = _b[1];
|
|
1820
|
+
async processSyncExpressions() {
|
|
1821
|
+
if (!this.syncExpressions || !this.syncExpressions.length) {
|
|
1822
|
+
return new WeakMap();
|
|
1823
|
+
}
|
|
1824
|
+
const syncPredicates = await Promise.all(this.syncExpressions.map(async (syncExpression) => {
|
|
1825
|
+
const { modelConstructor, conditionProducer } = await syncExpression;
|
|
1826
|
+
const modelDefinition = getModelDefinition(modelConstructor);
|
|
1827
|
+
// conditionProducer is either a predicate, e.g. (c) => c.field.eq(1)
|
|
1828
|
+
// OR a function/promise that returns a predicate
|
|
1829
|
+
const condition = await this.unwrapPromise(conditionProducer);
|
|
1830
|
+
if (isPredicatesAll(condition)) {
|
|
1831
|
+
return [modelDefinition, null];
|
|
1832
|
+
}
|
|
1833
|
+
const predicate = internals(condition(predicateFor({
|
|
1834
|
+
builder: modelConstructor,
|
|
1835
|
+
schema: modelDefinition,
|
|
1836
|
+
pkField: extractPrimaryKeyFieldNames(modelDefinition),
|
|
1837
|
+
}))).toStoragePredicate();
|
|
1838
|
+
return [modelDefinition, predicate];
|
|
1839
|
+
}));
|
|
1840
|
+
return this.weakMapFromEntries(syncPredicates);
|
|
1841
|
+
}
|
|
1842
|
+
async unwrapPromise(conditionProducer) {
|
|
1843
|
+
try {
|
|
1844
|
+
const condition = await conditionProducer();
|
|
1845
|
+
return condition || conditionProducer;
|
|
1846
|
+
}
|
|
1847
|
+
catch (error) {
|
|
1848
|
+
if (error instanceof TypeError) {
|
|
1849
|
+
return conditionProducer;
|
|
1850
|
+
}
|
|
1851
|
+
throw error;
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
weakMapFromEntries(entries) {
|
|
1855
|
+
return entries.reduce((map, [modelDefinition, predicate]) => {
|
|
2341
1856
|
if (map.has(modelDefinition)) {
|
|
2342
|
-
|
|
2343
|
-
logger.warn(
|
|
1857
|
+
const { name } = modelDefinition;
|
|
1858
|
+
logger.warn(`You can only utilize one Sync Expression per model.
|
|
1859
|
+
Subsequent sync expressions for the ${name} model will be ignored.`);
|
|
2344
1860
|
return map;
|
|
2345
1861
|
}
|
|
2346
1862
|
if (predicate) {
|
|
@@ -2348,29 +1864,28 @@ var DataStore = /** @class */ (function () {
|
|
|
2348
1864
|
}
|
|
2349
1865
|
return map;
|
|
2350
1866
|
}, new WeakMap());
|
|
2351
|
-
}
|
|
1867
|
+
}
|
|
2352
1868
|
/**
|
|
2353
1869
|
* A session ID to allow CMS to open databases against multiple apps.
|
|
2354
1870
|
* This session ID is only expected be set by AWS Amplify Studio.
|
|
2355
1871
|
*/
|
|
2356
|
-
|
|
1872
|
+
retrieveSessionId() {
|
|
2357
1873
|
try {
|
|
2358
|
-
|
|
1874
|
+
const sessionId = sessionStorage.getItem('datastoreSessionId');
|
|
2359
1875
|
if (sessionId) {
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
return
|
|
1876
|
+
const { aws_appsync_graphqlEndpoint } = this.amplifyConfig;
|
|
1877
|
+
const appSyncUrl = aws_appsync_graphqlEndpoint.split('/')[2];
|
|
1878
|
+
const [appSyncId] = appSyncUrl.split('.');
|
|
1879
|
+
return `${sessionId}-${appSyncId}`;
|
|
2364
1880
|
}
|
|
2365
1881
|
}
|
|
2366
|
-
catch
|
|
1882
|
+
catch { }
|
|
2367
1883
|
return undefined;
|
|
2368
|
-
}
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
var instance = new DataStore();
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
const instance = new DataStore();
|
|
2372
1887
|
instance.configure({});
|
|
2373
|
-
Hub.listen('core',
|
|
1888
|
+
Hub.listen('core', capsule => {
|
|
2374
1889
|
if (capsule.payload.event === 'configure') {
|
|
2375
1890
|
instance.configure({});
|
|
2376
1891
|
}
|