@aws-amplify/graphql-model-transformer 0.6.3-headless-s3-not-for-production.0 → 0.6.5-amplify-export2.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 +19 -1
- package/lib/definitions.d.ts +1 -0
- package/lib/definitions.d.ts.map +1 -1
- package/lib/definitions.js +2 -1
- package/lib/definitions.js.map +1 -1
- package/lib/graphql-model-transformer.d.ts +6 -5
- package/lib/graphql-model-transformer.d.ts.map +1 -1
- package/lib/graphql-model-transformer.js +48 -11
- package/lib/graphql-model-transformer.js.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -1
- package/lib/index.js.map +1 -1
- package/lib/resolvers/common.d.ts +2 -1
- package/lib/resolvers/common.d.ts.map +1 -1
- package/lib/resolvers/common.js +17 -3
- 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 +1 -0
- package/lib/resolvers/query.d.ts.map +1 -1
- package/lib/resolvers/query.js +55 -7
- package/lib/resolvers/query.js.map +1 -1
- package/package.json +34 -32
- package/src/__tests__/__snapshots__/model-transformer.test.ts.snap +3300 -1052
- package/src/__tests__/model-transformer.test.ts +76 -2
- package/src/definitions.ts +1 -1
- package/src/graphql-model-transformer.ts +80 -25
- package/src/index.ts +2 -1
- package/src/resolvers/common.ts +27 -3
- package/src/resolvers/mutation.ts +0 -3
- package/src/resolvers/query.ts +101 -7
- 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(),
|
|
@@ -880,7 +881,7 @@ describe('ModelTransformer: ', () => {
|
|
|
880
881
|
validateModelSchema(parse(out.schema));
|
|
881
882
|
});
|
|
882
883
|
|
|
883
|
-
it('should generate sync resolver with ConflictHandlerType.
|
|
884
|
+
it('should generate sync resolver with ConflictHandlerType.Automerge', () => {
|
|
884
885
|
const validSchema = `
|
|
885
886
|
type Post @model {
|
|
886
887
|
id: ID!
|
|
@@ -949,7 +950,7 @@ describe('ModelTransformer: ', () => {
|
|
|
949
950
|
validateModelSchema(parse(definition));
|
|
950
951
|
});
|
|
951
952
|
|
|
952
|
-
it('should generate sync resolver with ConflictHandlerType.
|
|
953
|
+
it('should generate sync resolver with ConflictHandlerType.Optimistic', () => {
|
|
953
954
|
const validSchema = `
|
|
954
955
|
type Post @model {
|
|
955
956
|
id: ID!
|
|
@@ -982,4 +983,77 @@ describe('ModelTransformer: ', () => {
|
|
|
982
983
|
|
|
983
984
|
validateModelSchema(parse(definition));
|
|
984
985
|
});
|
|
986
|
+
|
|
987
|
+
it('should generate iam role names under 64 chars and subscriptions under 50', () => {
|
|
988
|
+
const validSchema = `
|
|
989
|
+
type ThisIsAVeryLongNameModelThatShouldNotGenerateIAMRoleNamesOver64Characters @model {
|
|
990
|
+
id: ID!
|
|
991
|
+
title: String!
|
|
992
|
+
}
|
|
993
|
+
`;
|
|
994
|
+
|
|
995
|
+
const config: SyncConfig = {
|
|
996
|
+
ConflictDetection: 'VERSION',
|
|
997
|
+
ConflictHandler: ConflictHandlerType.AUTOMERGE,
|
|
998
|
+
};
|
|
999
|
+
|
|
1000
|
+
const transformer = new GraphQLTransform({
|
|
1001
|
+
transformers: [new ModelTransformer()],
|
|
1002
|
+
featureFlags,
|
|
1003
|
+
transformConfig: {
|
|
1004
|
+
ResolverConfig: {
|
|
1005
|
+
project: config,
|
|
1006
|
+
},
|
|
1007
|
+
},
|
|
1008
|
+
});
|
|
1009
|
+
const out = transformer.transform(validSchema);
|
|
1010
|
+
expect(out).toBeDefined();
|
|
1011
|
+
|
|
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);
|
|
1058
|
+
});
|
|
985
1059
|
});
|
package/src/definitions.ts
CHANGED
|
@@ -13,4 +13,4 @@ export const BOOLEAN_FUNCTIONS = new Set<string>(['attributeExists', 'attributeT
|
|
|
13
13
|
|
|
14
14
|
export const ATTRIBUTE_TYPES = ['binary', 'binarySet', 'bool', 'list', 'map', 'number', 'numberSet', 'string', 'stringSet', '_null'];
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
export const OPERATION_KEY = '__operation';
|
|
@@ -54,6 +54,7 @@ import {
|
|
|
54
54
|
makeUpdateInputField,
|
|
55
55
|
} from './graphql-types';
|
|
56
56
|
import {
|
|
57
|
+
generateAuthExpressionForSandboxMode,
|
|
57
58
|
generateCreateInitSlotTemplate,
|
|
58
59
|
generateCreateRequestTemplate,
|
|
59
60
|
generateDefaultResponseMappingTemplate,
|
|
@@ -64,7 +65,12 @@ import {
|
|
|
64
65
|
generateUpdateInitSlotTemplate,
|
|
65
66
|
generateUpdateRequestTemplate,
|
|
66
67
|
} from './resolvers';
|
|
67
|
-
import {
|
|
68
|
+
import {
|
|
69
|
+
generateGetRequestTemplate,
|
|
70
|
+
generateGetResponseTemplate,
|
|
71
|
+
generateListRequestTemplate,
|
|
72
|
+
generateSyncRequestTemplate,
|
|
73
|
+
} from './resolvers/query';
|
|
68
74
|
import {
|
|
69
75
|
DirectiveWrapper,
|
|
70
76
|
FieldWrapper,
|
|
@@ -72,6 +78,7 @@ import {
|
|
|
72
78
|
ObjectDefinitionWrapper,
|
|
73
79
|
} from './wrappers/object-definition-wrapper';
|
|
74
80
|
import { CfnRole } from '@aws-cdk/aws-iam';
|
|
81
|
+
import md5 from 'md5';
|
|
75
82
|
|
|
76
83
|
export type Nullable<T> = T | null;
|
|
77
84
|
export type OptionalAndNullable<T> = Partial<T>;
|
|
@@ -87,17 +94,17 @@ export type ModelDirectiveConfiguration = {
|
|
|
87
94
|
list: OptionalAndNullable<string>;
|
|
88
95
|
sync: OptionalAndNullable<string>;
|
|
89
96
|
}>;
|
|
90
|
-
mutations: {
|
|
97
|
+
mutations: OptionalAndNullable<{
|
|
91
98
|
create: OptionalAndNullable<string>;
|
|
92
99
|
update: OptionalAndNullable<string>;
|
|
93
100
|
delete: OptionalAndNullable<string>;
|
|
94
|
-
}
|
|
95
|
-
subscriptions: {
|
|
101
|
+
}>;
|
|
102
|
+
subscriptions: OptionalAndNullable<{
|
|
96
103
|
onCreate: OptionalAndNullable<string>[];
|
|
97
104
|
onUpdate: OptionalAndNullable<string>[];
|
|
98
105
|
onDelete: OptionalAndNullable<string>[];
|
|
99
|
-
level:
|
|
100
|
-
}
|
|
106
|
+
level: SubscriptionLevel;
|
|
107
|
+
}>;
|
|
101
108
|
timestamps: OptionalAndNullable<{
|
|
102
109
|
createdAt: OptionalAndNullable<string>;
|
|
103
110
|
updatedAt: OptionalAndNullable<string>;
|
|
@@ -168,10 +175,13 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
168
175
|
`'${definition.name.value}' is a reserved type name and currently in use within the default schema element.`,
|
|
169
176
|
);
|
|
170
177
|
}
|
|
171
|
-
|
|
172
178
|
// todo: get model configuration with default values and store it in the map
|
|
173
179
|
const typeName = definition.name.value;
|
|
174
|
-
|
|
180
|
+
|
|
181
|
+
if (ctx.isProjectUsingDataStore()) {
|
|
182
|
+
SyncUtils.validateResolverConfigForType(ctx, typeName);
|
|
183
|
+
}
|
|
184
|
+
|
|
175
185
|
const directiveWrapped: DirectiveWrapper = new DirectiveWrapper(directive);
|
|
176
186
|
const options = directiveWrapped.getArguments({
|
|
177
187
|
queries: {
|
|
@@ -185,10 +195,10 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
185
195
|
delete: toCamelCase(['delete', typeName]),
|
|
186
196
|
},
|
|
187
197
|
subscriptions: {
|
|
188
|
-
level: SubscriptionLevel.
|
|
189
|
-
onCreate: [toCamelCase(['onCreate', typeName])],
|
|
190
|
-
onDelete: [toCamelCase(['onDelete', typeName])],
|
|
191
|
-
onUpdate: [toCamelCase(['onUpdate', typeName])],
|
|
198
|
+
level: SubscriptionLevel.on,
|
|
199
|
+
onCreate: [this.ensureValidSubscriptionName(toCamelCase(['onCreate', typeName]))],
|
|
200
|
+
onDelete: [this.ensureValidSubscriptionName(toCamelCase(['onDelete', typeName]))],
|
|
201
|
+
onUpdate: [this.ensureValidSubscriptionName(toCamelCase(['onUpdate', typeName]))],
|
|
192
202
|
},
|
|
193
203
|
timestamps: {
|
|
194
204
|
createdAt: 'createdAt',
|
|
@@ -238,8 +248,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
238
248
|
|
|
239
249
|
generateResolvers = (context: TransformerContextProvider): void => {
|
|
240
250
|
for (let type of this.typesWithModelDirective) {
|
|
241
|
-
const def = context.output.getObject(type)
|
|
242
|
-
|
|
251
|
+
const def = context.output.getObject(type)!;
|
|
243
252
|
// This name is used by the mock functionality. Changing this can break mock.
|
|
244
253
|
const tableLogicalName = `${def!.name.value}Table`;
|
|
245
254
|
const stack = context.stackManager.getStackFor(tableLogicalName, def!.name.value);
|
|
@@ -262,7 +271,13 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
262
271
|
default:
|
|
263
272
|
throw new Error('Unknown query field type');
|
|
264
273
|
}
|
|
265
|
-
|
|
274
|
+
resolver.addToSlot(
|
|
275
|
+
'postAuth',
|
|
276
|
+
MappingTemplate.s3MappingTemplateFromString(
|
|
277
|
+
generateAuthExpressionForSandboxMode(context),
|
|
278
|
+
`${query.typeName}.${query.fieldName}.{slotName}.{slotIndex}.req.vtl`,
|
|
279
|
+
),
|
|
280
|
+
);
|
|
266
281
|
resolver.mapToStack(stack);
|
|
267
282
|
context.resolvers.addResolver(query.typeName, query.fieldName, resolver);
|
|
268
283
|
}
|
|
@@ -281,11 +296,49 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
281
296
|
resolver = this.generateUpdateResolver(context, def!, mutation.typeName, mutation.fieldName);
|
|
282
297
|
break;
|
|
283
298
|
default:
|
|
284
|
-
throw new Error('Unknown
|
|
299
|
+
throw new Error('Unknown mutation field type');
|
|
285
300
|
}
|
|
301
|
+
resolver.addToSlot(
|
|
302
|
+
'postAuth',
|
|
303
|
+
MappingTemplate.s3MappingTemplateFromString(
|
|
304
|
+
generateAuthExpressionForSandboxMode(context),
|
|
305
|
+
`${mutation.typeName}.${mutation.fieldName}.{slotName}.{slotIndex}.req.vtl`,
|
|
306
|
+
),
|
|
307
|
+
);
|
|
286
308
|
resolver.mapToStack(stack);
|
|
287
309
|
context.resolvers.addResolver(mutation.typeName, mutation.fieldName, resolver);
|
|
288
310
|
}
|
|
311
|
+
|
|
312
|
+
const subscriptionLevel = this.modelDirectiveConfig.get(def.name.value)?.subscriptions?.level;
|
|
313
|
+
// in order to create subscription resolvers the level needs to be on
|
|
314
|
+
if (subscriptionLevel === SubscriptionLevel.on) {
|
|
315
|
+
const subscriptionFields = this.getSubscriptionFieldNames(context, def!);
|
|
316
|
+
for (let subscription of subscriptionFields.values()) {
|
|
317
|
+
let resolver;
|
|
318
|
+
switch (subscription.type) {
|
|
319
|
+
case SubscriptionFieldType.ON_CREATE:
|
|
320
|
+
resolver = this.generateOnCreateResolver(context, def, subscription.typeName, subscription.fieldName);
|
|
321
|
+
break;
|
|
322
|
+
case SubscriptionFieldType.ON_UPDATE:
|
|
323
|
+
resolver = this.generateOnUpdateResolver(context, def, subscription.typeName, subscription.fieldName);
|
|
324
|
+
break;
|
|
325
|
+
case SubscriptionFieldType.ON_DELETE:
|
|
326
|
+
resolver = this.generateOnDeleteResolver(context, def, subscription.typeName, subscription.fieldName);
|
|
327
|
+
break;
|
|
328
|
+
default:
|
|
329
|
+
throw new Error('Unknown subscription field type');
|
|
330
|
+
}
|
|
331
|
+
resolver.addToSlot(
|
|
332
|
+
'postAuth',
|
|
333
|
+
MappingTemplate.s3MappingTemplateFromString(
|
|
334
|
+
generateAuthExpressionForSandboxMode(context),
|
|
335
|
+
`${subscription.typeName}.${subscription.fieldName}.{slotName}.{slotIndex}.req.vtl`,
|
|
336
|
+
),
|
|
337
|
+
);
|
|
338
|
+
resolver.mapToStack(stack);
|
|
339
|
+
context.resolvers.addResolver(subscription.typeName, subscription.fieldName, resolver);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
289
342
|
}
|
|
290
343
|
};
|
|
291
344
|
|
|
@@ -304,10 +357,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
304
357
|
fieldName,
|
|
305
358
|
dataSource,
|
|
306
359
|
MappingTemplate.s3MappingTemplateFromString(generateGetRequestTemplate(), `${typeName}.${fieldName}.req.vtl`),
|
|
307
|
-
MappingTemplate.s3MappingTemplateFromString(
|
|
308
|
-
generateDefaultResponseMappingTemplate(isSyncEnabled),
|
|
309
|
-
`${typeName}.${fieldName}.res.vtl`,
|
|
310
|
-
),
|
|
360
|
+
MappingTemplate.s3MappingTemplateFromString(generateGetResponseTemplate(isSyncEnabled), `${typeName}.${fieldName}.res.vtl`),
|
|
311
361
|
);
|
|
312
362
|
}
|
|
313
363
|
return this.resolverMap[resolverKey];
|
|
@@ -356,7 +406,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
356
406
|
`${typeName}.${fieldName}.req.vtl`,
|
|
357
407
|
),
|
|
358
408
|
MappingTemplate.s3MappingTemplateFromString(
|
|
359
|
-
generateDefaultResponseMappingTemplate(isSyncEnabled),
|
|
409
|
+
generateDefaultResponseMappingTemplate(isSyncEnabled, true),
|
|
360
410
|
`${typeName}.${fieldName}.res.vtl`,
|
|
361
411
|
),
|
|
362
412
|
);
|
|
@@ -388,7 +438,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
388
438
|
dataSource,
|
|
389
439
|
MappingTemplate.s3MappingTemplateFromString(generateDeleteRequestTemplate(isSyncEnabled), `${typeName}.${fieldName}.req.vtl`),
|
|
390
440
|
MappingTemplate.s3MappingTemplateFromString(
|
|
391
|
-
generateDefaultResponseMappingTemplate(isSyncEnabled),
|
|
441
|
+
generateDefaultResponseMappingTemplate(isSyncEnabled, true),
|
|
392
442
|
`${typeName}.${fieldName}.res.vtl`,
|
|
393
443
|
),
|
|
394
444
|
);
|
|
@@ -698,7 +748,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
698
748
|
dataSource,
|
|
699
749
|
MappingTemplate.s3MappingTemplateFromString(generateCreateRequestTemplate(type.name.value), `${typeName}.${fieldName}.req.vtl`),
|
|
700
750
|
MappingTemplate.s3MappingTemplateFromString(
|
|
701
|
-
generateDefaultResponseMappingTemplate(isSyncEnabled),
|
|
751
|
+
generateDefaultResponseMappingTemplate(isSyncEnabled, true),
|
|
702
752
|
`${typeName}.${fieldName}.res.vtl`,
|
|
703
753
|
),
|
|
704
754
|
);
|
|
@@ -1106,7 +1156,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
1106
1156
|
}
|
|
1107
1157
|
|
|
1108
1158
|
private createIAMRole(context: TransformerContextProvider, def: ObjectTypeDefinitionNode, stack: cdk.Stack, tableName: string) {
|
|
1109
|
-
const roleName = context.resourceHelper.
|
|
1159
|
+
const roleName = context.resourceHelper.generateIAMRoleName(ModelResourceIDs.ModelTableIAMRoleID(def!.name.value));
|
|
1110
1160
|
const role = new iam.Role(stack, ModelResourceIDs.ModelTableIAMRoleID(def!.name.value), {
|
|
1111
1161
|
roleName: roleName,
|
|
1112
1162
|
assumedBy: new iam.ServicePrincipal('appsync.amazonaws.com'),
|
|
@@ -1161,7 +1211,6 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
1161
1211
|
SyncUtils.createSyncLambdaIAMPolicy(stack, syncConfig.LambdaConflictHandler.name, syncConfig.LambdaConflictHandler.region),
|
|
1162
1212
|
);
|
|
1163
1213
|
}
|
|
1164
|
-
|
|
1165
1214
|
return role;
|
|
1166
1215
|
}
|
|
1167
1216
|
|
|
@@ -1179,4 +1228,10 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
|
|
|
1179
1228
|
...options,
|
|
1180
1229
|
};
|
|
1181
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
|
+
};
|
|
1182
1237
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export { ModelTransformer } from './graphql-model-transformer';
|
|
1
|
+
export { ModelTransformer, ModelDirectiveConfiguration, SubscriptionLevel } from './graphql-model-transformer';
|
|
2
|
+
export { OPERATION_KEY } from './definitions';
|
|
2
3
|
export * from './graphql-types';
|
|
3
4
|
export * from './resolvers';
|
package/src/resolvers/common.ts
CHANGED
|
@@ -15,7 +15,13 @@ import {
|
|
|
15
15
|
ifElse,
|
|
16
16
|
printBlock,
|
|
17
17
|
toJson,
|
|
18
|
+
qref,
|
|
19
|
+
str,
|
|
20
|
+
not,
|
|
18
21
|
} from 'graphql-mapping-template';
|
|
22
|
+
import { OPERATION_KEY } from '../definitions';
|
|
23
|
+
|
|
24
|
+
const API_KEY = 'API Key Authorization';
|
|
19
25
|
|
|
20
26
|
/**
|
|
21
27
|
* Helper method to generate code that converts DynamoDB condition object to condition
|
|
@@ -57,9 +63,11 @@ export const generateConditionSlot = (inputConditionObjectName: string, conditio
|
|
|
57
63
|
|
|
58
64
|
/**
|
|
59
65
|
* Generate common response template used by most of the resolvers.
|
|
66
|
+
* Append operation if response is coming from a mutation, this is to protect field resolver for subscriptions
|
|
60
67
|
*/
|
|
61
|
-
export const generateDefaultResponseMappingTemplate = (isSyncEnabled: boolean): string => {
|
|
68
|
+
export const generateDefaultResponseMappingTemplate = (isSyncEnabled: boolean, mutation = false): string => {
|
|
62
69
|
const statements: Expression[] = [];
|
|
70
|
+
if (mutation) statements.push(qref(methodCall(ref('ctx.result.put'), str(OPERATION_KEY), str('Mutation'))));
|
|
63
71
|
if (isSyncEnabled) {
|
|
64
72
|
statements.push(
|
|
65
73
|
ifElse(
|
|
@@ -74,14 +82,30 @@ export const generateDefaultResponseMappingTemplate = (isSyncEnabled: boolean):
|
|
|
74
82
|
);
|
|
75
83
|
}
|
|
76
84
|
|
|
77
|
-
return printBlock('
|
|
85
|
+
return printBlock('ResponseTemplate')(compoundExpression(statements));
|
|
78
86
|
};
|
|
79
87
|
|
|
80
88
|
/**
|
|
81
|
-
* Util function to
|
|
89
|
+
* Util function to generate resolver key used to keep track of all the resolvers in memory
|
|
82
90
|
* @param typeName Name of the type
|
|
83
91
|
* @param fieldName Name of the field
|
|
84
92
|
*/
|
|
85
93
|
export const generateResolverKey = (typeName: string, fieldName: string): string => {
|
|
86
94
|
return `${typeName}.${fieldName}`;
|
|
87
95
|
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Util function to generate sandbox mode expression
|
|
99
|
+
* @param ctx context to get sandbox mode
|
|
100
|
+
*/
|
|
101
|
+
export const generateAuthExpressionForSandboxMode = (ctx: any): string => {
|
|
102
|
+
const enabled = ctx.resourceHelper.api.sandboxModeEnabled;
|
|
103
|
+
let exp;
|
|
104
|
+
|
|
105
|
+
if (enabled) exp = iff(notEquals(methodCall(ref('util.authType')), str(API_KEY)), methodCall(ref('util.unauthorized')));
|
|
106
|
+
else exp = methodCall(ref('util.unauthorized'));
|
|
107
|
+
|
|
108
|
+
return printBlock(`Sandbox Mode ${enabled ? 'Enabled' : 'Disabled'}`)(
|
|
109
|
+
compoundExpression([iff(not(ref('ctx.stash.get("hasAuth")')), exp), toJson(obj({}))]),
|
|
110
|
+
);
|
|
111
|
+
};
|
|
@@ -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
|
@@ -16,27 +16,86 @@ import {
|
|
|
16
16
|
equals,
|
|
17
17
|
bool,
|
|
18
18
|
and,
|
|
19
|
+
isNullOrEmpty,
|
|
20
|
+
list,
|
|
21
|
+
forEach,
|
|
19
22
|
nul,
|
|
20
23
|
} from 'graphql-mapping-template';
|
|
21
24
|
import { ResourceConstants } from 'graphql-transformer-common';
|
|
25
|
+
const authFilter = ref('ctx.stash.authFilter');
|
|
26
|
+
|
|
22
27
|
/**
|
|
23
28
|
* Generate get query resolver template
|
|
24
29
|
*/
|
|
25
30
|
export const generateGetRequestTemplate = (): string => {
|
|
26
31
|
const statements: Expression[] = [
|
|
27
|
-
set(ref('GetRequest'), obj({ version: str('2018-05-29'), operation: str('
|
|
32
|
+
set(ref('GetRequest'), obj({ version: str('2018-05-29'), operation: str('Query') })),
|
|
28
33
|
ifElse(
|
|
29
34
|
ref('ctx.stash.metadata.modelObjectKey'),
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
compoundExpression([
|
|
36
|
+
set(ref('expression'), str('')),
|
|
37
|
+
set(ref('expressionNames'), obj({})),
|
|
38
|
+
set(ref('expressionValues'), obj({})),
|
|
39
|
+
forEach(ref('item'), ref('ctx.stash.metadata.modelObjectKey.entrySet()'), [
|
|
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'))),
|
|
43
|
+
]),
|
|
44
|
+
set(ref('expression'), methodCall(ref('expression.replaceAll'), str('AND $'), str(''))),
|
|
45
|
+
set(
|
|
46
|
+
ref('query'),
|
|
47
|
+
obj({ expression: ref('expression'), expressionNames: ref('expressionNames'), expressionValues: ref('expressionValues') }),
|
|
48
|
+
),
|
|
49
|
+
]),
|
|
50
|
+
set(
|
|
51
|
+
ref('query'),
|
|
52
|
+
obj({
|
|
53
|
+
expression: str('id = :id'),
|
|
54
|
+
expressionValues: obj({
|
|
55
|
+
':id': methodCall(ref('util.parseJson'), methodCall(ref('util.dynamodb.toDynamoDBJson'), ref('ctx.args.id'))),
|
|
56
|
+
}),
|
|
57
|
+
}),
|
|
58
|
+
),
|
|
59
|
+
),
|
|
60
|
+
qref(methodCall(ref('GetRequest.put'), str('query'), ref('query'))),
|
|
61
|
+
iff(
|
|
62
|
+
not(isNullOrEmpty(authFilter)),
|
|
63
|
+
qref(
|
|
64
|
+
methodCall(
|
|
65
|
+
ref('GetRequest.put'),
|
|
66
|
+
str('filter'),
|
|
67
|
+
methodCall(ref('util.parseJson'), methodCall(ref('util.transform.toDynamoDBFilterExpression'), authFilter)),
|
|
68
|
+
),
|
|
69
|
+
),
|
|
32
70
|
),
|
|
33
|
-
qref(methodCall(ref('GetRequest.put'), str('key'), ref('key'))),
|
|
34
71
|
toJson(ref('GetRequest')),
|
|
35
72
|
];
|
|
36
73
|
|
|
37
74
|
return printBlock('Get Request template')(compoundExpression(statements));
|
|
38
75
|
};
|
|
39
76
|
|
|
77
|
+
export const generateGetResponseTemplate = (isSyncEnabled: boolean): string => {
|
|
78
|
+
const statements = new Array<Expression>();
|
|
79
|
+
if (isSyncEnabled) {
|
|
80
|
+
statements.push(
|
|
81
|
+
iff(ref('ctx.error'), methodCall(ref('util.error'), ref('ctx.error.message'), ref('ctx.error.type'), ref('ctx.result'))),
|
|
82
|
+
);
|
|
83
|
+
} else {
|
|
84
|
+
statements.push(iff(ref('ctx.error'), methodCall(ref('util.error'), ref('ctx.error.message'), ref('ctx.error.type'))));
|
|
85
|
+
}
|
|
86
|
+
statements.push(
|
|
87
|
+
ifElse(
|
|
88
|
+
and([not(ref('ctx.result.items.isEmpty()')), equals(ref('ctx.result.scannedCount'), int(1))]),
|
|
89
|
+
toJson(ref('ctx.result.items[0]')),
|
|
90
|
+
compoundExpression([
|
|
91
|
+
iff(and([ref('ctx.result.items.isEmpty()'), equals(ref('ctx.result.scannedCount'), int(1))]), ref('util.unauthorized()')),
|
|
92
|
+
toJson(nul()),
|
|
93
|
+
]),
|
|
94
|
+
),
|
|
95
|
+
);
|
|
96
|
+
return printBlock('Get Response template')(compoundExpression(statements));
|
|
97
|
+
};
|
|
98
|
+
|
|
40
99
|
export const generateListRequestTemplate = (): string => {
|
|
41
100
|
const requestVariable = 'ListRequest';
|
|
42
101
|
const modelQueryObj = 'ctx.stash.modelQueryExpression';
|
|
@@ -51,12 +110,20 @@ export const generateListRequestTemplate = (): string => {
|
|
|
51
110
|
}),
|
|
52
111
|
),
|
|
53
112
|
iff(ref('context.args.nextToken'), set(ref(`${requestVariable}.nextToken`), ref('context.args.nextToken'))),
|
|
113
|
+
ifElse(
|
|
114
|
+
not(isNullOrEmpty(authFilter)),
|
|
115
|
+
compoundExpression([
|
|
116
|
+
set(ref('filter'), authFilter),
|
|
117
|
+
iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), obj({ and: list([ref('filter'), ref('ctx.args.filter')]) }))),
|
|
118
|
+
]),
|
|
119
|
+
iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), ref('ctx.args.filter'))),
|
|
120
|
+
),
|
|
54
121
|
iff(
|
|
55
|
-
ref('
|
|
122
|
+
not(isNullOrEmpty(ref('filter'))),
|
|
56
123
|
compoundExpression([
|
|
57
124
|
set(
|
|
58
125
|
ref(`filterExpression`),
|
|
59
|
-
methodCall(ref('util.parseJson'), methodCall(ref('util.transform.toDynamoDBFilterExpression'), ref('
|
|
126
|
+
methodCall(ref('util.parseJson'), methodCall(ref('util.transform.toDynamoDBFilterExpression'), ref('filter'))),
|
|
60
127
|
),
|
|
61
128
|
iff(
|
|
62
129
|
not(methodCall(ref('util.isNullOrBlank'), ref('filterExpression.expression'))),
|
|
@@ -95,10 +162,37 @@ export const generateListRequestTemplate = (): string => {
|
|
|
95
162
|
export const generateSyncRequestTemplate = (): string => {
|
|
96
163
|
return printBlock('Sync Request template')(
|
|
97
164
|
compoundExpression([
|
|
165
|
+
ifElse(
|
|
166
|
+
not(isNullOrEmpty(authFilter)),
|
|
167
|
+
compoundExpression([
|
|
168
|
+
set(ref('filter'), authFilter),
|
|
169
|
+
iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), obj({ and: list([ref('filter'), ref('ctx.args.filter')]) }))),
|
|
170
|
+
]),
|
|
171
|
+
iff(not(isNullOrEmpty(ref('ctx.args.filter'))), set(ref('filter'), ref('ctx.args.filter'))),
|
|
172
|
+
),
|
|
173
|
+
iff(
|
|
174
|
+
not(isNullOrEmpty(ref('filter'))),
|
|
175
|
+
compoundExpression([
|
|
176
|
+
set(
|
|
177
|
+
ref(`filterExpression`),
|
|
178
|
+
methodCall(ref('util.parseJson'), methodCall(ref('util.transform.toDynamoDBFilterExpression'), ref('filter'))),
|
|
179
|
+
),
|
|
180
|
+
iff(
|
|
181
|
+
not(methodCall(ref('util.isNullOrBlank'), ref('filterExpression.expression'))),
|
|
182
|
+
compoundExpression([
|
|
183
|
+
iff(
|
|
184
|
+
equals(methodCall(ref('filterEpression.expressionValues.size')), int(0)),
|
|
185
|
+
qref(methodCall(ref('filterEpression.remove'), str('expressionValues'))),
|
|
186
|
+
),
|
|
187
|
+
set(ref('filter'), ref('filterExpression')),
|
|
188
|
+
]),
|
|
189
|
+
),
|
|
190
|
+
]),
|
|
191
|
+
),
|
|
98
192
|
obj({
|
|
99
193
|
version: str('2018-05-29'),
|
|
100
194
|
operation: str('Sync'),
|
|
101
|
-
filter: ifElse(ref('
|
|
195
|
+
filter: ifElse(ref('filter'), ref('util.toJson($filter)'), nul()),
|
|
102
196
|
limit: ref(`util.defaultIfNull($ctx.args.limit, ${ResourceConstants.DEFAULT_SYNC_QUERY_PAGE_LIMIT})`),
|
|
103
197
|
lastSync: ref('util.toJson($util.defaultIfNull($ctx.args.lastSync, null))'),
|
|
104
198
|
nextToken: ref('util.toJson($util.defaultIfNull($ctx.args.nextToken, null))'),
|