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