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