@aws-amplify/datastore 3.12.12 → 3.12.13-custom-pk.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/dist/aws-amplify-datastore.js +1854 -965
  2. package/dist/aws-amplify-datastore.js.map +1 -1
  3. package/dist/aws-amplify-datastore.min.js +7 -7
  4. package/dist/aws-amplify-datastore.min.js.map +1 -1
  5. package/lib/datastore/datastore.d.ts +13 -16
  6. package/lib/datastore/datastore.js +130 -63
  7. package/lib/datastore/datastore.js.map +1 -1
  8. package/lib/index.d.ts +3 -19
  9. package/lib/predicates/index.d.ts +3 -2
  10. package/lib/predicates/index.js +12 -2
  11. package/lib/predicates/index.js.map +1 -1
  12. package/lib/storage/adapter/AsyncStorageAdapter.d.ts +4 -3
  13. package/lib/storage/adapter/AsyncStorageAdapter.js +354 -203
  14. package/lib/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  15. package/lib/storage/adapter/AsyncStorageDatabase.d.ts +14 -4
  16. package/lib/storage/adapter/AsyncStorageDatabase.js +65 -28
  17. package/lib/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  18. package/lib/storage/adapter/IndexedDBAdapter.d.ts +5 -4
  19. package/lib/storage/adapter/IndexedDBAdapter.js +389 -267
  20. package/lib/storage/adapter/IndexedDBAdapter.js.map +1 -1
  21. package/lib/storage/adapter/index.d.ts +1 -1
  22. package/lib/storage/storage.d.ts +1 -1
  23. package/lib/storage/storage.js +92 -27
  24. package/lib/storage/storage.js.map +1 -1
  25. package/lib/sync/index.d.ts +21 -4
  26. package/lib/sync/index.js +13 -11
  27. package/lib/sync/index.js.map +1 -1
  28. package/lib/sync/merger.d.ts +3 -3
  29. package/lib/sync/merger.js +7 -6
  30. package/lib/sync/merger.js.map +1 -1
  31. package/lib/sync/outbox.d.ts +2 -2
  32. package/lib/sync/outbox.js +11 -9
  33. package/lib/sync/outbox.js.map +1 -1
  34. package/lib/sync/processors/mutation.js +60 -42
  35. package/lib/sync/processors/mutation.js.map +1 -1
  36. package/lib/sync/processors/subscription.js.map +1 -1
  37. package/lib/sync/processors/sync.js.map +1 -1
  38. package/lib/sync/utils.d.ts +3 -2
  39. package/lib/sync/utils.js +61 -8
  40. package/lib/sync/utils.js.map +1 -1
  41. package/lib/types.d.ts +64 -25
  42. package/lib/types.js +10 -1
  43. package/lib/types.js.map +1 -1
  44. package/lib/util.d.ts +56 -24
  45. package/lib/util.js +334 -170
  46. package/lib/util.js.map +1 -1
  47. package/lib-esm/datastore/datastore.d.ts +13 -16
  48. package/lib-esm/datastore/datastore.js +132 -65
  49. package/lib-esm/datastore/datastore.js.map +1 -1
  50. package/lib-esm/index.d.ts +3 -19
  51. package/lib-esm/predicates/index.d.ts +3 -2
  52. package/lib-esm/predicates/index.js +13 -3
  53. package/lib-esm/predicates/index.js.map +1 -1
  54. package/lib-esm/storage/adapter/AsyncStorageAdapter.d.ts +4 -3
  55. package/lib-esm/storage/adapter/AsyncStorageAdapter.js +355 -204
  56. package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  57. package/lib-esm/storage/adapter/AsyncStorageDatabase.d.ts +14 -4
  58. package/lib-esm/storage/adapter/AsyncStorageDatabase.js +66 -29
  59. package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  60. package/lib-esm/storage/adapter/IndexedDBAdapter.d.ts +5 -4
  61. package/lib-esm/storage/adapter/IndexedDBAdapter.js +390 -268
  62. package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +1 -1
  63. package/lib-esm/storage/adapter/index.d.ts +1 -1
  64. package/lib-esm/storage/storage.d.ts +1 -1
  65. package/lib-esm/storage/storage.js +92 -27
  66. package/lib-esm/storage/storage.js.map +1 -1
  67. package/lib-esm/sync/index.d.ts +21 -4
  68. package/lib-esm/sync/index.js +15 -13
  69. package/lib-esm/sync/index.js.map +1 -1
  70. package/lib-esm/sync/merger.d.ts +3 -3
  71. package/lib-esm/sync/merger.js +7 -6
  72. package/lib-esm/sync/merger.js.map +1 -1
  73. package/lib-esm/sync/outbox.d.ts +2 -2
  74. package/lib-esm/sync/outbox.js +12 -10
  75. package/lib-esm/sync/outbox.js.map +1 -1
  76. package/lib-esm/sync/processors/mutation.js +61 -43
  77. package/lib-esm/sync/processors/mutation.js.map +1 -1
  78. package/lib-esm/sync/processors/subscription.js.map +1 -1
  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 +62 -10
  82. package/lib-esm/sync/utils.js.map +1 -1
  83. package/lib-esm/types.d.ts +64 -25
  84. package/lib-esm/types.js +9 -2
  85. package/lib-esm/types.js.map +1 -1
  86. package/lib-esm/util.d.ts +56 -24
  87. package/lib-esm/util.js +334 -170
  88. package/lib-esm/util.js.map +1 -1
  89. package/package.json +7 -7
  90. package/src/datastore/datastore.ts +253 -113
  91. package/src/predicates/index.ts +32 -10
  92. package/src/storage/adapter/AsyncStorageAdapter.ts +309 -93
  93. package/src/storage/adapter/AsyncStorageDatabase.ts +74 -26
  94. package/src/storage/adapter/IndexedDBAdapter.ts +319 -136
  95. package/src/storage/adapter/index.ts +1 -1
  96. package/src/storage/storage.ts +68 -21
  97. package/src/sync/index.ts +41 -26
  98. package/src/sync/merger.ts +14 -4
  99. package/src/sync/outbox.ts +21 -8
  100. package/src/sync/processors/mutation.ts +49 -45
  101. package/src/sync/processors/subscription.ts +0 -1
  102. package/src/sync/processors/sync.ts +1 -3
  103. package/src/sync/utils.ts +69 -12
  104. package/src/types.ts +181 -29
  105. package/src/util.ts +415 -176
@@ -41,17 +41,6 @@ var __asyncValues = (this && this.__asyncValues) || function (o) {
41
41
  function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
42
42
  function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
43
43
  };
44
- var __values = (this && this.__values) || function(o) {
45
- var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
46
- if (m) return m.call(o);
47
- if (o && typeof o.length === "number") return {
48
- next: function () {
49
- if (o && i >= o.length) o = void 0;
50
- return { value: o && o[i++], done: !o };
51
- }
52
- };
53
- throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
54
- };
55
44
  var __read = (this && this.__read) || function (o, n) {
56
45
  var m = typeof Symbol === "function" && o[Symbol.iterator];
57
46
  if (!m) return o;
@@ -68,6 +57,17 @@ var __read = (this && this.__read) || function (o, n) {
68
57
  }
69
58
  return ar;
70
59
  };
60
+ var __values = (this && this.__values) || function(o) {
61
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
62
+ if (m) return m.call(o);
63
+ if (o && typeof o.length === "number") return {
64
+ next: function () {
65
+ if (o && i >= o.length) o = void 0;
66
+ return { value: o && o[i++], done: !o };
67
+ }
68
+ };
69
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
70
+ };
71
71
  var __spread = (this && this.__spread) || function () {
72
72
  for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
73
73
  return ar;
@@ -76,13 +76,26 @@ import { ConsoleLogger as Logger } from '@aws-amplify/core';
76
76
  import * as idb from 'idb';
77
77
  import { ModelPredicateCreator, ModelSortPredicateCreator, } from '../../predicates';
78
78
  import { isPredicateObj, OpType, QueryOne, } from '../../types';
79
- import { exhaustiveCheck, getIndex, getIndexFromAssociation, isModelConstructor, isPrivateMode, traverseModel, validatePredicate, sortCompareFunction, } from '../../util';
79
+ import { exhaustiveCheck, getIndex, getIndexFromAssociation, isModelConstructor, isPrivateMode, traverseModel, validatePredicate, sortCompareFunction, keysEqual, getStorename, getIndexKeys, extractPrimaryKeyValues, } from '../../util';
80
80
  var logger = new Logger('DataStore');
81
81
  var DB_NAME = 'amplify-datastore';
82
82
  var IndexedDBAdapter = /** @class */ (function () {
83
83
  function IndexedDBAdapter() {
84
84
  this.dbName = DB_NAME;
85
85
  }
86
+ IndexedDBAdapter.prototype.getStorenameForModel = function (modelConstructor) {
87
+ var namespace = this.namespaceResolver(modelConstructor);
88
+ var modelName = modelConstructor.name;
89
+ return getStorename(namespace, modelName);
90
+ };
91
+ // Retrieves primary key values from a model
92
+ IndexedDBAdapter.prototype.getIndexKeyValuesFromModel = function (model) {
93
+ var modelConstructor = Object.getPrototypeOf(model)
94
+ .constructor;
95
+ var namespaceName = this.namespaceResolver(modelConstructor);
96
+ var keys = getIndexKeys(this.schema.namespaces[namespaceName], modelConstructor.name);
97
+ return extractPrimaryKeyValues(model, keys);
98
+ };
86
99
  IndexedDBAdapter.prototype.checkPrivate = function () {
87
100
  return __awaiter(this, void 0, void 0, function () {
88
101
  var isPrivate;
@@ -105,14 +118,12 @@ var IndexedDBAdapter = /** @class */ (function () {
105
118
  });
106
119
  });
107
120
  };
108
- IndexedDBAdapter.prototype.getStorenameForModel = function (modelConstructor) {
109
- var namespace = this.namespaceResolver(modelConstructor);
110
- var modelName = modelConstructor.name;
111
- return this.getStorename(namespace, modelName);
112
- };
113
- IndexedDBAdapter.prototype.getStorename = function (namespace, modelName) {
114
- var storeName = namespace + "_" + modelName;
115
- return storeName;
121
+ IndexedDBAdapter.prototype.getNamespaceAndModelFromStorename = function (storeName) {
122
+ var _a = __read(storeName.split('_')), namespaceName = _a[0], modelNameArr = _a.slice(1);
123
+ return {
124
+ namespaceName: namespaceName,
125
+ modelName: modelNameArr.join('_'),
126
+ };
116
127
  };
117
128
  IndexedDBAdapter.prototype.setUp = function (theSchema, namespaceResolver, modelInstanceCreator, getModelConstructorByModelName, sessionId) {
118
129
  return __awaiter(this, void 0, void 0, function () {
@@ -145,79 +156,76 @@ var IndexedDBAdapter = /** @class */ (function () {
145
156
  case 5:
146
157
  _b.trys.push([5, 8, , 9]);
147
158
  if (!!this.db) return [3 /*break*/, 7];
148
- VERSION = 2;
159
+ VERSION = 3;
149
160
  _a = this;
150
161
  return [4 /*yield*/, idb.openDB(this.dbName, VERSION, {
151
162
  upgrade: function (db, oldVersion, newVersion, txn) { return __awaiter(_this, void 0, void 0, function () {
152
- var _a, _b, storeName, origStore, tmpName, newStore, cursor, count, e_1_1, error_2;
153
- var e_1, _c;
163
+ var _a, _b, storeName, origStore, tmpName, _c, namespaceName, modelName, newStore, cursor, count, e_1_1, error_2;
164
+ var e_1, _d;
154
165
  var _this = this;
155
- return __generator(this, function (_d) {
156
- switch (_d.label) {
166
+ return __generator(this, function (_e) {
167
+ switch (_e.label) {
157
168
  case 0:
158
169
  if (oldVersion === 0) {
159
170
  Object.keys(theSchema.namespaces).forEach(function (namespaceName) {
160
171
  var namespace = theSchema.namespaces[namespaceName];
161
172
  Object.keys(namespace.models).forEach(function (modelName) {
162
- var storeName = _this.getStorename(namespaceName, modelName);
173
+ var storeName = getStorename(namespaceName, modelName);
163
174
  _this.createObjectStoreForModel(db, namespaceName, storeName, modelName);
164
175
  });
165
176
  });
166
177
  return [2 /*return*/];
167
178
  }
168
- if (!(oldVersion === 1 && newVersion === 2)) return [3 /*break*/, 16];
169
- _d.label = 1;
179
+ if (!((oldVersion === 1 || oldVersion === 2) && newVersion === 3)) return [3 /*break*/, 16];
180
+ _e.label = 1;
170
181
  case 1:
171
- _d.trys.push([1, 14, , 15]);
172
- _d.label = 2;
182
+ _e.trys.push([1, 14, , 15]);
183
+ _e.label = 2;
173
184
  case 2:
174
- _d.trys.push([2, 11, 12, 13]);
185
+ _e.trys.push([2, 11, 12, 13]);
175
186
  _a = __values(txn.objectStoreNames), _b = _a.next();
176
- _d.label = 3;
187
+ _e.label = 3;
177
188
  case 3:
178
189
  if (!!_b.done) return [3 /*break*/, 10];
179
190
  storeName = _b.value;
180
191
  origStore = txn.objectStore(storeName);
181
192
  tmpName = "tmp_" + storeName;
182
193
  origStore.name = tmpName;
183
- newStore = db.createObjectStore(storeName, {
184
- keyPath: undefined,
185
- autoIncrement: true,
186
- });
187
- newStore.createIndex('byId', 'id', { unique: true });
194
+ _c = this.getNamespaceAndModelFromStorename(storeName), namespaceName = _c.namespaceName, modelName = _c.modelName;
195
+ newStore = this.createObjectStoreForModel(db, namespaceName, storeName, modelName);
188
196
  return [4 /*yield*/, origStore.openCursor()];
189
197
  case 4:
190
- cursor = _d.sent();
198
+ cursor = _e.sent();
191
199
  count = 0;
192
- _d.label = 5;
200
+ _e.label = 5;
193
201
  case 5:
194
202
  if (!(cursor && cursor.value)) return [3 /*break*/, 8];
195
203
  // we don't pass key, since they are all new entries in the new store
196
204
  return [4 /*yield*/, newStore.put(cursor.value)];
197
205
  case 6:
198
206
  // we don't pass key, since they are all new entries in the new store
199
- _d.sent();
207
+ _e.sent();
200
208
  return [4 /*yield*/, cursor.continue()];
201
209
  case 7:
202
- cursor = _d.sent();
210
+ cursor = _e.sent();
203
211
  count++;
204
212
  return [3 /*break*/, 5];
205
213
  case 8:
206
214
  // delete original
207
215
  db.deleteObjectStore(tmpName);
208
216
  logger.debug(count + " " + storeName + " records migrated");
209
- _d.label = 9;
217
+ _e.label = 9;
210
218
  case 9:
211
219
  _b = _a.next();
212
220
  return [3 /*break*/, 3];
213
221
  case 10: return [3 /*break*/, 13];
214
222
  case 11:
215
- e_1_1 = _d.sent();
223
+ e_1_1 = _e.sent();
216
224
  e_1 = { error: e_1_1 };
217
225
  return [3 /*break*/, 13];
218
226
  case 12:
219
227
  try {
220
- if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
228
+ if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
221
229
  }
222
230
  finally { if (e_1) throw e_1.error; }
223
231
  return [7 /*endfinally*/];
@@ -232,7 +240,7 @@ var IndexedDBAdapter = /** @class */ (function () {
232
240
  .map(function (modelName) {
233
241
  return [
234
242
  modelName,
235
- _this.getStorename(namespaceName, modelName),
243
+ getStorename(namespaceName, modelName),
236
244
  ];
237
245
  })
238
246
  .filter(function (_a) {
@@ -246,7 +254,7 @@ var IndexedDBAdapter = /** @class */ (function () {
246
254
  });
247
255
  return [3 /*break*/, 15];
248
256
  case 14:
249
- error_2 = _d.sent();
257
+ error_2 = _e.sent();
250
258
  logger.error('Error migrating IndexedDB data', error_2);
251
259
  txn.abort();
252
260
  throw error_2;
@@ -270,7 +278,7 @@ var IndexedDBAdapter = /** @class */ (function () {
270
278
  });
271
279
  });
272
280
  };
273
- IndexedDBAdapter.prototype._get = function (storeOrStoreName, id) {
281
+ IndexedDBAdapter.prototype._get = function (storeOrStoreName, keyArr) {
274
282
  return __awaiter(this, void 0, void 0, function () {
275
283
  var index, storeName, store, result;
276
284
  return __generator(this, function (_a) {
@@ -278,13 +286,13 @@ var IndexedDBAdapter = /** @class */ (function () {
278
286
  case 0:
279
287
  if (typeof storeOrStoreName === 'string') {
280
288
  storeName = storeOrStoreName;
281
- index = this.db.transaction(storeName, 'readonly').store.index('byId');
289
+ index = this.db.transaction(storeName, 'readonly').store.index('byPk');
282
290
  }
283
291
  else {
284
292
  store = storeOrStoreName;
285
- index = store.index('byId');
293
+ index = store.index('byPk');
286
294
  }
287
- return [4 /*yield*/, index.get(id)];
295
+ return [4 /*yield*/, index.get(keyArr)];
288
296
  case 1:
289
297
  result = _a.sent();
290
298
  return [2 /*return*/, result];
@@ -295,7 +303,7 @@ var IndexedDBAdapter = /** @class */ (function () {
295
303
  IndexedDBAdapter.prototype.save = function (model, condition) {
296
304
  var e_2, _a;
297
305
  return __awaiter(this, void 0, void 0, function () {
298
- 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;
306
+ 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;
299
307
  var _this = this;
300
308
  return __generator(this, function (_b) {
301
309
  switch (_b.label) {
@@ -305,18 +313,20 @@ var IndexedDBAdapter = /** @class */ (function () {
305
313
  modelConstructor = Object.getPrototypeOf(model)
306
314
  .constructor;
307
315
  storeName = this.getStorenameForModel(modelConstructor);
308
- connectedModels = traverseModel(modelConstructor.name, model, this.schema.namespaces[this.namespaceResolver(modelConstructor)], this.modelInstanceCreator, this.getModelConstructorByModelName);
309
316
  namespaceName = this.namespaceResolver(modelConstructor);
317
+ connectedModels = traverseModel(modelConstructor.name, model, this.schema.namespaces[namespaceName], this.modelInstanceCreator, this.getModelConstructorByModelName);
310
318
  set = new Set();
311
319
  connectionStoreNames = Object.values(connectedModels).map(function (_a) {
312
320
  var modelName = _a.modelName, item = _a.item, instance = _a.instance;
313
- var storeName = _this.getStorename(namespaceName, modelName);
321
+ var storeName = getStorename(namespaceName, modelName);
314
322
  set.add(storeName);
315
- return { storeName: storeName, item: item, instance: instance };
323
+ var keys = getIndexKeys(_this.schema.namespaces[namespaceName], modelName);
324
+ return { storeName: storeName, item: item, instance: instance, keys: keys };
316
325
  });
317
326
  tx = this.db.transaction(__spread([storeName], Array.from(set.values())), 'readwrite');
318
327
  store = tx.objectStore(storeName);
319
- return [4 /*yield*/, this._get(store, model.id)];
328
+ keyValues = this.getIndexKeyValuesFromModel(model);
329
+ return [4 /*yield*/, this._get(store, keyValues)];
320
330
  case 2:
321
331
  fromDB = _b.sent();
322
332
  if (condition && fromDB) {
@@ -339,15 +349,20 @@ var IndexedDBAdapter = /** @class */ (function () {
339
349
  case 5:
340
350
  if (!(connectionStoreNames_1_1 = _b.sent(), !connectionStoreNames_1_1.done)) return [3 /*break*/, 10];
341
351
  resItem = connectionStoreNames_1_1.value;
342
- storeName_1 = resItem.storeName, item = resItem.item, instance = resItem.instance;
352
+ storeName_1 = resItem.storeName, item = resItem.item, instance = resItem.instance, keys = resItem.keys;
343
353
  store_1 = tx.objectStore(storeName_1);
344
- id = item.id;
345
- return [4 /*yield*/, this._get(store_1, id)];
354
+ itemKeyValues = keys.map(function (key) {
355
+ var value = item[key];
356
+ return value;
357
+ });
358
+ return [4 /*yield*/, this._get(store_1, itemKeyValues)];
346
359
  case 6:
347
360
  fromDB_1 = _b.sent();
348
361
  opType = fromDB_1 === undefined ? OpType.INSERT : OpType.UPDATE;
349
- if (!(id === model.id || opType === OpType.INSERT)) return [3 /*break*/, 9];
350
- return [4 /*yield*/, store_1.index('byId').getKey(item.id)];
362
+ modelKeyValues = this.getIndexKeyValuesFromModel(model);
363
+ if (!(keysEqual(itemKeyValues, modelKeyValues) ||
364
+ opType === OpType.INSERT)) return [3 /*break*/, 9];
365
+ return [4 /*yield*/, store_1.index('byPk').getKey(itemKeyValues)];
351
366
  case 7:
352
367
  key = _b.sent();
353
368
  return [4 /*yield*/, store_1.put(item, key)];
@@ -385,7 +400,7 @@ var IndexedDBAdapter = /** @class */ (function () {
385
400
  var records_1, records_1_1, records_2, records_2_1;
386
401
  var e_3, _a, e_4, _b, e_5, _c;
387
402
  return __awaiter(this, void 0, void 0, function () {
388
- 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;
403
+ 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;
389
404
  var _this = this;
390
405
  return __generator(this, function (_e) {
391
406
  switch (_e.label) {
@@ -394,7 +409,7 @@ var IndexedDBAdapter = /** @class */ (function () {
394
409
  relations = namespace.relationships[srcModelName].relationTypes;
395
410
  connectionStoreNames = relations.map(function (_a) {
396
411
  var modelName = _a.modelName;
397
- return _this.getStorename(namespaceName, modelName);
412
+ return getStorename(namespaceName, modelName);
398
413
  });
399
414
  modelConstructor = this.getModelConstructorByModelName(namespaceName, srcModelName);
400
415
  if (connectionStoreNames.length === 0) {
@@ -405,122 +420,170 @@ var IndexedDBAdapter = /** @class */ (function () {
405
420
  tx = this.db.transaction(__spread(connectionStoreNames), 'readonly');
406
421
  _e.label = 1;
407
422
  case 1:
408
- _e.trys.push([1, 34, 35, 40]);
423
+ _e.trys.push([1, 38, 39, 44]);
409
424
  relations_1 = __asyncValues(relations);
410
425
  _e.label = 2;
411
426
  case 2: return [4 /*yield*/, relations_1.next()];
412
427
  case 3:
413
- if (!(relations_1_1 = _e.sent(), !relations_1_1.done)) return [3 /*break*/, 33];
428
+ if (!(relations_1_1 = _e.sent(), !relations_1_1.done)) return [3 /*break*/, 37];
414
429
  relation = relations_1_1.value;
415
- fieldName = relation.fieldName, modelName = relation.modelName, targetName = relation.targetName;
416
- storeName = this.getStorename(namespaceName, modelName);
430
+ fieldName = relation.fieldName, modelName = relation.modelName, targetName = relation.targetName, targetNames = relation.targetNames;
431
+ storeName = getStorename(namespaceName, modelName);
417
432
  store = tx.objectStore(storeName);
418
433
  modelConstructor_1 = this.getModelConstructorByModelName(namespaceName, modelName);
419
434
  _d = relation.relationType;
420
435
  switch (_d) {
421
436
  case 'HAS_ONE': return [3 /*break*/, 4];
422
- case 'BELONGS_TO': return [3 /*break*/, 17];
423
- case 'HAS_MANY': return [3 /*break*/, 30];
437
+ case 'BELONGS_TO': return [3 /*break*/, 19];
438
+ case 'HAS_MANY': return [3 /*break*/, 34];
424
439
  }
425
- return [3 /*break*/, 31];
440
+ return [3 /*break*/, 35];
426
441
  case 4:
427
- _e.trys.push([4, 10, 11, 16]);
442
+ _e.trys.push([4, 12, 13, 18]);
428
443
  records_1 = __asyncValues(records);
429
444
  _e.label = 5;
430
445
  case 5: return [4 /*yield*/, records_1.next()];
431
446
  case 6:
432
- if (!(records_1_1 = _e.sent(), !records_1_1.done)) return [3 /*break*/, 9];
447
+ if (!(records_1_1 = _e.sent(), !records_1_1.done)) return [3 /*break*/, 11];
433
448
  recordItem = records_1_1.value;
434
- getByfield = recordItem[targetName] ? targetName : fieldName;
435
- if (!recordItem[getByfield])
436
- return [3 /*break*/, 9];
437
- return [4 /*yield*/, this._get(store, recordItem[getByfield])];
449
+ if (!(targetNames === null || targetNames === void 0 ? void 0 : targetNames.length)) return [3 /*break*/, 8];
450
+ getByFields = [];
451
+ allPresent = void 0;
452
+ // iterate through all targetnames to make sure they are all present in the recordItem
453
+ allPresent = targetNames.every(function (targetName) {
454
+ return recordItem[targetName] != null;
455
+ });
456
+ if (!allPresent) {
457
+ return [3 /*break*/, 11];
458
+ }
459
+ getByFields = targetNames;
460
+ keys = getByFields.map(function (getByField) { return recordItem[getByField]; });
461
+ return [4 /*yield*/, this._get(store, keys)];
438
462
  case 7:
439
463
  connectionRecord = _e.sent();
440
464
  recordItem[fieldName] =
441
465
  connectionRecord &&
442
466
  this.modelInstanceCreator(modelConstructor_1, connectionRecord);
443
- _e.label = 8;
444
- case 8: return [3 /*break*/, 5];
445
- case 9: return [3 /*break*/, 16];
446
- case 10:
467
+ return [3 /*break*/, 10];
468
+ case 8:
469
+ getByfield = recordItem[targetName]
470
+ ? targetName
471
+ : fieldName;
472
+ // We break here, because the recordItem does not have 'team', the `getByField`
473
+ // extract the keys on the related model.
474
+ if (!recordItem[getByfield])
475
+ return [3 /*break*/, 11];
476
+ key = [recordItem[getByfield]];
477
+ return [4 /*yield*/, this._get(store, key)];
478
+ case 9:
479
+ connectionRecord = _e.sent();
480
+ recordItem[fieldName] =
481
+ connectionRecord &&
482
+ this.modelInstanceCreator(modelConstructor_1, connectionRecord);
483
+ _e.label = 10;
484
+ case 10: return [3 /*break*/, 5];
485
+ case 11: return [3 /*break*/, 18];
486
+ case 12:
447
487
  e_4_1 = _e.sent();
448
488
  e_4 = { error: e_4_1 };
449
- return [3 /*break*/, 16];
450
- case 11:
451
- _e.trys.push([11, , 14, 15]);
452
- if (!(records_1_1 && !records_1_1.done && (_b = records_1.return))) return [3 /*break*/, 13];
489
+ return [3 /*break*/, 18];
490
+ case 13:
491
+ _e.trys.push([13, , 16, 17]);
492
+ if (!(records_1_1 && !records_1_1.done && (_b = records_1.return))) return [3 /*break*/, 15];
453
493
  return [4 /*yield*/, _b.call(records_1)];
454
- case 12:
455
- _e.sent();
456
- _e.label = 13;
457
- case 13: return [3 /*break*/, 15];
458
494
  case 14:
495
+ _e.sent();
496
+ _e.label = 15;
497
+ case 15: return [3 /*break*/, 17];
498
+ case 16:
459
499
  if (e_4) throw e_4.error;
460
500
  return [7 /*endfinally*/];
461
- case 15: return [7 /*endfinally*/];
462
- case 16: return [3 /*break*/, 32];
463
- case 17:
464
- _e.trys.push([17, 23, 24, 29]);
465
- records_2 = __asyncValues(records);
466
- _e.label = 18;
467
- case 18: return [4 /*yield*/, records_2.next()];
501
+ case 17: return [7 /*endfinally*/];
502
+ case 18: return [3 /*break*/, 36];
468
503
  case 19:
469
- if (!(records_2_1 = _e.sent(), !records_2_1.done)) return [3 /*break*/, 22];
504
+ _e.trys.push([19, 27, 28, 33]);
505
+ records_2 = __asyncValues(records);
506
+ _e.label = 20;
507
+ case 20: return [4 /*yield*/, records_2.next()];
508
+ case 21:
509
+ if (!(records_2_1 = _e.sent(), !records_2_1.done)) return [3 /*break*/, 26];
470
510
  recordItem = records_2_1.value;
471
- if (!recordItem[targetName]) return [3 /*break*/, 21];
472
- return [4 /*yield*/, this._get(store, recordItem[targetName])];
473
- case 20:
511
+ if (!(targetNames === null || targetNames === void 0 ? void 0 : targetNames.length)) return [3 /*break*/, 23];
512
+ allPresent = void 0;
513
+ // iterate through all targetnames to make sure they are all present in the recordItem
514
+ allPresent = targetNames.every(function (targetName) {
515
+ return recordItem[targetName] != null;
516
+ });
517
+ // If not present, there is not yet a connected record
518
+ if (!allPresent) {
519
+ return [3 /*break*/, 26];
520
+ }
521
+ keys = targetNames.map(function (targetName) { return recordItem[targetName]; });
522
+ return [4 /*yield*/, this._get(store, keys)];
523
+ case 22:
474
524
  connectionRecord = _e.sent();
475
525
  recordItem[fieldName] =
476
526
  connectionRecord &&
477
527
  this.modelInstanceCreator(modelConstructor_1, connectionRecord);
478
- delete recordItem[targetName];
479
- _e.label = 21;
480
- case 21: return [3 /*break*/, 18];
481
- case 22: return [3 /*break*/, 29];
528
+ targetNames === null || targetNames === void 0 ? void 0 : targetNames.map(function (targetName) {
529
+ delete recordItem[targetName];
530
+ });
531
+ return [3 /*break*/, 25];
482
532
  case 23:
533
+ if (!recordItem[targetName]) return [3 /*break*/, 25];
534
+ key = [recordItem[targetName]];
535
+ return [4 /*yield*/, this._get(store, key)];
536
+ case 24:
537
+ connectionRecord = _e.sent();
538
+ recordItem[fieldName] =
539
+ connectionRecord &&
540
+ this.modelInstanceCreator(modelConstructor_1, connectionRecord);
541
+ delete recordItem[targetName];
542
+ _e.label = 25;
543
+ case 25: return [3 /*break*/, 20];
544
+ case 26: return [3 /*break*/, 33];
545
+ case 27:
483
546
  e_5_1 = _e.sent();
484
547
  e_5 = { error: e_5_1 };
485
- return [3 /*break*/, 29];
486
- case 24:
487
- _e.trys.push([24, , 27, 28]);
488
- if (!(records_2_1 && !records_2_1.done && (_c = records_2.return))) return [3 /*break*/, 26];
548
+ return [3 /*break*/, 33];
549
+ case 28:
550
+ _e.trys.push([28, , 31, 32]);
551
+ if (!(records_2_1 && !records_2_1.done && (_c = records_2.return))) return [3 /*break*/, 30];
489
552
  return [4 /*yield*/, _c.call(records_2)];
490
- case 25:
553
+ case 29:
491
554
  _e.sent();
492
- _e.label = 26;
493
- case 26: return [3 /*break*/, 28];
494
- case 27:
555
+ _e.label = 30;
556
+ case 30: return [3 /*break*/, 32];
557
+ case 31:
495
558
  if (e_5) throw e_5.error;
496
559
  return [7 /*endfinally*/];
497
- case 28: return [7 /*endfinally*/];
498
- case 29: return [3 /*break*/, 32];
499
- case 30:
560
+ case 32: return [7 /*endfinally*/];
561
+ case 33: return [3 /*break*/, 36];
562
+ case 34:
500
563
  // TODO: Lazy loading
501
- return [3 /*break*/, 32];
502
- case 31:
564
+ return [3 /*break*/, 36];
565
+ case 35:
503
566
  exhaustiveCheck(relation.relationType);
504
- return [3 /*break*/, 32];
505
- case 32: return [3 /*break*/, 2];
506
- case 33: return [3 /*break*/, 40];
507
- case 34:
567
+ return [3 /*break*/, 36];
568
+ case 36: return [3 /*break*/, 2];
569
+ case 37: return [3 /*break*/, 44];
570
+ case 38:
508
571
  e_3_1 = _e.sent();
509
572
  e_3 = { error: e_3_1 };
510
- return [3 /*break*/, 40];
511
- case 35:
512
- _e.trys.push([35, , 38, 39]);
513
- if (!(relations_1_1 && !relations_1_1.done && (_a = relations_1.return))) return [3 /*break*/, 37];
573
+ return [3 /*break*/, 44];
574
+ case 39:
575
+ _e.trys.push([39, , 42, 43]);
576
+ if (!(relations_1_1 && !relations_1_1.done && (_a = relations_1.return))) return [3 /*break*/, 41];
514
577
  return [4 /*yield*/, _a.call(relations_1)];
515
- case 36:
578
+ case 40:
516
579
  _e.sent();
517
- _e.label = 37;
518
- case 37: return [3 /*break*/, 39];
519
- case 38:
580
+ _e.label = 41;
581
+ case 41: return [3 /*break*/, 43];
582
+ case 42:
520
583
  if (e_3) throw e_3.error;
521
584
  return [7 /*endfinally*/];
522
- case 39: return [7 /*endfinally*/];
523
- case 40: return [2 /*return*/, records.map(function (record) {
585
+ case 43: return [7 /*endfinally*/];
586
+ case 44: return [2 /*return*/, records.map(function (record) {
524
587
  return _this.modelInstanceCreator(modelConstructor, record);
525
588
  })];
526
589
  }
@@ -529,7 +592,7 @@ var IndexedDBAdapter = /** @class */ (function () {
529
592
  };
530
593
  IndexedDBAdapter.prototype.query = function (modelConstructor, predicate, pagination) {
531
594
  return __awaiter(this, void 0, void 0, function () {
532
- var storeName, namespaceName, predicates, queryById, hasSort, hasPagination, records;
595
+ var storeName, namespaceName, predicates, keyPath, queryByKey, hasSort, hasPagination, records;
533
596
  var _this = this;
534
597
  return __generator(this, function (_a) {
535
598
  switch (_a.label) {
@@ -539,7 +602,8 @@ var IndexedDBAdapter = /** @class */ (function () {
539
602
  storeName = this.getStorenameForModel(modelConstructor);
540
603
  namespaceName = this.namespaceResolver(modelConstructor);
541
604
  predicates = predicate && ModelPredicateCreator.getPredicates(predicate);
542
- queryById = predicates && this.idFromPredicate(predicates);
605
+ keyPath = getIndexKeys(this.schema.namespaces[namespaceName], modelConstructor.name);
606
+ queryByKey = predicates && this.keyValueFromPredicate(predicates, keyPath);
543
607
  hasSort = pagination && pagination.sort;
544
608
  hasPagination = pagination && pagination.limit;
545
609
  return [4 /*yield*/, (function () { return __awaiter(_this, void 0, void 0, function () {
@@ -547,8 +611,8 @@ var IndexedDBAdapter = /** @class */ (function () {
547
611
  return __generator(this, function (_a) {
548
612
  switch (_a.label) {
549
613
  case 0:
550
- if (!queryById) return [3 /*break*/, 2];
551
- return [4 /*yield*/, this.getById(storeName, queryById)];
614
+ if (!queryByKey) return [3 /*break*/, 2];
615
+ return [4 /*yield*/, this.getByKey(storeName, queryByKey)];
552
616
  case 1:
553
617
  record = _a.sent();
554
618
  return [2 /*return*/, record ? [record] : []];
@@ -580,12 +644,12 @@ var IndexedDBAdapter = /** @class */ (function () {
580
644
  });
581
645
  });
582
646
  };
583
- IndexedDBAdapter.prototype.getById = function (storeName, id) {
647
+ IndexedDBAdapter.prototype.getByKey = function (storeName, keyValue) {
584
648
  return __awaiter(this, void 0, void 0, function () {
585
649
  var record;
586
650
  return __generator(this, function (_a) {
587
651
  switch (_a.label) {
588
- case 0: return [4 /*yield*/, this._get(storeName, id)];
652
+ case 0: return [4 /*yield*/, this._get(storeName, keyValue)];
589
653
  case 1:
590
654
  record = _a.sent();
591
655
  return [2 /*return*/, record];
@@ -603,11 +667,31 @@ var IndexedDBAdapter = /** @class */ (function () {
603
667
  });
604
668
  });
605
669
  };
606
- IndexedDBAdapter.prototype.idFromPredicate = function (predicates) {
670
+ IndexedDBAdapter.prototype.keyValueFromPredicate = function (predicates, keyPath) {
671
+ var e_6, _a;
607
672
  var predicateObjs = predicates.predicates;
608
- var idPredicate = predicateObjs.length === 1 &&
609
- predicateObjs.find(function (p) { return isPredicateObj(p) && p.field === 'id' && p.operator === 'eq'; });
610
- return idPredicate && idPredicate.operand;
673
+ if (predicateObjs.length !== keyPath.length) {
674
+ return;
675
+ }
676
+ var keyValues = [];
677
+ var _loop_1 = function (key) {
678
+ var predicateObj = predicateObjs.find(function (p) { return isPredicateObj(p) && p.field === key && p.operator === 'eq'; });
679
+ predicateObj && keyValues.push(predicateObj.operand);
680
+ };
681
+ try {
682
+ for (var keyPath_1 = __values(keyPath), keyPath_1_1 = keyPath_1.next(); !keyPath_1_1.done; keyPath_1_1 = keyPath_1.next()) {
683
+ var key = keyPath_1_1.value;
684
+ _loop_1(key);
685
+ }
686
+ }
687
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
688
+ finally {
689
+ try {
690
+ if (keyPath_1_1 && !keyPath_1_1.done && (_a = keyPath_1.return)) _a.call(keyPath_1);
691
+ }
692
+ finally { if (e_6) throw e_6.error; }
693
+ }
694
+ return keyValues.length === keyPath.length ? keyValues : undefined;
611
695
  };
612
696
  IndexedDBAdapter.prototype.filterOnPredicate = function (storeName, predicates) {
613
697
  return __awaiter(this, void 0, void 0, function () {
@@ -713,7 +797,7 @@ var IndexedDBAdapter = /** @class */ (function () {
713
797
  };
714
798
  IndexedDBAdapter.prototype.delete = function (modelOrModelConstructor, condition) {
715
799
  return __awaiter(this, void 0, void 0, function () {
716
- 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;
800
+ 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;
717
801
  return __generator(this, function (_a) {
718
802
  switch (_a.label) {
719
803
  case 0: return [4 /*yield*/, this.checkPrivate()];
@@ -762,12 +846,13 @@ var IndexedDBAdapter = /** @class */ (function () {
762
846
  model = modelOrModelConstructor;
763
847
  modelConstructor = Object.getPrototypeOf(model)
764
848
  .constructor;
765
- nameSpace = this.namespaceResolver(modelConstructor);
849
+ namespaceName = this.namespaceResolver(modelConstructor);
766
850
  storeName = this.getStorenameForModel(modelConstructor);
767
851
  if (!condition) return [3 /*break*/, 13];
768
852
  tx = this.db.transaction([storeName], 'readwrite');
769
853
  store = tx.objectStore(storeName);
770
- return [4 /*yield*/, this._get(store, model.id)];
854
+ keyValues = this.getIndexKeyValuesFromModel(model);
855
+ return [4 /*yield*/, this._get(store, keyValues)];
771
856
  case 10:
772
857
  fromDB = _a.sent();
773
858
  if (fromDB === undefined) {
@@ -786,16 +871,14 @@ var IndexedDBAdapter = /** @class */ (function () {
786
871
  return [4 /*yield*/, tx.done];
787
872
  case 11:
788
873
  _a.sent();
789
- relations = this.schema.namespaces[nameSpace].relationships[modelConstructor.name]
790
- .relationTypes;
791
- return [4 /*yield*/, this.deleteTraverse(relations, [model], modelConstructor.name, nameSpace, deleteQueue)];
874
+ relations = this.schema.namespaces[namespaceName].relationships[modelConstructor.name].relationTypes;
875
+ return [4 /*yield*/, this.deleteTraverse(relations, [model], modelConstructor.name, namespaceName, deleteQueue)];
792
876
  case 12:
793
877
  _a.sent();
794
878
  return [3 /*break*/, 15];
795
879
  case 13:
796
- relations = this.schema.namespaces[nameSpace].relationships[modelConstructor.name]
797
- .relationTypes;
798
- return [4 /*yield*/, this.deleteTraverse(relations, [model], modelConstructor.name, nameSpace, deleteQueue)];
880
+ relations = this.schema.namespaces[namespaceName].relationships[modelConstructor.name].relationTypes;
881
+ return [4 /*yield*/, this.deleteTraverse(relations, [model], modelConstructor.name, namespaceName, deleteQueue)];
799
882
  case 14:
800
883
  _a.sent();
801
884
  _a.label = 15;
@@ -814,9 +897,9 @@ var IndexedDBAdapter = /** @class */ (function () {
814
897
  };
815
898
  IndexedDBAdapter.prototype.deleteItem = function (deleteQueue) {
816
899
  var deleteQueue_1, deleteQueue_1_1;
817
- var e_6, _a, e_7, _b;
900
+ var e_7, _a, e_8, _b;
818
901
  return __awaiter(this, void 0, void 0, function () {
819
- var connectionStoreNames, tx, deleteItem, storeName, items, store, items_1, items_1_1, item, key, e_7_1, e_6_1;
902
+ var connectionStoreNames, tx, deleteItem, storeName, items, store, items_1, items_1_1, item, key, keyValues, itemKey, e_8_1, e_7_1;
820
903
  return __generator(this, function (_c) {
821
904
  switch (_c.label) {
822
905
  case 0:
@@ -848,11 +931,14 @@ var IndexedDBAdapter = /** @class */ (function () {
848
931
  if (!item) return [3 /*break*/, 12];
849
932
  key = void 0;
850
933
  if (!(typeof item === 'object')) return [3 /*break*/, 8];
851
- return [4 /*yield*/, store.index('byId').getKey(item['id'])];
934
+ keyValues = this.getIndexKeyValuesFromModel(item);
935
+ return [4 /*yield*/, store.index('byPk').getKey(keyValues)];
852
936
  case 7:
853
937
  key = _c.sent();
854
938
  return [3 /*break*/, 10];
855
- case 8: return [4 /*yield*/, store.index('byId').getKey(item.toString())];
939
+ case 8:
940
+ itemKey = [item.toString()];
941
+ return [4 /*yield*/, store.index('byPk').getKey([itemKey])];
856
942
  case 9:
857
943
  key = _c.sent();
858
944
  _c.label = 10;
@@ -865,8 +951,8 @@ var IndexedDBAdapter = /** @class */ (function () {
865
951
  case 12: return [3 /*break*/, 5];
866
952
  case 13: return [3 /*break*/, 20];
867
953
  case 14:
868
- e_7_1 = _c.sent();
869
- e_7 = { error: e_7_1 };
954
+ e_8_1 = _c.sent();
955
+ e_8 = { error: e_8_1 };
870
956
  return [3 /*break*/, 20];
871
957
  case 15:
872
958
  _c.trys.push([15, , 18, 19]);
@@ -877,14 +963,14 @@ var IndexedDBAdapter = /** @class */ (function () {
877
963
  _c.label = 17;
878
964
  case 17: return [3 /*break*/, 19];
879
965
  case 18:
880
- if (e_7) throw e_7.error;
966
+ if (e_8) throw e_8.error;
881
967
  return [7 /*endfinally*/];
882
968
  case 19: return [7 /*endfinally*/];
883
969
  case 20: return [3 /*break*/, 2];
884
970
  case 21: return [3 /*break*/, 28];
885
971
  case 22:
886
- e_6_1 = _c.sent();
887
- e_6 = { error: e_6_1 };
972
+ e_7_1 = _c.sent();
973
+ e_7 = { error: e_7_1 };
888
974
  return [3 /*break*/, 28];
889
975
  case 23:
890
976
  _c.trys.push([23, , 26, 27]);
@@ -895,7 +981,7 @@ var IndexedDBAdapter = /** @class */ (function () {
895
981
  _c.label = 25;
896
982
  case 25: return [3 /*break*/, 27];
897
983
  case 26:
898
- if (e_6) throw e_6.error;
984
+ if (e_7) throw e_7.error;
899
985
  return [7 /*endfinally*/];
900
986
  case 27: return [7 /*endfinally*/];
901
987
  case 28: return [2 /*return*/];
@@ -905,145 +991,178 @@ var IndexedDBAdapter = /** @class */ (function () {
905
991
  };
906
992
  IndexedDBAdapter.prototype.deleteTraverse = function (relations, models, srcModel, nameSpace, deleteQueue) {
907
993
  var relations_2, relations_2_1, models_1, models_1_1, models_2, models_2_1;
908
- var e_8, _a, e_9, _b, e_10, _c;
994
+ var e_9, _a, e_10, _b, e_11, _c;
909
995
  return __awaiter(this, void 0, void 0, function () {
910
- 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;
996
+ 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;
911
997
  var _this = this;
912
998
  return __generator(this, function (_e) {
913
999
  switch (_e.label) {
914
1000
  case 0:
915
- _e.trys.push([0, 35, 36, 41]);
1001
+ _e.trys.push([0, 38, 39, 44]);
916
1002
  relations_2 = __asyncValues(relations);
917
1003
  _e.label = 1;
918
1004
  case 1: return [4 /*yield*/, relations_2.next()];
919
1005
  case 2:
920
- if (!(relations_2_1 = _e.sent(), !relations_2_1.done)) return [3 /*break*/, 34];
1006
+ if (!(relations_2_1 = _e.sent(), !relations_2_1.done)) return [3 /*break*/, 37];
921
1007
  rel = relations_2_1.value;
922
- relationType = rel.relationType, fieldName = rel.fieldName, modelName = rel.modelName, targetName = rel.targetName;
923
- storeName = this.getStorename(nameSpace, modelName);
924
- index = getIndex(this.schema.namespaces[nameSpace].relationships[modelName]
925
- .relationTypes, srcModel) ||
926
- // if we were unable to find an index via relationTypes
927
- // i.e. for keyName connections, attempt to find one by the
928
- // associatedWith property
929
- getIndexFromAssociation(this.schema.namespaces[nameSpace].relationships[modelName].indexes, rel.associatedWith);
1008
+ relationType = rel.relationType, modelName = rel.modelName, targetName = rel.targetName, targetNames = rel.targetNames, associatedWith = rel.associatedWith;
1009
+ storeName = getStorename(nameSpace, modelName);
930
1010
  _d = relationType;
931
1011
  switch (_d) {
932
1012
  case 'HAS_ONE': return [3 /*break*/, 3];
933
- case 'HAS_MANY': return [3 /*break*/, 17];
934
- case 'BELONGS_TO': return [3 /*break*/, 31];
1013
+ case 'HAS_MANY': return [3 /*break*/, 20];
1014
+ case 'BELONGS_TO': return [3 /*break*/, 34];
935
1015
  }
936
- return [3 /*break*/, 32];
1016
+ return [3 /*break*/, 35];
937
1017
  case 3:
938
- _e.trys.push([3, 10, 11, 16]);
1018
+ _e.trys.push([3, 13, 14, 19]);
939
1019
  models_1 = __asyncValues(models);
940
1020
  _e.label = 4;
941
1021
  case 4: return [4 /*yield*/, models_1.next()];
942
1022
  case 5:
943
- if (!(models_1_1 = _e.sent(), !models_1_1.done)) return [3 /*break*/, 9];
1023
+ if (!(models_1_1 = _e.sent(), !models_1_1.done)) return [3 /*break*/, 12];
944
1024
  model = models_1_1.value;
945
- hasOneIndex = index || 'byId';
946
- hasOneCustomField = targetName in model;
947
- value = hasOneCustomField ? model[targetName] : model.id;
948
- if (!value)
949
- return [3 /*break*/, 9];
1025
+ hasOneIndex = 'byPk';
1026
+ if (!(targetNames === null || targetNames === void 0 ? void 0 : targetNames.length)) return [3 /*break*/, 8];
1027
+ values = targetNames.map(function (targetName) { return model[targetName]; });
1028
+ if (values.length === 0)
1029
+ return [3 /*break*/, 12];
950
1030
  return [4 /*yield*/, this.db
951
1031
  .transaction(storeName, 'readwrite')
952
1032
  .objectStore(storeName)
953
1033
  .index(hasOneIndex)
954
- .get(value)];
1034
+ .get(values)];
955
1035
  case 6:
956
1036
  recordToDelete = (_e.sent());
957
1037
  return [4 /*yield*/, this.deleteTraverse(this.schema.namespaces[nameSpace].relationships[modelName]
958
1038
  .relationTypes, recordToDelete ? [recordToDelete] : [], modelName, nameSpace, deleteQueue)];
959
1039
  case 7:
960
1040
  _e.sent();
961
- _e.label = 8;
962
- case 8: return [3 /*break*/, 4];
963
- case 9: return [3 /*break*/, 16];
1041
+ return [3 /*break*/, 12];
1042
+ case 8:
1043
+ index = void 0;
1044
+ values = void 0;
1045
+ if (targetName && targetName in model) {
1046
+ index = hasOneIndex;
1047
+ value = model[targetName];
1048
+ values = [value];
1049
+ }
1050
+ else {
1051
+ // backwards compatability for older versions of codegen that did not emit targetName for HAS_ONE relations
1052
+ // TODO: can we deprecate this? it's been ~2 years since codegen started including targetName for HAS_ONE
1053
+ // If we deprecate, we'll need to re-gen the MIPR in __tests__/schema.ts > newSchema
1054
+ // otherwise some unit tests will fail
1055
+ index = getIndex(this.schema.namespaces[nameSpace].relationships[modelName]
1056
+ .relationTypes, srcModel);
1057
+ values = this.getIndexKeyValuesFromModel(model);
1058
+ }
1059
+ if (!values || !index)
1060
+ return [3 /*break*/, 12];
1061
+ return [4 /*yield*/, this.db
1062
+ .transaction(storeName, 'readwrite')
1063
+ .objectStore(storeName)
1064
+ .index(index)
1065
+ .get(values)];
1066
+ case 9:
1067
+ recordToDelete = (_e.sent());
1068
+ return [4 /*yield*/, this.deleteTraverse(this.schema.namespaces[nameSpace].relationships[modelName]
1069
+ .relationTypes, recordToDelete ? [recordToDelete] : [], modelName, nameSpace, deleteQueue)];
964
1070
  case 10:
965
- e_9_1 = _e.sent();
966
- e_9 = { error: e_9_1 };
967
- return [3 /*break*/, 16];
968
- case 11:
969
- _e.trys.push([11, , 14, 15]);
970
- if (!(models_1_1 && !models_1_1.done && (_b = models_1.return))) return [3 /*break*/, 13];
971
- return [4 /*yield*/, _b.call(models_1)];
972
- case 12:
973
1071
  _e.sent();
974
- _e.label = 13;
975
- case 13: return [3 /*break*/, 15];
1072
+ _e.label = 11;
1073
+ case 11: return [3 /*break*/, 4];
1074
+ case 12: return [3 /*break*/, 19];
1075
+ case 13:
1076
+ e_10_1 = _e.sent();
1077
+ e_10 = { error: e_10_1 };
1078
+ return [3 /*break*/, 19];
976
1079
  case 14:
977
- if (e_9) throw e_9.error;
978
- return [7 /*endfinally*/];
979
- case 15: return [7 /*endfinally*/];
980
- case 16: return [3 /*break*/, 33];
1080
+ _e.trys.push([14, , 17, 18]);
1081
+ if (!(models_1_1 && !models_1_1.done && (_b = models_1.return))) return [3 /*break*/, 16];
1082
+ return [4 /*yield*/, _b.call(models_1)];
1083
+ case 15:
1084
+ _e.sent();
1085
+ _e.label = 16;
1086
+ case 16: return [3 /*break*/, 18];
981
1087
  case 17:
982
- _e.trys.push([17, 24, 25, 30]);
1088
+ if (e_10) throw e_10.error;
1089
+ return [7 /*endfinally*/];
1090
+ case 18: return [7 /*endfinally*/];
1091
+ case 19: return [3 /*break*/, 36];
1092
+ case 20:
1093
+ _e.trys.push([20, 27, 28, 33]);
983
1094
  models_2 = __asyncValues(models);
984
- _e.label = 18;
985
- case 18: return [4 /*yield*/, models_2.next()];
986
- case 19:
987
- if (!(models_2_1 = _e.sent(), !models_2_1.done)) return [3 /*break*/, 23];
1095
+ _e.label = 21;
1096
+ case 21: return [4 /*yield*/, models_2.next()];
1097
+ case 22:
1098
+ if (!(models_2_1 = _e.sent(), !models_2_1.done)) return [3 /*break*/, 26];
988
1099
  model = models_2_1.value;
1100
+ index =
1101
+ // explicit bi-directional @hasMany and @manyToMany
1102
+ getIndex(this.schema.namespaces[nameSpace].relationships[modelName]
1103
+ .relationTypes, srcModel) ||
1104
+ // uni and/or implicit @hasMany
1105
+ getIndexFromAssociation(this.schema.namespaces[nameSpace].relationships[modelName]
1106
+ .indexes, associatedWith);
1107
+ keyValues = this.getIndexKeyValuesFromModel(model);
989
1108
  return [4 /*yield*/, this.db
990
1109
  .transaction(storeName, 'readwrite')
991
1110
  .objectStore(storeName)
992
1111
  .index(index)
993
- .getAll(model['id'])];
994
- case 20:
1112
+ .getAll(keyValues)];
1113
+ case 23:
995
1114
  childrenArray = _e.sent();
996
1115
  return [4 /*yield*/, this.deleteTraverse(this.schema.namespaces[nameSpace].relationships[modelName]
997
1116
  .relationTypes, childrenArray, modelName, nameSpace, deleteQueue)];
998
- case 21:
999
- _e.sent();
1000
- _e.label = 22;
1001
- case 22: return [3 /*break*/, 18];
1002
- case 23: return [3 /*break*/, 30];
1003
1117
  case 24:
1004
- e_10_1 = _e.sent();
1005
- e_10 = { error: e_10_1 };
1006
- return [3 /*break*/, 30];
1007
- case 25:
1008
- _e.trys.push([25, , 28, 29]);
1009
- if (!(models_2_1 && !models_2_1.done && (_c = models_2.return))) return [3 /*break*/, 27];
1010
- return [4 /*yield*/, _c.call(models_2)];
1011
- case 26:
1012
1118
  _e.sent();
1013
- _e.label = 27;
1014
- case 27: return [3 /*break*/, 29];
1119
+ _e.label = 25;
1120
+ case 25: return [3 /*break*/, 21];
1121
+ case 26: return [3 /*break*/, 33];
1122
+ case 27:
1123
+ e_11_1 = _e.sent();
1124
+ e_11 = { error: e_11_1 };
1125
+ return [3 /*break*/, 33];
1015
1126
  case 28:
1016
- if (e_10) throw e_10.error;
1127
+ _e.trys.push([28, , 31, 32]);
1128
+ if (!(models_2_1 && !models_2_1.done && (_c = models_2.return))) return [3 /*break*/, 30];
1129
+ return [4 /*yield*/, _c.call(models_2)];
1130
+ case 29:
1131
+ _e.sent();
1132
+ _e.label = 30;
1133
+ case 30: return [3 /*break*/, 32];
1134
+ case 31:
1135
+ if (e_11) throw e_11.error;
1017
1136
  return [7 /*endfinally*/];
1018
- case 29: return [7 /*endfinally*/];
1019
- case 30: return [3 /*break*/, 33];
1020
- case 31:
1137
+ case 32: return [7 /*endfinally*/];
1138
+ case 33: return [3 /*break*/, 36];
1139
+ case 34:
1021
1140
  // Intentionally blank
1022
- return [3 /*break*/, 33];
1023
- case 32:
1024
- exhaustiveCheck(relationType);
1025
- return [3 /*break*/, 33];
1026
- case 33: return [3 /*break*/, 1];
1027
- case 34: return [3 /*break*/, 41];
1141
+ return [3 /*break*/, 36];
1028
1142
  case 35:
1029
- e_8_1 = _e.sent();
1030
- e_8 = { error: e_8_1 };
1031
- return [3 /*break*/, 41];
1032
- case 36:
1033
- _e.trys.push([36, , 39, 40]);
1034
- if (!(relations_2_1 && !relations_2_1.done && (_a = relations_2.return))) return [3 /*break*/, 38];
1143
+ exhaustiveCheck(relationType);
1144
+ return [3 /*break*/, 36];
1145
+ case 36: return [3 /*break*/, 1];
1146
+ case 37: return [3 /*break*/, 44];
1147
+ case 38:
1148
+ e_9_1 = _e.sent();
1149
+ e_9 = { error: e_9_1 };
1150
+ return [3 /*break*/, 44];
1151
+ case 39:
1152
+ _e.trys.push([39, , 42, 43]);
1153
+ if (!(relations_2_1 && !relations_2_1.done && (_a = relations_2.return))) return [3 /*break*/, 41];
1035
1154
  return [4 /*yield*/, _a.call(relations_2)];
1036
- case 37:
1155
+ case 40:
1037
1156
  _e.sent();
1038
- _e.label = 38;
1039
- case 38: return [3 /*break*/, 40];
1040
- case 39:
1041
- if (e_8) throw e_8.error;
1157
+ _e.label = 41;
1158
+ case 41: return [3 /*break*/, 43];
1159
+ case 42:
1160
+ if (e_9) throw e_9.error;
1042
1161
  return [7 /*endfinally*/];
1043
- case 40: return [7 /*endfinally*/];
1044
- case 41:
1162
+ case 43: return [7 /*endfinally*/];
1163
+ case 44:
1045
1164
  deleteQueue.push({
1046
- storeName: this.getStorename(nameSpace, srcModel),
1165
+ storeName: getStorename(nameSpace, srcModel),
1047
1166
  items: models.map(function (record) {
1048
1167
  return _this.modelInstanceCreator(_this.getModelConstructorByModelName(nameSpace, srcModel), record);
1049
1168
  }),
@@ -1074,8 +1193,9 @@ var IndexedDBAdapter = /** @class */ (function () {
1074
1193
  };
1075
1194
  IndexedDBAdapter.prototype.batchSave = function (modelConstructor, items) {
1076
1195
  return __awaiter(this, void 0, void 0, function () {
1077
- var result, storeName, txn, store, _loop_1, this_1, items_2, items_2_1, item, e_11_1;
1078
- var e_11, _a;
1196
+ var result, storeName, txn, store, _loop_2, this_1, items_2, items_2_1, item, e_12_1;
1197
+ var e_12, _a;
1198
+ var _this = this;
1079
1199
  return __generator(this, function (_b) {
1080
1200
  switch (_b.label) {
1081
1201
  case 0:
@@ -1089,21 +1209,26 @@ var IndexedDBAdapter = /** @class */ (function () {
1089
1209
  storeName = this.getStorenameForModel(modelConstructor);
1090
1210
  txn = this.db.transaction(storeName, 'readwrite');
1091
1211
  store = txn.store;
1092
- _loop_1 = function (item) {
1093
- var connectedModels, id, _deleted, index, key, instance;
1212
+ _loop_2 = function (item) {
1213
+ var namespaceName, modelName, model, connectedModels, keyValues, _deleted, index, key, instance;
1094
1214
  return __generator(this, function (_a) {
1095
1215
  switch (_a.label) {
1096
1216
  case 0:
1097
- connectedModels = traverseModel(modelConstructor.name, this_1.modelInstanceCreator(modelConstructor, item), this_1.schema.namespaces[this_1.namespaceResolver(modelConstructor)], this_1.modelInstanceCreator, this_1.getModelConstructorByModelName);
1098
- id = item.id, _deleted = item._deleted;
1099
- index = store.index('byId');
1100
- return [4 /*yield*/, index.getKey(id)];
1217
+ namespaceName = this_1.namespaceResolver(modelConstructor);
1218
+ modelName = modelConstructor.name;
1219
+ model = this_1.modelInstanceCreator(modelConstructor, item);
1220
+ connectedModels = traverseModel(modelName, model, this_1.schema.namespaces[namespaceName], this_1.modelInstanceCreator, this_1.getModelConstructorByModelName);
1221
+ keyValues = this_1.getIndexKeyValuesFromModel(model);
1222
+ _deleted = item._deleted;
1223
+ index = store.index('byPk');
1224
+ return [4 /*yield*/, index.getKey(keyValues)];
1101
1225
  case 1:
1102
1226
  key = _a.sent();
1103
1227
  if (!!_deleted) return [3 /*break*/, 3];
1104
1228
  instance = connectedModels.find(function (_a) {
1105
1229
  var instance = _a.instance;
1106
- return instance.id === id;
1230
+ var instanceKeyValues = _this.getIndexKeyValuesFromModel(instance);
1231
+ return keysEqual(instanceKeyValues, keyValues);
1107
1232
  }).instance;
1108
1233
  result.push([
1109
1234
  instance,
@@ -1133,7 +1258,7 @@ var IndexedDBAdapter = /** @class */ (function () {
1133
1258
  case 3:
1134
1259
  if (!!items_2_1.done) return [3 /*break*/, 6];
1135
1260
  item = items_2_1.value;
1136
- return [5 /*yield**/, _loop_1(item)];
1261
+ return [5 /*yield**/, _loop_2(item)];
1137
1262
  case 4:
1138
1263
  _b.sent();
1139
1264
  _b.label = 5;
@@ -1142,14 +1267,14 @@ var IndexedDBAdapter = /** @class */ (function () {
1142
1267
  return [3 /*break*/, 3];
1143
1268
  case 6: return [3 /*break*/, 9];
1144
1269
  case 7:
1145
- e_11_1 = _b.sent();
1146
- e_11 = { error: e_11_1 };
1270
+ e_12_1 = _b.sent();
1271
+ e_12 = { error: e_12_1 };
1147
1272
  return [3 /*break*/, 9];
1148
1273
  case 8:
1149
1274
  try {
1150
1275
  if (items_2_1 && !items_2_1.done && (_a = items_2.return)) _a.call(items_2);
1151
1276
  }
1152
- finally { if (e_11) throw e_11.error; }
1277
+ finally { if (e_12) throw e_12.error; }
1153
1278
  return [7 /*endfinally*/];
1154
1279
  case 9: return [4 /*yield*/, txn.done];
1155
1280
  case 10:
@@ -1160,18 +1285,15 @@ var IndexedDBAdapter = /** @class */ (function () {
1160
1285
  });
1161
1286
  };
1162
1287
  IndexedDBAdapter.prototype.createObjectStoreForModel = function (db, namespaceName, storeName, modelName) {
1163
- return __awaiter(this, void 0, void 0, function () {
1164
- var store, indexes;
1165
- return __generator(this, function (_a) {
1166
- store = db.createObjectStore(storeName, {
1167
- autoIncrement: true,
1168
- });
1169
- indexes = this.schema.namespaces[namespaceName].relationships[modelName].indexes;
1170
- indexes.forEach(function (index) { return store.createIndex(index, index); });
1171
- store.createIndex('byId', 'id', { unique: true });
1172
- return [2 /*return*/];
1173
- });
1288
+ var store = db.createObjectStore(storeName, {
1289
+ autoIncrement: true,
1290
+ });
1291
+ var indexes = this.schema.namespaces[namespaceName].relationships[modelName].indexes;
1292
+ indexes.forEach(function (_a) {
1293
+ var _b = __read(_a, 3), idxName = _b[0], keyPath = _b[1], options = _b[2];
1294
+ store.createIndex(idxName, keyPath, options);
1174
1295
  });
1296
+ return store;
1175
1297
  };
1176
1298
  return IndexedDBAdapter;
1177
1299
  }());