@aws-amplify/datastore 4.7.6-api-v6-models.b3abc9b.0 → 5.0.0
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/README.md +4 -0
- package/lib/authModeStrategies/defaultAuthStrategy.js +3 -2
- package/lib/authModeStrategies/index.js +3 -3
- package/lib/authModeStrategies/multiAuthStrategy.js +38 -53
- package/lib/datastore/datastore.d.ts +4 -5
- package/lib/datastore/datastore.js +929 -1284
- package/lib/index.d.ts +1 -1
- package/lib/index.js +26 -13
- package/lib/predicates/index.js +54 -69
- package/lib/predicates/next.d.ts +2 -2
- package/lib/predicates/next.js +313 -462
- package/lib/predicates/sort.js +24 -28
- package/lib/ssr/index.js +2 -2
- package/lib/storage/adapter/AsyncStorageAdapter.js +120 -342
- package/lib/storage/adapter/AsyncStorageDatabase.js +217 -421
- package/lib/storage/adapter/InMemoryStore.js +28 -51
- package/lib/storage/adapter/InMemoryStore.native.js +5 -3
- package/lib/storage/adapter/IndexedDBAdapter.js +466 -871
- package/lib/storage/adapter/StorageAdapterBase.js +180 -330
- package/lib/storage/adapter/getDefaultAdapter/index.js +8 -10
- package/lib/storage/adapter/getDefaultAdapter/index.native.js +5 -4
- package/lib/storage/adapter/index.js +0 -1
- package/lib/storage/relationship.js +177 -253
- package/lib/storage/storage.d.ts +4 -4
- package/lib/storage/storage.js +255 -433
- package/lib/sync/datastoreConnectivity.d.ts +2 -2
- package/lib/sync/datastoreConnectivity.js +29 -39
- package/lib/sync/datastoreReachability/index.d.ts +1 -3
- package/lib/sync/datastoreReachability/index.js +3 -3
- package/lib/sync/datastoreReachability/index.native.d.ts +1 -3
- package/lib/sync/datastoreReachability/index.native.js +4 -5
- package/lib/sync/index.d.ts +2 -2
- package/lib/sync/index.js +522 -827
- package/lib/sync/merger.js +31 -63
- package/lib/sync/outbox.js +148 -232
- package/lib/sync/processors/errorMaps.d.ts +1 -1
- package/lib/sync/processors/errorMaps.js +30 -47
- package/lib/sync/processors/mutation.d.ts +2 -2
- package/lib/sync/processors/mutation.js +343 -502
- package/lib/sync/processors/subscription.d.ts +5 -2
- package/lib/sync/processors/subscription.js +283 -437
- package/lib/sync/processors/sync.d.ts +2 -2
- package/lib/sync/processors/sync.js +279 -404
- package/lib/sync/utils.d.ts +5 -4
- package/lib/sync/utils.js +267 -320
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/lib/types.d.ts +138 -140
- package/lib/types.js +17 -24
- package/lib/util.d.ts +9 -17
- package/lib/util.js +387 -511
- package/lib-esm/authModeStrategies/defaultAuthStrategy.js +1 -2
- package/lib-esm/authModeStrategies/index.js +0 -1
- package/lib-esm/authModeStrategies/multiAuthStrategy.js +35 -52
- package/lib-esm/datastore/datastore.d.ts +4 -5
- package/lib-esm/datastore/datastore.js +888 -1247
- package/lib-esm/index.d.ts +1 -1
- package/lib-esm/index.js +6 -7
- package/lib-esm/predicates/index.js +53 -70
- package/lib-esm/predicates/next.d.ts +2 -2
- package/lib-esm/predicates/next.js +306 -459
- package/lib-esm/predicates/sort.js +23 -28
- package/lib-esm/ssr/index.js +1 -2
- package/lib-esm/storage/adapter/AsyncStorageAdapter.js +111 -338
- package/lib-esm/storage/adapter/AsyncStorageDatabase.js +212 -416
- package/lib-esm/storage/adapter/InMemoryStore.js +27 -52
- package/lib-esm/storage/adapter/InMemoryStore.native.js +0 -1
- package/lib-esm/storage/adapter/IndexedDBAdapter.js +438 -866
- package/lib-esm/storage/adapter/StorageAdapterBase.js +173 -325
- package/lib-esm/storage/adapter/getDefaultAdapter/index.js +2 -6
- package/lib-esm/storage/adapter/getDefaultAdapter/index.native.js +1 -2
- package/lib-esm/storage/adapter/index.js +1 -1
- package/lib-esm/storage/relationship.js +173 -251
- package/lib-esm/storage/storage.d.ts +4 -4
- package/lib-esm/storage/storage.js +242 -424
- package/lib-esm/sync/datastoreConnectivity.d.ts +2 -2
- package/lib-esm/sync/datastoreConnectivity.js +28 -39
- package/lib-esm/sync/datastoreReachability/index.d.ts +1 -3
- package/lib-esm/sync/datastoreReachability/index.js +2 -3
- package/lib-esm/sync/datastoreReachability/index.native.d.ts +1 -3
- package/lib-esm/sync/datastoreReachability/index.native.js +3 -4
- package/lib-esm/sync/index.d.ts +2 -2
- package/lib-esm/sync/index.js +502 -812
- package/lib-esm/sync/merger.js +28 -61
- package/lib-esm/sync/outbox.js +143 -228
- package/lib-esm/sync/processors/errorMaps.d.ts +1 -1
- package/lib-esm/sync/processors/errorMaps.js +32 -50
- package/lib-esm/sync/processors/mutation.d.ts +2 -2
- package/lib-esm/sync/processors/mutation.js +329 -490
- package/lib-esm/sync/processors/subscription.d.ts +5 -2
- package/lib-esm/sync/processors/subscription.js +266 -421
- package/lib-esm/sync/processors/sync.d.ts +2 -2
- package/lib-esm/sync/processors/sync.js +271 -397
- package/lib-esm/sync/utils.d.ts +5 -4
- package/lib-esm/sync/utils.js +252 -307
- package/lib-esm/tsconfig.tsbuildinfo +1 -0
- package/lib-esm/types.d.ts +138 -140
- package/lib-esm/types.js +16 -25
- package/lib-esm/util.d.ts +9 -17
- package/lib-esm/util.js +335 -497
- package/package.json +31 -26
- package/src/authModeStrategies/multiAuthStrategy.ts +15 -12
- package/src/datastore/datastore.ts +36 -35
- package/src/predicates/sort.ts +3 -1
- package/src/storage/adapter/InMemoryStore.ts +1 -1
- package/src/storage/adapter/IndexedDBAdapter.ts +2 -2
- package/src/storage/adapter/StorageAdapterBase.ts +2 -2
- package/src/storage/adapter/getDefaultAdapter/index.ts +1 -4
- package/src/storage/storage.ts +29 -24
- package/src/sync/datastoreConnectivity.ts +6 -6
- package/src/sync/datastoreReachability/index.native.ts +5 -3
- package/src/sync/datastoreReachability/index.ts +1 -1
- package/src/sync/index.ts +79 -89
- package/src/sync/processors/errorMaps.ts +7 -7
- package/src/sync/processors/mutation.ts +19 -13
- package/src/sync/processors/subscription.ts +221 -295
- package/src/sync/processors/sync.ts +11 -8
- package/src/sync/utils.ts +30 -15
- package/src/types.ts +4 -8
- package/src/util.ts +46 -9
- package/lib/.tsbuildinfo +0 -3
- package/lib/authModeStrategies/defaultAuthStrategy.js.map +0 -1
- package/lib/authModeStrategies/index.js.map +0 -1
- package/lib/authModeStrategies/multiAuthStrategy.js.map +0 -1
- package/lib/datastore/datastore.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/predicates/index.js.map +0 -1
- package/lib/predicates/next.js.map +0 -1
- package/lib/predicates/sort.js.map +0 -1
- package/lib/ssr/index.js.map +0 -1
- package/lib/storage/adapter/AsyncStorageAdapter.js.map +0 -1
- package/lib/storage/adapter/AsyncStorageDatabase.js.map +0 -1
- package/lib/storage/adapter/InMemoryStore.js.map +0 -1
- package/lib/storage/adapter/InMemoryStore.native.js.map +0 -1
- package/lib/storage/adapter/IndexedDBAdapter.js.map +0 -1
- package/lib/storage/adapter/StorageAdapterBase.js.map +0 -1
- package/lib/storage/adapter/getDefaultAdapter/index.js.map +0 -1
- package/lib/storage/adapter/getDefaultAdapter/index.native.js.map +0 -1
- package/lib/storage/adapter/index.js.map +0 -1
- package/lib/storage/relationship.js.map +0 -1
- package/lib/storage/storage.js.map +0 -1
- package/lib/sync/datastoreConnectivity.js.map +0 -1
- package/lib/sync/datastoreReachability/index.js.map +0 -1
- package/lib/sync/datastoreReachability/index.native.js.map +0 -1
- package/lib/sync/index.js.map +0 -1
- package/lib/sync/merger.js.map +0 -1
- package/lib/sync/outbox.js.map +0 -1
- package/lib/sync/processors/errorMaps.js.map +0 -1
- package/lib/sync/processors/mutation.js.map +0 -1
- package/lib/sync/processors/subscription.js.map +0 -1
- package/lib/sync/processors/sync.js.map +0 -1
- package/lib/sync/utils.js.map +0 -1
- package/lib/types.js.map +0 -1
- package/lib/util.js.map +0 -1
- package/lib-esm/.tsbuildinfo +0 -3
- package/lib-esm/authModeStrategies/defaultAuthStrategy.js.map +0 -1
- package/lib-esm/authModeStrategies/index.js.map +0 -1
- package/lib-esm/authModeStrategies/multiAuthStrategy.js.map +0 -1
- package/lib-esm/datastore/datastore.js.map +0 -1
- package/lib-esm/index.js.map +0 -1
- package/lib-esm/predicates/index.js.map +0 -1
- package/lib-esm/predicates/next.js.map +0 -1
- package/lib-esm/predicates/sort.js.map +0 -1
- package/lib-esm/ssr/index.js.map +0 -1
- package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +0 -1
- package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +0 -1
- package/lib-esm/storage/adapter/InMemoryStore.js.map +0 -1
- package/lib-esm/storage/adapter/InMemoryStore.native.js.map +0 -1
- package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +0 -1
- package/lib-esm/storage/adapter/StorageAdapterBase.js.map +0 -1
- package/lib-esm/storage/adapter/getDefaultAdapter/index.js.map +0 -1
- package/lib-esm/storage/adapter/getDefaultAdapter/index.native.js.map +0 -1
- package/lib-esm/storage/adapter/index.js.map +0 -1
- package/lib-esm/storage/relationship.js.map +0 -1
- package/lib-esm/storage/storage.js.map +0 -1
- package/lib-esm/sync/datastoreConnectivity.js.map +0 -1
- package/lib-esm/sync/datastoreReachability/index.js.map +0 -1
- package/lib-esm/sync/datastoreReachability/index.native.js.map +0 -1
- package/lib-esm/sync/index.js.map +0 -1
- package/lib-esm/sync/merger.js.map +0 -1
- package/lib-esm/sync/outbox.js.map +0 -1
- package/lib-esm/sync/processors/errorMaps.js.map +0 -1
- package/lib-esm/sync/processors/mutation.js.map +0 -1
- package/lib-esm/sync/processors/subscription.js.map +0 -1
- package/lib-esm/sync/processors/sync.js.map +0 -1
- package/lib-esm/sync/utils.js.map +0 -1
- package/lib-esm/types.js.map +0 -1
- package/lib-esm/util.js.map +0 -1
package/lib-esm/sync/utils.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import { __assign, __awaiter, __generator, __read, __spread, __values } from "tslib";
|
|
2
1
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
import { GRAPHQL_AUTH_MODE } from '@aws-amplify/api-graphql';
|
|
5
3
|
import { GraphQLAuthError } from '@aws-amplify/api';
|
|
6
|
-
import { Logger } from '@aws-amplify/core';
|
|
7
4
|
import { isEnumFieldType, isGraphQLScalarType, isPredicateObj, isSchemaModel, isSchemaModelWithAttributes, isTargetNameAssociation, isNonModelFieldType, OpType, ModelOperation, isPredicateGroup, } from '../types';
|
|
8
5
|
import { extractPrimaryKeyFieldNames, establishRelationAndKeys, IDENTIFIER_KEY_SEPARATOR, } from '../util';
|
|
9
|
-
|
|
6
|
+
import { ConsoleLogger } from '@aws-amplify/core';
|
|
7
|
+
const logger = new ConsoleLogger('DataStore');
|
|
10
8
|
var GraphQLOperationType;
|
|
11
9
|
(function (GraphQLOperationType) {
|
|
12
10
|
GraphQLOperationType["LIST"] = "query";
|
|
@@ -22,24 +20,21 @@ export var TransformerMutationType;
|
|
|
22
20
|
TransformerMutationType["DELETE"] = "Delete";
|
|
23
21
|
TransformerMutationType["GET"] = "Get";
|
|
24
22
|
})(TransformerMutationType || (TransformerMutationType = {}));
|
|
25
|
-
|
|
23
|
+
const dummyMetadata = {
|
|
26
24
|
_version: undefined,
|
|
27
25
|
_lastChangedAt: undefined,
|
|
28
26
|
_deleted: undefined,
|
|
29
27
|
};
|
|
30
|
-
|
|
28
|
+
const metadataFields = (Object.keys(dummyMetadata));
|
|
31
29
|
export function getMetadataFields() {
|
|
32
30
|
return metadataFields;
|
|
33
31
|
}
|
|
34
32
|
export function generateSelectionSet(namespace, modelDefinition) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
.map(
|
|
40
|
-
var name = _a.name;
|
|
41
|
-
return name;
|
|
42
|
-
})
|
|
33
|
+
const scalarFields = getScalarFields(modelDefinition);
|
|
34
|
+
const nonModelFields = getNonModelFields(namespace, modelDefinition);
|
|
35
|
+
const implicitOwnerField = getImplicitOwnerField(modelDefinition, scalarFields);
|
|
36
|
+
let scalarAndMetadataFields = Object.values(scalarFields)
|
|
37
|
+
.map(({ name }) => name)
|
|
43
38
|
.concat(implicitOwnerField)
|
|
44
39
|
.concat(nonModelFields);
|
|
45
40
|
if (isSchemaModel(modelDefinition)) {
|
|
@@ -47,22 +42,22 @@ export function generateSelectionSet(namespace, modelDefinition) {
|
|
|
47
42
|
.concat(getMetadataFields())
|
|
48
43
|
.concat(getConnectionFields(modelDefinition, namespace));
|
|
49
44
|
}
|
|
50
|
-
|
|
45
|
+
const result = scalarAndMetadataFields.join('\n');
|
|
51
46
|
return result;
|
|
52
47
|
}
|
|
53
48
|
function getImplicitOwnerField(modelDefinition, scalarFields) {
|
|
54
|
-
|
|
49
|
+
const ownerFields = getOwnerFields(modelDefinition);
|
|
55
50
|
if (!scalarFields.owner && ownerFields.includes('owner')) {
|
|
56
51
|
return ['owner'];
|
|
57
52
|
}
|
|
58
53
|
return [];
|
|
59
54
|
}
|
|
60
55
|
function getOwnerFields(modelDefinition) {
|
|
61
|
-
|
|
56
|
+
const ownerFields = [];
|
|
62
57
|
if (isSchemaModelWithAttributes(modelDefinition)) {
|
|
63
|
-
modelDefinition.attributes.forEach(
|
|
58
|
+
modelDefinition.attributes.forEach(attr => {
|
|
64
59
|
if (attr.properties && attr.properties.rules) {
|
|
65
|
-
|
|
60
|
+
const rule = attr.properties.rules.find(rule => rule.allow === 'owner');
|
|
66
61
|
if (rule && rule.ownerField) {
|
|
67
62
|
ownerFields.push(rule.ownerField);
|
|
68
63
|
}
|
|
@@ -72,15 +67,15 @@ function getOwnerFields(modelDefinition) {
|
|
|
72
67
|
return ownerFields;
|
|
73
68
|
}
|
|
74
69
|
function getScalarFields(modelDefinition) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
.filter(
|
|
70
|
+
const { fields } = modelDefinition;
|
|
71
|
+
const result = Object.values(fields)
|
|
72
|
+
.filter(field => {
|
|
78
73
|
if (isGraphQLScalarType(field.type) || isEnumFieldType(field.type)) {
|
|
79
74
|
return true;
|
|
80
75
|
}
|
|
81
76
|
return false;
|
|
82
77
|
})
|
|
83
|
-
.reduce(
|
|
78
|
+
.reduce((acc, field) => {
|
|
84
79
|
acc[field.name] = field;
|
|
85
80
|
return acc;
|
|
86
81
|
}, {});
|
|
@@ -88,15 +83,11 @@ function getScalarFields(modelDefinition) {
|
|
|
88
83
|
}
|
|
89
84
|
// Used for generating the selection set for queries and mutations
|
|
90
85
|
function getConnectionFields(modelDefinition, namespace) {
|
|
91
|
-
|
|
86
|
+
const result = [];
|
|
92
87
|
Object.values(modelDefinition.fields)
|
|
93
|
-
.filter(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
})
|
|
97
|
-
.forEach(function (_a) {
|
|
98
|
-
var name = _a.name, association = _a.association;
|
|
99
|
-
var connectionType = (association || {}).connectionType;
|
|
88
|
+
.filter(({ association }) => association && Object.keys(association).length)
|
|
89
|
+
.forEach(({ name, association }) => {
|
|
90
|
+
const { connectionType } = association || {};
|
|
100
91
|
switch (connectionType) {
|
|
101
92
|
case 'HAS_ONE':
|
|
102
93
|
case 'HAS_MANY':
|
|
@@ -107,86 +98,79 @@ function getConnectionFields(modelDefinition, namespace) {
|
|
|
107
98
|
// New codegen (CPK)
|
|
108
99
|
if (association.targetNames && association.targetNames.length > 0) {
|
|
109
100
|
// Need to retrieve relations in order to get connected model keys
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
});
|
|
116
|
-
var keyFields = byPkIndex && byPkIndex[1];
|
|
117
|
-
var keyFieldSelectionSet = keyFields === null || keyFields === void 0 ? void 0 : keyFields.join(' ');
|
|
101
|
+
const [relations] = establishRelationAndKeys(namespace);
|
|
102
|
+
const connectedModelName = modelDefinition.fields[name].type['model'];
|
|
103
|
+
const byPkIndex = relations[connectedModelName].indexes.find(([name]) => name === 'byPk');
|
|
104
|
+
const keyFields = byPkIndex && byPkIndex[1];
|
|
105
|
+
const keyFieldSelectionSet = keyFields?.join(' ');
|
|
118
106
|
// We rely on `_deleted` when we process the sync query (e.g. in batchSave in the adapters)
|
|
119
|
-
result.push(name
|
|
107
|
+
result.push(`${name} { ${keyFieldSelectionSet} _deleted }`);
|
|
120
108
|
}
|
|
121
109
|
else {
|
|
122
110
|
// backwards-compatability for schema generated prior to custom primary key support
|
|
123
|
-
result.push(name
|
|
111
|
+
result.push(`${name} { id _deleted }`);
|
|
124
112
|
}
|
|
125
113
|
}
|
|
126
114
|
break;
|
|
127
115
|
default:
|
|
128
|
-
throw new Error(
|
|
116
|
+
throw new Error(`Invalid connection type ${connectionType}`);
|
|
129
117
|
}
|
|
130
118
|
});
|
|
131
119
|
return result;
|
|
132
120
|
}
|
|
133
121
|
function getNonModelFields(namespace, modelDefinition) {
|
|
134
|
-
|
|
135
|
-
Object.values(modelDefinition.fields).forEach(
|
|
136
|
-
var name = _a.name, type = _a.type;
|
|
122
|
+
const result = [];
|
|
123
|
+
Object.values(modelDefinition.fields).forEach(({ name, type }) => {
|
|
137
124
|
if (isNonModelFieldType(type)) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
var nested_1 = [];
|
|
144
|
-
Object.values(typeDefinition.fields).forEach(function (field) {
|
|
145
|
-
var type = field.type, name = field.name;
|
|
125
|
+
const typeDefinition = namespace.nonModels[type.nonModel];
|
|
126
|
+
const scalarFields = Object.values(getScalarFields(typeDefinition)).map(({ name }) => name);
|
|
127
|
+
const nested = [];
|
|
128
|
+
Object.values(typeDefinition.fields).forEach(field => {
|
|
129
|
+
const { type, name } = field;
|
|
146
130
|
if (isNonModelFieldType(type)) {
|
|
147
|
-
|
|
148
|
-
|
|
131
|
+
const typeDefinition = namespace.nonModels[type.nonModel];
|
|
132
|
+
nested.push(`${name} { ${generateSelectionSet(namespace, typeDefinition)} }`);
|
|
149
133
|
}
|
|
150
134
|
});
|
|
151
|
-
result.push(name
|
|
135
|
+
result.push(`${name} { ${scalarFields.join(' ')} ${nested.join(' ')} }`);
|
|
152
136
|
}
|
|
153
137
|
});
|
|
154
138
|
return result;
|
|
155
139
|
}
|
|
156
140
|
export function getAuthorizationRules(modelDefinition) {
|
|
157
141
|
// Searching for owner authorization on attributes
|
|
158
|
-
|
|
142
|
+
const authConfig = []
|
|
159
143
|
.concat(modelDefinition.attributes || [])
|
|
160
|
-
.find(
|
|
161
|
-
|
|
162
|
-
|
|
144
|
+
.find(attr => attr && attr.type === 'auth');
|
|
145
|
+
const { properties: { rules = [] } = {} } = authConfig || {};
|
|
146
|
+
const resultRules = [];
|
|
163
147
|
// Multiple rules can be declared for allow: owner
|
|
164
|
-
rules.forEach(
|
|
148
|
+
rules.forEach(rule => {
|
|
165
149
|
// setting defaults for backwards compatibility with old cli
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
150
|
+
const { identityClaim = 'cognito:username', ownerField = 'owner', operations = ['create', 'update', 'delete', 'read'], provider = 'userPools', groupClaim = 'cognito:groups', allow: authStrategy = 'iam', groups = [], groupsField = '', } = rule;
|
|
151
|
+
const isReadAuthorized = operations.includes('read');
|
|
152
|
+
const isOwnerAuth = authStrategy === 'owner';
|
|
169
153
|
if (!isReadAuthorized && !isOwnerAuth) {
|
|
170
154
|
return;
|
|
171
155
|
}
|
|
172
|
-
|
|
173
|
-
identityClaim
|
|
174
|
-
ownerField
|
|
175
|
-
provider
|
|
176
|
-
groupClaim
|
|
177
|
-
authStrategy
|
|
178
|
-
groups
|
|
179
|
-
groupsField
|
|
156
|
+
const authRule = {
|
|
157
|
+
identityClaim,
|
|
158
|
+
ownerField,
|
|
159
|
+
provider,
|
|
160
|
+
groupClaim,
|
|
161
|
+
authStrategy,
|
|
162
|
+
groups,
|
|
163
|
+
groupsField,
|
|
180
164
|
areSubscriptionsPublic: false,
|
|
181
165
|
};
|
|
182
166
|
if (isOwnerAuth) {
|
|
183
167
|
// look for the subscription level override
|
|
184
168
|
// only pay attention to the public level
|
|
185
|
-
|
|
169
|
+
const modelConfig = []
|
|
186
170
|
.concat(modelDefinition.attributes || [])
|
|
187
|
-
.find(
|
|
171
|
+
.find(attr => attr && attr.type === 'model');
|
|
188
172
|
// find the subscriptions level. ON is default
|
|
189
|
-
|
|
173
|
+
const { properties: { subscriptions: { level = 'on' } = {} } = {} } = modelConfig || {};
|
|
190
174
|
// treat subscriptions as public for owner auth with unprotected reads
|
|
191
175
|
// when `read` is omitted from `operations`
|
|
192
176
|
authRule.areSubscriptionsPublic =
|
|
@@ -201,81 +185,92 @@ export function getAuthorizationRules(modelDefinition) {
|
|
|
201
185
|
});
|
|
202
186
|
return resultRules;
|
|
203
187
|
}
|
|
204
|
-
export function buildSubscriptionGraphQLOperation(namespace, modelDefinition, transformerMutationType, isOwnerAuthorization, ownerField, filterArg) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
var opArgs = [];
|
|
188
|
+
export function buildSubscriptionGraphQLOperation(namespace, modelDefinition, transformerMutationType, isOwnerAuthorization, ownerField, filterArg = false) {
|
|
189
|
+
const selectionSet = generateSelectionSet(namespace, modelDefinition);
|
|
190
|
+
const { name: typeName } = modelDefinition;
|
|
191
|
+
const opName = `on${transformerMutationType}${typeName}`;
|
|
192
|
+
const docArgs = [];
|
|
193
|
+
const opArgs = [];
|
|
211
194
|
if (filterArg) {
|
|
212
|
-
docArgs.push(
|
|
195
|
+
docArgs.push(`$filter: ModelSubscription${typeName}FilterInput`);
|
|
213
196
|
opArgs.push('filter: $filter');
|
|
214
197
|
}
|
|
215
198
|
if (isOwnerAuthorization) {
|
|
216
|
-
docArgs.push(
|
|
217
|
-
opArgs.push(ownerField
|
|
199
|
+
docArgs.push(`$${ownerField}: String!`);
|
|
200
|
+
opArgs.push(`${ownerField}: $${ownerField}`);
|
|
218
201
|
}
|
|
219
|
-
|
|
220
|
-
|
|
202
|
+
const docStr = docArgs.length ? `(${docArgs.join(',')})` : '';
|
|
203
|
+
const opStr = opArgs.length ? `(${opArgs.join(',')})` : '';
|
|
221
204
|
return [
|
|
222
205
|
transformerMutationType,
|
|
223
206
|
opName,
|
|
224
|
-
|
|
207
|
+
`subscription operation${docStr}{
|
|
208
|
+
${opName}${opStr}{
|
|
209
|
+
${selectionSet}
|
|
210
|
+
}
|
|
211
|
+
}`,
|
|
225
212
|
];
|
|
226
213
|
}
|
|
227
214
|
export function buildGraphQLOperation(namespace, modelDefinition, graphQLOpType) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
215
|
+
let selectionSet = generateSelectionSet(namespace, modelDefinition);
|
|
216
|
+
const { name: typeName, pluralName: pluralTypeName } = modelDefinition;
|
|
217
|
+
let operation;
|
|
218
|
+
let documentArgs;
|
|
219
|
+
let operationArgs;
|
|
220
|
+
let transformerMutationType;
|
|
234
221
|
switch (graphQLOpType) {
|
|
235
222
|
case 'LIST':
|
|
236
|
-
operation =
|
|
237
|
-
documentArgs =
|
|
223
|
+
operation = `sync${pluralTypeName}`;
|
|
224
|
+
documentArgs = `($limit: Int, $nextToken: String, $lastSync: AWSTimestamp, $filter: Model${typeName}FilterInput)`;
|
|
238
225
|
operationArgs =
|
|
239
226
|
'(limit: $limit, nextToken: $nextToken, lastSync: $lastSync, filter: $filter)';
|
|
240
|
-
selectionSet =
|
|
227
|
+
selectionSet = `items {
|
|
228
|
+
${selectionSet}
|
|
229
|
+
}
|
|
230
|
+
nextToken
|
|
231
|
+
startedAt`;
|
|
241
232
|
break;
|
|
242
233
|
case 'CREATE':
|
|
243
|
-
operation =
|
|
244
|
-
documentArgs =
|
|
234
|
+
operation = `create${typeName}`;
|
|
235
|
+
documentArgs = `($input: Create${typeName}Input!)`;
|
|
245
236
|
operationArgs = '(input: $input)';
|
|
246
237
|
transformerMutationType = TransformerMutationType.CREATE;
|
|
247
238
|
break;
|
|
248
239
|
case 'UPDATE':
|
|
249
|
-
operation =
|
|
250
|
-
documentArgs =
|
|
240
|
+
operation = `update${typeName}`;
|
|
241
|
+
documentArgs = `($input: Update${typeName}Input!, $condition: Model${typeName}ConditionInput)`;
|
|
251
242
|
operationArgs = '(input: $input, condition: $condition)';
|
|
252
243
|
transformerMutationType = TransformerMutationType.UPDATE;
|
|
253
244
|
break;
|
|
254
245
|
case 'DELETE':
|
|
255
|
-
operation =
|
|
256
|
-
documentArgs =
|
|
246
|
+
operation = `delete${typeName}`;
|
|
247
|
+
documentArgs = `($input: Delete${typeName}Input!, $condition: Model${typeName}ConditionInput)`;
|
|
257
248
|
operationArgs = '(input: $input, condition: $condition)';
|
|
258
249
|
transformerMutationType = TransformerMutationType.DELETE;
|
|
259
250
|
break;
|
|
260
251
|
case 'GET':
|
|
261
|
-
operation =
|
|
262
|
-
documentArgs =
|
|
252
|
+
operation = `get${typeName}`;
|
|
253
|
+
documentArgs = `($id: ID!)`;
|
|
263
254
|
operationArgs = '(id: $id)';
|
|
264
255
|
transformerMutationType = TransformerMutationType.GET;
|
|
265
256
|
break;
|
|
266
257
|
default:
|
|
267
|
-
throw new Error(
|
|
258
|
+
throw new Error(`Invalid graphQlOpType ${graphQLOpType}`);
|
|
268
259
|
}
|
|
269
260
|
return [
|
|
270
261
|
[
|
|
271
262
|
transformerMutationType,
|
|
272
263
|
operation,
|
|
273
|
-
GraphQLOperationType[graphQLOpType]
|
|
264
|
+
`${GraphQLOperationType[graphQLOpType]} operation${documentArgs}{
|
|
265
|
+
${operation}${operationArgs}{
|
|
266
|
+
${selectionSet}
|
|
267
|
+
}
|
|
268
|
+
}`,
|
|
274
269
|
],
|
|
275
270
|
];
|
|
276
271
|
}
|
|
277
272
|
export function createMutationInstanceFromModelOperation(relationships, modelDefinition, opType, model, element, condition, MutationEventConstructor, modelInstanceCreator, id) {
|
|
278
|
-
|
|
273
|
+
let operation;
|
|
279
274
|
switch (opType) {
|
|
280
275
|
case OpType.INSERT:
|
|
281
276
|
operation = TransformerMutationType.CREATE;
|
|
@@ -287,13 +282,13 @@ export function createMutationInstanceFromModelOperation(relationships, modelDef
|
|
|
287
282
|
operation = TransformerMutationType.DELETE;
|
|
288
283
|
break;
|
|
289
284
|
default:
|
|
290
|
-
throw new Error(
|
|
285
|
+
throw new Error(`Invalid opType ${opType}`);
|
|
291
286
|
}
|
|
292
287
|
// stringify nested objects of type AWSJSON
|
|
293
288
|
// this allows us to return parsed JSON to users (see `castInstanceType()` in datastore.ts),
|
|
294
289
|
// but still send the object correctly over the wire
|
|
295
|
-
|
|
296
|
-
|
|
290
|
+
const replacer = (k, v) => {
|
|
291
|
+
const isAWSJSON = k &&
|
|
297
292
|
v !== null &&
|
|
298
293
|
typeof v === 'object' &&
|
|
299
294
|
modelDefinition.fields[k] &&
|
|
@@ -303,13 +298,20 @@ export function createMutationInstanceFromModelOperation(relationships, modelDef
|
|
|
303
298
|
}
|
|
304
299
|
return v;
|
|
305
300
|
};
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
301
|
+
const modelId = getIdentifierValue(modelDefinition, element);
|
|
302
|
+
const optionalId = OpType.INSERT && id ? { id } : {};
|
|
303
|
+
const mutationEvent = modelInstanceCreator(MutationEventConstructor, {
|
|
304
|
+
...optionalId,
|
|
305
|
+
data: JSON.stringify(element, replacer),
|
|
306
|
+
modelId,
|
|
307
|
+
model: model.name,
|
|
308
|
+
operation: operation,
|
|
309
|
+
condition: JSON.stringify(condition),
|
|
310
|
+
});
|
|
309
311
|
return mutationEvent;
|
|
310
312
|
}
|
|
311
313
|
export function predicateToGraphQLCondition(predicate, modelDefinition) {
|
|
312
|
-
|
|
314
|
+
const result = {};
|
|
313
315
|
if (!predicate || !Array.isArray(predicate.predicates)) {
|
|
314
316
|
return result;
|
|
315
317
|
}
|
|
@@ -320,7 +322,7 @@ export function predicateToGraphQLCondition(predicate, modelDefinition) {
|
|
|
320
322
|
// Or all records where PK = some value but SKs are different values
|
|
321
323
|
// TODO: if the Transform gets updated we'll need to modify this logic to only omit
|
|
322
324
|
// key fields from the predicate/condition when ALL of the keyFields are present and using `eq` operators
|
|
323
|
-
|
|
325
|
+
const keyFields = extractPrimaryKeyFieldNames(modelDefinition);
|
|
324
326
|
return predicateToGraphQLFilter(predicate, keyFields);
|
|
325
327
|
}
|
|
326
328
|
/**
|
|
@@ -338,37 +340,34 @@ export function predicateToGraphQLCondition(predicate, modelDefinition) {
|
|
|
338
340
|
{ and:[{ username: { eq: 'bob' }}] }
|
|
339
341
|
```
|
|
340
342
|
*/
|
|
341
|
-
export function predicateToGraphQLFilter(predicatesGroup, fieldsToOmit, root) {
|
|
342
|
-
|
|
343
|
-
if (root === void 0) { root = true; }
|
|
344
|
-
var result = {};
|
|
343
|
+
export function predicateToGraphQLFilter(predicatesGroup, fieldsToOmit = [], root = true) {
|
|
344
|
+
const result = {};
|
|
345
345
|
if (!predicatesGroup || !Array.isArray(predicatesGroup.predicates)) {
|
|
346
346
|
return result;
|
|
347
347
|
}
|
|
348
|
-
|
|
349
|
-
|
|
348
|
+
const { type, predicates } = predicatesGroup;
|
|
349
|
+
const isList = type === 'and' || type === 'or';
|
|
350
350
|
result[type] = isList ? [] : {};
|
|
351
|
-
|
|
352
|
-
predicates.forEach(
|
|
353
|
-
var _a, _b;
|
|
351
|
+
const children = [];
|
|
352
|
+
predicates.forEach(predicate => {
|
|
354
353
|
if (isPredicateObj(predicate)) {
|
|
355
|
-
|
|
354
|
+
const { field, operator, operand } = predicate;
|
|
356
355
|
if (fieldsToOmit.includes(field))
|
|
357
356
|
return;
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
357
|
+
const gqlField = {
|
|
358
|
+
[field]: { [operator]: operand },
|
|
359
|
+
};
|
|
361
360
|
children.push(gqlField);
|
|
362
361
|
return;
|
|
363
362
|
}
|
|
364
|
-
|
|
363
|
+
const child = predicateToGraphQLFilter(predicate, fieldsToOmit, false);
|
|
365
364
|
if (Object.keys(child).length > 0) {
|
|
366
365
|
children.push(child);
|
|
367
366
|
}
|
|
368
367
|
});
|
|
369
368
|
// flatten redundant list predicates
|
|
370
369
|
if (children.length === 1) {
|
|
371
|
-
|
|
370
|
+
const [child] = children;
|
|
372
371
|
if (
|
|
373
372
|
// any nested list node
|
|
374
373
|
(isList && !root) ||
|
|
@@ -379,7 +378,7 @@ export function predicateToGraphQLFilter(predicatesGroup, fieldsToOmit, root) {
|
|
|
379
378
|
return result;
|
|
380
379
|
}
|
|
381
380
|
}
|
|
382
|
-
children.forEach(
|
|
381
|
+
children.forEach(child => {
|
|
383
382
|
if (isList) {
|
|
384
383
|
result[type].push(child);
|
|
385
384
|
}
|
|
@@ -403,18 +402,18 @@ export function predicateToGraphQLFilter(predicatesGroup, fieldsToOmit, root) {
|
|
|
403
402
|
* @returns set of distinct field names in the filter group
|
|
404
403
|
*/
|
|
405
404
|
export function filterFields(group) {
|
|
406
|
-
|
|
405
|
+
const fields = new Set();
|
|
407
406
|
if (!group || !Array.isArray(group.predicates))
|
|
408
407
|
return fields;
|
|
409
|
-
|
|
410
|
-
|
|
408
|
+
const { predicates } = group;
|
|
409
|
+
const stack = [...predicates];
|
|
411
410
|
while (stack.length > 0) {
|
|
412
|
-
|
|
411
|
+
const current = stack.pop();
|
|
413
412
|
if (isPredicateObj(current)) {
|
|
414
413
|
fields.add(current.field);
|
|
415
414
|
}
|
|
416
415
|
else if (isPredicateGroup(current)) {
|
|
417
|
-
stack.push
|
|
416
|
+
stack.push(...current.predicates);
|
|
418
417
|
}
|
|
419
418
|
}
|
|
420
419
|
return fields;
|
|
@@ -425,27 +424,16 @@ export function filterFields(group) {
|
|
|
425
424
|
* @returns set of field names used with dynamic auth modes configured for the provided model definition
|
|
426
425
|
*/
|
|
427
426
|
export function dynamicAuthFields(modelDefinition) {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
if (rule.groupsField && !rule.groups.length) {
|
|
435
|
-
// dynamic group rule will have no values in `rule.groups`
|
|
436
|
-
fields.add(rule.groupsField);
|
|
437
|
-
}
|
|
438
|
-
else if (rule.ownerField) {
|
|
439
|
-
fields.add(rule.ownerField);
|
|
440
|
-
}
|
|
427
|
+
const rules = getAuthorizationRules(modelDefinition);
|
|
428
|
+
const fields = new Set();
|
|
429
|
+
for (const rule of rules) {
|
|
430
|
+
if (rule.groupsField && !rule.groups.length) {
|
|
431
|
+
// dynamic group rule will have no values in `rule.groups`
|
|
432
|
+
fields.add(rule.groupsField);
|
|
441
433
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
finally {
|
|
445
|
-
try {
|
|
446
|
-
if (rules_1_1 && !rules_1_1.done && (_a = rules_1.return)) _a.call(rules_1);
|
|
434
|
+
else if (rule.ownerField) {
|
|
435
|
+
fields.add(rule.ownerField);
|
|
447
436
|
}
|
|
448
|
-
finally { if (e_1) throw e_1.error; }
|
|
449
437
|
}
|
|
450
438
|
return fields;
|
|
451
439
|
}
|
|
@@ -465,17 +453,17 @@ export function dynamicAuthFields(modelDefinition) {
|
|
|
465
453
|
export function countFilterCombinations(group) {
|
|
466
454
|
if (!group || !Array.isArray(group.predicates))
|
|
467
455
|
return 0;
|
|
468
|
-
|
|
469
|
-
|
|
456
|
+
let count = 0;
|
|
457
|
+
const stack = [group];
|
|
470
458
|
while (stack.length > 0) {
|
|
471
|
-
|
|
459
|
+
const current = stack.pop();
|
|
472
460
|
if (isPredicateGroup(current)) {
|
|
473
|
-
|
|
461
|
+
const { predicates, type } = current;
|
|
474
462
|
// ignore length = 1; groups with 1 predicate will get flattened when converted to gqlFilter
|
|
475
463
|
if (type === 'or' && predicates.length > 1) {
|
|
476
464
|
count += predicates.length;
|
|
477
465
|
}
|
|
478
|
-
stack.push
|
|
466
|
+
stack.push(...predicates);
|
|
479
467
|
}
|
|
480
468
|
}
|
|
481
469
|
// if we didn't encounter any OR groups, default to 1
|
|
@@ -498,50 +486,37 @@ export function repeatedFieldInGroup(group) {
|
|
|
498
486
|
if (!group || !Array.isArray(group.predicates))
|
|
499
487
|
return null;
|
|
500
488
|
// convert to filter in order to flatten redundant groups
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
var _b = __read(Object.keys(f), 1), fieldName = _b[0];
|
|
510
|
-
if (seen[fieldName]) {
|
|
511
|
-
return fieldName;
|
|
512
|
-
}
|
|
513
|
-
seen[fieldName] = true;
|
|
489
|
+
const gqlFilter = predicateToGraphQLFilter(group);
|
|
490
|
+
const stack = [gqlFilter];
|
|
491
|
+
const hasGroupRepeatedFields = (fields) => {
|
|
492
|
+
const seen = {};
|
|
493
|
+
for (const f of fields) {
|
|
494
|
+
const [fieldName] = Object.keys(f);
|
|
495
|
+
if (seen[fieldName]) {
|
|
496
|
+
return fieldName;
|
|
514
497
|
}
|
|
515
|
-
|
|
516
|
-
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
517
|
-
finally {
|
|
518
|
-
try {
|
|
519
|
-
if (fields_1_1 && !fields_1_1.done && (_a = fields_1.return)) _a.call(fields_1);
|
|
520
|
-
}
|
|
521
|
-
finally { if (e_2) throw e_2.error; }
|
|
498
|
+
seen[fieldName] = true;
|
|
522
499
|
}
|
|
523
500
|
return null;
|
|
524
501
|
};
|
|
525
502
|
while (stack.length > 0) {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
503
|
+
const current = stack.pop();
|
|
504
|
+
const [key] = Object.keys(current);
|
|
505
|
+
const values = current[key];
|
|
529
506
|
if (!Array.isArray(values)) {
|
|
530
507
|
return null;
|
|
531
508
|
}
|
|
532
509
|
// field value will be single object
|
|
533
|
-
|
|
510
|
+
const predicateObjects = values.filter(v => !Array.isArray(Object.values(v)[0]));
|
|
534
511
|
// group value will be an array
|
|
535
|
-
|
|
536
|
-
return Array.isArray(Object.values(v)[0]);
|
|
537
|
-
});
|
|
512
|
+
const predicateGroups = values.filter(v => Array.isArray(Object.values(v)[0]));
|
|
538
513
|
if (key === 'and') {
|
|
539
|
-
|
|
514
|
+
const repeatedField = hasGroupRepeatedFields(predicateObjects);
|
|
540
515
|
if (repeatedField) {
|
|
541
516
|
return repeatedField;
|
|
542
517
|
}
|
|
543
518
|
}
|
|
544
|
-
stack.push
|
|
519
|
+
stack.push(...predicateGroups);
|
|
545
520
|
}
|
|
546
521
|
return null;
|
|
547
522
|
}
|
|
@@ -555,41 +530,41 @@ export var RTFError;
|
|
|
555
530
|
RTFError[RTFError["FieldNotInType"] = 5] = "FieldNotInType";
|
|
556
531
|
})(RTFError || (RTFError = {}));
|
|
557
532
|
export function generateRTFRemediation(errorType, modelDefinition, predicatesGroup) {
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
533
|
+
const selSyncFields = filterFields(predicatesGroup);
|
|
534
|
+
const selSyncFieldStr = [...selSyncFields].join(', ');
|
|
535
|
+
const dynamicAuthModeFields = dynamicAuthFields(modelDefinition);
|
|
536
|
+
const dynamicAuthFieldsStr = [...dynamicAuthModeFields].join(', ');
|
|
537
|
+
const filterCombinations = countFilterCombinations(predicatesGroup);
|
|
538
|
+
const repeatedField = repeatedFieldInGroup(predicatesGroup);
|
|
564
539
|
switch (errorType) {
|
|
565
540
|
case RTFError.UnknownField:
|
|
566
|
-
return (
|
|
541
|
+
return (`Your API was generated with an older version of the CLI that doesn't support backend subscription filtering.` +
|
|
567
542
|
'To enable backend subscription filtering, upgrade your Amplify CLI to the latest version and push your app by running `amplify upgrade` followed by `amplify push`');
|
|
568
543
|
case RTFError.MaxAttributes: {
|
|
569
|
-
|
|
544
|
+
let message = `Your selective sync expression for ${modelDefinition.name} contains ${selSyncFields.size} different model fields: ${selSyncFieldStr}.\n\n`;
|
|
570
545
|
if (dynamicAuthModeFields.size > 0) {
|
|
571
546
|
message +=
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
547
|
+
`Note: the number of fields you can use with selective sync is affected by @auth rules configured on the model.\n\n` +
|
|
548
|
+
`Dynamic auth modes, such as owner auth and dynamic group auth each utilize 1 field.\n` +
|
|
549
|
+
`You currently have ${dynamicAuthModeFields.size} dynamic auth mode(s) configured on this model: ${dynamicAuthFieldsStr}.`;
|
|
575
550
|
}
|
|
576
551
|
return message;
|
|
577
552
|
}
|
|
578
553
|
case RTFError.MaxCombinations: {
|
|
579
|
-
|
|
554
|
+
let message = `Your selective sync expression for ${modelDefinition.name} contains ${filterCombinations} field combinations (total number of predicates in an OR expression).\n\n`;
|
|
580
555
|
if (dynamicAuthModeFields.size > 0) {
|
|
581
556
|
message +=
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
557
|
+
`Note: the number of fields you can use with selective sync is affected by @auth rules configured on the model.\n\n` +
|
|
558
|
+
`Dynamic auth modes, such as owner auth and dynamic group auth factor in to the number of combinations you're using.\n` +
|
|
559
|
+
`You currently have ${dynamicAuthModeFields.size} dynamic auth mode(s) configured on this model: ${dynamicAuthFieldsStr}.`;
|
|
585
560
|
}
|
|
586
561
|
return message;
|
|
587
562
|
}
|
|
588
563
|
case RTFError.RepeatedFieldname:
|
|
589
|
-
return
|
|
564
|
+
return `Your selective sync expression for ${modelDefinition.name} contains multiple entries for ${repeatedField} in the same AND group.`;
|
|
590
565
|
case RTFError.NotGroup:
|
|
591
|
-
return (
|
|
592
|
-
|
|
566
|
+
return (`Your selective sync expression for ${modelDefinition.name} uses a \`not\` group. If you'd like to filter subscriptions in the backend, ` +
|
|
567
|
+
`rewrite your expression using \`ne\` or \`notContains\` operators.`);
|
|
593
568
|
case RTFError.FieldNotInType:
|
|
594
569
|
// no remediation instructions. We'll surface the message directly
|
|
595
570
|
return '';
|
|
@@ -597,9 +572,9 @@ export function generateRTFRemediation(errorType, modelDefinition, predicatesGro
|
|
|
597
572
|
}
|
|
598
573
|
export function getUserGroupsFromToken(token, rule) {
|
|
599
574
|
// validate token against groupClaim
|
|
600
|
-
|
|
575
|
+
let userGroups = token[rule.groupClaim] || [];
|
|
601
576
|
if (typeof userGroups === 'string') {
|
|
602
|
-
|
|
577
|
+
let parsedGroups;
|
|
603
578
|
try {
|
|
604
579
|
parsedGroups = JSON.parse(userGroups);
|
|
605
580
|
}
|
|
@@ -610,122 +585,92 @@ export function getUserGroupsFromToken(token, rule) {
|
|
|
610
585
|
}
|
|
611
586
|
return userGroups;
|
|
612
587
|
}
|
|
613
|
-
export function getModelAuthModes(
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
_b.trys.push([1, 3, , 4]);
|
|
631
|
-
return [4 /*yield*/, Promise.all(operations.map(function (operation) { return __awaiter(_this, void 0, void 0, function () {
|
|
632
|
-
var authModes;
|
|
633
|
-
return __generator(this, function (_a) {
|
|
634
|
-
switch (_a.label) {
|
|
635
|
-
case 0: return [4 /*yield*/, authModeStrategy({
|
|
636
|
-
schema: schema,
|
|
637
|
-
modelName: modelName,
|
|
638
|
-
operation: operation,
|
|
639
|
-
})];
|
|
640
|
-
case 1:
|
|
641
|
-
authModes = _a.sent();
|
|
642
|
-
if (typeof authModes === 'string') {
|
|
643
|
-
modelAuthModes[operation] = [authModes];
|
|
644
|
-
}
|
|
645
|
-
else if (Array.isArray(authModes) && authModes.length) {
|
|
646
|
-
modelAuthModes[operation] = authModes;
|
|
647
|
-
}
|
|
648
|
-
else {
|
|
649
|
-
// Use default auth mode if nothing is returned from authModeStrategy
|
|
650
|
-
modelAuthModes[operation] = [defaultAuthMode];
|
|
651
|
-
}
|
|
652
|
-
return [2 /*return*/];
|
|
653
|
-
}
|
|
654
|
-
});
|
|
655
|
-
}); }))];
|
|
656
|
-
case 2:
|
|
657
|
-
_b.sent();
|
|
658
|
-
return [3 /*break*/, 4];
|
|
659
|
-
case 3:
|
|
660
|
-
error_1 = _b.sent();
|
|
661
|
-
logger.debug("Error getting auth modes for model: " + modelName, error_1);
|
|
662
|
-
return [3 /*break*/, 4];
|
|
663
|
-
case 4: return [2 /*return*/, modelAuthModes];
|
|
588
|
+
export async function getModelAuthModes({ authModeStrategy, defaultAuthMode, modelName, schema, }) {
|
|
589
|
+
const operations = Object.values(ModelOperation);
|
|
590
|
+
const modelAuthModes = {
|
|
591
|
+
CREATE: [],
|
|
592
|
+
READ: [],
|
|
593
|
+
UPDATE: [],
|
|
594
|
+
DELETE: [],
|
|
595
|
+
};
|
|
596
|
+
try {
|
|
597
|
+
await Promise.all(operations.map(async (operation) => {
|
|
598
|
+
const authModes = await authModeStrategy({
|
|
599
|
+
schema,
|
|
600
|
+
modelName,
|
|
601
|
+
operation,
|
|
602
|
+
});
|
|
603
|
+
if (typeof authModes === 'string') {
|
|
604
|
+
modelAuthModes[operation] = [authModes];
|
|
664
605
|
}
|
|
665
|
-
|
|
666
|
-
|
|
606
|
+
else if (Array.isArray(authModes) && authModes.length) {
|
|
607
|
+
modelAuthModes[operation] = authModes;
|
|
608
|
+
}
|
|
609
|
+
else {
|
|
610
|
+
// Use default auth mode if nothing is returned from authModeStrategy
|
|
611
|
+
modelAuthModes[operation] = [defaultAuthMode];
|
|
612
|
+
}
|
|
613
|
+
}));
|
|
614
|
+
}
|
|
615
|
+
catch (error) {
|
|
616
|
+
logger.debug(`Error getting auth modes for model: ${modelName}`, error);
|
|
617
|
+
}
|
|
618
|
+
return modelAuthModes;
|
|
667
619
|
}
|
|
668
620
|
export function getForbiddenError(error) {
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
'Request failed with status code 403',
|
|
672
|
-
];
|
|
673
|
-
var forbiddenError;
|
|
621
|
+
const forbiddenErrorCodes = [401, 403];
|
|
622
|
+
let forbiddenError;
|
|
674
623
|
if (error && error.errors) {
|
|
675
|
-
forbiddenError = error.errors.find(
|
|
676
|
-
return forbiddenErrorMessages.includes(err.message);
|
|
677
|
-
});
|
|
624
|
+
forbiddenError = error.errors.find(err => forbiddenErrorCodes.includes(resolveServiceErrorStatusCode(err)));
|
|
678
625
|
}
|
|
679
626
|
else if (error && error.message) {
|
|
680
627
|
forbiddenError = error;
|
|
681
628
|
}
|
|
682
629
|
if (forbiddenError) {
|
|
683
|
-
return forbiddenError.message
|
|
630
|
+
return (forbiddenError.message ??
|
|
631
|
+
`Request failed with status code ${resolveServiceErrorStatusCode(forbiddenError)}`);
|
|
684
632
|
}
|
|
685
633
|
return null;
|
|
686
634
|
}
|
|
635
|
+
export function resolveServiceErrorStatusCode(error) {
|
|
636
|
+
if (error?.['$metadata']?.['httpStatusCode']) {
|
|
637
|
+
return Number(error?.['$metadata']?.['httpStatusCode']);
|
|
638
|
+
}
|
|
639
|
+
else if (error?.originalError) {
|
|
640
|
+
return resolveServiceErrorStatusCode(error?.originalError);
|
|
641
|
+
}
|
|
642
|
+
else {
|
|
643
|
+
return null;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
687
646
|
export function getClientSideAuthError(error) {
|
|
688
|
-
|
|
689
|
-
|
|
647
|
+
const clientSideAuthErrors = Object.values(GraphQLAuthError);
|
|
648
|
+
const clientSideError = error &&
|
|
690
649
|
error.message &&
|
|
691
|
-
clientSideAuthErrors.find(
|
|
692
|
-
return error.message.includes(clientError);
|
|
693
|
-
});
|
|
650
|
+
clientSideAuthErrors.find(clientError => error.message.includes(clientError));
|
|
694
651
|
return clientSideError || null;
|
|
695
652
|
}
|
|
696
|
-
export function getTokenForCustomAuth(authMode, amplifyConfig) {
|
|
697
|
-
if (
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
if (!(authMode === GRAPHQL_AUTH_MODE.AWS_LAMBDA)) return [3 /*break*/, 6];
|
|
704
|
-
_a = amplifyConfig.authProviders, functionAuthProvider = (_a === void 0 ? { functionAuthProvider: null } : _a).functionAuthProvider;
|
|
705
|
-
if (!(functionAuthProvider && typeof functionAuthProvider === 'function')) return [3 /*break*/, 5];
|
|
706
|
-
_b.label = 1;
|
|
707
|
-
case 1:
|
|
708
|
-
_b.trys.push([1, 3, , 4]);
|
|
709
|
-
return [4 /*yield*/, functionAuthProvider()];
|
|
710
|
-
case 2:
|
|
711
|
-
token = (_b.sent()).token;
|
|
712
|
-
return [2 /*return*/, token];
|
|
713
|
-
case 3:
|
|
714
|
-
error_2 = _b.sent();
|
|
715
|
-
throw new Error("Error retrieving token from `functionAuthProvider`: " + error_2);
|
|
716
|
-
case 4: return [3 /*break*/, 6];
|
|
717
|
-
case 5:
|
|
718
|
-
// TODO: add docs link once available
|
|
719
|
-
throw new Error("You must provide a `functionAuthProvider` function to `DataStore.configure` when using " + GRAPHQL_AUTH_MODE.AWS_LAMBDA);
|
|
720
|
-
case 6: return [2 /*return*/];
|
|
653
|
+
export async function getTokenForCustomAuth(authMode, amplifyConfig = {}) {
|
|
654
|
+
if (authMode === 'lambda') {
|
|
655
|
+
const { authProviders: { functionAuthProvider } = { functionAuthProvider: null }, } = amplifyConfig;
|
|
656
|
+
if (functionAuthProvider && typeof functionAuthProvider === 'function') {
|
|
657
|
+
try {
|
|
658
|
+
const { token } = await functionAuthProvider();
|
|
659
|
+
return token;
|
|
721
660
|
}
|
|
722
|
-
|
|
723
|
-
|
|
661
|
+
catch (error) {
|
|
662
|
+
throw new Error(`Error retrieving token from \`functionAuthProvider\`: ${error}`);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
else {
|
|
666
|
+
// TODO: add docs link once available
|
|
667
|
+
throw new Error('You must provide a `functionAuthProvider` function to `DataStore.configure` when using lambda');
|
|
668
|
+
}
|
|
669
|
+
}
|
|
724
670
|
}
|
|
725
671
|
// Util that takes a modelDefinition and model and returns either the id value(s) or the custom primary key value(s)
|
|
726
672
|
export function getIdentifierValue(modelDefinition, model) {
|
|
727
|
-
|
|
728
|
-
|
|
673
|
+
const pkFieldNames = extractPrimaryKeyFieldNames(modelDefinition);
|
|
674
|
+
const idOrPk = pkFieldNames.map(f => model[f]).join(IDENTIFIER_KEY_SEPARATOR);
|
|
729
675
|
return idOrPk;
|
|
730
676
|
}
|
|
731
|
-
//# sourceMappingURL=utils.js.map
|