@aws-amplify/datastore 3.7.3 → 3.7.4-custom-pk.86
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/CHANGELOG.md +144 -17
- package/README.md +154 -0
- package/dist/aws-amplify-datastore.js +3740 -1599
- package/dist/aws-amplify-datastore.js.map +1 -1
- package/dist/aws-amplify-datastore.min.js +25 -95
- package/dist/aws-amplify-datastore.min.js.map +1 -1
- package/lib/authModeStrategies/multiAuthStrategy.d.ts +2 -2
- package/lib/authModeStrategies/multiAuthStrategy.js +32 -26
- package/lib/authModeStrategies/multiAuthStrategy.js.map +1 -1
- package/lib/datastore/datastore.d.ts +17 -16
- package/lib/datastore/datastore.js +291 -83
- package/lib/datastore/datastore.js.map +1 -1
- package/lib/index.d.ts +3 -19
- package/lib/predicates/index.d.ts +3 -2
- package/lib/predicates/index.js +12 -2
- package/lib/predicates/index.js.map +1 -1
- package/lib/storage/adapter/AsyncStorageAdapter.d.ts +6 -2
- package/lib/storage/adapter/AsyncStorageAdapter.js +361 -193
- package/lib/storage/adapter/AsyncStorageAdapter.js.map +1 -1
- package/lib/storage/adapter/AsyncStorageDatabase.d.ts +4 -4
- package/lib/storage/adapter/AsyncStorageDatabase.js +59 -28
- package/lib/storage/adapter/AsyncStorageDatabase.js.map +1 -1
- package/lib/storage/adapter/InMemoryStore.js +2 -2
- package/lib/storage/adapter/InMemoryStore.js.map +1 -1
- package/lib/storage/adapter/IndexedDBAdapter.d.ts +7 -2
- package/lib/storage/adapter/IndexedDBAdapter.js +454 -252
- package/lib/storage/adapter/IndexedDBAdapter.js.map +1 -1
- package/lib/storage/adapter/index.d.ts +1 -1
- package/lib/storage/storage.d.ts +3 -3
- package/lib/storage/storage.js +106 -28
- package/lib/storage/storage.js.map +1 -1
- package/lib/sync/index.d.ts +23 -7
- package/lib/sync/index.js +18 -17
- package/lib/sync/index.js.map +1 -1
- package/lib/sync/merger.d.ts +3 -3
- package/lib/sync/merger.js +8 -6
- package/lib/sync/merger.js.map +1 -1
- package/lib/sync/outbox.d.ts +2 -2
- package/lib/sync/outbox.js +12 -9
- package/lib/sync/outbox.js.map +1 -1
- package/lib/sync/processors/errorMaps.d.ts +17 -0
- package/lib/sync/processors/errorMaps.js +125 -0
- package/lib/sync/processors/errorMaps.js.map +1 -0
- package/lib/sync/processors/mutation.d.ts +22 -4
- package/lib/sync/processors/mutation.js +119 -51
- package/lib/sync/processors/mutation.js.map +1 -1
- package/lib/sync/processors/subscription.d.ts +4 -2
- package/lib/sync/processors/subscription.js +76 -41
- package/lib/sync/processors/subscription.js.map +1 -1
- package/lib/sync/processors/sync.d.ts +4 -2
- package/lib/sync/processors/sync.js +62 -27
- package/lib/sync/processors/sync.js.map +1 -1
- package/lib/sync/utils.d.ts +3 -2
- package/lib/sync/utils.js +58 -7
- package/lib/sync/utils.js.map +1 -1
- package/lib/types.d.ts +90 -34
- package/lib/types.js +31 -2
- package/lib/types.js.map +1 -1
- package/lib/util.d.ts +48 -33
- package/lib/util.js +219 -57
- package/lib/util.js.map +1 -1
- package/lib-esm/authModeStrategies/multiAuthStrategy.d.ts +2 -2
- package/lib-esm/authModeStrategies/multiAuthStrategy.js +32 -26
- package/lib-esm/authModeStrategies/multiAuthStrategy.js.map +1 -1
- package/lib-esm/datastore/datastore.d.ts +17 -16
- package/lib-esm/datastore/datastore.js +293 -85
- package/lib-esm/datastore/datastore.js.map +1 -1
- package/lib-esm/index.d.ts +3 -19
- package/lib-esm/predicates/index.d.ts +3 -2
- package/lib-esm/predicates/index.js +13 -3
- package/lib-esm/predicates/index.js.map +1 -1
- package/lib-esm/storage/adapter/AsyncStorageAdapter.d.ts +6 -2
- package/lib-esm/storage/adapter/AsyncStorageAdapter.js +361 -193
- package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +1 -1
- package/lib-esm/storage/adapter/AsyncStorageDatabase.d.ts +4 -4
- package/lib-esm/storage/adapter/AsyncStorageDatabase.js +60 -29
- package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +1 -1
- package/lib-esm/storage/adapter/InMemoryStore.js +2 -2
- package/lib-esm/storage/adapter/InMemoryStore.js.map +1 -1
- package/lib-esm/storage/adapter/IndexedDBAdapter.d.ts +7 -2
- package/lib-esm/storage/adapter/IndexedDBAdapter.js +454 -252
- package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +1 -1
- package/lib-esm/storage/adapter/index.d.ts +1 -1
- package/lib-esm/storage/storage.d.ts +3 -3
- package/lib-esm/storage/storage.js +106 -28
- package/lib-esm/storage/storage.js.map +1 -1
- package/lib-esm/sync/index.d.ts +23 -7
- package/lib-esm/sync/index.js +20 -19
- package/lib-esm/sync/index.js.map +1 -1
- package/lib-esm/sync/merger.d.ts +3 -3
- package/lib-esm/sync/merger.js +8 -6
- package/lib-esm/sync/merger.js.map +1 -1
- package/lib-esm/sync/outbox.d.ts +2 -2
- package/lib-esm/sync/outbox.js +13 -10
- package/lib-esm/sync/outbox.js.map +1 -1
- package/lib-esm/sync/processors/errorMaps.d.ts +17 -0
- package/lib-esm/sync/processors/errorMaps.js +119 -0
- package/lib-esm/sync/processors/errorMaps.js.map +1 -0
- package/lib-esm/sync/processors/mutation.d.ts +22 -4
- package/lib-esm/sync/processors/mutation.js +122 -54
- package/lib-esm/sync/processors/mutation.js.map +1 -1
- package/lib-esm/sync/processors/subscription.d.ts +4 -2
- package/lib-esm/sync/processors/subscription.js +77 -42
- package/lib-esm/sync/processors/subscription.js.map +1 -1
- package/lib-esm/sync/processors/sync.d.ts +4 -2
- package/lib-esm/sync/processors/sync.js +62 -27
- package/lib-esm/sync/processors/sync.js.map +1 -1
- package/lib-esm/sync/utils.d.ts +3 -2
- package/lib-esm/sync/utils.js +58 -8
- package/lib-esm/sync/utils.js.map +1 -1
- package/lib-esm/types.d.ts +90 -34
- package/lib-esm/types.js +29 -3
- package/lib-esm/types.js.map +1 -1
- package/lib-esm/util.d.ts +48 -33
- package/lib-esm/util.js +207 -54
- package/lib-esm/util.js.map +1 -1
- package/package.json +10 -9
- package/src/authModeStrategies/multiAuthStrategy.ts +24 -21
- package/src/datastore/datastore.ts +448 -148
- package/src/predicates/index.ts +32 -10
- package/src/storage/adapter/AsyncStorageAdapter.ts +305 -78
- package/src/storage/adapter/AsyncStorageDatabase.ts +65 -26
- package/src/storage/adapter/InMemoryStore.ts +2 -2
- package/src/storage/adapter/IndexedDBAdapter.ts +344 -101
- package/src/storage/adapter/index.ts +1 -1
- package/src/storage/storage.ts +85 -24
- package/src/sync/index.ts +74 -58
- package/src/sync/merger.ts +16 -4
- package/src/sync/outbox.ts +22 -8
- package/src/sync/processors/errorMaps.ts +93 -0
- package/src/sync/processors/mutation.ts +143 -84
- package/src/sync/processors/subscription.ts +67 -36
- package/src/sync/processors/sync.ts +37 -12
- package/src/sync/utils.ts +67 -16
- package/src/types.ts +252 -50
- package/src/util.ts +256 -42
- package/ssr/package.json +1 -1
|
@@ -8,6 +8,9 @@ import {
|
|
|
8
8
|
PredicatesGroup,
|
|
9
9
|
GraphQLFilter,
|
|
10
10
|
AuthModeStrategy,
|
|
11
|
+
ErrorHandler,
|
|
12
|
+
ProcessName,
|
|
13
|
+
AmplifyContext,
|
|
11
14
|
} from '../../types';
|
|
12
15
|
import {
|
|
13
16
|
buildGraphQLOperation,
|
|
@@ -17,6 +20,7 @@ import {
|
|
|
17
20
|
predicateToGraphQLFilter,
|
|
18
21
|
getTokenForCustomAuth,
|
|
19
22
|
} from '../utils';
|
|
23
|
+
import { USER_AGENT_SUFFIX_DATASTORE } from '../../util';
|
|
20
24
|
import {
|
|
21
25
|
jitteredExponentialRetry,
|
|
22
26
|
ConsoleLogger as Logger,
|
|
@@ -24,7 +28,7 @@ import {
|
|
|
24
28
|
NonRetryableError,
|
|
25
29
|
} from '@aws-amplify/core';
|
|
26
30
|
import { ModelPredicateCreator } from '../../predicates';
|
|
27
|
-
|
|
31
|
+
import { getSyncErrorType } from './errorMaps';
|
|
28
32
|
const opResultDefaults = {
|
|
29
33
|
items: [],
|
|
30
34
|
nextToken: null,
|
|
@@ -40,8 +44,11 @@ class SyncProcessor {
|
|
|
40
44
|
private readonly schema: InternalSchema,
|
|
41
45
|
private readonly syncPredicates: WeakMap<SchemaModel, ModelPredicate<any>>,
|
|
42
46
|
private readonly amplifyConfig: Record<string, any> = {},
|
|
43
|
-
private readonly authModeStrategy: AuthModeStrategy
|
|
47
|
+
private readonly authModeStrategy: AuthModeStrategy,
|
|
48
|
+
private readonly errorHandler: ErrorHandler,
|
|
49
|
+
private readonly amplifyContext: AmplifyContext
|
|
44
50
|
) {
|
|
51
|
+
amplifyContext.API = amplifyContext.API || API;
|
|
45
52
|
this.generateQueries();
|
|
46
53
|
}
|
|
47
54
|
|
|
@@ -65,10 +72,11 @@ class SyncProcessor {
|
|
|
65
72
|
if (!this.syncPredicates) {
|
|
66
73
|
return null;
|
|
67
74
|
}
|
|
68
|
-
const predicatesGroup: PredicatesGroup<any> =
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
75
|
+
const predicatesGroup: PredicatesGroup<any> =
|
|
76
|
+
ModelPredicateCreator.getPredicates(
|
|
77
|
+
this.syncPredicates.get(model),
|
|
78
|
+
false
|
|
79
|
+
);
|
|
72
80
|
|
|
73
81
|
if (!predicatesGroup) {
|
|
74
82
|
return null;
|
|
@@ -77,9 +85,7 @@ class SyncProcessor {
|
|
|
77
85
|
return predicateToGraphQLFilter(predicatesGroup);
|
|
78
86
|
}
|
|
79
87
|
|
|
80
|
-
private async retrievePage<
|
|
81
|
-
T extends ModelInstanceMetadata = ModelInstanceMetadata
|
|
82
|
-
>(
|
|
88
|
+
private async retrievePage<T extends ModelInstanceMetadata>(
|
|
83
89
|
modelDefinition: SchemaModel,
|
|
84
90
|
lastSync: number,
|
|
85
91
|
nextToken: string,
|
|
@@ -202,11 +208,12 @@ class SyncProcessor {
|
|
|
202
208
|
this.amplifyConfig
|
|
203
209
|
);
|
|
204
210
|
|
|
205
|
-
return await API.graphql({
|
|
211
|
+
return await this.amplifyContext.API.graphql({
|
|
206
212
|
query,
|
|
207
213
|
variables,
|
|
208
214
|
authMode,
|
|
209
215
|
authToken,
|
|
216
|
+
userAgentSuffix: USER_AGENT_SUFFIX_DATASTORE,
|
|
210
217
|
});
|
|
211
218
|
} catch (error) {
|
|
212
219
|
// Catch client-side (GraphQLAuthError) & 401/403 errors here so that we don't continue to retry
|
|
@@ -222,15 +229,33 @@ class SyncProcessor {
|
|
|
222
229
|
error.data[opName] &&
|
|
223
230
|
error.data[opName].items
|
|
224
231
|
);
|
|
225
|
-
|
|
226
232
|
if (this.partialDataFeatureFlagEnabled()) {
|
|
227
233
|
if (hasItems) {
|
|
228
234
|
const result = error;
|
|
229
235
|
result.data[opName].items = result.data[opName].items.filter(
|
|
230
236
|
item => item !== null
|
|
231
237
|
);
|
|
232
|
-
|
|
233
238
|
if (error.errors) {
|
|
239
|
+
await Promise.all(
|
|
240
|
+
error.errors.map(async err => {
|
|
241
|
+
try {
|
|
242
|
+
await this.errorHandler({
|
|
243
|
+
recoverySuggestion:
|
|
244
|
+
'Ensure app code is up to date, auth directives exist and are correct on each model, and that server-side data has not been invalidated by a schema change. If the problem persists, search for or create an issue: https://github.com/aws-amplify/amplify-js/issues',
|
|
245
|
+
localModel: null,
|
|
246
|
+
message: err.message,
|
|
247
|
+
model: modelDefinition.name,
|
|
248
|
+
operation: opName,
|
|
249
|
+
errorType: getSyncErrorType(err),
|
|
250
|
+
process: ProcessName.sync,
|
|
251
|
+
remoteModel: null,
|
|
252
|
+
cause: err,
|
|
253
|
+
});
|
|
254
|
+
} catch (e) {
|
|
255
|
+
logger.error('Sync error handler failed with:', e);
|
|
256
|
+
}
|
|
257
|
+
})
|
|
258
|
+
);
|
|
234
259
|
Hub.dispatch('datastore', {
|
|
235
260
|
event: 'syncQueriesPartialSyncError',
|
|
236
261
|
data: {
|
package/src/sync/utils.ts
CHANGED
|
@@ -27,7 +27,11 @@ import {
|
|
|
27
27
|
InternalSchema,
|
|
28
28
|
AuthModeStrategy,
|
|
29
29
|
} from '../types';
|
|
30
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
exhaustiveCheck,
|
|
32
|
+
extractPrimaryKeyFieldNames,
|
|
33
|
+
establishRelationAndKeys,
|
|
34
|
+
} from '../util';
|
|
31
35
|
import { MutationEvent } from './';
|
|
32
36
|
|
|
33
37
|
const logger = new Logger('DataStore');
|
|
@@ -47,7 +51,7 @@ export enum TransformerMutationType {
|
|
|
47
51
|
GET = 'Get',
|
|
48
52
|
}
|
|
49
53
|
|
|
50
|
-
const dummyMetadata:
|
|
54
|
+
const dummyMetadata: ModelInstanceMetadata = {
|
|
51
55
|
_version: undefined,
|
|
52
56
|
_lastChangedAt: undefined,
|
|
53
57
|
_deleted: undefined,
|
|
@@ -79,7 +83,7 @@ export function generateSelectionSet(
|
|
|
79
83
|
if (isSchemaModel(modelDefinition)) {
|
|
80
84
|
scalarAndMetadataFields = scalarAndMetadataFields
|
|
81
85
|
.concat(getMetadataFields())
|
|
82
|
-
.concat(getConnectionFields(modelDefinition));
|
|
86
|
+
.concat(getConnectionFields(modelDefinition, namespace));
|
|
83
87
|
}
|
|
84
88
|
|
|
85
89
|
const result = scalarAndMetadataFields.join('\n');
|
|
@@ -138,8 +142,12 @@ function getScalarFields(
|
|
|
138
142
|
return result;
|
|
139
143
|
}
|
|
140
144
|
|
|
141
|
-
|
|
142
|
-
|
|
145
|
+
// Used for generating the selection set for queries and mutations
|
|
146
|
+
function getConnectionFields(
|
|
147
|
+
modelDefinition: SchemaModel,
|
|
148
|
+
namespace: SchemaNamespace
|
|
149
|
+
): string[] {
|
|
150
|
+
const result: string[] = [];
|
|
143
151
|
|
|
144
152
|
Object.values(modelDefinition.fields)
|
|
145
153
|
.filter(({ association }) => association && Object.keys(association).length)
|
|
@@ -153,7 +161,26 @@ function getConnectionFields(modelDefinition: SchemaModel): string[] {
|
|
|
153
161
|
break;
|
|
154
162
|
case 'BELONGS_TO':
|
|
155
163
|
if (isTargetNameAssociation(association)) {
|
|
156
|
-
|
|
164
|
+
// New codegen (CPK)
|
|
165
|
+
if (association.targetNames && association.targetNames.length > 0) {
|
|
166
|
+
// Need to retrieve relations in order to get connected model keys
|
|
167
|
+
const [relations] = establishRelationAndKeys(namespace);
|
|
168
|
+
|
|
169
|
+
const connectedModelName =
|
|
170
|
+
modelDefinition.fields[name].type['model'];
|
|
171
|
+
|
|
172
|
+
const byPkIndex = relations[connectedModelName].indexes.find(
|
|
173
|
+
([name]) => name === 'byPk'
|
|
174
|
+
);
|
|
175
|
+
const keyFields = byPkIndex && byPkIndex[1];
|
|
176
|
+
const keyFieldSelectionSet = keyFields?.join(' ');
|
|
177
|
+
|
|
178
|
+
// We rely on `_deleted` when we process the sync query (e.g. in batchSave in the adapters)
|
|
179
|
+
result.push(`${name} { ${keyFieldSelectionSet} _deleted }`);
|
|
180
|
+
} else {
|
|
181
|
+
// backwards-compatability for schema generated prior to custom primary key support
|
|
182
|
+
result.push(`${name} { id _deleted }`);
|
|
183
|
+
}
|
|
157
184
|
}
|
|
158
185
|
break;
|
|
159
186
|
default:
|
|
@@ -412,10 +439,13 @@ export function createMutationInstanceFromModelOperation<
|
|
|
412
439
|
return v;
|
|
413
440
|
};
|
|
414
441
|
|
|
442
|
+
const modelId = getIdentifierValue(modelDefinition, element);
|
|
443
|
+
const optionalId = OpType.INSERT && id ? { id } : {};
|
|
444
|
+
|
|
415
445
|
const mutationEvent = modelInstanceCreator(MutationEventConstructor, {
|
|
416
|
-
...
|
|
446
|
+
...optionalId,
|
|
417
447
|
data: JSON.stringify(element, replacer),
|
|
418
|
-
modelId
|
|
448
|
+
modelId,
|
|
419
449
|
model: model.name,
|
|
420
450
|
operation,
|
|
421
451
|
condition: JSON.stringify(condition),
|
|
@@ -425,7 +455,8 @@ export function createMutationInstanceFromModelOperation<
|
|
|
425
455
|
}
|
|
426
456
|
|
|
427
457
|
export function predicateToGraphQLCondition(
|
|
428
|
-
predicate: PredicatesGroup<any
|
|
458
|
+
predicate: PredicatesGroup<any>,
|
|
459
|
+
modelDefinition: SchemaModel
|
|
429
460
|
): GraphQLCondition {
|
|
430
461
|
const result = {};
|
|
431
462
|
|
|
@@ -433,17 +464,27 @@ export function predicateToGraphQLCondition(
|
|
|
433
464
|
return result;
|
|
434
465
|
}
|
|
435
466
|
|
|
467
|
+
const keyFields = extractPrimaryKeyFieldNames(modelDefinition);
|
|
468
|
+
|
|
436
469
|
predicate.predicates.forEach(p => {
|
|
437
470
|
if (isPredicateObj(p)) {
|
|
438
471
|
const { field, operator, operand } = p;
|
|
439
472
|
|
|
440
|
-
|
|
473
|
+
// This is compatible with how the GQL Transform currently generates the Condition Input,
|
|
474
|
+
// i.e. any PK and SK fields are omitted and can't be used as conditions.
|
|
475
|
+
// However, I think this limits usability.
|
|
476
|
+
// What if we want to delete all records where SK > some value
|
|
477
|
+
// Or all records where PK = some value but SKs are different values
|
|
478
|
+
|
|
479
|
+
// TODO: if the Transform gets updated ^ we'll need to modify this logic to only omit
|
|
480
|
+
// key fields from the predicate/condition when ALL of the keyFields are present and using `eq` operators
|
|
481
|
+
if (keyFields.includes(field as string)) {
|
|
441
482
|
return;
|
|
442
483
|
}
|
|
443
484
|
|
|
444
485
|
result[field] = { [operator]: operand };
|
|
445
486
|
} else {
|
|
446
|
-
result[p.type] = predicateToGraphQLCondition(p);
|
|
487
|
+
result[p.type] = predicateToGraphQLCondition(p, modelDefinition);
|
|
447
488
|
}
|
|
448
489
|
});
|
|
449
490
|
|
|
@@ -515,11 +556,9 @@ export async function getModelAuthModes({
|
|
|
515
556
|
defaultAuthMode: GRAPHQL_AUTH_MODE;
|
|
516
557
|
modelName: string;
|
|
517
558
|
schema: InternalSchema;
|
|
518
|
-
}): Promise<
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
}
|
|
522
|
-
> {
|
|
559
|
+
}): Promise<{
|
|
560
|
+
[key in ModelOperation]: GRAPHQL_AUTH_MODE[];
|
|
561
|
+
}> {
|
|
523
562
|
const operations = Object.values(ModelOperation);
|
|
524
563
|
|
|
525
564
|
const modelAuthModes: {
|
|
@@ -612,3 +651,15 @@ export async function getTokenForCustomAuth(
|
|
|
612
651
|
}
|
|
613
652
|
}
|
|
614
653
|
}
|
|
654
|
+
|
|
655
|
+
// Util that takes a modelDefinition and model and returns either the id value(s) or the custom primary key value(s)
|
|
656
|
+
export function getIdentifierValue(
|
|
657
|
+
modelDefinition: SchemaModel,
|
|
658
|
+
model: ModelInstanceMetadata | PersistentModel
|
|
659
|
+
): string {
|
|
660
|
+
const pkFieldNames = extractPrimaryKeyFieldNames(modelDefinition);
|
|
661
|
+
|
|
662
|
+
const idOrPk = pkFieldNames.map(f => model[f]).join('-');
|
|
663
|
+
|
|
664
|
+
return idOrPk;
|
|
665
|
+
}
|