@aws-amplify/datastore 3.14.1-unstable.2 → 3.14.1

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/CHANGELOG.md +12 -0
  2. package/dist/aws-amplify-datastore.js +2798 -1458
  3. package/dist/aws-amplify-datastore.js.map +1 -1
  4. package/dist/aws-amplify-datastore.min.js +10 -10
  5. package/dist/aws-amplify-datastore.min.js.map +1 -1
  6. package/lib/authModeStrategies/multiAuthStrategy.js +11 -0
  7. package/lib/authModeStrategies/multiAuthStrategy.js.map +1 -1
  8. package/lib/datastore/datastore.js +524 -323
  9. package/lib/datastore/datastore.js.map +1 -1
  10. package/lib/storage/adapter/IndexedDBAdapter.js +76 -25
  11. package/lib/storage/adapter/IndexedDBAdapter.js.map +1 -1
  12. package/lib/storage/storage.js +2 -2
  13. package/lib/storage/storage.js.map +1 -1
  14. package/lib/sync/datastoreConnectivity.js +45 -0
  15. package/lib/sync/datastoreConnectivity.js.map +1 -1
  16. package/lib/sync/index.js +518 -395
  17. package/lib/sync/index.js.map +1 -1
  18. package/lib/sync/merger.js +6 -0
  19. package/lib/sync/merger.js.map +1 -1
  20. package/lib/sync/outbox.js +66 -62
  21. package/lib/sync/outbox.js.map +1 -1
  22. package/lib/sync/processors/mutation.js +207 -165
  23. package/lib/sync/processors/mutation.js.map +1 -1
  24. package/lib/sync/processors/subscription.js +210 -175
  25. package/lib/sync/processors/subscription.js.map +1 -1
  26. package/lib/sync/processors/sync.js +95 -72
  27. package/lib/sync/processors/sync.js.map +1 -1
  28. package/lib/sync/utils.js +1 -3
  29. package/lib/sync/utils.js.map +1 -1
  30. package/lib/util.js +89 -0
  31. package/lib/util.js.map +1 -1
  32. package/lib-esm/authModeStrategies/multiAuthStrategy.d.ts +11 -0
  33. package/lib-esm/authModeStrategies/multiAuthStrategy.js +11 -0
  34. package/lib-esm/authModeStrategies/multiAuthStrategy.js.map +1 -1
  35. package/lib-esm/datastore/datastore.d.ts +95 -2
  36. package/lib-esm/datastore/datastore.js +524 -323
  37. package/lib-esm/datastore/datastore.js.map +1 -1
  38. package/lib-esm/storage/adapter/IndexedDBAdapter.d.ts +21 -0
  39. package/lib-esm/storage/adapter/IndexedDBAdapter.js +77 -26
  40. package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +1 -1
  41. package/lib-esm/storage/storage.js +2 -2
  42. package/lib-esm/storage/storage.js.map +1 -1
  43. package/lib-esm/sync/datastoreConnectivity.d.ts +1 -0
  44. package/lib-esm/sync/datastoreConnectivity.js +45 -0
  45. package/lib-esm/sync/datastoreConnectivity.js.map +1 -1
  46. package/lib-esm/sync/index.d.ts +9 -1
  47. package/lib-esm/sync/index.js +519 -396
  48. package/lib-esm/sync/index.js.map +1 -1
  49. package/lib-esm/sync/merger.d.ts +6 -0
  50. package/lib-esm/sync/merger.js +6 -0
  51. package/lib-esm/sync/merger.js.map +1 -1
  52. package/lib-esm/sync/outbox.js +66 -62
  53. package/lib-esm/sync/outbox.js.map +1 -1
  54. package/lib-esm/sync/processors/mutation.d.ts +2 -0
  55. package/lib-esm/sync/processors/mutation.js +208 -166
  56. package/lib-esm/sync/processors/mutation.js.map +1 -1
  57. package/lib-esm/sync/processors/subscription.d.ts +2 -0
  58. package/lib-esm/sync/processors/subscription.js +211 -176
  59. package/lib-esm/sync/processors/subscription.js.map +1 -1
  60. package/lib-esm/sync/processors/sync.d.ts +2 -0
  61. package/lib-esm/sync/processors/sync.js +96 -73
  62. package/lib-esm/sync/processors/sync.js.map +1 -1
  63. package/lib-esm/sync/utils.js +1 -3
  64. package/lib-esm/sync/utils.js.map +1 -1
  65. package/lib-esm/util.d.ts +11 -0
  66. package/lib-esm/util.js +89 -0
  67. package/lib-esm/util.js.map +1 -1
  68. package/package.json +7 -7
  69. package/src/authModeStrategies/multiAuthStrategy.ts +11 -0
  70. package/src/datastore/datastore.ts +572 -366
  71. package/src/storage/adapter/IndexedDBAdapter.ts +50 -9
  72. package/src/storage/storage.ts +2 -2
  73. package/src/sync/datastoreConnectivity.ts +6 -0
  74. package/src/sync/index.ts +492 -400
  75. package/src/sync/merger.ts +6 -0
  76. package/src/sync/outbox.ts +1 -1
  77. package/src/sync/processors/mutation.ts +139 -104
  78. package/src/sync/processors/subscription.ts +287 -250
  79. package/src/sync/processors/sync.ts +88 -60
  80. package/src/sync/utils.ts +1 -3
  81. package/src/util.ts +92 -2
  82. package/lib/authModeStrategies/defaultAuthStrategy.d.ts +0 -2
  83. package/lib/authModeStrategies/index.d.ts +0 -2
  84. package/lib/authModeStrategies/multiAuthStrategy.d.ts +0 -2
  85. package/lib/datastore/datastore.d.ts +0 -63
  86. package/lib/index.d.ts +0 -15
  87. package/lib/predicates/index.d.ts +0 -16
  88. package/lib/predicates/sort.d.ts +0 -8
  89. package/lib/ssr/index.d.ts +0 -3
  90. package/lib/storage/adapter/AsyncStorageAdapter.d.ts +0 -41
  91. package/lib/storage/adapter/AsyncStorageDatabase.d.ts +0 -39
  92. package/lib/storage/adapter/InMemoryStore.d.ts +0 -11
  93. package/lib/storage/adapter/InMemoryStore.native.d.ts +0 -1
  94. package/lib/storage/adapter/IndexedDBAdapter.d.ts +0 -38
  95. package/lib/storage/adapter/getDefaultAdapter/index.d.ts +0 -3
  96. package/lib/storage/adapter/getDefaultAdapter/index.native.d.ts +0 -3
  97. package/lib/storage/adapter/index.d.ts +0 -9
  98. package/lib/storage/storage.d.ts +0 -49
  99. package/lib/sync/datastoreConnectivity.d.ts +0 -15
  100. package/lib/sync/datastoreReachability/index.d.ts +0 -3
  101. package/lib/sync/datastoreReachability/index.native.d.ts +0 -3
  102. package/lib/sync/index.d.ts +0 -81
  103. package/lib/sync/merger.d.ts +0 -11
  104. package/lib/sync/outbox.d.ts +0 -27
  105. package/lib/sync/processors/errorMaps.d.ts +0 -17
  106. package/lib/sync/processors/mutation.d.ts +0 -56
  107. package/lib/sync/processors/subscription.d.ts +0 -31
  108. package/lib/sync/processors/sync.d.ts +0 -26
  109. package/lib/sync/utils.d.ts +0 -42
  110. package/lib/types.d.ts +0 -501
  111. package/lib/util.d.ts +0 -145
@@ -93,9 +93,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
93
93
  };
94
94
  Object.defineProperty(exports, "__esModule", { value: true });
95
95
  var api_1 = __importDefault(require("@aws-amplify/api"));
96
- var core_1 = require("@aws-amplify/core");
97
96
  var auth_1 = require("@aws-amplify/auth");
98
97
  var cache_1 = __importDefault(require("@aws-amplify/cache"));
98
+ var core_1 = require("@aws-amplify/core");
99
99
  var immer_1 = require("immer");
100
100
  var uuid_1 = require("uuid");
101
101
  var zen_observable_ts_1 = __importDefault(require("zen-observable-ts"));
@@ -209,10 +209,14 @@ var initSchema = function (userSchema) {
209
209
  return userClasses;
210
210
  };
211
211
  exports.initSchema = initSchema;
212
- /* Checks if the schema has been initialized by initSchema().
212
+ /**
213
+ * Throws an exception if the schema has *not* been initialized
214
+ * by `initSchema()`.
215
+ *
216
+ * **To be called before trying to access schema.**
213
217
  *
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.
218
+ * Currently this only needs to be called in `start()` and `clear()` because
219
+ * all other functions will call start first.
216
220
  */
217
221
  var checkSchemaInitialized = function () {
218
222
  if (schema === undefined) {
@@ -236,6 +240,11 @@ var createTypeClasses = function (namespace) {
236
240
  });
237
241
  return classes;
238
242
  };
243
+ /**
244
+ * Collection of instantiated models to allow storage of metadata apart from
245
+ * the model visible to the consuming app -- in case the app doesn't have
246
+ * metadata fields (_version, _deleted, etc.) exposed on the model itself.
247
+ */
239
248
  var instancesMetadata = new WeakSet();
240
249
  function modelInstanceCreator(modelConstructor, init) {
241
250
  instancesMetadata.add(init);
@@ -554,6 +563,18 @@ function getModelConstructorByModelName(namespaceName, modelName) {
554
563
  throw new Error(msg);
555
564
  }
556
565
  }
566
+ /**
567
+ * Queries the DataStore metadata tables to see if they are the expected
568
+ * version. If not, clobbers the whole DB. If so, leaves them alone.
569
+ * Otherwise, simply writes the schema version.
570
+ *
571
+ * SIDE EFFECT:
572
+ * 1. Creates a transaction
573
+ * 1. Updates data.
574
+ *
575
+ * @param storage Storage adapter containing the metadata.
576
+ * @param version The expected schema version.
577
+ */
557
578
  function checkSchemaVersion(storage, version) {
558
579
  return __awaiter(this, void 0, void 0, function () {
559
580
  var Setting, modelDefinition;
@@ -636,6 +657,14 @@ function getNamespace() {
636
657
  };
637
658
  return namespace;
638
659
  }
660
+ var DataStoreState;
661
+ (function (DataStoreState) {
662
+ DataStoreState["NotRunning"] = "Not Running";
663
+ DataStoreState["Starting"] = "Starting";
664
+ DataStoreState["Running"] = "Running";
665
+ DataStoreState["Stopping"] = "Stopping";
666
+ DataStoreState["Clearing"] = "Clearing";
667
+ })(DataStoreState || (DataStoreState = {}));
639
668
  var DataStore = /** @class */ (function () {
640
669
  function DataStore() {
641
670
  var _this = this;
@@ -651,168 +680,235 @@ var DataStore = /** @class */ (function () {
651
680
  API: this.API,
652
681
  Cache: this.Cache,
653
682
  };
683
+ /**
684
+ * **IMPORTANT!**
685
+ *
686
+ * Accumulator for background things that can **and MUST** be called when
687
+ * DataStore stops.
688
+ *
689
+ * These jobs **MUST** be *idempotent promises* that resolve ONLY
690
+ * once the intended jobs are completely finished and/or otherwise destroyed
691
+ * and cleaned up with ZERO outstanding:
692
+ *
693
+ * 1. side effects (e.g., state changes)
694
+ * 1. callbacks
695
+ * 1. subscriptions
696
+ * 1. calls to storage
697
+ * 1. *etc.*
698
+ *
699
+ * Methods that create pending promises, subscriptions, callbacks, or any
700
+ * type of side effect **MUST** be registered with the manager. And, a new
701
+ * manager must be created after each `exit()`.
702
+ *
703
+ * Failure to comply will put DataStore into a highly unpredictable state
704
+ * when it needs to stop or clear -- which occurs when restarting with new
705
+ * sync expressions, during testing, and potentially during app code
706
+ * recovery handling, etc..
707
+ *
708
+ * It is up to the discretion of each disposer whether to wait for job
709
+ * completion or to cancel operations and issue failures *as long as the
710
+ * disposer returns in a reasonable amount of time.*
711
+ *
712
+ * (Reasonable = *seconds*, not minutes.)
713
+ */
714
+ this.runningProcesses = new core_1.BackgroundProcessManager();
715
+ /**
716
+ * Indicates what state DataStore is in.
717
+ *
718
+ * Not [yet?] used for actual state management; but for messaging
719
+ * when errors occur, to help troubleshoot.
720
+ */
721
+ this.state = DataStoreState.NotRunning;
722
+ /**
723
+ * If not already done:
724
+ * 1. Attaches and initializes storage.
725
+ * 1. Loads the schema and records metadata.
726
+ * 1. If `this.amplifyConfig.aws_appsync_graphqlEndpoint` contains a URL,
727
+ * attaches a sync engine, starts it, and subscribes.
728
+ */
654
729
  this.start = function () { return __awaiter(_this, void 0, void 0, function () {
655
- var aws_appsync_graphqlEndpoint, _a, fullSyncIntervalInMilliseconds;
656
730
  var _this = this;
657
- return __generator(this, function (_b) {
658
- switch (_b.label) {
659
- case 0:
660
- if (!(this.initialized === undefined)) return [3 /*break*/, 1];
661
- logger.debug('Starting DataStore');
662
- this.initialized = new Promise(function (res, rej) {
663
- _this.initResolve = res;
664
- _this.initReject = rej;
665
- });
666
- return [3 /*break*/, 3];
667
- case 1: return [4 /*yield*/, this.initialized];
668
- case 2:
669
- _b.sent();
670
- return [2 /*return*/];
671
- case 3:
672
- this.storage = new storage_1.ExclusiveStorage(schema, namespaceResolver, getModelConstructorByModelName, modelInstanceCreator, this.storageAdapter, this.sessionId);
673
- return [4 /*yield*/, this.storage.init()];
674
- case 4:
675
- _b.sent();
676
- checkSchemaInitialized();
677
- return [4 /*yield*/, checkSchemaVersion(this.storage, schema.version)];
678
- case 5:
679
- _b.sent();
680
- aws_appsync_graphqlEndpoint = this.amplifyConfig.aws_appsync_graphqlEndpoint;
681
- if (!aws_appsync_graphqlEndpoint) return [3 /*break*/, 7];
682
- logger.debug('GraphQL endpoint available', aws_appsync_graphqlEndpoint);
683
- _a = this;
684
- return [4 /*yield*/, this.processSyncExpressions()];
685
- case 6:
686
- _a.syncPredicates = _b.sent();
687
- 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);
688
- fullSyncIntervalInMilliseconds = this.fullSyncInterval * 1000 * 60;
689
- syncSubscription = this.sync
690
- .start({ fullSyncInterval: fullSyncIntervalInMilliseconds })
691
- .subscribe({
692
- next: function (_a) {
693
- var type = _a.type, data = _a.data;
694
- // In Node, we need to wait for queries to be synced to prevent returning empty arrays.
695
- // In the Browser, we can begin returning data once subscriptions are in place.
696
- var readyType = isNode
697
- ? sync_1.ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY
698
- : sync_1.ControlMessage.SYNC_ENGINE_STORAGE_SUBSCRIBED;
699
- if (type === readyType) {
700
- _this.initResolve();
701
- }
702
- core_1.Hub.dispatch('datastore', {
703
- event: type,
704
- data: data,
705
- });
706
- },
707
- error: function (err) {
708
- logger.warn('Sync error', err);
709
- _this.initReject();
710
- },
711
- });
712
- return [3 /*break*/, 8];
713
- case 7:
714
- logger.warn("Data won't be synchronized. No GraphQL endpoint configured. Did you forget `Amplify.configure(awsconfig)`?", {
715
- config: this.amplifyConfig,
731
+ return __generator(this, function (_a) {
732
+ return [2 /*return*/, this.runningProcesses
733
+ .add(function () { return __awaiter(_this, void 0, void 0, function () {
734
+ var aws_appsync_graphqlEndpoint, _a, fullSyncIntervalInMilliseconds;
735
+ var _this = this;
736
+ return __generator(this, function (_b) {
737
+ switch (_b.label) {
738
+ case 0:
739
+ this.state = DataStoreState.Starting;
740
+ if (!(this.initialized === undefined)) return [3 /*break*/, 1];
741
+ logger.debug('Starting DataStore');
742
+ this.initialized = new Promise(function (res, rej) {
743
+ _this.initResolve = res;
744
+ _this.initReject = rej;
745
+ });
746
+ return [3 /*break*/, 3];
747
+ case 1: return [4 /*yield*/, this.initialized];
748
+ case 2:
749
+ _b.sent();
750
+ return [2 /*return*/];
751
+ case 3:
752
+ this.storage = new storage_1.ExclusiveStorage(schema, namespaceResolver, getModelConstructorByModelName, modelInstanceCreator, this.storageAdapter, this.sessionId);
753
+ return [4 /*yield*/, this.storage.init()];
754
+ case 4:
755
+ _b.sent();
756
+ checkSchemaInitialized();
757
+ return [4 /*yield*/, checkSchemaVersion(this.storage, schema.version)];
758
+ case 5:
759
+ _b.sent();
760
+ aws_appsync_graphqlEndpoint = this.amplifyConfig.aws_appsync_graphqlEndpoint;
761
+ if (!aws_appsync_graphqlEndpoint) return [3 /*break*/, 7];
762
+ logger.debug('GraphQL endpoint available', aws_appsync_graphqlEndpoint);
763
+ _a = this;
764
+ return [4 /*yield*/, this.processSyncExpressions()];
765
+ case 6:
766
+ _a.syncPredicates = _b.sent();
767
+ this.sync = new sync_1.SyncEngine(schema, namespaceResolver, exports.syncClasses, userClasses, this.storage, modelInstanceCreator, this.conflictHandler, this.errorHandler, this.syncPredicates, this.amplifyConfig, this.authModeStrategy, this.amplifyContext, this.connectivityMonitor);
768
+ fullSyncIntervalInMilliseconds = this.fullSyncInterval * 1000 * 60;
769
+ syncSubscription = this.sync
770
+ .start({ fullSyncInterval: fullSyncIntervalInMilliseconds })
771
+ .subscribe({
772
+ next: function (_a) {
773
+ var type = _a.type, data = _a.data;
774
+ // In Node, we need to wait for queries to be synced to prevent returning empty arrays.
775
+ // In the Browser, we can begin returning data once subscriptions are in place.
776
+ var readyType = isNode
777
+ ? sync_1.ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY
778
+ : sync_1.ControlMessage.SYNC_ENGINE_STORAGE_SUBSCRIBED;
779
+ if (type === readyType) {
780
+ _this.initResolve();
781
+ }
782
+ core_1.Hub.dispatch('datastore', {
783
+ event: type,
784
+ data: data,
785
+ });
786
+ },
787
+ error: function (err) {
788
+ logger.warn('Sync error', err);
789
+ _this.initReject();
790
+ },
791
+ });
792
+ return [3 /*break*/, 8];
793
+ case 7:
794
+ logger.warn("Data won't be synchronized. No GraphQL endpoint configured. Did you forget `Amplify.configure(awsconfig)`?", {
795
+ config: this.amplifyConfig,
796
+ });
797
+ this.initResolve();
798
+ _b.label = 8;
799
+ case 8: return [4 /*yield*/, this.initialized];
800
+ case 9:
801
+ _b.sent();
802
+ this.state = DataStoreState.Running;
803
+ return [2 /*return*/];
804
+ }
716
805
  });
717
- this.initResolve();
718
- _b.label = 8;
719
- case 8: return [4 /*yield*/, this.initialized];
720
- case 9:
721
- _b.sent();
722
- return [2 /*return*/];
723
- }
806
+ }); }, 'datastore start')
807
+ .catch(this.handleAddProcError('DataStore.start()'))];
724
808
  });
725
809
  }); };
726
810
  this.query = function (modelConstructor, identifierOrCriteria, paginationProducer) { return __awaiter(_this, void 0, void 0, function () {
727
- var msg, modelDefinition, keyFields, predicate, msg, pagination, result, returnOne;
811
+ var _this = this;
728
812
  return __generator(this, function (_a) {
729
- switch (_a.label) {
730
- case 0: return [4 /*yield*/, this.start()];
731
- case 1:
732
- _a.sent();
733
- //#region Input validation
734
- if (!isValidModelConstructor(modelConstructor)) {
735
- msg = 'Constructor is not for a valid model';
736
- logger.error(msg, { modelConstructor: modelConstructor });
737
- throw new Error(msg);
738
- }
739
- if (typeof identifierOrCriteria === 'string') {
740
- if (paginationProducer !== undefined) {
741
- logger.warn('Pagination is ignored when querying by id');
742
- }
743
- }
744
- modelDefinition = getModelDefinition(modelConstructor);
745
- keyFields = util_1.extractPrimaryKeyFieldNames(modelDefinition);
746
- if (isQueryOne(identifierOrCriteria)) {
747
- if (keyFields.length > 1) {
748
- msg = util_1.errorMessages.queryByPkWithCompositeKeyPresent;
749
- logger.error(msg, { keyFields: keyFields });
750
- throw new Error(msg);
751
- }
752
- predicate = predicates_1.ModelPredicateCreator.createForSingleField(modelDefinition, keyFields[0], identifierOrCriteria);
753
- }
754
- else {
755
- // Object is being queried using object literal syntax
756
- if (types_1.isIdentifierObject(identifierOrCriteria, modelDefinition)) {
757
- predicate = predicates_1.ModelPredicateCreator.createForPk(modelDefinition, identifierOrCriteria);
758
- }
759
- else if (predicates_1.isPredicatesAll(identifierOrCriteria)) {
760
- // Predicates.ALL means "all records", so no predicate (undefined)
761
- predicate = undefined;
762
- }
763
- else {
764
- predicate = predicates_1.ModelPredicateCreator.createFromExisting(modelDefinition, identifierOrCriteria);
813
+ return [2 /*return*/, this.runningProcesses
814
+ .add(function () { return __awaiter(_this, void 0, void 0, function () {
815
+ var msg, modelDefinition, keyFields, predicate, msg, pagination, result, returnOne;
816
+ return __generator(this, function (_a) {
817
+ switch (_a.label) {
818
+ case 0: return [4 /*yield*/, this.start()];
819
+ case 1:
820
+ _a.sent();
821
+ //#region Input validation
822
+ if (!isValidModelConstructor(modelConstructor)) {
823
+ msg = 'Constructor is not for a valid model';
824
+ logger.error(msg, { modelConstructor: modelConstructor });
825
+ throw new Error(msg);
826
+ }
827
+ if (typeof identifierOrCriteria === 'string') {
828
+ if (paginationProducer !== undefined) {
829
+ logger.warn('Pagination is ignored when querying by id');
830
+ }
831
+ }
832
+ modelDefinition = getModelDefinition(modelConstructor);
833
+ keyFields = util_1.extractPrimaryKeyFieldNames(modelDefinition);
834
+ if (isQueryOne(identifierOrCriteria)) {
835
+ if (keyFields.length > 1) {
836
+ msg = util_1.errorMessages.queryByPkWithCompositeKeyPresent;
837
+ logger.error(msg, { keyFields: keyFields });
838
+ throw new Error(msg);
839
+ }
840
+ predicate = predicates_1.ModelPredicateCreator.createForSingleField(modelDefinition, keyFields[0], identifierOrCriteria);
841
+ }
842
+ else {
843
+ // Object is being queried using object literal syntax
844
+ if (types_1.isIdentifierObject(identifierOrCriteria, modelDefinition)) {
845
+ predicate = predicates_1.ModelPredicateCreator.createForPk(modelDefinition, identifierOrCriteria);
846
+ }
847
+ else if (predicates_1.isPredicatesAll(identifierOrCriteria)) {
848
+ // Predicates.ALL means "all records", so no predicate (undefined)
849
+ predicate = undefined;
850
+ }
851
+ else {
852
+ predicate = predicates_1.ModelPredicateCreator.createFromExisting(modelDefinition, identifierOrCriteria);
853
+ }
854
+ }
855
+ pagination = this.processPagination(modelDefinition, paginationProducer);
856
+ //#endregion
857
+ logger.debug('params ready', {
858
+ modelConstructor: modelConstructor,
859
+ predicate: predicates_1.ModelPredicateCreator.getPredicates(predicate, false),
860
+ pagination: __assign(__assign({}, pagination), { sort: predicates_1.ModelSortPredicateCreator.getPredicates(pagination && pagination.sort, false) }),
861
+ });
862
+ return [4 /*yield*/, this.storage.query(modelConstructor, predicate, pagination)];
863
+ case 2:
864
+ result = _a.sent();
865
+ returnOne = isQueryOne(identifierOrCriteria) ||
866
+ types_1.isIdentifierObject(identifierOrCriteria, modelDefinition);
867
+ return [2 /*return*/, returnOne ? result[0] : result];
765
868
  }
766
- }
767
- pagination = this.processPagination(modelDefinition, paginationProducer);
768
- //#endregion
769
- logger.debug('params ready', {
770
- modelConstructor: modelConstructor,
771
- predicate: predicates_1.ModelPredicateCreator.getPredicates(predicate, false),
772
- pagination: __assign(__assign({}, pagination), { sort: predicates_1.ModelSortPredicateCreator.getPredicates(pagination && pagination.sort, false) }),
773
869
  });
774
- return [4 /*yield*/, this.storage.query(modelConstructor, predicate, pagination)];
775
- case 2:
776
- result = _a.sent();
777
- returnOne = isQueryOne(identifierOrCriteria) ||
778
- types_1.isIdentifierObject(identifierOrCriteria, modelDefinition);
779
- return [2 /*return*/, returnOne ? result[0] : result];
780
- }
870
+ }); }, 'datastore query')
871
+ .catch(this.handleAddProcError('DataStore.query()'))];
781
872
  });
782
873
  }); };
783
874
  this.save = function (model, condition) { return __awaiter(_this, void 0, void 0, function () {
784
- var patchesTuple, modelConstructor, msg, modelDefinition, producedCondition, _a, savedModel;
785
875
  var _this = this;
786
- return __generator(this, function (_b) {
787
- switch (_b.label) {
788
- case 0: return [4 /*yield*/, this.start()];
789
- case 1:
790
- _b.sent();
791
- patchesTuple = modelPatchesMap.get(model);
792
- modelConstructor = model
793
- ? model.constructor
794
- : undefined;
795
- if (!isValidModelConstructor(modelConstructor)) {
796
- msg = 'Object is not an instance of a valid model';
797
- logger.error(msg, { model: model });
798
- throw new Error(msg);
799
- }
800
- modelDefinition = getModelDefinition(modelConstructor);
801
- producedCondition = predicates_1.ModelPredicateCreator.createFromExisting(modelDefinition, condition);
802
- return [4 /*yield*/, this.storage.runExclusive(function (s) { return __awaiter(_this, void 0, void 0, function () {
803
- return __generator(this, function (_a) {
804
- switch (_a.label) {
805
- case 0: return [4 /*yield*/, s.save(model, producedCondition, undefined, patchesTuple)];
806
- case 1:
807
- _a.sent();
808
- return [2 /*return*/, s.query(modelConstructor, predicates_1.ModelPredicateCreator.createForPk(modelDefinition, model))];
876
+ return __generator(this, function (_a) {
877
+ return [2 /*return*/, this.runningProcesses
878
+ .add(function () { return __awaiter(_this, void 0, void 0, function () {
879
+ var patchesTuple, modelConstructor, msg, modelDefinition, producedCondition, _a, savedModel;
880
+ var _this = this;
881
+ return __generator(this, function (_b) {
882
+ switch (_b.label) {
883
+ case 0: return [4 /*yield*/, this.start()];
884
+ case 1:
885
+ _b.sent();
886
+ patchesTuple = modelPatchesMap.get(model);
887
+ modelConstructor = model ? model.constructor : undefined;
888
+ if (!isValidModelConstructor(modelConstructor)) {
889
+ msg = 'Object is not an instance of a valid model';
890
+ logger.error(msg, { model: model });
891
+ throw new Error(msg);
809
892
  }
810
- });
811
- }); })];
812
- case 2:
813
- _a = __read.apply(void 0, [_b.sent(), 1]), savedModel = _a[0];
814
- return [2 /*return*/, savedModel];
815
- }
893
+ modelDefinition = getModelDefinition(modelConstructor);
894
+ producedCondition = predicates_1.ModelPredicateCreator.createFromExisting(modelDefinition, condition);
895
+ return [4 /*yield*/, this.storage.runExclusive(function (s) { return __awaiter(_this, void 0, void 0, function () {
896
+ return __generator(this, function (_a) {
897
+ switch (_a.label) {
898
+ case 0: return [4 /*yield*/, s.save(model, producedCondition, undefined, patchesTuple)];
899
+ case 1:
900
+ _a.sent();
901
+ return [2 /*return*/, s.query(modelConstructor, predicates_1.ModelPredicateCreator.createForPk(modelDefinition, model))];
902
+ }
903
+ });
904
+ }); })];
905
+ case 2:
906
+ _a = __read.apply(void 0, [_b.sent(), 1]), savedModel = _a[0];
907
+ return [2 /*return*/, savedModel];
908
+ }
909
+ });
910
+ }); }, 'datastore save')
911
+ .catch(this.handleAddProcError('DataStore.save()'))];
816
912
  });
817
913
  }); };
818
914
  this.setConflictHandler = function (config) {
@@ -842,83 +938,91 @@ var DataStore = /** @class */ (function () {
842
938
  return _this.errorHandler || defaultErrorHandler;
843
939
  };
844
940
  this.delete = function (modelOrConstructor, identifierOrCriteria) { return __awaiter(_this, void 0, void 0, function () {
845
- var condition, msg, modelConstructor, msg, modelDefinition, keyFields, msg, msg, _a, deleted, model, modelConstructor, msg, modelDefinition, pkPredicate, msg, _b, _c, deleted;
846
- return __generator(this, function (_d) {
847
- switch (_d.label) {
848
- case 0: return [4 /*yield*/, this.start()];
849
- case 1:
850
- _d.sent();
851
- if (!modelOrConstructor) {
852
- msg = 'Model or Model Constructor required';
853
- logger.error(msg, { modelOrConstructor: modelOrConstructor });
854
- throw new Error(msg);
855
- }
856
- if (!isValidModelConstructor(modelOrConstructor)) return [3 /*break*/, 3];
857
- modelConstructor = modelOrConstructor;
858
- if (!identifierOrCriteria) {
859
- msg = 'Id to delete or criteria required. Do you want to delete all? Pass Predicates.ALL';
860
- logger.error(msg, { identifierOrCriteria: identifierOrCriteria });
861
- throw new Error(msg);
862
- }
863
- modelDefinition = getModelDefinition(modelConstructor);
864
- if (typeof identifierOrCriteria === 'string') {
865
- keyFields = util_1.extractPrimaryKeyFieldNames(modelDefinition);
866
- if (keyFields.length > 1) {
867
- msg = util_1.errorMessages.deleteByPkWithCompositeKeyPresent;
868
- logger.error(msg, { keyFields: keyFields });
869
- throw new Error(msg);
870
- }
871
- condition = predicates_1.ModelPredicateCreator.createForSingleField(getModelDefinition(modelConstructor), keyFields[0], identifierOrCriteria);
872
- }
873
- else {
874
- if (types_1.isIdentifierObject(identifierOrCriteria, modelDefinition)) {
875
- condition = predicates_1.ModelPredicateCreator.createForPk(modelDefinition, identifierOrCriteria);
876
- }
877
- else {
878
- condition = predicates_1.ModelPredicateCreator.createFromExisting(modelDefinition,
879
- /**
880
- * idOrCriteria is always a ProducerModelPredicate<T>, never a symbol.
881
- * The symbol is used only for typing purposes. e.g. see Predicates.ALL
882
- */
883
- identifierOrCriteria);
884
- }
885
- if (!condition || !predicates_1.ModelPredicateCreator.isValidPredicate(condition)) {
886
- msg = 'Criteria required. Do you want to delete all? Pass Predicates.ALL';
887
- logger.error(msg, { condition: condition });
888
- throw new Error(msg);
889
- }
890
- }
891
- return [4 /*yield*/, this.storage.delete(modelConstructor, condition)];
892
- case 2:
893
- _a = __read.apply(void 0, [_d.sent(), 1]), deleted = _a[0];
894
- return [2 /*return*/, deleted];
895
- case 3:
896
- model = modelOrConstructor;
897
- modelConstructor = Object.getPrototypeOf(model || {})
898
- .constructor;
899
- if (!isValidModelConstructor(modelConstructor)) {
900
- msg = 'Object is not an instance of a valid model';
901
- logger.error(msg, { model: model });
902
- throw new Error(msg);
903
- }
904
- modelDefinition = getModelDefinition(modelConstructor);
905
- pkPredicate = predicates_1.ModelPredicateCreator.createForPk(modelDefinition, model);
906
- if (identifierOrCriteria) {
907
- if (typeof identifierOrCriteria !== 'function') {
908
- msg = 'Invalid criteria';
909
- logger.error(msg, { identifierOrCriteria: identifierOrCriteria });
910
- throw new Error(msg);
941
+ var _this = this;
942
+ return __generator(this, function (_a) {
943
+ return [2 /*return*/, this.runningProcesses
944
+ .add(function () { return __awaiter(_this, void 0, void 0, function () {
945
+ var condition, msg, modelConstructor, msg, modelDefinition, keyFields, msg, msg, _a, deleted, model, modelConstructor, msg, modelDefinition, pkPredicate, msg, _b, _c, deleted;
946
+ return __generator(this, function (_d) {
947
+ switch (_d.label) {
948
+ case 0: return [4 /*yield*/, this.start()];
949
+ case 1:
950
+ _d.sent();
951
+ if (!modelOrConstructor) {
952
+ msg = 'Model or Model Constructor required';
953
+ logger.error(msg, { modelOrConstructor: modelOrConstructor });
954
+ throw new Error(msg);
955
+ }
956
+ if (!isValidModelConstructor(modelOrConstructor)) return [3 /*break*/, 3];
957
+ modelConstructor = modelOrConstructor;
958
+ if (!identifierOrCriteria) {
959
+ msg = 'Id to delete or criteria required. Do you want to delete all? Pass Predicates.ALL';
960
+ logger.error(msg, { identifierOrCriteria: identifierOrCriteria });
961
+ throw new Error(msg);
962
+ }
963
+ modelDefinition = getModelDefinition(modelConstructor);
964
+ if (typeof identifierOrCriteria === 'string') {
965
+ keyFields = util_1.extractPrimaryKeyFieldNames(modelDefinition);
966
+ if (keyFields.length > 1) {
967
+ msg = util_1.errorMessages.deleteByPkWithCompositeKeyPresent;
968
+ logger.error(msg, { keyFields: keyFields });
969
+ throw new Error(msg);
970
+ }
971
+ condition = predicates_1.ModelPredicateCreator.createForSingleField(getModelDefinition(modelConstructor), keyFields[0], identifierOrCriteria);
972
+ }
973
+ else {
974
+ if (types_1.isIdentifierObject(identifierOrCriteria, modelDefinition)) {
975
+ condition = predicates_1.ModelPredicateCreator.createForPk(modelDefinition, identifierOrCriteria);
976
+ }
977
+ else {
978
+ condition = predicates_1.ModelPredicateCreator.createFromExisting(modelDefinition,
979
+ /**
980
+ * idOrCriteria is always a ProducerModelPredicate<T>, never a symbol.
981
+ * The symbol is used only for typing purposes. e.g. see Predicates.ALL
982
+ */
983
+ identifierOrCriteria);
984
+ }
985
+ if (!condition ||
986
+ !predicates_1.ModelPredicateCreator.isValidPredicate(condition)) {
987
+ msg = 'Criteria required. Do you want to delete all? Pass Predicates.ALL';
988
+ logger.error(msg, { condition: condition });
989
+ throw new Error(msg);
990
+ }
991
+ }
992
+ return [4 /*yield*/, this.storage.delete(modelConstructor, condition)];
993
+ case 2:
994
+ _a = __read.apply(void 0, [_d.sent(), 1]), deleted = _a[0];
995
+ return [2 /*return*/, deleted];
996
+ case 3:
997
+ model = modelOrConstructor;
998
+ modelConstructor = Object.getPrototypeOf(model || {})
999
+ .constructor;
1000
+ if (!isValidModelConstructor(modelConstructor)) {
1001
+ msg = 'Object is not an instance of a valid model';
1002
+ logger.error(msg, { model: model });
1003
+ throw new Error(msg);
1004
+ }
1005
+ modelDefinition = getModelDefinition(modelConstructor);
1006
+ pkPredicate = predicates_1.ModelPredicateCreator.createForPk(modelDefinition, model);
1007
+ if (identifierOrCriteria) {
1008
+ if (typeof identifierOrCriteria !== 'function') {
1009
+ msg = 'Invalid criteria';
1010
+ logger.error(msg, { identifierOrCriteria: identifierOrCriteria });
1011
+ throw new Error(msg);
1012
+ }
1013
+ condition = identifierOrCriteria(pkPredicate);
1014
+ }
1015
+ else {
1016
+ condition = pkPredicate;
1017
+ }
1018
+ return [4 /*yield*/, this.storage.delete(model, condition)];
1019
+ case 4:
1020
+ _b = __read.apply(void 0, [_d.sent(), 1]), _c = __read(_b[0], 1), deleted = _c[0];
1021
+ return [2 /*return*/, deleted];
911
1022
  }
912
- condition = identifierOrCriteria(pkPredicate);
913
- }
914
- else {
915
- condition = pkPredicate;
916
- }
917
- return [4 /*yield*/, this.storage.delete(model, condition)];
918
- case 4:
919
- _b = __read.apply(void 0, [_d.sent(), 1]), _c = __read(_b[0], 1), deleted = _c[0];
920
- return [2 /*return*/, deleted];
921
- }
1023
+ });
1024
+ }); }, 'datastore delete')
1025
+ .catch(this.handleAddProcError('DataStore.delete()'))];
922
1026
  });
923
1027
  }); };
924
1028
  this.observe = function (modelOrConstructor, identifierOrCriteria) {
@@ -979,7 +1083,8 @@ var DataStore = /** @class */ (function () {
979
1083
  }
980
1084
  return new zen_observable_ts_1.default(function (observer) {
981
1085
  var handle;
982
- (function () { return __awaiter(_this, void 0, void 0, function () {
1086
+ _this.runningProcesses
1087
+ .add(function () { return __awaiter(_this, void 0, void 0, function () {
983
1088
  var _this = this;
984
1089
  return __generator(this, function (_a) {
985
1090
  switch (_a.label) {
@@ -995,39 +1100,52 @@ var DataStore = /** @class */ (function () {
995
1100
  return namespaceResolver(model) === util_1.USER;
996
1101
  })
997
1102
  .subscribe({
998
- next: function (item) { return __awaiter(_this, void 0, void 0, function () {
999
- var message, modelDefinition, keyFields, primaryKeysAndValues, freshElement;
1000
- return __generator(this, function (_a) {
1001
- switch (_a.label) {
1002
- case 0:
1003
- message = item;
1004
- if (!(item.opType !== 'DELETE')) return [3 /*break*/, 2];
1005
- modelDefinition = getModelDefinition(item.model);
1006
- keyFields = util_1.extractPrimaryKeyFieldNames(modelDefinition);
1007
- primaryKeysAndValues = util_1.extractPrimaryKeysAndValues(item.element, keyFields);
1008
- return [4 /*yield*/, this.query(item.model, primaryKeysAndValues)];
1009
- case 1:
1010
- freshElement = _a.sent();
1011
- message = __assign(__assign({}, message), { element: freshElement });
1012
- _a.label = 2;
1013
- case 2:
1014
- observer.next(message);
1015
- return [2 /*return*/];
1016
- }
1017
- });
1018
- }); },
1103
+ next: function (item) {
1104
+ return _this.runningProcesses.isOpen &&
1105
+ _this.runningProcesses.add(function () { return __awaiter(_this, void 0, void 0, function () {
1106
+ var message, modelDefinition, keyFields, primaryKeysAndValues, freshElement;
1107
+ return __generator(this, function (_a) {
1108
+ switch (_a.label) {
1109
+ case 0:
1110
+ message = item;
1111
+ if (!(item.opType !== 'DELETE')) return [3 /*break*/, 2];
1112
+ modelDefinition = getModelDefinition(item.model);
1113
+ keyFields = util_1.extractPrimaryKeyFieldNames(modelDefinition);
1114
+ primaryKeysAndValues = util_1.extractPrimaryKeysAndValues(item.element, keyFields);
1115
+ return [4 /*yield*/, this.query(item.model, primaryKeysAndValues)];
1116
+ case 1:
1117
+ freshElement = _a.sent();
1118
+ message = __assign(__assign({}, message), { element: freshElement });
1119
+ _a.label = 2;
1120
+ case 2:
1121
+ observer.next(message);
1122
+ return [2 /*return*/];
1123
+ }
1124
+ });
1125
+ }); }, 'datastore observe message handler');
1126
+ },
1019
1127
  error: function (err) { return observer.error(err); },
1020
1128
  complete: function () { return observer.complete(); },
1021
1129
  });
1022
1130
  return [2 /*return*/];
1023
1131
  }
1024
1132
  });
1025
- }); })();
1026
- return function () {
1027
- if (handle) {
1028
- handle.unsubscribe();
1029
- }
1030
- };
1133
+ }); }, 'datastore observe observable initialization')
1134
+ .catch(_this.handleAddProcError('DataStore.observe()'))
1135
+ .catch(function (error) {
1136
+ observer.error(error);
1137
+ });
1138
+ // better than no cleaner, but if the subscriber is handling the
1139
+ // complete() message async and not registering with the context,
1140
+ // this will still be problematic.
1141
+ return _this.runningProcesses.addCleaner(function () { return __awaiter(_this, void 0, void 0, function () {
1142
+ return __generator(this, function (_a) {
1143
+ if (handle) {
1144
+ handle.unsubscribe();
1145
+ }
1146
+ return [2 /*return*/];
1147
+ });
1148
+ }); }, 'DataStore.observe() cleanup');
1031
1149
  });
1032
1150
  };
1033
1151
  this.observeQuery = function (model, criteria, options) {
@@ -1076,7 +1194,8 @@ var DataStore = /** @class */ (function () {
1076
1194
  }
1077
1195
  var _a = predicates_1.ModelPredicateCreator.getPredicates(predicate, false) || {}, predicates = _a.predicates, predicateGroupType = _a.type;
1078
1196
  var hasPredicate = !!predicates;
1079
- (function () { return __awaiter(_this, void 0, void 0, function () {
1197
+ _this.runningProcesses
1198
+ .add(function () { return __awaiter(_this, void 0, void 0, function () {
1080
1199
  var err_1;
1081
1200
  var _this = this;
1082
1201
  return __generator(this, function (_a) {
@@ -1126,7 +1245,8 @@ var DataStore = /** @class */ (function () {
1126
1245
  itemsChanged.set(idOrPk, element);
1127
1246
  }
1128
1247
  var isSynced = (_c = (_b = _this.sync) === null || _b === void 0 ? void 0 : _b.getModelSyncedStatus(model)) !== null && _c !== void 0 ? _c : false;
1129
- var limit = itemsChanged.size - deletedItemIds.length >= _this.syncPageSize;
1248
+ var limit = itemsChanged.size - deletedItemIds.length >=
1249
+ _this.syncPageSize;
1130
1250
  if (limit || isSynced) {
1131
1251
  limitTimerRace.resolve();
1132
1252
  }
@@ -1143,7 +1263,11 @@ var DataStore = /** @class */ (function () {
1143
1263
  case 3: return [2 /*return*/];
1144
1264
  }
1145
1265
  });
1146
- }); })();
1266
+ }); }, 'datastore observequery startup')
1267
+ .catch(_this.handleAddProcError('DataStore.observeQuery()'))
1268
+ .catch(function (error) {
1269
+ observer.error(error);
1270
+ });
1147
1271
  /**
1148
1272
  * Combines the `items`, `itemsChanged`, and `deletedItemIds` collections into
1149
1273
  * a snapshot in the form of `{ items: T[], isSynced: boolean}`.
@@ -1179,7 +1303,8 @@ var DataStore = /** @class */ (function () {
1179
1303
  * @param snapshot The generated items data to emit.
1180
1304
  */
1181
1305
  var emitSnapshot = function (snapshot) {
1182
- // send the generated snapshot to the primary subscription
1306
+ // send the generated snapshot to the primary subscription.
1307
+ // NOTE: This observer's handler *could* be async ...
1183
1308
  observer.next(snapshot);
1184
1309
  // reset the changed items sets
1185
1310
  itemsChanged.clear();
@@ -1215,15 +1340,18 @@ var DataStore = /** @class */ (function () {
1215
1340
  if (event === sync_1.ControlMessage.SYNC_ENGINE_MODEL_SYNCED &&
1216
1341
  ((_b = data === null || data === void 0 ? void 0 : data.model) === null || _b === void 0 ? void 0 : _b.name) === model.name) {
1217
1342
  generateAndEmitSnapshot();
1218
- core_1.Hub.remove('api', hubCallback);
1343
+ core_1.Hub.remove('datastore', hubCallback);
1219
1344
  }
1220
1345
  };
1221
1346
  core_1.Hub.listen('datastore', hubCallback);
1222
- return function () {
1223
- if (handle) {
1224
- handle.unsubscribe();
1225
- }
1226
- };
1347
+ return _this.runningProcesses.addCleaner(function () { return __awaiter(_this, void 0, void 0, function () {
1348
+ return __generator(this, function (_a) {
1349
+ if (handle) {
1350
+ handle.unsubscribe();
1351
+ }
1352
+ return [2 /*return*/];
1353
+ });
1354
+ }); }, 'datastore observequery cleaner');
1227
1355
  });
1228
1356
  };
1229
1357
  this.configure = function (config) {
@@ -1282,66 +1410,132 @@ var DataStore = /** @class */ (function () {
1282
1410
  undefined;
1283
1411
  _this.sessionId = _this.retrieveSessionId();
1284
1412
  };
1285
- this.clear = function clear() {
1286
- return __awaiter(this, void 0, void 0, function () {
1287
- return __generator(this, function (_a) {
1288
- switch (_a.label) {
1289
- case 0:
1290
- checkSchemaInitialized();
1291
- if (!(this.storage === undefined)) return [3 /*break*/, 2];
1292
- // connect to storage so that it can be cleared without fully starting DataStore
1293
- this.storage = new storage_1.ExclusiveStorage(schema, namespaceResolver, getModelConstructorByModelName, modelInstanceCreator, this.storageAdapter, this.sessionId);
1294
- return [4 /*yield*/, this.storage.init()];
1295
- case 1:
1296
- _a.sent();
1297
- _a.label = 2;
1298
- case 2:
1299
- if (syncSubscription && !syncSubscription.closed) {
1300
- syncSubscription.unsubscribe();
1301
- }
1302
- return [4 /*yield*/, this.storage.clear()];
1303
- case 3:
1304
- _a.sent();
1305
- if (this.sync) {
1306
- this.sync.unsubscribeConnectivity();
1307
- }
1308
- this.initialized = undefined; // Should re-initialize when start() is called.
1309
- this.storage = undefined;
1310
- this.sync = undefined;
1311
- this.syncPredicates = new WeakMap();
1312
- return [2 /*return*/];
1313
- }
1314
- });
1315
- });
1316
- };
1317
- this.stop = function stop() {
1318
- return __awaiter(this, void 0, void 0, function () {
1319
- return __generator(this, function (_a) {
1320
- switch (_a.label) {
1321
- case 0:
1322
- if (!(this.initialized !== undefined)) return [3 /*break*/, 2];
1323
- return [4 /*yield*/, this.start()];
1324
- case 1:
1325
- _a.sent();
1326
- _a.label = 2;
1327
- case 2:
1328
- if (syncSubscription && !syncSubscription.closed) {
1329
- syncSubscription.unsubscribe();
1330
- }
1331
- if (this.sync) {
1332
- this.sync.unsubscribeConnectivity();
1333
- }
1334
- this.initialized = undefined; // Should re-initialize when start() is called.
1335
- this.sync = undefined;
1336
- return [2 /*return*/];
1337
- }
1338
- });
1339
- });
1340
- };
1341
1413
  }
1342
1414
  DataStore.prototype.getModuleName = function () {
1343
1415
  return 'DataStore';
1344
1416
  };
1417
+ /**
1418
+ * Builds a function to capture `BackgroundManagerNotOpenError`'s to produce friendlier,
1419
+ * more instructive errors for customers.
1420
+ *
1421
+ * @param operation The name of the operation (usually a Datastore method) the customer
1422
+ * tried to call.
1423
+ */
1424
+ DataStore.prototype.handleAddProcError = function (operation) {
1425
+ var _this = this;
1426
+ /**
1427
+ * If the tested error is a `BackgroundManagerNotOpenError`, it will be captured
1428
+ * and replaced with a friendlier message that instructs the App Developer.
1429
+ *
1430
+ * @param err An error to test.
1431
+ */
1432
+ var handler = function (err) {
1433
+ if (err.message.startsWith('BackgroundManagerNotOpenError')) {
1434
+ throw new Error([
1435
+ "DataStoreStateError: Tried to execute `" + operation + "` while DataStore was \"" + _this.state + "\".",
1436
+ "This can only be done while DataStore is \"Started\" or \"Stopped\". To remedy:",
1437
+ 'Ensure all calls to `stop()` and `clear()` have completed first.',
1438
+ 'If this is not possible, retry the operation until it succeeds.',
1439
+ ].join('\n'));
1440
+ }
1441
+ else {
1442
+ throw err;
1443
+ }
1444
+ };
1445
+ return handler;
1446
+ };
1447
+ /**
1448
+ * Clears all data from storage and removes all data, schema info, other
1449
+ * initialization details, and then stops DataStore.
1450
+ *
1451
+ * That said, reinitialization is required after clearing. This can be done
1452
+ * by explicitiliy calling `start()` or any method that implicitly starts
1453
+ * DataStore, such as `query()`, `save()`, or `delete()`.
1454
+ */
1455
+ DataStore.prototype.clear = function () {
1456
+ return __awaiter(this, void 0, void 0, function () {
1457
+ return __generator(this, function (_a) {
1458
+ switch (_a.label) {
1459
+ case 0:
1460
+ checkSchemaInitialized();
1461
+ this.state = DataStoreState.Clearing;
1462
+ return [4 /*yield*/, this.runningProcesses.close()];
1463
+ case 1:
1464
+ _a.sent();
1465
+ if (!(this.storage === undefined)) return [3 /*break*/, 3];
1466
+ // connect to storage so that it can be cleared without fully starting DataStore
1467
+ this.storage = new storage_1.ExclusiveStorage(schema, namespaceResolver, getModelConstructorByModelName, modelInstanceCreator, this.storageAdapter, this.sessionId);
1468
+ return [4 /*yield*/, this.storage.init()];
1469
+ case 2:
1470
+ _a.sent();
1471
+ _a.label = 3;
1472
+ case 3:
1473
+ if (syncSubscription && !syncSubscription.closed) {
1474
+ syncSubscription.unsubscribe();
1475
+ }
1476
+ if (!this.sync) return [3 /*break*/, 5];
1477
+ return [4 /*yield*/, this.sync.stop()];
1478
+ case 4:
1479
+ _a.sent();
1480
+ _a.label = 5;
1481
+ case 5: return [4 /*yield*/, this.storage.clear()];
1482
+ case 6:
1483
+ _a.sent();
1484
+ this.initialized = undefined; // Should re-initialize when start() is called.
1485
+ this.storage = undefined;
1486
+ this.sync = undefined;
1487
+ this.syncPredicates = new WeakMap();
1488
+ return [4 /*yield*/, this.runningProcesses.open()];
1489
+ case 7:
1490
+ _a.sent();
1491
+ this.state = DataStoreState.NotRunning;
1492
+ return [2 /*return*/];
1493
+ }
1494
+ });
1495
+ });
1496
+ };
1497
+ /**
1498
+ * Stops all DataStore sync activities.
1499
+ *
1500
+ * TODO: "Waits for graceful termination of
1501
+ * running queries and terminates subscriptions."
1502
+ */
1503
+ DataStore.prototype.stop = function () {
1504
+ return __awaiter(this, void 0, void 0, function () {
1505
+ return __generator(this, function (_a) {
1506
+ switch (_a.label) {
1507
+ case 0:
1508
+ this.state = DataStoreState.Stopping;
1509
+ return [4 /*yield*/, this.runningProcesses.close()];
1510
+ case 1:
1511
+ _a.sent();
1512
+ if (syncSubscription && !syncSubscription.closed) {
1513
+ syncSubscription.unsubscribe();
1514
+ }
1515
+ if (!this.sync) return [3 /*break*/, 3];
1516
+ return [4 /*yield*/, this.sync.stop()];
1517
+ case 2:
1518
+ _a.sent();
1519
+ _a.label = 3;
1520
+ case 3:
1521
+ this.initialized = undefined; // Should re-initialize when start() is called.
1522
+ this.sync = undefined;
1523
+ return [4 /*yield*/, this.runningProcesses.open()];
1524
+ case 4:
1525
+ _a.sent();
1526
+ this.state = DataStoreState.NotRunning;
1527
+ return [2 /*return*/];
1528
+ }
1529
+ });
1530
+ });
1531
+ };
1532
+ /**
1533
+ * Validates given pagination input from a query and creates a pagination
1534
+ * argument for use against the storage layer.
1535
+ *
1536
+ * @param modelDefinition
1537
+ * @param paginationProducer
1538
+ */
1345
1539
  DataStore.prototype.processPagination = function (modelDefinition, paginationProducer) {
1346
1540
  var sortPredicate;
1347
1541
  var _a = paginationProducer || {}, limit = _a.limit, page = _a.page, sort = _a.sort;
@@ -1376,6 +1570,10 @@ var DataStore = /** @class */ (function () {
1376
1570
  sort: sortPredicate,
1377
1571
  };
1378
1572
  };
1573
+ /**
1574
+ * Examines the configured `syncExpressions` and produces a WeakMap of
1575
+ * SchemaModel -> predicate to use during sync.
1576
+ */
1379
1577
  DataStore.prototype.processSyncExpressions = function () {
1380
1578
  return __awaiter(this, void 0, void 0, function () {
1381
1579
  var syncPredicates;
@@ -1457,7 +1655,10 @@ var DataStore = /** @class */ (function () {
1457
1655
  return map;
1458
1656
  }, new WeakMap());
1459
1657
  };
1460
- // database separation for Amplify Console. Not a public API
1658
+ /**
1659
+ * A session ID to allow CMS to open databases against multiple apps.
1660
+ * This session ID is only expected be set by AWS Amplify Studio.
1661
+ */
1461
1662
  DataStore.prototype.retrieveSessionId = function () {
1462
1663
  try {
1463
1664
  var sessionId = sessionStorage.getItem('datastoreSessionId');