@aws-amplify/datastore 4.0.12 → 4.0.13-push-notification-dryrun.43

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.
Files changed (111) hide show
  1. package/lib/datastore/datastore.d.ts +29 -3
  2. package/lib/datastore/datastore.js +308 -147
  3. package/lib/datastore/datastore.js.map +1 -1
  4. package/lib/predicates/index.d.ts +77 -7
  5. package/lib/predicates/index.js +142 -122
  6. package/lib/predicates/index.js.map +1 -1
  7. package/lib/predicates/next.d.ts +51 -10
  8. package/lib/predicates/next.js +111 -91
  9. package/lib/predicates/next.js.map +1 -1
  10. package/lib/storage/adapter/AsyncStorageAdapter.d.ts +28 -30
  11. package/lib/storage/adapter/AsyncStorageAdapter.js +135 -532
  12. package/lib/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  13. package/lib/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  14. package/lib/storage/adapter/IndexedDBAdapter.d.ts +28 -29
  15. package/lib/storage/adapter/IndexedDBAdapter.js +490 -885
  16. package/lib/storage/adapter/IndexedDBAdapter.js.map +1 -1
  17. package/lib/storage/adapter/StorageAdapterBase.d.ts +134 -0
  18. package/lib/storage/adapter/StorageAdapterBase.js +439 -0
  19. package/lib/storage/adapter/StorageAdapterBase.js.map +1 -0
  20. package/lib/storage/relationship.d.ts +9 -0
  21. package/lib/storage/relationship.js +9 -0
  22. package/lib/storage/relationship.js.map +1 -1
  23. package/lib/storage/storage.d.ts +1 -1
  24. package/lib/storage/storage.js +4 -3
  25. package/lib/storage/storage.js.map +1 -1
  26. package/lib/sync/index.d.ts +15 -1
  27. package/lib/sync/index.js +80 -13
  28. package/lib/sync/index.js.map +1 -1
  29. package/lib/sync/outbox.js +14 -7
  30. package/lib/sync/outbox.js.map +1 -1
  31. package/lib/sync/processors/mutation.d.ts +10 -1
  32. package/lib/sync/processors/mutation.js +33 -12
  33. package/lib/sync/processors/mutation.js.map +1 -1
  34. package/lib/sync/processors/subscription.d.ts +7 -1
  35. package/lib/sync/processors/subscription.js +196 -135
  36. package/lib/sync/processors/subscription.js.map +1 -1
  37. package/lib/sync/processors/sync.d.ts +1 -1
  38. package/lib/sync/processors/sync.js.map +1 -1
  39. package/lib/sync/utils.d.ts +66 -2
  40. package/lib/sync/utils.js +264 -16
  41. package/lib/sync/utils.js.map +1 -1
  42. package/lib/types.d.ts +9 -1
  43. package/lib/types.js.map +1 -1
  44. package/lib/util.d.ts +16 -0
  45. package/lib/util.js +31 -2
  46. package/lib/util.js.map +1 -1
  47. package/lib-esm/datastore/datastore.d.ts +29 -3
  48. package/lib-esm/datastore/datastore.js +310 -149
  49. package/lib-esm/datastore/datastore.js.map +1 -1
  50. package/lib-esm/predicates/index.d.ts +77 -7
  51. package/lib-esm/predicates/index.js +143 -123
  52. package/lib-esm/predicates/index.js.map +1 -1
  53. package/lib-esm/predicates/next.d.ts +51 -10
  54. package/lib-esm/predicates/next.js +111 -91
  55. package/lib-esm/predicates/next.js.map +1 -1
  56. package/lib-esm/storage/adapter/AsyncStorageAdapter.d.ts +28 -30
  57. package/lib-esm/storage/adapter/AsyncStorageAdapter.js +138 -535
  58. package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  59. package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  60. package/lib-esm/storage/adapter/IndexedDBAdapter.d.ts +28 -29
  61. package/lib-esm/storage/adapter/IndexedDBAdapter.js +489 -884
  62. package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +1 -1
  63. package/lib-esm/storage/adapter/StorageAdapterBase.d.ts +134 -0
  64. package/lib-esm/storage/adapter/StorageAdapterBase.js +437 -0
  65. package/lib-esm/storage/adapter/StorageAdapterBase.js.map +1 -0
  66. package/lib-esm/storage/relationship.d.ts +9 -0
  67. package/lib-esm/storage/relationship.js +9 -0
  68. package/lib-esm/storage/relationship.js.map +1 -1
  69. package/lib-esm/storage/storage.d.ts +1 -1
  70. package/lib-esm/storage/storage.js +4 -3
  71. package/lib-esm/storage/storage.js.map +1 -1
  72. package/lib-esm/sync/index.d.ts +15 -1
  73. package/lib-esm/sync/index.js +82 -15
  74. package/lib-esm/sync/index.js.map +1 -1
  75. package/lib-esm/sync/outbox.js +14 -7
  76. package/lib-esm/sync/outbox.js.map +1 -1
  77. package/lib-esm/sync/processors/mutation.d.ts +10 -1
  78. package/lib-esm/sync/processors/mutation.js +33 -12
  79. package/lib-esm/sync/processors/mutation.js.map +1 -1
  80. package/lib-esm/sync/processors/subscription.d.ts +7 -1
  81. package/lib-esm/sync/processors/subscription.js +197 -136
  82. package/lib-esm/sync/processors/subscription.js.map +1 -1
  83. package/lib-esm/sync/processors/sync.d.ts +1 -1
  84. package/lib-esm/sync/processors/sync.js.map +1 -1
  85. package/lib-esm/sync/utils.d.ts +66 -2
  86. package/lib-esm/sync/utils.js +261 -18
  87. package/lib-esm/sync/utils.js.map +1 -1
  88. package/lib-esm/types.d.ts +9 -1
  89. package/lib-esm/types.js.map +1 -1
  90. package/lib-esm/util.d.ts +16 -0
  91. package/lib-esm/util.js +32 -3
  92. package/lib-esm/util.js.map +1 -1
  93. package/package.json +12 -11
  94. package/src/datastore/datastore.ts +288 -159
  95. package/src/predicates/index.ts +145 -175
  96. package/src/predicates/next.ts +114 -81
  97. package/src/storage/adapter/AsyncStorageAdapter.ts +97 -563
  98. package/src/storage/adapter/AsyncStorageDatabase.ts +2 -2
  99. package/src/storage/adapter/IndexedDBAdapter.ts +318 -770
  100. package/src/storage/adapter/StorageAdapterBase.ts +545 -0
  101. package/src/storage/relationship.ts +9 -0
  102. package/src/storage/storage.ts +12 -9
  103. package/src/sync/index.ts +108 -20
  104. package/src/sync/outbox.ts +17 -11
  105. package/src/sync/processors/mutation.ts +35 -4
  106. package/src/sync/processors/subscription.ts +124 -10
  107. package/src/sync/processors/sync.ts +4 -1
  108. package/src/sync/utils.ts +285 -15
  109. package/src/types.ts +15 -2
  110. package/src/util.ts +40 -1
  111. package/CHANGELOG.md +0 -904
@@ -11,8 +11,8 @@ import { isPredicatesAll, ModelPredicateCreator, ModelSortPredicateCreator, } fr
11
11
  import { ExclusiveStorage as Storage } from '../storage/storage';
12
12
  import { ModelRelationship } from '../storage/relationship';
13
13
  import { ControlMessage, SyncEngine } from '../sync';
14
- import { GraphQLScalarType, isGraphQLScalarType, isSchemaModelWithAttributes, AuthModeStrategyType, isNonModelFieldType, isModelFieldType, isIdentifierObject, isFieldAssociation, } from '../types';
15
- import { DATASTORE, errorMessages, establishRelationAndKeys, isModelConstructor, monotonicUlidFactory, STORAGE, SYNC, USER, isNullOrUndefined, registerNonModelClass, sortCompareFunction, DeferredCallbackResolver, inMemoryPagination, extractPrimaryKeyFieldNames, extractPrimaryKeysAndValues, isIdManaged, isIdOptionallyManaged, mergePatches, } from '../util';
14
+ import { GraphQLScalarType, isGraphQLScalarType, isSchemaModelWithAttributes, AuthModeStrategyType, isNonModelFieldType, isModelFieldType, isIdentifierObject, } from '../types';
15
+ import { DATASTORE, errorMessages, establishRelationAndKeys, isModelConstructor, monotonicUlidFactory, STORAGE, SYNC, USER, isNullOrUndefined, registerNonModelClass, sortCompareFunction, DeferredCallbackResolver, inMemoryPagination, extractPrimaryKeyFieldNames, extractPrimaryKeysAndValues, isIdManaged, isIdOptionallyManaged, mergePatches, getTimestampFields, } from '../util';
16
16
  import { recursivePredicateFor, predicateFor, internals, } from '../predicates/next';
17
17
  import { getIdentifierValue } from '../sync/utils';
18
18
  setAutoFreeze(true);
@@ -23,70 +23,28 @@ var isNode = browserOrNode().isNode;
23
23
  var SETTING_SCHEMA_VERSION = 'schemaVersion';
24
24
  var schema;
25
25
  var modelNamespaceMap = new WeakMap();
26
- // stores data for crafting the correct update mutation input for a model
27
- // Patch[] - array of changed fields and metadata
28
- // PersistentModel - the source model, used for diffing object-type fields
26
+ /**
27
+ * Stores data for crafting the correct update mutation input for a model.
28
+ *
29
+ * - `Patch[]` - array of changed fields and metadata.
30
+ * - `PersistentModel` - the source model, used for diffing object-type fields.
31
+ */
29
32
  var modelPatchesMap = new WeakMap();
30
33
  var getModelDefinition = function (modelConstructor) {
31
- var e_1, _a, e_2, _b;
32
34
  var namespace = modelNamespaceMap.get(modelConstructor);
33
35
  var definition = namespace
34
36
  ? schema.namespaces[namespace].models[modelConstructor.name]
35
37
  : undefined;
36
- // compatibility with legacy/pre-PK codegen for lazy loading to inject
37
- // index fields into the model definition.
38
- if (definition) {
39
- var indexes = schema.namespaces[namespace].relationships[modelConstructor.name]
40
- .indexes;
41
- var indexFields = new Set();
42
- try {
43
- for (var indexes_1 = __values(indexes), indexes_1_1 = indexes_1.next(); !indexes_1_1.done; indexes_1_1 = indexes_1.next()) {
44
- var index = indexes_1_1.value;
45
- try {
46
- for (var _c = (e_2 = void 0, __values(index[1])), _d = _c.next(); !_d.done; _d = _c.next()) {
47
- var indexField = _d.value;
48
- indexFields.add(indexField);
49
- }
50
- }
51
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
52
- finally {
53
- try {
54
- if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
55
- }
56
- finally { if (e_2) throw e_2.error; }
57
- }
58
- }
59
- }
60
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
61
- finally {
62
- try {
63
- if (indexes_1_1 && !indexes_1_1.done && (_a = indexes_1.return)) _a.call(indexes_1);
64
- }
65
- finally { if (e_1) throw e_1.error; }
66
- }
67
- definition.fields = __assign(__assign({}, Object.fromEntries(__spread(indexFields.values()).map(function (name) { return [
68
- name,
69
- {
70
- name: name,
71
- type: 'ID',
72
- isArray: false,
73
- },
74
- ]; }, []))), definition.fields);
75
- }
76
38
  return definition;
77
39
  };
78
- var getModelPKFieldName = function (modelConstructor) {
79
- var _a, _b, _c;
80
- var namespace = modelNamespaceMap.get(modelConstructor);
81
- return ((namespace && ((_c = (_b = (_a = schema.namespaces) === null || _a === void 0 ? void 0 : _a[namespace]) === null || _b === void 0 ? void 0 : _b.keys) === null || _c === void 0 ? void 0 : _c[modelConstructor.name].primaryKey)) || ['id']);
82
- };
40
+ /**
41
+ * Determines whether the given object is a Model Constructor that DataStore can
42
+ * safely use to construct objects and discover related metadata.
43
+ *
44
+ * @param obj The object to test.
45
+ */
83
46
  var isValidModelConstructor = function (obj) {
84
- if (isModelConstructor(obj) && modelNamespaceMap.has(obj)) {
85
- return true;
86
- }
87
- else {
88
- return false;
89
- }
47
+ return isModelConstructor(obj) && modelNamespaceMap.has(obj);
90
48
  };
91
49
  var namespaceResolver = function (modelConstructor) {
92
50
  var resolver = modelNamespaceMap.get(modelConstructor);
@@ -95,13 +53,32 @@ var namespaceResolver = function (modelConstructor) {
95
53
  }
96
54
  return resolver;
97
55
  };
56
+ /**
57
+ * Creates a predicate without any conditions that can be passed to customer
58
+ * code to have conditions added to it.
59
+ *
60
+ * For example, in this query:
61
+ *
62
+ * ```ts
63
+ * await DataStore.query(
64
+ * Model,
65
+ * item => item.field.eq('value')
66
+ * );
67
+ * ```
68
+ *
69
+ * `buildSeedPredicate(Model)` is used to create `item`, which is passed to the
70
+ * predicate function, which in turn uses that "seed" predicate (`item`) to build
71
+ * a predicate tree.
72
+ *
73
+ * @param modelConstructor The model the predicate will query.
74
+ */
98
75
  var buildSeedPredicate = function (modelConstructor) {
99
76
  if (!modelConstructor)
100
77
  throw new Error('Missing modelConstructor');
101
78
  var modelSchema = getModelDefinition(modelConstructor);
102
79
  if (!modelSchema)
103
80
  throw new Error('Missing modelSchema');
104
- var pks = getModelPKFieldName(modelConstructor);
81
+ var pks = extractPrimaryKeyFieldNames(modelSchema);
105
82
  if (!pks)
106
83
  throw new Error('Could not determine PK');
107
84
  return recursivePredicateFor({
@@ -208,12 +185,13 @@ var initSchema = function (userSchema) {
208
185
  codegenVersion: userSchema.codegenVersion,
209
186
  };
210
187
  Object.keys(schema.namespaces).forEach(function (namespace) {
211
- var e_3, _a;
188
+ var e_1, _a;
212
189
  var _b = __read(establishRelationAndKeys(schema.namespaces[namespace]), 2), relations = _b[0], keys = _b[1];
213
190
  schema.namespaces[namespace].relationships = relations;
214
191
  schema.namespaces[namespace].keys = keys;
215
192
  var modelAssociations = new Map();
216
193
  Object.values(schema.namespaces[namespace].models).forEach(function (model) {
194
+ var e_2, _a, e_3, _b;
217
195
  var connectedModels = [];
218
196
  Object.values(model.fields)
219
197
  .filter(function (field) {
@@ -225,20 +203,64 @@ var initSchema = function (userSchema) {
225
203
  return connectedModels.push(field.type.model);
226
204
  });
227
205
  modelAssociations.set(model.name, connectedModels);
206
+ // Precompute model info (such as pk fields) so that downstream schema consumers
207
+ // (such as predicate builders) don't have to reach back into "DataStore" space
208
+ // to go looking for it.
228
209
  Object.values(model.fields).forEach(function (field) {
229
- if (typeof field.type === 'object' &&
230
- !Object.getOwnPropertyDescriptor(field.type, 'modelConstructor')) {
210
+ var relatedModel = userClasses[field.type.model];
211
+ if (isModelConstructor(relatedModel)) {
231
212
  Object.defineProperty(field.type, 'modelConstructor', {
232
213
  get: function () {
214
+ var relatedModelDefinition = getModelDefinition(relatedModel);
215
+ if (!relatedModelDefinition)
216
+ throw new Error("Could not find model definition for " + relatedModel.name);
233
217
  return {
234
- builder: userClasses[field.type.model],
235
- schema: schema.namespaces[namespace].models[field.type.model],
236
- pkField: getModelPKFieldName(userClasses[field.type.model]),
218
+ builder: relatedModel,
219
+ schema: relatedModelDefinition,
220
+ pkField: extractPrimaryKeyFieldNames(relatedModelDefinition),
237
221
  };
238
222
  },
239
223
  });
240
224
  }
241
225
  });
226
+ // compatibility with legacy/pre-PK codegen for lazy loading to inject
227
+ // index fields into the model definition.
228
+ // definition.cloudFields = { ...definition.fields };
229
+ var indexes = schema.namespaces[namespace].relationships[model.name].indexes;
230
+ var indexFields = new Set();
231
+ try {
232
+ for (var indexes_1 = __values(indexes), indexes_1_1 = indexes_1.next(); !indexes_1_1.done; indexes_1_1 = indexes_1.next()) {
233
+ var index = indexes_1_1.value;
234
+ try {
235
+ for (var _c = (e_3 = void 0, __values(index[1])), _d = _c.next(); !_d.done; _d = _c.next()) {
236
+ var indexField = _d.value;
237
+ indexFields.add(indexField);
238
+ }
239
+ }
240
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
241
+ finally {
242
+ try {
243
+ if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
244
+ }
245
+ finally { if (e_3) throw e_3.error; }
246
+ }
247
+ }
248
+ }
249
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
250
+ finally {
251
+ try {
252
+ if (indexes_1_1 && !indexes_1_1.done && (_a = indexes_1.return)) _a.call(indexes_1);
253
+ }
254
+ finally { if (e_2) throw e_2.error; }
255
+ }
256
+ model.allFields = __assign(__assign({}, Object.fromEntries(__spread(indexFields.values()).map(function (name) { return [
257
+ name,
258
+ {
259
+ name: name,
260
+ type: 'ID',
261
+ isArray: false,
262
+ },
263
+ ]; }))), model.fields);
242
264
  });
243
265
  var result = new Map();
244
266
  var count = 1000;
@@ -251,7 +273,7 @@ var initSchema = function (userSchema) {
251
273
  throw new Error('Models are not topologically sortable. Please verify your schema.');
252
274
  }
253
275
  try {
254
- for (var _c = (e_3 = void 0, __values(Array.from(modelAssociations.keys()))), _d = _c.next(); !_d.done; _d = _c.next()) {
276
+ for (var _c = (e_1 = void 0, __values(Array.from(modelAssociations.keys()))), _d = _c.next(); !_d.done; _d = _c.next()) {
255
277
  var modelName = _d.value;
256
278
  var parents = modelAssociations.get(modelName);
257
279
  if (parents === null || parents === void 0 ? void 0 : parents.every(function (x) { return result.has(x); })) {
@@ -259,12 +281,12 @@ var initSchema = function (userSchema) {
259
281
  }
260
282
  }
261
283
  }
262
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
284
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
263
285
  finally {
264
286
  try {
265
287
  if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
266
288
  }
267
- finally { if (e_3) throw e_3.error; }
289
+ finally { if (e_1) throw e_1.error; }
268
290
  }
269
291
  Array.from(result.keys()).forEach(function (x) { return modelAssociations.delete(x); });
270
292
  }
@@ -307,7 +329,6 @@ var checkSchemaInitialized = function () {
307
329
  * @param codegenVersion schema codegenVersion
308
330
  */
309
331
  var checkSchemaCodegenVersion = function (codegenVersion) {
310
- // TODO: set to correct version when released in codegen
311
332
  var majorVersion = 3;
312
333
  var minorVersion = 2;
313
334
  var isValid = false;
@@ -355,7 +376,12 @@ var validateModelFields = function (modelDefinition) { return function (k, v) {
355
376
  var fieldDefinition = modelDefinition.fields[k];
356
377
  if (fieldDefinition !== undefined) {
357
378
  var type_1 = fieldDefinition.type, isRequired_1 = fieldDefinition.isRequired, isArrayNullable = fieldDefinition.isArrayNullable, name_1 = fieldDefinition.name, isArray = fieldDefinition.isArray;
379
+ var timestamps = isSchemaModelWithAttributes(modelDefinition)
380
+ ? getTimestampFields(modelDefinition)
381
+ : {};
382
+ var isTimestampField = !!timestamps[name_1];
358
383
  if (((!isArray && isRequired_1) || (isArray && !isArrayNullable)) &&
384
+ !isTimestampField &&
359
385
  (v === null || v === undefined)) {
360
386
  throw new Error("Field " + name_1 + " is required");
361
387
  }
@@ -489,6 +515,20 @@ var castInstanceType = function (modelDefinition, k, v) {
489
515
  }
490
516
  return v;
491
517
  };
518
+ /**
519
+ * Records the patches (as if against an empty object) used to initialize
520
+ * an instance of a Model. This can be used for determining which fields to
521
+ * send to the cloud durnig a CREATE mutation.
522
+ */
523
+ var initPatches = new WeakMap();
524
+ /**
525
+ * Attempts to apply type-aware, casted field values from a given `init`
526
+ * object to the given `draft`.
527
+ *
528
+ * @param init The initialization object to extract field values from.
529
+ * @param modelDefinition The definition describing the target object shape.
530
+ * @param draft The draft to apply field values to.
531
+ */
492
532
  var initializeInstance = function (init, modelDefinition, draft) {
493
533
  var modelValidator = validateModelFields(modelDefinition);
494
534
  Object.entries(init).forEach(function (_a) {
@@ -498,10 +538,51 @@ var initializeInstance = function (init, modelDefinition, draft) {
498
538
  draft[k] = parsedValue;
499
539
  });
500
540
  };
541
+ /**
542
+ * Updates a draft to standardize its customer-defined fields so that they are
543
+ * consistent with the data as it would look after having been synchronized from
544
+ * Cloud storage.
545
+ *
546
+ * The exceptions to this are:
547
+ *
548
+ * 1. Non-schema/Internal [sync] metadata fields.
549
+ * 2. Cloud-managed fields, which are `null` until set by cloud storage.
550
+ *
551
+ * This function should be expanded if/when deviations between canonical Cloud
552
+ * storage data and locally managed data are found. For now, the known areas
553
+ * that require normalization are:
554
+ *
555
+ * 1. Ensuring all non-metadata fields are *defined*. (I.e., turn `undefined` -> `null`.)
556
+ *
557
+ * @param modelDefinition Definition for the draft. Used to discover all fields.
558
+ * @param draft The instance draft to apply normalizations to.
559
+ */
560
+ var normalize = function (modelDefinition, draft) {
561
+ var e_4, _a;
562
+ try {
563
+ for (var _b = __values(Object.keys(modelDefinition.fields)), _c = _b.next(); !_c.done; _c = _b.next()) {
564
+ var k = _c.value;
565
+ if (draft[k] === undefined)
566
+ draft[k] = null;
567
+ }
568
+ }
569
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
570
+ finally {
571
+ try {
572
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
573
+ }
574
+ finally { if (e_4) throw e_4.error; }
575
+ }
576
+ };
501
577
  var createModelClass = function (modelDefinition) {
578
+ var e_5, _a;
502
579
  var clazz = /** @class */ (function () {
503
580
  function Model(init) {
504
- var instance = produce(this, function (draft) {
581
+ // we create a base instance first so we can distinguish which fields were explicitly
582
+ // set by customer code versus those set by normalization. only those fields
583
+ // which are explicitly set by customers should be part of create mutations.
584
+ var patches = [];
585
+ var baseInstance = produce(this, function (draft) {
505
586
  initializeInstance(init, modelDefinition, draft);
506
587
  // model is initialized inside a DataStore component (e.g. by Sync Engine, Storage Engine, etc.)
507
588
  var isInternallyInitialized = instancesMetadata.has(init);
@@ -531,8 +612,17 @@ var createModelClass = function (modelDefinition) {
531
612
  draft._lastChangedAt = _lastChangedAt;
532
613
  draft._deleted = _deleted;
533
614
  }
615
+ }, function (p) { return (patches = p); });
616
+ // now that we have a list of patches that encapsulate the explicit, customer-provided
617
+ // fields, we can normalize. patches from normalization are ignored, because the changes
618
+ // are only create to provide a consistent view of the data for fields pre/post sync
619
+ // where possible. (not all fields can be normalized pre-sync, because they're generally
620
+ // "cloud managed" fields, like createdAt and updatedAt.)
621
+ var normalized = produce(baseInstance, function (draft) {
622
+ return normalize(modelDefinition, draft);
534
623
  });
535
- return instance;
624
+ initPatches.set(normalized, patches);
625
+ return normalized;
536
626
  }
537
627
  Model.copyOf = function (source, fn) {
538
628
  var modelConstructor = Object.getPrototypeOf(source || {}).constructor;
@@ -558,6 +648,7 @@ var createModelClass = function (modelDefinition) {
558
648
  var parsedValue = castInstanceType(modelDefinition, k, v);
559
649
  modelValidator(k, parsedValue);
560
650
  });
651
+ normalize(modelDefinition, draft);
561
652
  }, function (p) { return (patches = p); });
562
653
  var hasExistingPatches = modelPatchesMap.has(source);
563
654
  if (patches.length || hasExistingPatches) {
@@ -572,6 +663,15 @@ var createModelClass = function (modelDefinition) {
572
663
  checkReadOnlyPropertyOnUpdate(patches, modelDefinition);
573
664
  }
574
665
  }
666
+ else {
667
+ // always register patches when performing a copyOf, even if the
668
+ // patches list is empty. this allows `save()` to recognize when an
669
+ // instance is the result of a `copyOf()`. without more significant
670
+ // refactoring, this is the only way for `save()` to know which
671
+ // diffs (patches) are relevant for `storage` to use in building
672
+ // the list of "changed" fields for mutations.
673
+ modelPatchesMap.set(model, [[], source]);
674
+ }
575
675
  return attached(model, ModelAttachment.DataStore);
576
676
  };
577
677
  // "private" method (that's hidden via `Setting`) for `withSSRContext` to use
@@ -593,67 +693,89 @@ var createModelClass = function (modelDefinition) {
593
693
  }());
594
694
  clazz[immerable] = true;
595
695
  Object.defineProperty(clazz, 'name', { value: modelDefinition.name });
596
- var _loop_1 = function (field) {
597
- if (!isFieldAssociation(modelDefinition, field)) {
598
- return "continue";
599
- }
600
- var _a = modelDefinition.fields[field], type = _a.type, localAssociation = _a.association, _b = _a.association, targetName = _b.targetName, targetNames = _b.targetNames;
601
- var relationship = new ModelRelationship({
602
- builder: clazz,
603
- schema: modelDefinition,
604
- pkField: extractPrimaryKeyFieldNames(modelDefinition),
605
- }, field);
696
+ // Add getters/setters for relationship fields.
697
+ // getter - for lazy loading
698
+ // setter - for FK management
699
+ var allModelRelationships = ModelRelationship.allFrom({
700
+ builder: clazz,
701
+ schema: modelDefinition,
702
+ pkField: extractPrimaryKeyFieldNames(modelDefinition),
703
+ });
704
+ var _loop_1 = function (relationship) {
705
+ var field = relationship.field;
606
706
  Object.defineProperty(clazz.prototype, modelDefinition.fields[field].name, {
607
707
  set: function (model) {
608
- if (!model || !(typeof model === 'object'))
708
+ if (!(typeof model === 'object' || typeof model === 'undefined'))
609
709
  return;
610
- // Avoid validation error when processing AppSync response with nested
611
- // selection set. Nested entitites lack version field and can not be validated
612
- // TODO: explore a more reliable method to solve this
613
- if (model.hasOwnProperty('_version')) {
614
- var modelConstructor = Object.getPrototypeOf(model || {})
615
- .constructor;
616
- if (!isValidModelConstructor(modelConstructor)) {
617
- var msg = "Value passed to " + modelDefinition.name + "." + field + " is not a valid instance of a model";
618
- logger.error(msg, { model: model });
619
- throw new Error(msg);
620
- }
621
- if (modelConstructor.name.toLowerCase() !==
622
- relationship.remoteModelConstructor.name.toLowerCase()) {
623
- var msg = "Value passed to " + modelDefinition.name + "." + field + " is not an instance of " + relationship.remoteModelConstructor.name;
624
- logger.error(msg, { model: model });
625
- throw new Error(msg);
710
+ // if model is undefined or null, the connection should be removed
711
+ if (model) {
712
+ // Avoid validation error when processing AppSync response with nested
713
+ // selection set. Nested entitites lack version field and can not be validated
714
+ // TODO: explore a more reliable method to solve this
715
+ if (model.hasOwnProperty('_version')) {
716
+ var modelConstructor = Object.getPrototypeOf(model || {})
717
+ .constructor;
718
+ if (!isValidModelConstructor(modelConstructor)) {
719
+ var msg = "Value passed to " + modelDefinition.name + "." + field + " is not a valid instance of a model";
720
+ logger.error(msg, { model: model });
721
+ throw new Error(msg);
722
+ }
723
+ if (modelConstructor.name.toLowerCase() !==
724
+ relationship.remoteModelConstructor.name.toLowerCase()) {
725
+ var msg = "Value passed to " + modelDefinition.name + "." + field + " is not an instance of " + relationship.remoteModelConstructor.name;
726
+ logger.error(msg, { model: model });
727
+ throw new Error(msg);
728
+ }
626
729
  }
627
730
  }
731
+ // if the relationship can be managed automagically, set the FK's
628
732
  if (relationship.isComplete) {
629
733
  for (var i = 0; i < relationship.localJoinFields.length; i++) {
630
- this[relationship.localJoinFields[i]] =
631
- model[relationship.remoteJoinFields[i]];
734
+ this[relationship.localJoinFields[i]] = model === null || model === void 0 ? void 0 : model[relationship.remoteJoinFields[i]];
632
735
  }
633
736
  var instanceMemos = modelInstanceAssociationsMap.has(this)
634
737
  ? modelInstanceAssociationsMap.get(this)
635
738
  : modelInstanceAssociationsMap.set(this, {}).get(this);
636
- instanceMemos[field] = model;
739
+ instanceMemos[field] = model || undefined;
637
740
  }
638
741
  },
639
742
  get: function () {
640
743
  var _this = this;
744
+ /**
745
+ * Bucket for holding related models instances specific to `this` instance.
746
+ */
641
747
  var instanceMemos = modelInstanceAssociationsMap.has(this)
642
748
  ? modelInstanceAssociationsMap.get(this)
643
749
  : modelInstanceAssociationsMap.set(this, {}).get(this);
750
+ // if the memos already has a result for this field, we'll use it.
751
+ // there is no "cache" invalidation of any kind; memos are permanent to
752
+ // keep an immutable perception of the instance.
644
753
  if (!instanceMemos.hasOwnProperty(field)) {
754
+ // before we populate the memo, we need to know where to look for relatives.
755
+ // today, this only supports DataStore. Models aren't managed elsewhere in Amplify.
645
756
  if (getAttachment(this) === ModelAttachment.DataStore) {
757
+ // when we fetch the results using a query constructed under the guidance
758
+ // of the relationship metadata, we DO NOT AWAIT resolution. we want to
759
+ // drop the promise into the memo's synchronously, eliminating the chance
760
+ // for a race.
646
761
  var resultPromise = instance.query(relationship.remoteModelConstructor, function (base) {
647
762
  return base.and(function (q) {
648
763
  return relationship.remoteJoinFields.map(function (field, index) {
764
+ // TODO: anything we can use instead of `any` here?
649
765
  return q[field].eq(_this[relationship.localJoinFields[index]]);
650
766
  });
651
767
  });
652
768
  });
769
+ // results in hand, how we return them to the caller depends on the relationship type.
653
770
  if (relationship.type === 'HAS_MANY') {
771
+ // collections should support async iteration, even though we don't
772
+ // leverage it fully [yet].
654
773
  instanceMemos[field] = new AsyncCollection(resultPromise);
655
774
  }
656
775
  else {
776
+ // non-collections should only ever return 1 value *or nothing*.
777
+ // if we have more than 1 record, something's amiss. it's not our job
778
+ // pick a result for the customer. it's our job to say "something's wrong."
657
779
  instanceMemos[field] = resultPromise.then(function (rows) {
658
780
  if (rows.length > 1) {
659
781
  // should never happen for a HAS_ONE or BELONGS_TO.
@@ -683,11 +805,24 @@ var createModelClass = function (modelDefinition) {
683
805
  },
684
806
  });
685
807
  };
686
- for (var field in modelDefinition.fields) {
687
- _loop_1(field);
808
+ try {
809
+ for (var allModelRelationships_1 = __values(allModelRelationships), allModelRelationships_1_1 = allModelRelationships_1.next(); !allModelRelationships_1_1.done; allModelRelationships_1_1 = allModelRelationships_1.next()) {
810
+ var relationship = allModelRelationships_1_1.value;
811
+ _loop_1(relationship);
812
+ }
813
+ }
814
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
815
+ finally {
816
+ try {
817
+ if (allModelRelationships_1_1 && !allModelRelationships_1_1.done && (_a = allModelRelationships_1.return)) _a.call(allModelRelationships_1);
818
+ }
819
+ finally { if (e_5) throw e_5.error; }
688
820
  }
689
821
  return clazz;
690
822
  };
823
+ /**
824
+ * An eventually loaded related model instance.
825
+ */
691
826
  var AsyncItem = /** @class */ (function (_super) {
692
827
  __extends(AsyncItem, _super);
693
828
  function AsyncItem() {
@@ -696,10 +831,26 @@ var AsyncItem = /** @class */ (function (_super) {
696
831
  return AsyncItem;
697
832
  }(Promise));
698
833
  export { AsyncItem };
834
+ /**
835
+ * A collection of related model instances.
836
+ *
837
+ * This collection can be async-iterated or turned directly into an array using `toArray()`.
838
+ */
699
839
  var AsyncCollection = /** @class */ (function () {
700
840
  function AsyncCollection(values) {
701
841
  this.values = values;
702
842
  }
843
+ /**
844
+ * Facilitates async iteration.
845
+ *
846
+ * ```ts
847
+ * for await (const item of collection) {
848
+ * handle(item)
849
+ * }
850
+ * ```
851
+ *
852
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of
853
+ */
703
854
  AsyncCollection.prototype[Symbol.asyncIterator] = function () {
704
855
  var _this = this;
705
856
  var values;
@@ -733,11 +884,19 @@ var AsyncCollection = /** @class */ (function () {
733
884
  }); },
734
885
  };
735
886
  };
887
+ /**
888
+ * Turns the collection into an array, up to the amount specified in `max` param.
889
+ *
890
+ * ```ts
891
+ * const all = await collection.toArray();
892
+ * const first100 = await collection.toArray({max: 100});
893
+ * ```
894
+ */
736
895
  AsyncCollection.prototype.toArray = function (_a) {
737
896
  var _b = (_a === void 0 ? {} : _a).max, max = _b === void 0 ? Number.MAX_SAFE_INTEGER : _b;
738
- var e_4, _c;
897
+ var e_6, _c;
739
898
  return __awaiter(this, void 0, void 0, function () {
740
- var output, i, _d, _e, element, e_4_1;
899
+ var output, i, _d, _e, element, e_6_1;
741
900
  return __generator(this, function (_f) {
742
901
  switch (_f.label) {
743
902
  case 0:
@@ -763,8 +922,8 @@ var AsyncCollection = /** @class */ (function () {
763
922
  case 4: return [3 /*break*/, 2];
764
923
  case 5: return [3 /*break*/, 12];
765
924
  case 6:
766
- e_4_1 = _f.sent();
767
- e_4 = { error: e_4_1 };
925
+ e_6_1 = _f.sent();
926
+ e_6 = { error: e_6_1 };
768
927
  return [3 /*break*/, 12];
769
928
  case 7:
770
929
  _f.trys.push([7, , 10, 11]);
@@ -775,7 +934,7 @@ var AsyncCollection = /** @class */ (function () {
775
934
  _f.label = 9;
776
935
  case 9: return [3 /*break*/, 11];
777
936
  case 10:
778
- if (e_4) throw e_4.error;
937
+ if (e_6) throw e_6.error;
779
938
  return [7 /*endfinally*/];
780
939
  case 11: return [7 /*endfinally*/];
781
940
  case 12: return [2 /*return*/, output];
@@ -885,8 +1044,8 @@ function checkSchemaVersion(storage, version) {
885
1044
  var _a, schemaVersionSetting, storedValue;
886
1045
  return __generator(this, function (_b) {
887
1046
  switch (_b.label) {
888
- case 0: return [4 /*yield*/, s.query(Setting, ModelPredicateCreator.createFromExisting(modelDefinition, function (c) {
889
- return c.key('eq', SETTING_SCHEMA_VERSION);
1047
+ case 0: return [4 /*yield*/, s.query(Setting, ModelPredicateCreator.createFromAST(modelDefinition, {
1048
+ and: { key: { eq: SETTING_SCHEMA_VERSION } },
890
1049
  }), { page: 0, limit: 1 })];
891
1050
  case 1:
892
1051
  _a = __read.apply(void 0, [_b.sent(), 1]), schemaVersionSetting = _a[0];
@@ -962,6 +1121,8 @@ var DataStoreState;
962
1121
  DataStoreState["Stopping"] = "Stopping";
963
1122
  DataStoreState["Clearing"] = "Clearing";
964
1123
  })(DataStoreState || (DataStoreState = {}));
1124
+ // TODO: How can we get rid of the non-null assertions?
1125
+ // https://github.com/aws-amplify/amplify-js/pull/10477/files#r1007363485
965
1126
  var DataStore = /** @class */ (function () {
966
1127
  function DataStore() {
967
1128
  var _this = this;
@@ -1025,8 +1186,8 @@ var DataStore = /** @class */ (function () {
1025
1186
  /**
1026
1187
  * If not already done:
1027
1188
  * 1. Attaches and initializes storage.
1028
- * 1. Loads the schema and records metadata.
1029
- * 1. If `this.amplifyConfig.aws_appsync_graphqlEndpoint` contains a URL,
1189
+ * 2. Loads the schema and records metadata.
1190
+ * 3. If `this.amplifyConfig.aws_appsync_graphqlEndpoint` contains a URL,
1030
1191
  * attaches a sync engine, starts it, and subscribes.
1031
1192
  */
1032
1193
  this.start = function () { return __awaiter(_this, void 0, void 0, function () {
@@ -1117,11 +1278,12 @@ var DataStore = /** @class */ (function () {
1117
1278
  .add(function () { return __awaiter(_this, void 0, void 0, function () {
1118
1279
  var result, msg, modelDefinition, pagination, keyFields, msg, predicate, predicate, seedPredicate, predicate, returnOne;
1119
1280
  var _a;
1120
- return __generator(this, function (_b) {
1121
- switch (_b.label) {
1281
+ var _b;
1282
+ return __generator(this, function (_c) {
1283
+ switch (_c.label) {
1122
1284
  case 0: return [4 /*yield*/, this.start()];
1123
1285
  case 1:
1124
- _b.sent();
1286
+ _c.sent();
1125
1287
  if (!this.storage) {
1126
1288
  throw new Error('No storage to query');
1127
1289
  }
@@ -1148,37 +1310,37 @@ var DataStore = /** @class */ (function () {
1148
1310
  logger.error(msg, { keyFields: keyFields });
1149
1311
  throw new Error(msg);
1150
1312
  }
1151
- predicate = ModelPredicateCreator.createForSingleField(modelDefinition, keyFields[0], identifierOrCriteria);
1313
+ predicate = ModelPredicateCreator.createFromFlatEqualities(modelDefinition, (_a = {}, _a[keyFields[0]] = identifierOrCriteria, _a));
1152
1314
  return [4 /*yield*/, this.storage.query(modelConstructor, predicate, pagination)];
1153
1315
  case 2:
1154
- result = _b.sent();
1316
+ result = _c.sent();
1155
1317
  return [3 /*break*/, 9];
1156
1318
  case 3:
1157
1319
  if (!isIdentifierObject(identifierOrCriteria, modelDefinition)) return [3 /*break*/, 5];
1158
1320
  predicate = ModelPredicateCreator.createForPk(modelDefinition, identifierOrCriteria);
1159
1321
  return [4 /*yield*/, this.storage.query(modelConstructor, predicate, pagination)];
1160
1322
  case 4:
1161
- result = _b.sent();
1323
+ result = _c.sent();
1162
1324
  return [3 /*break*/, 9];
1163
1325
  case 5:
1164
1326
  if (!(!identifierOrCriteria ||
1165
1327
  isPredicatesAll(identifierOrCriteria))) return [3 /*break*/, 7];
1166
- return [4 /*yield*/, ((_a = this.storage) === null || _a === void 0 ? void 0 : _a.query(modelConstructor, undefined, pagination))];
1328
+ return [4 /*yield*/, ((_b = this.storage) === null || _b === void 0 ? void 0 : _b.query(modelConstructor, undefined, pagination))];
1167
1329
  case 6:
1168
- result = _b.sent();
1330
+ result = _c.sent();
1169
1331
  return [3 /*break*/, 9];
1170
1332
  case 7:
1171
1333
  seedPredicate = recursivePredicateFor({
1172
1334
  builder: modelConstructor,
1173
1335
  schema: modelDefinition,
1174
- pkField: getModelPKFieldName(modelConstructor),
1336
+ pkField: extractPrimaryKeyFieldNames(modelDefinition),
1175
1337
  });
1176
1338
  predicate = internals(identifierOrCriteria(seedPredicate));
1177
1339
  return [4 /*yield*/, predicate.fetch(this.storage)];
1178
1340
  case 8:
1179
- result = (_b.sent());
1341
+ result = (_c.sent());
1180
1342
  result = inMemoryPagination(result, pagination);
1181
- _b.label = 9;
1343
+ _c.label = 9;
1182
1344
  case 9:
1183
1345
  returnOne = isQueryOne(identifierOrCriteria) ||
1184
1346
  isIdentifierObject(identifierOrCriteria, modelDefinition);
@@ -1194,7 +1356,7 @@ var DataStore = /** @class */ (function () {
1194
1356
  return __generator(this, function (_a) {
1195
1357
  return [2 /*return*/, this.runningProcesses
1196
1358
  .add(function () { return __awaiter(_this, void 0, void 0, function () {
1197
- var patchesTuple, modelConstructor, msg, modelDefinition, modelMeta, producedCondition, _a, savedModel;
1359
+ var updatedPatchesTuple, initPatchesTuple, patchesTuple, modelConstructor, msg, modelDefinition, modelMeta, producedCondition, _a, savedModel;
1198
1360
  var _this = this;
1199
1361
  return __generator(this, function (_b) {
1200
1362
  switch (_b.label) {
@@ -1204,7 +1366,11 @@ var DataStore = /** @class */ (function () {
1204
1366
  if (!this.storage) {
1205
1367
  throw new Error('No storage to save to');
1206
1368
  }
1207
- patchesTuple = modelPatchesMap.get(model);
1369
+ updatedPatchesTuple = modelPatchesMap.get(model);
1370
+ initPatchesTuple = initPatches.has(model)
1371
+ ? [initPatches.get(model), {}]
1372
+ : undefined;
1373
+ patchesTuple = updatedPatchesTuple || initPatchesTuple;
1208
1374
  modelConstructor = model ? model.constructor : undefined;
1209
1375
  if (!isValidModelConstructor(modelConstructor)) {
1210
1376
  msg = 'Object is not an instance of a valid model';
@@ -1221,8 +1387,8 @@ var DataStore = /** @class */ (function () {
1221
1387
  pkField: extractPrimaryKeyFieldNames(modelDefinition),
1222
1388
  };
1223
1389
  return [4 /*yield*/, this.storage.runExclusive(function (s) { return __awaiter(_this, void 0, void 0, function () {
1224
- var nonHasManyRelationships, nonHasManyRelationships_1, nonHasManyRelationships_1_1, relationship, queryObject, related, e_5_1;
1225
- var e_5, _a;
1390
+ var nonHasManyRelationships, nonHasManyRelationships_1, nonHasManyRelationships_1_1, relationship, queryObject, related, e_7_1;
1391
+ var e_7, _a;
1226
1392
  var _b;
1227
1393
  return __generator(this, function (_c) {
1228
1394
  switch (_c.label) {
@@ -1255,14 +1421,14 @@ var DataStore = /** @class */ (function () {
1255
1421
  return [3 /*break*/, 2];
1256
1422
  case 5: return [3 /*break*/, 8];
1257
1423
  case 6:
1258
- e_5_1 = _c.sent();
1259
- e_5 = { error: e_5_1 };
1424
+ e_7_1 = _c.sent();
1425
+ e_7 = { error: e_7_1 };
1260
1426
  return [3 /*break*/, 8];
1261
1427
  case 7:
1262
1428
  try {
1263
1429
  if (nonHasManyRelationships_1_1 && !nonHasManyRelationships_1_1.done && (_a = nonHasManyRelationships_1.return)) _a.call(nonHasManyRelationships_1);
1264
1430
  }
1265
- finally { if (e_5) throw e_5.error; }
1431
+ finally { if (e_7) throw e_7.error; }
1266
1432
  return [7 /*endfinally*/];
1267
1433
  case 8: return [2 /*return*/];
1268
1434
  }
@@ -1325,11 +1491,12 @@ var DataStore = /** @class */ (function () {
1325
1491
  return [2 /*return*/, this.runningProcesses
1326
1492
  .add(function () { return __awaiter(_this, void 0, void 0, function () {
1327
1493
  var condition, msg, modelConstructor, msg, modelDefinition, keyFields, msg, msg, _a, deleted, model, modelConstructor, msg, modelDefinition, pkPredicate, msg, _b, _c, deleted;
1328
- return __generator(this, function (_d) {
1329
- switch (_d.label) {
1494
+ var _d;
1495
+ return __generator(this, function (_e) {
1496
+ switch (_e.label) {
1330
1497
  case 0: return [4 /*yield*/, this.start()];
1331
1498
  case 1:
1332
- _d.sent();
1499
+ _e.sent();
1333
1500
  if (!this.storage) {
1334
1501
  throw new Error('No storage to delete from');
1335
1502
  }
@@ -1356,7 +1523,7 @@ var DataStore = /** @class */ (function () {
1356
1523
  logger.error(msg, { keyFields: keyFields });
1357
1524
  throw new Error(msg);
1358
1525
  }
1359
- condition = ModelPredicateCreator.createForSingleField(modelDefinition, keyFields[0], identifierOrCriteria);
1526
+ condition = ModelPredicateCreator.createFromFlatEqualities(modelDefinition, (_d = {}, _d[keyFields[0]] = identifierOrCriteria, _d));
1360
1527
  }
1361
1528
  else {
1362
1529
  if (isIdentifierObject(identifierOrCriteria, modelDefinition)) {
@@ -1378,7 +1545,7 @@ var DataStore = /** @class */ (function () {
1378
1545
  }
1379
1546
  return [4 /*yield*/, this.storage.delete(modelConstructor, condition)];
1380
1547
  case 2:
1381
- _a = __read.apply(void 0, [_d.sent(), 1]), deleted = _a[0];
1548
+ _a = __read.apply(void 0, [_e.sent(), 1]), deleted = _a[0];
1382
1549
  return [2 /*return*/, attached(deleted, ModelAttachment.DataStore)];
1383
1550
  case 3:
1384
1551
  model = modelOrConstructor;
@@ -1404,14 +1571,14 @@ var DataStore = /** @class */ (function () {
1404
1571
  builder: modelConstructor,
1405
1572
  schema: modelDefinition,
1406
1573
  pkField: extractPrimaryKeyFieldNames(modelDefinition),
1407
- }))).toStoragePredicate(pkPredicate);
1574
+ }))).toStoragePredicate();
1408
1575
  }
1409
1576
  else {
1410
1577
  condition = pkPredicate;
1411
1578
  }
1412
1579
  return [4 /*yield*/, this.storage.delete(model, condition)];
1413
1580
  case 4:
1414
- _b = __read.apply(void 0, [_d.sent(), 1]), _c = __read(_b[0], 1), deleted = _c[0];
1581
+ _b = __read.apply(void 0, [_e.sent(), 1]), _c = __read(_b[0], 1), deleted = _c[0];
1415
1582
  return [2 /*return*/, attached(deleted, ModelAttachment.DataStore)];
1416
1583
  }
1417
1584
  });
@@ -1683,9 +1850,6 @@ var DataStore = /** @class */ (function () {
1683
1850
  var _a, _b;
1684
1851
  var isSynced = (_b = (_a = _this.sync) === null || _a === void 0 ? void 0 : _a.getModelSyncedStatus(model)) !== null && _b !== void 0 ? _b : false;
1685
1852
  var itemsArray = __spread(Array.from(items.values()), Array.from(itemsChanged.values()));
1686
- if (options === null || options === void 0 ? void 0 : options.sort) {
1687
- sortItems(itemsArray);
1688
- }
1689
1853
  items.clear();
1690
1854
  itemsArray.forEach(function (item) {
1691
1855
  var itemModelDefinition = getModelDefinition(model);
@@ -1694,8 +1858,14 @@ var DataStore = /** @class */ (function () {
1694
1858
  });
1695
1859
  // remove deleted items from the final result set
1696
1860
  deletedItemIds.forEach(function (idOrPk) { return items.delete(idOrPk); });
1861
+ var snapshot = Array.from(items.values());
1862
+ // we sort after we merge the snapshots (items, itemsChanged)
1863
+ // otherwise, the merge may not
1864
+ if (options === null || options === void 0 ? void 0 : options.sort) {
1865
+ sortItems(snapshot);
1866
+ }
1697
1867
  return {
1698
- items: Array.from(items.values()),
1868
+ items: snapshot,
1699
1869
  isSynced: isSynced,
1700
1870
  };
1701
1871
  };
@@ -2019,15 +2189,6 @@ var DataStore = /** @class */ (function () {
2019
2189
  });
2020
2190
  });
2021
2191
  };
2022
- DataStore.prototype.createFromCondition = function (modelDefinition, condition) {
2023
- try {
2024
- return ModelPredicateCreator.createFromExisting(modelDefinition, condition);
2025
- }
2026
- catch (error) {
2027
- logger.error('Error creating Sync Predicate');
2028
- throw error;
2029
- }
2030
- };
2031
2192
  DataStore.prototype.unwrapPromise = function (conditionProducer) {
2032
2193
  return __awaiter(this, void 0, void 0, function () {
2033
2194
  var condition, error_1;