@aws-amplify/datastore 3.7.3 → 3.7.4-custom-pk.86

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 (137) hide show
  1. package/CHANGELOG.md +144 -17
  2. package/README.md +154 -0
  3. package/dist/aws-amplify-datastore.js +3740 -1599
  4. package/dist/aws-amplify-datastore.js.map +1 -1
  5. package/dist/aws-amplify-datastore.min.js +25 -95
  6. package/dist/aws-amplify-datastore.min.js.map +1 -1
  7. package/lib/authModeStrategies/multiAuthStrategy.d.ts +2 -2
  8. package/lib/authModeStrategies/multiAuthStrategy.js +32 -26
  9. package/lib/authModeStrategies/multiAuthStrategy.js.map +1 -1
  10. package/lib/datastore/datastore.d.ts +17 -16
  11. package/lib/datastore/datastore.js +291 -83
  12. package/lib/datastore/datastore.js.map +1 -1
  13. package/lib/index.d.ts +3 -19
  14. package/lib/predicates/index.d.ts +3 -2
  15. package/lib/predicates/index.js +12 -2
  16. package/lib/predicates/index.js.map +1 -1
  17. package/lib/storage/adapter/AsyncStorageAdapter.d.ts +6 -2
  18. package/lib/storage/adapter/AsyncStorageAdapter.js +361 -193
  19. package/lib/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  20. package/lib/storage/adapter/AsyncStorageDatabase.d.ts +4 -4
  21. package/lib/storage/adapter/AsyncStorageDatabase.js +59 -28
  22. package/lib/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  23. package/lib/storage/adapter/InMemoryStore.js +2 -2
  24. package/lib/storage/adapter/InMemoryStore.js.map +1 -1
  25. package/lib/storage/adapter/IndexedDBAdapter.d.ts +7 -2
  26. package/lib/storage/adapter/IndexedDBAdapter.js +454 -252
  27. package/lib/storage/adapter/IndexedDBAdapter.js.map +1 -1
  28. package/lib/storage/adapter/index.d.ts +1 -1
  29. package/lib/storage/storage.d.ts +3 -3
  30. package/lib/storage/storage.js +106 -28
  31. package/lib/storage/storage.js.map +1 -1
  32. package/lib/sync/index.d.ts +23 -7
  33. package/lib/sync/index.js +18 -17
  34. package/lib/sync/index.js.map +1 -1
  35. package/lib/sync/merger.d.ts +3 -3
  36. package/lib/sync/merger.js +8 -6
  37. package/lib/sync/merger.js.map +1 -1
  38. package/lib/sync/outbox.d.ts +2 -2
  39. package/lib/sync/outbox.js +12 -9
  40. package/lib/sync/outbox.js.map +1 -1
  41. package/lib/sync/processors/errorMaps.d.ts +17 -0
  42. package/lib/sync/processors/errorMaps.js +125 -0
  43. package/lib/sync/processors/errorMaps.js.map +1 -0
  44. package/lib/sync/processors/mutation.d.ts +22 -4
  45. package/lib/sync/processors/mutation.js +119 -51
  46. package/lib/sync/processors/mutation.js.map +1 -1
  47. package/lib/sync/processors/subscription.d.ts +4 -2
  48. package/lib/sync/processors/subscription.js +76 -41
  49. package/lib/sync/processors/subscription.js.map +1 -1
  50. package/lib/sync/processors/sync.d.ts +4 -2
  51. package/lib/sync/processors/sync.js +62 -27
  52. package/lib/sync/processors/sync.js.map +1 -1
  53. package/lib/sync/utils.d.ts +3 -2
  54. package/lib/sync/utils.js +58 -7
  55. package/lib/sync/utils.js.map +1 -1
  56. package/lib/types.d.ts +90 -34
  57. package/lib/types.js +31 -2
  58. package/lib/types.js.map +1 -1
  59. package/lib/util.d.ts +48 -33
  60. package/lib/util.js +219 -57
  61. package/lib/util.js.map +1 -1
  62. package/lib-esm/authModeStrategies/multiAuthStrategy.d.ts +2 -2
  63. package/lib-esm/authModeStrategies/multiAuthStrategy.js +32 -26
  64. package/lib-esm/authModeStrategies/multiAuthStrategy.js.map +1 -1
  65. package/lib-esm/datastore/datastore.d.ts +17 -16
  66. package/lib-esm/datastore/datastore.js +293 -85
  67. package/lib-esm/datastore/datastore.js.map +1 -1
  68. package/lib-esm/index.d.ts +3 -19
  69. package/lib-esm/predicates/index.d.ts +3 -2
  70. package/lib-esm/predicates/index.js +13 -3
  71. package/lib-esm/predicates/index.js.map +1 -1
  72. package/lib-esm/storage/adapter/AsyncStorageAdapter.d.ts +6 -2
  73. package/lib-esm/storage/adapter/AsyncStorageAdapter.js +361 -193
  74. package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  75. package/lib-esm/storage/adapter/AsyncStorageDatabase.d.ts +4 -4
  76. package/lib-esm/storage/adapter/AsyncStorageDatabase.js +60 -29
  77. package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  78. package/lib-esm/storage/adapter/InMemoryStore.js +2 -2
  79. package/lib-esm/storage/adapter/InMemoryStore.js.map +1 -1
  80. package/lib-esm/storage/adapter/IndexedDBAdapter.d.ts +7 -2
  81. package/lib-esm/storage/adapter/IndexedDBAdapter.js +454 -252
  82. package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +1 -1
  83. package/lib-esm/storage/adapter/index.d.ts +1 -1
  84. package/lib-esm/storage/storage.d.ts +3 -3
  85. package/lib-esm/storage/storage.js +106 -28
  86. package/lib-esm/storage/storage.js.map +1 -1
  87. package/lib-esm/sync/index.d.ts +23 -7
  88. package/lib-esm/sync/index.js +20 -19
  89. package/lib-esm/sync/index.js.map +1 -1
  90. package/lib-esm/sync/merger.d.ts +3 -3
  91. package/lib-esm/sync/merger.js +8 -6
  92. package/lib-esm/sync/merger.js.map +1 -1
  93. package/lib-esm/sync/outbox.d.ts +2 -2
  94. package/lib-esm/sync/outbox.js +13 -10
  95. package/lib-esm/sync/outbox.js.map +1 -1
  96. package/lib-esm/sync/processors/errorMaps.d.ts +17 -0
  97. package/lib-esm/sync/processors/errorMaps.js +119 -0
  98. package/lib-esm/sync/processors/errorMaps.js.map +1 -0
  99. package/lib-esm/sync/processors/mutation.d.ts +22 -4
  100. package/lib-esm/sync/processors/mutation.js +122 -54
  101. package/lib-esm/sync/processors/mutation.js.map +1 -1
  102. package/lib-esm/sync/processors/subscription.d.ts +4 -2
  103. package/lib-esm/sync/processors/subscription.js +77 -42
  104. package/lib-esm/sync/processors/subscription.js.map +1 -1
  105. package/lib-esm/sync/processors/sync.d.ts +4 -2
  106. package/lib-esm/sync/processors/sync.js +62 -27
  107. package/lib-esm/sync/processors/sync.js.map +1 -1
  108. package/lib-esm/sync/utils.d.ts +3 -2
  109. package/lib-esm/sync/utils.js +58 -8
  110. package/lib-esm/sync/utils.js.map +1 -1
  111. package/lib-esm/types.d.ts +90 -34
  112. package/lib-esm/types.js +29 -3
  113. package/lib-esm/types.js.map +1 -1
  114. package/lib-esm/util.d.ts +48 -33
  115. package/lib-esm/util.js +207 -54
  116. package/lib-esm/util.js.map +1 -1
  117. package/package.json +10 -9
  118. package/src/authModeStrategies/multiAuthStrategy.ts +24 -21
  119. package/src/datastore/datastore.ts +448 -148
  120. package/src/predicates/index.ts +32 -10
  121. package/src/storage/adapter/AsyncStorageAdapter.ts +305 -78
  122. package/src/storage/adapter/AsyncStorageDatabase.ts +65 -26
  123. package/src/storage/adapter/InMemoryStore.ts +2 -2
  124. package/src/storage/adapter/IndexedDBAdapter.ts +344 -101
  125. package/src/storage/adapter/index.ts +1 -1
  126. package/src/storage/storage.ts +85 -24
  127. package/src/sync/index.ts +74 -58
  128. package/src/sync/merger.ts +16 -4
  129. package/src/sync/outbox.ts +22 -8
  130. package/src/sync/processors/errorMaps.ts +93 -0
  131. package/src/sync/processors/mutation.ts +143 -84
  132. package/src/sync/processors/subscription.ts +67 -36
  133. package/src/sync/processors/sync.ts +37 -12
  134. package/src/sync/utils.ts +67 -16
  135. package/src/types.ts +252 -50
  136. package/src/util.ts +256 -42
  137. package/ssr/package.json +1 -1
@@ -92,7 +92,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
92
92
  return (mod && mod.__esModule) ? mod : { "default": mod };
93
93
  };
94
94
  Object.defineProperty(exports, "__esModule", { value: true });
95
+ var api_1 = __importDefault(require("@aws-amplify/api"));
95
96
  var core_1 = require("@aws-amplify/core");
97
+ var auth_1 = require("@aws-amplify/auth");
98
+ var cache_1 = __importDefault(require("@aws-amplify/cache"));
96
99
  var immer_1 = require("immer");
97
100
  var uuid_1 = require("uuid");
98
101
  var zen_observable_ts_1 = __importDefault(require("zen-observable-ts"));
@@ -102,6 +105,7 @@ var storage_1 = require("../storage/storage");
102
105
  var sync_1 = require("../sync");
103
106
  var types_1 = require("../types");
104
107
  var util_1 = require("../util");
108
+ var utils_1 = require("../sync/utils");
105
109
  immer_1.setAutoFreeze(true);
106
110
  immer_1.enablePatches();
107
111
  var logger = new core_1.ConsoleLogger('DataStore');
@@ -205,6 +209,18 @@ var initSchema = function (userSchema) {
205
209
  return userClasses;
206
210
  };
207
211
  exports.initSchema = initSchema;
212
+ /* Checks if the schema has been initialized by initSchema().
213
+ *
214
+ * Call this function before accessing schema.
215
+ * Currently this only needs to be called in start() and clear() because all other functions will call start first.
216
+ */
217
+ var checkSchemaInitialized = function () {
218
+ if (schema === undefined) {
219
+ var 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';
220
+ logger.error(message);
221
+ throw new Error(message);
222
+ }
223
+ };
208
224
  var createTypeClasses = function (namespace) {
209
225
  var classes = {};
210
226
  Object.entries(namespace.models).forEach(function (_a) {
@@ -225,6 +241,9 @@ function modelInstanceCreator(modelConstructor, init) {
225
241
  instancesMetadata.add(init);
226
242
  return new modelConstructor(init);
227
243
  }
244
+ function isSchemaModel(m) {
245
+ return m.attributes !== undefined;
246
+ }
228
247
  var validateModelFields = function (modelDefinition) { return function (k, v) {
229
248
  var fieldDefinition = modelDefinition.fields[k];
230
249
  if (fieldDefinition !== undefined) {
@@ -233,6 +252,13 @@ var validateModelFields = function (modelDefinition) { return function (k, v) {
233
252
  (v === null || v === undefined)) {
234
253
  throw new Error("Field " + name_1 + " is required");
235
254
  }
255
+ if (isSchemaModel(modelDefinition) && !util_1.isIdManaged(modelDefinition)) {
256
+ var keys = util_1.extractPrimaryKeyFieldNames(modelDefinition);
257
+ if (keys.includes(k) && v === '') {
258
+ logger.error(util_1.errorMessages.idEmptyString, { k: k, value: v });
259
+ throw new Error(util_1.errorMessages.idEmptyString);
260
+ }
261
+ }
236
262
  if (types_1.isGraphQLScalarType(type)) {
237
263
  var jsType_1 = types_1.GraphQLScalarType.getJSType(type);
238
264
  var validateScalar_1 = types_1.GraphQLScalarType.getValidationFunction(type);
@@ -333,21 +359,29 @@ var createModelClass = function (modelDefinition) {
333
359
  function Model(init) {
334
360
  var instance = immer_1.produce(this, function (draft) {
335
361
  initializeInstance(init, modelDefinition, draft);
336
- var modelInstanceMetadata = instancesMetadata.has(init)
362
+ // model is initialized inside a DataStore component (e.g. by Sync Engine, Storage Engine, etc.)
363
+ var isInternallyInitialized = instancesMetadata.has(init);
364
+ var modelInstanceMetadata = isInternallyInitialized
337
365
  ? init
338
366
  : {};
339
- var _id = modelInstanceMetadata.id, _version = modelInstanceMetadata._version, _lastChangedAt = modelInstanceMetadata._lastChangedAt, _deleted = modelInstanceMetadata._deleted;
340
- // instancesIds are set by modelInstanceCreator, it is accessible only internally
341
- var isInternal = _id !== null && _id !== undefined;
342
- var id = isInternal
343
- ? _id
344
- : modelDefinition.syncable
345
- ? uuid_1.v4()
346
- : ulid();
347
- if (!isInternal) {
367
+ var _id = modelInstanceMetadata.id;
368
+ if (util_1.isIdManaged(modelDefinition)) {
369
+ var isInternalModel = _id !== null && _id !== undefined;
370
+ var id = isInternalModel
371
+ ? _id
372
+ : modelDefinition.syncable
373
+ ? uuid_1.v4()
374
+ : ulid();
375
+ draft.id = id;
376
+ }
377
+ else if (util_1.isIdOptionallyManaged(modelDefinition)) {
378
+ // only auto-populate if the id was not provided
379
+ draft.id = draft.id || uuid_1.v4();
380
+ }
381
+ if (!isInternallyInitialized) {
348
382
  checkReadOnlyPropertyOnCreate(draft, modelDefinition);
349
383
  }
350
- draft.id = id;
384
+ var _version = modelInstanceMetadata._version, _lastChangedAt = modelInstanceMetadata._lastChangedAt, _deleted = modelInstanceMetadata._deleted;
351
385
  if (modelDefinition.syncable) {
352
386
  draft._version = _version;
353
387
  draft._lastChangedAt = _lastChangedAt;
@@ -366,7 +400,10 @@ var createModelClass = function (modelDefinition) {
366
400
  var patches;
367
401
  var model = immer_1.produce(source, function (draft) {
368
402
  fn(draft);
369
- draft.id = source.id;
403
+ var keyNames = util_1.extractPrimaryKeyFieldNames(modelDefinition);
404
+ // Keys are immutable
405
+ // @ts-ignore TODO: fix type
406
+ keyNames.forEach(function (key) { return (draft[key] = source[key]); });
370
407
  var modelValidator = validateModelFields(modelDefinition);
371
408
  Object.entries(draft).forEach(function (_a) {
372
409
  var _b = __read(_a, 2), k = _b[0], v = _b[1];
@@ -374,9 +411,18 @@ var createModelClass = function (modelDefinition) {
374
411
  modelValidator(k, parsedValue);
375
412
  });
376
413
  }, function (p) { return (patches = p); });
377
- if (patches.length) {
378
- modelPatchesMap.set(model, [patches, source]);
379
- checkReadOnlyPropertyOnUpdate(patches, modelDefinition);
414
+ var hasExistingPatches = modelPatchesMap.has(source);
415
+ if (patches.length || hasExistingPatches) {
416
+ if (hasExistingPatches) {
417
+ var _a = __read(modelPatchesMap.get(source), 2), existingPatches = _a[0], existingSource = _a[1];
418
+ var mergedPatches = util_1.mergePatches(existingSource, existingPatches, patches);
419
+ modelPatchesMap.set(model, [mergedPatches, existingSource]);
420
+ checkReadOnlyPropertyOnUpdate(mergedPatches, modelDefinition);
421
+ }
422
+ else {
423
+ modelPatchesMap.set(model, [patches, source]);
424
+ checkReadOnlyPropertyOnUpdate(patches, modelDefinition);
425
+ }
380
426
  }
381
427
  return model;
382
428
  };
@@ -490,7 +536,6 @@ function checkSchemaVersion(storage, version) {
490
536
  return __generator(this, function (_b) {
491
537
  switch (_b.label) {
492
538
  case 0: return [4 /*yield*/, s.query(Setting, predicates_1.ModelPredicateCreator.createFromExisting(modelDefinition, function (c) {
493
- // @ts-ignore Argument of type '"eq"' is not assignable to parameter of type 'never'.
494
539
  return c.key('eq', SETTING_SCHEMA_VERSION);
495
540
  }), { page: 0, limit: 1 })];
496
541
  case 1:
@@ -562,8 +607,18 @@ function getNamespace() {
562
607
  var DataStore = /** @class */ (function () {
563
608
  function DataStore() {
564
609
  var _this = this;
610
+ // reference to configured category instances. Used for preserving SSR context
611
+ this.Auth = auth_1.Auth;
612
+ this.API = api_1.default;
613
+ this.Cache = cache_1.default;
565
614
  this.amplifyConfig = {};
566
615
  this.syncPredicates = new WeakMap();
616
+ // object that gets passed to descendent classes. Allows us to pass these down by reference
617
+ this.amplifyContext = {
618
+ Auth: this.Auth,
619
+ API: this.API,
620
+ Cache: this.Cache,
621
+ };
567
622
  this.start = function () { return __awaiter(_this, void 0, void 0, function () {
568
623
  var aws_appsync_graphqlEndpoint, _a, fullSyncIntervalInMilliseconds;
569
624
  var _this = this;
@@ -586,6 +641,7 @@ var DataStore = /** @class */ (function () {
586
641
  return [4 /*yield*/, this.storage.init()];
587
642
  case 4:
588
643
  _b.sent();
644
+ checkSchemaInitialized();
589
645
  return [4 /*yield*/, checkSchemaVersion(this.storage, schema.version)];
590
646
  case 5:
591
647
  _b.sent();
@@ -596,7 +652,7 @@ var DataStore = /** @class */ (function () {
596
652
  return [4 /*yield*/, this.processSyncExpressions()];
597
653
  case 6:
598
654
  _a.syncPredicates = _b.sent();
599
- this.sync = new sync_1.SyncEngine(schema, namespaceResolver, exports.syncClasses, userClasses, this.storage, modelInstanceCreator, this.maxRecordsToSync, this.syncPageSize, this.conflictHandler, this.errorHandler, this.syncPredicates, this.amplifyConfig, this.authModeStrategy);
655
+ this.sync = new sync_1.SyncEngine(schema, namespaceResolver, exports.syncClasses, userClasses, this.storage, modelInstanceCreator, this.conflictHandler, this.errorHandler, this.syncPredicates, this.amplifyConfig, this.authModeStrategy, this.amplifyContext);
600
656
  fullSyncIntervalInMilliseconds = this.fullSyncInterval * 1000 * 60;
601
657
  syncSubscription = this.sync
602
658
  .start({ fullSyncInterval: fullSyncIntervalInMilliseconds })
@@ -635,8 +691,8 @@ var DataStore = /** @class */ (function () {
635
691
  }
636
692
  });
637
693
  }); };
638
- this.query = function (modelConstructor, idOrCriteria, paginationProducer) { return __awaiter(_this, void 0, void 0, function () {
639
- var msg, modelDefinition, predicate, pagination, result;
694
+ this.query = function (modelConstructor, identifierOrCriteria, paginationProducer) { return __awaiter(_this, void 0, void 0, function () {
695
+ var msg, modelDefinition, keyFields, predicate, pagination, result, isSingleFieldIdentifier, returnOne;
640
696
  return __generator(this, function (_a) {
641
697
  switch (_a.label) {
642
698
  case 0: return [4 /*yield*/, this.start()];
@@ -648,22 +704,27 @@ var DataStore = /** @class */ (function () {
648
704
  logger.error(msg, { modelConstructor: modelConstructor });
649
705
  throw new Error(msg);
650
706
  }
651
- if (typeof idOrCriteria === 'string') {
707
+ if (typeof identifierOrCriteria === 'string') {
652
708
  if (paginationProducer !== undefined) {
653
709
  logger.warn('Pagination is ignored when querying by id');
654
710
  }
655
711
  }
656
712
  modelDefinition = getModelDefinition(modelConstructor);
657
- if (isQueryOne(idOrCriteria)) {
658
- predicate = predicates_1.ModelPredicateCreator.createForId(modelDefinition, idOrCriteria);
713
+ keyFields = util_1.extractPrimaryKeyFieldNames(modelDefinition);
714
+ if (isQueryOne(identifierOrCriteria)) {
715
+ predicate = predicates_1.ModelPredicateCreator.createForSingleField(modelDefinition, keyFields[0], identifierOrCriteria);
659
716
  }
660
717
  else {
661
- if (predicates_1.isPredicatesAll(idOrCriteria)) {
718
+ // Object is being queried using object literal syntax
719
+ if (types_1.isIdentifierObject(identifierOrCriteria, modelDefinition)) {
720
+ predicate = predicates_1.ModelPredicateCreator.createForPk(modelDefinition, identifierOrCriteria);
721
+ }
722
+ else if (predicates_1.isPredicatesAll(identifierOrCriteria)) {
662
723
  // Predicates.ALL means "all records", so no predicate (undefined)
663
724
  predicate = undefined;
664
725
  }
665
726
  else {
666
- predicate = predicates_1.ModelPredicateCreator.createFromExisting(modelDefinition, idOrCriteria);
727
+ predicate = predicates_1.ModelPredicateCreator.createFromExisting(modelDefinition, identifierOrCriteria);
667
728
  }
668
729
  }
669
730
  pagination = this.processPagination(modelDefinition, paginationProducer);
@@ -676,7 +737,11 @@ var DataStore = /** @class */ (function () {
676
737
  return [4 /*yield*/, this.storage.query(modelConstructor, predicate, pagination)];
677
738
  case 2:
678
739
  result = _a.sent();
679
- return [2 /*return*/, isQueryOne(idOrCriteria) ? result[0] : result];
740
+ isSingleFieldIdentifier = keyFields.length === 1;
741
+ returnOne = isSingleFieldIdentifier &&
742
+ (isQueryOne(identifierOrCriteria) ||
743
+ types_1.isIdentifierObject(identifierOrCriteria, modelDefinition));
744
+ return [2 /*return*/, returnOne ? result[0] : result];
680
745
  }
681
746
  });
682
747
  }); };
@@ -705,7 +770,7 @@ var DataStore = /** @class */ (function () {
705
770
  case 0: return [4 /*yield*/, s.save(model, producedCondition, undefined, patchesTuple)];
706
771
  case 1:
707
772
  _a.sent();
708
- return [2 /*return*/, s.query(modelConstructor, predicates_1.ModelPredicateCreator.createForId(modelDefinition, model.id))];
773
+ return [2 /*return*/, s.query(modelConstructor, predicates_1.ModelPredicateCreator.createForPk(modelDefinition, model))];
709
774
  }
710
775
  });
711
776
  }); })];
@@ -741,13 +806,13 @@ var DataStore = /** @class */ (function () {
741
806
  }
742
807
  return _this.errorHandler || defaultErrorHandler;
743
808
  };
744
- this.delete = function (modelOrConstructor, idOrCriteria) { return __awaiter(_this, void 0, void 0, function () {
745
- var condition, msg, modelConstructor, msg, msg, _a, deleted, model, modelConstructor, msg, modelDefinition, idPredicate, msg, _b, _c, deleted;
746
- return __generator(this, function (_d) {
747
- switch (_d.label) {
809
+ this.delete = function (modelOrConstructor, identifierOrCriteria) { return __awaiter(_this, void 0, void 0, function () {
810
+ var condition, msg, modelConstructor, msg, modelDefinition, _a, keyField, msg, _b, deleted, model, modelConstructor, msg, modelDefinition, pkPredicate, msg, _c, _d, deleted;
811
+ return __generator(this, function (_e) {
812
+ switch (_e.label) {
748
813
  case 0: return [4 /*yield*/, this.start()];
749
814
  case 1:
750
- _d.sent();
815
+ _e.sent();
751
816
  if (!modelOrConstructor) {
752
817
  msg = 'Model or Model Constructor required';
753
818
  logger.error(msg, { modelOrConstructor: modelOrConstructor });
@@ -755,21 +820,28 @@ var DataStore = /** @class */ (function () {
755
820
  }
756
821
  if (!isValidModelConstructor(modelOrConstructor)) return [3 /*break*/, 3];
757
822
  modelConstructor = modelOrConstructor;
758
- if (!idOrCriteria) {
823
+ if (!identifierOrCriteria) {
759
824
  msg = 'Id to delete or criteria required. Do you want to delete all? Pass Predicates.ALL';
760
- logger.error(msg, { idOrCriteria: idOrCriteria });
825
+ logger.error(msg, { identifierOrCriteria: identifierOrCriteria });
761
826
  throw new Error(msg);
762
827
  }
763
- if (typeof idOrCriteria === 'string') {
764
- condition = predicates_1.ModelPredicateCreator.createForId(getModelDefinition(modelConstructor), idOrCriteria);
828
+ modelDefinition = getModelDefinition(modelConstructor);
829
+ if (typeof identifierOrCriteria === 'string') {
830
+ _a = __read(util_1.extractPrimaryKeyFieldNames(modelDefinition), 1), keyField = _a[0];
831
+ condition = predicates_1.ModelPredicateCreator.createForSingleField(getModelDefinition(modelConstructor), keyField, identifierOrCriteria);
765
832
  }
766
833
  else {
767
- condition = predicates_1.ModelPredicateCreator.createFromExisting(getModelDefinition(modelConstructor),
768
- /**
769
- * idOrCriteria is always a ProducerModelPredicate<T>, never a symbol.
770
- * The symbol is used only for typing purposes. e.g. see Predicates.ALL
771
- */
772
- idOrCriteria);
834
+ if (types_1.isIdentifierObject(identifierOrCriteria, modelDefinition)) {
835
+ condition = predicates_1.ModelPredicateCreator.createForPk(modelDefinition, identifierOrCriteria);
836
+ }
837
+ else {
838
+ condition = predicates_1.ModelPredicateCreator.createFromExisting(modelDefinition,
839
+ /**
840
+ * idOrCriteria is always a ProducerModelPredicate<T>, never a symbol.
841
+ * The symbol is used only for typing purposes. e.g. see Predicates.ALL
842
+ */
843
+ identifierOrCriteria);
844
+ }
773
845
  if (!condition || !predicates_1.ModelPredicateCreator.isValidPredicate(condition)) {
774
846
  msg = 'Criteria required. Do you want to delete all? Pass Predicates.ALL';
775
847
  logger.error(msg, { condition: condition });
@@ -778,7 +850,7 @@ var DataStore = /** @class */ (function () {
778
850
  }
779
851
  return [4 /*yield*/, this.storage.delete(modelConstructor, condition)];
780
852
  case 2:
781
- _a = __read.apply(void 0, [_d.sent(), 1]), deleted = _a[0];
853
+ _b = __read.apply(void 0, [_e.sent(), 1]), deleted = _b[0];
782
854
  return [2 /*return*/, deleted];
783
855
  case 3:
784
856
  model = modelOrConstructor;
@@ -790,26 +862,26 @@ var DataStore = /** @class */ (function () {
790
862
  throw new Error(msg);
791
863
  }
792
864
  modelDefinition = getModelDefinition(modelConstructor);
793
- idPredicate = predicates_1.ModelPredicateCreator.createForId(modelDefinition, model.id);
794
- if (idOrCriteria) {
795
- if (typeof idOrCriteria !== 'function') {
865
+ pkPredicate = predicates_1.ModelPredicateCreator.createForPk(modelDefinition, model);
866
+ if (identifierOrCriteria) {
867
+ if (typeof identifierOrCriteria !== 'function') {
796
868
  msg = 'Invalid criteria';
797
- logger.error(msg, { idOrCriteria: idOrCriteria });
869
+ logger.error(msg, { identifierOrCriteria: identifierOrCriteria });
798
870
  throw new Error(msg);
799
871
  }
800
- condition = idOrCriteria(idPredicate);
872
+ condition = identifierOrCriteria(pkPredicate);
801
873
  }
802
874
  else {
803
- condition = idPredicate;
875
+ condition = pkPredicate;
804
876
  }
805
877
  return [4 /*yield*/, this.storage.delete(model, condition)];
806
878
  case 4:
807
- _b = __read.apply(void 0, [_d.sent(), 1]), _c = __read(_b[0], 1), deleted = _c[0];
879
+ _c = __read.apply(void 0, [_e.sent(), 1]), _d = __read(_c[0], 1), deleted = _d[0];
808
880
  return [2 /*return*/, deleted];
809
881
  }
810
882
  });
811
883
  }); };
812
- this.observe = function (modelOrConstructor, idOrCriteria) {
884
+ this.observe = function (modelOrConstructor, identifierOrCriteria) {
813
885
  var predicate;
814
886
  var modelConstructor = modelOrConstructor && isValidModelConstructor(modelOrConstructor)
815
887
  ? modelOrConstructor
@@ -818,10 +890,10 @@ var DataStore = /** @class */ (function () {
818
890
  var model = modelOrConstructor;
819
891
  var modelConstructor_1 = model && Object.getPrototypeOf(model).constructor;
820
892
  if (isValidModelConstructor(modelConstructor_1)) {
821
- if (idOrCriteria) {
893
+ if (identifierOrCriteria) {
822
894
  logger.warn('idOrCriteria is ignored when using a model instance', {
823
895
  model: model,
824
- idOrCriteria: idOrCriteria,
896
+ identifierOrCriteria: identifierOrCriteria,
825
897
  });
826
898
  }
827
899
  return _this.observe(modelConstructor_1, model.id);
@@ -832,9 +904,9 @@ var DataStore = /** @class */ (function () {
832
904
  throw new Error(msg);
833
905
  }
834
906
  }
835
- if (idOrCriteria !== undefined && modelConstructor === undefined) {
907
+ if (identifierOrCriteria !== undefined && modelConstructor === undefined) {
836
908
  var msg = 'Cannot provide criteria without a modelConstructor';
837
- logger.error(msg, idOrCriteria);
909
+ logger.error(msg, identifierOrCriteria);
838
910
  throw new Error(msg);
839
911
  }
840
912
  if (modelConstructor && !isValidModelConstructor(modelConstructor)) {
@@ -842,29 +914,63 @@ var DataStore = /** @class */ (function () {
842
914
  logger.error(msg, { modelConstructor: modelConstructor });
843
915
  throw new Error(msg);
844
916
  }
845
- if (typeof idOrCriteria === 'string') {
846
- predicate = predicates_1.ModelPredicateCreator.createForId(getModelDefinition(modelConstructor), idOrCriteria);
917
+ if (typeof identifierOrCriteria === 'string') {
918
+ var modelDefinition = getModelDefinition(modelConstructor);
919
+ var _a = __read(util_1.extractPrimaryKeyFieldNames(modelDefinition), 1), keyField = _a[0];
920
+ predicate = predicates_1.ModelPredicateCreator.createForSingleField(getModelDefinition(modelConstructor), keyField, identifierOrCriteria);
847
921
  }
848
922
  else {
849
- predicate =
850
- modelConstructor &&
851
- predicates_1.ModelPredicateCreator.createFromExisting(getModelDefinition(modelConstructor), idOrCriteria);
923
+ if (predicates_1.isPredicatesAll(identifierOrCriteria)) {
924
+ predicate = undefined;
925
+ }
926
+ else {
927
+ predicate =
928
+ modelConstructor &&
929
+ predicates_1.ModelPredicateCreator.createFromExisting(getModelDefinition(modelConstructor), identifierOrCriteria);
930
+ }
852
931
  }
853
932
  return new zen_observable_ts_1.default(function (observer) {
854
933
  var handle;
855
934
  (function () { return __awaiter(_this, void 0, void 0, function () {
935
+ var _this = this;
856
936
  return __generator(this, function (_a) {
857
937
  switch (_a.label) {
858
938
  case 0: return [4 /*yield*/, this.start()];
859
939
  case 1:
860
940
  _a.sent();
941
+ // Filter the events returned by Storage according to namespace,
942
+ // append original element data, and subscribe to the observable
861
943
  handle = this.storage
862
944
  .observe(modelConstructor, predicate)
863
945
  .filter(function (_a) {
864
946
  var model = _a.model;
865
947
  return namespaceResolver(model) === util_1.USER;
866
948
  })
867
- .subscribe(observer);
949
+ .subscribe({
950
+ next: function (item) { return __awaiter(_this, void 0, void 0, function () {
951
+ var message, modelDefinition, keyFields, primaryKeysAndValues, freshElement;
952
+ return __generator(this, function (_a) {
953
+ switch (_a.label) {
954
+ case 0:
955
+ message = item;
956
+ if (!(item.opType !== 'DELETE')) return [3 /*break*/, 2];
957
+ modelDefinition = getModelDefinition(item.model);
958
+ keyFields = util_1.extractPrimaryKeyFieldNames(modelDefinition);
959
+ primaryKeysAndValues = util_1.extractPrimaryKeysAndValues(item.element, keyFields);
960
+ return [4 /*yield*/, this.query(item.model, primaryKeysAndValues)];
961
+ case 1:
962
+ freshElement = _a.sent();
963
+ message = __assign(__assign({}, message), { element: freshElement });
964
+ _a.label = 2;
965
+ case 2:
966
+ observer.next(message);
967
+ return [2 /*return*/];
968
+ }
969
+ });
970
+ }); },
971
+ error: function (err) { return observer.error(err); },
972
+ complete: function () { return observer.complete(); },
973
+ });
868
974
  return [2 /*return*/];
869
975
  }
870
976
  });
@@ -882,6 +988,17 @@ var DataStore = /** @class */ (function () {
882
988
  var itemsChanged = new Map();
883
989
  var deletedItemIds = [];
884
990
  var handle;
991
+ var predicate;
992
+ /**
993
+ * As the name suggests, this geneates a snapshot in the form of
994
+ * `{items: T[], isSynced: boolean}`
995
+ * and sends it to the observer.
996
+ *
997
+ * SIDE EFFECT: The underlying generation and emission methods may touch:
998
+ * `items`, `itemsChanged`, and `deletedItemIds`.
999
+ *
1000
+ * Refer to `generateSnapshot` and `emitSnapshot` for more details.
1001
+ */
885
1002
  var generateAndEmitSnapshot = function () {
886
1003
  var snapshot = generateSnapshot();
887
1004
  emitSnapshot(snapshot);
@@ -895,6 +1012,22 @@ var DataStore = /** @class */ (function () {
895
1012
  });
896
1013
  var sort = (options || {}).sort;
897
1014
  var sortOptions = sort ? { sort: sort } : undefined;
1015
+ var modelDefinition = getModelDefinition(model);
1016
+ var keyFields = util_1.extractPrimaryKeyFieldNames(modelDefinition);
1017
+ if (isQueryOne(criteria)) {
1018
+ predicate = predicates_1.ModelPredicateCreator.createForSingleField(modelDefinition, keyFields[0], criteria);
1019
+ }
1020
+ else {
1021
+ if (predicates_1.isPredicatesAll(criteria)) {
1022
+ // Predicates.ALL means "all records", so no predicate (undefined)
1023
+ predicate = undefined;
1024
+ }
1025
+ else {
1026
+ predicate = predicates_1.ModelPredicateCreator.createFromExisting(modelDefinition, criteria);
1027
+ }
1028
+ }
1029
+ var _a = predicates_1.ModelPredicateCreator.getPredicates(predicate, false) || {}, predicates = _a.predicates, predicateGroupType = _a.type;
1030
+ var hasPredicate = !!predicates;
898
1031
  (function () { return __awaiter(_this, void 0, void 0, function () {
899
1032
  var err_1;
900
1033
  var _this = this;
@@ -906,23 +1039,53 @@ var DataStore = /** @class */ (function () {
906
1039
  case 1:
907
1040
  // first, query and return any locally-available records
908
1041
  (_a.sent()).forEach(function (item) {
909
- return items.set(item.id, item);
1042
+ var record = item;
1043
+ // TODO: fix query
1044
+ if (Array.isArray(item)) {
1045
+ record = item[0];
1046
+ }
1047
+ var itemModelDefinition = getModelDefinition(model);
1048
+ var idOrPk = utils_1.getIdentifierValue(itemModelDefinition, record);
1049
+ items.set(idOrPk, record);
910
1050
  });
911
- // observe the model and send a stream of updates (debounced)
912
- handle = this.observe(model,
913
- // @ts-ignore TODO: fix this TSlint error
914
- criteria).subscribe(function (_a) {
1051
+ // Observe the model and send a stream of updates (debounced).
1052
+ // We need to post-filter results instead of passing criteria through
1053
+ // to have visibility into items that move from in-set to out-of-set.
1054
+ // We need to explicitly remove those items from the existing snapshot.
1055
+ handle = this.observe(model).subscribe(function (_a) {
915
1056
  var element = _a.element, model = _a.model, opType = _a.opType;
916
1057
  var _b, _c;
1058
+ var record = element;
1059
+ // TODO: fix query
1060
+ if (Array.isArray(element)) {
1061
+ record = element[0];
1062
+ }
1063
+ var itemModelDefinition = getModelDefinition(model);
1064
+ var idOrPk = utils_1.getIdentifierValue(itemModelDefinition, record);
1065
+ if (hasPredicate &&
1066
+ !util_1.validatePredicate(record, predicateGroupType, predicates)) {
1067
+ if (opType === 'UPDATE' &&
1068
+ (items.has(idOrPk) || itemsChanged.has(idOrPk))) {
1069
+ // tracking as a "deleted item" will include the item in
1070
+ // page limit calculations and ensure it is removed from the
1071
+ // final items collection, regardless of which collection(s)
1072
+ // it is currently in. (I mean, it could be in both, right!?)
1073
+ deletedItemIds.push(idOrPk);
1074
+ }
1075
+ else {
1076
+ // ignore updates for irrelevant/filtered items.
1077
+ return;
1078
+ }
1079
+ }
917
1080
  // Flag items which have been recently deleted
918
1081
  // NOTE: Merging of separate operations to the same model instance is handled upstream
919
1082
  // in the `mergePage` method within src/sync/merger.ts. The final state of a model instance
920
1083
  // depends on the LATEST record (for a given id).
921
1084
  if (opType === 'DELETE') {
922
- deletedItemIds.push(element.id);
1085
+ deletedItemIds.push(idOrPk);
923
1086
  }
924
1087
  else {
925
- itemsChanged.set(element.id, element);
1088
+ itemsChanged.set(idOrPk, record);
926
1089
  }
927
1090
  var isSynced = (_c = (_b = _this.sync) === null || _b === void 0 ? void 0 : _b.getModelSyncedStatus(model)) !== null && _c !== void 0 ? _c : false;
928
1091
  var limit = itemsChanged.size - deletedItemIds.length >= _this.syncPageSize;
@@ -943,7 +1106,12 @@ var DataStore = /** @class */ (function () {
943
1106
  }
944
1107
  });
945
1108
  }); })();
946
- // TODO: abstract this function into a util file to be able to write better unit tests
1109
+ /**
1110
+ * Combines the `items`, `itemsChanged`, and `deletedItemIds` collections into
1111
+ * a snapshot in the form of `{ items: T[], isSynced: boolean}`.
1112
+ *
1113
+ * SIDE EFFECT: The shared `items` collection is recreated.
1114
+ */
947
1115
  var generateSnapshot = function () {
948
1116
  var _a, _b;
949
1117
  var isSynced = (_b = (_a = _this.sync) === null || _a === void 0 ? void 0 : _a.getModelSyncedStatus(model)) !== null && _b !== void 0 ? _b : false;
@@ -952,14 +1120,31 @@ var DataStore = /** @class */ (function () {
952
1120
  sortItems(itemsArray);
953
1121
  }
954
1122
  items.clear();
955
- itemsArray.forEach(function (item) { return items.set(item.id, item); });
1123
+ itemsArray.forEach(function (item) {
1124
+ // CPK TODO: fix query
1125
+ var record = item;
1126
+ if (Array.isArray(item)) {
1127
+ record = item[0];
1128
+ }
1129
+ var itemModelDefinition = getModelDefinition(model);
1130
+ var idOrPk = utils_1.getIdentifierValue(itemModelDefinition, record);
1131
+ items.set(idOrPk, record);
1132
+ });
956
1133
  // remove deleted items from the final result set
957
- deletedItemIds.forEach(function (id) { return items.delete(id); });
1134
+ deletedItemIds.forEach(function (idOrPk) { return items.delete(idOrPk); });
958
1135
  return {
959
1136
  items: Array.from(items.values()),
960
1137
  isSynced: isSynced,
961
1138
  };
962
1139
  };
1140
+ /**
1141
+ * Emits the list of items to the observer.
1142
+ *
1143
+ * SIDE EFFECT: `itemsChanged` and `deletedItemIds` are cleared to prepare
1144
+ * for the next snapshot.
1145
+ *
1146
+ * @param snapshot The generated items data to emit.
1147
+ */
963
1148
  var emitSnapshot = function (snapshot) {
964
1149
  // send the generated snapshot to the primary subscription
965
1150
  observer.next(snapshot);
@@ -967,6 +1152,12 @@ var DataStore = /** @class */ (function () {
967
1152
  itemsChanged.clear();
968
1153
  deletedItemIds = [];
969
1154
  };
1155
+ /**
1156
+ * Sorts an `Array` of `T` according to the sort instructions given in the
1157
+ * original `observeQuery()` call.
1158
+ *
1159
+ * @param itemsToSort A array of model type.
1160
+ */
970
1161
  var sortItems = function (itemsToSort) {
971
1162
  var modelDefinition = getModelDefinition(model);
972
1163
  var pagination = _this.processPagination(modelDefinition, options);
@@ -976,7 +1167,14 @@ var DataStore = /** @class */ (function () {
976
1167
  itemsToSort.sort(compareFn);
977
1168
  }
978
1169
  };
979
- // send one last snapshot when the model is fully synced
1170
+ /**
1171
+ * Force one last snapshot when the model is fully synced.
1172
+ *
1173
+ * This reduces latency for that last snapshot, which will otherwise
1174
+ * wait for the configured timeout.
1175
+ *
1176
+ * @param payload The payload from the Hub event.
1177
+ */
980
1178
  var hubCallback = function (_a) {
981
1179
  var payload = _a.payload;
982
1180
  var _b;
@@ -997,6 +1195,9 @@ var DataStore = /** @class */ (function () {
997
1195
  };
998
1196
  this.configure = function (config) {
999
1197
  if (config === void 0) { config = {}; }
1198
+ _this.amplifyContext.Auth = _this.Auth;
1199
+ _this.amplifyContext.API = _this.API;
1200
+ _this.amplifyContext.Cache = _this.Cache;
1000
1201
  var configDataStore = config.DataStore, configAuthModeStrategyType = config.authModeStrategyType, configConflictHandler = config.conflictHandler, configErrorHandler = config.errorHandler, configMaxRecordsToSync = config.maxRecordsToSync, configSyncPageSize = config.syncPageSize, configFullSyncInterval = config.fullSyncInterval, configSyncExpressions = config.syncExpressions, configAuthProviders = config.authProviders, configStorageAdapter = config.storageAdapter, configFromAmplify = __rest(config, ["DataStore", "authModeStrategyType", "conflictHandler", "errorHandler", "maxRecordsToSync", "syncPageSize", "fullSyncInterval", "syncExpressions", "authProviders", "storageAdapter"]);
1001
1202
  _this.amplifyConfig = __assign(__assign({}, configFromAmplify), _this.amplifyConfig);
1002
1203
  _this.conflictHandler = _this.setConflictHandler(config);
@@ -1006,7 +1207,7 @@ var DataStore = /** @class */ (function () {
1006
1207
  types_1.AuthModeStrategyType.DEFAULT;
1007
1208
  switch (authModeStrategyType) {
1008
1209
  case types_1.AuthModeStrategyType.MULTI_AUTH:
1009
- _this.authModeStrategy = authModeStrategies_1.multiAuthStrategy;
1210
+ _this.authModeStrategy = authModeStrategies_1.multiAuthStrategy(_this.amplifyContext);
1010
1211
  break;
1011
1212
  case types_1.AuthModeStrategyType.DEFAULT:
1012
1213
  _this.authModeStrategy = authModeStrategies_1.defaultAuthStrategy;
@@ -1020,29 +1221,31 @@ var DataStore = /** @class */ (function () {
1020
1221
  (configDataStore && configDataStore.authProviders) || configAuthProviders;
1021
1222
  _this.syncExpressions =
1022
1223
  (configDataStore && configDataStore.syncExpressions) ||
1023
- _this.syncExpressions ||
1024
- configSyncExpressions;
1224
+ configSyncExpressions ||
1225
+ _this.syncExpressions;
1025
1226
  _this.maxRecordsToSync =
1026
1227
  (configDataStore && configDataStore.maxRecordsToSync) ||
1027
1228
  configMaxRecordsToSync ||
1229
+ _this.maxRecordsToSync ||
1028
1230
  10000;
1029
1231
  // store on config object, so that Sync, Subscription, and Mutation processors can have access
1030
1232
  _this.amplifyConfig.maxRecordsToSync = _this.maxRecordsToSync;
1031
1233
  _this.syncPageSize =
1032
1234
  (configDataStore && configDataStore.syncPageSize) ||
1033
1235
  configSyncPageSize ||
1236
+ _this.syncPageSize ||
1034
1237
  1000;
1035
1238
  // store on config object, so that Sync, Subscription, and Mutation processors can have access
1036
1239
  _this.amplifyConfig.syncPageSize = _this.syncPageSize;
1037
1240
  _this.fullSyncInterval =
1038
1241
  (configDataStore && configDataStore.fullSyncInterval) ||
1039
- _this.fullSyncInterval ||
1040
1242
  configFullSyncInterval ||
1243
+ _this.fullSyncInterval ||
1041
1244
  24 * 60; // 1 day
1042
1245
  _this.storageAdapter =
1043
1246
  (configDataStore && configDataStore.storageAdapter) ||
1044
- _this.storageAdapter ||
1045
1247
  configStorageAdapter ||
1248
+ _this.storageAdapter ||
1046
1249
  undefined;
1047
1250
  _this.sessionId = _this.retrieveSessionId();
1048
1251
  };
@@ -1051,14 +1254,20 @@ var DataStore = /** @class */ (function () {
1051
1254
  return __generator(this, function (_a) {
1052
1255
  switch (_a.label) {
1053
1256
  case 0:
1054
- if (this.storage === undefined) {
1055
- return [2 /*return*/];
1056
- }
1257
+ checkSchemaInitialized();
1258
+ if (!(this.storage === undefined)) return [3 /*break*/, 2];
1259
+ // connect to storage so that it can be cleared without fully starting DataStore
1260
+ this.storage = new storage_1.ExclusiveStorage(schema, namespaceResolver, getModelConstructorByModelName, modelInstanceCreator, this.storageAdapter, this.sessionId);
1261
+ return [4 /*yield*/, this.storage.init()];
1262
+ case 1:
1263
+ _a.sent();
1264
+ _a.label = 2;
1265
+ case 2:
1057
1266
  if (syncSubscription && !syncSubscription.closed) {
1058
1267
  syncSubscription.unsubscribe();
1059
1268
  }
1060
1269
  return [4 /*yield*/, this.storage.clear()];
1061
- case 1:
1270
+ case 3:
1062
1271
  _a.sent();
1063
1272
  if (this.sync) {
1064
1273
  this.sync.unsubscribeConnectivity();
@@ -1226,9 +1435,8 @@ var DataStore = /** @class */ (function () {
1226
1435
  return sessionId + "-" + appSyncId;
1227
1436
  }
1228
1437
  }
1229
- catch (_b) {
1230
- return undefined;
1231
- }
1438
+ catch (_b) { }
1439
+ return undefined;
1232
1440
  };
1233
1441
  return DataStore;
1234
1442
  }());