@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
package/lib/util.js CHANGED
@@ -7,6 +7,27 @@ var uuid_1 = require("uuid");
7
7
  var immer_1 = require("immer");
8
8
  var types_1 = require("./types");
9
9
  var amazon_cognito_identity_js_1 = require("amazon-cognito-identity-js");
10
+ exports.ID = 'id';
11
+ /**
12
+ * Used by the Async Storage Adapter to concatenate key values
13
+ * for a record. For instance, if a model has the following keys:
14
+ * `customId: ID! @primaryKey(sortKeyFields: ["createdAt"])`,
15
+ * we concatenate the `customId` and `createdAt` as:
16
+ * `12-234-5#2022-09-28T00:00:00.000Z`
17
+ */
18
+ exports.DEFAULT_PRIMARY_KEY_VALUE_SEPARATOR = '#';
19
+ /**
20
+ * Used for generating spinal-cased index name from an array of
21
+ * key field names.
22
+ * E.g. for keys `[id, title]` => 'id-title'
23
+ */
24
+ exports.IDENTIFIER_KEY_SEPARATOR = '-';
25
+ exports.errorMessages = {
26
+ idEmptyString: 'An index field cannot contain an empty string value',
27
+ queryByPkWithCompositeKeyPresent: 'Models with composite primary keys cannot be queried by a single key value. Use object literal syntax for composite keys instead: https://docs.amplify.aws/lib/datastore/advanced-workflows/q/platform/js/#querying-records-with-custom-primary-keys',
28
+ deleteByPkWithCompositeKeyPresent: 'Models with composite primary keys cannot be deleted by a single key value, unless using a predicate. Use object literal syntax for composite keys instead: https://docs.amplify.aws/lib/datastore/advanced-workflows/q/platform/js/#querying-records-with-custom-primary-keys',
29
+ observeWithObjectLiteral: 'Object literal syntax cannot be used with observe. Use a predicate instead: https://docs.amplify.aws/lib/datastore/data-access/q/platform/js/#predicates',
30
+ };
10
31
  var NAMESPACES;
11
32
  (function (NAMESPACES) {
12
33
  NAMESPACES["DATASTORE"] = "datastore";
@@ -108,148 +129,6 @@ exports.registerNonModelClass = registerNonModelClass;
108
129
  exports.isNonModelConstructor = function (obj) {
109
130
  return nonModelClasses.has(obj);
110
131
  };
111
- /*
112
- When we have GSI(s) with composite sort keys defined on a model
113
- There are some very particular rules regarding which fields must be included in the update mutation input
114
- The field selection becomes more complex as the number of GSIs with composite sort keys grows
115
-
116
- To summarize: any time we update a field that is part of the composite sort key of a GSI, we must include:
117
- 1. all of the other fields in that composite sort key
118
- 2. all of the fields from any other composite sort key that intersect with the fields from 1.
119
-
120
- E.g.,
121
- Model @model
122
- @key(name: 'key1' fields: ['hk', 'a', 'b', 'c'])
123
- @key(name: 'key2' fields: ['hk', 'a', 'b', 'd'])
124
- @key(name: 'key3' fields: ['hk', 'x', 'y', 'z'])
125
-
126
- Model.a is updated => include ['a', 'b', 'c', 'd']
127
- Model.c is updated => include ['a', 'b', 'c', 'd']
128
- Model.d is updated => include ['a', 'b', 'c', 'd']
129
- Model.x is updated => include ['x', 'y', 'z']
130
-
131
- This function accepts a model's attributes and returns grouped sets of composite key fields
132
- Using our example Model above, the function will return:
133
- [
134
- Set('a', 'b', 'c', 'd'),
135
- Set('x', 'y', 'z'),
136
- ]
137
-
138
- This gives us the opportunity to correctly include the required fields for composite keys
139
- When crafting the mutation input in Storage.getUpdateMutationInput
140
-
141
- See 'processCompositeKeys' test in util.test.ts for more examples
142
- */
143
- exports.processCompositeKeys = function (attributes) {
144
- var extractCompositeSortKey = function (_c) {
145
- var
146
- // ignore the HK (fields[0]) we only need to include the composite sort key fields[1...n]
147
- _d = tslib_1.__read(_c.properties.fields), sortKeyFields = _d.slice(1);
148
- return sortKeyFields;
149
- };
150
- var compositeKeyFields = attributes
151
- .filter(types_1.isModelAttributeCompositeKey)
152
- .map(extractCompositeSortKey);
153
- /*
154
- if 2 sets of fields have any intersecting fields => combine them into 1 union set
155
- e.g., ['a', 'b', 'c'] and ['a', 'b', 'd'] => ['a', 'b', 'c', 'd']
156
- */
157
- var combineIntersecting = function (fields) {
158
- return fields.reduce(function (combined, sortKeyFields) {
159
- var sortKeyFieldsSet = new Set(sortKeyFields);
160
- if (combined.length === 0) {
161
- combined.push(sortKeyFieldsSet);
162
- return combined;
163
- }
164
- // does the current set share values with another set we've already added to `combined`?
165
- var intersectingSetIdx = combined.findIndex(function (existingSet) {
166
- return tslib_1.__spread(existingSet).some(function (f) { return sortKeyFieldsSet.has(f); });
167
- });
168
- if (intersectingSetIdx > -1) {
169
- var union = new Set(tslib_1.__spread(combined[intersectingSetIdx], sortKeyFieldsSet));
170
- // combine the current set with the intersecting set we found above
171
- combined[intersectingSetIdx] = union;
172
- }
173
- else {
174
- // none of the sets in `combined` have intersecting values with the current set
175
- combined.push(sortKeyFieldsSet);
176
- }
177
- return combined;
178
- }, []);
179
- };
180
- var initial = combineIntersecting(compositeKeyFields);
181
- // a single pass pay not be enough to correctly combine all the fields
182
- // call the function once more to get a final merged list of sets
183
- var combined = combineIntersecting(initial);
184
- return combined;
185
- };
186
- exports.establishRelationAndKeys = function (namespace) {
187
- var relationship = {};
188
- var keys = {};
189
- Object.keys(namespace.models).forEach(function (mKey) {
190
- var e_1, _c, e_2, _d;
191
- relationship[mKey] = { indexes: [], relationTypes: [] };
192
- keys[mKey] = {};
193
- var model = namespace.models[mKey];
194
- Object.keys(model.fields).forEach(function (attr) {
195
- var fieldAttribute = model.fields[attr];
196
- if (typeof fieldAttribute.type === 'object' &&
197
- 'model' in fieldAttribute.type) {
198
- var connectionType = fieldAttribute.association.connectionType;
199
- relationship[mKey].relationTypes.push({
200
- fieldName: fieldAttribute.name,
201
- modelName: fieldAttribute.type.model,
202
- relationType: connectionType,
203
- targetName: fieldAttribute.association['targetName'],
204
- associatedWith: fieldAttribute.association['associatedWith'],
205
- });
206
- if (connectionType === 'BELONGS_TO') {
207
- relationship[mKey].indexes.push(fieldAttribute.association['targetName']);
208
- }
209
- }
210
- });
211
- if (model.attributes) {
212
- keys[mKey].compositeKeys = exports.processCompositeKeys(model.attributes);
213
- try {
214
- for (var _e = tslib_1.__values(model.attributes), _f = _e.next(); !_f.done; _f = _e.next()) {
215
- var attribute = _f.value;
216
- if (!types_1.isModelAttributeKey(attribute)) {
217
- continue;
218
- }
219
- if (types_1.isModelAttributePrimaryKey(attribute)) {
220
- keys[mKey].primaryKey = attribute.properties.fields;
221
- }
222
- var fields = attribute.properties.fields;
223
- try {
224
- for (var fields_1 = (e_2 = void 0, tslib_1.__values(fields)), fields_1_1 = fields_1.next(); !fields_1_1.done; fields_1_1 = fields_1.next()) {
225
- var field = fields_1_1.value;
226
- // only add index if it hasn't already been added
227
- var exists = relationship[mKey].indexes.includes(field);
228
- if (!exists) {
229
- relationship[mKey].indexes.push(field);
230
- }
231
- }
232
- }
233
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
234
- finally {
235
- try {
236
- if (fields_1_1 && !fields_1_1.done && (_d = fields_1.return)) _d.call(fields_1);
237
- }
238
- finally { if (e_2) throw e_2.error; }
239
- }
240
- }
241
- }
242
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
243
- finally {
244
- try {
245
- if (_f && !_f.done && (_c = _e.return)) _c.call(_e);
246
- }
247
- finally { if (e_1) throw e_1.error; }
248
- }
249
- }
250
- });
251
- return [relationship, keys];
252
- };
253
132
  var topologicallySortedModels = new WeakMap();
254
133
  exports.traverseModel = function (srcModelName, instance, namespace, modelInstanceCreator, getModelConstructorByModelName) {
255
134
  var relationships = namespace.relationships;
@@ -275,12 +154,26 @@ exports.traverseModel = function (srcModelName, instance, namespace, modelInstan
275
154
  item: instance[rItem.fieldName],
276
155
  instance: modelInstance,
277
156
  });
278
- // targetName will be defined for Has One if feature flag
157
+ var targetNames = exports.extractTargetNamesFromSrc(rItem);
158
+ // `targetName` will be defined for Has One if feature flag
279
159
  // https://docs.amplify.aws/cli/reference/feature-flags/#useAppsyncModelgenPlugin
280
160
  // is true (default as of 5/7/21)
281
161
  // Making this conditional for backward-compatibility
282
- if (rItem.targetName) {
283
- draftInstance[rItem.targetName] = (draftInstance[rItem.fieldName]).id;
162
+ if (targetNames) {
163
+ targetNames.forEach(function (targetName, idx) {
164
+ // Get the connected record
165
+ var relatedRecordInProxy = (draftInstance[rItem.fieldName]);
166
+ // Previously, we used the hardcoded 'id' as they key,
167
+ // now we need the value of the key to get the PK (and SK)
168
+ // values from the related record
169
+ var primaryKey = namespace.keys[modelConstructor.name].primaryKey;
170
+ var keyField = primaryKey && primaryKey[idx];
171
+ // Get the value
172
+ var relatedRecordInProxyPkValue = relatedRecordInProxy[keyField];
173
+ // Set the targetName value
174
+ draftInstance[targetName] = relatedRecordInProxyPkValue;
175
+ });
176
+ // Delete the instance from the proxy
284
177
  delete draftInstance[rItem.fieldName];
285
178
  }
286
179
  else {
@@ -307,8 +200,25 @@ exports.traverseModel = function (srcModelName, instance, namespace, modelInstan
307
200
  }
308
201
  }
309
202
  if (draftInstance[rItem.fieldName]) {
310
- draftInstance[rItem.targetName] = (draftInstance[rItem.fieldName]).id;
311
- delete draftInstance[rItem.fieldName];
203
+ var targetNames = exports.extractTargetNamesFromSrc(rItem);
204
+ if (targetNames) {
205
+ targetNames.forEach(function (targetName, idx) {
206
+ // Get the connected record
207
+ var relatedRecordInProxy = (draftInstance[rItem.fieldName]);
208
+ // Previously, we used the hardcoded `id` for the key.
209
+ // Now, we need the value of the key to get the PK (and SK)
210
+ // values from the related record
211
+ var primaryKey = namespace.keys[modelConstructor.name].primaryKey;
212
+ // fall back to ID if
213
+ var keyField = primaryKey && primaryKey[idx];
214
+ // Get the value
215
+ var relatedRecordInProxyPkValue = relatedRecordInProxy[keyField];
216
+ // Set the targetName value
217
+ draftInstance[targetName] = relatedRecordInProxyPkValue;
218
+ });
219
+ // Delete the instance from the proxy
220
+ delete draftInstance[rItem.fieldName];
221
+ }
312
222
  }
313
223
  break;
314
224
  case 'HAS_MANY':
@@ -334,19 +244,6 @@ exports.traverseModel = function (srcModelName, instance, namespace, modelInstan
334
244
  });
335
245
  return result;
336
246
  };
337
- exports.getIndex = function (rel, src) {
338
- var index = '';
339
- rel.some(function (relItem) {
340
- if (relItem.modelName === src) {
341
- index = relItem.targetName;
342
- }
343
- });
344
- return index;
345
- };
346
- exports.getIndexFromAssociation = function (indexes, src) {
347
- var index = indexes.find(function (idx) { return idx === src; });
348
- return index;
349
- };
350
247
  var privateModeCheckResult;
351
248
  exports.isPrivateMode = function () {
352
249
  return new Promise(function (resolve) {
@@ -386,6 +283,95 @@ exports.isPrivateMode = function () {
386
283
  db.onsuccess = isNotPrivate;
387
284
  });
388
285
  };
286
+ var safariCompatabilityModeResult;
287
+ /**
288
+ * Whether the browser's implementation of IndexedDB breaks on array lookups
289
+ * against composite indexes whose keypath contains a single column.
290
+ *
291
+ * E.g., Whether `store.createIndex(indexName, ['id'])` followed by
292
+ * `store.index(indexName).get([1])` will *ever* return records.
293
+ *
294
+ * In all known, modern Safari browsers as of Q4 2022, the query against an index like
295
+ * this will *always* return `undefined`. So, the index needs to be created as a scalar.
296
+ */
297
+ exports.isSafariCompatabilityMode = function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
298
+ var dbName_1, storeName_1, indexName_1, db_1, rwTx, rwStore, result, error_1;
299
+ return tslib_1.__generator(this, function (_c) {
300
+ switch (_c.label) {
301
+ case 0:
302
+ _c.trys.push([0, 6, , 7]);
303
+ dbName_1 = uuid_1.v4();
304
+ storeName_1 = 'indexedDBFeatureProbeStore';
305
+ indexName_1 = 'idx';
306
+ if (indexedDB === null)
307
+ return [2 /*return*/, false];
308
+ if (safariCompatabilityModeResult !== undefined) {
309
+ return [2 /*return*/, safariCompatabilityModeResult];
310
+ }
311
+ return [4 /*yield*/, new Promise(function (resolve) {
312
+ var dbOpenRequest = indexedDB.open(dbName_1);
313
+ dbOpenRequest.onerror = function () { return resolve(false); };
314
+ dbOpenRequest.onsuccess = function () {
315
+ var db = dbOpenRequest.result;
316
+ resolve(db);
317
+ };
318
+ dbOpenRequest.onupgradeneeded = function (event) {
319
+ var _c;
320
+ var db = (_c = event === null || event === void 0 ? void 0 : event.target) === null || _c === void 0 ? void 0 : _c.result;
321
+ db.onerror = function () { return resolve(false); };
322
+ var store = db.createObjectStore(storeName_1, {
323
+ autoIncrement: true,
324
+ });
325
+ store.createIndex(indexName_1, ['id']);
326
+ };
327
+ })];
328
+ case 1:
329
+ db_1 = _c.sent();
330
+ if (!db_1) {
331
+ throw new Error('Could not open probe DB');
332
+ }
333
+ rwTx = db_1.transaction(storeName_1, 'readwrite');
334
+ rwStore = rwTx.objectStore(storeName_1);
335
+ rwStore.add({
336
+ id: 1,
337
+ });
338
+ rwTx.commit();
339
+ return [4 /*yield*/, new Promise(function (resolve) {
340
+ var tx = db_1.transaction(storeName_1, 'readonly');
341
+ var store = tx.objectStore(storeName_1);
342
+ var index = store.index(indexName_1);
343
+ var getRequest = index.get([1]);
344
+ getRequest.onerror = function () { return resolve(false); };
345
+ getRequest.onsuccess = function (event) {
346
+ var _c;
347
+ resolve((_c = event === null || event === void 0 ? void 0 : event.target) === null || _c === void 0 ? void 0 : _c.result);
348
+ };
349
+ })];
350
+ case 2:
351
+ result = _c.sent();
352
+ if (!(db_1 && typeof db_1.close === 'function')) return [3 /*break*/, 4];
353
+ return [4 /*yield*/, db_1.close()];
354
+ case 3:
355
+ _c.sent();
356
+ _c.label = 4;
357
+ case 4: return [4 /*yield*/, indexedDB.deleteDatabase(dbName_1)];
358
+ case 5:
359
+ _c.sent();
360
+ if (result === undefined) {
361
+ safariCompatabilityModeResult = true;
362
+ }
363
+ else {
364
+ safariCompatabilityModeResult = false;
365
+ }
366
+ return [3 /*break*/, 7];
367
+ case 6:
368
+ error_1 = _c.sent();
369
+ safariCompatabilityModeResult = false;
370
+ return [3 /*break*/, 7];
371
+ case 7: return [2 /*return*/, safariCompatabilityModeResult];
372
+ }
373
+ });
374
+ }); };
389
375
  var randomBytes = function (nBytes) {
390
376
  return buffer_1.Buffer.from(new amazon_cognito_identity_js_1.WordArray().random(nBytes).toString(), 'hex');
391
377
  };
@@ -422,7 +408,7 @@ function getNow() {
422
408
  exports.getNow = getNow;
423
409
  function sortCompareFunction(sortPredicates) {
424
410
  return function compareFunction(a, b) {
425
- var e_3, _c;
411
+ var e_1, _c;
426
412
  try {
427
413
  // enable multi-field sort by iterating over predicates until
428
414
  // a comparison returns -1 or 1
@@ -439,12 +425,12 @@ function sortCompareFunction(sortPredicates) {
439
425
  }
440
426
  }
441
427
  }
442
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
428
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
443
429
  finally {
444
430
  try {
445
431
  if (sortPredicates_1_1 && !sortPredicates_1_1.done && (_c = sortPredicates_1.return)) _c.call(sortPredicates_1);
446
432
  }
447
- finally { if (e_3) throw e_3.error; }
433
+ finally { if (e_1) throw e_1.error; }
448
434
  }
449
435
  return 0;
450
436
  };
@@ -456,7 +442,7 @@ exports.sortCompareFunction = sortCompareFunction;
456
442
  // if nullish is true, treat undefined and null values as equal
457
443
  // to normalize for GQL response values for undefined fields
458
444
  function valuesEqual(valA, valB, nullish) {
459
- var e_4, _c;
445
+ var e_2, _c;
460
446
  if (nullish === void 0) { nullish = false; }
461
447
  var a = valA;
462
448
  var b = valB;
@@ -508,12 +494,12 @@ function valuesEqual(valA, valB, nullish) {
508
494
  }
509
495
  }
510
496
  }
511
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
497
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
512
498
  finally {
513
499
  try {
514
500
  if (keys_1_1 && !keys_1_1.done && (_c = keys_1.return)) _c.call(keys_1);
515
501
  }
516
- finally { if (e_4) throw e_4.error; }
502
+ finally { if (e_2) throw e_2.error; }
517
503
  }
518
504
  return true;
519
505
  }
@@ -661,4 +647,271 @@ function mergePatches(originalSource, oldPatches, newPatches) {
661
647
  return patches;
662
648
  }
663
649
  exports.mergePatches = mergePatches;
650
+ exports.getStorename = function (namespace, modelName) {
651
+ var storeName = namespace + "_" + modelName;
652
+ return storeName;
653
+ };
654
+ //#region Key Utils
655
+ /*
656
+ When we have GSI(s) with composite sort keys defined on a model
657
+ There are some very particular rules regarding which fields must be included in the update mutation input
658
+ The field selection becomes more complex as the number of GSIs with composite sort keys grows
659
+
660
+ To summarize: any time we update a field that is part of the composite sort key of a GSI, we must include:
661
+ 1. all of the other fields in that composite sort key
662
+ 2. all of the fields from any other composite sort key that intersect with the fields from 1.
663
+
664
+ E.g.,
665
+ Model @model
666
+ @key(name: 'key1' fields: ['hk', 'a', 'b', 'c'])
667
+ @key(name: 'key2' fields: ['hk', 'a', 'b', 'd'])
668
+ @key(name: 'key3' fields: ['hk', 'x', 'y', 'z'])
669
+
670
+ Model.a is updated => include ['a', 'b', 'c', 'd']
671
+ Model.c is updated => include ['a', 'b', 'c', 'd']
672
+ Model.d is updated => include ['a', 'b', 'c', 'd']
673
+ Model.x is updated => include ['x', 'y', 'z']
674
+
675
+ This function accepts a model's attributes and returns grouped sets of composite key fields
676
+ Using our example Model above, the function will return:
677
+ [
678
+ Set('a', 'b', 'c', 'd'),
679
+ Set('x', 'y', 'z'),
680
+ ]
681
+
682
+ This gives us the opportunity to correctly include the required fields for composite keys
683
+ When crafting the mutation input in Storage.getUpdateMutationInput
684
+
685
+ See 'processCompositeKeys' test in util.test.ts for more examples
686
+ */
687
+ exports.processCompositeKeys = function (attributes) {
688
+ var extractCompositeSortKey = function (_c) {
689
+ var
690
+ // ignore the HK (fields[0]) we only need to include the composite sort key fields[1...n]
691
+ _d = tslib_1.__read(_c.properties.fields), sortKeyFields = _d.slice(1);
692
+ return sortKeyFields;
693
+ };
694
+ var compositeKeyFields = attributes
695
+ .filter(types_1.isModelAttributeCompositeKey)
696
+ .map(extractCompositeSortKey);
697
+ /*
698
+ if 2 sets of fields have any intersecting fields => combine them into 1 union set
699
+ e.g., ['a', 'b', 'c'] and ['a', 'b', 'd'] => ['a', 'b', 'c', 'd']
700
+ */
701
+ var combineIntersecting = function (fields) {
702
+ return fields.reduce(function (combined, sortKeyFields) {
703
+ var sortKeyFieldsSet = new Set(sortKeyFields);
704
+ if (combined.length === 0) {
705
+ combined.push(sortKeyFieldsSet);
706
+ return combined;
707
+ }
708
+ // does the current set share values with another set we've already added to `combined`?
709
+ var intersectingSetIdx = combined.findIndex(function (existingSet) {
710
+ return tslib_1.__spread(existingSet).some(function (f) { return sortKeyFieldsSet.has(f); });
711
+ });
712
+ if (intersectingSetIdx > -1) {
713
+ var union = new Set(tslib_1.__spread(combined[intersectingSetIdx], sortKeyFieldsSet));
714
+ // combine the current set with the intersecting set we found above
715
+ combined[intersectingSetIdx] = union;
716
+ }
717
+ else {
718
+ // none of the sets in `combined` have intersecting values with the current set
719
+ combined.push(sortKeyFieldsSet);
720
+ }
721
+ return combined;
722
+ }, []);
723
+ };
724
+ var initial = combineIntersecting(compositeKeyFields);
725
+ // a single pass pay not be enough to correctly combine all the fields
726
+ // call the function once more to get a final merged list of sets
727
+ var combined = combineIntersecting(initial);
728
+ return combined;
729
+ };
730
+ exports.extractKeyIfExists = function (modelDefinition) {
731
+ var _c;
732
+ var keyAttribute = (_c = modelDefinition === null || modelDefinition === void 0 ? void 0 : modelDefinition.attributes) === null || _c === void 0 ? void 0 : _c.find(types_1.isModelAttributeKey);
733
+ return keyAttribute;
734
+ };
735
+ exports.extractPrimaryKeyFieldNames = function (modelDefinition) {
736
+ var keyAttribute = exports.extractKeyIfExists(modelDefinition);
737
+ if (keyAttribute && types_1.isModelAttributePrimaryKey(keyAttribute)) {
738
+ return keyAttribute.properties.fields;
739
+ }
740
+ return [exports.ID];
741
+ };
742
+ exports.extractPrimaryKeyValues = function (model, keyFields) {
743
+ return keyFields.map(function (key) { return model[key]; });
744
+ };
745
+ exports.extractPrimaryKeysAndValues = function (model, keyFields) {
746
+ var primaryKeysAndValues = {};
747
+ keyFields.forEach(function (key) { return (primaryKeysAndValues[key] = model[key]); });
748
+ return primaryKeysAndValues;
749
+ };
750
+ // IdentifierFields<ManagedIdentifier>
751
+ // Default behavior without explicit @primaryKey defined
752
+ exports.isIdManaged = function (modelDefinition) {
753
+ var keyAttribute = exports.extractKeyIfExists(modelDefinition);
754
+ if (keyAttribute && types_1.isModelAttributePrimaryKey(keyAttribute)) {
755
+ return false;
756
+ }
757
+ return true;
758
+ };
759
+ // IdentifierFields<OptionallyManagedIdentifier>
760
+ // @primaryKey with explicit `id` in the PK. Single key or composite
761
+ exports.isIdOptionallyManaged = function (modelDefinition) {
762
+ var keyAttribute = exports.extractKeyIfExists(modelDefinition);
763
+ if (keyAttribute && types_1.isModelAttributePrimaryKey(keyAttribute)) {
764
+ return keyAttribute.properties.fields[0] === exports.ID;
765
+ }
766
+ return false;
767
+ };
768
+ exports.establishRelationAndKeys = function (namespace) {
769
+ var relationship = {};
770
+ var keys = {};
771
+ Object.keys(namespace.models).forEach(function (mKey) {
772
+ var e_3, _c;
773
+ relationship[mKey] = { indexes: [], relationTypes: [] };
774
+ keys[mKey] = {};
775
+ var model = namespace.models[mKey];
776
+ Object.keys(model.fields).forEach(function (attr) {
777
+ var fieldAttribute = model.fields[attr];
778
+ if (typeof fieldAttribute.type === 'object' &&
779
+ 'model' in fieldAttribute.type) {
780
+ var connectionType = fieldAttribute.association.connectionType;
781
+ relationship[mKey].relationTypes.push({
782
+ fieldName: fieldAttribute.name,
783
+ modelName: fieldAttribute.type.model,
784
+ relationType: connectionType,
785
+ targetName: fieldAttribute.association['targetName'],
786
+ targetNames: fieldAttribute.association['targetNames'],
787
+ associatedWith: fieldAttribute.association['associatedWith'],
788
+ });
789
+ if (connectionType === 'BELONGS_TO') {
790
+ var targetNames = exports.extractTargetNamesFromSrc(fieldAttribute.association);
791
+ if (targetNames) {
792
+ var idxName = exports.indexNameFromKeys(targetNames);
793
+ relationship[mKey].indexes.push([idxName, targetNames]);
794
+ }
795
+ }
796
+ }
797
+ });
798
+ if (model.attributes) {
799
+ keys[mKey].compositeKeys = exports.processCompositeKeys(model.attributes);
800
+ var _loop_1 = function (attribute) {
801
+ if (!types_1.isModelAttributeKey(attribute)) {
802
+ return "continue";
803
+ }
804
+ var fields = attribute.properties.fields;
805
+ if (types_1.isModelAttributePrimaryKey(attribute)) {
806
+ keys[mKey].primaryKey = fields;
807
+ return "continue";
808
+ }
809
+ // create indexes for all other keys
810
+ var idxName = exports.indexNameFromKeys(fields);
811
+ var idxExists = relationship[mKey].indexes.find(function (_c) {
812
+ var _d = tslib_1.__read(_c, 1), index = _d[0];
813
+ return index === idxName;
814
+ });
815
+ if (!idxExists) {
816
+ relationship[mKey].indexes.push([idxName, fields]);
817
+ }
818
+ };
819
+ try {
820
+ for (var _d = tslib_1.__values(model.attributes), _e = _d.next(); !_e.done; _e = _d.next()) {
821
+ var attribute = _e.value;
822
+ _loop_1(attribute);
823
+ }
824
+ }
825
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
826
+ finally {
827
+ try {
828
+ if (_e && !_e.done && (_c = _d.return)) _c.call(_d);
829
+ }
830
+ finally { if (e_3) throw e_3.error; }
831
+ }
832
+ }
833
+ // set 'id' as the PK for models without a custom PK explicitly defined
834
+ if (!keys[mKey].primaryKey) {
835
+ keys[mKey].primaryKey = [exports.ID];
836
+ }
837
+ // create primary index
838
+ relationship[mKey].indexes.push([
839
+ 'byPk',
840
+ keys[mKey].primaryKey,
841
+ { unique: true },
842
+ ]);
843
+ });
844
+ return [relationship, keys];
845
+ };
846
+ exports.getIndex = function (rel, src) {
847
+ var indexName;
848
+ rel.some(function (relItem) {
849
+ if (relItem.modelName === src) {
850
+ var targetNames = exports.extractTargetNamesFromSrc(relItem);
851
+ indexName = targetNames && exports.indexNameFromKeys(targetNames);
852
+ return true;
853
+ }
854
+ });
855
+ return indexName;
856
+ };
857
+ exports.getIndexFromAssociation = function (indexes, src) {
858
+ var indexName;
859
+ if (Array.isArray(src)) {
860
+ indexName = exports.indexNameFromKeys(src);
861
+ }
862
+ else {
863
+ indexName = src;
864
+ }
865
+ var associationIndex = indexes.find(function (_c) {
866
+ var _d = tslib_1.__read(_c, 1), idxName = _d[0];
867
+ return idxName === indexName;
868
+ });
869
+ return associationIndex && associationIndex[0];
870
+ };
871
+ /**
872
+ * Backwards-compatability for schema generated prior to custom primary key support:
873
+ the single field `targetName` has been replaced with an array of `targetNames`.
874
+ `targetName` and `targetNames` are exclusive (will never exist on the same schema)
875
+ * @param src {RelationType | ModelAssociation | undefined}
876
+ * @returns array of targetNames, or `undefined`
877
+ */
878
+ exports.extractTargetNamesFromSrc = function (src) {
879
+ var targetName = src === null || src === void 0 ? void 0 : src.targetName;
880
+ var targetNames = src === null || src === void 0 ? void 0 : src.targetNames;
881
+ if (Array.isArray(targetNames)) {
882
+ return targetNames;
883
+ }
884
+ else if (typeof targetName === 'string') {
885
+ return [targetName];
886
+ }
887
+ else {
888
+ return undefined;
889
+ }
890
+ };
891
+ // Generates spinal-cased index name from an array of key field names
892
+ // E.g. for keys `[id, title]` => 'id-title'
893
+ exports.indexNameFromKeys = function (keys) {
894
+ return keys.reduce(function (prev, cur, idx) {
895
+ if (idx === 0) {
896
+ return cur;
897
+ }
898
+ return "" + prev + exports.IDENTIFIER_KEY_SEPARATOR + cur;
899
+ }, '');
900
+ };
901
+ exports.keysEqual = function (keysA, keysB) {
902
+ if (keysA.length !== keysB.length) {
903
+ return false;
904
+ }
905
+ return keysA.every(function (key, idx) { return key === keysB[idx]; });
906
+ };
907
+ // Returns primary keys for a model
908
+ exports.getIndexKeys = function (namespace, modelName) {
909
+ var _c;
910
+ var keyPath = (_c = namespace === null || namespace === void 0 ? void 0 : namespace.keys[modelName]) === null || _c === void 0 ? void 0 : _c.primaryKey;
911
+ if (keyPath) {
912
+ return keyPath;
913
+ }
914
+ return [exports.ID];
915
+ };
916
+ //#endregion
664
917
  //# sourceMappingURL=util.js.map