@aws-amplify/datastore 4.0.12 → 4.0.13-push-notification-dryrun.43

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 (111) hide show
  1. package/lib/datastore/datastore.d.ts +29 -3
  2. package/lib/datastore/datastore.js +308 -147
  3. package/lib/datastore/datastore.js.map +1 -1
  4. package/lib/predicates/index.d.ts +77 -7
  5. package/lib/predicates/index.js +142 -122
  6. package/lib/predicates/index.js.map +1 -1
  7. package/lib/predicates/next.d.ts +51 -10
  8. package/lib/predicates/next.js +111 -91
  9. package/lib/predicates/next.js.map +1 -1
  10. package/lib/storage/adapter/AsyncStorageAdapter.d.ts +28 -30
  11. package/lib/storage/adapter/AsyncStorageAdapter.js +135 -532
  12. package/lib/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  13. package/lib/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  14. package/lib/storage/adapter/IndexedDBAdapter.d.ts +28 -29
  15. package/lib/storage/adapter/IndexedDBAdapter.js +490 -885
  16. package/lib/storage/adapter/IndexedDBAdapter.js.map +1 -1
  17. package/lib/storage/adapter/StorageAdapterBase.d.ts +134 -0
  18. package/lib/storage/adapter/StorageAdapterBase.js +439 -0
  19. package/lib/storage/adapter/StorageAdapterBase.js.map +1 -0
  20. package/lib/storage/relationship.d.ts +9 -0
  21. package/lib/storage/relationship.js +9 -0
  22. package/lib/storage/relationship.js.map +1 -1
  23. package/lib/storage/storage.d.ts +1 -1
  24. package/lib/storage/storage.js +4 -3
  25. package/lib/storage/storage.js.map +1 -1
  26. package/lib/sync/index.d.ts +15 -1
  27. package/lib/sync/index.js +80 -13
  28. package/lib/sync/index.js.map +1 -1
  29. package/lib/sync/outbox.js +14 -7
  30. package/lib/sync/outbox.js.map +1 -1
  31. package/lib/sync/processors/mutation.d.ts +10 -1
  32. package/lib/sync/processors/mutation.js +33 -12
  33. package/lib/sync/processors/mutation.js.map +1 -1
  34. package/lib/sync/processors/subscription.d.ts +7 -1
  35. package/lib/sync/processors/subscription.js +196 -135
  36. package/lib/sync/processors/subscription.js.map +1 -1
  37. package/lib/sync/processors/sync.d.ts +1 -1
  38. package/lib/sync/processors/sync.js.map +1 -1
  39. package/lib/sync/utils.d.ts +66 -2
  40. package/lib/sync/utils.js +264 -16
  41. package/lib/sync/utils.js.map +1 -1
  42. package/lib/types.d.ts +9 -1
  43. package/lib/types.js.map +1 -1
  44. package/lib/util.d.ts +16 -0
  45. package/lib/util.js +31 -2
  46. package/lib/util.js.map +1 -1
  47. package/lib-esm/datastore/datastore.d.ts +29 -3
  48. package/lib-esm/datastore/datastore.js +310 -149
  49. package/lib-esm/datastore/datastore.js.map +1 -1
  50. package/lib-esm/predicates/index.d.ts +77 -7
  51. package/lib-esm/predicates/index.js +143 -123
  52. package/lib-esm/predicates/index.js.map +1 -1
  53. package/lib-esm/predicates/next.d.ts +51 -10
  54. package/lib-esm/predicates/next.js +111 -91
  55. package/lib-esm/predicates/next.js.map +1 -1
  56. package/lib-esm/storage/adapter/AsyncStorageAdapter.d.ts +28 -30
  57. package/lib-esm/storage/adapter/AsyncStorageAdapter.js +138 -535
  58. package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  59. package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  60. package/lib-esm/storage/adapter/IndexedDBAdapter.d.ts +28 -29
  61. package/lib-esm/storage/adapter/IndexedDBAdapter.js +489 -884
  62. package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +1 -1
  63. package/lib-esm/storage/adapter/StorageAdapterBase.d.ts +134 -0
  64. package/lib-esm/storage/adapter/StorageAdapterBase.js +437 -0
  65. package/lib-esm/storage/adapter/StorageAdapterBase.js.map +1 -0
  66. package/lib-esm/storage/relationship.d.ts +9 -0
  67. package/lib-esm/storage/relationship.js +9 -0
  68. package/lib-esm/storage/relationship.js.map +1 -1
  69. package/lib-esm/storage/storage.d.ts +1 -1
  70. package/lib-esm/storage/storage.js +4 -3
  71. package/lib-esm/storage/storage.js.map +1 -1
  72. package/lib-esm/sync/index.d.ts +15 -1
  73. package/lib-esm/sync/index.js +82 -15
  74. package/lib-esm/sync/index.js.map +1 -1
  75. package/lib-esm/sync/outbox.js +14 -7
  76. package/lib-esm/sync/outbox.js.map +1 -1
  77. package/lib-esm/sync/processors/mutation.d.ts +10 -1
  78. package/lib-esm/sync/processors/mutation.js +33 -12
  79. package/lib-esm/sync/processors/mutation.js.map +1 -1
  80. package/lib-esm/sync/processors/subscription.d.ts +7 -1
  81. package/lib-esm/sync/processors/subscription.js +197 -136
  82. package/lib-esm/sync/processors/subscription.js.map +1 -1
  83. package/lib-esm/sync/processors/sync.d.ts +1 -1
  84. package/lib-esm/sync/processors/sync.js.map +1 -1
  85. package/lib-esm/sync/utils.d.ts +66 -2
  86. package/lib-esm/sync/utils.js +261 -18
  87. package/lib-esm/sync/utils.js.map +1 -1
  88. package/lib-esm/types.d.ts +9 -1
  89. package/lib-esm/types.js.map +1 -1
  90. package/lib-esm/util.d.ts +16 -0
  91. package/lib-esm/util.js +32 -3
  92. package/lib-esm/util.js.map +1 -1
  93. package/package.json +12 -11
  94. package/src/datastore/datastore.ts +288 -159
  95. package/src/predicates/index.ts +145 -175
  96. package/src/predicates/next.ts +114 -81
  97. package/src/storage/adapter/AsyncStorageAdapter.ts +97 -563
  98. package/src/storage/adapter/AsyncStorageDatabase.ts +2 -2
  99. package/src/storage/adapter/IndexedDBAdapter.ts +318 -770
  100. package/src/storage/adapter/StorageAdapterBase.ts +545 -0
  101. package/src/storage/relationship.ts +9 -0
  102. package/src/storage/storage.ts +12 -9
  103. package/src/sync/index.ts +108 -20
  104. package/src/sync/outbox.ts +17 -11
  105. package/src/sync/processors/mutation.ts +35 -4
  106. package/src/sync/processors/subscription.ts +124 -10
  107. package/src/sync/processors/sync.ts +4 -1
  108. package/src/sync/utils.ts +285 -15
  109. package/src/types.ts +15 -2
  110. package/src/util.ts +40 -1
  111. package/CHANGELOG.md +0 -904
@@ -26,7 +26,9 @@ type GroupOperator = 'and' | 'or' | 'not';
26
26
  type UntypedCondition = {
27
27
  fetch: (storage: StorageAdapter) => Promise<Record<string, any>[]>;
28
28
  matches: (item: Record<string, any>) => Promise<boolean>;
29
- copy(extract: GroupCondition): [UntypedCondition, GroupCondition | undefined];
29
+ copy(
30
+ extract?: GroupCondition
31
+ ): [UntypedCondition, GroupCondition | undefined];
30
32
  toAST(): any;
31
33
  };
32
34
 
@@ -89,48 +91,6 @@ const negations = {
89
91
  notContains: 'contains',
90
92
  };
91
93
 
92
- /**
93
- * Given a V1 predicate "seed", applies a list of V2 field-level conditions
94
- * to the predicate, returning a new/final V1 predicate chain link.
95
- * @param predicate The base/seed V1 predicate to build on
96
- * @param conditions The V2 conditions to add to the predicate chain.
97
- * @param negateChildren Whether the conditions should be negated first.
98
- * @returns A V1 predicate, with conditions incorporated.
99
- */
100
- function applyConditionsToV1Predicate<T>(
101
- predicate: T,
102
- conditions: FieldCondition[],
103
- negateChildren: boolean
104
- ): T {
105
- let p = predicate;
106
- const finalConditions: FieldCondition[] = [];
107
-
108
- for (const c of conditions) {
109
- if (negateChildren) {
110
- if (c.operator === 'between') {
111
- finalConditions.push(
112
- new FieldCondition(c.field, 'lt', [c.operands[0]]),
113
- new FieldCondition(c.field, 'gt', [c.operands[1]])
114
- );
115
- } else {
116
- finalConditions.push(
117
- new FieldCondition(c.field, negations[c.operator], c.operands)
118
- );
119
- }
120
- } else {
121
- finalConditions.push(c);
122
- }
123
- }
124
-
125
- for (const c of finalConditions) {
126
- p = p[c.field](
127
- c.operator as never,
128
- (c.operator === 'between' ? c.operands : c.operands[0]) as never
129
- );
130
- }
131
- return p;
132
- }
133
-
134
94
  /**
135
95
  * A condition that can operate against a single "primitive" field of a model or item.
136
96
  * @member field The field of *some record* to test against.
@@ -151,13 +111,29 @@ export class FieldCondition {
151
111
  * @param extract Not used. Present only to fulfill the `UntypedCondition` interface.
152
112
  * @returns A new, identitical `FieldCondition`.
153
113
  */
154
- copy(extract: GroupCondition): [FieldCondition, GroupCondition | undefined] {
114
+ copy(extract?: GroupCondition): [FieldCondition, GroupCondition | undefined] {
155
115
  return [
156
116
  new FieldCondition(this.field, this.operator, [...this.operands]),
157
117
  undefined,
158
118
  ];
159
119
  }
160
120
 
121
+ /**
122
+ * Produces a tree structure similar to a graphql condition. The returned
123
+ * structure is "dumb" and is intended for another query/condition
124
+ * generation mechanism to interpret, such as the cloud or storage query
125
+ * builders.
126
+ *
127
+ * E.g.,
128
+ *
129
+ * ```json
130
+ * {
131
+ * "name": {
132
+ * "eq": "robert"
133
+ * }
134
+ * }
135
+ * ```
136
+ */
161
137
  toAST() {
162
138
  return {
163
139
  [this.field]: {
@@ -169,6 +145,44 @@ export class FieldCondition {
169
145
  };
170
146
  }
171
147
 
148
+ /**
149
+ * Produces a new condition (`FieldCondition` or `GroupCondition`) that
150
+ * matches the opposite of this condition.
151
+ *
152
+ * Intended to be used when applying De Morgan's Law, which can be done to
153
+ * produce more efficient queries against the storage layer if a negation
154
+ * appears in the query tree.
155
+ *
156
+ * For example:
157
+ *
158
+ * 1. `name.eq('robert')` becomes `name.ne('robert')`
159
+ * 2. `price.between(100, 200)` becomes `m => m.or(m => [m.price.lt(100), m.price.gt(200)])`
160
+ *
161
+ * @param model The model meta to use when construction a new `GroupCondition`
162
+ * for cases where the negation requires multiple `FieldCondition`'s.
163
+ */
164
+ negated(model: ModelMeta<any>) {
165
+ if (this.operator === 'between') {
166
+ return new GroupCondition(model, undefined, undefined, 'or', [
167
+ new FieldCondition(this.field, 'lt', [this.operands[0]]),
168
+ new FieldCondition(this.field, 'gt', [this.operands[1]]),
169
+ ]);
170
+ } else if (this.operator === 'beginsWith') {
171
+ // beginsWith negation doesn't have a good, safe optimation right now.
172
+ // just re-wrap it in negation. The adapter will have to scan-and-filter,
173
+ // as is likely optimal for negated beginsWith conditions *anyway*.
174
+ return new GroupCondition(model, undefined, undefined, 'not', [
175
+ new FieldCondition(this.field, 'beginsWith', [this.operands[0]]),
176
+ ]);
177
+ } else {
178
+ return new FieldCondition(
179
+ this.field,
180
+ negations[this.operator],
181
+ this.operands
182
+ );
183
+ }
184
+ }
185
+
172
186
  /**
173
187
  * Not implemented. Not needed. GroupCondition instead consumes FieldConditions and
174
188
  * transforms them into legacy predicates. (*For now.*)
@@ -193,9 +207,9 @@ export class FieldCondition {
193
207
  ge: () => v >= this.operands[0],
194
208
  lt: () => v < this.operands[0],
195
209
  le: () => v <= this.operands[0],
196
- contains: () => v.indexOf(this.operands[0]) > -1,
197
- notContains: () => v.indexOf(this.operands[0]) === -1,
198
- beginsWith: () => v.startsWith(this.operands[0]),
210
+ contains: () => v?.indexOf(this.operands[0]) > -1,
211
+ notContains: () => (!v ? true : v.indexOf(this.operands[0]) === -1),
212
+ beginsWith: () => v?.startsWith(this.operands[0]),
199
213
  between: () => v >= this.operands[0] && v <= this.operands[1],
200
214
  };
201
215
  const operation = operations[this.operator as keyof typeof operations];
@@ -338,7 +352,7 @@ export class GroupCondition {
338
352
  * @param extract A node of interest. Its copy will *also* be returned if the node exists.
339
353
  * @returns [The full copy, the copy of `extract` | undefined]
340
354
  */
341
- copy(extract: GroupCondition): [GroupCondition, GroupCondition | undefined] {
355
+ copy(extract?: GroupCondition): [GroupCondition, GroupCondition | undefined] {
342
356
  const copied = new GroupCondition(
343
357
  this.model,
344
358
  this.field,
@@ -359,6 +373,33 @@ export class GroupCondition {
359
373
  return [copied, extractedCopy];
360
374
  }
361
375
 
376
+ /**
377
+ * Creates a new `GroupCondition` that contains only the local field conditions,
378
+ * omitting related model conditions. That resulting `GroupCondition` can be
379
+ * used to produce predicates that are compatible with the storage adapters and
380
+ * Cloud storage.
381
+ *
382
+ * @param negate Whether the condition tree should be negated according
383
+ * to De Morgan's law.
384
+ */
385
+ withFieldConditionsOnly(negate: boolean) {
386
+ const negateChildren = negate !== (this.operator === 'not');
387
+ return new GroupCondition(
388
+ this.model,
389
+ undefined,
390
+ undefined,
391
+ (negate ? negations[this.operator] : this.operator) as
392
+ | 'or'
393
+ | 'and'
394
+ | 'not',
395
+ this.operands
396
+ .filter(o => o instanceof FieldCondition)
397
+ .map(o =>
398
+ negateChildren ? (o as FieldCondition).negated(this.model) : o
399
+ )
400
+ );
401
+ }
402
+
362
403
  /**
363
404
  * Returns a version of the predicate tree with unnecessary logical groups
364
405
  * condensed and merged together. This is intended to create a dense tree
@@ -543,9 +584,7 @@ export class GroupCondition {
543
584
  }
544
585
  );
545
586
 
546
- resultGroups.push(
547
- await storage.query(this.model.builder, predicate as any)
548
- );
587
+ resultGroups.push(await storage.query(this.model.builder, predicate));
549
588
  } else {
550
589
  throw new Error('Missing field metadata.');
551
590
  }
@@ -558,17 +597,9 @@ export class GroupCondition {
558
597
  // if conditions is empty at this point, child predicates found no matches.
559
598
  // i.e., we can stop looking and return empty.
560
599
  if (conditions.length > 0) {
561
- const predicate = FlatModelPredicateCreator.createFromExisting(
562
- this.model.schema,
563
- p =>
564
- p[operator](c =>
565
- applyConditionsToV1Predicate(c, conditions, negateChildren)
566
- )
567
- );
568
-
569
- resultGroups.push(
570
- await storage.query(this.model.builder, predicate as any)
571
- );
600
+ const predicate =
601
+ this.withFieldConditionsOnly(negateChildren).toStoragePredicate();
602
+ resultGroups.push(await storage.query(this.model.builder, predicate));
572
603
  } else if (conditions.length === 0 && resultGroups.length === 0) {
573
604
  resultGroups.push(await storage.query(this.model.builder));
574
605
  }
@@ -685,13 +716,15 @@ export class GroupCondition {
685
716
  };
686
717
  }
687
718
 
688
- toStoragePredicate<T>(
689
- baseCondition?: StoragePredicate<T>
690
- ): StoragePredicate<T> {
691
- return FlatModelPredicateCreator.createFromAST(
719
+ /**
720
+ * Turn this predicate group into something a storage adapter
721
+ * understands how to use.
722
+ */
723
+ toStoragePredicate<T>(): StoragePredicate<T> {
724
+ return FlatModelPredicateCreator.createFromAST<T>(
692
725
  this.model.schema,
693
726
  this.toAST()
694
- ) as unknown as StoragePredicate<T>;
727
+ ) as StoragePredicate<T>;
695
728
  }
696
729
 
697
730
  /**
@@ -725,12 +758,6 @@ export class GroupCondition {
725
758
  * `predicateFor()` returns objecst with recursive getters. To facilitate this,
726
759
  * a `query` and `tail` can be provided to "accumulate" nested conditions.
727
760
  *
728
- * TODO: the sortof-immutable algorithm was originally done to support legacy style
729
- * predicate branching (`p => p.x.eq(value).y.eq(value)`). i'm not sure this is
730
- * necessary or beneficial at this point, since we decided that each field condition
731
- * must flly terminate a branch. is the strong mutation barrier between chain links
732
- * still necessary or helpful?
733
- *
734
761
  * @param ModelType The ModelMeta used to build child properties.
735
762
  * @param field Scopes the query branch to a field.
736
763
  * @param query A base query to build on. Omit to start a new query.
@@ -753,7 +780,7 @@ export function recursivePredicateFor<T extends PersistentModel>(
753
780
 
754
781
  // our eventual return object, which can be built upon.
755
782
  // next steps will be to add or(), and(), not(), and field.op() methods.
756
- const link = {} as any;
783
+ const link = {} as RecursiveModelPredicate<T>;
757
784
 
758
785
  // so it can be looked up later with in the internals when processing conditions.
759
786
  registerPredicateInternals(baseCondition, link);
@@ -772,10 +799,8 @@ export function recursivePredicateFor<T extends PersistentModel>(
772
799
 
773
800
  // Adds .or() and .and() methods to the link.
774
801
  // TODO: If revisiting this code, consider writing a Proxy instead.
775
- ['and', 'or'].forEach(op => {
776
- (link as any)[op] = (
777
- builder: RecursiveModelPredicateAggregateExtender<T>
778
- ) => {
802
+ (['and', 'or'] as const).forEach(op => {
803
+ link[op] = (builder: RecursiveModelPredicateAggregateExtender<T>) => {
779
804
  // or() and and() will return a copy of the original link
780
805
  // to head off mutability concerns.
781
806
  const { query, newTail } = copyLink();
@@ -832,11 +857,11 @@ export function recursivePredicateFor<T extends PersistentModel>(
832
857
  // For each field on the model schema, we want to add a getter
833
858
  // that creates the appropriate new `link` in the query chain.
834
859
  // TODO: If revisiting, consider a proxy.
835
- for (const fieldName in ModelType.schema.fields) {
860
+ for (const fieldName in ModelType.schema.allFields) {
836
861
  Object.defineProperty(link, fieldName, {
837
862
  enumerable: true,
838
863
  get: () => {
839
- const def = ModelType.schema.fields[fieldName];
864
+ const def = ModelType.schema.allFields![fieldName];
840
865
 
841
866
  if (!def.association) {
842
867
  // we're looking at a value field. we need to return a
@@ -856,10 +881,16 @@ export function recursivePredicateFor<T extends PersistentModel>(
856
881
  // the same link is being used elsewhere by the customer.
857
882
  const { query, newTail } = copyLink();
858
883
 
884
+ // normalize operands. if any of the values are `undefiend`, use
885
+ // `null` instead, because that's what will be stored cross-platform.
886
+ const normalizedOperands = operands.map(o =>
887
+ o === undefined ? null : o
888
+ );
889
+
859
890
  // add the given condition to the link's TAIL node.
860
891
  // remember: the base link might go N nodes deep! e.g.,
861
892
  newTail?.operands.push(
862
- new FieldCondition(fieldName, operator, operands)
893
+ new FieldCondition(fieldName, operator, normalizedOperands)
863
894
  );
864
895
 
865
896
  // A `FinalModelPredicate`.
@@ -929,5 +960,7 @@ export function recursivePredicateFor<T extends PersistentModel>(
929
960
  export function predicateFor<T extends PersistentModel>(
930
961
  ModelType: ModelMeta<T>
931
962
  ): ModelPredicate<T> & PredicateInternalsKey {
963
+ // the cast here is just a cheap way to reduce the surface area from
964
+ // the recursive type.
932
965
  return recursivePredicateFor(ModelType, false) as any as ModelPredicate<T>;
933
966
  }