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