@aws-amplify/datastore 3.12.6-next.20 → 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 (144) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/lib/authModeStrategies/multiAuthStrategy.js +13 -2
  3. package/lib/authModeStrategies/multiAuthStrategy.js.map +1 -1
  4. package/lib/datastore/datastore.js +648 -344
  5. package/lib/datastore/datastore.js.map +1 -1
  6. package/lib/predicates/index.js +12 -2
  7. package/lib/predicates/index.js.map +1 -1
  8. package/lib/storage/adapter/AsyncStorageAdapter.js +354 -203
  9. package/lib/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  10. package/lib/storage/adapter/AsyncStorageDatabase.js +65 -28
  11. package/lib/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  12. package/lib/storage/adapter/IndexedDBAdapter.js +444 -271
  13. package/lib/storage/adapter/IndexedDBAdapter.js.map +1 -1
  14. package/lib/storage/storage.js +93 -28
  15. package/lib/storage/storage.js.map +1 -1
  16. package/lib/sync/datastoreConnectivity.js +9 -0
  17. package/lib/sync/datastoreConnectivity.js.map +1 -1
  18. package/lib/sync/index.js +522 -397
  19. package/lib/sync/index.js.map +1 -1
  20. package/lib/sync/merger.js +13 -6
  21. package/lib/sync/merger.js.map +1 -1
  22. package/lib/sync/outbox.js +77 -71
  23. package/lib/sync/outbox.js.map +1 -1
  24. package/lib/sync/processors/mutation.js +269 -209
  25. package/lib/sync/processors/mutation.js.map +1 -1
  26. package/lib/sync/processors/subscription.js +213 -178
  27. package/lib/sync/processors/subscription.js.map +1 -1
  28. package/lib/sync/processors/sync.js +126 -121
  29. package/lib/sync/processors/sync.js.map +1 -1
  30. package/lib/sync/utils.js +43 -8
  31. package/lib/sync/utils.js.map +1 -1
  32. package/lib/types.js +10 -1
  33. package/lib/types.js.map +1 -1
  34. package/lib/util.js +419 -166
  35. package/lib/util.js.map +1 -1
  36. package/lib-esm/authModeStrategies/multiAuthStrategy.d.ts +11 -0
  37. package/lib-esm/authModeStrategies/multiAuthStrategy.js +12 -1
  38. package/lib-esm/authModeStrategies/multiAuthStrategy.js.map +1 -1
  39. package/lib-esm/datastore/datastore.d.ts +107 -17
  40. package/lib-esm/datastore/datastore.js +648 -344
  41. package/lib-esm/datastore/datastore.js.map +1 -1
  42. package/lib-esm/index.d.ts +3 -19
  43. package/lib-esm/predicates/index.d.ts +3 -2
  44. package/lib-esm/predicates/index.js +13 -3
  45. package/lib-esm/predicates/index.js.map +1 -1
  46. package/lib-esm/storage/adapter/AsyncStorageAdapter.d.ts +4 -3
  47. package/lib-esm/storage/adapter/AsyncStorageAdapter.js +355 -204
  48. package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  49. package/lib-esm/storage/adapter/AsyncStorageDatabase.d.ts +14 -4
  50. package/lib-esm/storage/adapter/AsyncStorageDatabase.js +66 -29
  51. package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  52. package/lib-esm/storage/adapter/IndexedDBAdapter.d.ts +26 -4
  53. package/lib-esm/storage/adapter/IndexedDBAdapter.js +445 -272
  54. package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +1 -1
  55. package/lib-esm/storage/adapter/index.d.ts +1 -1
  56. package/lib-esm/storage/storage.d.ts +1 -1
  57. package/lib-esm/storage/storage.js +93 -28
  58. package/lib-esm/storage/storage.js.map +1 -1
  59. package/lib-esm/sync/datastoreConnectivity.d.ts +1 -0
  60. package/lib-esm/sync/datastoreConnectivity.js +10 -1
  61. package/lib-esm/sync/datastoreConnectivity.js.map +1 -1
  62. package/lib-esm/sync/index.d.ts +31 -5
  63. package/lib-esm/sync/index.js +524 -399
  64. package/lib-esm/sync/index.js.map +1 -1
  65. package/lib-esm/sync/merger.d.ts +9 -3
  66. package/lib-esm/sync/merger.js +13 -6
  67. package/lib-esm/sync/merger.js.map +1 -1
  68. package/lib-esm/sync/outbox.d.ts +2 -2
  69. package/lib-esm/sync/outbox.js +78 -72
  70. package/lib-esm/sync/outbox.js.map +1 -1
  71. package/lib-esm/sync/processors/mutation.d.ts +2 -0
  72. package/lib-esm/sync/processors/mutation.js +270 -210
  73. package/lib-esm/sync/processors/mutation.js.map +1 -1
  74. package/lib-esm/sync/processors/subscription.d.ts +2 -0
  75. package/lib-esm/sync/processors/subscription.js +213 -178
  76. package/lib-esm/sync/processors/subscription.js.map +1 -1
  77. package/lib-esm/sync/processors/sync.d.ts +2 -1
  78. package/lib-esm/sync/processors/sync.js +126 -121
  79. package/lib-esm/sync/processors/sync.js.map +1 -1
  80. package/lib-esm/sync/utils.d.ts +3 -2
  81. package/lib-esm/sync/utils.js +45 -11
  82. package/lib-esm/sync/utils.js.map +1 -1
  83. package/lib-esm/types.d.ts +65 -26
  84. package/lib-esm/types.js +9 -2
  85. package/lib-esm/types.js.map +1 -1
  86. package/lib-esm/util.d.ts +67 -24
  87. package/lib-esm/util.js +419 -166
  88. package/lib-esm/util.js.map +1 -1
  89. package/package.json +13 -7
  90. package/src/authModeStrategies/multiAuthStrategy.ts +12 -1
  91. package/src/datastore/datastore.ts +798 -397
  92. package/src/predicates/index.ts +32 -10
  93. package/src/storage/adapter/AsyncStorageAdapter.ts +309 -93
  94. package/src/storage/adapter/AsyncStorageDatabase.ts +74 -26
  95. package/src/storage/adapter/IndexedDBAdapter.ts +358 -134
  96. package/src/storage/adapter/index.ts +1 -1
  97. package/src/storage/storage.ts +69 -22
  98. package/src/sync/datastoreConnectivity.ts +6 -0
  99. package/src/sync/index.ts +521 -412
  100. package/src/sync/merger.ts +20 -4
  101. package/src/sync/outbox.ts +22 -9
  102. package/src/sync/processors/mutation.ts +188 -150
  103. package/src/sync/processors/subscription.ts +289 -253
  104. package/src/sync/processors/sync.ts +151 -138
  105. package/src/sync/utils.ts +67 -12
  106. package/src/types.ts +182 -30
  107. package/src/util.ts +505 -176
  108. package/build.js +0 -5
  109. package/dist/aws-amplify-datastore.js +0 -83311
  110. package/dist/aws-amplify-datastore.js.map +0 -1
  111. package/dist/aws-amplify-datastore.min.js +0 -168
  112. package/dist/aws-amplify-datastore.min.js.map +0 -1
  113. package/index.js +0 -7
  114. package/lib/authModeStrategies/defaultAuthStrategy.d.ts +0 -2
  115. package/lib/authModeStrategies/index.d.ts +0 -2
  116. package/lib/authModeStrategies/multiAuthStrategy.d.ts +0 -2
  117. package/lib/datastore/datastore.d.ts +0 -66
  118. package/lib/index.d.ts +0 -31
  119. package/lib/predicates/index.d.ts +0 -15
  120. package/lib/predicates/sort.d.ts +0 -8
  121. package/lib/ssr/index.d.ts +0 -3
  122. package/lib/storage/adapter/AsyncStorageAdapter.d.ts +0 -40
  123. package/lib/storage/adapter/AsyncStorageDatabase.d.ts +0 -29
  124. package/lib/storage/adapter/InMemoryStore.d.ts +0 -11
  125. package/lib/storage/adapter/InMemoryStore.native.d.ts +0 -1
  126. package/lib/storage/adapter/IndexedDBAdapter.d.ts +0 -37
  127. package/lib/storage/adapter/getDefaultAdapter/index.d.ts +0 -3
  128. package/lib/storage/adapter/getDefaultAdapter/index.native.d.ts +0 -3
  129. package/lib/storage/adapter/index.d.ts +0 -9
  130. package/lib/storage/storage.d.ts +0 -49
  131. package/lib/sync/datastoreConnectivity.d.ts +0 -15
  132. package/lib/sync/datastoreReachability/index.d.ts +0 -3
  133. package/lib/sync/datastoreReachability/index.native.d.ts +0 -3
  134. package/lib/sync/index.d.ts +0 -63
  135. package/lib/sync/merger.d.ts +0 -11
  136. package/lib/sync/outbox.d.ts +0 -27
  137. package/lib/sync/processors/errorMaps.d.ts +0 -17
  138. package/lib/sync/processors/mutation.d.ts +0 -56
  139. package/lib/sync/processors/subscription.d.ts +0 -31
  140. package/lib/sync/processors/sync.d.ts +0 -27
  141. package/lib/sync/utils.d.ts +0 -41
  142. package/lib/types.d.ts +0 -462
  143. package/lib/util.d.ts +0 -113
  144. package/webpack.config.dev.js +0 -6
@@ -3,13 +3,42 @@ import { ConsoleLogger as Logger } from '@aws-amplify/core';
3
3
  import * as idb from 'idb';
4
4
  import { ModelPredicateCreator, ModelSortPredicateCreator, } from '../../predicates';
5
5
  import { isPredicateObj, OpType, QueryOne, } from '../../types';
6
- import { exhaustiveCheck, getIndex, getIndexFromAssociation, isModelConstructor, isPrivateMode, traverseModel, validatePredicate, sortCompareFunction, } from '../../util';
6
+ import { exhaustiveCheck, getIndex, getIndexFromAssociation, isModelConstructor, isPrivateMode, traverseModel, validatePredicate, sortCompareFunction, keysEqual, getStorename, getIndexKeys, extractPrimaryKeyValues, isSafariCompatabilityMode, } from '../../util';
7
7
  var logger = new Logger('DataStore');
8
8
  var DB_NAME = 'amplify-datastore';
9
9
  var IndexedDBAdapter = /** @class */ (function () {
10
10
  function IndexedDBAdapter() {
11
+ var _this = this;
11
12
  this.dbName = DB_NAME;
13
+ this.safariCompatabilityMode = false;
14
+ /**
15
+ * Checks the given path against the browser's IndexedDB implementation for
16
+ * necessary compatibility transformations, applying those transforms if needed.
17
+ *
18
+ * @param `keyArr` strings to compatibilize for browser-indexeddb index operations
19
+ * @returns An array or string, depending on and given key,
20
+ * that is ensured to be compatible with the IndexedDB implementation's nuances.
21
+ */
22
+ this.canonicalKeyPath = function (keyArr) {
23
+ if (_this.safariCompatabilityMode) {
24
+ return keyArr.length > 1 ? keyArr : keyArr[0];
25
+ }
26
+ return keyArr;
27
+ };
12
28
  }
29
+ IndexedDBAdapter.prototype.getStorenameForModel = function (modelConstructor) {
30
+ var namespace = this.namespaceResolver(modelConstructor);
31
+ var modelName = modelConstructor.name;
32
+ return getStorename(namespace, modelName);
33
+ };
34
+ // Retrieves primary key values from a model
35
+ IndexedDBAdapter.prototype.getIndexKeyValuesFromModel = function (model) {
36
+ var modelConstructor = Object.getPrototypeOf(model)
37
+ .constructor;
38
+ var namespaceName = this.namespaceResolver(modelConstructor);
39
+ var keys = getIndexKeys(this.schema.namespaces[namespaceName], modelConstructor.name);
40
+ return extractPrimaryKeyValues(model, keys);
41
+ };
13
42
  IndexedDBAdapter.prototype.checkPrivate = function () {
14
43
  return __awaiter(this, void 0, void 0, function () {
15
44
  var isPrivate;
@@ -32,14 +61,40 @@ var IndexedDBAdapter = /** @class */ (function () {
32
61
  });
33
62
  });
34
63
  };
35
- IndexedDBAdapter.prototype.getStorenameForModel = function (modelConstructor) {
36
- var namespace = this.namespaceResolver(modelConstructor);
37
- var modelName = modelConstructor.name;
38
- return this.getStorename(namespace, modelName);
64
+ /**
65
+ * Whether the browser's implementation of IndexedDB is coercing single-field
66
+ * indexes to a scalar key.
67
+ *
68
+ * If this returns `true`, we need to treat indexes containing a single field
69
+ * as scalars.
70
+ *
71
+ * See PR description for reference:
72
+ * https://github.com/aws-amplify/amplify-js/pull/10527
73
+ */
74
+ IndexedDBAdapter.prototype.setSafariCompatabilityMode = function () {
75
+ return __awaiter(this, void 0, void 0, function () {
76
+ var _a;
77
+ return __generator(this, function (_b) {
78
+ switch (_b.label) {
79
+ case 0:
80
+ _a = this;
81
+ return [4 /*yield*/, isSafariCompatabilityMode()];
82
+ case 1:
83
+ _a.safariCompatabilityMode = _b.sent();
84
+ if (this.safariCompatabilityMode === true) {
85
+ logger.debug('IndexedDB Adapter is running in Safari Compatability Mode');
86
+ }
87
+ return [2 /*return*/];
88
+ }
89
+ });
90
+ });
39
91
  };
40
- IndexedDBAdapter.prototype.getStorename = function (namespace, modelName) {
41
- var storeName = namespace + "_" + modelName;
42
- return storeName;
92
+ IndexedDBAdapter.prototype.getNamespaceAndModelFromStorename = function (storeName) {
93
+ var _a = __read(storeName.split('_')), namespaceName = _a[0], modelNameArr = _a.slice(1);
94
+ return {
95
+ namespaceName: namespaceName,
96
+ modelName: modelNameArr.join('_'),
97
+ };
43
98
  };
44
99
  IndexedDBAdapter.prototype.setUp = function (theSchema, namespaceResolver, modelInstanceCreator, getModelConstructorByModelName, sessionId) {
45
100
  return __awaiter(this, void 0, void 0, function () {
@@ -50,17 +105,20 @@ var IndexedDBAdapter = /** @class */ (function () {
50
105
  case 0: return [4 /*yield*/, this.checkPrivate()];
51
106
  case 1:
52
107
  _b.sent();
53
- if (!!this.initPromise) return [3 /*break*/, 2];
108
+ return [4 /*yield*/, this.setSafariCompatabilityMode()];
109
+ case 2:
110
+ _b.sent();
111
+ if (!!this.initPromise) return [3 /*break*/, 3];
54
112
  this.initPromise = new Promise(function (res, rej) {
55
113
  _this.resolve = res;
56
114
  _this.reject = rej;
57
115
  });
58
- return [3 /*break*/, 4];
59
- case 2: return [4 /*yield*/, this.initPromise];
60
- case 3:
61
- _b.sent();
62
- _b.label = 4;
116
+ return [3 /*break*/, 5];
117
+ case 3: return [4 /*yield*/, this.initPromise];
63
118
  case 4:
119
+ _b.sent();
120
+ _b.label = 5;
121
+ case 5:
64
122
  if (sessionId) {
65
123
  this.dbName = DB_NAME + "-" + sessionId;
66
124
  }
@@ -68,83 +126,80 @@ var IndexedDBAdapter = /** @class */ (function () {
68
126
  this.namespaceResolver = namespaceResolver;
69
127
  this.modelInstanceCreator = modelInstanceCreator;
70
128
  this.getModelConstructorByModelName = getModelConstructorByModelName;
71
- _b.label = 5;
72
- case 5:
73
- _b.trys.push([5, 8, , 9]);
74
- if (!!this.db) return [3 /*break*/, 7];
75
- VERSION = 2;
129
+ _b.label = 6;
130
+ case 6:
131
+ _b.trys.push([6, 9, , 10]);
132
+ if (!!this.db) return [3 /*break*/, 8];
133
+ VERSION = 3;
76
134
  _a = this;
77
135
  return [4 /*yield*/, idb.openDB(this.dbName, VERSION, {
78
136
  upgrade: function (db, oldVersion, newVersion, txn) { return __awaiter(_this, void 0, void 0, function () {
79
- var _a, _b, storeName, origStore, tmpName, newStore, cursor, count, e_1_1, error_2;
80
- var e_1, _c;
137
+ var _a, _b, storeName, origStore, tmpName, _c, namespaceName, modelName, newStore, cursor, count, e_1_1, error_2;
138
+ var e_1, _d;
81
139
  var _this = this;
82
- return __generator(this, function (_d) {
83
- switch (_d.label) {
140
+ return __generator(this, function (_e) {
141
+ switch (_e.label) {
84
142
  case 0:
85
143
  if (oldVersion === 0) {
86
144
  Object.keys(theSchema.namespaces).forEach(function (namespaceName) {
87
145
  var namespace = theSchema.namespaces[namespaceName];
88
146
  Object.keys(namespace.models).forEach(function (modelName) {
89
- var storeName = _this.getStorename(namespaceName, modelName);
147
+ var storeName = getStorename(namespaceName, modelName);
90
148
  _this.createObjectStoreForModel(db, namespaceName, storeName, modelName);
91
149
  });
92
150
  });
93
151
  return [2 /*return*/];
94
152
  }
95
- if (!(oldVersion === 1 && newVersion === 2)) return [3 /*break*/, 16];
96
- _d.label = 1;
153
+ if (!((oldVersion === 1 || oldVersion === 2) && newVersion === 3)) return [3 /*break*/, 16];
154
+ _e.label = 1;
97
155
  case 1:
98
- _d.trys.push([1, 14, , 15]);
99
- _d.label = 2;
156
+ _e.trys.push([1, 14, , 15]);
157
+ _e.label = 2;
100
158
  case 2:
101
- _d.trys.push([2, 11, 12, 13]);
159
+ _e.trys.push([2, 11, 12, 13]);
102
160
  _a = __values(txn.objectStoreNames), _b = _a.next();
103
- _d.label = 3;
161
+ _e.label = 3;
104
162
  case 3:
105
163
  if (!!_b.done) return [3 /*break*/, 10];
106
164
  storeName = _b.value;
107
165
  origStore = txn.objectStore(storeName);
108
166
  tmpName = "tmp_" + storeName;
109
167
  origStore.name = tmpName;
110
- newStore = db.createObjectStore(storeName, {
111
- keyPath: undefined,
112
- autoIncrement: true,
113
- });
114
- newStore.createIndex('byId', 'id', { unique: true });
168
+ _c = this.getNamespaceAndModelFromStorename(storeName), namespaceName = _c.namespaceName, modelName = _c.modelName;
169
+ newStore = this.createObjectStoreForModel(db, namespaceName, storeName, modelName);
115
170
  return [4 /*yield*/, origStore.openCursor()];
116
171
  case 4:
117
- cursor = _d.sent();
172
+ cursor = _e.sent();
118
173
  count = 0;
119
- _d.label = 5;
174
+ _e.label = 5;
120
175
  case 5:
121
176
  if (!(cursor && cursor.value)) return [3 /*break*/, 8];
122
177
  // we don't pass key, since they are all new entries in the new store
123
178
  return [4 /*yield*/, newStore.put(cursor.value)];
124
179
  case 6:
125
180
  // we don't pass key, since they are all new entries in the new store
126
- _d.sent();
181
+ _e.sent();
127
182
  return [4 /*yield*/, cursor.continue()];
128
183
  case 7:
129
- cursor = _d.sent();
184
+ cursor = _e.sent();
130
185
  count++;
131
186
  return [3 /*break*/, 5];
132
187
  case 8:
133
188
  // delete original
134
189
  db.deleteObjectStore(tmpName);
135
190
  logger.debug(count + " " + storeName + " records migrated");
136
- _d.label = 9;
191
+ _e.label = 9;
137
192
  case 9:
138
193
  _b = _a.next();
139
194
  return [3 /*break*/, 3];
140
195
  case 10: return [3 /*break*/, 13];
141
196
  case 11:
142
- e_1_1 = _d.sent();
197
+ e_1_1 = _e.sent();
143
198
  e_1 = { error: e_1_1 };
144
199
  return [3 /*break*/, 13];
145
200
  case 12:
146
201
  try {
147
- if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
202
+ if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
148
203
  }
149
204
  finally { if (e_1) throw e_1.error; }
150
205
  return [7 /*endfinally*/];
@@ -159,7 +214,7 @@ var IndexedDBAdapter = /** @class */ (function () {
159
214
  .map(function (modelName) {
160
215
  return [
161
216
  modelName,
162
- _this.getStorename(namespaceName, modelName),
217
+ getStorename(namespaceName, modelName),
163
218
  ];
164
219
  })
165
220
  .filter(function (_a) {
@@ -173,7 +228,7 @@ var IndexedDBAdapter = /** @class */ (function () {
173
228
  });
174
229
  return [3 /*break*/, 15];
175
230
  case 14:
176
- error_2 = _d.sent();
231
+ error_2 = _e.sent();
177
232
  logger.error('Error migrating IndexedDB data', error_2);
178
233
  txn.abort();
179
234
  throw error_2;
@@ -183,21 +238,21 @@ var IndexedDBAdapter = /** @class */ (function () {
183
238
  });
184
239
  }); },
185
240
  })];
186
- case 6:
241
+ case 7:
187
242
  _a.db = _b.sent();
188
243
  this.resolve();
189
- _b.label = 7;
190
- case 7: return [3 /*break*/, 9];
191
- case 8:
244
+ _b.label = 8;
245
+ case 8: return [3 /*break*/, 10];
246
+ case 9:
192
247
  error_1 = _b.sent();
193
248
  this.reject(error_1);
194
- return [3 /*break*/, 9];
195
- case 9: return [2 /*return*/];
249
+ return [3 /*break*/, 10];
250
+ case 10: return [2 /*return*/];
196
251
  }
197
252
  });
198
253
  });
199
254
  };
200
- IndexedDBAdapter.prototype._get = function (storeOrStoreName, id) {
255
+ IndexedDBAdapter.prototype._get = function (storeOrStoreName, keyArr) {
201
256
  return __awaiter(this, void 0, void 0, function () {
202
257
  var index, storeName, store, result;
203
258
  return __generator(this, function (_a) {
@@ -205,13 +260,13 @@ var IndexedDBAdapter = /** @class */ (function () {
205
260
  case 0:
206
261
  if (typeof storeOrStoreName === 'string') {
207
262
  storeName = storeOrStoreName;
208
- index = this.db.transaction(storeName, 'readonly').store.index('byId');
263
+ index = this.db.transaction(storeName, 'readonly').store.index('byPk');
209
264
  }
210
265
  else {
211
266
  store = storeOrStoreName;
212
- index = store.index('byId');
267
+ index = store.index('byPk');
213
268
  }
214
- return [4 /*yield*/, index.get(id)];
269
+ return [4 /*yield*/, index.get(this.canonicalKeyPath(keyArr))];
215
270
  case 1:
216
271
  result = _a.sent();
217
272
  return [2 /*return*/, result];
@@ -222,7 +277,7 @@ var IndexedDBAdapter = /** @class */ (function () {
222
277
  IndexedDBAdapter.prototype.save = function (model, condition) {
223
278
  var e_2, _a;
224
279
  return __awaiter(this, void 0, void 0, function () {
225
- var modelConstructor, storeName, connectedModels, namespaceName, set, connectionStoreNames, tx, store, fromDB, predicates, predicateObjs, type, isValid, msg, result, connectionStoreNames_1, connectionStoreNames_1_1, resItem, storeName_1, item, instance, store_1, id, fromDB_1, opType, key, e_2_1;
280
+ var modelConstructor, storeName, namespaceName, connectedModels, set, connectionStoreNames, tx, store, keyValues, fromDB, predicates, predicateObjs, type, isValid, msg, result, connectionStoreNames_1, connectionStoreNames_1_1, resItem, storeName_1, item, instance, keys, store_1, itemKeyValues, fromDB_1, opType, modelKeyValues, key, e_2_1;
226
281
  var _this = this;
227
282
  return __generator(this, function (_b) {
228
283
  switch (_b.label) {
@@ -232,18 +287,20 @@ var IndexedDBAdapter = /** @class */ (function () {
232
287
  modelConstructor = Object.getPrototypeOf(model)
233
288
  .constructor;
234
289
  storeName = this.getStorenameForModel(modelConstructor);
235
- connectedModels = traverseModel(modelConstructor.name, model, this.schema.namespaces[this.namespaceResolver(modelConstructor)], this.modelInstanceCreator, this.getModelConstructorByModelName);
236
290
  namespaceName = this.namespaceResolver(modelConstructor);
291
+ connectedModels = traverseModel(modelConstructor.name, model, this.schema.namespaces[namespaceName], this.modelInstanceCreator, this.getModelConstructorByModelName);
237
292
  set = new Set();
238
293
  connectionStoreNames = Object.values(connectedModels).map(function (_a) {
239
294
  var modelName = _a.modelName, item = _a.item, instance = _a.instance;
240
- var storeName = _this.getStorename(namespaceName, modelName);
295
+ var storeName = getStorename(namespaceName, modelName);
241
296
  set.add(storeName);
242
- return { storeName: storeName, item: item, instance: instance };
297
+ var keys = getIndexKeys(_this.schema.namespaces[namespaceName], modelName);
298
+ return { storeName: storeName, item: item, instance: instance, keys: keys };
243
299
  });
244
300
  tx = this.db.transaction(__spread([storeName], Array.from(set.values())), 'readwrite');
245
301
  store = tx.objectStore(storeName);
246
- return [4 /*yield*/, this._get(store, model.id)];
302
+ keyValues = this.getIndexKeyValuesFromModel(model);
303
+ return [4 /*yield*/, this._get(store, keyValues)];
247
304
  case 2:
248
305
  fromDB = _b.sent();
249
306
  if (condition && fromDB) {
@@ -266,15 +323,22 @@ var IndexedDBAdapter = /** @class */ (function () {
266
323
  case 5:
267
324
  if (!(connectionStoreNames_1_1 = _b.sent(), !connectionStoreNames_1_1.done)) return [3 /*break*/, 10];
268
325
  resItem = connectionStoreNames_1_1.value;
269
- storeName_1 = resItem.storeName, item = resItem.item, instance = resItem.instance;
326
+ storeName_1 = resItem.storeName, item = resItem.item, instance = resItem.instance, keys = resItem.keys;
270
327
  store_1 = tx.objectStore(storeName_1);
271
- id = item.id;
272
- return [4 /*yield*/, this._get(store_1, id)];
328
+ itemKeyValues = keys.map(function (key) {
329
+ var value = item[key];
330
+ return value;
331
+ });
332
+ return [4 /*yield*/, this._get(store_1, itemKeyValues)];
273
333
  case 6:
274
334
  fromDB_1 = _b.sent();
275
335
  opType = fromDB_1 === undefined ? OpType.INSERT : OpType.UPDATE;
276
- if (!(id === model.id || opType === OpType.INSERT)) return [3 /*break*/, 9];
277
- return [4 /*yield*/, store_1.index('byId').getKey(item.id)];
336
+ modelKeyValues = this.getIndexKeyValuesFromModel(model);
337
+ if (!(keysEqual(itemKeyValues, modelKeyValues) ||
338
+ opType === OpType.INSERT)) return [3 /*break*/, 9];
339
+ return [4 /*yield*/, store_1
340
+ .index('byPk')
341
+ .getKey(this.canonicalKeyPath(itemKeyValues))];
278
342
  case 7:
279
343
  key = _b.sent();
280
344
  return [4 /*yield*/, store_1.put(item, key)];
@@ -312,7 +376,7 @@ var IndexedDBAdapter = /** @class */ (function () {
312
376
  var records_1, records_1_1, records_2, records_2_1;
313
377
  var e_3, _a, e_4, _b, e_5, _c;
314
378
  return __awaiter(this, void 0, void 0, function () {
315
- var namespace, relations, connectionStoreNames, modelConstructor, tx, relations_1, relations_1_1, relation, fieldName, modelName, targetName, storeName, store, modelConstructor_1, _d, recordItem, getByfield, connectionRecord, e_4_1, recordItem, connectionRecord, e_5_1, e_3_1;
379
+ var namespace, relations, connectionStoreNames, modelConstructor, tx, relations_1, relations_1_1, relation, fieldName, modelName, targetName, targetNames, storeName, store, modelConstructor_1, _d, recordItem, getByFields, allPresent, keys, connectionRecord, getByfield, key, connectionRecord, e_4_1, recordItem, allPresent, keys, connectionRecord, key, connectionRecord, e_5_1, e_3_1;
316
380
  var _this = this;
317
381
  return __generator(this, function (_e) {
318
382
  switch (_e.label) {
@@ -321,7 +385,7 @@ var IndexedDBAdapter = /** @class */ (function () {
321
385
  relations = namespace.relationships[srcModelName].relationTypes;
322
386
  connectionStoreNames = relations.map(function (_a) {
323
387
  var modelName = _a.modelName;
324
- return _this.getStorename(namespaceName, modelName);
388
+ return getStorename(namespaceName, modelName);
325
389
  });
326
390
  modelConstructor = this.getModelConstructorByModelName(namespaceName, srcModelName);
327
391
  if (connectionStoreNames.length === 0) {
@@ -332,122 +396,170 @@ var IndexedDBAdapter = /** @class */ (function () {
332
396
  tx = this.db.transaction(__spread(connectionStoreNames), 'readonly');
333
397
  _e.label = 1;
334
398
  case 1:
335
- _e.trys.push([1, 34, 35, 40]);
399
+ _e.trys.push([1, 38, 39, 44]);
336
400
  relations_1 = __asyncValues(relations);
337
401
  _e.label = 2;
338
402
  case 2: return [4 /*yield*/, relations_1.next()];
339
403
  case 3:
340
- if (!(relations_1_1 = _e.sent(), !relations_1_1.done)) return [3 /*break*/, 33];
404
+ if (!(relations_1_1 = _e.sent(), !relations_1_1.done)) return [3 /*break*/, 37];
341
405
  relation = relations_1_1.value;
342
- fieldName = relation.fieldName, modelName = relation.modelName, targetName = relation.targetName;
343
- storeName = this.getStorename(namespaceName, modelName);
406
+ fieldName = relation.fieldName, modelName = relation.modelName, targetName = relation.targetName, targetNames = relation.targetNames;
407
+ storeName = getStorename(namespaceName, modelName);
344
408
  store = tx.objectStore(storeName);
345
409
  modelConstructor_1 = this.getModelConstructorByModelName(namespaceName, modelName);
346
410
  _d = relation.relationType;
347
411
  switch (_d) {
348
412
  case 'HAS_ONE': return [3 /*break*/, 4];
349
- case 'BELONGS_TO': return [3 /*break*/, 17];
350
- case 'HAS_MANY': return [3 /*break*/, 30];
413
+ case 'BELONGS_TO': return [3 /*break*/, 19];
414
+ case 'HAS_MANY': return [3 /*break*/, 34];
351
415
  }
352
- return [3 /*break*/, 31];
416
+ return [3 /*break*/, 35];
353
417
  case 4:
354
- _e.trys.push([4, 10, 11, 16]);
418
+ _e.trys.push([4, 12, 13, 18]);
355
419
  records_1 = __asyncValues(records);
356
420
  _e.label = 5;
357
421
  case 5: return [4 /*yield*/, records_1.next()];
358
422
  case 6:
359
- if (!(records_1_1 = _e.sent(), !records_1_1.done)) return [3 /*break*/, 9];
423
+ if (!(records_1_1 = _e.sent(), !records_1_1.done)) return [3 /*break*/, 11];
360
424
  recordItem = records_1_1.value;
361
- getByfield = recordItem[targetName] ? targetName : fieldName;
362
- if (!recordItem[getByfield])
363
- return [3 /*break*/, 9];
364
- return [4 /*yield*/, this._get(store, recordItem[getByfield])];
425
+ if (!(targetNames === null || targetNames === void 0 ? void 0 : targetNames.length)) return [3 /*break*/, 8];
426
+ getByFields = [];
427
+ allPresent = void 0;
428
+ // iterate through all targetnames to make sure they are all present in the recordItem
429
+ allPresent = targetNames.every(function (targetName) {
430
+ return recordItem[targetName] != null;
431
+ });
432
+ if (!allPresent) {
433
+ return [3 /*break*/, 11];
434
+ }
435
+ getByFields = targetNames;
436
+ keys = getByFields.map(function (getByField) { return recordItem[getByField]; });
437
+ return [4 /*yield*/, this._get(store, keys)];
365
438
  case 7:
366
439
  connectionRecord = _e.sent();
367
440
  recordItem[fieldName] =
368
441
  connectionRecord &&
369
442
  this.modelInstanceCreator(modelConstructor_1, connectionRecord);
370
- _e.label = 8;
371
- case 8: return [3 /*break*/, 5];
372
- case 9: return [3 /*break*/, 16];
373
- case 10:
443
+ return [3 /*break*/, 10];
444
+ case 8:
445
+ getByfield = recordItem[targetName]
446
+ ? targetName
447
+ : fieldName;
448
+ // We break here, because the recordItem does not have 'team', the `getByField`
449
+ // extract the keys on the related model.
450
+ if (!recordItem[getByfield])
451
+ return [3 /*break*/, 11];
452
+ key = [recordItem[getByfield]];
453
+ return [4 /*yield*/, this._get(store, key)];
454
+ case 9:
455
+ connectionRecord = _e.sent();
456
+ recordItem[fieldName] =
457
+ connectionRecord &&
458
+ this.modelInstanceCreator(modelConstructor_1, connectionRecord);
459
+ _e.label = 10;
460
+ case 10: return [3 /*break*/, 5];
461
+ case 11: return [3 /*break*/, 18];
462
+ case 12:
374
463
  e_4_1 = _e.sent();
375
464
  e_4 = { error: e_4_1 };
376
- return [3 /*break*/, 16];
377
- case 11:
378
- _e.trys.push([11, , 14, 15]);
379
- if (!(records_1_1 && !records_1_1.done && (_b = records_1.return))) return [3 /*break*/, 13];
465
+ return [3 /*break*/, 18];
466
+ case 13:
467
+ _e.trys.push([13, , 16, 17]);
468
+ if (!(records_1_1 && !records_1_1.done && (_b = records_1.return))) return [3 /*break*/, 15];
380
469
  return [4 /*yield*/, _b.call(records_1)];
381
- case 12:
382
- _e.sent();
383
- _e.label = 13;
384
- case 13: return [3 /*break*/, 15];
385
470
  case 14:
471
+ _e.sent();
472
+ _e.label = 15;
473
+ case 15: return [3 /*break*/, 17];
474
+ case 16:
386
475
  if (e_4) throw e_4.error;
387
476
  return [7 /*endfinally*/];
388
- case 15: return [7 /*endfinally*/];
389
- case 16: return [3 /*break*/, 32];
390
- case 17:
391
- _e.trys.push([17, 23, 24, 29]);
392
- records_2 = __asyncValues(records);
393
- _e.label = 18;
394
- case 18: return [4 /*yield*/, records_2.next()];
477
+ case 17: return [7 /*endfinally*/];
478
+ case 18: return [3 /*break*/, 36];
395
479
  case 19:
396
- if (!(records_2_1 = _e.sent(), !records_2_1.done)) return [3 /*break*/, 22];
480
+ _e.trys.push([19, 27, 28, 33]);
481
+ records_2 = __asyncValues(records);
482
+ _e.label = 20;
483
+ case 20: return [4 /*yield*/, records_2.next()];
484
+ case 21:
485
+ if (!(records_2_1 = _e.sent(), !records_2_1.done)) return [3 /*break*/, 26];
397
486
  recordItem = records_2_1.value;
398
- if (!recordItem[targetName]) return [3 /*break*/, 21];
399
- return [4 /*yield*/, this._get(store, recordItem[targetName])];
400
- case 20:
487
+ if (!(targetNames === null || targetNames === void 0 ? void 0 : targetNames.length)) return [3 /*break*/, 23];
488
+ allPresent = void 0;
489
+ // iterate through all targetnames to make sure they are all present in the recordItem
490
+ allPresent = targetNames.every(function (targetName) {
491
+ return recordItem[targetName] != null;
492
+ });
493
+ // If not present, there is not yet a connected record
494
+ if (!allPresent) {
495
+ return [3 /*break*/, 26];
496
+ }
497
+ keys = targetNames.map(function (targetName) { return recordItem[targetName]; });
498
+ return [4 /*yield*/, this._get(store, keys)];
499
+ case 22:
401
500
  connectionRecord = _e.sent();
402
501
  recordItem[fieldName] =
403
502
  connectionRecord &&
404
503
  this.modelInstanceCreator(modelConstructor_1, connectionRecord);
405
- delete recordItem[targetName];
406
- _e.label = 21;
407
- case 21: return [3 /*break*/, 18];
408
- case 22: return [3 /*break*/, 29];
504
+ targetNames === null || targetNames === void 0 ? void 0 : targetNames.map(function (targetName) {
505
+ delete recordItem[targetName];
506
+ });
507
+ return [3 /*break*/, 25];
409
508
  case 23:
509
+ if (!recordItem[targetName]) return [3 /*break*/, 25];
510
+ key = [recordItem[targetName]];
511
+ return [4 /*yield*/, this._get(store, key)];
512
+ case 24:
513
+ connectionRecord = _e.sent();
514
+ recordItem[fieldName] =
515
+ connectionRecord &&
516
+ this.modelInstanceCreator(modelConstructor_1, connectionRecord);
517
+ delete recordItem[targetName];
518
+ _e.label = 25;
519
+ case 25: return [3 /*break*/, 20];
520
+ case 26: return [3 /*break*/, 33];
521
+ case 27:
410
522
  e_5_1 = _e.sent();
411
523
  e_5 = { error: e_5_1 };
412
- return [3 /*break*/, 29];
413
- case 24:
414
- _e.trys.push([24, , 27, 28]);
415
- if (!(records_2_1 && !records_2_1.done && (_c = records_2.return))) return [3 /*break*/, 26];
524
+ return [3 /*break*/, 33];
525
+ case 28:
526
+ _e.trys.push([28, , 31, 32]);
527
+ if (!(records_2_1 && !records_2_1.done && (_c = records_2.return))) return [3 /*break*/, 30];
416
528
  return [4 /*yield*/, _c.call(records_2)];
417
- case 25:
529
+ case 29:
418
530
  _e.sent();
419
- _e.label = 26;
420
- case 26: return [3 /*break*/, 28];
421
- case 27:
531
+ _e.label = 30;
532
+ case 30: return [3 /*break*/, 32];
533
+ case 31:
422
534
  if (e_5) throw e_5.error;
423
535
  return [7 /*endfinally*/];
424
- case 28: return [7 /*endfinally*/];
425
- case 29: return [3 /*break*/, 32];
426
- case 30:
536
+ case 32: return [7 /*endfinally*/];
537
+ case 33: return [3 /*break*/, 36];
538
+ case 34:
427
539
  // TODO: Lazy loading
428
- return [3 /*break*/, 32];
429
- case 31:
540
+ return [3 /*break*/, 36];
541
+ case 35:
430
542
  exhaustiveCheck(relation.relationType);
431
- return [3 /*break*/, 32];
432
- case 32: return [3 /*break*/, 2];
433
- case 33: return [3 /*break*/, 40];
434
- case 34:
543
+ return [3 /*break*/, 36];
544
+ case 36: return [3 /*break*/, 2];
545
+ case 37: return [3 /*break*/, 44];
546
+ case 38:
435
547
  e_3_1 = _e.sent();
436
548
  e_3 = { error: e_3_1 };
437
- return [3 /*break*/, 40];
438
- case 35:
439
- _e.trys.push([35, , 38, 39]);
440
- if (!(relations_1_1 && !relations_1_1.done && (_a = relations_1.return))) return [3 /*break*/, 37];
549
+ return [3 /*break*/, 44];
550
+ case 39:
551
+ _e.trys.push([39, , 42, 43]);
552
+ if (!(relations_1_1 && !relations_1_1.done && (_a = relations_1.return))) return [3 /*break*/, 41];
441
553
  return [4 /*yield*/, _a.call(relations_1)];
442
- case 36:
554
+ case 40:
443
555
  _e.sent();
444
- _e.label = 37;
445
- case 37: return [3 /*break*/, 39];
446
- case 38:
556
+ _e.label = 41;
557
+ case 41: return [3 /*break*/, 43];
558
+ case 42:
447
559
  if (e_3) throw e_3.error;
448
560
  return [7 /*endfinally*/];
449
- case 39: return [7 /*endfinally*/];
450
- case 40: return [2 /*return*/, records.map(function (record) {
561
+ case 43: return [7 /*endfinally*/];
562
+ case 44: return [2 /*return*/, records.map(function (record) {
451
563
  return _this.modelInstanceCreator(modelConstructor, record);
452
564
  })];
453
565
  }
@@ -456,7 +568,7 @@ var IndexedDBAdapter = /** @class */ (function () {
456
568
  };
457
569
  IndexedDBAdapter.prototype.query = function (modelConstructor, predicate, pagination) {
458
570
  return __awaiter(this, void 0, void 0, function () {
459
- var storeName, namespaceName, predicates, queryById, hasSort, hasPagination, records;
571
+ var storeName, namespaceName, predicates, keyPath, queryByKey, hasSort, hasPagination, records;
460
572
  var _this = this;
461
573
  return __generator(this, function (_a) {
462
574
  switch (_a.label) {
@@ -466,7 +578,8 @@ var IndexedDBAdapter = /** @class */ (function () {
466
578
  storeName = this.getStorenameForModel(modelConstructor);
467
579
  namespaceName = this.namespaceResolver(modelConstructor);
468
580
  predicates = predicate && ModelPredicateCreator.getPredicates(predicate);
469
- queryById = predicates && this.idFromPredicate(predicates);
581
+ keyPath = getIndexKeys(this.schema.namespaces[namespaceName], modelConstructor.name);
582
+ queryByKey = predicates && this.keyValueFromPredicate(predicates, keyPath);
470
583
  hasSort = pagination && pagination.sort;
471
584
  hasPagination = pagination && pagination.limit;
472
585
  return [4 /*yield*/, (function () { return __awaiter(_this, void 0, void 0, function () {
@@ -474,8 +587,8 @@ var IndexedDBAdapter = /** @class */ (function () {
474
587
  return __generator(this, function (_a) {
475
588
  switch (_a.label) {
476
589
  case 0:
477
- if (!queryById) return [3 /*break*/, 2];
478
- return [4 /*yield*/, this.getById(storeName, queryById)];
590
+ if (!queryByKey) return [3 /*break*/, 2];
591
+ return [4 /*yield*/, this.getByKey(storeName, queryByKey)];
479
592
  case 1:
480
593
  record = _a.sent();
481
594
  return [2 /*return*/, record ? [record] : []];
@@ -507,12 +620,12 @@ var IndexedDBAdapter = /** @class */ (function () {
507
620
  });
508
621
  });
509
622
  };
510
- IndexedDBAdapter.prototype.getById = function (storeName, id) {
623
+ IndexedDBAdapter.prototype.getByKey = function (storeName, keyValue) {
511
624
  return __awaiter(this, void 0, void 0, function () {
512
625
  var record;
513
626
  return __generator(this, function (_a) {
514
627
  switch (_a.label) {
515
- case 0: return [4 /*yield*/, this._get(storeName, id)];
628
+ case 0: return [4 /*yield*/, this._get(storeName, keyValue)];
516
629
  case 1:
517
630
  record = _a.sent();
518
631
  return [2 /*return*/, record];
@@ -530,11 +643,31 @@ var IndexedDBAdapter = /** @class */ (function () {
530
643
  });
531
644
  });
532
645
  };
533
- IndexedDBAdapter.prototype.idFromPredicate = function (predicates) {
646
+ IndexedDBAdapter.prototype.keyValueFromPredicate = function (predicates, keyPath) {
647
+ var e_6, _a;
534
648
  var predicateObjs = predicates.predicates;
535
- var idPredicate = predicateObjs.length === 1 &&
536
- predicateObjs.find(function (p) { return isPredicateObj(p) && p.field === 'id' && p.operator === 'eq'; });
537
- return idPredicate && idPredicate.operand;
649
+ if (predicateObjs.length !== keyPath.length) {
650
+ return;
651
+ }
652
+ var keyValues = [];
653
+ var _loop_1 = function (key) {
654
+ var predicateObj = predicateObjs.find(function (p) { return isPredicateObj(p) && p.field === key && p.operator === 'eq'; });
655
+ predicateObj && keyValues.push(predicateObj.operand);
656
+ };
657
+ try {
658
+ for (var keyPath_1 = __values(keyPath), keyPath_1_1 = keyPath_1.next(); !keyPath_1_1.done; keyPath_1_1 = keyPath_1.next()) {
659
+ var key = keyPath_1_1.value;
660
+ _loop_1(key);
661
+ }
662
+ }
663
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
664
+ finally {
665
+ try {
666
+ if (keyPath_1_1 && !keyPath_1_1.done && (_a = keyPath_1.return)) _a.call(keyPath_1);
667
+ }
668
+ finally { if (e_6) throw e_6.error; }
669
+ }
670
+ return keyValues.length === keyPath.length ? keyValues : undefined;
538
671
  };
539
672
  IndexedDBAdapter.prototype.filterOnPredicate = function (storeName, predicates) {
540
673
  return __awaiter(this, void 0, void 0, function () {
@@ -640,7 +773,7 @@ var IndexedDBAdapter = /** @class */ (function () {
640
773
  };
641
774
  IndexedDBAdapter.prototype.delete = function (modelOrModelConstructor, condition) {
642
775
  return __awaiter(this, void 0, void 0, function () {
643
- var deleteQueue, modelConstructor, nameSpace, storeName, models, relations, deletedModels, deletedModels, model, modelConstructor, nameSpace, storeName, tx, store, fromDB, msg, predicates, predicateObjs, type, isValid, msg, relations, relations, deletedModels;
776
+ var deleteQueue, modelConstructor, nameSpace, storeName, models, relations, deletedModels, deletedModels, model, modelConstructor, namespaceName, storeName, tx, store, keyValues, fromDB, msg, predicates, predicateObjs, type, isValid, msg, relations, relations, deletedModels;
644
777
  return __generator(this, function (_a) {
645
778
  switch (_a.label) {
646
779
  case 0: return [4 /*yield*/, this.checkPrivate()];
@@ -689,12 +822,13 @@ var IndexedDBAdapter = /** @class */ (function () {
689
822
  model = modelOrModelConstructor;
690
823
  modelConstructor = Object.getPrototypeOf(model)
691
824
  .constructor;
692
- nameSpace = this.namespaceResolver(modelConstructor);
825
+ namespaceName = this.namespaceResolver(modelConstructor);
693
826
  storeName = this.getStorenameForModel(modelConstructor);
694
827
  if (!condition) return [3 /*break*/, 13];
695
828
  tx = this.db.transaction([storeName], 'readwrite');
696
829
  store = tx.objectStore(storeName);
697
- return [4 /*yield*/, this._get(store, model.id)];
830
+ keyValues = this.getIndexKeyValuesFromModel(model);
831
+ return [4 /*yield*/, this._get(store, keyValues)];
698
832
  case 10:
699
833
  fromDB = _a.sent();
700
834
  if (fromDB === undefined) {
@@ -713,16 +847,14 @@ var IndexedDBAdapter = /** @class */ (function () {
713
847
  return [4 /*yield*/, tx.done];
714
848
  case 11:
715
849
  _a.sent();
716
- relations = this.schema.namespaces[nameSpace].relationships[modelConstructor.name]
717
- .relationTypes;
718
- return [4 /*yield*/, this.deleteTraverse(relations, [model], modelConstructor.name, nameSpace, deleteQueue)];
850
+ relations = this.schema.namespaces[namespaceName].relationships[modelConstructor.name].relationTypes;
851
+ return [4 /*yield*/, this.deleteTraverse(relations, [model], modelConstructor.name, namespaceName, deleteQueue)];
719
852
  case 12:
720
853
  _a.sent();
721
854
  return [3 /*break*/, 15];
722
855
  case 13:
723
- relations = this.schema.namespaces[nameSpace].relationships[modelConstructor.name]
724
- .relationTypes;
725
- return [4 /*yield*/, this.deleteTraverse(relations, [model], modelConstructor.name, nameSpace, deleteQueue)];
856
+ relations = this.schema.namespaces[namespaceName].relationships[modelConstructor.name].relationTypes;
857
+ return [4 /*yield*/, this.deleteTraverse(relations, [model], modelConstructor.name, namespaceName, deleteQueue)];
726
858
  case 14:
727
859
  _a.sent();
728
860
  _a.label = 15;
@@ -741,9 +873,9 @@ var IndexedDBAdapter = /** @class */ (function () {
741
873
  };
742
874
  IndexedDBAdapter.prototype.deleteItem = function (deleteQueue) {
743
875
  var deleteQueue_1, deleteQueue_1_1;
744
- var e_6, _a, e_7, _b;
876
+ var e_7, _a, e_8, _b;
745
877
  return __awaiter(this, void 0, void 0, function () {
746
- var connectionStoreNames, tx, deleteItem, storeName, items, store, items_1, items_1_1, item, key, e_7_1, e_6_1;
878
+ var connectionStoreNames, tx, deleteItem, storeName, items, store, items_1, items_1_1, item, key, keyValues, itemKey, e_8_1, e_7_1;
747
879
  return __generator(this, function (_c) {
748
880
  switch (_c.label) {
749
881
  case 0:
@@ -775,11 +907,16 @@ var IndexedDBAdapter = /** @class */ (function () {
775
907
  if (!item) return [3 /*break*/, 12];
776
908
  key = void 0;
777
909
  if (!(typeof item === 'object')) return [3 /*break*/, 8];
778
- return [4 /*yield*/, store.index('byId').getKey(item['id'])];
910
+ keyValues = this.getIndexKeyValuesFromModel(item);
911
+ return [4 /*yield*/, store
912
+ .index('byPk')
913
+ .getKey(this.canonicalKeyPath(keyValues))];
779
914
  case 7:
780
915
  key = _c.sent();
781
916
  return [3 /*break*/, 10];
782
- case 8: return [4 /*yield*/, store.index('byId').getKey(item.toString())];
917
+ case 8:
918
+ itemKey = item.toString();
919
+ return [4 /*yield*/, store.index('byPk').getKey(itemKey)];
783
920
  case 9:
784
921
  key = _c.sent();
785
922
  _c.label = 10;
@@ -792,8 +929,8 @@ var IndexedDBAdapter = /** @class */ (function () {
792
929
  case 12: return [3 /*break*/, 5];
793
930
  case 13: return [3 /*break*/, 20];
794
931
  case 14:
795
- e_7_1 = _c.sent();
796
- e_7 = { error: e_7_1 };
932
+ e_8_1 = _c.sent();
933
+ e_8 = { error: e_8_1 };
797
934
  return [3 /*break*/, 20];
798
935
  case 15:
799
936
  _c.trys.push([15, , 18, 19]);
@@ -804,14 +941,14 @@ var IndexedDBAdapter = /** @class */ (function () {
804
941
  _c.label = 17;
805
942
  case 17: return [3 /*break*/, 19];
806
943
  case 18:
807
- if (e_7) throw e_7.error;
944
+ if (e_8) throw e_8.error;
808
945
  return [7 /*endfinally*/];
809
946
  case 19: return [7 /*endfinally*/];
810
947
  case 20: return [3 /*break*/, 2];
811
948
  case 21: return [3 /*break*/, 28];
812
949
  case 22:
813
- e_6_1 = _c.sent();
814
- e_6 = { error: e_6_1 };
950
+ e_7_1 = _c.sent();
951
+ e_7 = { error: e_7_1 };
815
952
  return [3 /*break*/, 28];
816
953
  case 23:
817
954
  _c.trys.push([23, , 26, 27]);
@@ -822,7 +959,7 @@ var IndexedDBAdapter = /** @class */ (function () {
822
959
  _c.label = 25;
823
960
  case 25: return [3 /*break*/, 27];
824
961
  case 26:
825
- if (e_6) throw e_6.error;
962
+ if (e_7) throw e_7.error;
826
963
  return [7 /*endfinally*/];
827
964
  case 27: return [7 /*endfinally*/];
828
965
  case 28: return [2 /*return*/];
@@ -832,145 +969,178 @@ var IndexedDBAdapter = /** @class */ (function () {
832
969
  };
833
970
  IndexedDBAdapter.prototype.deleteTraverse = function (relations, models, srcModel, nameSpace, deleteQueue) {
834
971
  var relations_2, relations_2_1, models_1, models_1_1, models_2, models_2_1;
835
- var e_8, _a, e_9, _b, e_10, _c;
972
+ var e_9, _a, e_10, _b, e_11, _c;
836
973
  return __awaiter(this, void 0, void 0, function () {
837
- var rel, relationType, fieldName, modelName, targetName, storeName, index, _d, model, hasOneIndex, hasOneCustomField, value, recordToDelete, e_9_1, model, childrenArray, e_10_1, e_8_1;
974
+ var rel, relationType, modelName, targetName, targetNames, associatedWith, storeName, _d, model, hasOneIndex, values, recordToDelete, index, values, value, recordToDelete, e_10_1, model, index, keyValues, childrenArray, e_11_1, e_9_1;
838
975
  var _this = this;
839
976
  return __generator(this, function (_e) {
840
977
  switch (_e.label) {
841
978
  case 0:
842
- _e.trys.push([0, 35, 36, 41]);
979
+ _e.trys.push([0, 38, 39, 44]);
843
980
  relations_2 = __asyncValues(relations);
844
981
  _e.label = 1;
845
982
  case 1: return [4 /*yield*/, relations_2.next()];
846
983
  case 2:
847
- if (!(relations_2_1 = _e.sent(), !relations_2_1.done)) return [3 /*break*/, 34];
984
+ if (!(relations_2_1 = _e.sent(), !relations_2_1.done)) return [3 /*break*/, 37];
848
985
  rel = relations_2_1.value;
849
- relationType = rel.relationType, fieldName = rel.fieldName, modelName = rel.modelName, targetName = rel.targetName;
850
- storeName = this.getStorename(nameSpace, modelName);
851
- index = getIndex(this.schema.namespaces[nameSpace].relationships[modelName]
852
- .relationTypes, srcModel) ||
853
- // if we were unable to find an index via relationTypes
854
- // i.e. for keyName connections, attempt to find one by the
855
- // associatedWith property
856
- getIndexFromAssociation(this.schema.namespaces[nameSpace].relationships[modelName].indexes, rel.associatedWith);
986
+ relationType = rel.relationType, modelName = rel.modelName, targetName = rel.targetName, targetNames = rel.targetNames, associatedWith = rel.associatedWith;
987
+ storeName = getStorename(nameSpace, modelName);
857
988
  _d = relationType;
858
989
  switch (_d) {
859
990
  case 'HAS_ONE': return [3 /*break*/, 3];
860
- case 'HAS_MANY': return [3 /*break*/, 17];
861
- case 'BELONGS_TO': return [3 /*break*/, 31];
991
+ case 'HAS_MANY': return [3 /*break*/, 20];
992
+ case 'BELONGS_TO': return [3 /*break*/, 34];
862
993
  }
863
- return [3 /*break*/, 32];
994
+ return [3 /*break*/, 35];
864
995
  case 3:
865
- _e.trys.push([3, 10, 11, 16]);
996
+ _e.trys.push([3, 13, 14, 19]);
866
997
  models_1 = __asyncValues(models);
867
998
  _e.label = 4;
868
999
  case 4: return [4 /*yield*/, models_1.next()];
869
1000
  case 5:
870
- if (!(models_1_1 = _e.sent(), !models_1_1.done)) return [3 /*break*/, 9];
1001
+ if (!(models_1_1 = _e.sent(), !models_1_1.done)) return [3 /*break*/, 12];
871
1002
  model = models_1_1.value;
872
- hasOneIndex = index || 'byId';
873
- hasOneCustomField = targetName in model;
874
- value = hasOneCustomField ? model[targetName] : model.id;
875
- if (!value)
876
- return [3 /*break*/, 9];
1003
+ hasOneIndex = 'byPk';
1004
+ if (!(targetNames === null || targetNames === void 0 ? void 0 : targetNames.length)) return [3 /*break*/, 8];
1005
+ values = targetNames.map(function (targetName) { return model[targetName]; });
1006
+ if (values.length === 0)
1007
+ return [3 /*break*/, 12];
877
1008
  return [4 /*yield*/, this.db
878
1009
  .transaction(storeName, 'readwrite')
879
1010
  .objectStore(storeName)
880
1011
  .index(hasOneIndex)
881
- .get(value)];
1012
+ .get(this.canonicalKeyPath(values))];
882
1013
  case 6:
883
1014
  recordToDelete = (_e.sent());
884
1015
  return [4 /*yield*/, this.deleteTraverse(this.schema.namespaces[nameSpace].relationships[modelName]
885
1016
  .relationTypes, recordToDelete ? [recordToDelete] : [], modelName, nameSpace, deleteQueue)];
886
1017
  case 7:
887
1018
  _e.sent();
888
- _e.label = 8;
889
- case 8: return [3 /*break*/, 4];
890
- case 9: return [3 /*break*/, 16];
1019
+ return [3 /*break*/, 12];
1020
+ case 8:
1021
+ index = void 0;
1022
+ values = void 0;
1023
+ if (targetName && targetName in model) {
1024
+ index = hasOneIndex;
1025
+ value = model[targetName];
1026
+ values = [value];
1027
+ }
1028
+ else {
1029
+ // backwards compatability for older versions of codegen that did not emit targetName for HAS_ONE relations
1030
+ // TODO: can we deprecate this? it's been ~2 years since codegen started including targetName for HAS_ONE
1031
+ // If we deprecate, we'll need to re-gen the MIPR in __tests__/schema.ts > newSchema
1032
+ // otherwise some unit tests will fail
1033
+ index = getIndex(this.schema.namespaces[nameSpace].relationships[modelName]
1034
+ .relationTypes, srcModel);
1035
+ values = this.getIndexKeyValuesFromModel(model);
1036
+ }
1037
+ if (!values || !index)
1038
+ return [3 /*break*/, 12];
1039
+ return [4 /*yield*/, this.db
1040
+ .transaction(storeName, 'readwrite')
1041
+ .objectStore(storeName)
1042
+ .index(index)
1043
+ .get(this.canonicalKeyPath(values))];
1044
+ case 9:
1045
+ recordToDelete = (_e.sent());
1046
+ return [4 /*yield*/, this.deleteTraverse(this.schema.namespaces[nameSpace].relationships[modelName]
1047
+ .relationTypes, recordToDelete ? [recordToDelete] : [], modelName, nameSpace, deleteQueue)];
891
1048
  case 10:
892
- e_9_1 = _e.sent();
893
- e_9 = { error: e_9_1 };
894
- return [3 /*break*/, 16];
895
- case 11:
896
- _e.trys.push([11, , 14, 15]);
897
- if (!(models_1_1 && !models_1_1.done && (_b = models_1.return))) return [3 /*break*/, 13];
898
- return [4 /*yield*/, _b.call(models_1)];
899
- case 12:
900
1049
  _e.sent();
901
- _e.label = 13;
902
- case 13: return [3 /*break*/, 15];
1050
+ _e.label = 11;
1051
+ case 11: return [3 /*break*/, 4];
1052
+ case 12: return [3 /*break*/, 19];
1053
+ case 13:
1054
+ e_10_1 = _e.sent();
1055
+ e_10 = { error: e_10_1 };
1056
+ return [3 /*break*/, 19];
903
1057
  case 14:
904
- if (e_9) throw e_9.error;
905
- return [7 /*endfinally*/];
906
- case 15: return [7 /*endfinally*/];
907
- case 16: return [3 /*break*/, 33];
1058
+ _e.trys.push([14, , 17, 18]);
1059
+ if (!(models_1_1 && !models_1_1.done && (_b = models_1.return))) return [3 /*break*/, 16];
1060
+ return [4 /*yield*/, _b.call(models_1)];
1061
+ case 15:
1062
+ _e.sent();
1063
+ _e.label = 16;
1064
+ case 16: return [3 /*break*/, 18];
908
1065
  case 17:
909
- _e.trys.push([17, 24, 25, 30]);
1066
+ if (e_10) throw e_10.error;
1067
+ return [7 /*endfinally*/];
1068
+ case 18: return [7 /*endfinally*/];
1069
+ case 19: return [3 /*break*/, 36];
1070
+ case 20:
1071
+ _e.trys.push([20, 27, 28, 33]);
910
1072
  models_2 = __asyncValues(models);
911
- _e.label = 18;
912
- case 18: return [4 /*yield*/, models_2.next()];
913
- case 19:
914
- if (!(models_2_1 = _e.sent(), !models_2_1.done)) return [3 /*break*/, 23];
1073
+ _e.label = 21;
1074
+ case 21: return [4 /*yield*/, models_2.next()];
1075
+ case 22:
1076
+ if (!(models_2_1 = _e.sent(), !models_2_1.done)) return [3 /*break*/, 26];
915
1077
  model = models_2_1.value;
1078
+ index =
1079
+ // explicit bi-directional @hasMany and @manyToMany
1080
+ getIndex(this.schema.namespaces[nameSpace].relationships[modelName]
1081
+ .relationTypes, srcModel) ||
1082
+ // uni and/or implicit @hasMany
1083
+ getIndexFromAssociation(this.schema.namespaces[nameSpace].relationships[modelName]
1084
+ .indexes, associatedWith);
1085
+ keyValues = this.getIndexKeyValuesFromModel(model);
916
1086
  return [4 /*yield*/, this.db
917
1087
  .transaction(storeName, 'readwrite')
918
1088
  .objectStore(storeName)
919
1089
  .index(index)
920
- .getAll(model['id'])];
921
- case 20:
1090
+ .getAll(this.canonicalKeyPath(keyValues))];
1091
+ case 23:
922
1092
  childrenArray = _e.sent();
923
1093
  return [4 /*yield*/, this.deleteTraverse(this.schema.namespaces[nameSpace].relationships[modelName]
924
1094
  .relationTypes, childrenArray, modelName, nameSpace, deleteQueue)];
925
- case 21:
926
- _e.sent();
927
- _e.label = 22;
928
- case 22: return [3 /*break*/, 18];
929
- case 23: return [3 /*break*/, 30];
930
1095
  case 24:
931
- e_10_1 = _e.sent();
932
- e_10 = { error: e_10_1 };
933
- return [3 /*break*/, 30];
934
- case 25:
935
- _e.trys.push([25, , 28, 29]);
936
- if (!(models_2_1 && !models_2_1.done && (_c = models_2.return))) return [3 /*break*/, 27];
937
- return [4 /*yield*/, _c.call(models_2)];
938
- case 26:
939
1096
  _e.sent();
940
- _e.label = 27;
941
- case 27: return [3 /*break*/, 29];
1097
+ _e.label = 25;
1098
+ case 25: return [3 /*break*/, 21];
1099
+ case 26: return [3 /*break*/, 33];
1100
+ case 27:
1101
+ e_11_1 = _e.sent();
1102
+ e_11 = { error: e_11_1 };
1103
+ return [3 /*break*/, 33];
942
1104
  case 28:
943
- if (e_10) throw e_10.error;
1105
+ _e.trys.push([28, , 31, 32]);
1106
+ if (!(models_2_1 && !models_2_1.done && (_c = models_2.return))) return [3 /*break*/, 30];
1107
+ return [4 /*yield*/, _c.call(models_2)];
1108
+ case 29:
1109
+ _e.sent();
1110
+ _e.label = 30;
1111
+ case 30: return [3 /*break*/, 32];
1112
+ case 31:
1113
+ if (e_11) throw e_11.error;
944
1114
  return [7 /*endfinally*/];
945
- case 29: return [7 /*endfinally*/];
946
- case 30: return [3 /*break*/, 33];
947
- case 31:
1115
+ case 32: return [7 /*endfinally*/];
1116
+ case 33: return [3 /*break*/, 36];
1117
+ case 34:
948
1118
  // Intentionally blank
949
- return [3 /*break*/, 33];
950
- case 32:
951
- exhaustiveCheck(relationType);
952
- return [3 /*break*/, 33];
953
- case 33: return [3 /*break*/, 1];
954
- case 34: return [3 /*break*/, 41];
1119
+ return [3 /*break*/, 36];
955
1120
  case 35:
956
- e_8_1 = _e.sent();
957
- e_8 = { error: e_8_1 };
958
- return [3 /*break*/, 41];
959
- case 36:
960
- _e.trys.push([36, , 39, 40]);
961
- if (!(relations_2_1 && !relations_2_1.done && (_a = relations_2.return))) return [3 /*break*/, 38];
1121
+ exhaustiveCheck(relationType);
1122
+ return [3 /*break*/, 36];
1123
+ case 36: return [3 /*break*/, 1];
1124
+ case 37: return [3 /*break*/, 44];
1125
+ case 38:
1126
+ e_9_1 = _e.sent();
1127
+ e_9 = { error: e_9_1 };
1128
+ return [3 /*break*/, 44];
1129
+ case 39:
1130
+ _e.trys.push([39, , 42, 43]);
1131
+ if (!(relations_2_1 && !relations_2_1.done && (_a = relations_2.return))) return [3 /*break*/, 41];
962
1132
  return [4 /*yield*/, _a.call(relations_2)];
963
- case 37:
1133
+ case 40:
964
1134
  _e.sent();
965
- _e.label = 38;
966
- case 38: return [3 /*break*/, 40];
967
- case 39:
968
- if (e_8) throw e_8.error;
1135
+ _e.label = 41;
1136
+ case 41: return [3 /*break*/, 43];
1137
+ case 42:
1138
+ if (e_9) throw e_9.error;
969
1139
  return [7 /*endfinally*/];
970
- case 40: return [7 /*endfinally*/];
971
- case 41:
1140
+ case 43: return [7 /*endfinally*/];
1141
+ case 44:
972
1142
  deleteQueue.push({
973
- storeName: this.getStorename(nameSpace, srcModel),
1143
+ storeName: getStorename(nameSpace, srcModel),
974
1144
  items: models.map(function (record) {
975
1145
  return _this.modelInstanceCreator(_this.getModelConstructorByModelName(nameSpace, srcModel), record);
976
1146
  }),
@@ -1001,8 +1171,9 @@ var IndexedDBAdapter = /** @class */ (function () {
1001
1171
  };
1002
1172
  IndexedDBAdapter.prototype.batchSave = function (modelConstructor, items) {
1003
1173
  return __awaiter(this, void 0, void 0, function () {
1004
- var result, storeName, txn, store, _loop_1, this_1, items_2, items_2_1, item, e_11_1;
1005
- var e_11, _a;
1174
+ var result, storeName, txn, store, _loop_2, this_1, items_2, items_2_1, item, e_12_1;
1175
+ var e_12, _a;
1176
+ var _this = this;
1006
1177
  return __generator(this, function (_b) {
1007
1178
  switch (_b.label) {
1008
1179
  case 0:
@@ -1016,21 +1187,26 @@ var IndexedDBAdapter = /** @class */ (function () {
1016
1187
  storeName = this.getStorenameForModel(modelConstructor);
1017
1188
  txn = this.db.transaction(storeName, 'readwrite');
1018
1189
  store = txn.store;
1019
- _loop_1 = function (item) {
1020
- var connectedModels, id, _deleted, index, key, instance;
1190
+ _loop_2 = function (item) {
1191
+ var namespaceName, modelName, model, connectedModels, keyValues, _deleted, index, key, instance;
1021
1192
  return __generator(this, function (_a) {
1022
1193
  switch (_a.label) {
1023
1194
  case 0:
1024
- connectedModels = traverseModel(modelConstructor.name, this_1.modelInstanceCreator(modelConstructor, item), this_1.schema.namespaces[this_1.namespaceResolver(modelConstructor)], this_1.modelInstanceCreator, this_1.getModelConstructorByModelName);
1025
- id = item.id, _deleted = item._deleted;
1026
- index = store.index('byId');
1027
- return [4 /*yield*/, index.getKey(id)];
1195
+ namespaceName = this_1.namespaceResolver(modelConstructor);
1196
+ modelName = modelConstructor.name;
1197
+ model = this_1.modelInstanceCreator(modelConstructor, item);
1198
+ connectedModels = traverseModel(modelName, model, this_1.schema.namespaces[namespaceName], this_1.modelInstanceCreator, this_1.getModelConstructorByModelName);
1199
+ keyValues = this_1.getIndexKeyValuesFromModel(model);
1200
+ _deleted = item._deleted;
1201
+ index = store.index('byPk');
1202
+ return [4 /*yield*/, index.getKey(this_1.canonicalKeyPath(keyValues))];
1028
1203
  case 1:
1029
1204
  key = _a.sent();
1030
1205
  if (!!_deleted) return [3 /*break*/, 3];
1031
1206
  instance = connectedModels.find(function (_a) {
1032
1207
  var instance = _a.instance;
1033
- return instance.id === id;
1208
+ var instanceKeyValues = _this.getIndexKeyValuesFromModel(instance);
1209
+ return keysEqual(instanceKeyValues, keyValues);
1034
1210
  }).instance;
1035
1211
  result.push([
1036
1212
  instance,
@@ -1060,7 +1236,7 @@ var IndexedDBAdapter = /** @class */ (function () {
1060
1236
  case 3:
1061
1237
  if (!!items_2_1.done) return [3 /*break*/, 6];
1062
1238
  item = items_2_1.value;
1063
- return [5 /*yield**/, _loop_1(item)];
1239
+ return [5 /*yield**/, _loop_2(item)];
1064
1240
  case 4:
1065
1241
  _b.sent();
1066
1242
  _b.label = 5;
@@ -1069,14 +1245,14 @@ var IndexedDBAdapter = /** @class */ (function () {
1069
1245
  return [3 /*break*/, 3];
1070
1246
  case 6: return [3 /*break*/, 9];
1071
1247
  case 7:
1072
- e_11_1 = _b.sent();
1073
- e_11 = { error: e_11_1 };
1248
+ e_12_1 = _b.sent();
1249
+ e_12 = { error: e_12_1 };
1074
1250
  return [3 /*break*/, 9];
1075
1251
  case 8:
1076
1252
  try {
1077
1253
  if (items_2_1 && !items_2_1.done && (_a = items_2.return)) _a.call(items_2);
1078
1254
  }
1079
- finally { if (e_11) throw e_11.error; }
1255
+ finally { if (e_12) throw e_12.error; }
1080
1256
  return [7 /*endfinally*/];
1081
1257
  case 9: return [4 /*yield*/, txn.done];
1082
1258
  case 10:
@@ -1087,18 +1263,15 @@ var IndexedDBAdapter = /** @class */ (function () {
1087
1263
  });
1088
1264
  };
1089
1265
  IndexedDBAdapter.prototype.createObjectStoreForModel = function (db, namespaceName, storeName, modelName) {
1090
- return __awaiter(this, void 0, void 0, function () {
1091
- var store, indexes;
1092
- return __generator(this, function (_a) {
1093
- store = db.createObjectStore(storeName, {
1094
- autoIncrement: true,
1095
- });
1096
- indexes = this.schema.namespaces[namespaceName].relationships[modelName].indexes;
1097
- indexes.forEach(function (index) { return store.createIndex(index, index); });
1098
- store.createIndex('byId', 'id', { unique: true });
1099
- return [2 /*return*/];
1100
- });
1266
+ var store = db.createObjectStore(storeName, {
1267
+ autoIncrement: true,
1268
+ });
1269
+ var indexes = this.schema.namespaces[namespaceName].relationships[modelName].indexes;
1270
+ indexes.forEach(function (_a) {
1271
+ var _b = __read(_a, 3), idxName = _b[0], keyPath = _b[1], options = _b[2];
1272
+ store.createIndex(idxName, keyPath, options);
1101
1273
  });
1274
+ return store;
1102
1275
  };
1103
1276
  return IndexedDBAdapter;
1104
1277
  }());