@aws-amplify/datastore 4.7.6-api-v6-models.b3abc9b.0 → 5.0.0

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 (187) hide show
  1. package/README.md +4 -0
  2. package/lib/authModeStrategies/defaultAuthStrategy.js +3 -2
  3. package/lib/authModeStrategies/index.js +3 -3
  4. package/lib/authModeStrategies/multiAuthStrategy.js +38 -53
  5. package/lib/datastore/datastore.d.ts +4 -5
  6. package/lib/datastore/datastore.js +929 -1284
  7. package/lib/index.d.ts +1 -1
  8. package/lib/index.js +26 -13
  9. package/lib/predicates/index.js +54 -69
  10. package/lib/predicates/next.d.ts +2 -2
  11. package/lib/predicates/next.js +313 -462
  12. package/lib/predicates/sort.js +24 -28
  13. package/lib/ssr/index.js +2 -2
  14. package/lib/storage/adapter/AsyncStorageAdapter.js +120 -342
  15. package/lib/storage/adapter/AsyncStorageDatabase.js +217 -421
  16. package/lib/storage/adapter/InMemoryStore.js +28 -51
  17. package/lib/storage/adapter/InMemoryStore.native.js +5 -3
  18. package/lib/storage/adapter/IndexedDBAdapter.js +466 -871
  19. package/lib/storage/adapter/StorageAdapterBase.js +180 -330
  20. package/lib/storage/adapter/getDefaultAdapter/index.js +8 -10
  21. package/lib/storage/adapter/getDefaultAdapter/index.native.js +5 -4
  22. package/lib/storage/adapter/index.js +0 -1
  23. package/lib/storage/relationship.js +177 -253
  24. package/lib/storage/storage.d.ts +4 -4
  25. package/lib/storage/storage.js +255 -433
  26. package/lib/sync/datastoreConnectivity.d.ts +2 -2
  27. package/lib/sync/datastoreConnectivity.js +29 -39
  28. package/lib/sync/datastoreReachability/index.d.ts +1 -3
  29. package/lib/sync/datastoreReachability/index.js +3 -3
  30. package/lib/sync/datastoreReachability/index.native.d.ts +1 -3
  31. package/lib/sync/datastoreReachability/index.native.js +4 -5
  32. package/lib/sync/index.d.ts +2 -2
  33. package/lib/sync/index.js +522 -827
  34. package/lib/sync/merger.js +31 -63
  35. package/lib/sync/outbox.js +148 -232
  36. package/lib/sync/processors/errorMaps.d.ts +1 -1
  37. package/lib/sync/processors/errorMaps.js +30 -47
  38. package/lib/sync/processors/mutation.d.ts +2 -2
  39. package/lib/sync/processors/mutation.js +343 -502
  40. package/lib/sync/processors/subscription.d.ts +5 -2
  41. package/lib/sync/processors/subscription.js +283 -437
  42. package/lib/sync/processors/sync.d.ts +2 -2
  43. package/lib/sync/processors/sync.js +279 -404
  44. package/lib/sync/utils.d.ts +5 -4
  45. package/lib/sync/utils.js +267 -320
  46. package/lib/tsconfig.tsbuildinfo +1 -0
  47. package/lib/types.d.ts +138 -140
  48. package/lib/types.js +17 -24
  49. package/lib/util.d.ts +9 -17
  50. package/lib/util.js +387 -511
  51. package/lib-esm/authModeStrategies/defaultAuthStrategy.js +1 -2
  52. package/lib-esm/authModeStrategies/index.js +0 -1
  53. package/lib-esm/authModeStrategies/multiAuthStrategy.js +35 -52
  54. package/lib-esm/datastore/datastore.d.ts +4 -5
  55. package/lib-esm/datastore/datastore.js +888 -1247
  56. package/lib-esm/index.d.ts +1 -1
  57. package/lib-esm/index.js +6 -7
  58. package/lib-esm/predicates/index.js +53 -70
  59. package/lib-esm/predicates/next.d.ts +2 -2
  60. package/lib-esm/predicates/next.js +306 -459
  61. package/lib-esm/predicates/sort.js +23 -28
  62. package/lib-esm/ssr/index.js +1 -2
  63. package/lib-esm/storage/adapter/AsyncStorageAdapter.js +111 -338
  64. package/lib-esm/storage/adapter/AsyncStorageDatabase.js +212 -416
  65. package/lib-esm/storage/adapter/InMemoryStore.js +27 -52
  66. package/lib-esm/storage/adapter/InMemoryStore.native.js +0 -1
  67. package/lib-esm/storage/adapter/IndexedDBAdapter.js +438 -866
  68. package/lib-esm/storage/adapter/StorageAdapterBase.js +173 -325
  69. package/lib-esm/storage/adapter/getDefaultAdapter/index.js +2 -6
  70. package/lib-esm/storage/adapter/getDefaultAdapter/index.native.js +1 -2
  71. package/lib-esm/storage/adapter/index.js +1 -1
  72. package/lib-esm/storage/relationship.js +173 -251
  73. package/lib-esm/storage/storage.d.ts +4 -4
  74. package/lib-esm/storage/storage.js +242 -424
  75. package/lib-esm/sync/datastoreConnectivity.d.ts +2 -2
  76. package/lib-esm/sync/datastoreConnectivity.js +28 -39
  77. package/lib-esm/sync/datastoreReachability/index.d.ts +1 -3
  78. package/lib-esm/sync/datastoreReachability/index.js +2 -3
  79. package/lib-esm/sync/datastoreReachability/index.native.d.ts +1 -3
  80. package/lib-esm/sync/datastoreReachability/index.native.js +3 -4
  81. package/lib-esm/sync/index.d.ts +2 -2
  82. package/lib-esm/sync/index.js +502 -812
  83. package/lib-esm/sync/merger.js +28 -61
  84. package/lib-esm/sync/outbox.js +143 -228
  85. package/lib-esm/sync/processors/errorMaps.d.ts +1 -1
  86. package/lib-esm/sync/processors/errorMaps.js +32 -50
  87. package/lib-esm/sync/processors/mutation.d.ts +2 -2
  88. package/lib-esm/sync/processors/mutation.js +329 -490
  89. package/lib-esm/sync/processors/subscription.d.ts +5 -2
  90. package/lib-esm/sync/processors/subscription.js +266 -421
  91. package/lib-esm/sync/processors/sync.d.ts +2 -2
  92. package/lib-esm/sync/processors/sync.js +271 -397
  93. package/lib-esm/sync/utils.d.ts +5 -4
  94. package/lib-esm/sync/utils.js +252 -307
  95. package/lib-esm/tsconfig.tsbuildinfo +1 -0
  96. package/lib-esm/types.d.ts +138 -140
  97. package/lib-esm/types.js +16 -25
  98. package/lib-esm/util.d.ts +9 -17
  99. package/lib-esm/util.js +335 -497
  100. package/package.json +31 -26
  101. package/src/authModeStrategies/multiAuthStrategy.ts +15 -12
  102. package/src/datastore/datastore.ts +36 -35
  103. package/src/predicates/sort.ts +3 -1
  104. package/src/storage/adapter/InMemoryStore.ts +1 -1
  105. package/src/storage/adapter/IndexedDBAdapter.ts +2 -2
  106. package/src/storage/adapter/StorageAdapterBase.ts +2 -2
  107. package/src/storage/adapter/getDefaultAdapter/index.ts +1 -4
  108. package/src/storage/storage.ts +29 -24
  109. package/src/sync/datastoreConnectivity.ts +6 -6
  110. package/src/sync/datastoreReachability/index.native.ts +5 -3
  111. package/src/sync/datastoreReachability/index.ts +1 -1
  112. package/src/sync/index.ts +79 -89
  113. package/src/sync/processors/errorMaps.ts +7 -7
  114. package/src/sync/processors/mutation.ts +19 -13
  115. package/src/sync/processors/subscription.ts +221 -295
  116. package/src/sync/processors/sync.ts +11 -8
  117. package/src/sync/utils.ts +30 -15
  118. package/src/types.ts +4 -8
  119. package/src/util.ts +46 -9
  120. package/lib/.tsbuildinfo +0 -3
  121. package/lib/authModeStrategies/defaultAuthStrategy.js.map +0 -1
  122. package/lib/authModeStrategies/index.js.map +0 -1
  123. package/lib/authModeStrategies/multiAuthStrategy.js.map +0 -1
  124. package/lib/datastore/datastore.js.map +0 -1
  125. package/lib/index.js.map +0 -1
  126. package/lib/predicates/index.js.map +0 -1
  127. package/lib/predicates/next.js.map +0 -1
  128. package/lib/predicates/sort.js.map +0 -1
  129. package/lib/ssr/index.js.map +0 -1
  130. package/lib/storage/adapter/AsyncStorageAdapter.js.map +0 -1
  131. package/lib/storage/adapter/AsyncStorageDatabase.js.map +0 -1
  132. package/lib/storage/adapter/InMemoryStore.js.map +0 -1
  133. package/lib/storage/adapter/InMemoryStore.native.js.map +0 -1
  134. package/lib/storage/adapter/IndexedDBAdapter.js.map +0 -1
  135. package/lib/storage/adapter/StorageAdapterBase.js.map +0 -1
  136. package/lib/storage/adapter/getDefaultAdapter/index.js.map +0 -1
  137. package/lib/storage/adapter/getDefaultAdapter/index.native.js.map +0 -1
  138. package/lib/storage/adapter/index.js.map +0 -1
  139. package/lib/storage/relationship.js.map +0 -1
  140. package/lib/storage/storage.js.map +0 -1
  141. package/lib/sync/datastoreConnectivity.js.map +0 -1
  142. package/lib/sync/datastoreReachability/index.js.map +0 -1
  143. package/lib/sync/datastoreReachability/index.native.js.map +0 -1
  144. package/lib/sync/index.js.map +0 -1
  145. package/lib/sync/merger.js.map +0 -1
  146. package/lib/sync/outbox.js.map +0 -1
  147. package/lib/sync/processors/errorMaps.js.map +0 -1
  148. package/lib/sync/processors/mutation.js.map +0 -1
  149. package/lib/sync/processors/subscription.js.map +0 -1
  150. package/lib/sync/processors/sync.js.map +0 -1
  151. package/lib/sync/utils.js.map +0 -1
  152. package/lib/types.js.map +0 -1
  153. package/lib/util.js.map +0 -1
  154. package/lib-esm/.tsbuildinfo +0 -3
  155. package/lib-esm/authModeStrategies/defaultAuthStrategy.js.map +0 -1
  156. package/lib-esm/authModeStrategies/index.js.map +0 -1
  157. package/lib-esm/authModeStrategies/multiAuthStrategy.js.map +0 -1
  158. package/lib-esm/datastore/datastore.js.map +0 -1
  159. package/lib-esm/index.js.map +0 -1
  160. package/lib-esm/predicates/index.js.map +0 -1
  161. package/lib-esm/predicates/next.js.map +0 -1
  162. package/lib-esm/predicates/sort.js.map +0 -1
  163. package/lib-esm/ssr/index.js.map +0 -1
  164. package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +0 -1
  165. package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +0 -1
  166. package/lib-esm/storage/adapter/InMemoryStore.js.map +0 -1
  167. package/lib-esm/storage/adapter/InMemoryStore.native.js.map +0 -1
  168. package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +0 -1
  169. package/lib-esm/storage/adapter/StorageAdapterBase.js.map +0 -1
  170. package/lib-esm/storage/adapter/getDefaultAdapter/index.js.map +0 -1
  171. package/lib-esm/storage/adapter/getDefaultAdapter/index.native.js.map +0 -1
  172. package/lib-esm/storage/adapter/index.js.map +0 -1
  173. package/lib-esm/storage/relationship.js.map +0 -1
  174. package/lib-esm/storage/storage.js.map +0 -1
  175. package/lib-esm/sync/datastoreConnectivity.js.map +0 -1
  176. package/lib-esm/sync/datastoreReachability/index.js.map +0 -1
  177. package/lib-esm/sync/datastoreReachability/index.native.js.map +0 -1
  178. package/lib-esm/sync/index.js.map +0 -1
  179. package/lib-esm/sync/merger.js.map +0 -1
  180. package/lib-esm/sync/outbox.js.map +0 -1
  181. package/lib-esm/sync/processors/errorMaps.js.map +0 -1
  182. package/lib-esm/sync/processors/mutation.js.map +0 -1
  183. package/lib-esm/sync/processors/subscription.js.map +0 -1
  184. package/lib-esm/sync/processors/sync.js.map +0 -1
  185. package/lib-esm/sync/utils.js.map +0 -1
  186. package/lib-esm/types.js.map +0 -1
  187. package/lib-esm/util.js.map +0 -1
@@ -1,14 +1,36 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  Object.defineProperty(exports, "__esModule", { value: true });
3
- var tslib_1 = require("tslib");
4
26
  // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
5
27
  // SPDX-License-Identifier: Apache-2.0
6
- var core_1 = require("@aws-amplify/core");
7
- var idb = tslib_1.__importStar(require("idb"));
8
- var types_1 = require("../../types");
9
- var util_1 = require("../../util");
10
- var StorageAdapterBase_1 = require("./StorageAdapterBase");
11
- var logger = new core_1.ConsoleLogger('DataStore');
28
+ const idb = __importStar(require("idb"));
29
+ const types_1 = require("../../types");
30
+ const util_1 = require("../../util");
31
+ const StorageAdapterBase_1 = require("./StorageAdapterBase");
32
+ const core_1 = require("@aws-amplify/core");
33
+ const logger = new core_1.ConsoleLogger('DataStore');
12
34
  /**
13
35
  * The point after which queries composed of multiple simple OR conditions
14
36
  * should scan-and-filter instead of individual queries for each condition.
@@ -30,14 +52,13 @@ var logger = new core_1.ConsoleLogger('DataStore');
30
52
  * etc...
31
53
  *
32
54
  */
33
- var MULTI_OR_CONDITION_SCAN_BREAKPOINT = 7;
55
+ const MULTI_OR_CONDITION_SCAN_BREAKPOINT = 7;
34
56
  //
35
- var DB_VERSION = 3;
36
- var IndexedDBAdapter = /** @class */ (function (_super) {
37
- tslib_1.__extends(IndexedDBAdapter, _super);
38
- function IndexedDBAdapter() {
39
- var _this = _super !== null && _super.apply(this, arguments) || this;
40
- _this.safariCompatabilityMode = false;
57
+ const DB_VERSION = 3;
58
+ class IndexedDBAdapter extends StorageAdapterBase_1.StorageAdapterBase {
59
+ constructor() {
60
+ super(...arguments);
61
+ this.safariCompatabilityMode = false;
41
62
  /**
42
63
  * Checks the given path against the browser's IndexedDB implementation for
43
64
  * necessary compatibility transformations, applying those transforms if needed.
@@ -46,43 +67,22 @@ var IndexedDBAdapter = /** @class */ (function (_super) {
46
67
  * @returns An array or string, depending on and given key,
47
68
  * that is ensured to be compatible with the IndexedDB implementation's nuances.
48
69
  */
49
- _this.canonicalKeyPath = function (keyArr) {
50
- if (_this.safariCompatabilityMode) {
70
+ this.canonicalKeyPath = (keyArr) => {
71
+ if (this.safariCompatabilityMode) {
51
72
  return keyArr.length > 1 ? keyArr : keyArr[0];
52
73
  }
53
74
  return keyArr;
54
75
  };
55
- return _this;
56
76
  //#endregion
57
77
  }
58
78
  // checks are called by StorageAdapterBase class
59
- IndexedDBAdapter.prototype.preSetUpChecks = function () {
60
- return tslib_1.__awaiter(this, void 0, void 0, function () {
61
- return tslib_1.__generator(this, function (_a) {
62
- switch (_a.label) {
63
- case 0: return [4 /*yield*/, this.checkPrivate()];
64
- case 1:
65
- _a.sent();
66
- return [4 /*yield*/, this.setSafariCompatabilityMode()];
67
- case 2:
68
- _a.sent();
69
- return [2 /*return*/];
70
- }
71
- });
72
- });
73
- };
74
- IndexedDBAdapter.prototype.preOpCheck = function () {
75
- return tslib_1.__awaiter(this, void 0, void 0, function () {
76
- return tslib_1.__generator(this, function (_a) {
77
- switch (_a.label) {
78
- case 0: return [4 /*yield*/, this.checkPrivate()];
79
- case 1:
80
- _a.sent();
81
- return [2 /*return*/];
82
- }
83
- });
84
- });
85
- };
79
+ async preSetUpChecks() {
80
+ await this.checkPrivate();
81
+ await this.setSafariCompatabilityMode();
82
+ }
83
+ async preOpCheck() {
84
+ await this.checkPrivate();
85
+ }
86
86
  /**
87
87
  * Initialize IndexedDB database
88
88
  * Create new DB if one doesn't exist
@@ -92,518 +92,245 @@ var IndexedDBAdapter = /** @class */ (function (_super) {
92
92
  *
93
93
  * @returns IDB Database instance
94
94
  */
95
- IndexedDBAdapter.prototype.initDb = function () {
96
- return tslib_1.__awaiter(this, void 0, void 0, function () {
97
- var _this = this;
98
- return tslib_1.__generator(this, function (_a) {
99
- switch (_a.label) {
100
- case 0: return [4 /*yield*/, idb.openDB(this.dbName, DB_VERSION, {
101
- upgrade: function (db, oldVersion, newVersion, txn) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
102
- var _a, _b, storeName, origStore, tmpName, _c, namespaceName, modelName, modelInCurrentSchema, newStore, cursor, count, e_1_1, error_1;
103
- var e_1, _d;
104
- var _this = this;
105
- return tslib_1.__generator(this, function (_e) {
106
- switch (_e.label) {
107
- case 0:
108
- // create new database
109
- if (oldVersion === 0) {
110
- Object.keys(this.schema.namespaces).forEach(function (namespaceName) {
111
- var namespace = _this.schema.namespaces[namespaceName];
112
- Object.keys(namespace.models).forEach(function (modelName) {
113
- var storeName = util_1.getStorename(namespaceName, modelName);
114
- _this.createObjectStoreForModel(db, namespaceName, storeName, modelName);
115
- });
116
- });
117
- return [2 /*return*/];
118
- }
119
- if (!((oldVersion === 1 || oldVersion === 2) && newVersion === 3)) return [3 /*break*/, 16];
120
- _e.label = 1;
121
- case 1:
122
- _e.trys.push([1, 14, , 15]);
123
- _e.label = 2;
124
- case 2:
125
- _e.trys.push([2, 11, 12, 13]);
126
- _a = tslib_1.__values(txn.objectStoreNames), _b = _a.next();
127
- _e.label = 3;
128
- case 3:
129
- if (!!_b.done) return [3 /*break*/, 10];
130
- storeName = _b.value;
131
- origStore = txn.objectStore(storeName);
132
- tmpName = "tmp_" + storeName;
133
- origStore.name = tmpName;
134
- _c = this.getNamespaceAndModelFromStorename(storeName), namespaceName = _c.namespaceName, modelName = _c.modelName;
135
- modelInCurrentSchema = modelName in this.schema.namespaces[namespaceName].models;
136
- if (!modelInCurrentSchema) {
137
- // delete original
138
- db.deleteObjectStore(tmpName);
139
- return [3 /*break*/, 9];
140
- }
141
- newStore = this.createObjectStoreForModel(db, namespaceName, storeName, modelName);
142
- return [4 /*yield*/, origStore.openCursor()];
143
- case 4:
144
- cursor = _e.sent();
145
- count = 0;
146
- _e.label = 5;
147
- case 5:
148
- if (!(cursor && cursor.value)) return [3 /*break*/, 8];
149
- // we don't pass key, since they are all new entries in the new store
150
- return [4 /*yield*/, newStore.put(cursor.value)];
151
- case 6:
152
- // we don't pass key, since they are all new entries in the new store
153
- _e.sent();
154
- return [4 /*yield*/, cursor.continue()];
155
- case 7:
156
- cursor = _e.sent();
157
- count++;
158
- return [3 /*break*/, 5];
159
- case 8:
160
- // delete original
161
- db.deleteObjectStore(tmpName);
162
- logger.debug(count + " " + storeName + " records migrated");
163
- _e.label = 9;
164
- case 9:
165
- _b = _a.next();
166
- return [3 /*break*/, 3];
167
- case 10: return [3 /*break*/, 13];
168
- case 11:
169
- e_1_1 = _e.sent();
170
- e_1 = { error: e_1_1 };
171
- return [3 /*break*/, 13];
172
- case 12:
173
- try {
174
- if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
175
- }
176
- finally { if (e_1) throw e_1.error; }
177
- return [7 /*endfinally*/];
178
- case 13:
179
- // add new models created after IndexedDB, but before migration
180
- // this case may happen when a user has not opened an app for
181
- // some time and a new model is added during that time
182
- Object.keys(this.schema.namespaces).forEach(function (namespaceName) {
183
- var namespace = _this.schema.namespaces[namespaceName];
184
- var objectStoreNames = new Set(txn.objectStoreNames);
185
- Object.keys(namespace.models)
186
- .map(function (modelName) {
187
- return [modelName, util_1.getStorename(namespaceName, modelName)];
188
- })
189
- .filter(function (_a) {
190
- var _b = tslib_1.__read(_a, 2), storeName = _b[1];
191
- return !objectStoreNames.has(storeName);
192
- })
193
- .forEach(function (_a) {
194
- var _b = tslib_1.__read(_a, 2), modelName = _b[0], storeName = _b[1];
195
- _this.createObjectStoreForModel(db, namespaceName, storeName, modelName);
196
- });
197
- });
198
- return [3 /*break*/, 15];
199
- case 14:
200
- error_1 = _e.sent();
201
- logger.error('Error migrating IndexedDB data', error_1);
202
- txn.abort();
203
- throw error_1;
204
- case 15: return [2 /*return*/];
205
- case 16: return [2 /*return*/];
206
- }
207
- });
208
- }); },
209
- })];
210
- case 1: return [2 /*return*/, _a.sent()];
211
- }
212
- });
213
- });
214
- };
215
- IndexedDBAdapter.prototype._get = function (storeOrStoreName, keyArr) {
216
- return tslib_1.__awaiter(this, void 0, void 0, function () {
217
- var index, storeName, store, result;
218
- return tslib_1.__generator(this, function (_a) {
219
- switch (_a.label) {
220
- case 0:
221
- if (typeof storeOrStoreName === 'string') {
222
- storeName = storeOrStoreName;
223
- index = this.db.transaction(storeName, 'readonly').store.index('byPk');
224
- }
225
- else {
226
- store = storeOrStoreName;
227
- index = store.index('byPk');
228
- }
229
- return [4 /*yield*/, index.get(this.canonicalKeyPath(keyArr))];
230
- case 1:
231
- result = _a.sent();
232
- return [2 /*return*/, result];
233
- }
234
- });
235
- });
236
- };
237
- IndexedDBAdapter.prototype.clear = function () {
238
- var _a;
239
- return tslib_1.__awaiter(this, void 0, void 0, function () {
240
- return tslib_1.__generator(this, function (_b) {
241
- switch (_b.label) {
242
- case 0: return [4 /*yield*/, this.checkPrivate()];
243
- case 1:
244
- _b.sent();
245
- (_a = this.db) === null || _a === void 0 ? void 0 : _a.close();
246
- return [4 /*yield*/, idb.deleteDB(this.dbName)];
247
- case 2:
248
- _b.sent();
249
- this.db = undefined;
250
- this.initPromise = undefined;
251
- return [2 /*return*/];
252
- }
253
- });
254
- });
255
- };
256
- IndexedDBAdapter.prototype.save = function (model, condition) {
257
- var e_2, _a;
258
- return tslib_1.__awaiter(this, void 0, void 0, function () {
259
- var _b, storeName, set, connectionStoreNames, modelKeyValues, tx, store, fromDB, result, connectionStoreNames_1, connectionStoreNames_1_1, resItem, storeName_1, item, instance, keys, store_1, itemKeyValues, fromDB_1, opType, key, e_2_1;
260
- return tslib_1.__generator(this, function (_c) {
261
- switch (_c.label) {
262
- case 0: return [4 /*yield*/, this.checkPrivate()];
263
- case 1:
264
- _c.sent();
265
- _b = this.saveMetadata(model), storeName = _b.storeName, set = _b.set, connectionStoreNames = _b.connectionStoreNames, modelKeyValues = _b.modelKeyValues;
266
- tx = this.db.transaction(tslib_1.__spread([storeName], Array.from(set.values())), 'readwrite');
267
- store = tx.objectStore(storeName);
268
- return [4 /*yield*/, this._get(store, modelKeyValues)];
269
- case 2:
270
- fromDB = _c.sent();
271
- this.validateSaveCondition(condition, fromDB);
272
- result = [];
273
- _c.label = 3;
274
- case 3:
275
- _c.trys.push([3, 11, 12, 17]);
276
- connectionStoreNames_1 = tslib_1.__asyncValues(connectionStoreNames);
277
- _c.label = 4;
278
- case 4: return [4 /*yield*/, connectionStoreNames_1.next()];
279
- case 5:
280
- if (!(connectionStoreNames_1_1 = _c.sent(), !connectionStoreNames_1_1.done)) return [3 /*break*/, 10];
281
- resItem = connectionStoreNames_1_1.value;
282
- storeName_1 = resItem.storeName, item = resItem.item, instance = resItem.instance, keys = resItem.keys;
283
- store_1 = tx.objectStore(storeName_1);
284
- itemKeyValues = keys.map(function (key) { return item[key]; });
285
- return [4 /*yield*/, this._get(store_1, itemKeyValues)];
286
- case 6:
287
- fromDB_1 = _c.sent();
288
- opType = fromDB_1 ? types_1.OpType.UPDATE : types_1.OpType.INSERT;
289
- if (!(util_1.keysEqual(itemKeyValues, modelKeyValues) ||
290
- opType === types_1.OpType.INSERT)) return [3 /*break*/, 9];
291
- return [4 /*yield*/, store_1
292
- .index('byPk')
293
- .getKey(this.canonicalKeyPath(itemKeyValues))];
294
- case 7:
295
- key = _c.sent();
296
- return [4 /*yield*/, store_1.put(item, key)];
297
- case 8:
298
- _c.sent();
299
- result.push([instance, opType]);
300
- _c.label = 9;
301
- case 9: return [3 /*break*/, 4];
302
- case 10: return [3 /*break*/, 17];
303
- case 11:
304
- e_2_1 = _c.sent();
305
- e_2 = { error: e_2_1 };
306
- return [3 /*break*/, 17];
307
- case 12:
308
- _c.trys.push([12, , 15, 16]);
309
- if (!(connectionStoreNames_1_1 && !connectionStoreNames_1_1.done && (_a = connectionStoreNames_1.return))) return [3 /*break*/, 14];
310
- return [4 /*yield*/, _a.call(connectionStoreNames_1)];
311
- case 13:
312
- _c.sent();
313
- _c.label = 14;
314
- case 14: return [3 /*break*/, 16];
315
- case 15:
316
- if (e_2) throw e_2.error;
317
- return [7 /*endfinally*/];
318
- case 16: return [7 /*endfinally*/];
319
- case 17: return [4 /*yield*/, tx.done];
320
- case 18:
321
- _c.sent();
322
- return [2 /*return*/, result];
323
- }
324
- });
325
- });
326
- };
327
- IndexedDBAdapter.prototype.query = function (modelConstructor, predicate, pagination) {
328
- return tslib_1.__awaiter(this, void 0, void 0, function () {
329
- var _a, storeName, namespaceName, queryByKey, predicates, hasSort, hasPagination, records;
330
- var _this = this;
331
- return tslib_1.__generator(this, function (_b) {
332
- switch (_b.label) {
333
- case 0: return [4 /*yield*/, this.checkPrivate()];
334
- case 1:
335
- _b.sent();
336
- _a = this.queryMetadata(modelConstructor, predicate, pagination), storeName = _a.storeName, namespaceName = _a.namespaceName, queryByKey = _a.queryByKey, predicates = _a.predicates, hasSort = _a.hasSort, hasPagination = _a.hasPagination;
337
- return [4 /*yield*/, (function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
338
- var record, filtered, all;
339
- return tslib_1.__generator(this, function (_a) {
340
- switch (_a.label) {
341
- case 0:
342
- if (!queryByKey) return [3 /*break*/, 2];
343
- return [4 /*yield*/, this.getByKey(storeName, queryByKey)];
344
- case 1:
345
- record = _a.sent();
346
- return [2 /*return*/, record ? [record] : []];
347
- case 2:
348
- if (!predicates) return [3 /*break*/, 4];
349
- return [4 /*yield*/, this.filterOnPredicate(storeName, predicates)];
350
- case 3:
351
- filtered = _a.sent();
352
- return [2 /*return*/, this.inMemoryPagination(filtered, pagination)];
353
- case 4:
354
- if (!hasSort) return [3 /*break*/, 6];
355
- return [4 /*yield*/, this.getAll(storeName)];
356
- case 5:
357
- all = _a.sent();
358
- return [2 /*return*/, this.inMemoryPagination(all, pagination)];
359
- case 6:
360
- if (hasPagination) {
361
- return [2 /*return*/, this.enginePagination(storeName, pagination)];
362
- }
363
- return [2 /*return*/, this.getAll(storeName)];
364
- }
365
- });
366
- }); })()];
367
- case 2:
368
- records = (_b.sent());
369
- return [4 /*yield*/, this.load(namespaceName, modelConstructor.name, records)];
370
- case 3: return [2 /*return*/, _b.sent()];
371
- }
372
- });
373
- });
374
- };
375
- IndexedDBAdapter.prototype.queryOne = function (modelConstructor, firstOrLast) {
376
- if (firstOrLast === void 0) { firstOrLast = types_1.QueryOne.FIRST; }
377
- return tslib_1.__awaiter(this, void 0, void 0, function () {
378
- var storeName, cursor, result;
379
- return tslib_1.__generator(this, function (_a) {
380
- switch (_a.label) {
381
- case 0: return [4 /*yield*/, this.checkPrivate()];
382
- case 1:
383
- _a.sent();
384
- storeName = this.getStorenameForModel(modelConstructor);
385
- return [4 /*yield*/, this.db
386
- .transaction([storeName], 'readonly')
387
- .objectStore(storeName)
388
- .openCursor(undefined, firstOrLast === types_1.QueryOne.FIRST ? 'next' : 'prev')];
389
- case 2:
390
- cursor = _a.sent();
391
- result = cursor ? cursor.value : undefined;
392
- return [2 /*return*/, result && this.modelInstanceCreator(modelConstructor, result)];
95
+ async initDb() {
96
+ return await idb.openDB(this.dbName, DB_VERSION, {
97
+ upgrade: async (db, oldVersion, newVersion, txn) => {
98
+ // create new database
99
+ if (oldVersion === 0) {
100
+ Object.keys(this.schema.namespaces).forEach(namespaceName => {
101
+ const namespace = this.schema.namespaces[namespaceName];
102
+ Object.keys(namespace.models).forEach(modelName => {
103
+ const storeName = (0, util_1.getStorename)(namespaceName, modelName);
104
+ this.createObjectStoreForModel(db, namespaceName, storeName, modelName);
105
+ });
106
+ });
107
+ return;
393
108
  }
394
- });
395
- });
396
- };
397
- IndexedDBAdapter.prototype.batchSave = function (modelConstructor, items) {
398
- return tslib_1.__awaiter(this, void 0, void 0, function () {
399
- var modelName, namespaceName, storeName, result, txn, store, _loop_1, this_1, items_1, items_1_1, item, e_3_1;
400
- var e_3, _a;
401
- var _this = this;
402
- return tslib_1.__generator(this, function (_b) {
403
- switch (_b.label) {
404
- case 0: return [4 /*yield*/, this.checkPrivate()];
405
- case 1:
406
- _b.sent();
407
- if (items.length === 0) {
408
- return [2 /*return*/, []];
109
+ // migrate existing database to latest schema
110
+ if ((oldVersion === 1 || oldVersion === 2) && newVersion === 3) {
111
+ try {
112
+ for (const storeName of txn.objectStoreNames) {
113
+ const origStore = txn.objectStore(storeName);
114
+ // rename original store
115
+ const tmpName = `tmp_${storeName}`;
116
+ origStore.name = tmpName;
117
+ const { namespaceName, modelName } = this.getNamespaceAndModelFromStorename(storeName);
118
+ const modelInCurrentSchema = modelName in this.schema.namespaces[namespaceName].models;
119
+ if (!modelInCurrentSchema) {
120
+ // delete original
121
+ db.deleteObjectStore(tmpName);
122
+ continue;
123
+ }
124
+ const newStore = this.createObjectStoreForModel(db, namespaceName, storeName, modelName);
125
+ let cursor = await origStore.openCursor();
126
+ let count = 0;
127
+ // Copy data from original to new
128
+ while (cursor && cursor.value) {
129
+ // we don't pass key, since they are all new entries in the new store
130
+ await newStore.put(cursor.value);
131
+ cursor = await cursor.continue();
132
+ count++;
133
+ }
134
+ // delete original
135
+ db.deleteObjectStore(tmpName);
136
+ logger.debug(`${count} ${storeName} records migrated`);
409
137
  }
410
- modelName = modelConstructor.name;
411
- namespaceName = this.namespaceResolver(modelConstructor);
412
- storeName = this.getStorenameForModel(modelConstructor);
413
- result = [];
414
- txn = this.db.transaction(storeName, 'readwrite');
415
- store = txn.store;
416
- _loop_1 = function (item) {
417
- var model, connectedModels, keyValues, _deleted, index, key, instance;
418
- return tslib_1.__generator(this, function (_a) {
419
- switch (_a.label) {
420
- case 0:
421
- model = this_1.modelInstanceCreator(modelConstructor, item);
422
- connectedModels = util_1.traverseModel(modelName, model, this_1.schema.namespaces[namespaceName], this_1.modelInstanceCreator, this_1.getModelConstructorByModelName);
423
- keyValues = this_1.getIndexKeyValuesFromModel(model);
424
- _deleted = item._deleted;
425
- index = store.index('byPk');
426
- return [4 /*yield*/, index.getKey(this_1.canonicalKeyPath(keyValues))];
427
- case 1:
428
- key = _a.sent();
429
- if (!!_deleted) return [3 /*break*/, 3];
430
- instance = connectedModels.find(function (_a) {
431
- var instance = _a.instance;
432
- var instanceKeyValues = _this.getIndexKeyValuesFromModel(instance);
433
- return util_1.keysEqual(instanceKeyValues, keyValues);
434
- }).instance;
435
- result.push([
436
- instance,
437
- key ? types_1.OpType.UPDATE : types_1.OpType.INSERT,
438
- ]);
439
- return [4 /*yield*/, store.put(instance, key)];
440
- case 2:
441
- _a.sent();
442
- return [3 /*break*/, 5];
443
- case 3:
444
- result.push([item, types_1.OpType.DELETE]);
445
- if (!key) return [3 /*break*/, 5];
446
- return [4 /*yield*/, store.delete(key)];
447
- case 4:
448
- _a.sent();
449
- _a.label = 5;
450
- case 5: return [2 /*return*/];
451
- }
138
+ // add new models created after IndexedDB, but before migration
139
+ // this case may happen when a user has not opened an app for
140
+ // some time and a new model is added during that time
141
+ Object.keys(this.schema.namespaces).forEach(namespaceName => {
142
+ const namespace = this.schema.namespaces[namespaceName];
143
+ const objectStoreNames = new Set(txn.objectStoreNames);
144
+ Object.keys(namespace.models)
145
+ .map(modelName => {
146
+ return [modelName, (0, util_1.getStorename)(namespaceName, modelName)];
147
+ })
148
+ .filter(([, storeName]) => !objectStoreNames.has(storeName))
149
+ .forEach(([modelName, storeName]) => {
150
+ this.createObjectStoreForModel(db, namespaceName, storeName, modelName);
452
151
  });
453
- };
454
- this_1 = this;
455
- _b.label = 2;
456
- case 2:
457
- _b.trys.push([2, 7, 8, 9]);
458
- items_1 = tslib_1.__values(items), items_1_1 = items_1.next();
459
- _b.label = 3;
460
- case 3:
461
- if (!!items_1_1.done) return [3 /*break*/, 6];
462
- item = items_1_1.value;
463
- return [5 /*yield**/, _loop_1(item)];
464
- case 4:
465
- _b.sent();
466
- _b.label = 5;
467
- case 5:
468
- items_1_1 = items_1.next();
469
- return [3 /*break*/, 3];
470
- case 6: return [3 /*break*/, 9];
471
- case 7:
472
- e_3_1 = _b.sent();
473
- e_3 = { error: e_3_1 };
474
- return [3 /*break*/, 9];
475
- case 8:
476
- try {
477
- if (items_1_1 && !items_1_1.done && (_a = items_1.return)) _a.call(items_1);
478
- }
479
- finally { if (e_3) throw e_3.error; }
480
- return [7 /*endfinally*/];
481
- case 9: return [4 /*yield*/, txn.done];
482
- case 10:
483
- _b.sent();
484
- return [2 /*return*/, result];
152
+ });
153
+ }
154
+ catch (error) {
155
+ logger.error('Error migrating IndexedDB data', error);
156
+ txn.abort();
157
+ throw error;
158
+ }
159
+ return;
485
160
  }
486
- });
161
+ },
487
162
  });
488
- };
489
- IndexedDBAdapter.prototype.deleteItem = function (deleteQueue) {
490
- var e_4, _a, e_5, _b;
491
- return tslib_1.__awaiter(this, void 0, void 0, function () {
492
- var connectionStoreNames, tx, _c, _d, deleteItem, storeName, items, store, items_2, items_2_1, item, key, keyValues, itemKey, e_5_1, e_4_1;
493
- return tslib_1.__generator(this, function (_e) {
494
- switch (_e.label) {
495
- case 0:
496
- connectionStoreNames = deleteQueue.map(function (_a) {
497
- var storeName = _a.storeName;
498
- return storeName;
499
- });
500
- tx = this.db.transaction(tslib_1.__spread(connectionStoreNames), 'readwrite');
501
- _e.label = 1;
502
- case 1:
503
- _e.trys.push([1, 22, 23, 28]);
504
- _c = tslib_1.__asyncValues(deleteQueue);
505
- _e.label = 2;
506
- case 2: return [4 /*yield*/, _c.next()];
507
- case 3:
508
- if (!(_d = _e.sent(), !_d.done)) return [3 /*break*/, 21];
509
- deleteItem = _d.value;
510
- storeName = deleteItem.storeName, items = deleteItem.items;
511
- store = tx.objectStore(storeName);
512
- _e.label = 4;
513
- case 4:
514
- _e.trys.push([4, 14, 15, 20]);
515
- items_2 = tslib_1.__asyncValues(items);
516
- _e.label = 5;
517
- case 5: return [4 /*yield*/, items_2.next()];
518
- case 6:
519
- if (!(items_2_1 = _e.sent(), !items_2_1.done)) return [3 /*break*/, 13];
520
- item = items_2_1.value;
521
- if (!item) return [3 /*break*/, 12];
522
- key = void 0;
523
- if (!(typeof item === 'object')) return [3 /*break*/, 8];
524
- keyValues = this.getIndexKeyValuesFromModel(item);
525
- return [4 /*yield*/, store
526
- .index('byPk')
527
- .getKey(this.canonicalKeyPath(keyValues))];
528
- case 7:
529
- key = _e.sent();
530
- return [3 /*break*/, 10];
531
- case 8:
532
- itemKey = item.toString();
533
- return [4 /*yield*/, store.index('byPk').getKey(itemKey)];
534
- case 9:
535
- key = _e.sent();
536
- _e.label = 10;
537
- case 10:
538
- if (!(key !== undefined)) return [3 /*break*/, 12];
539
- return [4 /*yield*/, store.delete(key)];
540
- case 11:
541
- _e.sent();
542
- _e.label = 12;
543
- case 12: return [3 /*break*/, 5];
544
- case 13: return [3 /*break*/, 20];
545
- case 14:
546
- e_5_1 = _e.sent();
547
- e_5 = { error: e_5_1 };
548
- return [3 /*break*/, 20];
549
- case 15:
550
- _e.trys.push([15, , 18, 19]);
551
- if (!(items_2_1 && !items_2_1.done && (_b = items_2.return))) return [3 /*break*/, 17];
552
- return [4 /*yield*/, _b.call(items_2)];
553
- case 16:
554
- _e.sent();
555
- _e.label = 17;
556
- case 17: return [3 /*break*/, 19];
557
- case 18:
558
- if (e_5) throw e_5.error;
559
- return [7 /*endfinally*/];
560
- case 19: return [7 /*endfinally*/];
561
- case 20: return [3 /*break*/, 2];
562
- case 21: return [3 /*break*/, 28];
563
- case 22:
564
- e_4_1 = _e.sent();
565
- e_4 = { error: e_4_1 };
566
- return [3 /*break*/, 28];
567
- case 23:
568
- _e.trys.push([23, , 26, 27]);
569
- if (!(_d && !_d.done && (_a = _c.return))) return [3 /*break*/, 25];
570
- return [4 /*yield*/, _a.call(_c)];
571
- case 24:
572
- _e.sent();
573
- _e.label = 25;
574
- case 25: return [3 /*break*/, 27];
575
- case 26:
576
- if (e_4) throw e_4.error;
577
- return [7 /*endfinally*/];
578
- case 27: return [7 /*endfinally*/];
579
- case 28: return [2 /*return*/];
163
+ }
164
+ async _get(storeOrStoreName, keyArr) {
165
+ let index;
166
+ if (typeof storeOrStoreName === 'string') {
167
+ const storeName = storeOrStoreName;
168
+ index = this.db.transaction(storeName, 'readonly').store.index('byPk');
169
+ }
170
+ else {
171
+ const store = storeOrStoreName;
172
+ index = store.index('byPk');
173
+ }
174
+ const result = await index.get(this.canonicalKeyPath(keyArr));
175
+ return result;
176
+ }
177
+ async clear() {
178
+ await this.checkPrivate();
179
+ this.db?.close();
180
+ await idb.deleteDB(this.dbName);
181
+ this.db = undefined;
182
+ this.initPromise = undefined;
183
+ }
184
+ async save(model, condition) {
185
+ await this.checkPrivate();
186
+ const { storeName, set, connectionStoreNames, modelKeyValues } = this.saveMetadata(model);
187
+ const tx = this.db.transaction([storeName, ...Array.from(set.values())], 'readwrite');
188
+ const store = tx.objectStore(storeName);
189
+ const fromDB = await this._get(store, modelKeyValues);
190
+ this.validateSaveCondition(condition, fromDB);
191
+ const result = [];
192
+ for await (const resItem of connectionStoreNames) {
193
+ const { storeName, item, instance, keys } = resItem;
194
+ const store = tx.objectStore(storeName);
195
+ const itemKeyValues = keys.map(key => item[key]);
196
+ const fromDB = await this._get(store, itemKeyValues);
197
+ const opType = fromDB ? types_1.OpType.UPDATE : types_1.OpType.INSERT;
198
+ if ((0, util_1.keysEqual)(itemKeyValues, modelKeyValues) ||
199
+ opType === types_1.OpType.INSERT) {
200
+ const key = await store
201
+ .index('byPk')
202
+ .getKey(this.canonicalKeyPath(itemKeyValues));
203
+ await store.put(item, key);
204
+ result.push([instance, opType]);
205
+ }
206
+ }
207
+ await tx.done;
208
+ return result;
209
+ }
210
+ async query(modelConstructor, predicate, pagination) {
211
+ await this.checkPrivate();
212
+ const { storeName, namespaceName, queryByKey, predicates, hasSort, hasPagination, } = this.queryMetadata(modelConstructor, predicate, pagination);
213
+ const records = (await (async () => {
214
+ //
215
+ // NOTE: @svidgen explored removing this and letting query() take care of automatic
216
+ // index leveraging. This would eliminate some amount of very similar code.
217
+ // But, getAll is slightly slower than get()
218
+ //
219
+ // On Chrome:
220
+ // ~700ms vs ~1175ms per 10k reads.
221
+ //
222
+ // You can (and should) check my work here:
223
+ // https://gist.github.com/svidgen/74e55d573b19c3e5432b1b5bdf0f4d96
224
+ //
225
+ if (queryByKey) {
226
+ const record = await this.getByKey(storeName, queryByKey);
227
+ return record ? [record] : [];
228
+ }
229
+ if (predicates) {
230
+ const filtered = await this.filterOnPredicate(storeName, predicates);
231
+ return this.inMemoryPagination(filtered, pagination);
232
+ }
233
+ if (hasSort) {
234
+ const all = await this.getAll(storeName);
235
+ return this.inMemoryPagination(all, pagination);
236
+ }
237
+ if (hasPagination) {
238
+ return this.enginePagination(storeName, pagination);
239
+ }
240
+ return this.getAll(storeName);
241
+ })());
242
+ return await this.load(namespaceName, modelConstructor.name, records);
243
+ }
244
+ async queryOne(modelConstructor, firstOrLast = types_1.QueryOne.FIRST) {
245
+ await this.checkPrivate();
246
+ const storeName = this.getStorenameForModel(modelConstructor);
247
+ const cursor = await this.db
248
+ .transaction([storeName], 'readonly')
249
+ .objectStore(storeName)
250
+ .openCursor(undefined, firstOrLast === types_1.QueryOne.FIRST ? 'next' : 'prev');
251
+ const result = cursor ? cursor.value : undefined;
252
+ return result && this.modelInstanceCreator(modelConstructor, result);
253
+ }
254
+ async batchSave(modelConstructor, items) {
255
+ await this.checkPrivate();
256
+ if (items.length === 0) {
257
+ return [];
258
+ }
259
+ const modelName = modelConstructor.name;
260
+ const namespaceName = this.namespaceResolver(modelConstructor);
261
+ const storeName = this.getStorenameForModel(modelConstructor);
262
+ const result = [];
263
+ const txn = this.db.transaction(storeName, 'readwrite');
264
+ const store = txn.store;
265
+ for (const item of items) {
266
+ const model = this.modelInstanceCreator(modelConstructor, item);
267
+ const connectedModels = (0, util_1.traverseModel)(modelName, model, this.schema.namespaces[namespaceName], this.modelInstanceCreator, this.getModelConstructorByModelName);
268
+ const keyValues = this.getIndexKeyValuesFromModel(model);
269
+ const { _deleted } = item;
270
+ const index = store.index('byPk');
271
+ const key = await index.getKey(this.canonicalKeyPath(keyValues));
272
+ if (!_deleted) {
273
+ const { instance } = connectedModels.find(({ instance }) => {
274
+ const instanceKeyValues = this.getIndexKeyValuesFromModel(instance);
275
+ return (0, util_1.keysEqual)(instanceKeyValues, keyValues);
276
+ });
277
+ result.push([
278
+ instance,
279
+ key ? types_1.OpType.UPDATE : types_1.OpType.INSERT,
280
+ ]);
281
+ await store.put(instance, key);
282
+ }
283
+ else {
284
+ result.push([item, types_1.OpType.DELETE]);
285
+ if (key) {
286
+ await store.delete(key);
580
287
  }
581
- });
288
+ }
289
+ }
290
+ await txn.done;
291
+ return result;
292
+ }
293
+ async deleteItem(deleteQueue) {
294
+ const connectionStoreNames = deleteQueue.map(({ storeName }) => {
295
+ return storeName;
582
296
  });
583
- };
584
- //#region platform-specific helper methods
585
- IndexedDBAdapter.prototype.checkPrivate = function () {
586
- return tslib_1.__awaiter(this, void 0, void 0, function () {
587
- var isPrivate;
588
- return tslib_1.__generator(this, function (_a) {
589
- switch (_a.label) {
590
- case 0: return [4 /*yield*/, util_1.isPrivateMode().then(function (isPrivate) {
591
- return isPrivate;
592
- })];
593
- case 1:
594
- isPrivate = _a.sent();
595
- if (isPrivate) {
596
- logger.error("IndexedDB not supported in this browser's private mode");
597
- return [2 /*return*/, Promise.reject("IndexedDB not supported in this browser's private mode")];
598
- }
599
- else {
600
- return [2 /*return*/, Promise.resolve()];
601
- }
602
- return [2 /*return*/];
297
+ const tx = this.db.transaction([...connectionStoreNames], 'readwrite');
298
+ for await (const deleteItem of deleteQueue) {
299
+ const { storeName, items } = deleteItem;
300
+ const store = tx.objectStore(storeName);
301
+ for await (const item of items) {
302
+ if (item) {
303
+ let key;
304
+ if (typeof item === 'object') {
305
+ const keyValues = this.getIndexKeyValuesFromModel(item);
306
+ key = await store
307
+ .index('byPk')
308
+ .getKey(this.canonicalKeyPath(keyValues));
309
+ }
310
+ else {
311
+ const itemKey = item.toString();
312
+ key = await store.index('byPk').getKey(itemKey);
313
+ }
314
+ if (key !== undefined) {
315
+ await store.delete(key);
316
+ }
603
317
  }
604
- });
318
+ }
319
+ }
320
+ }
321
+ //#region platform-specific helper methods
322
+ async checkPrivate() {
323
+ const isPrivate = await (0, util_1.isPrivateMode)().then(isPrivate => {
324
+ return isPrivate;
605
325
  });
606
- };
326
+ if (isPrivate) {
327
+ logger.error("IndexedDB not supported in this browser's private mode");
328
+ return Promise.reject("IndexedDB not supported in this browser's private mode");
329
+ }
330
+ else {
331
+ return Promise.resolve();
332
+ }
333
+ }
607
334
  /**
608
335
  * Whether the browser's implementation of IndexedDB is coercing single-field
609
336
  * indexes to a scalar key.
@@ -614,62 +341,35 @@ var IndexedDBAdapter = /** @class */ (function (_super) {
614
341
  * See PR description for reference:
615
342
  * https://github.com/aws-amplify/amplify-js/pull/10527
616
343
  */
617
- IndexedDBAdapter.prototype.setSafariCompatabilityMode = function () {
618
- return tslib_1.__awaiter(this, void 0, void 0, function () {
619
- var _a;
620
- return tslib_1.__generator(this, function (_b) {
621
- switch (_b.label) {
622
- case 0:
623
- _a = this;
624
- return [4 /*yield*/, util_1.isSafariCompatabilityMode()];
625
- case 1:
626
- _a.safariCompatabilityMode = _b.sent();
627
- if (this.safariCompatabilityMode === true) {
628
- logger.debug('IndexedDB Adapter is running in Safari Compatability Mode');
629
- }
630
- return [2 /*return*/];
631
- }
632
- });
633
- });
634
- };
635
- IndexedDBAdapter.prototype.getNamespaceAndModelFromStorename = function (storeName) {
636
- var _a = tslib_1.__read(storeName.split('_')), namespaceName = _a[0], modelNameArr = _a.slice(1);
344
+ async setSafariCompatabilityMode() {
345
+ this.safariCompatabilityMode = await (0, util_1.isSafariCompatabilityMode)();
346
+ if (this.safariCompatabilityMode === true) {
347
+ logger.debug('IndexedDB Adapter is running in Safari Compatability Mode');
348
+ }
349
+ }
350
+ getNamespaceAndModelFromStorename(storeName) {
351
+ const [namespaceName, ...modelNameArr] = storeName.split('_');
637
352
  return {
638
- namespaceName: namespaceName,
353
+ namespaceName,
639
354
  modelName: modelNameArr.join('_'),
640
355
  };
641
- };
642
- IndexedDBAdapter.prototype.createObjectStoreForModel = function (db, namespaceName, storeName, modelName) {
643
- var store = db.createObjectStore(storeName, {
356
+ }
357
+ createObjectStoreForModel(db, namespaceName, storeName, modelName) {
358
+ const store = db.createObjectStore(storeName, {
644
359
  autoIncrement: true,
645
360
  });
646
- var indexes = this.schema.namespaces[namespaceName].relationships[modelName].indexes;
647
- indexes.forEach(function (_a) {
648
- var _b = tslib_1.__read(_a, 3), idxName = _b[0], keyPath = _b[1], options = _b[2];
361
+ const { indexes } = this.schema.namespaces[namespaceName].relationships[modelName];
362
+ indexes.forEach(([idxName, keyPath, options]) => {
649
363
  store.createIndex(idxName, keyPath, options);
650
364
  });
651
365
  return store;
652
- };
653
- IndexedDBAdapter.prototype.getByKey = function (storeName, keyValue) {
654
- return tslib_1.__awaiter(this, void 0, void 0, function () {
655
- return tslib_1.__generator(this, function (_a) {
656
- switch (_a.label) {
657
- case 0: return [4 /*yield*/, this._get(storeName, keyValue)];
658
- case 1: return [2 /*return*/, _a.sent()];
659
- }
660
- });
661
- });
662
- };
663
- IndexedDBAdapter.prototype.getAll = function (storeName) {
664
- return tslib_1.__awaiter(this, void 0, void 0, function () {
665
- return tslib_1.__generator(this, function (_a) {
666
- switch (_a.label) {
667
- case 0: return [4 /*yield*/, this.db.getAll(storeName)];
668
- case 1: return [2 /*return*/, _a.sent()];
669
- }
670
- });
671
- });
672
- };
366
+ }
367
+ async getByKey(storeName, keyValue) {
368
+ return await this._get(storeName, keyValue);
369
+ }
370
+ async getAll(storeName) {
371
+ return await this.db.getAll(storeName);
372
+ }
673
373
  /**
674
374
  * Tries to generate an index fetcher for the given predicates. Assumes
675
375
  * that the given predicate conditions are contained by an AND group and
@@ -679,296 +379,191 @@ var IndexedDBAdapter = /** @class */ (function (_super) {
679
379
  * @param predicates The predicates to try to AND together.
680
380
  * @param transaction
681
381
  */
682
- IndexedDBAdapter.prototype.matchingIndexQueries = function (storeName, predicates, transaction) {
683
- var e_6, _a, e_7, _b;
684
- var _this = this;
382
+ matchingIndexQueries(storeName, predicates, transaction) {
685
383
  // could be expanded later to include `exec()` and a `cardinality` estimate?
686
- var queries = [];
687
- var predicateIndex = new Map();
688
- try {
689
- for (var predicates_1 = tslib_1.__values(predicates), predicates_1_1 = predicates_1.next(); !predicates_1_1.done; predicates_1_1 = predicates_1.next()) {
690
- var predicate = predicates_1_1.value;
691
- predicateIndex.set(String(predicate.field), predicate);
692
- }
693
- }
694
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
695
- finally {
696
- try {
697
- if (predicates_1_1 && !predicates_1_1.done && (_a = predicates_1.return)) _a.call(predicates_1);
698
- }
699
- finally { if (e_6) throw e_6.error; }
384
+ const queries = [];
385
+ const predicateIndex = new Map();
386
+ for (const predicate of predicates) {
387
+ predicateIndex.set(String(predicate.field), predicate);
700
388
  }
701
- var store = transaction.objectStore(storeName);
702
- var _loop_2 = function (name_1) {
703
- var e_8, _a;
704
- var idx = store.index(name_1);
705
- var keypath = Array.isArray(idx.keyPath) ? idx.keyPath : [idx.keyPath];
706
- var matchingPredicateValues = [];
707
- try {
708
- for (var keypath_1 = (e_8 = void 0, tslib_1.__values(keypath)), keypath_1_1 = keypath_1.next(); !keypath_1_1.done; keypath_1_1 = keypath_1.next()) {
709
- var field = keypath_1_1.value;
710
- var p = predicateIndex.get(field);
711
- if (p && p.operand !== null && p.operand !== undefined) {
712
- matchingPredicateValues.push(p.operand);
713
- }
714
- else {
715
- break;
716
- }
389
+ const store = transaction.objectStore(storeName);
390
+ for (const name of store.indexNames) {
391
+ const idx = store.index(name);
392
+ const keypath = Array.isArray(idx.keyPath) ? idx.keyPath : [idx.keyPath];
393
+ const matchingPredicateValues = [];
394
+ for (const field of keypath) {
395
+ const p = predicateIndex.get(field);
396
+ if (p && p.operand !== null && p.operand !== undefined) {
397
+ matchingPredicateValues.push(p.operand);
717
398
  }
718
- }
719
- catch (e_8_1) { e_8 = { error: e_8_1 }; }
720
- finally {
721
- try {
722
- if (keypath_1_1 && !keypath_1_1.done && (_a = keypath_1.return)) _a.call(keypath_1);
399
+ else {
400
+ break;
723
401
  }
724
- finally { if (e_8) throw e_8.error; }
725
402
  }
726
403
  // if we have a matching predicate field for each component of this index,
727
404
  // we can build a query for it. otherwise, we can't.
728
405
  if (matchingPredicateValues.length === keypath.length) {
729
406
  // re-create a transaction, because the transaction used to fetch the
730
407
  // indexes may no longer be active.
731
- queries.push(function () {
732
- return _this.db
733
- .transaction(storeName)
734
- .objectStore(storeName)
735
- .index(name_1)
736
- .getAll(_this.canonicalKeyPath(matchingPredicateValues));
737
- });
738
- }
739
- };
740
- try {
741
- for (var _c = tslib_1.__values(store.indexNames), _d = _c.next(); !_d.done; _d = _c.next()) {
742
- var name_1 = _d.value;
743
- _loop_2(name_1);
408
+ queries.push(() => this.db
409
+ .transaction(storeName)
410
+ .objectStore(storeName)
411
+ .index(name)
412
+ .getAll(this.canonicalKeyPath(matchingPredicateValues)));
744
413
  }
745
414
  }
746
- catch (e_7_1) { e_7 = { error: e_7_1 }; }
747
- finally {
748
- try {
749
- if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
415
+ return queries;
416
+ }
417
+ async baseQueryIndex(storeName, predicates, transaction) {
418
+ let { predicates: predicateObjs, type } = predicates;
419
+ // the predicate objects we care about tend to be nested at least
420
+ // one level down: `{and: {or: {and: { <the predicates we want> }}}}`
421
+ // so, we unpack and/or groups until we find a group with more than 1
422
+ // child OR a child that is not a group (and is therefore a predicate "object").
423
+ while (predicateObjs.length === 1 &&
424
+ (0, types_1.isPredicateGroup)(predicateObjs[0]) &&
425
+ predicateObjs[0].type !== 'not') {
426
+ type = predicateObjs[0].type;
427
+ predicateObjs = predicateObjs[0].predicates;
428
+ }
429
+ const fieldPredicates = predicateObjs.filter(p => (0, types_1.isPredicateObj)(p) && p.operator === 'eq');
430
+ // several sub-queries could occur here. explicitly start a txn here to avoid
431
+ // opening/closing multiple txns.
432
+ const txn = transaction || this.db.transaction(storeName);
433
+ let result = {};
434
+ // `or` conditions, if usable, need to generate multiple queries. this is unlike
435
+ // `and` conditions, which should just be combined.
436
+ if (type === 'or') {
437
+ /**
438
+ * Base queries for each child group.
439
+ *
440
+ * For each child group, if it's an AND condition that results in a single
441
+ * subordinate "base query", we can use it. if it's any more complicated
442
+ * than that, it's not a simple join condition we want to use.
443
+ */
444
+ const groupQueries = await Promise.all(predicateObjs
445
+ .filter(o => (0, types_1.isPredicateGroup)(o) && o.type === 'and')
446
+ .map(o => this.baseQueryIndex(storeName, o, txn))).then(queries => queries
447
+ .filter(q => q.indexedQueries.length === 1)
448
+ .map(i => i.indexedQueries));
449
+ /**
450
+ * Base queries for each simple child "object" (field condition).
451
+ */
452
+ const objectQueries = predicateObjs
453
+ .filter(o => (0, types_1.isPredicateObj)(o))
454
+ .map(o => this.matchingIndexQueries(storeName, [o], txn));
455
+ const indexedQueries = [...groupQueries, ...objectQueries]
456
+ .map(q => q[0])
457
+ .filter(i => i);
458
+ // if, after hunting for base queries, we don't have exactly 1 base query
459
+ // for each child group + object, stop trying to optimize. we're not dealing
460
+ // with a simple query that fits the intended optimization path.
461
+ if (predicateObjs.length > indexedQueries.length) {
462
+ result = {
463
+ groupType: null,
464
+ indexedQueries: [],
465
+ };
466
+ }
467
+ else {
468
+ result = {
469
+ groupType: 'or',
470
+ indexedQueries,
471
+ };
750
472
  }
751
- finally { if (e_7) throw e_7.error; }
752
473
  }
753
- return queries;
754
- };
755
- IndexedDBAdapter.prototype.baseQueryIndex = function (storeName, predicates, transaction) {
756
- return tslib_1.__awaiter(this, void 0, void 0, function () {
757
- var predicateObjs, type, fieldPredicates, txn, result, groupQueries, objectQueries, indexedQueries;
758
- var _this = this;
759
- return tslib_1.__generator(this, function (_a) {
760
- switch (_a.label) {
761
- case 0:
762
- predicateObjs = predicates.predicates, type = predicates.type;
763
- // the predicate objects we care about tend to be nested at least
764
- // one level down: `{and: {or: {and: { <the predicates we want> }}}}`
765
- // so, we unpack and/or groups until we find a group with more than 1
766
- // child OR a child that is not a group (and is therefore a predicate "object").
767
- while (predicateObjs.length === 1 &&
768
- types_1.isPredicateGroup(predicateObjs[0]) &&
769
- predicateObjs[0].type !== 'not') {
770
- type = predicateObjs[0].type;
771
- predicateObjs = predicateObjs[0].predicates;
772
- }
773
- fieldPredicates = predicateObjs.filter(function (p) { return types_1.isPredicateObj(p) && p.operator === 'eq'; });
774
- txn = transaction || this.db.transaction(storeName);
775
- result = {};
776
- if (!(type === 'or')) return [3 /*break*/, 2];
777
- return [4 /*yield*/, Promise.all(predicateObjs
778
- .filter(function (o) { return types_1.isPredicateGroup(o) && o.type === 'and'; })
779
- .map(function (o) {
780
- return _this.baseQueryIndex(storeName, o, txn);
781
- })).then(function (queries) {
782
- return queries
783
- .filter(function (q) { return q.indexedQueries.length === 1; })
784
- .map(function (i) { return i.indexedQueries; });
785
- })];
786
- case 1:
787
- groupQueries = _a.sent();
788
- objectQueries = predicateObjs
789
- .filter(function (o) { return types_1.isPredicateObj(o); })
790
- .map(function (o) {
791
- return _this.matchingIndexQueries(storeName, [o], txn);
792
- });
793
- indexedQueries = tslib_1.__spread(groupQueries, objectQueries).map(function (q) { return q[0]; })
794
- .filter(function (i) { return i; });
795
- // if, after hunting for base queries, we don't have exactly 1 base query
796
- // for each child group + object, stop trying to optimize. we're not dealing
797
- // with a simple query that fits the intended optimization path.
798
- if (predicateObjs.length > indexedQueries.length) {
799
- result = {
800
- groupType: null,
801
- indexedQueries: [],
802
- };
803
- }
804
- else {
805
- result = {
806
- groupType: 'or',
807
- indexedQueries: indexedQueries,
808
- };
809
- }
810
- return [3 /*break*/, 3];
811
- case 2:
812
- if (type === 'and') {
813
- // our potential indexes or lacks thereof.
814
- // note that we're only optimizing for `eq` right now.
815
- result = {
816
- groupType: type,
817
- indexedQueries: this.matchingIndexQueries(storeName, fieldPredicates, txn),
818
- };
819
- }
820
- else {
821
- result = {
822
- groupType: null,
823
- indexedQueries: [],
824
- };
825
- }
826
- _a.label = 3;
827
- case 3:
828
- if (!!transaction) return [3 /*break*/, 5];
829
- return [4 /*yield*/, txn.done];
830
- case 4:
831
- _a.sent();
832
- _a.label = 5;
833
- case 5: return [2 /*return*/, result];
834
- }
835
- });
836
- });
837
- };
838
- IndexedDBAdapter.prototype.filterOnPredicate = function (storeName, predicates) {
839
- return tslib_1.__awaiter(this, void 0, void 0, function () {
840
- var predicateObjs, type, _a, groupType, indexedQueries, candidateResults, distinctResults, indexedQueries_1, indexedQueries_1_1, query, resultGroup, resultGroup_1, resultGroup_1_1, item, distinctificationString, e_9_1, filtered;
841
- var e_9, _b, e_10, _c;
842
- return tslib_1.__generator(this, function (_d) {
843
- switch (_d.label) {
844
- case 0:
845
- predicateObjs = predicates.predicates, type = predicates.type;
846
- return [4 /*yield*/, this.baseQueryIndex(storeName, predicates)];
847
- case 1:
848
- _a = _d.sent(), groupType = _a.groupType, indexedQueries = _a.indexedQueries;
849
- if (!(groupType === 'and' && indexedQueries.length > 0)) return [3 /*break*/, 3];
850
- return [4 /*yield*/, indexedQueries[0]()];
851
- case 2:
852
- // each condition must be satsified, we can form a base set with any
853
- // ONE of those conditions and then filter.
854
- candidateResults = _d.sent();
855
- return [3 /*break*/, 14];
856
- case 3:
857
- if (!(groupType === 'or' &&
858
- indexedQueries.length > 0 &&
859
- indexedQueries.length <= MULTI_OR_CONDITION_SCAN_BREAKPOINT)) return [3 /*break*/, 12];
860
- distinctResults = new Map();
861
- _d.label = 4;
862
- case 4:
863
- _d.trys.push([4, 9, 10, 11]);
864
- indexedQueries_1 = tslib_1.__values(indexedQueries), indexedQueries_1_1 = indexedQueries_1.next();
865
- _d.label = 5;
866
- case 5:
867
- if (!!indexedQueries_1_1.done) return [3 /*break*/, 8];
868
- query = indexedQueries_1_1.value;
869
- return [4 /*yield*/, query()];
870
- case 6:
871
- resultGroup = _d.sent();
872
- try {
873
- for (resultGroup_1 = (e_10 = void 0, tslib_1.__values(resultGroup)), resultGroup_1_1 = resultGroup_1.next(); !resultGroup_1_1.done; resultGroup_1_1 = resultGroup_1.next()) {
874
- item = resultGroup_1_1.value;
875
- distinctificationString = JSON.stringify(item);
876
- distinctResults.set(distinctificationString, item);
877
- }
878
- }
879
- catch (e_10_1) { e_10 = { error: e_10_1 }; }
880
- finally {
881
- try {
882
- if (resultGroup_1_1 && !resultGroup_1_1.done && (_c = resultGroup_1.return)) _c.call(resultGroup_1);
883
- }
884
- finally { if (e_10) throw e_10.error; }
885
- }
886
- _d.label = 7;
887
- case 7:
888
- indexedQueries_1_1 = indexedQueries_1.next();
889
- return [3 /*break*/, 5];
890
- case 8: return [3 /*break*/, 11];
891
- case 9:
892
- e_9_1 = _d.sent();
893
- e_9 = { error: e_9_1 };
894
- return [3 /*break*/, 11];
895
- case 10:
896
- try {
897
- if (indexedQueries_1_1 && !indexedQueries_1_1.done && (_b = indexedQueries_1.return)) _b.call(indexedQueries_1);
898
- }
899
- finally { if (e_9) throw e_9.error; }
900
- return [7 /*endfinally*/];
901
- case 11:
902
- // we could conceivably check for special conditions and return early here.
903
- // but, this is simpler and has not yet had a measurable performance impact.
904
- candidateResults = Array.from(distinctResults.values());
905
- return [3 /*break*/, 14];
906
- case 12: return [4 /*yield*/, this.getAll(storeName)];
907
- case 13:
908
- // nothing intelligent we can do with `not` groups unless or until we start
909
- // smashing comparison operators against indexes -- at which point we could
910
- // perform some reversal here.
911
- candidateResults = (_d.sent());
912
- _d.label = 14;
913
- case 14:
914
- filtered = predicateObjs
915
- ? candidateResults.filter(function (m) { return util_1.validatePredicate(m, type, predicateObjs); })
916
- : candidateResults;
917
- return [2 /*return*/, filtered];
474
+ else if (type === 'and') {
475
+ // our potential indexes or lacks thereof.
476
+ // note that we're only optimizing for `eq` right now.
477
+ result = {
478
+ groupType: type,
479
+ indexedQueries: this.matchingIndexQueries(storeName, fieldPredicates, txn),
480
+ };
481
+ }
482
+ else {
483
+ result = {
484
+ groupType: null,
485
+ indexedQueries: [],
486
+ };
487
+ }
488
+ // Explicitly wait for txns from index queries to complete before proceding.
489
+ // This helps ensure IndexedDB is in a stable, ready state. Else, subseqeuent
490
+ // qeuries can sometimes appear to deadlock (at least in FakeIndexedDB).
491
+ // (Unless we were *given* the transaction -- we'll assume the parent handles it.)
492
+ if (!transaction)
493
+ await txn.done;
494
+ return result;
495
+ }
496
+ async filterOnPredicate(storeName, predicates) {
497
+ const { predicates: predicateObjs, type } = predicates;
498
+ const { groupType, indexedQueries } = await this.baseQueryIndex(storeName, predicates);
499
+ // where we'll accumulate candidate results, which will be filtered at the end.
500
+ let candidateResults;
501
+ // semi-naive implementation:
502
+ if (groupType === 'and' && indexedQueries.length > 0) {
503
+ // each condition must be satsified, we can form a base set with any
504
+ // ONE of those conditions and then filter.
505
+ candidateResults = await indexedQueries[0]();
506
+ }
507
+ else if (groupType === 'or' &&
508
+ indexedQueries.length > 0 &&
509
+ indexedQueries.length <= MULTI_OR_CONDITION_SCAN_BREAKPOINT) {
510
+ // NOTE: each condition implies a potentially distinct set. we only benefit
511
+ // from using indexes here if EVERY condition uses an index. if any one
512
+ // index requires a table scan, we gain nothing from the indexes.
513
+ // NOTE: results must be DISTINCT-ified if we leverage indexes.
514
+ const distinctResults = new Map();
515
+ for (const query of indexedQueries) {
516
+ const resultGroup = await query();
517
+ for (const item of resultGroup) {
518
+ const distinctificationString = JSON.stringify(item);
519
+ distinctResults.set(distinctificationString, item);
918
520
  }
919
- });
920
- });
921
- };
922
- IndexedDBAdapter.prototype.inMemoryPagination = function (records, pagination) {
923
- return util_1.inMemoryPagination(records, pagination);
924
- };
925
- IndexedDBAdapter.prototype.enginePagination = function (storeName, pagination) {
926
- return tslib_1.__awaiter(this, void 0, void 0, function () {
927
- var result, _a, page, _b, limit, initialRecord, cursor, pageResults, hasLimit;
928
- return tslib_1.__generator(this, function (_c) {
929
- switch (_c.label) {
930
- case 0:
931
- if (!pagination) return [3 /*break*/, 7];
932
- _a = pagination.page, page = _a === void 0 ? 0 : _a, _b = pagination.limit, limit = _b === void 0 ? 0 : _b;
933
- initialRecord = Math.max(0, page * limit) || 0;
934
- return [4 /*yield*/, this.db
935
- .transaction(storeName)
936
- .objectStore(storeName)
937
- .openCursor()];
938
- case 1:
939
- cursor = _c.sent();
940
- if (!(cursor && initialRecord > 0)) return [3 /*break*/, 3];
941
- return [4 /*yield*/, cursor.advance(initialRecord)];
942
- case 2:
943
- _c.sent();
944
- _c.label = 3;
945
- case 3:
946
- pageResults = [];
947
- hasLimit = typeof limit === 'number' && limit > 0;
948
- _c.label = 4;
949
- case 4:
950
- if (!(cursor && cursor.value)) return [3 /*break*/, 6];
951
- pageResults.push(cursor.value);
952
- if (hasLimit && pageResults.length === limit) {
953
- return [3 /*break*/, 6];
954
- }
955
- return [4 /*yield*/, cursor.continue()];
956
- case 5:
957
- cursor = _c.sent();
958
- return [3 /*break*/, 4];
959
- case 6:
960
- result = pageResults;
961
- return [3 /*break*/, 9];
962
- case 7: return [4 /*yield*/, this.db.getAll(storeName)];
963
- case 8:
964
- result = (_c.sent());
965
- _c.label = 9;
966
- case 9: return [2 /*return*/, result];
521
+ }
522
+ // we could conceivably check for special conditions and return early here.
523
+ // but, this is simpler and has not yet had a measurable performance impact.
524
+ candidateResults = Array.from(distinctResults.values());
525
+ }
526
+ else {
527
+ // nothing intelligent we can do with `not` groups unless or until we start
528
+ // smashing comparison operators against indexes -- at which point we could
529
+ // perform some reversal here.
530
+ candidateResults = await this.getAll(storeName);
531
+ }
532
+ const filtered = predicateObjs
533
+ ? candidateResults.filter(m => (0, util_1.validatePredicate)(m, type, predicateObjs))
534
+ : candidateResults;
535
+ return filtered;
536
+ }
537
+ inMemoryPagination(records, pagination) {
538
+ return (0, util_1.inMemoryPagination)(records, pagination);
539
+ }
540
+ async enginePagination(storeName, pagination) {
541
+ let result;
542
+ if (pagination) {
543
+ const { page = 0, limit = 0 } = pagination;
544
+ const initialRecord = Math.max(0, page * limit) || 0;
545
+ let cursor = await this.db
546
+ .transaction(storeName)
547
+ .objectStore(storeName)
548
+ .openCursor();
549
+ if (cursor && initialRecord > 0) {
550
+ await cursor.advance(initialRecord);
551
+ }
552
+ const pageResults = [];
553
+ const hasLimit = typeof limit === 'number' && limit > 0;
554
+ while (cursor && cursor.value) {
555
+ pageResults.push(cursor.value);
556
+ if (hasLimit && pageResults.length === limit) {
557
+ break;
967
558
  }
968
- });
969
- });
970
- };
971
- return IndexedDBAdapter;
972
- }(StorageAdapterBase_1.StorageAdapterBase));
559
+ cursor = await cursor.continue();
560
+ }
561
+ result = pageResults;
562
+ }
563
+ else {
564
+ result = await this.db.getAll(storeName);
565
+ }
566
+ return result;
567
+ }
568
+ }
973
569
  exports.default = new IndexedDBAdapter();
974
- //# sourceMappingURL=IndexedDBAdapter.js.map