@aws-amplify/datastore 3.12.6-next.20 → 3.12.6-next.36

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