@aws-amplify/datastore 3.12.6-next.13 → 3.12.6-next.32

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 (162) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/lib/authModeStrategies/multiAuthStrategy.js +17 -64
  3. package/lib/authModeStrategies/multiAuthStrategy.js.map +1 -1
  4. package/lib/datastore/datastore.js +682 -469
  5. package/lib/datastore/datastore.js.map +1 -1
  6. package/lib/index.js +2 -4
  7. package/lib/index.js.map +1 -1
  8. package/lib/predicates/index.js +12 -2
  9. package/lib/predicates/index.js.map +1 -1
  10. package/lib/storage/adapter/AsyncStorageAdapter.js +393 -298
  11. package/lib/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  12. package/lib/storage/adapter/AsyncStorageDatabase.js +97 -122
  13. package/lib/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  14. package/lib/storage/adapter/InMemoryStore.js +16 -67
  15. package/lib/storage/adapter/InMemoryStore.js.map +1 -1
  16. package/lib/storage/adapter/InMemoryStore.native.js +2 -4
  17. package/lib/storage/adapter/InMemoryStore.native.js.map +1 -1
  18. package/lib/storage/adapter/IndexedDBAdapter.js +497 -404
  19. package/lib/storage/adapter/IndexedDBAdapter.js.map +1 -1
  20. package/lib/storage/adapter/getDefaultAdapter/index.js +3 -5
  21. package/lib/storage/adapter/getDefaultAdapter/index.js.map +1 -1
  22. package/lib/storage/adapter/getDefaultAdapter/index.native.js +2 -4
  23. package/lib/storage/adapter/getDefaultAdapter/index.native.js.map +1 -1
  24. package/lib/storage/storage.js +129 -151
  25. package/lib/storage/storage.js.map +1 -1
  26. package/lib/sync/datastoreConnectivity.js +13 -17
  27. package/lib/sync/datastoreConnectivity.js.map +1 -1
  28. package/lib/sync/datastoreReachability/index.native.js +2 -4
  29. package/lib/sync/datastoreReachability/index.native.js.map +1 -1
  30. package/lib/sync/index.js +544 -488
  31. package/lib/sync/index.js.map +1 -1
  32. package/lib/sync/merger.js +21 -80
  33. package/lib/sync/merger.js.map +1 -1
  34. package/lib/sync/outbox.js +95 -162
  35. package/lib/sync/outbox.js.map +1 -1
  36. package/lib/sync/processors/errorMaps.js +4 -34
  37. package/lib/sync/processors/errorMaps.js.map +1 -1
  38. package/lib/sync/processors/mutation.js +285 -312
  39. package/lib/sync/processors/mutation.js.map +1 -1
  40. package/lib/sync/processors/subscription.js +218 -259
  41. package/lib/sync/processors/subscription.js.map +1 -1
  42. package/lib/sync/processors/sync.js +141 -212
  43. package/lib/sync/processors/sync.js.map +1 -1
  44. package/lib/sync/utils.js +50 -61
  45. package/lib/sync/utils.js.map +1 -1
  46. package/lib/types.js +13 -39
  47. package/lib/types.js.map +1 -1
  48. package/lib/util.js +429 -242
  49. package/lib/util.js.map +1 -1
  50. package/lib-esm/authModeStrategies/multiAuthStrategy.d.ts +11 -0
  51. package/lib-esm/authModeStrategies/multiAuthStrategy.js +13 -57
  52. package/lib-esm/authModeStrategies/multiAuthStrategy.js.map +1 -1
  53. package/lib-esm/datastore/datastore.d.ts +107 -17
  54. package/lib-esm/datastore/datastore.js +649 -433
  55. package/lib-esm/datastore/datastore.js.map +1 -1
  56. package/lib-esm/index.d.ts +3 -19
  57. package/lib-esm/predicates/index.d.ts +3 -2
  58. package/lib-esm/predicates/index.js +13 -3
  59. package/lib-esm/predicates/index.js.map +1 -1
  60. package/lib-esm/storage/adapter/AsyncStorageAdapter.d.ts +4 -3
  61. package/lib-esm/storage/adapter/AsyncStorageAdapter.js +356 -258
  62. package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  63. package/lib-esm/storage/adapter/AsyncStorageDatabase.d.ts +14 -4
  64. package/lib-esm/storage/adapter/AsyncStorageDatabase.js +67 -92
  65. package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  66. package/lib-esm/storage/adapter/InMemoryStore.js +1 -52
  67. package/lib-esm/storage/adapter/InMemoryStore.js.map +1 -1
  68. package/lib-esm/storage/adapter/IndexedDBAdapter.d.ts +26 -4
  69. package/lib-esm/storage/adapter/IndexedDBAdapter.js +446 -346
  70. package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +1 -1
  71. package/lib-esm/storage/adapter/index.d.ts +1 -1
  72. package/lib-esm/storage/storage.d.ts +1 -1
  73. package/lib-esm/storage/storage.js +94 -113
  74. package/lib-esm/storage/storage.js.map +1 -1
  75. package/lib-esm/sync/datastoreConnectivity.d.ts +1 -0
  76. package/lib-esm/sync/datastoreConnectivity.js +10 -11
  77. package/lib-esm/sync/datastoreConnectivity.js.map +1 -1
  78. package/lib-esm/sync/index.d.ts +31 -5
  79. package/lib-esm/sync/index.js +525 -466
  80. package/lib-esm/sync/index.js.map +1 -1
  81. package/lib-esm/sync/merger.d.ts +9 -3
  82. package/lib-esm/sync/merger.js +14 -73
  83. package/lib-esm/sync/merger.js.map +1 -1
  84. package/lib-esm/sync/outbox.d.ts +2 -2
  85. package/lib-esm/sync/outbox.js +79 -146
  86. package/lib-esm/sync/outbox.js.map +1 -1
  87. package/lib-esm/sync/processors/errorMaps.js +1 -31
  88. package/lib-esm/sync/processors/errorMaps.js.map +1 -1
  89. package/lib-esm/sync/processors/mutation.d.ts +2 -0
  90. package/lib-esm/sync/processors/mutation.js +271 -295
  91. package/lib-esm/sync/processors/mutation.js.map +1 -1
  92. package/lib-esm/sync/processors/subscription.d.ts +2 -0
  93. package/lib-esm/sync/processors/subscription.js +214 -245
  94. package/lib-esm/sync/processors/subscription.js.map +1 -1
  95. package/lib-esm/sync/processors/sync.d.ts +2 -1
  96. package/lib-esm/sync/processors/sync.js +127 -195
  97. package/lib-esm/sync/processors/sync.js.map +1 -1
  98. package/lib-esm/sync/utils.d.ts +3 -2
  99. package/lib-esm/sync/utils.js +45 -57
  100. package/lib-esm/sync/utils.js.map +1 -1
  101. package/lib-esm/types.d.ts +65 -26
  102. package/lib-esm/types.js +10 -38
  103. package/lib-esm/types.js.map +1 -1
  104. package/lib-esm/util.d.ts +67 -24
  105. package/lib-esm/util.js +420 -233
  106. package/lib-esm/util.js.map +1 -1
  107. package/package.json +14 -7
  108. package/src/authModeStrategies/multiAuthStrategy.ts +12 -1
  109. package/src/datastore/datastore.ts +798 -397
  110. package/src/predicates/index.ts +32 -10
  111. package/src/storage/adapter/AsyncStorageAdapter.ts +309 -93
  112. package/src/storage/adapter/AsyncStorageDatabase.ts +74 -26
  113. package/src/storage/adapter/IndexedDBAdapter.ts +358 -134
  114. package/src/storage/adapter/index.ts +1 -1
  115. package/src/storage/storage.ts +69 -22
  116. package/src/sync/datastoreConnectivity.ts +6 -0
  117. package/src/sync/index.ts +521 -412
  118. package/src/sync/merger.ts +20 -4
  119. package/src/sync/outbox.ts +22 -9
  120. package/src/sync/processors/mutation.ts +188 -150
  121. package/src/sync/processors/subscription.ts +289 -253
  122. package/src/sync/processors/sync.ts +151 -138
  123. package/src/sync/utils.ts +67 -12
  124. package/src/types.ts +182 -30
  125. package/src/util.ts +505 -176
  126. package/build.js +0 -5
  127. package/dist/aws-amplify-datastore.js +0 -98255
  128. package/dist/aws-amplify-datastore.js.map +0 -1
  129. package/dist/aws-amplify-datastore.min.js +0 -66
  130. package/dist/aws-amplify-datastore.min.js.map +0 -1
  131. package/index.js +0 -7
  132. package/lib/authModeStrategies/defaultAuthStrategy.d.ts +0 -2
  133. package/lib/authModeStrategies/index.d.ts +0 -2
  134. package/lib/authModeStrategies/multiAuthStrategy.d.ts +0 -2
  135. package/lib/datastore/datastore.d.ts +0 -66
  136. package/lib/index.d.ts +0 -31
  137. package/lib/predicates/index.d.ts +0 -15
  138. package/lib/predicates/sort.d.ts +0 -8
  139. package/lib/ssr/index.d.ts +0 -3
  140. package/lib/storage/adapter/AsyncStorageAdapter.d.ts +0 -40
  141. package/lib/storage/adapter/AsyncStorageDatabase.d.ts +0 -29
  142. package/lib/storage/adapter/InMemoryStore.d.ts +0 -11
  143. package/lib/storage/adapter/InMemoryStore.native.d.ts +0 -1
  144. package/lib/storage/adapter/IndexedDBAdapter.d.ts +0 -37
  145. package/lib/storage/adapter/getDefaultAdapter/index.d.ts +0 -3
  146. package/lib/storage/adapter/getDefaultAdapter/index.native.d.ts +0 -3
  147. package/lib/storage/adapter/index.d.ts +0 -9
  148. package/lib/storage/storage.d.ts +0 -49
  149. package/lib/sync/datastoreConnectivity.d.ts +0 -15
  150. package/lib/sync/datastoreReachability/index.d.ts +0 -3
  151. package/lib/sync/datastoreReachability/index.native.d.ts +0 -3
  152. package/lib/sync/index.d.ts +0 -63
  153. package/lib/sync/merger.d.ts +0 -11
  154. package/lib/sync/outbox.d.ts +0 -27
  155. package/lib/sync/processors/errorMaps.d.ts +0 -17
  156. package/lib/sync/processors/mutation.d.ts +0 -56
  157. package/lib/sync/processors/subscription.d.ts +0 -31
  158. package/lib/sync/processors/sync.d.ts +0 -27
  159. package/lib/sync/utils.d.ts +0 -41
  160. package/lib/types.d.ts +0 -462
  161. package/lib/util.d.ts +0 -113
  162. package/webpack.config.dev.js +0 -6
@@ -1,96 +1,8 @@
1
- var __assign = (this && this.__assign) || function () {
2
- __assign = Object.assign || function(t) {
3
- for (var s, i = 1, n = arguments.length; i < n; i++) {
4
- s = arguments[i];
5
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
- t[p] = s[p];
7
- }
8
- return t;
9
- };
10
- return __assign.apply(this, arguments);
11
- };
12
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
- return new (P || (P = Promise))(function (resolve, reject) {
15
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
- step((generator = generator.apply(thisArg, _arguments || [])).next());
19
- });
20
- };
21
- var __generator = (this && this.__generator) || function (thisArg, body) {
22
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
23
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
24
- function verb(n) { return function (v) { return step([n, v]); }; }
25
- function step(op) {
26
- if (f) throw new TypeError("Generator is already executing.");
27
- while (_) try {
28
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
29
- if (y = 0, t) op = [op[0] & 2, t.value];
30
- switch (op[0]) {
31
- case 0: case 1: t = op; break;
32
- case 4: _.label++; return { value: op[1], done: false };
33
- case 5: _.label++; y = op[1]; op = [0]; continue;
34
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
35
- default:
36
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
37
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
38
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
39
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
40
- if (t[2]) _.ops.pop();
41
- _.trys.pop(); continue;
42
- }
43
- op = body.call(thisArg, _);
44
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
45
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
- }
47
- };
48
- var __rest = (this && this.__rest) || function (s, e) {
49
- var t = {};
50
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
51
- t[p] = s[p];
52
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
53
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
54
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
55
- t[p[i]] = s[p[i]];
56
- }
57
- return t;
58
- };
59
- var __read = (this && this.__read) || function (o, n) {
60
- var m = typeof Symbol === "function" && o[Symbol.iterator];
61
- if (!m) return o;
62
- var i = m.call(o), r, ar = [], e;
63
- try {
64
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
65
- }
66
- catch (error) { e = { error: error }; }
67
- finally {
68
- try {
69
- if (r && !r.done && (m = i["return"])) m.call(i);
70
- }
71
- finally { if (e) throw e.error; }
72
- }
73
- return ar;
74
- };
75
- var __values = (this && this.__values) || function(o) {
76
- var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
77
- if (m) return m.call(o);
78
- if (o && typeof o.length === "number") return {
79
- next: function () {
80
- if (o && i >= o.length) o = void 0;
81
- return { value: o && o[i++], done: !o };
82
- }
83
- };
84
- throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
85
- };
86
- var __spread = (this && this.__spread) || function () {
87
- for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
88
- return ar;
89
- };
90
- import API from '@aws-amplify/api';
91
- import { Amplify, ConsoleLogger as Logger, Hub, JS } from '@aws-amplify/core';
1
+ import { __assign, __awaiter, __generator, __read, __rest, __spread, __values } from "tslib";
2
+ import { API } from '@aws-amplify/api';
92
3
  import { Auth } from '@aws-amplify/auth';
93
- import Cache from '@aws-amplify/cache';
4
+ import { BrowserStorageCache as Cache } from '@aws-amplify/cache';
5
+ import { Amplify, ConsoleLogger as Logger, Hub, browserOrNode, BackgroundProcessManager, } from '@aws-amplify/core';
94
6
  import { immerable, produce, setAutoFreeze, enablePatches, } from 'immer';
95
7
  import { v4 as uuid4 } from 'uuid';
96
8
  import Observable from 'zen-observable-ts';
@@ -98,13 +10,14 @@ import { defaultAuthStrategy, multiAuthStrategy } from '../authModeStrategies';
98
10
  import { isPredicatesAll, ModelPredicateCreator, ModelSortPredicateCreator, } from '../predicates';
99
11
  import { ExclusiveStorage as Storage } from '../storage/storage';
100
12
  import { ControlMessage, SyncEngine } from '../sync';
101
- import { GraphQLScalarType, isGraphQLScalarType, AuthModeStrategyType, isNonModelFieldType, isModelFieldType, } from '../types';
102
- import { DATASTORE, establishRelationAndKeys, exhaustiveCheck, isModelConstructor, monotonicUlidFactory, STORAGE, SYNC, USER, isNullOrUndefined, registerNonModelClass, sortCompareFunction, DeferredCallbackResolver, validatePredicate, mergePatches, } from '../util';
13
+ import { GraphQLScalarType, isGraphQLScalarType, isSchemaModelWithAttributes, AuthModeStrategyType, isNonModelFieldType, isModelFieldType, isIdentifierObject, } from '../types';
14
+ import { DATASTORE, errorMessages, establishRelationAndKeys, exhaustiveCheck, isModelConstructor, monotonicUlidFactory, STORAGE, SYNC, USER, isNullOrUndefined, registerNonModelClass, sortCompareFunction, DeferredCallbackResolver, extractPrimaryKeyFieldNames, extractPrimaryKeysAndValues, isIdManaged, isIdOptionallyManaged, validatePredicate, mergePatches, } from '../util';
15
+ import { getIdentifierValue } from '../sync/utils';
103
16
  setAutoFreeze(true);
104
17
  enablePatches();
105
18
  var logger = new Logger('DataStore');
106
19
  var ulid = monotonicUlidFactory(Date.now());
107
- var isNode = JS.browserOrNode().isNode;
20
+ var isNode = browserOrNode().isNode;
108
21
  var SETTING_SCHEMA_VERSION = 'schemaVersion';
109
22
  var schema;
110
23
  var modelNamespaceMap = new WeakMap();
@@ -204,10 +117,14 @@ var initSchema = function (userSchema) {
204
117
  });
205
118
  return userClasses;
206
119
  };
207
- /* Checks if the schema has been initialized by initSchema().
120
+ /**
121
+ * Throws an exception if the schema has *not* been initialized
122
+ * by `initSchema()`.
123
+ *
124
+ * **To be called before trying to access schema.**
208
125
  *
209
- * Call this function before accessing schema.
210
- * Currently this only needs to be called in start() and clear() because all other functions will call start first.
126
+ * Currently this only needs to be called in `start()` and `clear()` because
127
+ * all other functions will call start first.
211
128
  */
212
129
  var checkSchemaInitialized = function () {
213
130
  if (schema === undefined) {
@@ -231,6 +148,11 @@ var createTypeClasses = function (namespace) {
231
148
  });
232
149
  return classes;
233
150
  };
151
+ /**
152
+ * Collection of instantiated models to allow storage of metadata apart from
153
+ * the model visible to the consuming app -- in case the app doesn't have
154
+ * metadata fields (_version, _deleted, etc.) exposed on the model itself.
155
+ */
234
156
  var instancesMetadata = new WeakSet();
235
157
  function modelInstanceCreator(modelConstructor, init) {
236
158
  instancesMetadata.add(init);
@@ -239,15 +161,23 @@ function modelInstanceCreator(modelConstructor, init) {
239
161
  var validateModelFields = function (modelDefinition) { return function (k, v) {
240
162
  var fieldDefinition = modelDefinition.fields[k];
241
163
  if (fieldDefinition !== undefined) {
242
- var type = fieldDefinition.type, isRequired_1 = fieldDefinition.isRequired, isArrayNullable = fieldDefinition.isArrayNullable, name_1 = fieldDefinition.name, isArray = fieldDefinition.isArray;
164
+ var type_1 = fieldDefinition.type, isRequired_1 = fieldDefinition.isRequired, isArrayNullable = fieldDefinition.isArrayNullable, name_1 = fieldDefinition.name, isArray = fieldDefinition.isArray;
243
165
  if (((!isArray && isRequired_1) || (isArray && !isArrayNullable)) &&
244
166
  (v === null || v === undefined)) {
245
167
  throw new Error("Field " + name_1 + " is required");
246
168
  }
247
- if (isGraphQLScalarType(type)) {
248
- var jsType_1 = GraphQLScalarType.getJSType(type);
249
- var validateScalar_1 = GraphQLScalarType.getValidationFunction(type);
250
- if (type === 'AWSJSON') {
169
+ if (isSchemaModelWithAttributes(modelDefinition) &&
170
+ !isIdManaged(modelDefinition)) {
171
+ var keys = extractPrimaryKeyFieldNames(modelDefinition);
172
+ if (keys.includes(k) && v === '') {
173
+ logger.error(errorMessages.idEmptyString, { k: k, value: v });
174
+ throw new Error(errorMessages.idEmptyString);
175
+ }
176
+ }
177
+ if (isGraphQLScalarType(type_1)) {
178
+ var jsType_1 = GraphQLScalarType.getJSType(type_1);
179
+ var validateScalar_1 = GraphQLScalarType.getValidationFunction(type_1);
180
+ if (type_1 === 'AWSJSON') {
251
181
  if (typeof v === jsType_1) {
252
182
  return;
253
183
  }
@@ -291,7 +221,7 @@ var validateModelFields = function (modelDefinition) { return function (k, v) {
291
221
  }
292
222
  });
293
223
  if (!validationStatus.every(function (s) { return s; })) {
294
- throw new Error("All elements in the " + name_1 + " array should be of type " + type + ", validation failed for one or more elements. " + v);
224
+ throw new Error("All elements in the " + name_1 + " array should be of type " + type_1 + ", validation failed for one or more elements. " + v);
295
225
  }
296
226
  }
297
227
  }
@@ -304,7 +234,42 @@ var validateModelFields = function (modelDefinition) { return function (k, v) {
304
234
  else if (!isNullOrUndefined(v) &&
305
235
  validateScalar_1 &&
306
236
  !validateScalar_1(v)) {
307
- throw new Error("Field " + name_1 + " should be of type " + type + ", validation failed. " + v);
237
+ throw new Error("Field " + name_1 + " should be of type " + type_1 + ", validation failed. " + v);
238
+ }
239
+ }
240
+ else if (isNonModelFieldType(type_1)) {
241
+ // do not check non model fields if undefined or null
242
+ if (!isNullOrUndefined(v)) {
243
+ var subNonModelDefinition_1 = schema.namespaces.user.nonModels[type_1.nonModel];
244
+ var modelValidator_1 = validateModelFields(subNonModelDefinition_1);
245
+ if (isArray) {
246
+ var errorTypeText = type_1.nonModel;
247
+ if (!isRequired_1) {
248
+ errorTypeText = type_1.nonModel + " | null | undefined";
249
+ }
250
+ if (!Array.isArray(v)) {
251
+ throw new Error("Field " + name_1 + " should be of type [" + errorTypeText + "], " + typeof v + " received. " + v);
252
+ }
253
+ v.forEach(function (item) {
254
+ if ((isNullOrUndefined(item) && isRequired_1) ||
255
+ (typeof item !== 'object' && typeof item !== 'undefined')) {
256
+ throw new Error("All elements in the " + name_1 + " array should be of type " + type_1.nonModel + ", [" + typeof item + "] received. " + item);
257
+ }
258
+ if (!isNullOrUndefined(item)) {
259
+ Object.keys(subNonModelDefinition_1.fields).forEach(function (subKey) {
260
+ modelValidator_1(subKey, item[subKey]);
261
+ });
262
+ }
263
+ });
264
+ }
265
+ else {
266
+ if (typeof v !== 'object') {
267
+ throw new Error("Field " + name_1 + " should be of type " + type_1.nonModel + ", " + typeof v + " recieved. " + v);
268
+ }
269
+ Object.keys(subNonModelDefinition_1.fields).forEach(function (subKey) {
270
+ modelValidator_1(subKey, v[subKey]);
271
+ });
272
+ }
308
273
  }
309
274
  }
310
275
  }
@@ -344,21 +309,29 @@ var createModelClass = function (modelDefinition) {
344
309
  function Model(init) {
345
310
  var instance = produce(this, function (draft) {
346
311
  initializeInstance(init, modelDefinition, draft);
347
- var modelInstanceMetadata = instancesMetadata.has(init)
312
+ // model is initialized inside a DataStore component (e.g. by Sync Engine, Storage Engine, etc.)
313
+ var isInternallyInitialized = instancesMetadata.has(init);
314
+ var modelInstanceMetadata = isInternallyInitialized
348
315
  ? init
349
316
  : {};
350
- var _id = modelInstanceMetadata.id, _version = modelInstanceMetadata._version, _lastChangedAt = modelInstanceMetadata._lastChangedAt, _deleted = modelInstanceMetadata._deleted;
351
- // instancesIds are set by modelInstanceCreator, it is accessible only internally
352
- var isInternal = _id !== null && _id !== undefined;
353
- var id = isInternal
354
- ? _id
355
- : modelDefinition.syncable
356
- ? uuid4()
357
- : ulid();
358
- if (!isInternal) {
317
+ var _id = modelInstanceMetadata.id;
318
+ if (isIdManaged(modelDefinition)) {
319
+ var isInternalModel = _id !== null && _id !== undefined;
320
+ var id = isInternalModel
321
+ ? _id
322
+ : modelDefinition.syncable
323
+ ? uuid4()
324
+ : ulid();
325
+ draft.id = id;
326
+ }
327
+ else if (isIdOptionallyManaged(modelDefinition)) {
328
+ // only auto-populate if the id was not provided
329
+ draft.id = draft.id || uuid4();
330
+ }
331
+ if (!isInternallyInitialized) {
359
332
  checkReadOnlyPropertyOnCreate(draft, modelDefinition);
360
333
  }
361
- draft.id = id;
334
+ var _version = modelInstanceMetadata._version, _lastChangedAt = modelInstanceMetadata._lastChangedAt, _deleted = modelInstanceMetadata._deleted;
362
335
  if (modelDefinition.syncable) {
363
336
  draft._version = _version;
364
337
  draft._lastChangedAt = _lastChangedAt;
@@ -377,7 +350,9 @@ var createModelClass = function (modelDefinition) {
377
350
  var patches;
378
351
  var model = produce(source, function (draft) {
379
352
  fn(draft);
380
- draft.id = source.id;
353
+ var keyNames = extractPrimaryKeyFieldNames(modelDefinition);
354
+ // Keys are immutable
355
+ keyNames.forEach(function (key) { return (draft[key] = source[key]); });
381
356
  var modelValidator = validateModelFields(modelDefinition);
382
357
  Object.entries(draft).forEach(function (_a) {
383
358
  var _b = __read(_a, 2), k = _b[0], v = _b[1];
@@ -496,6 +471,18 @@ function getModelConstructorByModelName(namespaceName, modelName) {
496
471
  throw new Error(msg);
497
472
  }
498
473
  }
474
+ /**
475
+ * Queries the DataStore metadata tables to see if they are the expected
476
+ * version. If not, clobbers the whole DB. If so, leaves them alone.
477
+ * Otherwise, simply writes the schema version.
478
+ *
479
+ * SIDE EFFECT:
480
+ * 1. Creates a transaction
481
+ * 1. Updates data.
482
+ *
483
+ * @param storage Storage adapter containing the metadata.
484
+ * @param version The expected schema version.
485
+ */
499
486
  function checkSchemaVersion(storage, version) {
500
487
  return __awaiter(this, void 0, void 0, function () {
501
488
  var Setting, modelDefinition;
@@ -510,7 +497,6 @@ function checkSchemaVersion(storage, version) {
510
497
  return __generator(this, function (_b) {
511
498
  switch (_b.label) {
512
499
  case 0: return [4 /*yield*/, s.query(Setting, ModelPredicateCreator.createFromExisting(modelDefinition, function (c) {
513
- // @ts-ignore Argument of type '"eq"' is not assignable to parameter of type 'never'.
514
500
  return c.key('eq', SETTING_SCHEMA_VERSION);
515
501
  }), { page: 0, limit: 1 })];
516
502
  case 1:
@@ -579,6 +565,14 @@ function getNamespace() {
579
565
  };
580
566
  return namespace;
581
567
  }
568
+ var DataStoreState;
569
+ (function (DataStoreState) {
570
+ DataStoreState["NotRunning"] = "Not Running";
571
+ DataStoreState["Starting"] = "Starting";
572
+ DataStoreState["Running"] = "Running";
573
+ DataStoreState["Stopping"] = "Stopping";
574
+ DataStoreState["Clearing"] = "Clearing";
575
+ })(DataStoreState || (DataStoreState = {}));
582
576
  var DataStore = /** @class */ (function () {
583
577
  function DataStore() {
584
578
  var _this = this;
@@ -594,156 +588,235 @@ var DataStore = /** @class */ (function () {
594
588
  API: this.API,
595
589
  Cache: this.Cache,
596
590
  };
591
+ /**
592
+ * **IMPORTANT!**
593
+ *
594
+ * Accumulator for background things that can **and MUST** be called when
595
+ * DataStore stops.
596
+ *
597
+ * These jobs **MUST** be *idempotent promises* that resolve ONLY
598
+ * once the intended jobs are completely finished and/or otherwise destroyed
599
+ * and cleaned up with ZERO outstanding:
600
+ *
601
+ * 1. side effects (e.g., state changes)
602
+ * 1. callbacks
603
+ * 1. subscriptions
604
+ * 1. calls to storage
605
+ * 1. *etc.*
606
+ *
607
+ * Methods that create pending promises, subscriptions, callbacks, or any
608
+ * type of side effect **MUST** be registered with the manager. And, a new
609
+ * manager must be created after each `exit()`.
610
+ *
611
+ * Failure to comply will put DataStore into a highly unpredictable state
612
+ * when it needs to stop or clear -- which occurs when restarting with new
613
+ * sync expressions, during testing, and potentially during app code
614
+ * recovery handling, etc..
615
+ *
616
+ * It is up to the discretion of each disposer whether to wait for job
617
+ * completion or to cancel operations and issue failures *as long as the
618
+ * disposer returns in a reasonable amount of time.*
619
+ *
620
+ * (Reasonable = *seconds*, not minutes.)
621
+ */
622
+ this.runningProcesses = new BackgroundProcessManager();
623
+ /**
624
+ * Indicates what state DataStore is in.
625
+ *
626
+ * Not [yet?] used for actual state management; but for messaging
627
+ * when errors occur, to help troubleshoot.
628
+ */
629
+ this.state = DataStoreState.NotRunning;
630
+ /**
631
+ * If not already done:
632
+ * 1. Attaches and initializes storage.
633
+ * 1. Loads the schema and records metadata.
634
+ * 1. If `this.amplifyConfig.aws_appsync_graphqlEndpoint` contains a URL,
635
+ * attaches a sync engine, starts it, and subscribes.
636
+ */
597
637
  this.start = function () { return __awaiter(_this, void 0, void 0, function () {
598
- var aws_appsync_graphqlEndpoint, _a, fullSyncIntervalInMilliseconds;
599
638
  var _this = this;
600
- return __generator(this, function (_b) {
601
- switch (_b.label) {
602
- case 0:
603
- if (!(this.initialized === undefined)) return [3 /*break*/, 1];
604
- logger.debug('Starting DataStore');
605
- this.initialized = new Promise(function (res, rej) {
606
- _this.initResolve = res;
607
- _this.initReject = rej;
608
- });
609
- return [3 /*break*/, 3];
610
- case 1: return [4 /*yield*/, this.initialized];
611
- case 2:
612
- _b.sent();
613
- return [2 /*return*/];
614
- case 3:
615
- this.storage = new Storage(schema, namespaceResolver, getModelConstructorByModelName, modelInstanceCreator, this.storageAdapter, this.sessionId);
616
- return [4 /*yield*/, this.storage.init()];
617
- case 4:
618
- _b.sent();
619
- checkSchemaInitialized();
620
- return [4 /*yield*/, checkSchemaVersion(this.storage, schema.version)];
621
- case 5:
622
- _b.sent();
623
- aws_appsync_graphqlEndpoint = this.amplifyConfig.aws_appsync_graphqlEndpoint;
624
- if (!aws_appsync_graphqlEndpoint) return [3 /*break*/, 7];
625
- logger.debug('GraphQL endpoint available', aws_appsync_graphqlEndpoint);
626
- _a = this;
627
- return [4 /*yield*/, this.processSyncExpressions()];
628
- case 6:
629
- _a.syncPredicates = _b.sent();
630
- this.sync = new SyncEngine(schema, namespaceResolver, syncClasses, userClasses, this.storage, modelInstanceCreator, this.conflictHandler, this.errorHandler, this.syncPredicates, this.amplifyConfig, this.authModeStrategy, this.amplifyContext);
631
- fullSyncIntervalInMilliseconds = this.fullSyncInterval * 1000 * 60;
632
- syncSubscription = this.sync
633
- .start({ fullSyncInterval: fullSyncIntervalInMilliseconds })
634
- .subscribe({
635
- next: function (_a) {
636
- var type = _a.type, data = _a.data;
637
- // In Node, we need to wait for queries to be synced to prevent returning empty arrays.
638
- // In the Browser, we can begin returning data once subscriptions are in place.
639
- var readyType = isNode
640
- ? ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY
641
- : ControlMessage.SYNC_ENGINE_STORAGE_SUBSCRIBED;
642
- if (type === readyType) {
643
- _this.initResolve();
644
- }
645
- Hub.dispatch('datastore', {
646
- event: type,
647
- data: data,
648
- });
649
- },
650
- error: function (err) {
651
- logger.warn('Sync error', err);
652
- _this.initReject();
653
- },
654
- });
655
- return [3 /*break*/, 8];
656
- case 7:
657
- logger.warn("Data won't be synchronized. No GraphQL endpoint configured. Did you forget `Amplify.configure(awsconfig)`?", {
658
- config: this.amplifyConfig,
639
+ return __generator(this, function (_a) {
640
+ return [2 /*return*/, this.runningProcesses
641
+ .add(function () { return __awaiter(_this, void 0, void 0, function () {
642
+ var aws_appsync_graphqlEndpoint, _a, fullSyncIntervalInMilliseconds;
643
+ var _this = this;
644
+ return __generator(this, function (_b) {
645
+ switch (_b.label) {
646
+ case 0:
647
+ this.state = DataStoreState.Starting;
648
+ if (!(this.initialized === undefined)) return [3 /*break*/, 1];
649
+ logger.debug('Starting DataStore');
650
+ this.initialized = new Promise(function (res, rej) {
651
+ _this.initResolve = res;
652
+ _this.initReject = rej;
653
+ });
654
+ return [3 /*break*/, 3];
655
+ case 1: return [4 /*yield*/, this.initialized];
656
+ case 2:
657
+ _b.sent();
658
+ return [2 /*return*/];
659
+ case 3:
660
+ this.storage = new Storage(schema, namespaceResolver, getModelConstructorByModelName, modelInstanceCreator, this.storageAdapter, this.sessionId);
661
+ return [4 /*yield*/, this.storage.init()];
662
+ case 4:
663
+ _b.sent();
664
+ checkSchemaInitialized();
665
+ return [4 /*yield*/, checkSchemaVersion(this.storage, schema.version)];
666
+ case 5:
667
+ _b.sent();
668
+ aws_appsync_graphqlEndpoint = this.amplifyConfig.aws_appsync_graphqlEndpoint;
669
+ if (!aws_appsync_graphqlEndpoint) return [3 /*break*/, 7];
670
+ logger.debug('GraphQL endpoint available', aws_appsync_graphqlEndpoint);
671
+ _a = this;
672
+ return [4 /*yield*/, this.processSyncExpressions()];
673
+ case 6:
674
+ _a.syncPredicates = _b.sent();
675
+ this.sync = new SyncEngine(schema, namespaceResolver, syncClasses, userClasses, this.storage, modelInstanceCreator, this.conflictHandler, this.errorHandler, this.syncPredicates, this.amplifyConfig, this.authModeStrategy, this.amplifyContext, this.connectivityMonitor);
676
+ fullSyncIntervalInMilliseconds = this.fullSyncInterval * 1000 * 60;
677
+ syncSubscription = this.sync
678
+ .start({ fullSyncInterval: fullSyncIntervalInMilliseconds })
679
+ .subscribe({
680
+ next: function (_a) {
681
+ var type = _a.type, data = _a.data;
682
+ // In Node, we need to wait for queries to be synced to prevent returning empty arrays.
683
+ // In the Browser, we can begin returning data once subscriptions are in place.
684
+ var readyType = isNode
685
+ ? ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY
686
+ : ControlMessage.SYNC_ENGINE_STORAGE_SUBSCRIBED;
687
+ if (type === readyType) {
688
+ _this.initResolve();
689
+ }
690
+ Hub.dispatch('datastore', {
691
+ event: type,
692
+ data: data,
693
+ });
694
+ },
695
+ error: function (err) {
696
+ logger.warn('Sync error', err);
697
+ _this.initReject();
698
+ },
699
+ });
700
+ return [3 /*break*/, 8];
701
+ case 7:
702
+ logger.warn("Data won't be synchronized. No GraphQL endpoint configured. Did you forget `Amplify.configure(awsconfig)`?", {
703
+ config: this.amplifyConfig,
704
+ });
705
+ this.initResolve();
706
+ _b.label = 8;
707
+ case 8: return [4 /*yield*/, this.initialized];
708
+ case 9:
709
+ _b.sent();
710
+ this.state = DataStoreState.Running;
711
+ return [2 /*return*/];
712
+ }
659
713
  });
660
- this.initResolve();
661
- _b.label = 8;
662
- case 8: return [4 /*yield*/, this.initialized];
663
- case 9:
664
- _b.sent();
665
- return [2 /*return*/];
666
- }
714
+ }); }, 'datastore start')
715
+ .catch(this.handleAddProcError('DataStore.start()'))];
667
716
  });
668
717
  }); };
669
- this.query = function (modelConstructor, idOrCriteria, paginationProducer) { return __awaiter(_this, void 0, void 0, function () {
670
- var msg, modelDefinition, predicate, pagination, result;
718
+ this.query = function (modelConstructor, identifierOrCriteria, paginationProducer) { return __awaiter(_this, void 0, void 0, function () {
719
+ var _this = this;
671
720
  return __generator(this, function (_a) {
672
- switch (_a.label) {
673
- case 0: return [4 /*yield*/, this.start()];
674
- case 1:
675
- _a.sent();
676
- //#region Input validation
677
- if (!isValidModelConstructor(modelConstructor)) {
678
- msg = 'Constructor is not for a valid model';
679
- logger.error(msg, { modelConstructor: modelConstructor });
680
- throw new Error(msg);
681
- }
682
- if (typeof idOrCriteria === 'string') {
683
- if (paginationProducer !== undefined) {
684
- logger.warn('Pagination is ignored when querying by id');
685
- }
686
- }
687
- modelDefinition = getModelDefinition(modelConstructor);
688
- if (isQueryOne(idOrCriteria)) {
689
- predicate = ModelPredicateCreator.createForId(modelDefinition, idOrCriteria);
690
- }
691
- else {
692
- if (isPredicatesAll(idOrCriteria)) {
693
- // Predicates.ALL means "all records", so no predicate (undefined)
694
- predicate = undefined;
695
- }
696
- else {
697
- predicate = ModelPredicateCreator.createFromExisting(modelDefinition, idOrCriteria);
721
+ return [2 /*return*/, this.runningProcesses
722
+ .add(function () { return __awaiter(_this, void 0, void 0, function () {
723
+ var msg, modelDefinition, keyFields, predicate, msg, pagination, result, returnOne;
724
+ return __generator(this, function (_a) {
725
+ switch (_a.label) {
726
+ case 0: return [4 /*yield*/, this.start()];
727
+ case 1:
728
+ _a.sent();
729
+ //#region Input validation
730
+ if (!isValidModelConstructor(modelConstructor)) {
731
+ msg = 'Constructor is not for a valid model';
732
+ logger.error(msg, { modelConstructor: modelConstructor });
733
+ throw new Error(msg);
734
+ }
735
+ if (typeof identifierOrCriteria === 'string') {
736
+ if (paginationProducer !== undefined) {
737
+ logger.warn('Pagination is ignored when querying by id');
738
+ }
739
+ }
740
+ modelDefinition = getModelDefinition(modelConstructor);
741
+ keyFields = extractPrimaryKeyFieldNames(modelDefinition);
742
+ if (isQueryOne(identifierOrCriteria)) {
743
+ if (keyFields.length > 1) {
744
+ msg = errorMessages.queryByPkWithCompositeKeyPresent;
745
+ logger.error(msg, { keyFields: keyFields });
746
+ throw new Error(msg);
747
+ }
748
+ predicate = ModelPredicateCreator.createForSingleField(modelDefinition, keyFields[0], identifierOrCriteria);
749
+ }
750
+ else {
751
+ // Object is being queried using object literal syntax
752
+ if (isIdentifierObject(identifierOrCriteria, modelDefinition)) {
753
+ predicate = ModelPredicateCreator.createForPk(modelDefinition, identifierOrCriteria);
754
+ }
755
+ else if (isPredicatesAll(identifierOrCriteria)) {
756
+ // Predicates.ALL means "all records", so no predicate (undefined)
757
+ predicate = undefined;
758
+ }
759
+ else {
760
+ predicate = ModelPredicateCreator.createFromExisting(modelDefinition, identifierOrCriteria);
761
+ }
762
+ }
763
+ pagination = this.processPagination(modelDefinition, paginationProducer);
764
+ //#endregion
765
+ logger.debug('params ready', {
766
+ modelConstructor: modelConstructor,
767
+ predicate: ModelPredicateCreator.getPredicates(predicate, false),
768
+ pagination: __assign(__assign({}, pagination), { sort: ModelSortPredicateCreator.getPredicates(pagination && pagination.sort, false) }),
769
+ });
770
+ return [4 /*yield*/, this.storage.query(modelConstructor, predicate, pagination)];
771
+ case 2:
772
+ result = _a.sent();
773
+ returnOne = isQueryOne(identifierOrCriteria) ||
774
+ isIdentifierObject(identifierOrCriteria, modelDefinition);
775
+ return [2 /*return*/, returnOne ? result[0] : result];
698
776
  }
699
- }
700
- pagination = this.processPagination(modelDefinition, paginationProducer);
701
- //#endregion
702
- logger.debug('params ready', {
703
- modelConstructor: modelConstructor,
704
- predicate: ModelPredicateCreator.getPredicates(predicate, false),
705
- pagination: __assign(__assign({}, pagination), { sort: ModelSortPredicateCreator.getPredicates(pagination && pagination.sort, false) }),
706
777
  });
707
- return [4 /*yield*/, this.storage.query(modelConstructor, predicate, pagination)];
708
- case 2:
709
- result = _a.sent();
710
- return [2 /*return*/, isQueryOne(idOrCriteria) ? result[0] : result];
711
- }
778
+ }); }, 'datastore query')
779
+ .catch(this.handleAddProcError('DataStore.query()'))];
712
780
  });
713
781
  }); };
714
782
  this.save = function (model, condition) { return __awaiter(_this, void 0, void 0, function () {
715
- var patchesTuple, modelConstructor, msg, modelDefinition, producedCondition, _a, savedModel;
716
783
  var _this = this;
717
- return __generator(this, function (_b) {
718
- switch (_b.label) {
719
- case 0: return [4 /*yield*/, this.start()];
720
- case 1:
721
- _b.sent();
722
- patchesTuple = modelPatchesMap.get(model);
723
- modelConstructor = model
724
- ? model.constructor
725
- : undefined;
726
- if (!isValidModelConstructor(modelConstructor)) {
727
- msg = 'Object is not an instance of a valid model';
728
- logger.error(msg, { model: model });
729
- throw new Error(msg);
730
- }
731
- modelDefinition = getModelDefinition(modelConstructor);
732
- producedCondition = ModelPredicateCreator.createFromExisting(modelDefinition, condition);
733
- return [4 /*yield*/, this.storage.runExclusive(function (s) { return __awaiter(_this, void 0, void 0, function () {
734
- return __generator(this, function (_a) {
735
- switch (_a.label) {
736
- case 0: return [4 /*yield*/, s.save(model, producedCondition, undefined, patchesTuple)];
737
- case 1:
738
- _a.sent();
739
- return [2 /*return*/, s.query(modelConstructor, ModelPredicateCreator.createForId(modelDefinition, model.id))];
784
+ return __generator(this, function (_a) {
785
+ return [2 /*return*/, this.runningProcesses
786
+ .add(function () { return __awaiter(_this, void 0, void 0, function () {
787
+ var patchesTuple, modelConstructor, msg, modelDefinition, producedCondition, _a, savedModel;
788
+ var _this = this;
789
+ return __generator(this, function (_b) {
790
+ switch (_b.label) {
791
+ case 0: return [4 /*yield*/, this.start()];
792
+ case 1:
793
+ _b.sent();
794
+ patchesTuple = modelPatchesMap.get(model);
795
+ modelConstructor = model ? model.constructor : undefined;
796
+ if (!isValidModelConstructor(modelConstructor)) {
797
+ msg = 'Object is not an instance of a valid model';
798
+ logger.error(msg, { model: model });
799
+ throw new Error(msg);
740
800
  }
741
- });
742
- }); })];
743
- case 2:
744
- _a = __read.apply(void 0, [_b.sent(), 1]), savedModel = _a[0];
745
- return [2 /*return*/, savedModel];
746
- }
801
+ modelDefinition = getModelDefinition(modelConstructor);
802
+ producedCondition = ModelPredicateCreator.createFromExisting(modelDefinition, condition);
803
+ return [4 /*yield*/, this.storage.runExclusive(function (s) { return __awaiter(_this, void 0, void 0, function () {
804
+ return __generator(this, function (_a) {
805
+ switch (_a.label) {
806
+ case 0: return [4 /*yield*/, s.save(model, producedCondition, undefined, patchesTuple)];
807
+ case 1:
808
+ _a.sent();
809
+ return [2 /*return*/, s.query(modelConstructor, ModelPredicateCreator.createForPk(modelDefinition, model))];
810
+ }
811
+ });
812
+ }); })];
813
+ case 2:
814
+ _a = __read.apply(void 0, [_b.sent(), 1]), savedModel = _a[0];
815
+ return [2 /*return*/, savedModel];
816
+ }
817
+ });
818
+ }); }, 'datastore save')
819
+ .catch(this.handleAddProcError('DataStore.save()'))];
747
820
  });
748
821
  }); };
749
822
  this.setConflictHandler = function (config) {
@@ -772,75 +845,95 @@ var DataStore = /** @class */ (function () {
772
845
  }
773
846
  return _this.errorHandler || defaultErrorHandler;
774
847
  };
775
- this.delete = function (modelOrConstructor, idOrCriteria) { return __awaiter(_this, void 0, void 0, function () {
776
- var condition, msg, modelConstructor, msg, msg, _a, deleted, model, modelConstructor, msg, modelDefinition, idPredicate, msg, _b, _c, deleted;
777
- return __generator(this, function (_d) {
778
- switch (_d.label) {
779
- case 0: return [4 /*yield*/, this.start()];
780
- case 1:
781
- _d.sent();
782
- if (!modelOrConstructor) {
783
- msg = 'Model or Model Constructor required';
784
- logger.error(msg, { modelOrConstructor: modelOrConstructor });
785
- throw new Error(msg);
786
- }
787
- if (!isValidModelConstructor(modelOrConstructor)) return [3 /*break*/, 3];
788
- modelConstructor = modelOrConstructor;
789
- if (!idOrCriteria) {
790
- msg = 'Id to delete or criteria required. Do you want to delete all? Pass Predicates.ALL';
791
- logger.error(msg, { idOrCriteria: idOrCriteria });
792
- throw new Error(msg);
793
- }
794
- if (typeof idOrCriteria === 'string') {
795
- condition = ModelPredicateCreator.createForId(getModelDefinition(modelConstructor), idOrCriteria);
796
- }
797
- else {
798
- condition = ModelPredicateCreator.createFromExisting(getModelDefinition(modelConstructor),
799
- /**
800
- * idOrCriteria is always a ProducerModelPredicate<T>, never a symbol.
801
- * The symbol is used only for typing purposes. e.g. see Predicates.ALL
802
- */
803
- idOrCriteria);
804
- if (!condition || !ModelPredicateCreator.isValidPredicate(condition)) {
805
- msg = 'Criteria required. Do you want to delete all? Pass Predicates.ALL';
806
- logger.error(msg, { condition: condition });
807
- throw new Error(msg);
808
- }
809
- }
810
- return [4 /*yield*/, this.storage.delete(modelConstructor, condition)];
811
- case 2:
812
- _a = __read.apply(void 0, [_d.sent(), 1]), deleted = _a[0];
813
- return [2 /*return*/, deleted];
814
- case 3:
815
- model = modelOrConstructor;
816
- modelConstructor = Object.getPrototypeOf(model || {})
817
- .constructor;
818
- if (!isValidModelConstructor(modelConstructor)) {
819
- msg = 'Object is not an instance of a valid model';
820
- logger.error(msg, { model: model });
821
- throw new Error(msg);
822
- }
823
- modelDefinition = getModelDefinition(modelConstructor);
824
- idPredicate = ModelPredicateCreator.createForId(modelDefinition, model.id);
825
- if (idOrCriteria) {
826
- if (typeof idOrCriteria !== 'function') {
827
- msg = 'Invalid criteria';
828
- logger.error(msg, { idOrCriteria: idOrCriteria });
829
- throw new Error(msg);
848
+ this.delete = function (modelOrConstructor, identifierOrCriteria) { return __awaiter(_this, void 0, void 0, function () {
849
+ var _this = this;
850
+ return __generator(this, function (_a) {
851
+ return [2 /*return*/, this.runningProcesses
852
+ .add(function () { return __awaiter(_this, void 0, void 0, function () {
853
+ var condition, msg, modelConstructor, msg, modelDefinition, keyFields, msg, msg, _a, deleted, model, modelConstructor, msg, modelDefinition, pkPredicate, msg, _b, _c, deleted;
854
+ return __generator(this, function (_d) {
855
+ switch (_d.label) {
856
+ case 0: return [4 /*yield*/, this.start()];
857
+ case 1:
858
+ _d.sent();
859
+ if (!modelOrConstructor) {
860
+ msg = 'Model or Model Constructor required';
861
+ logger.error(msg, { modelOrConstructor: modelOrConstructor });
862
+ throw new Error(msg);
863
+ }
864
+ if (!isValidModelConstructor(modelOrConstructor)) return [3 /*break*/, 3];
865
+ modelConstructor = modelOrConstructor;
866
+ if (!identifierOrCriteria) {
867
+ msg = 'Id to delete or criteria required. Do you want to delete all? Pass Predicates.ALL';
868
+ logger.error(msg, { identifierOrCriteria: identifierOrCriteria });
869
+ throw new Error(msg);
870
+ }
871
+ modelDefinition = getModelDefinition(modelConstructor);
872
+ if (typeof identifierOrCriteria === 'string') {
873
+ keyFields = extractPrimaryKeyFieldNames(modelDefinition);
874
+ if (keyFields.length > 1) {
875
+ msg = errorMessages.deleteByPkWithCompositeKeyPresent;
876
+ logger.error(msg, { keyFields: keyFields });
877
+ throw new Error(msg);
878
+ }
879
+ condition = ModelPredicateCreator.createForSingleField(getModelDefinition(modelConstructor), keyFields[0], identifierOrCriteria);
880
+ }
881
+ else {
882
+ if (isIdentifierObject(identifierOrCriteria, modelDefinition)) {
883
+ condition = ModelPredicateCreator.createForPk(modelDefinition, identifierOrCriteria);
884
+ }
885
+ else {
886
+ condition = ModelPredicateCreator.createFromExisting(modelDefinition,
887
+ /**
888
+ * idOrCriteria is always a ProducerModelPredicate<T>, never a symbol.
889
+ * The symbol is used only for typing purposes. e.g. see Predicates.ALL
890
+ */
891
+ identifierOrCriteria);
892
+ }
893
+ if (!condition ||
894
+ !ModelPredicateCreator.isValidPredicate(condition)) {
895
+ msg = 'Criteria required. Do you want to delete all? Pass Predicates.ALL';
896
+ logger.error(msg, { condition: condition });
897
+ throw new Error(msg);
898
+ }
899
+ }
900
+ return [4 /*yield*/, this.storage.delete(modelConstructor, condition)];
901
+ case 2:
902
+ _a = __read.apply(void 0, [_d.sent(), 1]), deleted = _a[0];
903
+ return [2 /*return*/, deleted];
904
+ case 3:
905
+ model = modelOrConstructor;
906
+ modelConstructor = Object.getPrototypeOf(model || {})
907
+ .constructor;
908
+ if (!isValidModelConstructor(modelConstructor)) {
909
+ msg = 'Object is not an instance of a valid model';
910
+ logger.error(msg, { model: model });
911
+ throw new Error(msg);
912
+ }
913
+ modelDefinition = getModelDefinition(modelConstructor);
914
+ pkPredicate = ModelPredicateCreator.createForPk(modelDefinition, model);
915
+ if (identifierOrCriteria) {
916
+ if (typeof identifierOrCriteria !== 'function') {
917
+ msg = 'Invalid criteria';
918
+ logger.error(msg, { identifierOrCriteria: identifierOrCriteria });
919
+ throw new Error(msg);
920
+ }
921
+ condition = identifierOrCriteria(pkPredicate);
922
+ }
923
+ else {
924
+ condition = pkPredicate;
925
+ }
926
+ return [4 /*yield*/, this.storage.delete(model, condition)];
927
+ case 4:
928
+ _b = __read.apply(void 0, [_d.sent(), 1]), _c = __read(_b[0], 1), deleted = _c[0];
929
+ return [2 /*return*/, deleted];
830
930
  }
831
- condition = idOrCriteria(idPredicate);
832
- }
833
- else {
834
- condition = idPredicate;
835
- }
836
- return [4 /*yield*/, this.storage.delete(model, condition)];
837
- case 4:
838
- _b = __read.apply(void 0, [_d.sent(), 1]), _c = __read(_b[0], 1), deleted = _c[0];
839
- return [2 /*return*/, deleted];
840
- }
931
+ });
932
+ }); }, 'datastore delete')
933
+ .catch(this.handleAddProcError('DataStore.delete()'))];
841
934
  });
842
935
  }); };
843
- this.observe = function (modelOrConstructor, idOrCriteria) {
936
+ this.observe = function (modelOrConstructor, identifierOrCriteria) {
844
937
  var predicate;
845
938
  var modelConstructor = modelOrConstructor && isValidModelConstructor(modelOrConstructor)
846
939
  ? modelOrConstructor
@@ -849,10 +942,10 @@ var DataStore = /** @class */ (function () {
849
942
  var model = modelOrConstructor;
850
943
  var modelConstructor_1 = model && Object.getPrototypeOf(model).constructor;
851
944
  if (isValidModelConstructor(modelConstructor_1)) {
852
- if (idOrCriteria) {
945
+ if (identifierOrCriteria) {
853
946
  logger.warn('idOrCriteria is ignored when using a model instance', {
854
947
  model: model,
855
- idOrCriteria: idOrCriteria,
948
+ identifierOrCriteria: identifierOrCriteria,
856
949
  });
857
950
  }
858
951
  return _this.observe(modelConstructor_1, model.id);
@@ -863,9 +956,17 @@ var DataStore = /** @class */ (function () {
863
956
  throw new Error(msg);
864
957
  }
865
958
  }
866
- if (idOrCriteria !== undefined && modelConstructor === undefined) {
959
+ // observe should not accept object literal syntax
960
+ if (identifierOrCriteria &&
961
+ modelConstructor &&
962
+ isIdentifierObject(identifierOrCriteria, getModelDefinition(modelConstructor))) {
963
+ var msg = errorMessages.observeWithObjectLiteral;
964
+ logger.error(msg, { objectLiteral: identifierOrCriteria });
965
+ throw new Error(msg);
966
+ }
967
+ if (identifierOrCriteria !== undefined && modelConstructor === undefined) {
867
968
  var msg = 'Cannot provide criteria without a modelConstructor';
868
- logger.error(msg, idOrCriteria);
969
+ logger.error(msg, identifierOrCriteria);
869
970
  throw new Error(msg);
870
971
  }
871
972
  if (modelConstructor && !isValidModelConstructor(modelConstructor)) {
@@ -873,17 +974,25 @@ var DataStore = /** @class */ (function () {
873
974
  logger.error(msg, { modelConstructor: modelConstructor });
874
975
  throw new Error(msg);
875
976
  }
876
- if (typeof idOrCriteria === 'string') {
877
- predicate = ModelPredicateCreator.createForId(getModelDefinition(modelConstructor), idOrCriteria);
977
+ if (typeof identifierOrCriteria === 'string') {
978
+ var modelDefinition = getModelDefinition(modelConstructor);
979
+ var _a = __read(extractPrimaryKeyFieldNames(modelDefinition), 1), keyField = _a[0];
980
+ predicate = ModelPredicateCreator.createForSingleField(getModelDefinition(modelConstructor), keyField, identifierOrCriteria);
878
981
  }
879
982
  else {
880
- predicate =
881
- modelConstructor &&
882
- ModelPredicateCreator.createFromExisting(getModelDefinition(modelConstructor), idOrCriteria);
983
+ if (isPredicatesAll(identifierOrCriteria)) {
984
+ predicate = undefined;
985
+ }
986
+ else {
987
+ predicate =
988
+ modelConstructor &&
989
+ ModelPredicateCreator.createFromExisting(getModelDefinition(modelConstructor), identifierOrCriteria);
990
+ }
883
991
  }
884
992
  return new Observable(function (observer) {
885
993
  var handle;
886
- (function () { return __awaiter(_this, void 0, void 0, function () {
994
+ _this.runningProcesses
995
+ .add(function () { return __awaiter(_this, void 0, void 0, function () {
887
996
  var _this = this;
888
997
  return __generator(this, function (_a) {
889
998
  switch (_a.label) {
@@ -899,36 +1008,52 @@ var DataStore = /** @class */ (function () {
899
1008
  return namespaceResolver(model) === USER;
900
1009
  })
901
1010
  .subscribe({
902
- next: function (item) { return __awaiter(_this, void 0, void 0, function () {
903
- var message, freshElement;
904
- return __generator(this, function (_a) {
905
- switch (_a.label) {
906
- case 0:
907
- message = item;
908
- if (!(item.opType !== 'DELETE')) return [3 /*break*/, 2];
909
- return [4 /*yield*/, this.query(item.model, item.element.id)];
910
- case 1:
911
- freshElement = _a.sent();
912
- message = __assign(__assign({}, message), { element: freshElement });
913
- _a.label = 2;
914
- case 2:
915
- observer.next(message);
916
- return [2 /*return*/];
917
- }
918
- });
919
- }); },
1011
+ next: function (item) {
1012
+ return _this.runningProcesses.isOpen &&
1013
+ _this.runningProcesses.add(function () { return __awaiter(_this, void 0, void 0, function () {
1014
+ var message, modelDefinition, keyFields, primaryKeysAndValues, freshElement;
1015
+ return __generator(this, function (_a) {
1016
+ switch (_a.label) {
1017
+ case 0:
1018
+ message = item;
1019
+ if (!(item.opType !== 'DELETE')) return [3 /*break*/, 2];
1020
+ modelDefinition = getModelDefinition(item.model);
1021
+ keyFields = extractPrimaryKeyFieldNames(modelDefinition);
1022
+ primaryKeysAndValues = extractPrimaryKeysAndValues(item.element, keyFields);
1023
+ return [4 /*yield*/, this.query(item.model, primaryKeysAndValues)];
1024
+ case 1:
1025
+ freshElement = _a.sent();
1026
+ message = __assign(__assign({}, message), { element: freshElement });
1027
+ _a.label = 2;
1028
+ case 2:
1029
+ observer.next(message);
1030
+ return [2 /*return*/];
1031
+ }
1032
+ });
1033
+ }); }, 'datastore observe message handler');
1034
+ },
920
1035
  error: function (err) { return observer.error(err); },
921
1036
  complete: function () { return observer.complete(); },
922
1037
  });
923
1038
  return [2 /*return*/];
924
1039
  }
925
1040
  });
926
- }); })();
927
- return function () {
928
- if (handle) {
929
- handle.unsubscribe();
930
- }
931
- };
1041
+ }); }, 'datastore observe observable initialization')
1042
+ .catch(_this.handleAddProcError('DataStore.observe()'))
1043
+ .catch(function (error) {
1044
+ observer.error(error);
1045
+ });
1046
+ // better than no cleaner, but if the subscriber is handling the
1047
+ // complete() message async and not registering with the context,
1048
+ // this will still be problematic.
1049
+ return _this.runningProcesses.addCleaner(function () { return __awaiter(_this, void 0, void 0, function () {
1050
+ return __generator(this, function (_a) {
1051
+ if (handle) {
1052
+ handle.unsubscribe();
1053
+ }
1054
+ return [2 /*return*/];
1055
+ });
1056
+ }); }, 'DataStore.observe() cleanup');
932
1057
  });
933
1058
  };
934
1059
  this.observeQuery = function (model, criteria, options) {
@@ -962,8 +1087,9 @@ var DataStore = /** @class */ (function () {
962
1087
  var sort = (options || {}).sort;
963
1088
  var sortOptions = sort ? { sort: sort } : undefined;
964
1089
  var modelDefinition = getModelDefinition(model);
1090
+ var keyFields = extractPrimaryKeyFieldNames(modelDefinition);
965
1091
  if (isQueryOne(criteria)) {
966
- predicate = ModelPredicateCreator.createForId(modelDefinition, criteria);
1092
+ predicate = ModelPredicateCreator.createForSingleField(modelDefinition, keyFields[0], criteria);
967
1093
  }
968
1094
  else {
969
1095
  if (isPredicatesAll(criteria)) {
@@ -976,7 +1102,8 @@ var DataStore = /** @class */ (function () {
976
1102
  }
977
1103
  var _a = ModelPredicateCreator.getPredicates(predicate, false) || {}, predicates = _a.predicates, predicateGroupType = _a.type;
978
1104
  var hasPredicate = !!predicates;
979
- (function () { return __awaiter(_this, void 0, void 0, function () {
1105
+ _this.runningProcesses
1106
+ .add(function () { return __awaiter(_this, void 0, void 0, function () {
980
1107
  var err_1;
981
1108
  var _this = this;
982
1109
  return __generator(this, function (_a) {
@@ -987,7 +1114,9 @@ var DataStore = /** @class */ (function () {
987
1114
  case 1:
988
1115
  // first, query and return any locally-available records
989
1116
  (_a.sent()).forEach(function (item) {
990
- return items.set(item.id, item);
1117
+ var itemModelDefinition = getModelDefinition(model);
1118
+ var idOrPk = getIdentifierValue(itemModelDefinition, item);
1119
+ items.set(idOrPk, item);
991
1120
  });
992
1121
  // Observe the model and send a stream of updates (debounced).
993
1122
  // We need to post-filter results instead of passing criteria through
@@ -996,15 +1125,17 @@ var DataStore = /** @class */ (function () {
996
1125
  handle = this.observe(model).subscribe(function (_a) {
997
1126
  var element = _a.element, model = _a.model, opType = _a.opType;
998
1127
  var _b, _c;
1128
+ var itemModelDefinition = getModelDefinition(model);
1129
+ var idOrPk = getIdentifierValue(itemModelDefinition, element);
999
1130
  if (hasPredicate &&
1000
1131
  !validatePredicate(element, predicateGroupType, predicates)) {
1001
1132
  if (opType === 'UPDATE' &&
1002
- (items.has(element.id) || itemsChanged.has(element.id))) {
1133
+ (items.has(idOrPk) || itemsChanged.has(idOrPk))) {
1003
1134
  // tracking as a "deleted item" will include the item in
1004
1135
  // page limit calculations and ensure it is removed from the
1005
1136
  // final items collection, regardless of which collection(s)
1006
1137
  // it is currently in. (I mean, it could be in both, right!?)
1007
- deletedItemIds.push(element.id);
1138
+ deletedItemIds.push(idOrPk);
1008
1139
  }
1009
1140
  else {
1010
1141
  // ignore updates for irrelevant/filtered items.
@@ -1016,13 +1147,14 @@ var DataStore = /** @class */ (function () {
1016
1147
  // in the `mergePage` method within src/sync/merger.ts. The final state of a model instance
1017
1148
  // depends on the LATEST record (for a given id).
1018
1149
  if (opType === 'DELETE') {
1019
- deletedItemIds.push(element.id);
1150
+ deletedItemIds.push(idOrPk);
1020
1151
  }
1021
1152
  else {
1022
- itemsChanged.set(element.id, element);
1153
+ itemsChanged.set(idOrPk, element);
1023
1154
  }
1024
1155
  var isSynced = (_c = (_b = _this.sync) === null || _b === void 0 ? void 0 : _b.getModelSyncedStatus(model)) !== null && _c !== void 0 ? _c : false;
1025
- var limit = itemsChanged.size - deletedItemIds.length >= _this.syncPageSize;
1156
+ var limit = itemsChanged.size - deletedItemIds.length >=
1157
+ _this.syncPageSize;
1026
1158
  if (limit || isSynced) {
1027
1159
  limitTimerRace.resolve();
1028
1160
  }
@@ -1039,7 +1171,11 @@ var DataStore = /** @class */ (function () {
1039
1171
  case 3: return [2 /*return*/];
1040
1172
  }
1041
1173
  });
1042
- }); })();
1174
+ }); }, 'datastore observequery startup')
1175
+ .catch(_this.handleAddProcError('DataStore.observeQuery()'))
1176
+ .catch(function (error) {
1177
+ observer.error(error);
1178
+ });
1043
1179
  /**
1044
1180
  * Combines the `items`, `itemsChanged`, and `deletedItemIds` collections into
1045
1181
  * a snapshot in the form of `{ items: T[], isSynced: boolean}`.
@@ -1054,9 +1190,13 @@ var DataStore = /** @class */ (function () {
1054
1190
  sortItems(itemsArray);
1055
1191
  }
1056
1192
  items.clear();
1057
- itemsArray.forEach(function (item) { return items.set(item.id, item); });
1193
+ itemsArray.forEach(function (item) {
1194
+ var itemModelDefinition = getModelDefinition(model);
1195
+ var idOrPk = getIdentifierValue(itemModelDefinition, item);
1196
+ items.set(idOrPk, item);
1197
+ });
1058
1198
  // remove deleted items from the final result set
1059
- deletedItemIds.forEach(function (id) { return items.delete(id); });
1199
+ deletedItemIds.forEach(function (idOrPk) { return items.delete(idOrPk); });
1060
1200
  return {
1061
1201
  items: Array.from(items.values()),
1062
1202
  isSynced: isSynced,
@@ -1071,7 +1211,8 @@ var DataStore = /** @class */ (function () {
1071
1211
  * @param snapshot The generated items data to emit.
1072
1212
  */
1073
1213
  var emitSnapshot = function (snapshot) {
1074
- // send the generated snapshot to the primary subscription
1214
+ // send the generated snapshot to the primary subscription.
1215
+ // NOTE: This observer's handler *could* be async ...
1075
1216
  observer.next(snapshot);
1076
1217
  // reset the changed items sets
1077
1218
  itemsChanged.clear();
@@ -1107,15 +1248,18 @@ var DataStore = /** @class */ (function () {
1107
1248
  if (event === ControlMessage.SYNC_ENGINE_MODEL_SYNCED &&
1108
1249
  ((_b = data === null || data === void 0 ? void 0 : data.model) === null || _b === void 0 ? void 0 : _b.name) === model.name) {
1109
1250
  generateAndEmitSnapshot();
1110
- Hub.remove('api', hubCallback);
1251
+ Hub.remove('datastore', hubCallback);
1111
1252
  }
1112
1253
  };
1113
1254
  Hub.listen('datastore', hubCallback);
1114
- return function () {
1115
- if (handle) {
1116
- handle.unsubscribe();
1117
- }
1118
- };
1255
+ return _this.runningProcesses.addCleaner(function () { return __awaiter(_this, void 0, void 0, function () {
1256
+ return __generator(this, function (_a) {
1257
+ if (handle) {
1258
+ handle.unsubscribe();
1259
+ }
1260
+ return [2 /*return*/];
1261
+ });
1262
+ }); }, 'datastore observequery cleaner');
1119
1263
  });
1120
1264
  };
1121
1265
  this.configure = function (config) {
@@ -1174,66 +1318,132 @@ var DataStore = /** @class */ (function () {
1174
1318
  undefined;
1175
1319
  _this.sessionId = _this.retrieveSessionId();
1176
1320
  };
1177
- this.clear = function clear() {
1178
- return __awaiter(this, void 0, void 0, function () {
1179
- return __generator(this, function (_a) {
1180
- switch (_a.label) {
1181
- case 0:
1182
- checkSchemaInitialized();
1183
- if (!(this.storage === undefined)) return [3 /*break*/, 2];
1184
- // connect to storage so that it can be cleared without fully starting DataStore
1185
- this.storage = new Storage(schema, namespaceResolver, getModelConstructorByModelName, modelInstanceCreator, this.storageAdapter, this.sessionId);
1186
- return [4 /*yield*/, this.storage.init()];
1187
- case 1:
1188
- _a.sent();
1189
- _a.label = 2;
1190
- case 2:
1191
- if (syncSubscription && !syncSubscription.closed) {
1192
- syncSubscription.unsubscribe();
1193
- }
1194
- return [4 /*yield*/, this.storage.clear()];
1195
- case 3:
1196
- _a.sent();
1197
- if (this.sync) {
1198
- this.sync.unsubscribeConnectivity();
1199
- }
1200
- this.initialized = undefined; // Should re-initialize when start() is called.
1201
- this.storage = undefined;
1202
- this.sync = undefined;
1203
- this.syncPredicates = new WeakMap();
1204
- return [2 /*return*/];
1205
- }
1206
- });
1207
- });
1208
- };
1209
- this.stop = function stop() {
1210
- return __awaiter(this, void 0, void 0, function () {
1211
- return __generator(this, function (_a) {
1212
- switch (_a.label) {
1213
- case 0:
1214
- if (!(this.initialized !== undefined)) return [3 /*break*/, 2];
1215
- return [4 /*yield*/, this.start()];
1216
- case 1:
1217
- _a.sent();
1218
- _a.label = 2;
1219
- case 2:
1220
- if (syncSubscription && !syncSubscription.closed) {
1221
- syncSubscription.unsubscribe();
1222
- }
1223
- if (this.sync) {
1224
- this.sync.unsubscribeConnectivity();
1225
- }
1226
- this.initialized = undefined; // Should re-initialize when start() is called.
1227
- this.sync = undefined;
1228
- return [2 /*return*/];
1229
- }
1230
- });
1231
- });
1232
- };
1233
1321
  }
1234
1322
  DataStore.prototype.getModuleName = function () {
1235
1323
  return 'DataStore';
1236
1324
  };
1325
+ /**
1326
+ * Builds a function to capture `BackgroundManagerNotOpenError`'s to produce friendlier,
1327
+ * more instructive errors for customers.
1328
+ *
1329
+ * @param operation The name of the operation (usually a Datastore method) the customer
1330
+ * tried to call.
1331
+ */
1332
+ DataStore.prototype.handleAddProcError = function (operation) {
1333
+ var _this = this;
1334
+ /**
1335
+ * If the tested error is a `BackgroundManagerNotOpenError`, it will be captured
1336
+ * and replaced with a friendlier message that instructs the App Developer.
1337
+ *
1338
+ * @param err An error to test.
1339
+ */
1340
+ var handler = function (err) {
1341
+ if (err.message.startsWith('BackgroundManagerNotOpenError')) {
1342
+ throw new Error([
1343
+ "DataStoreStateError: Tried to execute `" + operation + "` while DataStore was \"" + _this.state + "\".",
1344
+ "This can only be done while DataStore is \"Started\" or \"Stopped\". To remedy:",
1345
+ 'Ensure all calls to `stop()` and `clear()` have completed first.',
1346
+ 'If this is not possible, retry the operation until it succeeds.',
1347
+ ].join('\n'));
1348
+ }
1349
+ else {
1350
+ throw err;
1351
+ }
1352
+ };
1353
+ return handler;
1354
+ };
1355
+ /**
1356
+ * Clears all data from storage and removes all data, schema info, other
1357
+ * initialization details, and then stops DataStore.
1358
+ *
1359
+ * That said, reinitialization is required after clearing. This can be done
1360
+ * by explicitiliy calling `start()` or any method that implicitly starts
1361
+ * DataStore, such as `query()`, `save()`, or `delete()`.
1362
+ */
1363
+ DataStore.prototype.clear = function () {
1364
+ return __awaiter(this, void 0, void 0, function () {
1365
+ return __generator(this, function (_a) {
1366
+ switch (_a.label) {
1367
+ case 0:
1368
+ checkSchemaInitialized();
1369
+ this.state = DataStoreState.Clearing;
1370
+ return [4 /*yield*/, this.runningProcesses.close()];
1371
+ case 1:
1372
+ _a.sent();
1373
+ if (!(this.storage === undefined)) return [3 /*break*/, 3];
1374
+ // connect to storage so that it can be cleared without fully starting DataStore
1375
+ this.storage = new Storage(schema, namespaceResolver, getModelConstructorByModelName, modelInstanceCreator, this.storageAdapter, this.sessionId);
1376
+ return [4 /*yield*/, this.storage.init()];
1377
+ case 2:
1378
+ _a.sent();
1379
+ _a.label = 3;
1380
+ case 3:
1381
+ if (syncSubscription && !syncSubscription.closed) {
1382
+ syncSubscription.unsubscribe();
1383
+ }
1384
+ if (!this.sync) return [3 /*break*/, 5];
1385
+ return [4 /*yield*/, this.sync.stop()];
1386
+ case 4:
1387
+ _a.sent();
1388
+ _a.label = 5;
1389
+ case 5: return [4 /*yield*/, this.storage.clear()];
1390
+ case 6:
1391
+ _a.sent();
1392
+ this.initialized = undefined; // Should re-initialize when start() is called.
1393
+ this.storage = undefined;
1394
+ this.sync = undefined;
1395
+ this.syncPredicates = new WeakMap();
1396
+ return [4 /*yield*/, this.runningProcesses.open()];
1397
+ case 7:
1398
+ _a.sent();
1399
+ this.state = DataStoreState.NotRunning;
1400
+ return [2 /*return*/];
1401
+ }
1402
+ });
1403
+ });
1404
+ };
1405
+ /**
1406
+ * Stops all DataStore sync activities.
1407
+ *
1408
+ * TODO: "Waits for graceful termination of
1409
+ * running queries and terminates subscriptions."
1410
+ */
1411
+ DataStore.prototype.stop = function () {
1412
+ return __awaiter(this, void 0, void 0, function () {
1413
+ return __generator(this, function (_a) {
1414
+ switch (_a.label) {
1415
+ case 0:
1416
+ this.state = DataStoreState.Stopping;
1417
+ return [4 /*yield*/, this.runningProcesses.close()];
1418
+ case 1:
1419
+ _a.sent();
1420
+ if (syncSubscription && !syncSubscription.closed) {
1421
+ syncSubscription.unsubscribe();
1422
+ }
1423
+ if (!this.sync) return [3 /*break*/, 3];
1424
+ return [4 /*yield*/, this.sync.stop()];
1425
+ case 2:
1426
+ _a.sent();
1427
+ _a.label = 3;
1428
+ case 3:
1429
+ this.initialized = undefined; // Should re-initialize when start() is called.
1430
+ this.sync = undefined;
1431
+ return [4 /*yield*/, this.runningProcesses.open()];
1432
+ case 4:
1433
+ _a.sent();
1434
+ this.state = DataStoreState.NotRunning;
1435
+ return [2 /*return*/];
1436
+ }
1437
+ });
1438
+ });
1439
+ };
1440
+ /**
1441
+ * Validates given pagination input from a query and creates a pagination
1442
+ * argument for use against the storage layer.
1443
+ *
1444
+ * @param modelDefinition
1445
+ * @param paginationProducer
1446
+ */
1237
1447
  DataStore.prototype.processPagination = function (modelDefinition, paginationProducer) {
1238
1448
  var sortPredicate;
1239
1449
  var _a = paginationProducer || {}, limit = _a.limit, page = _a.page, sort = _a.sort;
@@ -1268,6 +1478,10 @@ var DataStore = /** @class */ (function () {
1268
1478
  sort: sortPredicate,
1269
1479
  };
1270
1480
  };
1481
+ /**
1482
+ * Examines the configured `syncExpressions` and produces a WeakMap of
1483
+ * SchemaModel -> predicate to use during sync.
1484
+ */
1271
1485
  DataStore.prototype.processSyncExpressions = function () {
1272
1486
  return __awaiter(this, void 0, void 0, function () {
1273
1487
  var syncPredicates;
@@ -1349,7 +1563,10 @@ var DataStore = /** @class */ (function () {
1349
1563
  return map;
1350
1564
  }, new WeakMap());
1351
1565
  };
1352
- // database separation for Amplify Console. Not a public API
1566
+ /**
1567
+ * A session ID to allow CMS to open databases against multiple apps.
1568
+ * This session ID is only expected be set by AWS Amplify Studio.
1569
+ */
1353
1570
  DataStore.prototype.retrieveSessionId = function () {
1354
1571
  try {
1355
1572
  var sessionId = sessionStorage.getItem('datastoreSessionId');
@@ -1360,9 +1577,8 @@ var DataStore = /** @class */ (function () {
1360
1577
  return sessionId + "-" + appSyncId;
1361
1578
  }
1362
1579
  }
1363
- catch (_b) {
1364
- return undefined;
1365
- }
1580
+ catch (_b) { }
1581
+ return undefined;
1366
1582
  };
1367
1583
  return DataStore;
1368
1584
  }());