@aws-amplify/datastore 3.7.3 → 3.7.4-custom-pk.79

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 (137) hide show
  1. package/CHANGELOG.md +144 -17
  2. package/README.md +154 -0
  3. package/dist/aws-amplify-datastore.js +3344 -1405
  4. package/dist/aws-amplify-datastore.js.map +1 -1
  5. package/dist/aws-amplify-datastore.min.js +25 -95
  6. package/dist/aws-amplify-datastore.min.js.map +1 -1
  7. package/lib/authModeStrategies/multiAuthStrategy.d.ts +2 -2
  8. package/lib/authModeStrategies/multiAuthStrategy.js +32 -26
  9. package/lib/authModeStrategies/multiAuthStrategy.js.map +1 -1
  10. package/lib/datastore/datastore.d.ts +17 -16
  11. package/lib/datastore/datastore.js +250 -78
  12. package/lib/datastore/datastore.js.map +1 -1
  13. package/lib/index.d.ts +3 -19
  14. package/lib/predicates/index.d.ts +3 -2
  15. package/lib/predicates/index.js +12 -2
  16. package/lib/predicates/index.js.map +1 -1
  17. package/lib/storage/adapter/AsyncStorageAdapter.d.ts +6 -2
  18. package/lib/storage/adapter/AsyncStorageAdapter.js +140 -66
  19. package/lib/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  20. package/lib/storage/adapter/AsyncStorageDatabase.d.ts +4 -4
  21. package/lib/storage/adapter/AsyncStorageDatabase.js +57 -27
  22. package/lib/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  23. package/lib/storage/adapter/InMemoryStore.js +2 -2
  24. package/lib/storage/adapter/InMemoryStore.js.map +1 -1
  25. package/lib/storage/adapter/IndexedDBAdapter.d.ts +7 -2
  26. package/lib/storage/adapter/IndexedDBAdapter.js +460 -253
  27. package/lib/storage/adapter/IndexedDBAdapter.js.map +1 -1
  28. package/lib/storage/adapter/index.d.ts +1 -1
  29. package/lib/storage/storage.d.ts +3 -3
  30. package/lib/storage/storage.js +106 -28
  31. package/lib/storage/storage.js.map +1 -1
  32. package/lib/sync/index.d.ts +23 -7
  33. package/lib/sync/index.js +18 -17
  34. package/lib/sync/index.js.map +1 -1
  35. package/lib/sync/merger.d.ts +3 -3
  36. package/lib/sync/merger.js +8 -6
  37. package/lib/sync/merger.js.map +1 -1
  38. package/lib/sync/outbox.d.ts +2 -2
  39. package/lib/sync/outbox.js +12 -9
  40. package/lib/sync/outbox.js.map +1 -1
  41. package/lib/sync/processors/errorMaps.d.ts +17 -0
  42. package/lib/sync/processors/errorMaps.js +125 -0
  43. package/lib/sync/processors/errorMaps.js.map +1 -0
  44. package/lib/sync/processors/mutation.d.ts +22 -4
  45. package/lib/sync/processors/mutation.js +119 -51
  46. package/lib/sync/processors/mutation.js.map +1 -1
  47. package/lib/sync/processors/subscription.d.ts +4 -2
  48. package/lib/sync/processors/subscription.js +76 -41
  49. package/lib/sync/processors/subscription.js.map +1 -1
  50. package/lib/sync/processors/sync.d.ts +4 -2
  51. package/lib/sync/processors/sync.js +62 -27
  52. package/lib/sync/processors/sync.js.map +1 -1
  53. package/lib/sync/utils.d.ts +3 -2
  54. package/lib/sync/utils.js +54 -7
  55. package/lib/sync/utils.js.map +1 -1
  56. package/lib/types.d.ts +85 -33
  57. package/lib/types.js +31 -2
  58. package/lib/types.js.map +1 -1
  59. package/lib/util.d.ts +43 -33
  60. package/lib/util.js +161 -21
  61. package/lib/util.js.map +1 -1
  62. package/lib-esm/authModeStrategies/multiAuthStrategy.d.ts +2 -2
  63. package/lib-esm/authModeStrategies/multiAuthStrategy.js +32 -26
  64. package/lib-esm/authModeStrategies/multiAuthStrategy.js.map +1 -1
  65. package/lib-esm/datastore/datastore.d.ts +17 -16
  66. package/lib-esm/datastore/datastore.js +252 -80
  67. package/lib-esm/datastore/datastore.js.map +1 -1
  68. package/lib-esm/index.d.ts +3 -19
  69. package/lib-esm/predicates/index.d.ts +3 -2
  70. package/lib-esm/predicates/index.js +13 -3
  71. package/lib-esm/predicates/index.js.map +1 -1
  72. package/lib-esm/storage/adapter/AsyncStorageAdapter.d.ts +6 -2
  73. package/lib-esm/storage/adapter/AsyncStorageAdapter.js +140 -66
  74. package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  75. package/lib-esm/storage/adapter/AsyncStorageDatabase.d.ts +4 -4
  76. package/lib-esm/storage/adapter/AsyncStorageDatabase.js +57 -27
  77. package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  78. package/lib-esm/storage/adapter/InMemoryStore.js +2 -2
  79. package/lib-esm/storage/adapter/InMemoryStore.js.map +1 -1
  80. package/lib-esm/storage/adapter/IndexedDBAdapter.d.ts +7 -2
  81. package/lib-esm/storage/adapter/IndexedDBAdapter.js +460 -253
  82. package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +1 -1
  83. package/lib-esm/storage/adapter/index.d.ts +1 -1
  84. package/lib-esm/storage/storage.d.ts +3 -3
  85. package/lib-esm/storage/storage.js +106 -28
  86. package/lib-esm/storage/storage.js.map +1 -1
  87. package/lib-esm/sync/index.d.ts +23 -7
  88. package/lib-esm/sync/index.js +20 -19
  89. package/lib-esm/sync/index.js.map +1 -1
  90. package/lib-esm/sync/merger.d.ts +3 -3
  91. package/lib-esm/sync/merger.js +8 -6
  92. package/lib-esm/sync/merger.js.map +1 -1
  93. package/lib-esm/sync/outbox.d.ts +2 -2
  94. package/lib-esm/sync/outbox.js +13 -10
  95. package/lib-esm/sync/outbox.js.map +1 -1
  96. package/lib-esm/sync/processors/errorMaps.d.ts +17 -0
  97. package/lib-esm/sync/processors/errorMaps.js +119 -0
  98. package/lib-esm/sync/processors/errorMaps.js.map +1 -0
  99. package/lib-esm/sync/processors/mutation.d.ts +22 -4
  100. package/lib-esm/sync/processors/mutation.js +122 -54
  101. package/lib-esm/sync/processors/mutation.js.map +1 -1
  102. package/lib-esm/sync/processors/subscription.d.ts +4 -2
  103. package/lib-esm/sync/processors/subscription.js +77 -42
  104. package/lib-esm/sync/processors/subscription.js.map +1 -1
  105. package/lib-esm/sync/processors/sync.d.ts +4 -2
  106. package/lib-esm/sync/processors/sync.js +62 -27
  107. package/lib-esm/sync/processors/sync.js.map +1 -1
  108. package/lib-esm/sync/utils.d.ts +3 -2
  109. package/lib-esm/sync/utils.js +54 -8
  110. package/lib-esm/sync/utils.js.map +1 -1
  111. package/lib-esm/types.d.ts +85 -33
  112. package/lib-esm/types.js +29 -3
  113. package/lib-esm/types.js.map +1 -1
  114. package/lib-esm/util.d.ts +43 -33
  115. package/lib-esm/util.js +151 -18
  116. package/lib-esm/util.js.map +1 -1
  117. package/package.json +10 -9
  118. package/src/authModeStrategies/multiAuthStrategy.ts +24 -21
  119. package/src/datastore/datastore.ts +396 -143
  120. package/src/predicates/index.ts +32 -10
  121. package/src/storage/adapter/AsyncStorageAdapter.ts +161 -61
  122. package/src/storage/adapter/AsyncStorageDatabase.ts +62 -25
  123. package/src/storage/adapter/InMemoryStore.ts +2 -2
  124. package/src/storage/adapter/IndexedDBAdapter.ts +355 -101
  125. package/src/storage/adapter/index.ts +1 -1
  126. package/src/storage/storage.ts +85 -24
  127. package/src/sync/index.ts +74 -58
  128. package/src/sync/merger.ts +16 -4
  129. package/src/sync/outbox.ts +22 -8
  130. package/src/sync/processors/errorMaps.ts +93 -0
  131. package/src/sync/processors/mutation.ts +143 -84
  132. package/src/sync/processors/subscription.ts +67 -36
  133. package/src/sync/processors/sync.ts +37 -12
  134. package/src/sync/utils.ts +63 -15
  135. package/src/types.ts +242 -49
  136. package/src/util.ts +212 -35
  137. package/ssr/package.json +1 -1
package/src/util.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  import { Buffer } from 'buffer';
2
2
  import { monotonicFactory, ULID } from 'ulid';
3
3
  import { v4 as uuid } from 'uuid';
4
+ import { produce, applyPatches, Patch } from 'immer';
4
5
  import { ModelInstanceCreator } from './datastore/datastore';
5
6
  import {
6
7
  AllOperators,
7
8
  isPredicateGroup,
8
9
  isPredicateObj,
10
+ ModelAssociation,
9
11
  ModelInstanceMetadata,
10
12
  PersistentModel,
11
13
  PersistentModelConstructor,
@@ -25,8 +27,80 @@ import {
25
27
  NonModelTypeConstructor,
26
28
  DeferredCallbackResolverOptions,
27
29
  LimitTimerRaceResolvedValues,
30
+ SchemaModel,
31
+ ModelAttribute,
28
32
  } from './types';
29
33
  import { WordArray } from 'amazon-cognito-identity-js';
34
+ const ID = 'id';
35
+
36
+ export function extractKeyIfExists(
37
+ modelDefinition: SchemaModel
38
+ ): ModelAttribute | undefined {
39
+ const keyAttribute = modelDefinition?.attributes?.find(isModelAttributeKey);
40
+
41
+ return keyAttribute;
42
+ }
43
+
44
+ export function extractPrimaryKeyFieldNames(
45
+ modelDefinition: SchemaModel
46
+ ): string[] {
47
+ const keyAttribute = extractKeyIfExists(modelDefinition);
48
+ if (keyAttribute && isModelAttributePrimaryKey(keyAttribute)) {
49
+ return keyAttribute.properties.fields;
50
+ }
51
+
52
+ return [ID];
53
+ }
54
+
55
+ export function extractPrimaryKeyValues<T extends PersistentModel>(
56
+ model: T,
57
+ keyFields: string[]
58
+ ): string[] {
59
+ return keyFields.map(key => model[key]);
60
+ }
61
+
62
+ // IdentifierFields<ManagedIdentifier>
63
+ // Default behavior without explicit @primaryKey defined
64
+ export function isIdManaged(modelDefinition: SchemaModel): boolean {
65
+ const keyAttribute = extractKeyIfExists(modelDefinition);
66
+
67
+ if (keyAttribute && isModelAttributePrimaryKey(keyAttribute)) {
68
+ return false;
69
+ }
70
+
71
+ return true;
72
+ }
73
+
74
+ // IdentifierFields<OptionallyManagedIdentifier>
75
+ // @primaryKey with explicit `id` in the PK. Single key or composite
76
+ export function isIdOptionallyManaged(modelDefinition: SchemaModel): boolean {
77
+ const keyAttribute = extractKeyIfExists(modelDefinition);
78
+
79
+ if (keyAttribute && isModelAttributePrimaryKey(keyAttribute)) {
80
+ // const idInKey = !!keyAttribute.properties.fields.find(
81
+ // field => field === ID
82
+ // );
83
+ // return idInKey && keyAttribute.properties.fields.length === 1;
84
+ return keyAttribute.properties.fields[0] === ID;
85
+ }
86
+
87
+ return false;
88
+ }
89
+
90
+ export enum NAMESPACES {
91
+ DATASTORE = 'datastore',
92
+ USER = 'user',
93
+ SYNC = 'sync',
94
+ STORAGE = 'storage',
95
+ }
96
+
97
+ const DATASTORE = NAMESPACES.DATASTORE;
98
+ const USER = NAMESPACES.USER;
99
+ const SYNC = NAMESPACES.SYNC;
100
+ const STORAGE = NAMESPACES.STORAGE;
101
+
102
+ export { USER, SYNC, STORAGE, DATASTORE };
103
+ export const USER_AGENT_SUFFIX_DATASTORE = '/DataStore';
30
104
 
31
105
  export const exhaustiveCheck = (obj: never, throwOnError: boolean = true) => {
32
106
  if (throwOnError) {
@@ -146,7 +220,7 @@ export const isNonModelConstructor = (
146
220
  return nonModelClasses.has(obj);
147
221
  };
148
222
 
149
- /*
223
+ /*
150
224
  When we have GSI(s) with composite sort keys defined on a model
151
225
  There are some very particular rules regarding which fields must be included in the update mutation input
152
226
  The field selection becomes more complex as the number of GSIs with composite sort keys grows
@@ -156,7 +230,7 @@ export const isNonModelConstructor = (
156
230
  2. all of the fields from any other composite sort key that intersect with the fields from 1.
157
231
 
158
232
  E.g.,
159
- Model @model
233
+ Model @model
160
234
  @key(name: 'key1' fields: ['hk', 'a', 'b', 'c'])
161
235
  @key(name: 'key2' fields: ['hk', 'a', 'b', 'd'])
162
236
  @key(name: 'key3' fields: ['hk', 'x', 'y', 'z'])
@@ -192,7 +266,7 @@ export const processCompositeKeys = (
192
266
  .filter(isModelAttributeCompositeKey)
193
267
  .map(extractCompositeSortKey);
194
268
 
195
- /*
269
+ /*
196
270
  if 2 sets of fields have any intersecting fields => combine them into 1 union set
197
271
  e.g., ['a', 'b', 'c'] and ['a', 'b', 'd'] => ['a', 'b', 'c', 'd']
198
272
  */
@@ -256,13 +330,31 @@ export const establishRelationAndKeys = (
256
330
  modelName: fieldAttribute.type.model,
257
331
  relationType: connectionType,
258
332
  targetName: fieldAttribute.association['targetName'],
333
+ targetNames: fieldAttribute.association['targetNames'],
259
334
  associatedWith: fieldAttribute.association['associatedWith'],
260
335
  });
261
336
 
262
337
  if (connectionType === 'BELONGS_TO') {
263
- relationship[mKey].indexes.push(
264
- fieldAttribute.association['targetName']
265
- );
338
+ // const targetNames: string[] = extractTargetNamesFromSrc(
339
+ // fieldAttribute.association
340
+ // );
341
+
342
+ // targetNames.forEach((targetName: string) => {
343
+ // relationship[mKey].indexes.push(targetName);
344
+ // });
345
+ if (fieldAttribute.association.targetName) {
346
+ // backwards-compatability for schema generated prior to custom primary key support
347
+ relationship[mKey].indexes.push(
348
+ fieldAttribute.association['targetName']
349
+ );
350
+ } else {
351
+ // iterate through fieldAttribute.association.targetNames, and push to relationship[mKey].indexes
352
+ fieldAttribute.association.targetNames.forEach(
353
+ (targetName: string) => {
354
+ relationship[mKey].indexes.push(targetName);
355
+ }
356
+ );
357
+ }
266
358
  }
267
359
  }
268
360
  });
@@ -288,6 +380,10 @@ export const establishRelationAndKeys = (
288
380
  }
289
381
  }
290
382
  }
383
+
384
+ if (!keys[mKey].primaryKey) {
385
+ keys[mKey].primaryKey = [ID];
386
+ }
291
387
  }
292
388
  });
293
389
 
@@ -307,12 +403,14 @@ export const traverseModel = <T extends PersistentModel>(
307
403
  ) => PersistentModelConstructor<any>
308
404
  ) => {
309
405
  const relationships = namespace.relationships;
406
+
310
407
  const modelConstructor = getModelConstructorByModelName(
311
408
  namespace.name,
312
409
  srcModelName
313
410
  );
314
411
 
315
412
  const relation = relationships[srcModelName];
413
+
316
414
  const result: {
317
415
  modelName: string;
318
416
  item: T;
@@ -346,15 +444,36 @@ export const traverseModel = <T extends PersistentModel>(
346
444
  instance: modelInstance,
347
445
  });
348
446
 
349
- // targetName will be defined for Has One if feature flag
447
+ const targetNames: string[] | undefined =
448
+ extractTargetNamesFromSrc(rItem);
449
+
450
+ // `targetName` will be defined for Has One if feature flag
350
451
  // https://docs.amplify.aws/cli/reference/feature-flags/#useAppsyncModelgenPlugin
351
452
  // is true (default as of 5/7/21)
352
453
  // Making this conditional for backward-compatibility
353
- if (rItem.targetName) {
354
- (<any>draftInstance)[rItem.targetName] = (<PersistentModel>(
355
- draftInstance[rItem.fieldName]
356
- )).id;
357
- delete draftInstance[rItem.fieldName];
454
+ if (targetNames) {
455
+ targetNames.forEach((targetName, idx) => {
456
+ // Get the connected record
457
+ const relatedRecordInProxy = <PersistentModel>(
458
+ draftInstance[rItem.fieldName]
459
+ );
460
+
461
+ // Previously, we used the hardcoded 'id' as they key,
462
+ // now we need the value of the key to get the PK (and SK)
463
+ // values from the related record
464
+
465
+ const { primaryKey } = namespace.keys[modelConstructor.name];
466
+ const keyField = primaryKey && primaryKey[idx];
467
+
468
+ // Get the value
469
+ const relatedRecordInProxyPkValue =
470
+ relatedRecordInProxy[keyField];
471
+
472
+ // Set the targetName value
473
+ (<any>draftInstance)[targetName] = relatedRecordInProxyPkValue;
474
+ });
475
+ // Delete the instance from the proxy
476
+ delete (<any>draftInstance)[rItem.fieldName];
358
477
  } else {
359
478
  (<any>draftInstance)[rItem.fieldName] = (<PersistentModel>(
360
479
  draftInstance[rItem.fieldName]
@@ -389,10 +508,33 @@ export const traverseModel = <T extends PersistentModel>(
389
508
  }
390
509
 
391
510
  if (draftInstance[rItem.fieldName]) {
392
- (<any>draftInstance)[rItem.targetName] = (<PersistentModel>(
393
- draftInstance[rItem.fieldName]
394
- )).id;
395
- delete draftInstance[rItem.fieldName];
511
+ const targetNames: string[] | undefined =
512
+ extractTargetNamesFromSrc(rItem);
513
+
514
+ if (targetNames) {
515
+ targetNames.forEach((targetName, idx) => {
516
+ // Get the connected record
517
+ const relatedRecordInProxy = <PersistentModel>(
518
+ draftInstance[rItem.fieldName]
519
+ );
520
+ // Previously, we used the hardcoded `id` for the key.
521
+ // Now, we need the value of the key to get the PK (and SK)
522
+ // values from the related record
523
+ const { primaryKey } = namespace.keys[modelConstructor.name];
524
+
525
+ // fall back to ID if
526
+ const keyField = primaryKey && primaryKey[idx];
527
+
528
+ // Get the value
529
+ const relatedRecordInProxyPkValue =
530
+ relatedRecordInProxy[keyField];
531
+
532
+ // Set the targetName value
533
+ (<any>draftInstance)[targetName] = relatedRecordInProxyPkValue;
534
+ });
535
+ // Delete the instance from the proxy
536
+ delete (<any>draftInstance)[rItem.fieldName];
537
+ }
396
538
  }
397
539
 
398
540
  break;
@@ -430,7 +572,7 @@ export const traverseModel = <T extends PersistentModel>(
430
572
  return result;
431
573
  };
432
574
 
433
- export const getIndex = (rel: RelationType[], src: string): string => {
575
+ export const getIndex = (rel: RelationType[], src: any): string => {
434
576
  let index = '';
435
577
  rel.some((relItem: RelationType) => {
436
578
  if (relItem.modelName === src) {
@@ -440,28 +582,11 @@ export const getIndex = (rel: RelationType[], src: string): string => {
440
582
  return index;
441
583
  };
442
584
 
443
- export const getIndexFromAssociation = (
444
- indexes: string[],
445
- src: string
446
- ): string => {
585
+ export const getIndexFromAssociation = (indexes: string[], src: any): any => {
447
586
  const index = indexes.find(idx => idx === src);
448
587
  return index;
449
588
  };
450
589
 
451
- export enum NAMESPACES {
452
- DATASTORE = 'datastore',
453
- USER = 'user',
454
- SYNC = 'sync',
455
- STORAGE = 'storage',
456
- }
457
-
458
- const DATASTORE = NAMESPACES.DATASTORE;
459
- const USER = NAMESPACES.USER;
460
- const SYNC = NAMESPACES.SYNC;
461
- const STORAGE = NAMESPACES.STORAGE;
462
-
463
- export { USER, SYNC, STORAGE, DATASTORE };
464
-
465
590
  let privateModeCheckResult;
466
591
 
467
592
  export const isPrivateMode = () => {
@@ -773,3 +898,55 @@ export class DeferredCallbackResolver {
773
898
  this.limitPromise.resolve(LimitTimerRaceResolvedValues.LIMIT);
774
899
  }
775
900
  }
901
+
902
+ /**
903
+ * merge two sets of patches created by immer produce.
904
+ * newPatches take precedent over oldPatches for patches modifying the same path.
905
+ * In the case many consecutive pathces are merged the original model should
906
+ * always be the root model.
907
+ *
908
+ * Example:
909
+ * A -> B, patches1
910
+ * B -> C, patches2
911
+ *
912
+ * mergePatches(A, patches1, patches2) to get patches for A -> C
913
+ *
914
+ * @param originalSource the original Model the patches should be applied to
915
+ * @param oldPatches immer produce patch list
916
+ * @param newPatches immer produce patch list (will take precedence)
917
+ * @return merged patches
918
+ */
919
+ export function mergePatches<T>(
920
+ originalSource: T,
921
+ oldPatches: Patch[],
922
+ newPatches: Patch[]
923
+ ): Patch[] {
924
+ const patchesToMerge = oldPatches.concat(newPatches);
925
+ let patches: Patch[];
926
+ produce(
927
+ originalSource,
928
+ draft => {
929
+ applyPatches(draft, patchesToMerge);
930
+ },
931
+ p => {
932
+ patches = p;
933
+ }
934
+ );
935
+ return patches;
936
+ }
937
+
938
+ /* Backwards-compatability for schema generated prior to custom primary key support:
939
+ the single field `targetName` has been replaced with an array of `targetNames`
940
+ */
941
+ export function extractTargetNamesFromSrc(src: any): string[] | undefined {
942
+ const targetName = src?.targetName;
943
+ const targetNames = src?.targetNames;
944
+
945
+ if (Array.isArray(targetNames) && targetNames?.length) {
946
+ return targetNames;
947
+ } else if (typeof targetName === 'string') {
948
+ return [targetName];
949
+ } else {
950
+ return undefined;
951
+ }
952
+ }
package/ssr/package.json CHANGED
@@ -5,4 +5,4 @@
5
5
  "react-native": {
6
6
  "../lib/ssr/index": "../lib-esm/ssr/index.js"
7
7
  }
8
- }
8
+ }