@aws-amplify/graphql-model-transformer 0.7.0-auth-dir-v-next.3 → 0.7.0-ext12.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +19 -19
  2. package/lib/graphql-model-transformer.d.ts +14 -9
  3. package/lib/graphql-model-transformer.d.ts.map +1 -1
  4. package/lib/graphql-model-transformer.js +71 -41
  5. package/lib/graphql-model-transformer.js.map +1 -1
  6. package/lib/graphql-types/mutation.d.ts.map +1 -1
  7. package/lib/graphql-types/mutation.js +2 -5
  8. package/lib/graphql-types/mutation.js.map +1 -1
  9. package/lib/graphql-types/query.js +1 -1
  10. package/lib/graphql-types/query.js.map +1 -1
  11. package/lib/resolvers/common.js +2 -2
  12. package/lib/resolvers/common.js.map +1 -1
  13. package/lib/resolvers/mutation.d.ts.map +1 -1
  14. package/lib/resolvers/mutation.js +0 -1
  15. package/lib/resolvers/mutation.js.map +1 -1
  16. package/lib/resolvers/query.d.ts.map +1 -1
  17. package/lib/resolvers/query.js +7 -5
  18. package/lib/resolvers/query.js.map +1 -1
  19. package/lib/resolvers/subscriptions.js +1 -1
  20. package/lib/resolvers/subscriptions.js.map +1 -1
  21. package/lib/wrappers/object-definition-wrapper.d.ts +2 -15
  22. package/lib/wrappers/object-definition-wrapper.d.ts.map +1 -1
  23. package/lib/wrappers/object-definition-wrapper.js +7 -43
  24. package/lib/wrappers/object-definition-wrapper.js.map +1 -1
  25. package/package.json +34 -32
  26. package/src/__tests__/__snapshots__/model-transformer.test.ts.snap +515 -796
  27. package/src/__tests__/model-transformer.test.ts +92 -6
  28. package/src/graphql-model-transformer.ts +106 -37
  29. package/src/graphql-types/mutation.ts +2 -4
  30. package/src/graphql-types/query.ts +1 -1
  31. package/src/resolvers/common.ts +2 -2
  32. package/src/resolvers/mutation.ts +0 -3
  33. package/src/resolvers/query.ts +10 -11
  34. package/src/resolvers/subscriptions.ts +1 -1
  35. package/src/wrappers/object-definition-wrapper.ts +2 -52
  36. 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.Lambda', () => {
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,109 @@ describe('ModelTransformer: ', () => {
983
984
  validateModelSchema(parse(definition));
984
985
  });
985
986
 
986
- it('should support sandbox mode of api', async () => {
987
+ it('should generate iam role names under 64 chars and subscriptions under 50', () => {
987
988
  const validSchema = `
988
- type AMPLIFY_GLOBAL @allow_public_data_access_with_api_key(in: "staging")
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
+ },
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
+ });
1059
+
1060
+ it('should generate the ID field when not specified', () => {
1061
+ const validSchema = `type Todo @model {
1062
+ name: String
1063
+ }`;
1064
+
1065
+ const transformer = new GraphQLTransform({
1066
+ transformers: [new ModelTransformer()],
999
1067
  });
1000
1068
 
1001
1069
  const out = transformer.transform(validSchema);
1002
1070
  expect(out).toBeDefined();
1003
1071
 
1004
- parse(out.schema);
1072
+ const definition = out.schema;
1073
+ expect(definition).toBeDefined();
1074
+
1075
+ const parsed = parse(definition);
1076
+ validateModelSchema(parsed);
1077
+
1078
+ const createTodoInput = getInputType(parsed, 'CreateTodoInput');
1079
+ expect(createTodoInput).toBeDefined();
1080
+
1081
+ expectFieldsOnInputType(createTodoInput!, ['id', 'name']);
1082
+
1083
+ const idField = createTodoInput!.fields!.find(f => f.name.value === 'id');
1084
+ expect((idField!.type as NamedTypeNode).name!.value).toEqual('ID');
1085
+ expect((idField!.type as NamedTypeNode).kind).toEqual('NamedType');
1086
+
1087
+ const updateTodoInput = getInputType(parsed, 'UpdateTodoInput');
1088
+ expect(updateTodoInput).toBeDefined();
1089
+
1090
+ expectFieldsOnInputType(updateTodoInput!, ['name']);
1005
1091
  });
1006
1092
  });
@@ -1,4 +1,11 @@
1
- import { InvalidDirectiveError, MappingTemplate, SyncConfig, SyncUtils, TransformerModelBase } from '@aws-amplify/graphql-transformer-core';
1
+ import {
2
+ DirectiveWrapper,
3
+ InvalidDirectiveError,
4
+ MappingTemplate,
5
+ SyncConfig,
6
+ SyncUtils,
7
+ TransformerModelBase,
8
+ } from '@aws-amplify/graphql-transformer-core';
2
9
  import {
3
10
  AppSyncDataSourceType,
4
11
  DataSourceInstance,
@@ -37,6 +44,7 @@ import {
37
44
  makeValueNode,
38
45
  ModelResourceIDs,
39
46
  plurality,
47
+ ResolverResourceIDs,
40
48
  ResourceConstants,
41
49
  SyncResourceIDs,
42
50
  toCamelCase,
@@ -71,13 +79,9 @@ import {
71
79
  generateListRequestTemplate,
72
80
  generateSyncRequestTemplate,
73
81
  } from './resolvers/query';
74
- import {
75
- DirectiveWrapper,
76
- FieldWrapper,
77
- InputObjectDefinitionWrapper,
78
- ObjectDefinitionWrapper,
79
- } from './wrappers/object-definition-wrapper';
82
+ import { FieldWrapper, InputObjectDefinitionWrapper, ObjectDefinitionWrapper } from './wrappers/object-definition-wrapper';
80
83
  import { CfnRole } from '@aws-cdk/aws-iam';
84
+ import md5 from 'md5';
81
85
 
82
86
  export type Nullable<T> = T | null;
83
87
  export type OptionalAndNullable<T> = Partial<T>;
@@ -176,14 +180,17 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
176
180
  }
177
181
  // todo: get model configuration with default values and store it in the map
178
182
  const typeName = definition.name.value;
183
+
184
+ if (ctx.isProjectUsingDataStore()) {
185
+ SyncUtils.validateResolverConfigForType(ctx, typeName);
186
+ }
187
+
179
188
  const directiveWrapped: DirectiveWrapper = new DirectiveWrapper(directive);
180
189
  const options = directiveWrapped.getArguments({
181
190
  queries: {
182
191
  get: toCamelCase(['get', typeName]),
183
192
  list: toCamelCase(['list', plurality(typeName, true)]),
184
- ...((ctx as TransformerContextProvider).isProjectUsingDataStore()
185
- ? { sync: toCamelCase(['sync', plurality(typeName, true)]) }
186
- : undefined),
193
+ ...(ctx.isProjectUsingDataStore() ? { sync: toCamelCase(['sync', plurality(typeName, true)]) } : undefined),
187
194
  },
188
195
  mutations: {
189
196
  create: toCamelCase(['create', typeName]),
@@ -192,9 +199,9 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
192
199
  },
193
200
  subscriptions: {
194
201
  level: SubscriptionLevel.on,
195
- onCreate: [toCamelCase(['onCreate', typeName])],
196
- onDelete: [toCamelCase(['onDelete', typeName])],
197
- onUpdate: [toCamelCase(['onUpdate', typeName])],
202
+ onCreate: [this.ensureValidSubscriptionName(toCamelCase(['onCreate', typeName]))],
203
+ onDelete: [this.ensureValidSubscriptionName(toCamelCase(['onDelete', typeName]))],
204
+ onUpdate: [this.ensureValidSubscriptionName(toCamelCase(['onUpdate', typeName]))],
198
205
  },
199
206
  timestamps: {
200
207
  createdAt: 'createdAt',
@@ -237,7 +244,6 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
237
244
  this.addAutoGeneratableFields(ctx, type);
238
245
 
239
246
  if (ctx.isProjectUsingDataStore()) {
240
- this.options.SyncConfig = SyncUtils.getSyncConfig(ctx as TransformerContextProvider, def!.name.value);
241
247
  this.addModelSyncFields(ctx, type);
242
248
  }
243
249
  }
@@ -257,13 +263,13 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
257
263
  let resolver;
258
264
  switch (query.type) {
259
265
  case QueryFieldType.GET:
260
- resolver = this.generateGetResolver(context, def!, query.typeName, query.fieldName);
266
+ resolver = this.generateGetResolver(context, def!, query.typeName, query.fieldName, query.resolverLogicalId);
261
267
  break;
262
268
  case QueryFieldType.LIST:
263
- resolver = this.generateListResolver(context, def!, query.typeName, query.fieldName);
269
+ resolver = this.generateListResolver(context, def!, query.typeName, query.fieldName, query.resolverLogicalId);
264
270
  break;
265
271
  case QueryFieldType.SYNC:
266
- resolver = this.generateSyncResolver(context, def!, query.typeName, query.fieldName);
272
+ resolver = this.generateSyncResolver(context, def!, query.typeName, query.fieldName, query.resolverLogicalId);
267
273
  break;
268
274
  default:
269
275
  throw new Error('Unknown query field type');
@@ -284,13 +290,13 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
284
290
  let resolver;
285
291
  switch (mutation.type) {
286
292
  case MutationFieldType.CREATE:
287
- resolver = this.generateCreateResolver(context, def!, mutation.typeName, mutation.fieldName);
293
+ resolver = this.generateCreateResolver(context, def!, mutation.typeName, mutation.fieldName, mutation.resolverLogicalId);
288
294
  break;
289
295
  case MutationFieldType.DELETE:
290
- resolver = this.generateDeleteResolver(context, def!, mutation.typeName, mutation.fieldName);
296
+ resolver = this.generateDeleteResolver(context, def!, mutation.typeName, mutation.fieldName, mutation.resolverLogicalId);
291
297
  break;
292
298
  case MutationFieldType.UPDATE:
293
- resolver = this.generateUpdateResolver(context, def!, mutation.typeName, mutation.fieldName);
299
+ resolver = this.generateUpdateResolver(context, def!, mutation.typeName, mutation.fieldName, mutation.resolverLogicalId);
294
300
  break;
295
301
  default:
296
302
  throw new Error('Unknown mutation field type');
@@ -314,13 +320,31 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
314
320
  let resolver;
315
321
  switch (subscription.type) {
316
322
  case SubscriptionFieldType.ON_CREATE:
317
- resolver = this.generateOnCreateResolver(context, def, subscription.typeName, subscription.fieldName);
323
+ resolver = this.generateOnCreateResolver(
324
+ context,
325
+ def,
326
+ subscription.typeName,
327
+ subscription.fieldName,
328
+ subscription.resolverLogicalId,
329
+ );
318
330
  break;
319
331
  case SubscriptionFieldType.ON_UPDATE:
320
- resolver = this.generateOnUpdateResolver(context, def, subscription.typeName, subscription.fieldName);
332
+ resolver = this.generateOnUpdateResolver(
333
+ context,
334
+ def,
335
+ subscription.typeName,
336
+ subscription.fieldName,
337
+ subscription.resolverLogicalId,
338
+ );
321
339
  break;
322
340
  case SubscriptionFieldType.ON_DELETE:
323
- resolver = this.generateOnDeleteResolver(context, def, subscription.typeName, subscription.fieldName);
341
+ resolver = this.generateOnDeleteResolver(
342
+ context,
343
+ def,
344
+ subscription.typeName,
345
+ subscription.fieldName,
346
+ subscription.resolverLogicalId,
347
+ );
324
348
  break;
325
349
  default:
326
350
  throw new Error('Unknown subscription field type');
@@ -344,6 +368,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
344
368
  type: ObjectTypeDefinitionNode,
345
369
  typeName: string,
346
370
  fieldName: string,
371
+ resolverLogicalId: string,
347
372
  ): TransformerResolverProvider => {
348
373
  const isSyncEnabled = ctx.isProjectUsingDataStore();
349
374
  const dataSource = this.datasourceMap[type.name.value];
@@ -352,6 +377,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
352
377
  this.resolverMap[resolverKey] = ctx.resolvers.generateQueryResolver(
353
378
  typeName,
354
379
  fieldName,
380
+ resolverLogicalId,
355
381
  dataSource,
356
382
  MappingTemplate.s3MappingTemplateFromString(generateGetRequestTemplate(), `${typeName}.${fieldName}.req.vtl`),
357
383
  MappingTemplate.s3MappingTemplateFromString(generateGetResponseTemplate(isSyncEnabled), `${typeName}.${fieldName}.res.vtl`),
@@ -365,6 +391,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
365
391
  type: ObjectTypeDefinitionNode,
366
392
  typeName: string,
367
393
  fieldName: string,
394
+ resolverLogicalId: string,
368
395
  ): TransformerResolverProvider => {
369
396
  const isSyncEnabled = ctx.isProjectUsingDataStore();
370
397
  const dataSource = this.datasourceMap[type.name.value];
@@ -373,6 +400,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
373
400
  this.resolverMap[resolverKey] = ctx.resolvers.generateQueryResolver(
374
401
  typeName,
375
402
  fieldName,
403
+ resolverLogicalId,
376
404
  dataSource,
377
405
  MappingTemplate.s3MappingTemplateFromString(generateListRequestTemplate(), `${typeName}.${fieldName}.req.vtl`),
378
406
  MappingTemplate.s3MappingTemplateFromString(
@@ -389,6 +417,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
389
417
  type: ObjectTypeDefinitionNode,
390
418
  typeName: string,
391
419
  fieldName: string,
420
+ resolverLogicalId: string,
392
421
  ): TransformerResolverProvider => {
393
422
  const isSyncEnabled = ctx.isProjectUsingDataStore();
394
423
  const dataSource = this.datasourceMap[type.name.value];
@@ -397,6 +426,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
397
426
  const resolver = ctx.resolvers.generateMutationResolver(
398
427
  typeName,
399
428
  fieldName,
429
+ resolverLogicalId,
400
430
  dataSource,
401
431
  MappingTemplate.s3MappingTemplateFromString(
402
432
  generateUpdateRequestTemplate(typeName, isSyncEnabled),
@@ -424,6 +454,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
424
454
  type: ObjectTypeDefinitionNode,
425
455
  typeName: string,
426
456
  fieldName: string,
457
+ resolverLogicalId: string,
427
458
  ): TransformerResolverProvider => {
428
459
  const isSyncEnabled = ctx.isProjectUsingDataStore();
429
460
  const dataSource = this.datasourceMap[type.name.value];
@@ -432,6 +463,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
432
463
  this.resolverMap[resolverKey] = ctx.resolvers.generateMutationResolver(
433
464
  typeName,
434
465
  fieldName,
466
+ resolverLogicalId,
435
467
  dataSource,
436
468
  MappingTemplate.s3MappingTemplateFromString(generateDeleteRequestTemplate(isSyncEnabled), `${typeName}.${fieldName}.req.vtl`),
437
469
  MappingTemplate.s3MappingTemplateFromString(
@@ -448,12 +480,14 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
448
480
  type: ObjectTypeDefinitionNode,
449
481
  typeName: string,
450
482
  fieldName: string,
483
+ resolverLogicalId: string,
451
484
  ): TransformerResolverProvider => {
452
485
  const resolverKey = `OnCreate${generateResolverKey(typeName, fieldName)}`;
453
486
  if (!this.resolverMap[resolverKey]) {
454
487
  this.resolverMap[resolverKey] = ctx.resolvers.generateSubscriptionResolver(
455
488
  typeName,
456
489
  fieldName,
490
+ resolverLogicalId,
457
491
  MappingTemplate.s3MappingTemplateFromString(generateSubscriptionRequestTemplate(), `${typeName}.${fieldName}.req.vtl`),
458
492
  MappingTemplate.s3MappingTemplateFromString(generateSubscriptionResponseTemplate(), `${typeName}.${fieldName}.res.vtl`),
459
493
  );
@@ -465,12 +499,14 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
465
499
  type: ObjectTypeDefinitionNode,
466
500
  typeName: string,
467
501
  fieldName: string,
502
+ resolverLogicalId: string,
468
503
  ): TransformerResolverProvider => {
469
504
  const resolverKey = `OnUpdate${generateResolverKey(typeName, fieldName)}`;
470
505
  if (!this.resolverMap[resolverKey]) {
471
506
  this.resolverMap[resolverKey] = ctx.resolvers.generateSubscriptionResolver(
472
507
  typeName,
473
508
  fieldName,
509
+ resolverLogicalId,
474
510
  MappingTemplate.s3MappingTemplateFromString(generateSubscriptionRequestTemplate(), `${typeName}.${fieldName}.req.vtl`),
475
511
  MappingTemplate.s3MappingTemplateFromString(generateSubscriptionResponseTemplate(), `${typeName}.${fieldName}.res.vtl`),
476
512
  );
@@ -482,12 +518,14 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
482
518
  type: ObjectTypeDefinitionNode,
483
519
  typeName: string,
484
520
  fieldName: string,
521
+ resolverLogicalId: string,
485
522
  ): TransformerResolverProvider => {
486
523
  const resolverKey = `OnDelete${generateResolverKey(typeName, fieldName)}`;
487
524
  if (!this.resolverMap[resolverKey]) {
488
525
  this.resolverMap[resolverKey] = ctx.resolvers.generateSubscriptionResolver(
489
526
  typeName,
490
527
  fieldName,
528
+ resolverLogicalId,
491
529
  MappingTemplate.s3MappingTemplateFromString(generateSubscriptionRequestTemplate(), `${typeName}.${fieldName}.req.vtl`),
492
530
  MappingTemplate.s3MappingTemplateFromString(generateSubscriptionResponseTemplate(), `${typeName}.${fieldName}.res.vtl`),
493
531
  );
@@ -499,6 +537,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
499
537
  type: ObjectTypeDefinitionNode,
500
538
  typeName: string,
501
539
  fieldName: string,
540
+ resolverLogicalId: string,
502
541
  ): TransformerResolverProvider => {
503
542
  const isSyncEnabled = ctx.isProjectUsingDataStore();
504
543
  const dataSource = this.datasourceMap[type.name.value];
@@ -507,6 +546,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
507
546
  this.resolverMap[resolverKey] = ctx.resolvers.generateQueryResolver(
508
547
  typeName,
509
548
  fieldName,
549
+ resolverLogicalId,
510
550
  dataSource,
511
551
  MappingTemplate.s3MappingTemplateFromString(generateSyncRequestTemplate(), `${typeName}.${fieldName}.req.vtl`),
512
552
  MappingTemplate.s3MappingTemplateFromString(
@@ -521,15 +561,16 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
521
561
  getQueryFieldNames = (
522
562
  ctx: TransformerTransformSchemaStepContextProvider,
523
563
  type: ObjectTypeDefinitionNode,
524
- ): Set<{ fieldName: string; typeName: string; type: QueryFieldType }> => {
564
+ ): Set<{ fieldName: string; typeName: string; type: QueryFieldType; resolverLogicalId: string }> => {
525
565
  const typeName = type.name.value;
526
- const fields: Set<{ fieldName: string; typeName: string; type: QueryFieldType }> = new Set();
566
+ const fields: Set<{ fieldName: string; typeName: string; type: QueryFieldType; resolverLogicalId: string }> = new Set();
527
567
  const modelDirectiveConfig = this.modelDirectiveConfig.get(type.name.value);
528
568
  if (modelDirectiveConfig?.queries?.get) {
529
569
  fields.add({
530
570
  typeName: 'Query',
531
571
  fieldName: modelDirectiveConfig.queries.get || toCamelCase(['get', typeName]),
532
572
  type: QueryFieldType.GET,
573
+ resolverLogicalId: ResolverResourceIDs.DynamoDBGetResolverResourceID(typeName),
533
574
  });
534
575
  }
535
576
 
@@ -538,6 +579,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
538
579
  typeName: 'Query',
539
580
  fieldName: modelDirectiveConfig.queries.list || toCamelCase(['list', typeName]),
540
581
  type: QueryFieldType.LIST,
582
+ resolverLogicalId: ResolverResourceIDs.DynamoDBListResolverResourceID(typeName),
541
583
  });
542
584
  }
543
585
 
@@ -546,6 +588,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
546
588
  typeName: 'Query',
547
589
  fieldName: modelDirectiveConfig.queries.sync || toCamelCase(['sync', typeName]),
548
590
  type: QueryFieldType.SYNC,
591
+ resolverLogicalId: ResolverResourceIDs.SyncResolverResourceID(typeName),
549
592
  });
550
593
  }
551
594
 
@@ -555,7 +598,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
555
598
  getMutationFieldNames = (
556
599
  ctx: TransformerTransformSchemaStepContextProvider,
557
600
  type: ObjectTypeDefinitionNode,
558
- ): Set<{ fieldName: string; typeName: string; type: MutationFieldType }> => {
601
+ ): Set<{ fieldName: string; typeName: string; type: MutationFieldType; resolverLogicalId: string }> => {
559
602
  // Todo: get fields names from the directives
560
603
  const typeName = type.name.value;
561
604
  const modelDirectiveConfig = this.modelDirectiveConfig.get(typeName);
@@ -572,13 +615,27 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
572
615
  }
573
616
  };
574
617
 
575
- const fieldNames: Set<{ fieldName: string; typeName: string; type: MutationFieldType }> = new Set();
618
+ const getMutationResolverLogicalId = (type: string): string => {
619
+ switch (type) {
620
+ case 'create':
621
+ return ResolverResourceIDs.DynamoDBCreateResolverResourceID(typeName);
622
+ case 'update':
623
+ return ResolverResourceIDs.DynamoDBUpdateResolverResourceID(typeName);
624
+ case 'delete':
625
+ return ResolverResourceIDs.DynamoDBDeleteResolverResourceID(typeName);
626
+ default:
627
+ throw new Error('Unknown mutation type');
628
+ }
629
+ };
630
+
631
+ const fieldNames: Set<{ fieldName: string; typeName: string; type: MutationFieldType; resolverLogicalId: string }> = new Set();
576
632
  for (let [mutationType, mutationName] of Object.entries(modelDirectiveConfig?.mutations || {})) {
577
633
  if (mutationName) {
578
634
  fieldNames.add({
579
635
  typeName: 'Mutation',
580
636
  fieldName: mutationName,
581
637
  type: getMutationType(mutationType),
638
+ resolverLogicalId: getMutationResolverLogicalId(mutationType),
582
639
  });
583
640
  }
584
641
  }
@@ -592,6 +649,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
592
649
  fieldName: string;
593
650
  typeName: string;
594
651
  type: MutationFieldType;
652
+ resolverLogicalId: string;
595
653
  }>,
596
654
  ): string => {
597
655
  const mutationToSubscriptionTypeMap = {
@@ -677,11 +735,13 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
677
735
  fieldName: string;
678
736
  typeName: string;
679
737
  type: SubscriptionFieldType;
738
+ resolverLogicalId: string;
680
739
  }> => {
681
740
  const fields: Set<{
682
741
  fieldName: string;
683
742
  typeName: string;
684
743
  type: SubscriptionFieldType;
744
+ resolverLogicalId: string;
685
745
  }> = new Set();
686
746
 
687
747
  const modelDirectiveConfig = this.modelDirectiveConfig.get(type.name.value);
@@ -692,6 +752,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
692
752
  typeName: 'Subscription',
693
753
  fieldName: fieldName,
694
754
  type: SubscriptionFieldType.ON_CREATE,
755
+ resolverLogicalId: ModelResourceIDs.ModelOnCreateSubscriptionName(type.name.value),
695
756
  });
696
757
  }
697
758
  }
@@ -702,6 +763,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
702
763
  typeName: 'Subscription',
703
764
  fieldName: fieldName,
704
765
  type: SubscriptionFieldType.ON_UPDATE,
766
+ resolverLogicalId: ModelResourceIDs.ModelOnUpdateSubscriptionName(type.name.value),
705
767
  });
706
768
  }
707
769
  }
@@ -712,6 +774,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
712
774
  typeName: 'Subscription',
713
775
  fieldName: fieldName,
714
776
  type: SubscriptionFieldType.ON_DELETE,
777
+ resolverLogicalId: ModelResourceIDs.ModelOnDeleteSubscriptionName(type.name.value),
715
778
  });
716
779
  }
717
780
  }
@@ -734,6 +797,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
734
797
  type: ObjectTypeDefinitionNode,
735
798
  typeName: string,
736
799
  fieldName: string,
800
+ resolverLogicalId: string,
737
801
  ): TransformerResolverProvider => {
738
802
  const isSyncEnabled = ctx.isProjectUsingDataStore();
739
803
  const dataSource = this.datasourceMap[type.name.value];
@@ -742,6 +806,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
742
806
  const resolver = ctx.resolvers.generateMutationResolver(
743
807
  typeName,
744
808
  fieldName,
809
+ resolverLogicalId,
745
810
  dataSource,
746
811
  MappingTemplate.s3MappingTemplateFromString(generateCreateRequestTemplate(type.name.value), `${typeName}.${fieldName}.req.vtl`),
747
812
  MappingTemplate.s3MappingTemplateFromString(
@@ -1072,7 +1137,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
1072
1137
  stream: StreamViewType.NEW_AND_OLD_IMAGES,
1073
1138
  encryption: TableEncryption.DEFAULT,
1074
1139
  removalPolicy: removalPolicy,
1075
- ...(this.options.SyncConfig ? { timeToLiveAttribute: '_ttl' } : undefined),
1140
+ ...(context.isProjectUsingDataStore() ? { timeToLiveAttribute: '_ttl' } : undefined),
1076
1141
  });
1077
1142
  const cfnTable = table.node.defaultChild as CfnTable;
1078
1143
 
@@ -1128,8 +1193,9 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
1128
1193
 
1129
1194
  const cfnDataSource = dataSource.node.defaultChild as CfnDataSource;
1130
1195
  cfnDataSource.addDependsOn(role.node.defaultChild as CfnRole);
1196
+ cfnDataSource.overrideLogicalId(datasourceRoleLogicalID);
1131
1197
 
1132
- if (this.options.SyncConfig) {
1198
+ if (context.isProjectUsingDataStore()) {
1133
1199
  const datasourceDynamoDb = cfnDataSource.dynamoDbConfig as any;
1134
1200
  datasourceDynamoDb.deltaSyncConfig = {
1135
1201
  deltaSyncTableName: context.resourceHelper.generateResourceName(SyncResourceIDs.syncTableName),
@@ -1153,7 +1219,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
1153
1219
  }
1154
1220
 
1155
1221
  private createIAMRole(context: TransformerContextProvider, def: ObjectTypeDefinitionNode, stack: cdk.Stack, tableName: string) {
1156
- const roleName = context.resourceHelper.generateResourceName(ModelResourceIDs.ModelTableIAMRoleID(def!.name.value));
1222
+ const roleName = context.resourceHelper.generateIAMRoleName(ModelResourceIDs.ModelTableIAMRoleID(def!.name.value));
1157
1223
  const role = new iam.Role(stack, ModelResourceIDs.ModelTableIAMRoleID(def!.name.value), {
1158
1224
  roleName: roleName,
1159
1225
  assumedBy: new iam.ServicePrincipal('appsync.amazonaws.com'),
@@ -1184,7 +1250,7 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
1184
1250
  cdk.Fn.sub('arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${tablename}/*', {
1185
1251
  tablename: tableName,
1186
1252
  }),
1187
- ...(this.options.SyncConfig
1253
+ ...(context.isProjectUsingDataStore()
1188
1254
  ? [
1189
1255
  // eslint-disable-next-line no-template-curly-in-string
1190
1256
  cdk.Fn.sub('arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${tablename}', {
@@ -1202,13 +1268,10 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
1202
1268
  }),
1203
1269
  );
1204
1270
 
1205
- if (this.options.SyncConfig && SyncUtils.isLambdaSyncConfig(this.options.SyncConfig)) {
1271
+ const syncConfig = SyncUtils.getSyncConfig(context, def!.name.value);
1272
+ if (syncConfig && SyncUtils.isLambdaSyncConfig(syncConfig)) {
1206
1273
  role.attachInlinePolicy(
1207
- SyncUtils.createSyncLambdaIAMPolicy(
1208
- stack,
1209
- this.options.SyncConfig.LambdaConflictHandler.name,
1210
- this.options.SyncConfig.LambdaConflictHandler.region,
1211
- ),
1274
+ SyncUtils.createSyncLambdaIAMPolicy(stack, syncConfig.LambdaConflictHandler.name, syncConfig.LambdaConflictHandler.region),
1212
1275
  );
1213
1276
  }
1214
1277
  return role;
@@ -1228,4 +1291,10 @@ export class ModelTransformer extends TransformerModelBase implements Transforme
1228
1291
  ...options,
1229
1292
  };
1230
1293
  };
1294
+
1295
+ private ensureValidSubscriptionName = (name: string): string => {
1296
+ if (name.length <= 50) return name;
1297
+
1298
+ return name.slice(0, 45) + md5(name).slice(0, 5);
1299
+ };
1231
1300
  }
@@ -45,9 +45,7 @@ export const makeUpdateInputField = (
45
45
  input.fields.forEach(f => f.makeNullable());
46
46
 
47
47
  // Add id field and make it optional
48
- if (!hasIdField) {
49
- input.addField(InputFieldWrapper.create('id', 'ID', false));
50
- } else {
48
+ if (hasIdField) {
51
49
  const idField = input.fields.find(f => f.name === 'id');
52
50
  if (idField) {
53
51
  idField.makeNonNullable();
@@ -127,7 +125,7 @@ export const makeCreateInputField = (
127
125
 
128
126
  // Add id field and make it optional
129
127
  if (!hasIdField) {
130
- input.addField(InputFieldWrapper.create('id', 'ID'));
128
+ input.addField(InputFieldWrapper.create('id', 'ID', true));
131
129
  } else {
132
130
  const idField = input.fields.find(f => f.name === 'id');
133
131
  if (idField) {
@@ -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, true, true));
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) {
@@ -99,13 +99,13 @@ 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
- let enabled = ctx.resourceHelper.api.globalSandboxModeEnabled;
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')));
106
106
  else exp = methodCall(ref('util.unauthorized'));
107
107
 
108
108
  return printBlock(`Sandbox Mode ${enabled ? 'Enabled' : 'Disabled'}`)(
109
- compoundExpression([iff(not(ref('ctx.stash.get("hasAuth")')), exp)]),
109
+ compoundExpression([iff(not(ref('ctx.stash.get("hasAuth")')), exp), toJson(obj({}))]),
110
110
  );
111
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),