@aws-amplify/datastore 3.12.11 → 3.12.13-unstable.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/aws-amplify-datastore.js +1853 -964
  3. package/dist/aws-amplify-datastore.js.map +1 -1
  4. package/dist/aws-amplify-datastore.min.js +7 -7
  5. package/dist/aws-amplify-datastore.min.js.map +1 -1
  6. package/lib/datastore/datastore.d.ts +13 -16
  7. package/lib/datastore/datastore.js +130 -63
  8. package/lib/datastore/datastore.js.map +1 -1
  9. package/lib/index.d.ts +3 -19
  10. package/lib/predicates/index.d.ts +3 -2
  11. package/lib/predicates/index.js +12 -2
  12. package/lib/predicates/index.js.map +1 -1
  13. package/lib/storage/adapter/AsyncStorageAdapter.d.ts +4 -3
  14. package/lib/storage/adapter/AsyncStorageAdapter.js +354 -203
  15. package/lib/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  16. package/lib/storage/adapter/AsyncStorageDatabase.d.ts +14 -4
  17. package/lib/storage/adapter/AsyncStorageDatabase.js +65 -28
  18. package/lib/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  19. package/lib/storage/adapter/IndexedDBAdapter.d.ts +5 -4
  20. package/lib/storage/adapter/IndexedDBAdapter.js +389 -267
  21. package/lib/storage/adapter/IndexedDBAdapter.js.map +1 -1
  22. package/lib/storage/adapter/index.d.ts +1 -1
  23. package/lib/storage/storage.d.ts +1 -1
  24. package/lib/storage/storage.js +92 -27
  25. package/lib/storage/storage.js.map +1 -1
  26. package/lib/sync/index.d.ts +21 -4
  27. package/lib/sync/index.js +13 -11
  28. package/lib/sync/index.js.map +1 -1
  29. package/lib/sync/merger.d.ts +3 -3
  30. package/lib/sync/merger.js +7 -6
  31. package/lib/sync/merger.js.map +1 -1
  32. package/lib/sync/outbox.d.ts +2 -2
  33. package/lib/sync/outbox.js +11 -9
  34. package/lib/sync/outbox.js.map +1 -1
  35. package/lib/sync/processors/mutation.js +60 -42
  36. package/lib/sync/processors/mutation.js.map +1 -1
  37. package/lib/sync/processors/subscription.js.map +1 -1
  38. package/lib/sync/processors/sync.js.map +1 -1
  39. package/lib/sync/utils.d.ts +3 -2
  40. package/lib/sync/utils.js +61 -8
  41. package/lib/sync/utils.js.map +1 -1
  42. package/lib/types.d.ts +64 -25
  43. package/lib/types.js +10 -1
  44. package/lib/types.js.map +1 -1
  45. package/lib/util.d.ts +56 -24
  46. package/lib/util.js +334 -170
  47. package/lib/util.js.map +1 -1
  48. package/lib-esm/datastore/datastore.d.ts +13 -16
  49. package/lib-esm/datastore/datastore.js +132 -65
  50. package/lib-esm/datastore/datastore.js.map +1 -1
  51. package/lib-esm/index.d.ts +3 -19
  52. package/lib-esm/predicates/index.d.ts +3 -2
  53. package/lib-esm/predicates/index.js +13 -3
  54. package/lib-esm/predicates/index.js.map +1 -1
  55. package/lib-esm/storage/adapter/AsyncStorageAdapter.d.ts +4 -3
  56. package/lib-esm/storage/adapter/AsyncStorageAdapter.js +355 -204
  57. package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  58. package/lib-esm/storage/adapter/AsyncStorageDatabase.d.ts +14 -4
  59. package/lib-esm/storage/adapter/AsyncStorageDatabase.js +66 -29
  60. package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  61. package/lib-esm/storage/adapter/IndexedDBAdapter.d.ts +5 -4
  62. package/lib-esm/storage/adapter/IndexedDBAdapter.js +390 -268
  63. package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +1 -1
  64. package/lib-esm/storage/adapter/index.d.ts +1 -1
  65. package/lib-esm/storage/storage.d.ts +1 -1
  66. package/lib-esm/storage/storage.js +92 -27
  67. package/lib-esm/storage/storage.js.map +1 -1
  68. package/lib-esm/sync/index.d.ts +21 -4
  69. package/lib-esm/sync/index.js +15 -13
  70. package/lib-esm/sync/index.js.map +1 -1
  71. package/lib-esm/sync/merger.d.ts +3 -3
  72. package/lib-esm/sync/merger.js +7 -6
  73. package/lib-esm/sync/merger.js.map +1 -1
  74. package/lib-esm/sync/outbox.d.ts +2 -2
  75. package/lib-esm/sync/outbox.js +12 -10
  76. package/lib-esm/sync/outbox.js.map +1 -1
  77. package/lib-esm/sync/processors/mutation.js +61 -43
  78. package/lib-esm/sync/processors/mutation.js.map +1 -1
  79. package/lib-esm/sync/processors/subscription.js.map +1 -1
  80. package/lib-esm/sync/processors/sync.js.map +1 -1
  81. package/lib-esm/sync/utils.d.ts +3 -2
  82. package/lib-esm/sync/utils.js +62 -10
  83. package/lib-esm/sync/utils.js.map +1 -1
  84. package/lib-esm/types.d.ts +64 -25
  85. package/lib-esm/types.js +9 -2
  86. package/lib-esm/types.js.map +1 -1
  87. package/lib-esm/util.d.ts +56 -24
  88. package/lib-esm/util.js +334 -170
  89. package/lib-esm/util.js.map +1 -1
  90. package/package.json +7 -7
  91. package/src/datastore/datastore.ts +253 -113
  92. package/src/predicates/index.ts +32 -10
  93. package/src/storage/adapter/AsyncStorageAdapter.ts +309 -93
  94. package/src/storage/adapter/AsyncStorageDatabase.ts +74 -26
  95. package/src/storage/adapter/IndexedDBAdapter.ts +319 -136
  96. package/src/storage/adapter/index.ts +1 -1
  97. package/src/storage/storage.ts +68 -21
  98. package/src/sync/index.ts +41 -26
  99. package/src/sync/merger.ts +14 -4
  100. package/src/sync/outbox.ts +21 -8
  101. package/src/sync/processors/mutation.ts +49 -45
  102. package/src/sync/processors/subscription.ts +0 -1
  103. package/src/sync/processors/sync.ts +1 -3
  104. package/src/sync/utils.ts +69 -12
  105. package/src/types.ts +181 -29
  106. package/src/util.ts +415 -176
package/lib-esm/util.js CHANGED
@@ -50,10 +50,6 @@ var __read = (this && this.__read) || function (o, n) {
50
50
  }
51
51
  return ar;
52
52
  };
53
- var __spread = (this && this.__spread) || function () {
54
- for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
55
- return ar;
56
- };
57
53
  var __values = (this && this.__values) || function(o) {
58
54
  var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
59
55
  if (m) return m.call(o);
@@ -65,12 +61,37 @@ var __values = (this && this.__values) || function(o) {
65
61
  };
66
62
  throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
67
63
  };
64
+ var __spread = (this && this.__spread) || function () {
65
+ for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
66
+ return ar;
67
+ };
68
68
  import { Buffer } from 'buffer';
69
69
  import { monotonicFactory } from 'ulid';
70
70
  import { v4 as uuid } from 'uuid';
71
71
  import { produce, applyPatches } from 'immer';
72
72
  import { isPredicateGroup, isPredicateObj, SortDirection, isModelAttributeKey, isModelAttributePrimaryKey, isModelAttributeCompositeKey, LimitTimerRaceResolvedValues, } from './types';
73
73
  import { WordArray } from 'amazon-cognito-identity-js';
74
+ export var ID = 'id';
75
+ /**
76
+ * Used by the Async Storage Adapter to concatenate key values
77
+ * for a record. For instance, if a model has the following keys:
78
+ * `customId: ID! @primaryKey(sortKeyFields: ["createdAt"])`,
79
+ * we concatenate the `customId` and `createdAt` as:
80
+ * `12-234-5#2022-09-28T00:00:00.000Z`
81
+ */
82
+ export var DEFAULT_PRIMARY_KEY_VALUE_SEPARATOR = '#';
83
+ /**
84
+ * Used for generating spinal-cased index name from an array of
85
+ * key field names.
86
+ * E.g. for keys `[id, title]` => 'id-title'
87
+ */
88
+ export var IDENTIFIER_KEY_SEPARATOR = '-';
89
+ export var errorMessages = {
90
+ idEmptyString: 'An index field cannot contain an empty string value',
91
+ 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',
92
+ 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',
93
+ 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',
94
+ };
74
95
  export var NAMESPACES;
75
96
  (function (NAMESPACES) {
76
97
  NAMESPACES["DATASTORE"] = "datastore";
@@ -168,148 +189,6 @@ export function registerNonModelClass(clazz) {
168
189
  export var isNonModelConstructor = function (obj) {
169
190
  return nonModelClasses.has(obj);
170
191
  };
171
- /*
172
- When we have GSI(s) with composite sort keys defined on a model
173
- There are some very particular rules regarding which fields must be included in the update mutation input
174
- The field selection becomes more complex as the number of GSIs with composite sort keys grows
175
-
176
- To summarize: any time we update a field that is part of the composite sort key of a GSI, we must include:
177
- 1. all of the other fields in that composite sort key
178
- 2. all of the fields from any other composite sort key that intersect with the fields from 1.
179
-
180
- E.g.,
181
- Model @model
182
- @key(name: 'key1' fields: ['hk', 'a', 'b', 'c'])
183
- @key(name: 'key2' fields: ['hk', 'a', 'b', 'd'])
184
- @key(name: 'key3' fields: ['hk', 'x', 'y', 'z'])
185
-
186
- Model.a is updated => include ['a', 'b', 'c', 'd']
187
- Model.c is updated => include ['a', 'b', 'c', 'd']
188
- Model.d is updated => include ['a', 'b', 'c', 'd']
189
- Model.x is updated => include ['x', 'y', 'z']
190
-
191
- This function accepts a model's attributes and returns grouped sets of composite key fields
192
- Using our example Model above, the function will return:
193
- [
194
- Set('a', 'b', 'c', 'd'),
195
- Set('x', 'y', 'z'),
196
- ]
197
-
198
- This gives us the opportunity to correctly include the required fields for composite keys
199
- When crafting the mutation input in Storage.getUpdateMutationInput
200
-
201
- See 'processCompositeKeys' test in util.test.ts for more examples
202
- */
203
- export var processCompositeKeys = function (attributes) {
204
- var extractCompositeSortKey = function (_c) {
205
- var
206
- // ignore the HK (fields[0]) we only need to include the composite sort key fields[1...n]
207
- _d = __read(_c.properties.fields), sortKeyFields = _d.slice(1);
208
- return sortKeyFields;
209
- };
210
- var compositeKeyFields = attributes
211
- .filter(isModelAttributeCompositeKey)
212
- .map(extractCompositeSortKey);
213
- /*
214
- if 2 sets of fields have any intersecting fields => combine them into 1 union set
215
- e.g., ['a', 'b', 'c'] and ['a', 'b', 'd'] => ['a', 'b', 'c', 'd']
216
- */
217
- var combineIntersecting = function (fields) {
218
- return fields.reduce(function (combined, sortKeyFields) {
219
- var sortKeyFieldsSet = new Set(sortKeyFields);
220
- if (combined.length === 0) {
221
- combined.push(sortKeyFieldsSet);
222
- return combined;
223
- }
224
- // does the current set share values with another set we've already added to `combined`?
225
- var intersectingSetIdx = combined.findIndex(function (existingSet) {
226
- return __spread(existingSet).some(function (f) { return sortKeyFieldsSet.has(f); });
227
- });
228
- if (intersectingSetIdx > -1) {
229
- var union = new Set(__spread(combined[intersectingSetIdx], sortKeyFieldsSet));
230
- // combine the current set with the intersecting set we found above
231
- combined[intersectingSetIdx] = union;
232
- }
233
- else {
234
- // none of the sets in `combined` have intersecting values with the current set
235
- combined.push(sortKeyFieldsSet);
236
- }
237
- return combined;
238
- }, []);
239
- };
240
- var initial = combineIntersecting(compositeKeyFields);
241
- // a single pass pay not be enough to correctly combine all the fields
242
- // call the function once more to get a final merged list of sets
243
- var combined = combineIntersecting(initial);
244
- return combined;
245
- };
246
- export var establishRelationAndKeys = function (namespace) {
247
- var relationship = {};
248
- var keys = {};
249
- Object.keys(namespace.models).forEach(function (mKey) {
250
- var e_1, _c, e_2, _d;
251
- relationship[mKey] = { indexes: [], relationTypes: [] };
252
- keys[mKey] = {};
253
- var model = namespace.models[mKey];
254
- Object.keys(model.fields).forEach(function (attr) {
255
- var fieldAttribute = model.fields[attr];
256
- if (typeof fieldAttribute.type === 'object' &&
257
- 'model' in fieldAttribute.type) {
258
- var connectionType = fieldAttribute.association.connectionType;
259
- relationship[mKey].relationTypes.push({
260
- fieldName: fieldAttribute.name,
261
- modelName: fieldAttribute.type.model,
262
- relationType: connectionType,
263
- targetName: fieldAttribute.association['targetName'],
264
- associatedWith: fieldAttribute.association['associatedWith'],
265
- });
266
- if (connectionType === 'BELONGS_TO') {
267
- relationship[mKey].indexes.push(fieldAttribute.association['targetName']);
268
- }
269
- }
270
- });
271
- if (model.attributes) {
272
- keys[mKey].compositeKeys = processCompositeKeys(model.attributes);
273
- try {
274
- for (var _e = __values(model.attributes), _f = _e.next(); !_f.done; _f = _e.next()) {
275
- var attribute = _f.value;
276
- if (!isModelAttributeKey(attribute)) {
277
- continue;
278
- }
279
- if (isModelAttributePrimaryKey(attribute)) {
280
- keys[mKey].primaryKey = attribute.properties.fields;
281
- }
282
- var fields = attribute.properties.fields;
283
- try {
284
- 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()) {
285
- var field = fields_1_1.value;
286
- // only add index if it hasn't already been added
287
- var exists = relationship[mKey].indexes.includes(field);
288
- if (!exists) {
289
- relationship[mKey].indexes.push(field);
290
- }
291
- }
292
- }
293
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
294
- finally {
295
- try {
296
- if (fields_1_1 && !fields_1_1.done && (_d = fields_1.return)) _d.call(fields_1);
297
- }
298
- finally { if (e_2) throw e_2.error; }
299
- }
300
- }
301
- }
302
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
303
- finally {
304
- try {
305
- if (_f && !_f.done && (_c = _e.return)) _c.call(_e);
306
- }
307
- finally { if (e_1) throw e_1.error; }
308
- }
309
- }
310
- });
311
- return [relationship, keys];
312
- };
313
192
  var topologicallySortedModels = new WeakMap();
314
193
  export var traverseModel = function (srcModelName, instance, namespace, modelInstanceCreator, getModelConstructorByModelName) {
315
194
  var relationships = namespace.relationships;
@@ -335,12 +214,26 @@ export var traverseModel = function (srcModelName, instance, namespace, modelIns
335
214
  item: instance[rItem.fieldName],
336
215
  instance: modelInstance,
337
216
  });
338
- // targetName will be defined for Has One if feature flag
217
+ var targetNames = extractTargetNamesFromSrc(rItem);
218
+ // `targetName` will be defined for Has One if feature flag
339
219
  // https://docs.amplify.aws/cli/reference/feature-flags/#useAppsyncModelgenPlugin
340
220
  // is true (default as of 5/7/21)
341
221
  // Making this conditional for backward-compatibility
342
- if (rItem.targetName) {
343
- draftInstance[rItem.targetName] = (draftInstance[rItem.fieldName]).id;
222
+ if (targetNames) {
223
+ targetNames.forEach(function (targetName, idx) {
224
+ // Get the connected record
225
+ var relatedRecordInProxy = (draftInstance[rItem.fieldName]);
226
+ // Previously, we used the hardcoded 'id' as they key,
227
+ // now we need the value of the key to get the PK (and SK)
228
+ // values from the related record
229
+ var primaryKey = namespace.keys[modelConstructor.name].primaryKey;
230
+ var keyField = primaryKey && primaryKey[idx];
231
+ // Get the value
232
+ var relatedRecordInProxyPkValue = relatedRecordInProxy[keyField];
233
+ // Set the targetName value
234
+ draftInstance[targetName] = relatedRecordInProxyPkValue;
235
+ });
236
+ // Delete the instance from the proxy
344
237
  delete draftInstance[rItem.fieldName];
345
238
  }
346
239
  else {
@@ -367,8 +260,25 @@ export var traverseModel = function (srcModelName, instance, namespace, modelIns
367
260
  }
368
261
  }
369
262
  if (draftInstance[rItem.fieldName]) {
370
- draftInstance[rItem.targetName] = (draftInstance[rItem.fieldName]).id;
371
- delete draftInstance[rItem.fieldName];
263
+ var targetNames = extractTargetNamesFromSrc(rItem);
264
+ if (targetNames) {
265
+ targetNames.forEach(function (targetName, idx) {
266
+ // Get the connected record
267
+ var relatedRecordInProxy = (draftInstance[rItem.fieldName]);
268
+ // Previously, we used the hardcoded `id` for the key.
269
+ // Now, we need the value of the key to get the PK (and SK)
270
+ // values from the related record
271
+ var primaryKey = namespace.keys[modelConstructor.name].primaryKey;
272
+ // fall back to ID if
273
+ var keyField = primaryKey && primaryKey[idx];
274
+ // Get the value
275
+ var relatedRecordInProxyPkValue = relatedRecordInProxy[keyField];
276
+ // Set the targetName value
277
+ draftInstance[targetName] = relatedRecordInProxyPkValue;
278
+ });
279
+ // Delete the instance from the proxy
280
+ delete draftInstance[rItem.fieldName];
281
+ }
372
282
  }
373
283
  break;
374
284
  case 'HAS_MANY':
@@ -394,19 +304,6 @@ export var traverseModel = function (srcModelName, instance, namespace, modelIns
394
304
  });
395
305
  return result;
396
306
  };
397
- export var getIndex = function (rel, src) {
398
- var index = '';
399
- rel.some(function (relItem) {
400
- if (relItem.modelName === src) {
401
- index = relItem.targetName;
402
- }
403
- });
404
- return index;
405
- };
406
- export var getIndexFromAssociation = function (indexes, src) {
407
- var index = indexes.find(function (idx) { return idx === src; });
408
- return index;
409
- };
410
307
  var privateModeCheckResult;
411
308
  export var isPrivateMode = function () {
412
309
  return new Promise(function (resolve) {
@@ -480,7 +377,7 @@ export function getNow() {
480
377
  }
481
378
  export function sortCompareFunction(sortPredicates) {
482
379
  return function compareFunction(a, b) {
483
- var e_3, _c;
380
+ var e_1, _c;
484
381
  try {
485
382
  // enable multi-field sort by iterating over predicates until
486
383
  // a comparison returns -1 or 1
@@ -497,12 +394,12 @@ export function sortCompareFunction(sortPredicates) {
497
394
  }
498
395
  }
499
396
  }
500
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
397
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
501
398
  finally {
502
399
  try {
503
400
  if (sortPredicates_1_1 && !sortPredicates_1_1.done && (_c = sortPredicates_1.return)) _c.call(sortPredicates_1);
504
401
  }
505
- finally { if (e_3) throw e_3.error; }
402
+ finally { if (e_1) throw e_1.error; }
506
403
  }
507
404
  return 0;
508
405
  };
@@ -513,7 +410,7 @@ export function sortCompareFunction(sortPredicates) {
513
410
  // if nullish is true, treat undefined and null values as equal
514
411
  // to normalize for GQL response values for undefined fields
515
412
  export function valuesEqual(valA, valB, nullish) {
516
- var e_4, _c;
413
+ var e_2, _c;
517
414
  if (nullish === void 0) { nullish = false; }
518
415
  var a = valA;
519
416
  var b = valB;
@@ -565,12 +462,12 @@ export function valuesEqual(valA, valB, nullish) {
565
462
  }
566
463
  }
567
464
  }
568
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
465
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
569
466
  finally {
570
467
  try {
571
468
  if (keys_1_1 && !keys_1_1.done && (_c = keys_1.return)) _c.call(keys_1);
572
469
  }
573
- finally { if (e_4) throw e_4.error; }
470
+ finally { if (e_2) throw e_2.error; }
574
471
  }
575
472
  return true;
576
473
  }
@@ -716,4 +613,271 @@ export function mergePatches(originalSource, oldPatches, newPatches) {
716
613
  });
717
614
  return patches;
718
615
  }
616
+ export var getStorename = function (namespace, modelName) {
617
+ var storeName = namespace + "_" + modelName;
618
+ return storeName;
619
+ };
620
+ //#region Key Utils
621
+ /*
622
+ When we have GSI(s) with composite sort keys defined on a model
623
+ There are some very particular rules regarding which fields must be included in the update mutation input
624
+ The field selection becomes more complex as the number of GSIs with composite sort keys grows
625
+
626
+ To summarize: any time we update a field that is part of the composite sort key of a GSI, we must include:
627
+ 1. all of the other fields in that composite sort key
628
+ 2. all of the fields from any other composite sort key that intersect with the fields from 1.
629
+
630
+ E.g.,
631
+ Model @model
632
+ @key(name: 'key1' fields: ['hk', 'a', 'b', 'c'])
633
+ @key(name: 'key2' fields: ['hk', 'a', 'b', 'd'])
634
+ @key(name: 'key3' fields: ['hk', 'x', 'y', 'z'])
635
+
636
+ Model.a is updated => include ['a', 'b', 'c', 'd']
637
+ Model.c is updated => include ['a', 'b', 'c', 'd']
638
+ Model.d is updated => include ['a', 'b', 'c', 'd']
639
+ Model.x is updated => include ['x', 'y', 'z']
640
+
641
+ This function accepts a model's attributes and returns grouped sets of composite key fields
642
+ Using our example Model above, the function will return:
643
+ [
644
+ Set('a', 'b', 'c', 'd'),
645
+ Set('x', 'y', 'z'),
646
+ ]
647
+
648
+ This gives us the opportunity to correctly include the required fields for composite keys
649
+ When crafting the mutation input in Storage.getUpdateMutationInput
650
+
651
+ See 'processCompositeKeys' test in util.test.ts for more examples
652
+ */
653
+ export var processCompositeKeys = function (attributes) {
654
+ var extractCompositeSortKey = function (_c) {
655
+ var
656
+ // ignore the HK (fields[0]) we only need to include the composite sort key fields[1...n]
657
+ _d = __read(_c.properties.fields), sortKeyFields = _d.slice(1);
658
+ return sortKeyFields;
659
+ };
660
+ var compositeKeyFields = attributes
661
+ .filter(isModelAttributeCompositeKey)
662
+ .map(extractCompositeSortKey);
663
+ /*
664
+ if 2 sets of fields have any intersecting fields => combine them into 1 union set
665
+ e.g., ['a', 'b', 'c'] and ['a', 'b', 'd'] => ['a', 'b', 'c', 'd']
666
+ */
667
+ var combineIntersecting = function (fields) {
668
+ return fields.reduce(function (combined, sortKeyFields) {
669
+ var sortKeyFieldsSet = new Set(sortKeyFields);
670
+ if (combined.length === 0) {
671
+ combined.push(sortKeyFieldsSet);
672
+ return combined;
673
+ }
674
+ // does the current set share values with another set we've already added to `combined`?
675
+ var intersectingSetIdx = combined.findIndex(function (existingSet) {
676
+ return __spread(existingSet).some(function (f) { return sortKeyFieldsSet.has(f); });
677
+ });
678
+ if (intersectingSetIdx > -1) {
679
+ var union = new Set(__spread(combined[intersectingSetIdx], sortKeyFieldsSet));
680
+ // combine the current set with the intersecting set we found above
681
+ combined[intersectingSetIdx] = union;
682
+ }
683
+ else {
684
+ // none of the sets in `combined` have intersecting values with the current set
685
+ combined.push(sortKeyFieldsSet);
686
+ }
687
+ return combined;
688
+ }, []);
689
+ };
690
+ var initial = combineIntersecting(compositeKeyFields);
691
+ // a single pass pay not be enough to correctly combine all the fields
692
+ // call the function once more to get a final merged list of sets
693
+ var combined = combineIntersecting(initial);
694
+ return combined;
695
+ };
696
+ export var extractKeyIfExists = function (modelDefinition) {
697
+ var _c;
698
+ var keyAttribute = (_c = modelDefinition === null || modelDefinition === void 0 ? void 0 : modelDefinition.attributes) === null || _c === void 0 ? void 0 : _c.find(isModelAttributeKey);
699
+ return keyAttribute;
700
+ };
701
+ export var extractPrimaryKeyFieldNames = function (modelDefinition) {
702
+ var keyAttribute = extractKeyIfExists(modelDefinition);
703
+ if (keyAttribute && isModelAttributePrimaryKey(keyAttribute)) {
704
+ return keyAttribute.properties.fields;
705
+ }
706
+ return [ID];
707
+ };
708
+ export var extractPrimaryKeyValues = function (model, keyFields) {
709
+ return keyFields.map(function (key) { return model[key]; });
710
+ };
711
+ export var extractPrimaryKeysAndValues = function (model, keyFields) {
712
+ var primaryKeysAndValues = {};
713
+ keyFields.forEach(function (key) { return (primaryKeysAndValues[key] = model[key]); });
714
+ return primaryKeysAndValues;
715
+ };
716
+ // IdentifierFields<ManagedIdentifier>
717
+ // Default behavior without explicit @primaryKey defined
718
+ export var isIdManaged = function (modelDefinition) {
719
+ var keyAttribute = extractKeyIfExists(modelDefinition);
720
+ if (keyAttribute && isModelAttributePrimaryKey(keyAttribute)) {
721
+ return false;
722
+ }
723
+ return true;
724
+ };
725
+ // IdentifierFields<OptionallyManagedIdentifier>
726
+ // @primaryKey with explicit `id` in the PK. Single key or composite
727
+ export var isIdOptionallyManaged = function (modelDefinition) {
728
+ var keyAttribute = extractKeyIfExists(modelDefinition);
729
+ if (keyAttribute && isModelAttributePrimaryKey(keyAttribute)) {
730
+ return keyAttribute.properties.fields[0] === ID;
731
+ }
732
+ return false;
733
+ };
734
+ export var establishRelationAndKeys = function (namespace) {
735
+ var relationship = {};
736
+ var keys = {};
737
+ Object.keys(namespace.models).forEach(function (mKey) {
738
+ var e_3, _c;
739
+ relationship[mKey] = { indexes: [], relationTypes: [] };
740
+ keys[mKey] = {};
741
+ var model = namespace.models[mKey];
742
+ Object.keys(model.fields).forEach(function (attr) {
743
+ var fieldAttribute = model.fields[attr];
744
+ if (typeof fieldAttribute.type === 'object' &&
745
+ 'model' in fieldAttribute.type) {
746
+ var connectionType = fieldAttribute.association.connectionType;
747
+ relationship[mKey].relationTypes.push({
748
+ fieldName: fieldAttribute.name,
749
+ modelName: fieldAttribute.type.model,
750
+ relationType: connectionType,
751
+ targetName: fieldAttribute.association['targetName'],
752
+ targetNames: fieldAttribute.association['targetNames'],
753
+ associatedWith: fieldAttribute.association['associatedWith'],
754
+ });
755
+ if (connectionType === 'BELONGS_TO') {
756
+ var targetNames = extractTargetNamesFromSrc(fieldAttribute.association);
757
+ if (targetNames) {
758
+ var idxName = indexNameFromKeys(targetNames);
759
+ relationship[mKey].indexes.push([idxName, targetNames]);
760
+ }
761
+ }
762
+ }
763
+ });
764
+ if (model.attributes) {
765
+ keys[mKey].compositeKeys = processCompositeKeys(model.attributes);
766
+ var _loop_1 = function (attribute) {
767
+ if (!isModelAttributeKey(attribute)) {
768
+ return "continue";
769
+ }
770
+ var fields = attribute.properties.fields;
771
+ if (isModelAttributePrimaryKey(attribute)) {
772
+ keys[mKey].primaryKey = fields;
773
+ return "continue";
774
+ }
775
+ // create indexes for all other keys
776
+ var idxName = indexNameFromKeys(fields);
777
+ var idxExists = relationship[mKey].indexes.find(function (_c) {
778
+ var _d = __read(_c, 1), index = _d[0];
779
+ return index === idxName;
780
+ });
781
+ if (!idxExists) {
782
+ relationship[mKey].indexes.push([idxName, fields]);
783
+ }
784
+ };
785
+ try {
786
+ for (var _d = __values(model.attributes), _e = _d.next(); !_e.done; _e = _d.next()) {
787
+ var attribute = _e.value;
788
+ _loop_1(attribute);
789
+ }
790
+ }
791
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
792
+ finally {
793
+ try {
794
+ if (_e && !_e.done && (_c = _d.return)) _c.call(_d);
795
+ }
796
+ finally { if (e_3) throw e_3.error; }
797
+ }
798
+ }
799
+ // set 'id' as the PK for models without a custom PK explicitly defined
800
+ if (!keys[mKey].primaryKey) {
801
+ keys[mKey].primaryKey = [ID];
802
+ }
803
+ // create primary index
804
+ relationship[mKey].indexes.push([
805
+ 'byPk',
806
+ keys[mKey].primaryKey,
807
+ { unique: true },
808
+ ]);
809
+ });
810
+ return [relationship, keys];
811
+ };
812
+ export var getIndex = function (rel, src) {
813
+ var indexName;
814
+ rel.some(function (relItem) {
815
+ if (relItem.modelName === src) {
816
+ var targetNames = extractTargetNamesFromSrc(relItem);
817
+ indexName = targetNames && indexNameFromKeys(targetNames);
818
+ return true;
819
+ }
820
+ });
821
+ return indexName;
822
+ };
823
+ export var getIndexFromAssociation = function (indexes, src) {
824
+ var indexName;
825
+ if (Array.isArray(src)) {
826
+ indexName = indexNameFromKeys(src);
827
+ }
828
+ else {
829
+ indexName = src;
830
+ }
831
+ var associationIndex = indexes.find(function (_c) {
832
+ var _d = __read(_c, 1), idxName = _d[0];
833
+ return idxName === indexName;
834
+ });
835
+ return associationIndex && associationIndex[0];
836
+ };
837
+ /**
838
+ * Backwards-compatability for schema generated prior to custom primary key support:
839
+ the single field `targetName` has been replaced with an array of `targetNames`.
840
+ `targetName` and `targetNames` are exclusive (will never exist on the same schema)
841
+ * @param src {RelationType | ModelAssociation | undefined}
842
+ * @returns array of targetNames, or `undefined`
843
+ */
844
+ export var extractTargetNamesFromSrc = function (src) {
845
+ var targetName = src === null || src === void 0 ? void 0 : src.targetName;
846
+ var targetNames = src === null || src === void 0 ? void 0 : src.targetNames;
847
+ if (Array.isArray(targetNames)) {
848
+ return targetNames;
849
+ }
850
+ else if (typeof targetName === 'string') {
851
+ return [targetName];
852
+ }
853
+ else {
854
+ return undefined;
855
+ }
856
+ };
857
+ // Generates spinal-cased index name from an array of key field names
858
+ // E.g. for keys `[id, title]` => 'id-title'
859
+ export var indexNameFromKeys = function (keys) {
860
+ return keys.reduce(function (prev, cur, idx) {
861
+ if (idx === 0) {
862
+ return cur;
863
+ }
864
+ return "" + prev + IDENTIFIER_KEY_SEPARATOR + cur;
865
+ }, '');
866
+ };
867
+ export var keysEqual = function (keysA, keysB) {
868
+ if (keysA.length !== keysB.length) {
869
+ return false;
870
+ }
871
+ return keysA.every(function (key, idx) { return key === keysB[idx]; });
872
+ };
873
+ // Returns primary keys for a model
874
+ export var getIndexKeys = function (namespace, modelName) {
875
+ var _c;
876
+ var keyPath = (_c = namespace === null || namespace === void 0 ? void 0 : namespace.keys[modelName]) === null || _c === void 0 ? void 0 : _c.primaryKey;
877
+ if (keyPath) {
878
+ return keyPath;
879
+ }
880
+ return [ID];
881
+ };
882
+ //#endregion
719
883
  //# sourceMappingURL=util.js.map