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