@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
@@ -87,7 +87,10 @@ var __spread = (this && this.__spread) || function () {
87
87
  for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
88
88
  return ar;
89
89
  };
90
+ import API from '@aws-amplify/api';
90
91
  import { Amplify, ConsoleLogger as Logger, Hub, JS } from '@aws-amplify/core';
92
+ import { Auth } from '@aws-amplify/auth';
93
+ import Cache from '@aws-amplify/cache';
91
94
  import { immerable, produce, setAutoFreeze, enablePatches, } from 'immer';
92
95
  import { v4 as uuid4 } from 'uuid';
93
96
  import Observable from 'zen-observable-ts';
@@ -95,8 +98,9 @@ import { defaultAuthStrategy, multiAuthStrategy } from '../authModeStrategies';
95
98
  import { isPredicatesAll, ModelPredicateCreator, ModelSortPredicateCreator, } from '../predicates';
96
99
  import { ExclusiveStorage as Storage } from '../storage/storage';
97
100
  import { ControlMessage, SyncEngine } from '../sync';
98
- import { GraphQLScalarType, isGraphQLScalarType, AuthModeStrategyType, isNonModelFieldType, isModelFieldType, } from '../types';
99
- import { DATASTORE, establishRelationAndKeys, exhaustiveCheck, isModelConstructor, monotonicUlidFactory, STORAGE, SYNC, USER, isNullOrUndefined, registerNonModelClass, sortCompareFunction, DeferredCallbackResolver, } from '../util';
101
+ import { GraphQLScalarType, isGraphQLScalarType, AuthModeStrategyType, isNonModelFieldType, isModelFieldType, __modelMeta__, isIdentifierObject, } from '../types';
102
+ import { DATASTORE, errorMessages, establishRelationAndKeys, exhaustiveCheck, isModelConstructor, monotonicUlidFactory, STORAGE, SYNC, USER, isNullOrUndefined, registerNonModelClass, sortCompareFunction, DeferredCallbackResolver, extractPrimaryKeyFieldNames, extractPrimaryKeysAndValues, isIdManaged, isIdOptionallyManaged, validatePredicate, mergePatches, } from '../util';
103
+ import { getIdentifierValue } from '../sync/utils';
100
104
  setAutoFreeze(true);
101
105
  enablePatches();
102
106
  var logger = new Logger('DataStore');
@@ -201,6 +205,18 @@ var initSchema = function (userSchema) {
201
205
  });
202
206
  return userClasses;
203
207
  };
208
+ /* Checks if the schema has been initialized by initSchema().
209
+ *
210
+ * Call this function before accessing schema.
211
+ * Currently this only needs to be called in start() and clear() because all other functions will call start first.
212
+ */
213
+ var checkSchemaInitialized = function () {
214
+ if (schema === undefined) {
215
+ 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';
216
+ logger.error(message);
217
+ throw new Error(message);
218
+ }
219
+ };
204
220
  var createTypeClasses = function (namespace) {
205
221
  var classes = {};
206
222
  Object.entries(namespace.models).forEach(function (_a) {
@@ -221,6 +237,9 @@ function modelInstanceCreator(modelConstructor, init) {
221
237
  instancesMetadata.add(init);
222
238
  return new modelConstructor(init);
223
239
  }
240
+ function isSchemaModel(m) {
241
+ return m.attributes !== undefined;
242
+ }
224
243
  var validateModelFields = function (modelDefinition) { return function (k, v) {
225
244
  var fieldDefinition = modelDefinition.fields[k];
226
245
  if (fieldDefinition !== undefined) {
@@ -229,6 +248,13 @@ var validateModelFields = function (modelDefinition) { return function (k, v) {
229
248
  (v === null || v === undefined)) {
230
249
  throw new Error("Field " + name_1 + " is required");
231
250
  }
251
+ if (isSchemaModel(modelDefinition) && !isIdManaged(modelDefinition)) {
252
+ var keys = extractPrimaryKeyFieldNames(modelDefinition);
253
+ if (keys.includes(k) && v === '') {
254
+ logger.error(errorMessages.idEmptyString, { k: k, value: v });
255
+ throw new Error(errorMessages.idEmptyString);
256
+ }
257
+ }
232
258
  if (isGraphQLScalarType(type)) {
233
259
  var jsType_1 = GraphQLScalarType.getJSType(type);
234
260
  var validateScalar_1 = GraphQLScalarType.getValidationFunction(type);
@@ -329,21 +355,29 @@ var createModelClass = function (modelDefinition) {
329
355
  function Model(init) {
330
356
  var instance = produce(this, function (draft) {
331
357
  initializeInstance(init, modelDefinition, draft);
332
- var modelInstanceMetadata = instancesMetadata.has(init)
358
+ // model is initialized inside a DataStore component (e.g. by Sync Engine, Storage Engine, etc.)
359
+ var isInternallyInitialized = instancesMetadata.has(init);
360
+ var modelInstanceMetadata = isInternallyInitialized
333
361
  ? init
334
362
  : {};
335
- var _id = modelInstanceMetadata.id, _version = modelInstanceMetadata._version, _lastChangedAt = modelInstanceMetadata._lastChangedAt, _deleted = modelInstanceMetadata._deleted;
336
- // instancesIds are set by modelInstanceCreator, it is accessible only internally
337
- var isInternal = _id !== null && _id !== undefined;
338
- var id = isInternal
339
- ? _id
340
- : modelDefinition.syncable
341
- ? uuid4()
342
- : ulid();
343
- if (!isInternal) {
363
+ var _id = modelInstanceMetadata.id;
364
+ if (isIdManaged(modelDefinition)) {
365
+ var isInternalModel = _id !== null && _id !== undefined;
366
+ var id = isInternalModel
367
+ ? _id
368
+ : modelDefinition.syncable
369
+ ? uuid4()
370
+ : ulid();
371
+ draft.id = id;
372
+ }
373
+ else if (isIdOptionallyManaged(modelDefinition)) {
374
+ // only auto-populate if the id was not provided
375
+ draft.id = draft.id || uuid4();
376
+ }
377
+ if (!isInternallyInitialized) {
344
378
  checkReadOnlyPropertyOnCreate(draft, modelDefinition);
345
379
  }
346
- draft.id = id;
380
+ var _version = modelInstanceMetadata._version, _lastChangedAt = modelInstanceMetadata._lastChangedAt, _deleted = modelInstanceMetadata._deleted;
347
381
  if (modelDefinition.syncable) {
348
382
  draft._version = _version;
349
383
  draft._lastChangedAt = _lastChangedAt;
@@ -362,7 +396,10 @@ var createModelClass = function (modelDefinition) {
362
396
  var patches;
363
397
  var model = produce(source, function (draft) {
364
398
  fn(draft);
365
- draft.id = source.id;
399
+ var keyNames = extractPrimaryKeyFieldNames(modelDefinition);
400
+ // Keys are immutable
401
+ // @ts-ignore TODO: fix type
402
+ keyNames.forEach(function (key) { return (draft[key] = source[key]); });
366
403
  var modelValidator = validateModelFields(modelDefinition);
367
404
  Object.entries(draft).forEach(function (_a) {
368
405
  var _b = __read(_a, 2), k = _b[0], v = _b[1];
@@ -370,9 +407,18 @@ var createModelClass = function (modelDefinition) {
370
407
  modelValidator(k, parsedValue);
371
408
  });
372
409
  }, function (p) { return (patches = p); });
373
- if (patches.length) {
374
- modelPatchesMap.set(model, [patches, source]);
375
- checkReadOnlyPropertyOnUpdate(patches, modelDefinition);
410
+ var hasExistingPatches = modelPatchesMap.has(source);
411
+ if (patches.length || hasExistingPatches) {
412
+ if (hasExistingPatches) {
413
+ var _a = __read(modelPatchesMap.get(source), 2), existingPatches = _a[0], existingSource = _a[1];
414
+ var mergedPatches = mergePatches(existingSource, existingPatches, patches);
415
+ modelPatchesMap.set(model, [mergedPatches, existingSource]);
416
+ checkReadOnlyPropertyOnUpdate(mergedPatches, modelDefinition);
417
+ }
418
+ else {
419
+ modelPatchesMap.set(model, [patches, source]);
420
+ checkReadOnlyPropertyOnUpdate(patches, modelDefinition);
421
+ }
376
422
  }
377
423
  return model;
378
424
  };
@@ -486,7 +532,6 @@ function checkSchemaVersion(storage, version) {
486
532
  return __generator(this, function (_b) {
487
533
  switch (_b.label) {
488
534
  case 0: return [4 /*yield*/, s.query(Setting, ModelPredicateCreator.createFromExisting(modelDefinition, function (c) {
489
- // @ts-ignore Argument of type '"eq"' is not assignable to parameter of type 'never'.
490
535
  return c.key('eq', SETTING_SCHEMA_VERSION);
491
536
  }), { page: 0, limit: 1 })];
492
537
  case 1:
@@ -558,8 +603,18 @@ function getNamespace() {
558
603
  var DataStore = /** @class */ (function () {
559
604
  function DataStore() {
560
605
  var _this = this;
606
+ // reference to configured category instances. Used for preserving SSR context
607
+ this.Auth = Auth;
608
+ this.API = API;
609
+ this.Cache = Cache;
561
610
  this.amplifyConfig = {};
562
611
  this.syncPredicates = new WeakMap();
612
+ // object that gets passed to descendent classes. Allows us to pass these down by reference
613
+ this.amplifyContext = {
614
+ Auth: this.Auth,
615
+ API: this.API,
616
+ Cache: this.Cache,
617
+ };
563
618
  this.start = function () { return __awaiter(_this, void 0, void 0, function () {
564
619
  var aws_appsync_graphqlEndpoint, _a, fullSyncIntervalInMilliseconds;
565
620
  var _this = this;
@@ -582,6 +637,7 @@ var DataStore = /** @class */ (function () {
582
637
  return [4 /*yield*/, this.storage.init()];
583
638
  case 4:
584
639
  _b.sent();
640
+ checkSchemaInitialized();
585
641
  return [4 /*yield*/, checkSchemaVersion(this.storage, schema.version)];
586
642
  case 5:
587
643
  _b.sent();
@@ -592,7 +648,7 @@ var DataStore = /** @class */ (function () {
592
648
  return [4 /*yield*/, this.processSyncExpressions()];
593
649
  case 6:
594
650
  _a.syncPredicates = _b.sent();
595
- this.sync = new SyncEngine(schema, namespaceResolver, syncClasses, userClasses, this.storage, modelInstanceCreator, this.maxRecordsToSync, this.syncPageSize, this.conflictHandler, this.errorHandler, this.syncPredicates, this.amplifyConfig, this.authModeStrategy);
651
+ this.sync = new SyncEngine(schema, namespaceResolver, syncClasses, userClasses, this.storage, modelInstanceCreator, this.conflictHandler, this.errorHandler, this.syncPredicates, this.amplifyConfig, this.authModeStrategy, this.amplifyContext);
596
652
  fullSyncIntervalInMilliseconds = this.fullSyncInterval * 1000 * 60;
597
653
  syncSubscription = this.sync
598
654
  .start({ fullSyncInterval: fullSyncIntervalInMilliseconds })
@@ -631,8 +687,8 @@ var DataStore = /** @class */ (function () {
631
687
  }
632
688
  });
633
689
  }); };
634
- this.query = function (modelConstructor, idOrCriteria, paginationProducer) { return __awaiter(_this, void 0, void 0, function () {
635
- var msg, modelDefinition, predicate, pagination, result;
690
+ this.query = function (modelConstructor, identifierOrCriteria, paginationProducer) { return __awaiter(_this, void 0, void 0, function () {
691
+ var msg, modelDefinition, keyFields, predicate, pagination, result, isSingleFieldIdentifier, returnOne;
636
692
  return __generator(this, function (_a) {
637
693
  switch (_a.label) {
638
694
  case 0: return [4 /*yield*/, this.start()];
@@ -644,22 +700,27 @@ var DataStore = /** @class */ (function () {
644
700
  logger.error(msg, { modelConstructor: modelConstructor });
645
701
  throw new Error(msg);
646
702
  }
647
- if (typeof idOrCriteria === 'string') {
703
+ if (typeof identifierOrCriteria === 'string') {
648
704
  if (paginationProducer !== undefined) {
649
705
  logger.warn('Pagination is ignored when querying by id');
650
706
  }
651
707
  }
652
708
  modelDefinition = getModelDefinition(modelConstructor);
653
- if (isQueryOne(idOrCriteria)) {
654
- predicate = ModelPredicateCreator.createForId(modelDefinition, idOrCriteria);
709
+ keyFields = extractPrimaryKeyFieldNames(modelDefinition);
710
+ if (isQueryOne(identifierOrCriteria)) {
711
+ predicate = ModelPredicateCreator.createForSingleField(modelDefinition, keyFields[0], identifierOrCriteria);
655
712
  }
656
713
  else {
657
- if (isPredicatesAll(idOrCriteria)) {
714
+ // Object is being queried using object literal syntax
715
+ if (isIdentifierObject(identifierOrCriteria, modelDefinition)) {
716
+ predicate = ModelPredicateCreator.createForPk(modelDefinition, identifierOrCriteria);
717
+ }
718
+ else if (isPredicatesAll(identifierOrCriteria)) {
658
719
  // Predicates.ALL means "all records", so no predicate (undefined)
659
720
  predicate = undefined;
660
721
  }
661
722
  else {
662
- predicate = ModelPredicateCreator.createFromExisting(modelDefinition, idOrCriteria);
723
+ predicate = ModelPredicateCreator.createFromExisting(modelDefinition, identifierOrCriteria);
663
724
  }
664
725
  }
665
726
  pagination = this.processPagination(modelDefinition, paginationProducer);
@@ -672,7 +733,11 @@ var DataStore = /** @class */ (function () {
672
733
  return [4 /*yield*/, this.storage.query(modelConstructor, predicate, pagination)];
673
734
  case 2:
674
735
  result = _a.sent();
675
- return [2 /*return*/, isQueryOne(idOrCriteria) ? result[0] : result];
736
+ isSingleFieldIdentifier = keyFields.length === 1;
737
+ returnOne = isSingleFieldIdentifier &&
738
+ (isQueryOne(identifierOrCriteria) ||
739
+ isIdentifierObject(identifierOrCriteria, modelDefinition));
740
+ return [2 /*return*/, returnOne ? result[0] : result];
676
741
  }
677
742
  });
678
743
  }); };
@@ -701,7 +766,7 @@ var DataStore = /** @class */ (function () {
701
766
  case 0: return [4 /*yield*/, s.save(model, producedCondition, undefined, patchesTuple)];
702
767
  case 1:
703
768
  _a.sent();
704
- return [2 /*return*/, s.query(modelConstructor, ModelPredicateCreator.createForId(modelDefinition, model.id))];
769
+ return [2 /*return*/, s.query(modelConstructor, ModelPredicateCreator.createForPk(modelDefinition, model))];
705
770
  }
706
771
  });
707
772
  }); })];
@@ -737,13 +802,13 @@ var DataStore = /** @class */ (function () {
737
802
  }
738
803
  return _this.errorHandler || defaultErrorHandler;
739
804
  };
740
- this.delete = function (modelOrConstructor, idOrCriteria) { return __awaiter(_this, void 0, void 0, function () {
741
- var condition, msg, modelConstructor, msg, msg, _a, deleted, model, modelConstructor, msg, modelDefinition, idPredicate, msg, _b, _c, deleted;
742
- return __generator(this, function (_d) {
743
- switch (_d.label) {
805
+ this.delete = function (modelOrConstructor, identifierOrCriteria) { return __awaiter(_this, void 0, void 0, function () {
806
+ var condition, msg, modelConstructor, msg, modelDefinition, _a, keyField, msg, _b, deleted, model, modelConstructor, msg, modelDefinition, pkPredicate, msg, _c, _d, deleted;
807
+ return __generator(this, function (_e) {
808
+ switch (_e.label) {
744
809
  case 0: return [4 /*yield*/, this.start()];
745
810
  case 1:
746
- _d.sent();
811
+ _e.sent();
747
812
  if (!modelOrConstructor) {
748
813
  msg = 'Model or Model Constructor required';
749
814
  logger.error(msg, { modelOrConstructor: modelOrConstructor });
@@ -751,21 +816,28 @@ var DataStore = /** @class */ (function () {
751
816
  }
752
817
  if (!isValidModelConstructor(modelOrConstructor)) return [3 /*break*/, 3];
753
818
  modelConstructor = modelOrConstructor;
754
- if (!idOrCriteria) {
819
+ if (!identifierOrCriteria) {
755
820
  msg = 'Id to delete or criteria required. Do you want to delete all? Pass Predicates.ALL';
756
- logger.error(msg, { idOrCriteria: idOrCriteria });
821
+ logger.error(msg, { identifierOrCriteria: identifierOrCriteria });
757
822
  throw new Error(msg);
758
823
  }
759
- if (typeof idOrCriteria === 'string') {
760
- condition = ModelPredicateCreator.createForId(getModelDefinition(modelConstructor), idOrCriteria);
824
+ modelDefinition = getModelDefinition(modelConstructor);
825
+ if (typeof identifierOrCriteria === 'string') {
826
+ _a = __read(extractPrimaryKeyFieldNames(modelDefinition), 1), keyField = _a[0];
827
+ condition = ModelPredicateCreator.createForSingleField(getModelDefinition(modelConstructor), keyField, identifierOrCriteria);
761
828
  }
762
829
  else {
763
- condition = ModelPredicateCreator.createFromExisting(getModelDefinition(modelConstructor),
764
- /**
765
- * idOrCriteria is always a ProducerModelPredicate<T>, never a symbol.
766
- * The symbol is used only for typing purposes. e.g. see Predicates.ALL
767
- */
768
- idOrCriteria);
830
+ if (isIdentifierObject(identifierOrCriteria, modelDefinition)) {
831
+ condition = ModelPredicateCreator.createForPk(modelDefinition, identifierOrCriteria);
832
+ }
833
+ else {
834
+ condition = ModelPredicateCreator.createFromExisting(modelDefinition,
835
+ /**
836
+ * idOrCriteria is always a ProducerModelPredicate<T>, never a symbol.
837
+ * The symbol is used only for typing purposes. e.g. see Predicates.ALL
838
+ */
839
+ identifierOrCriteria);
840
+ }
769
841
  if (!condition || !ModelPredicateCreator.isValidPredicate(condition)) {
770
842
  msg = 'Criteria required. Do you want to delete all? Pass Predicates.ALL';
771
843
  logger.error(msg, { condition: condition });
@@ -774,7 +846,7 @@ var DataStore = /** @class */ (function () {
774
846
  }
775
847
  return [4 /*yield*/, this.storage.delete(modelConstructor, condition)];
776
848
  case 2:
777
- _a = __read.apply(void 0, [_d.sent(), 1]), deleted = _a[0];
849
+ _b = __read.apply(void 0, [_e.sent(), 1]), deleted = _b[0];
778
850
  return [2 /*return*/, deleted];
779
851
  case 3:
780
852
  model = modelOrConstructor;
@@ -786,26 +858,26 @@ var DataStore = /** @class */ (function () {
786
858
  throw new Error(msg);
787
859
  }
788
860
  modelDefinition = getModelDefinition(modelConstructor);
789
- idPredicate = ModelPredicateCreator.createForId(modelDefinition, model.id);
790
- if (idOrCriteria) {
791
- if (typeof idOrCriteria !== 'function') {
861
+ pkPredicate = ModelPredicateCreator.createForPk(modelDefinition, model);
862
+ if (identifierOrCriteria) {
863
+ if (typeof identifierOrCriteria !== 'function') {
792
864
  msg = 'Invalid criteria';
793
- logger.error(msg, { idOrCriteria: idOrCriteria });
865
+ logger.error(msg, { identifierOrCriteria: identifierOrCriteria });
794
866
  throw new Error(msg);
795
867
  }
796
- condition = idOrCriteria(idPredicate);
868
+ condition = identifierOrCriteria(pkPredicate);
797
869
  }
798
870
  else {
799
- condition = idPredicate;
871
+ condition = pkPredicate;
800
872
  }
801
873
  return [4 /*yield*/, this.storage.delete(model, condition)];
802
874
  case 4:
803
- _b = __read.apply(void 0, [_d.sent(), 1]), _c = __read(_b[0], 1), deleted = _c[0];
875
+ _c = __read.apply(void 0, [_e.sent(), 1]), _d = __read(_c[0], 1), deleted = _d[0];
804
876
  return [2 /*return*/, deleted];
805
877
  }
806
878
  });
807
879
  }); };
808
- this.observe = function (modelOrConstructor, idOrCriteria) {
880
+ this.observe = function (modelOrConstructor, identifierOrCriteria) {
809
881
  var predicate;
810
882
  var modelConstructor = modelOrConstructor && isValidModelConstructor(modelOrConstructor)
811
883
  ? modelOrConstructor
@@ -814,10 +886,10 @@ var DataStore = /** @class */ (function () {
814
886
  var model = modelOrConstructor;
815
887
  var modelConstructor_1 = model && Object.getPrototypeOf(model).constructor;
816
888
  if (isValidModelConstructor(modelConstructor_1)) {
817
- if (idOrCriteria) {
889
+ if (identifierOrCriteria) {
818
890
  logger.warn('idOrCriteria is ignored when using a model instance', {
819
891
  model: model,
820
- idOrCriteria: idOrCriteria,
892
+ identifierOrCriteria: identifierOrCriteria,
821
893
  });
822
894
  }
823
895
  return _this.observe(modelConstructor_1, model.id);
@@ -828,9 +900,9 @@ var DataStore = /** @class */ (function () {
828
900
  throw new Error(msg);
829
901
  }
830
902
  }
831
- if (idOrCriteria !== undefined && modelConstructor === undefined) {
903
+ if (identifierOrCriteria !== undefined && modelConstructor === undefined) {
832
904
  var msg = 'Cannot provide criteria without a modelConstructor';
833
- logger.error(msg, idOrCriteria);
905
+ logger.error(msg, identifierOrCriteria);
834
906
  throw new Error(msg);
835
907
  }
836
908
  if (modelConstructor && !isValidModelConstructor(modelConstructor)) {
@@ -838,29 +910,63 @@ var DataStore = /** @class */ (function () {
838
910
  logger.error(msg, { modelConstructor: modelConstructor });
839
911
  throw new Error(msg);
840
912
  }
841
- if (typeof idOrCriteria === 'string') {
842
- predicate = ModelPredicateCreator.createForId(getModelDefinition(modelConstructor), idOrCriteria);
913
+ if (typeof identifierOrCriteria === 'string') {
914
+ var modelDefinition = getModelDefinition(modelConstructor);
915
+ var _a = __read(extractPrimaryKeyFieldNames(modelDefinition), 1), keyField = _a[0];
916
+ predicate = ModelPredicateCreator.createForSingleField(getModelDefinition(modelConstructor), keyField, identifierOrCriteria);
843
917
  }
844
918
  else {
845
- predicate =
846
- modelConstructor &&
847
- ModelPredicateCreator.createFromExisting(getModelDefinition(modelConstructor), idOrCriteria);
919
+ if (isPredicatesAll(identifierOrCriteria)) {
920
+ predicate = undefined;
921
+ }
922
+ else {
923
+ predicate =
924
+ modelConstructor &&
925
+ ModelPredicateCreator.createFromExisting(getModelDefinition(modelConstructor), identifierOrCriteria);
926
+ }
848
927
  }
849
928
  return new Observable(function (observer) {
850
929
  var handle;
851
930
  (function () { return __awaiter(_this, void 0, void 0, function () {
931
+ var _this = this;
852
932
  return __generator(this, function (_a) {
853
933
  switch (_a.label) {
854
934
  case 0: return [4 /*yield*/, this.start()];
855
935
  case 1:
856
936
  _a.sent();
937
+ // Filter the events returned by Storage according to namespace,
938
+ // append original element data, and subscribe to the observable
857
939
  handle = this.storage
858
940
  .observe(modelConstructor, predicate)
859
941
  .filter(function (_a) {
860
942
  var model = _a.model;
861
943
  return namespaceResolver(model) === USER;
862
944
  })
863
- .subscribe(observer);
945
+ .subscribe({
946
+ next: function (item) { return __awaiter(_this, void 0, void 0, function () {
947
+ var message, modelDefinition, keyFields, primaryKeysAndValues, freshElement;
948
+ return __generator(this, function (_a) {
949
+ switch (_a.label) {
950
+ case 0:
951
+ message = item;
952
+ if (!(item.opType !== 'DELETE')) return [3 /*break*/, 2];
953
+ modelDefinition = getModelDefinition(item.model);
954
+ keyFields = extractPrimaryKeyFieldNames(modelDefinition);
955
+ primaryKeysAndValues = extractPrimaryKeysAndValues(item.element, keyFields);
956
+ return [4 /*yield*/, this.query(item.model, primaryKeysAndValues)];
957
+ case 1:
958
+ freshElement = _a.sent();
959
+ message = __assign(__assign({}, message), { element: freshElement });
960
+ _a.label = 2;
961
+ case 2:
962
+ observer.next(message);
963
+ return [2 /*return*/];
964
+ }
965
+ });
966
+ }); },
967
+ error: function (err) { return observer.error(err); },
968
+ complete: function () { return observer.complete(); },
969
+ });
864
970
  return [2 /*return*/];
865
971
  }
866
972
  });
@@ -878,6 +984,17 @@ var DataStore = /** @class */ (function () {
878
984
  var itemsChanged = new Map();
879
985
  var deletedItemIds = [];
880
986
  var handle;
987
+ var predicate;
988
+ /**
989
+ * As the name suggests, this geneates a snapshot in the form of
990
+ * `{items: T[], isSynced: boolean}`
991
+ * and sends it to the observer.
992
+ *
993
+ * SIDE EFFECT: The underlying generation and emission methods may touch:
994
+ * `items`, `itemsChanged`, and `deletedItemIds`.
995
+ *
996
+ * Refer to `generateSnapshot` and `emitSnapshot` for more details.
997
+ */
881
998
  var generateAndEmitSnapshot = function () {
882
999
  var snapshot = generateSnapshot();
883
1000
  emitSnapshot(snapshot);
@@ -891,6 +1008,22 @@ var DataStore = /** @class */ (function () {
891
1008
  });
892
1009
  var sort = (options || {}).sort;
893
1010
  var sortOptions = sort ? { sort: sort } : undefined;
1011
+ var modelDefinition = getModelDefinition(model);
1012
+ var keyFields = extractPrimaryKeyFieldNames(modelDefinition);
1013
+ if (isQueryOne(criteria)) {
1014
+ predicate = ModelPredicateCreator.createForSingleField(modelDefinition, keyFields[0], criteria);
1015
+ }
1016
+ else {
1017
+ if (isPredicatesAll(criteria)) {
1018
+ // Predicates.ALL means "all records", so no predicate (undefined)
1019
+ predicate = undefined;
1020
+ }
1021
+ else {
1022
+ predicate = ModelPredicateCreator.createFromExisting(modelDefinition, criteria);
1023
+ }
1024
+ }
1025
+ var _a = ModelPredicateCreator.getPredicates(predicate, false) || {}, predicates = _a.predicates, predicateGroupType = _a.type;
1026
+ var hasPredicate = !!predicates;
894
1027
  (function () { return __awaiter(_this, void 0, void 0, function () {
895
1028
  var err_1;
896
1029
  var _this = this;
@@ -902,23 +1035,53 @@ var DataStore = /** @class */ (function () {
902
1035
  case 1:
903
1036
  // first, query and return any locally-available records
904
1037
  (_a.sent()).forEach(function (item) {
905
- return items.set(item.id, item);
1038
+ var record = item;
1039
+ // TODO: fix query
1040
+ if (Array.isArray(item)) {
1041
+ record = item[0];
1042
+ }
1043
+ var itemModelDefinition = getModelDefinition(model);
1044
+ var idOrPk = getIdentifierValue(itemModelDefinition, record);
1045
+ items.set(idOrPk, record);
906
1046
  });
907
- // observe the model and send a stream of updates (debounced)
908
- handle = this.observe(model,
909
- // @ts-ignore TODO: fix this TSlint error
910
- criteria).subscribe(function (_a) {
1047
+ // Observe the model and send a stream of updates (debounced).
1048
+ // We need to post-filter results instead of passing criteria through
1049
+ // to have visibility into items that move from in-set to out-of-set.
1050
+ // We need to explicitly remove those items from the existing snapshot.
1051
+ handle = this.observe(model).subscribe(function (_a) {
911
1052
  var element = _a.element, model = _a.model, opType = _a.opType;
912
1053
  var _b, _c;
1054
+ var record = element;
1055
+ // TODO: fix query
1056
+ if (Array.isArray(element)) {
1057
+ record = element[0];
1058
+ }
1059
+ var itemModelDefinition = getModelDefinition(model);
1060
+ var idOrPk = getIdentifierValue(itemModelDefinition, record);
1061
+ if (hasPredicate &&
1062
+ !validatePredicate(record, predicateGroupType, predicates)) {
1063
+ if (opType === 'UPDATE' &&
1064
+ (items.has(idOrPk) || itemsChanged.has(idOrPk))) {
1065
+ // tracking as a "deleted item" will include the item in
1066
+ // page limit calculations and ensure it is removed from the
1067
+ // final items collection, regardless of which collection(s)
1068
+ // it is currently in. (I mean, it could be in both, right!?)
1069
+ deletedItemIds.push(idOrPk);
1070
+ }
1071
+ else {
1072
+ // ignore updates for irrelevant/filtered items.
1073
+ return;
1074
+ }
1075
+ }
913
1076
  // Flag items which have been recently deleted
914
1077
  // NOTE: Merging of separate operations to the same model instance is handled upstream
915
1078
  // in the `mergePage` method within src/sync/merger.ts. The final state of a model instance
916
1079
  // depends on the LATEST record (for a given id).
917
1080
  if (opType === 'DELETE') {
918
- deletedItemIds.push(element.id);
1081
+ deletedItemIds.push(idOrPk);
919
1082
  }
920
1083
  else {
921
- itemsChanged.set(element.id, element);
1084
+ itemsChanged.set(idOrPk, record);
922
1085
  }
923
1086
  var isSynced = (_c = (_b = _this.sync) === null || _b === void 0 ? void 0 : _b.getModelSyncedStatus(model)) !== null && _c !== void 0 ? _c : false;
924
1087
  var limit = itemsChanged.size - deletedItemIds.length >= _this.syncPageSize;
@@ -939,7 +1102,12 @@ var DataStore = /** @class */ (function () {
939
1102
  }
940
1103
  });
941
1104
  }); })();
942
- // TODO: abstract this function into a util file to be able to write better unit tests
1105
+ /**
1106
+ * Combines the `items`, `itemsChanged`, and `deletedItemIds` collections into
1107
+ * a snapshot in the form of `{ items: T[], isSynced: boolean}`.
1108
+ *
1109
+ * SIDE EFFECT: The shared `items` collection is recreated.
1110
+ */
943
1111
  var generateSnapshot = function () {
944
1112
  var _a, _b;
945
1113
  var isSynced = (_b = (_a = _this.sync) === null || _a === void 0 ? void 0 : _a.getModelSyncedStatus(model)) !== null && _b !== void 0 ? _b : false;
@@ -948,14 +1116,31 @@ var DataStore = /** @class */ (function () {
948
1116
  sortItems(itemsArray);
949
1117
  }
950
1118
  items.clear();
951
- itemsArray.forEach(function (item) { return items.set(item.id, item); });
1119
+ itemsArray.forEach(function (item) {
1120
+ // CPK TODO: fix query
1121
+ var record = item;
1122
+ if (Array.isArray(item)) {
1123
+ record = item[0];
1124
+ }
1125
+ var itemModelDefinition = getModelDefinition(model);
1126
+ var idOrPk = getIdentifierValue(itemModelDefinition, record);
1127
+ items.set(idOrPk, record);
1128
+ });
952
1129
  // remove deleted items from the final result set
953
- deletedItemIds.forEach(function (id) { return items.delete(id); });
1130
+ deletedItemIds.forEach(function (idOrPk) { return items.delete(idOrPk); });
954
1131
  return {
955
1132
  items: Array.from(items.values()),
956
1133
  isSynced: isSynced,
957
1134
  };
958
1135
  };
1136
+ /**
1137
+ * Emits the list of items to the observer.
1138
+ *
1139
+ * SIDE EFFECT: `itemsChanged` and `deletedItemIds` are cleared to prepare
1140
+ * for the next snapshot.
1141
+ *
1142
+ * @param snapshot The generated items data to emit.
1143
+ */
959
1144
  var emitSnapshot = function (snapshot) {
960
1145
  // send the generated snapshot to the primary subscription
961
1146
  observer.next(snapshot);
@@ -963,6 +1148,12 @@ var DataStore = /** @class */ (function () {
963
1148
  itemsChanged.clear();
964
1149
  deletedItemIds = [];
965
1150
  };
1151
+ /**
1152
+ * Sorts an `Array` of `T` according to the sort instructions given in the
1153
+ * original `observeQuery()` call.
1154
+ *
1155
+ * @param itemsToSort A array of model type.
1156
+ */
966
1157
  var sortItems = function (itemsToSort) {
967
1158
  var modelDefinition = getModelDefinition(model);
968
1159
  var pagination = _this.processPagination(modelDefinition, options);
@@ -972,7 +1163,14 @@ var DataStore = /** @class */ (function () {
972
1163
  itemsToSort.sort(compareFn);
973
1164
  }
974
1165
  };
975
- // send one last snapshot when the model is fully synced
1166
+ /**
1167
+ * Force one last snapshot when the model is fully synced.
1168
+ *
1169
+ * This reduces latency for that last snapshot, which will otherwise
1170
+ * wait for the configured timeout.
1171
+ *
1172
+ * @param payload The payload from the Hub event.
1173
+ */
976
1174
  var hubCallback = function (_a) {
977
1175
  var payload = _a.payload;
978
1176
  var _b;
@@ -993,6 +1191,9 @@ var DataStore = /** @class */ (function () {
993
1191
  };
994
1192
  this.configure = function (config) {
995
1193
  if (config === void 0) { config = {}; }
1194
+ _this.amplifyContext.Auth = _this.Auth;
1195
+ _this.amplifyContext.API = _this.API;
1196
+ _this.amplifyContext.Cache = _this.Cache;
996
1197
  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"]);
997
1198
  _this.amplifyConfig = __assign(__assign({}, configFromAmplify), _this.amplifyConfig);
998
1199
  _this.conflictHandler = _this.setConflictHandler(config);
@@ -1002,7 +1203,7 @@ var DataStore = /** @class */ (function () {
1002
1203
  AuthModeStrategyType.DEFAULT;
1003
1204
  switch (authModeStrategyType) {
1004
1205
  case AuthModeStrategyType.MULTI_AUTH:
1005
- _this.authModeStrategy = multiAuthStrategy;
1206
+ _this.authModeStrategy = multiAuthStrategy(_this.amplifyContext);
1006
1207
  break;
1007
1208
  case AuthModeStrategyType.DEFAULT:
1008
1209
  _this.authModeStrategy = defaultAuthStrategy;
@@ -1016,29 +1217,31 @@ var DataStore = /** @class */ (function () {
1016
1217
  (configDataStore && configDataStore.authProviders) || configAuthProviders;
1017
1218
  _this.syncExpressions =
1018
1219
  (configDataStore && configDataStore.syncExpressions) ||
1019
- _this.syncExpressions ||
1020
- configSyncExpressions;
1220
+ configSyncExpressions ||
1221
+ _this.syncExpressions;
1021
1222
  _this.maxRecordsToSync =
1022
1223
  (configDataStore && configDataStore.maxRecordsToSync) ||
1023
1224
  configMaxRecordsToSync ||
1225
+ _this.maxRecordsToSync ||
1024
1226
  10000;
1025
1227
  // store on config object, so that Sync, Subscription, and Mutation processors can have access
1026
1228
  _this.amplifyConfig.maxRecordsToSync = _this.maxRecordsToSync;
1027
1229
  _this.syncPageSize =
1028
1230
  (configDataStore && configDataStore.syncPageSize) ||
1029
1231
  configSyncPageSize ||
1232
+ _this.syncPageSize ||
1030
1233
  1000;
1031
1234
  // store on config object, so that Sync, Subscription, and Mutation processors can have access
1032
1235
  _this.amplifyConfig.syncPageSize = _this.syncPageSize;
1033
1236
  _this.fullSyncInterval =
1034
1237
  (configDataStore && configDataStore.fullSyncInterval) ||
1035
- _this.fullSyncInterval ||
1036
1238
  configFullSyncInterval ||
1239
+ _this.fullSyncInterval ||
1037
1240
  24 * 60; // 1 day
1038
1241
  _this.storageAdapter =
1039
1242
  (configDataStore && configDataStore.storageAdapter) ||
1040
- _this.storageAdapter ||
1041
1243
  configStorageAdapter ||
1244
+ _this.storageAdapter ||
1042
1245
  undefined;
1043
1246
  _this.sessionId = _this.retrieveSessionId();
1044
1247
  };
@@ -1047,14 +1250,20 @@ var DataStore = /** @class */ (function () {
1047
1250
  return __generator(this, function (_a) {
1048
1251
  switch (_a.label) {
1049
1252
  case 0:
1050
- if (this.storage === undefined) {
1051
- return [2 /*return*/];
1052
- }
1253
+ checkSchemaInitialized();
1254
+ if (!(this.storage === undefined)) return [3 /*break*/, 2];
1255
+ // connect to storage so that it can be cleared without fully starting DataStore
1256
+ this.storage = new Storage(schema, namespaceResolver, getModelConstructorByModelName, modelInstanceCreator, this.storageAdapter, this.sessionId);
1257
+ return [4 /*yield*/, this.storage.init()];
1258
+ case 1:
1259
+ _a.sent();
1260
+ _a.label = 2;
1261
+ case 2:
1053
1262
  if (syncSubscription && !syncSubscription.closed) {
1054
1263
  syncSubscription.unsubscribe();
1055
1264
  }
1056
1265
  return [4 /*yield*/, this.storage.clear()];
1057
- case 1:
1266
+ case 3:
1058
1267
  _a.sent();
1059
1268
  if (this.sync) {
1060
1269
  this.sync.unsubscribeConnectivity();
@@ -1222,9 +1431,8 @@ var DataStore = /** @class */ (function () {
1222
1431
  return sessionId + "-" + appSyncId;
1223
1432
  }
1224
1433
  }
1225
- catch (_b) {
1226
- return undefined;
1227
- }
1434
+ catch (_b) { }
1435
+ return undefined;
1228
1436
  };
1229
1437
  return DataStore;
1230
1438
  }());