@aws-amplify/graphql-model-transformer 0.7.0-auth-dir-v-next.4 → 0.8.0-beta.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/CHANGELOG.md +11 -29
- package/lib/graphql-model-transformer.d.ts +1 -0
- package/lib/graphql-model-transformer.d.ts.map +1 -1
- package/lib/graphql-model-transformer.js +23 -13
- package/lib/graphql-model-transformer.js.map +1 -1
- package/lib/graphql-types/query.js +1 -1
- package/lib/graphql-types/query.js.map +1 -1
- package/lib/resolvers/common.js +1 -1
- package/lib/resolvers/common.js.map +1 -1
- package/lib/resolvers/mutation.d.ts.map +1 -1
- package/lib/resolvers/mutation.js +0 -1
- package/lib/resolvers/mutation.js.map +1 -1
- package/lib/resolvers/query.d.ts.map +1 -1
- package/lib/resolvers/query.js +7 -5
- package/lib/resolvers/query.js.map +1 -1
- package/lib/resolvers/subscriptions.js +1 -1
- package/lib/resolvers/subscriptions.js.map +1 -1
- package/lib/wrappers/object-definition-wrapper.js +1 -1
- package/lib/wrappers/object-definition-wrapper.js.map +1 -1
- package/package.json +34 -32
- package/src/__tests__/__snapshots__/model-transformer.test.ts.snap +326 -796
- package/src/__tests__/model-transformer.test.ts +60 -7
- package/src/graphql-model-transformer.ts +23 -17
- package/src/graphql-types/query.ts +1 -1
- package/src/resolvers/common.ts +1 -1
- package/src/resolvers/mutation.ts +0 -3
- package/src/resolvers/query.ts +10 -11
- package/src/resolvers/subscriptions.ts +1 -1
- package/src/wrappers/object-definition-wrapper.ts +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
verifyInputCount,
|
|
14
14
|
verifyMatchingTypes,
|
|
15
15
|
} from './test-utils/helpers';
|
|
16
|
+
import { expect as cdkExpect, haveResource } from '@aws-cdk/assert';
|
|
16
17
|
|
|
17
18
|
const featureFlags = {
|
|
18
19
|
getBoolean: jest.fn(),
|
|
@@ -912,7 +913,7 @@ describe('ModelTransformer: ', () => {
|
|
|
912
913
|
validateModelSchema(parse(definition));
|
|
913
914
|
});
|
|
914
915
|
|
|
915
|
-
it('should generate sync resolver with ConflictHandlerType.
|
|
916
|
+
it('should generate sync resolver with ConflictHandlerType.LAMBDA', () => {
|
|
916
917
|
const validSchema = `
|
|
917
918
|
type Post @model {
|
|
918
919
|
id: ID!
|
|
@@ -983,24 +984,76 @@ describe('ModelTransformer: ', () => {
|
|
|
983
984
|
validateModelSchema(parse(definition));
|
|
984
985
|
});
|
|
985
986
|
|
|
986
|
-
it('should
|
|
987
|
+
it('should generate iam role names under 64 chars and subscriptions under 50', () => {
|
|
987
988
|
const validSchema = `
|
|
988
|
-
type
|
|
989
|
-
|
|
990
|
-
type Post @model {
|
|
989
|
+
type ThisIsAVeryLongNameModelThatShouldNotGenerateIAMRoleNamesOver64Characters @model {
|
|
991
990
|
id: ID!
|
|
992
991
|
title: String!
|
|
993
992
|
}
|
|
994
993
|
`;
|
|
995
994
|
|
|
995
|
+
const config: SyncConfig = {
|
|
996
|
+
ConflictDetection: 'VERSION',
|
|
997
|
+
ConflictHandler: ConflictHandlerType.AUTOMERGE,
|
|
998
|
+
};
|
|
999
|
+
|
|
996
1000
|
const transformer = new GraphQLTransform({
|
|
997
1001
|
transformers: [new ModelTransformer()],
|
|
998
1002
|
featureFlags,
|
|
1003
|
+
transformConfig: {
|
|
1004
|
+
ResolverConfig: {
|
|
1005
|
+
project: config,
|
|
1006
|
+
},
|
|
1007
|
+
},
|
|
999
1008
|
});
|
|
1000
|
-
|
|
1001
1009
|
const out = transformer.transform(validSchema);
|
|
1002
1010
|
expect(out).toBeDefined();
|
|
1003
1011
|
|
|
1004
|
-
|
|
1012
|
+
const definition = out.schema;
|
|
1013
|
+
expect(definition).toBeDefined();
|
|
1014
|
+
|
|
1015
|
+
const parsed = parse(definition);
|
|
1016
|
+
const subscriptionType = getObjectType(parsed, 'Subscription');
|
|
1017
|
+
expect(subscriptionType).toBeDefined();
|
|
1018
|
+
|
|
1019
|
+
subscriptionType!.fields!.forEach(it => {
|
|
1020
|
+
expect(it.name.value.length <= 50).toBeTruthy();
|
|
1021
|
+
});
|
|
1022
|
+
|
|
1023
|
+
const iamStackResource = out.stacks.ThisIsAVeryLongNameModelThatShouldNotGenerateIAMRoleNamesOver64Characters;
|
|
1024
|
+
expect(iamStackResource).toBeDefined();
|
|
1025
|
+
cdkExpect(iamStackResource).to(
|
|
1026
|
+
haveResource('AWS::IAM::Role', {
|
|
1027
|
+
AssumeRolePolicyDocument: {
|
|
1028
|
+
Statement: [
|
|
1029
|
+
{
|
|
1030
|
+
Action: 'sts:AssumeRole',
|
|
1031
|
+
Effect: 'Allow',
|
|
1032
|
+
Principal: {
|
|
1033
|
+
Service: 'appsync.amazonaws.com',
|
|
1034
|
+
},
|
|
1035
|
+
},
|
|
1036
|
+
],
|
|
1037
|
+
Version: '2012-10-17',
|
|
1038
|
+
},
|
|
1039
|
+
RoleName: {
|
|
1040
|
+
'Fn::Join': [
|
|
1041
|
+
'',
|
|
1042
|
+
[
|
|
1043
|
+
'ThisIsAVeryLongNameM2d9fca-',
|
|
1044
|
+
{
|
|
1045
|
+
Ref: 'referencetotransformerrootstackGraphQLAPI20497F53ApiId',
|
|
1046
|
+
},
|
|
1047
|
+
'-',
|
|
1048
|
+
{
|
|
1049
|
+
Ref: 'referencetotransformerrootstackenv10C5A902Ref',
|
|
1050
|
+
},
|
|
1051
|
+
],
|
|
1052
|
+
],
|
|
1053
|
+
},
|
|
1054
|
+
}),
|
|
1055
|
+
);
|
|
1056
|
+
|
|
1057
|
+
validateModelSchema(parsed);
|
|
1005
1058
|
});
|
|
1006
1059
|
});
|
|
@@ -78,6 +78,7 @@ import {
|
|
|
78
78
|
ObjectDefinitionWrapper,
|
|
79
79
|
} from './wrappers/object-definition-wrapper';
|
|
80
80
|
import { CfnRole } from '@aws-cdk/aws-iam';
|
|
81
|
+
import md5 from 'md5';
|
|
81
82
|
|
|
82
83
|
export type Nullable<T> = T | null;
|
|
83
84
|
export type OptionalAndNullable<T> = Partial<T>;
|
|
@@ -176,14 +177,17 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
176
177
|
}
|
|
177
178
|
// todo: get model configuration with default values and store it in the map
|
|
178
179
|
const typeName = definition.name.value;
|
|
180
|
+
|
|
181
|
+
if (ctx.isProjectUsingDataStore()) {
|
|
182
|
+
SyncUtils.validateResolverConfigForType(ctx, typeName);
|
|
183
|
+
}
|
|
184
|
+
|
|
179
185
|
const directiveWrapped: DirectiveWrapper = new DirectiveWrapper(directive);
|
|
180
186
|
const options = directiveWrapped.getArguments({
|
|
181
187
|
queries: {
|
|
182
188
|
get: toCamelCase(['get', typeName]),
|
|
183
189
|
list: toCamelCase(['list', plurality(typeName, true)]),
|
|
184
|
-
...(
|
|
185
|
-
? { sync: toCamelCase(['sync', plurality(typeName, true)]) }
|
|
186
|
-
: undefined),
|
|
190
|
+
...(ctx.isProjectUsingDataStore() ? { sync: toCamelCase(['sync', plurality(typeName, true)]) } : undefined),
|
|
187
191
|
},
|
|
188
192
|
mutations: {
|
|
189
193
|
create: toCamelCase(['create', typeName]),
|
|
@@ -192,9 +196,9 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
192
196
|
},
|
|
193
197
|
subscriptions: {
|
|
194
198
|
level: SubscriptionLevel.on,
|
|
195
|
-
onCreate: [toCamelCase(['onCreate', typeName])],
|
|
196
|
-
onDelete: [toCamelCase(['onDelete', typeName])],
|
|
197
|
-
onUpdate: [toCamelCase(['onUpdate', typeName])],
|
|
199
|
+
onCreate: [this.ensureValidSubscriptionName(toCamelCase(['onCreate', typeName]))],
|
|
200
|
+
onDelete: [this.ensureValidSubscriptionName(toCamelCase(['onDelete', typeName]))],
|
|
201
|
+
onUpdate: [this.ensureValidSubscriptionName(toCamelCase(['onUpdate', typeName]))],
|
|
198
202
|
},
|
|
199
203
|
timestamps: {
|
|
200
204
|
createdAt: 'createdAt',
|
|
@@ -237,7 +241,6 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
237
241
|
this.addAutoGeneratableFields(ctx, type);
|
|
238
242
|
|
|
239
243
|
if (ctx.isProjectUsingDataStore()) {
|
|
240
|
-
this.options.SyncConfig = SyncUtils.getSyncConfig(ctx as TransformerContextProvider, def!.name.value);
|
|
241
244
|
this.addModelSyncFields(ctx, type);
|
|
242
245
|
}
|
|
243
246
|
}
|
|
@@ -1072,7 +1075,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
1072
1075
|
stream: StreamViewType.NEW_AND_OLD_IMAGES,
|
|
1073
1076
|
encryption: TableEncryption.DEFAULT,
|
|
1074
1077
|
removalPolicy: removalPolicy,
|
|
1075
|
-
...(
|
|
1078
|
+
...(context.isProjectUsingDataStore() ? { timeToLiveAttribute: '_ttl' } : undefined),
|
|
1076
1079
|
});
|
|
1077
1080
|
const cfnTable = table.node.defaultChild as CfnTable;
|
|
1078
1081
|
|
|
@@ -1129,7 +1132,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
1129
1132
|
const cfnDataSource = dataSource.node.defaultChild as CfnDataSource;
|
|
1130
1133
|
cfnDataSource.addDependsOn(role.node.defaultChild as CfnRole);
|
|
1131
1134
|
|
|
1132
|
-
if (
|
|
1135
|
+
if (context.isProjectUsingDataStore()) {
|
|
1133
1136
|
const datasourceDynamoDb = cfnDataSource.dynamoDbConfig as any;
|
|
1134
1137
|
datasourceDynamoDb.deltaSyncConfig = {
|
|
1135
1138
|
deltaSyncTableName: context.resourceHelper.generateResourceName(SyncResourceIDs.syncTableName),
|
|
@@ -1153,7 +1156,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
1153
1156
|
}
|
|
1154
1157
|
|
|
1155
1158
|
private createIAMRole(context: TransformerContextProvider, def: ObjectTypeDefinitionNode, stack: cdk.Stack, tableName: string) {
|
|
1156
|
-
const roleName = context.resourceHelper.
|
|
1159
|
+
const roleName = context.resourceHelper.generateIAMRoleName(ModelResourceIDs.ModelTableIAMRoleID(def!.name.value));
|
|
1157
1160
|
const role = new iam.Role(stack, ModelResourceIDs.ModelTableIAMRoleID(def!.name.value), {
|
|
1158
1161
|
roleName: roleName,
|
|
1159
1162
|
assumedBy: new iam.ServicePrincipal('appsync.amazonaws.com'),
|
|
@@ -1184,7 +1187,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
1184
1187
|
cdk.Fn.sub('arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${tablename}/*', {
|
|
1185
1188
|
tablename: tableName,
|
|
1186
1189
|
}),
|
|
1187
|
-
...(
|
|
1190
|
+
...(context.isProjectUsingDataStore()
|
|
1188
1191
|
? [
|
|
1189
1192
|
// eslint-disable-next-line no-template-curly-in-string
|
|
1190
1193
|
cdk.Fn.sub('arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${tablename}', {
|
|
@@ -1202,13 +1205,10 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
1202
1205
|
}),
|
|
1203
1206
|
);
|
|
1204
1207
|
|
|
1205
|
-
|
|
1208
|
+
const syncConfig = SyncUtils.getSyncConfig(context, def!.name.value);
|
|
1209
|
+
if (syncConfig && SyncUtils.isLambdaSyncConfig(syncConfig)) {
|
|
1206
1210
|
role.attachInlinePolicy(
|
|
1207
|
-
SyncUtils.createSyncLambdaIAMPolicy(
|
|
1208
|
-
stack,
|
|
1209
|
-
this.options.SyncConfig.LambdaConflictHandler.name,
|
|
1210
|
-
this.options.SyncConfig.LambdaConflictHandler.region,
|
|
1211
|
-
),
|
|
1211
|
+
SyncUtils.createSyncLambdaIAMPolicy(stack, syncConfig.LambdaConflictHandler.name, syncConfig.LambdaConflictHandler.region),
|
|
1212
1212
|
);
|
|
1213
1213
|
}
|
|
1214
1214
|
return role;
|
|
@@ -1228,4 +1228,10 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
1228
1228
|
...options,
|
|
1229
1229
|
};
|
|
1230
1230
|
};
|
|
1231
|
+
|
|
1232
|
+
private ensureValidSubscriptionName = (name: string): string => {
|
|
1233
|
+
if (name.length <= 50) return name;
|
|
1234
|
+
|
|
1235
|
+
return name.slice(0, 45) + md5(name).slice(0, 5);
|
|
1236
|
+
};
|
|
1231
1237
|
}
|
|
@@ -13,7 +13,7 @@ export const makeListQueryFilterInput = (
|
|
|
13
13
|
export const makeListQueryModel = (type: ObjectTypeDefinitionNode, modelName: string, isSyncEnabled: boolean): ObjectTypeDefinitionNode => {
|
|
14
14
|
const outputType = ObjectDefinitionWrapper.create(modelName);
|
|
15
15
|
|
|
16
|
-
outputType.addField(FieldWrapper.create('items', type.name.value,
|
|
16
|
+
outputType.addField(FieldWrapper.create('items', type.name.value, false, true));
|
|
17
17
|
outputType.addField(FieldWrapper.create('nextToken', 'String', true, false));
|
|
18
18
|
|
|
19
19
|
if (isSyncEnabled) {
|
package/src/resolvers/common.ts
CHANGED
|
@@ -99,7 +99,7 @@ export const generateResolverKey = (typeName: string, fieldName: string): string
|
|
|
99
99
|
* @param ctx context to get sandbox mode
|
|
100
100
|
*/
|
|
101
101
|
export const generateAuthExpressionForSandboxMode = (ctx: any): string => {
|
|
102
|
-
|
|
102
|
+
const enabled = ctx.resourceHelper.api.sandboxModeEnabled;
|
|
103
103
|
let exp;
|
|
104
104
|
|
|
105
105
|
if (enabled) exp = iff(notEquals(methodCall(ref('util.authType')), str(API_KEY)), methodCall(ref('util.unauthorized')));
|
|
@@ -152,8 +152,6 @@ export const generateUpdateRequestTemplate = (modelName: string, isSyncEnabled:
|
|
|
152
152
|
*/
|
|
153
153
|
export const generateCreateRequestTemplate = (modelName: string): string => {
|
|
154
154
|
const statements: Expression[] = [
|
|
155
|
-
// set key the condition
|
|
156
|
-
...generateKeyConditionTemplate(false),
|
|
157
155
|
// Generate conditions
|
|
158
156
|
comment('Set the default values to put request'),
|
|
159
157
|
set(ref('mergedValues'), methodCall(ref('util.defaultIfNull'), ref('ctx.stash.defaultValues'), obj({}))),
|
|
@@ -174,7 +172,6 @@ export const generateCreateRequestTemplate = (modelName: string): string => {
|
|
|
174
172
|
),
|
|
175
173
|
|
|
176
174
|
// add conditions
|
|
177
|
-
|
|
178
175
|
iff(ref('context.args.condition'), qref(methodCall(ref('ctx.stash.conditions.add'), ref('context.args.condition')))),
|
|
179
176
|
// key conditions
|
|
180
177
|
...generateKeyConditionTemplate(false),
|
package/src/resolvers/query.ts
CHANGED
|
@@ -34,13 +34,18 @@ export const generateGetRequestTemplate = (): string => {
|
|
|
34
34
|
ref('ctx.stash.metadata.modelObjectKey'),
|
|
35
35
|
compoundExpression([
|
|
36
36
|
set(ref('expression'), str('')),
|
|
37
|
+
set(ref('expressionNames'), obj({})),
|
|
37
38
|
set(ref('expressionValues'), obj({})),
|
|
38
39
|
forEach(ref('item'), ref('ctx.stash.metadata.modelObjectKey.entrySet()'), [
|
|
39
|
-
set(ref('expression'), str('$expression$
|
|
40
|
-
qref(methodCall(ref('
|
|
40
|
+
set(ref('expression'), str('$expression#keyCount$velocityCount = :valueCount$velocityCount AND ')),
|
|
41
|
+
qref(methodCall(ref('expressionNames.put'), str('#keyCount$velocityCount'), ref('item.key'))),
|
|
42
|
+
qref(methodCall(ref('expressionValues.put'), str(':valueCount$velocityCount'), ref('item.value'))),
|
|
41
43
|
]),
|
|
42
44
|
set(ref('expression'), methodCall(ref('expression.replaceAll'), str('AND $'), str(''))),
|
|
43
|
-
set(
|
|
45
|
+
set(
|
|
46
|
+
ref('query'),
|
|
47
|
+
obj({ expression: ref('expression'), expressionNames: ref('expressionNames'), expressionValues: ref('expressionValues') }),
|
|
48
|
+
),
|
|
44
49
|
]),
|
|
45
50
|
set(
|
|
46
51
|
ref('query'),
|
|
@@ -109,10 +114,7 @@ export const generateListRequestTemplate = (): string => {
|
|
|
109
114
|
not(isNullOrEmpty(authFilter)),
|
|
110
115
|
compoundExpression([
|
|
111
116
|
set(ref('filter'), authFilter),
|
|
112
|
-
iff(
|
|
113
|
-
not(isNullOrEmpty(ref('ctx.args.filter'))),
|
|
114
|
-
set(ref('filter'), list([obj({ and: list([ref('filter'), ref('ctx.args.filter')]) })])),
|
|
115
|
-
),
|
|
117
|
+
iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), obj({ and: list([ref('filter'), ref('ctx.args.filter')]) }))),
|
|
116
118
|
]),
|
|
117
119
|
iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), ref('ctx.args.filter'))),
|
|
118
120
|
),
|
|
@@ -164,10 +166,7 @@ export const generateSyncRequestTemplate = (): string => {
|
|
|
164
166
|
not(isNullOrEmpty(authFilter)),
|
|
165
167
|
compoundExpression([
|
|
166
168
|
set(ref('filter'), authFilter),
|
|
167
|
-
iff(
|
|
168
|
-
not(isNullOrEmpty(ref('ctx.args.filter'))),
|
|
169
|
-
set(ref('filter'), list([obj({ and: list([ref('filter'), ref('ctx.args.filter')]) })])),
|
|
170
|
-
),
|
|
169
|
+
iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), obj({ and: list([ref('filter'), ref('ctx.args.filter')]) }))),
|
|
171
170
|
]),
|
|
172
171
|
iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), ref('ctx.args.filter'))),
|
|
173
172
|
),
|
|
@@ -7,5 +7,5 @@ export const generateSubscriptionRequestTemplate = (): string => {
|
|
|
7
7
|
|
|
8
8
|
export const generateSubscriptionResponseTemplate = (): string => {
|
|
9
9
|
const statements: Expression[] = [toJson(nul())];
|
|
10
|
-
return printBlock('Subscription
|
|
10
|
+
return printBlock('Subscription Response template')(compoundExpression(statements));
|
|
11
11
|
};
|