@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.
- package/lib/datastore/datastore.d.ts +29 -3
- package/lib/datastore/datastore.js +308 -147
- package/lib/datastore/datastore.js.map +1 -1
- package/lib/predicates/index.d.ts +77 -7
- package/lib/predicates/index.js +142 -122
- package/lib/predicates/index.js.map +1 -1
- package/lib/predicates/next.d.ts +51 -10
- package/lib/predicates/next.js +111 -91
- package/lib/predicates/next.js.map +1 -1
- package/lib/storage/adapter/AsyncStorageAdapter.d.ts +28 -30
- package/lib/storage/adapter/AsyncStorageAdapter.js +135 -532
- package/lib/storage/adapter/AsyncStorageAdapter.js.map +1 -1
- package/lib/storage/adapter/AsyncStorageDatabase.js.map +1 -1
- package/lib/storage/adapter/IndexedDBAdapter.d.ts +28 -29
- package/lib/storage/adapter/IndexedDBAdapter.js +490 -885
- package/lib/storage/adapter/IndexedDBAdapter.js.map +1 -1
- package/lib/storage/adapter/StorageAdapterBase.d.ts +134 -0
- package/lib/storage/adapter/StorageAdapterBase.js +439 -0
- package/lib/storage/adapter/StorageAdapterBase.js.map +1 -0
- package/lib/storage/relationship.d.ts +9 -0
- package/lib/storage/relationship.js +9 -0
- package/lib/storage/relationship.js.map +1 -1
- package/lib/storage/storage.d.ts +1 -1
- package/lib/storage/storage.js +4 -3
- package/lib/storage/storage.js.map +1 -1
- package/lib/sync/index.d.ts +15 -1
- package/lib/sync/index.js +80 -13
- package/lib/sync/index.js.map +1 -1
- package/lib/sync/outbox.js +14 -7
- package/lib/sync/outbox.js.map +1 -1
- package/lib/sync/processors/mutation.d.ts +10 -1
- package/lib/sync/processors/mutation.js +33 -12
- package/lib/sync/processors/mutation.js.map +1 -1
- package/lib/sync/processors/subscription.d.ts +7 -1
- package/lib/sync/processors/subscription.js +196 -135
- package/lib/sync/processors/subscription.js.map +1 -1
- package/lib/sync/processors/sync.d.ts +1 -1
- package/lib/sync/processors/sync.js.map +1 -1
- package/lib/sync/utils.d.ts +66 -2
- package/lib/sync/utils.js +264 -16
- package/lib/sync/utils.js.map +1 -1
- package/lib/types.d.ts +9 -1
- package/lib/types.js.map +1 -1
- package/lib/util.d.ts +16 -0
- package/lib/util.js +31 -2
- package/lib/util.js.map +1 -1
- package/lib-esm/datastore/datastore.d.ts +29 -3
- package/lib-esm/datastore/datastore.js +310 -149
- package/lib-esm/datastore/datastore.js.map +1 -1
- package/lib-esm/predicates/index.d.ts +77 -7
- package/lib-esm/predicates/index.js +143 -123
- package/lib-esm/predicates/index.js.map +1 -1
- package/lib-esm/predicates/next.d.ts +51 -10
- package/lib-esm/predicates/next.js +111 -91
- package/lib-esm/predicates/next.js.map +1 -1
- package/lib-esm/storage/adapter/AsyncStorageAdapter.d.ts +28 -30
- package/lib-esm/storage/adapter/AsyncStorageAdapter.js +138 -535
- package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +1 -1
- package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +1 -1
- package/lib-esm/storage/adapter/IndexedDBAdapter.d.ts +28 -29
- package/lib-esm/storage/adapter/IndexedDBAdapter.js +489 -884
- package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +1 -1
- package/lib-esm/storage/adapter/StorageAdapterBase.d.ts +134 -0
- package/lib-esm/storage/adapter/StorageAdapterBase.js +437 -0
- package/lib-esm/storage/adapter/StorageAdapterBase.js.map +1 -0
- package/lib-esm/storage/relationship.d.ts +9 -0
- package/lib-esm/storage/relationship.js +9 -0
- package/lib-esm/storage/relationship.js.map +1 -1
- package/lib-esm/storage/storage.d.ts +1 -1
- package/lib-esm/storage/storage.js +4 -3
- package/lib-esm/storage/storage.js.map +1 -1
- package/lib-esm/sync/index.d.ts +15 -1
- package/lib-esm/sync/index.js +82 -15
- package/lib-esm/sync/index.js.map +1 -1
- package/lib-esm/sync/outbox.js +14 -7
- package/lib-esm/sync/outbox.js.map +1 -1
- package/lib-esm/sync/processors/mutation.d.ts +10 -1
- package/lib-esm/sync/processors/mutation.js +33 -12
- package/lib-esm/sync/processors/mutation.js.map +1 -1
- package/lib-esm/sync/processors/subscription.d.ts +7 -1
- package/lib-esm/sync/processors/subscription.js +197 -136
- package/lib-esm/sync/processors/subscription.js.map +1 -1
- package/lib-esm/sync/processors/sync.d.ts +1 -1
- package/lib-esm/sync/processors/sync.js.map +1 -1
- package/lib-esm/sync/utils.d.ts +66 -2
- package/lib-esm/sync/utils.js +261 -18
- package/lib-esm/sync/utils.js.map +1 -1
- package/lib-esm/types.d.ts +9 -1
- package/lib-esm/types.js.map +1 -1
- package/lib-esm/util.d.ts +16 -0
- package/lib-esm/util.js +32 -3
- package/lib-esm/util.js.map +1 -1
- package/package.json +12 -11
- package/src/datastore/datastore.ts +288 -159
- package/src/predicates/index.ts +145 -175
- package/src/predicates/next.ts +114 -81
- package/src/storage/adapter/AsyncStorageAdapter.ts +97 -563
- package/src/storage/adapter/AsyncStorageDatabase.ts +2 -2
- package/src/storage/adapter/IndexedDBAdapter.ts +318 -770
- package/src/storage/adapter/StorageAdapterBase.ts +545 -0
- package/src/storage/relationship.ts +9 -0
- package/src/storage/storage.ts +12 -9
- package/src/sync/index.ts +108 -20
- package/src/sync/outbox.ts +17 -11
- package/src/sync/processors/mutation.ts +35 -4
- package/src/sync/processors/subscription.ts +124 -10
- package/src/sync/processors/sync.ts +4 -1
- package/src/sync/utils.ts +285 -15
- package/src/types.ts +15 -2
- package/src/util.ts +40 -1
- package/CHANGELOG.md +0 -904
package/src/predicates/next.ts
CHANGED
|
@@ -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(
|
|
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
|
|
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
|
|
197
|
-
notContains: () => v.indexOf(this.operands[0]) === -1,
|
|
198
|
-
beginsWith: () => v
|
|
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
|
|
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 =
|
|
562
|
-
this.
|
|
563
|
-
|
|
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
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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,
|
|
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
|
}
|