Skip to content

Commit 9aaa06f

Browse files
authored
Feat(amplify-codegen): Vnext directive enhancements (#237)
* primaryKey/index directives (#217) * Feature: Add new @PrimaryKey and @index directives Added support for the java visitor, swift and process-connection up next * Feature: swift visitor processes @PrimaryKey and @index Fix the location of the java visitor primaryKey/index tests to sit next to key * Feature: Adding @key replacement support to process-connections WIP * Feature: Adding @key replacement support to process-connections primaryKey and index are supported directives for connections unit tests are added We'll need to remove the side by side support for the v1 and v2 transformers post-release * Fix: add feature flags mocking to other unit tests * Fix: Update the way version is calculated for vNext transformer * Fix: Get feature flag according to codegen pattern * hasOne, hasMany, and belongsTo directive support (#229) * Feature: Add new @PrimaryKey and @index directives Added support for the java visitor, swift and process-connection up next * Feature: swift visitor processes @PrimaryKey and @index Fix the location of the java visitor primaryKey/index tests to sit next to key * Feature: Adding @key replacement support to process-connections WIP * Feature: Adding @key replacement support to process-connections primaryKey and index are supported directives for connections unit tests are added We'll need to remove the side by side support for the v1 and v2 transformers post-release * Fix: add feature flags mocking to other unit tests * Fix: Update the way version is calculated for vNext transformer * Feature: WIP addition of hasOne directive * Fix: Get feature flag according to codegen pattern * Feature: WIP addition of hasOne directive * WIP Feature: V2 connection directive replacements hasOne, hasMany, belongsTo manyToMany is to come in a future branch * Fix: Purge FeatureFlags cli core usage, update tests * Add another unit test for hasOne * Fix all the merge conflicts I already resolved but git re-broke * Fix: Process connections test suite Match the scenarios in the design doc, cover another case * Fix: Remove or update some outdated code in connections processing * Fix: Code quality changes for LGTM bot * Fix: swift visitor index directive, unit test compare metadata * Fix: remove unused import * Fix: Remove unreachable code and add some error checking belongsTo
1 parent c81695e commit 9aaa06f

File tree

15 files changed

+897
-23
lines changed

15 files changed

+897
-23
lines changed

packages/amplify-codegen/src/commands/models.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ async function generateModels(context) {
7272

7373
const generateIndexRules = readFeatureFlag('codegen.generateIndexRules');
7474
const emitAuthProvider = readFeatureFlag('codegen.emitAuthProvider');
75+
const usePipelinedTransformer = readFeatureFlag('graphQLTransformer.useExperimentalPipelinedTransformer')
7576

7677
let enableDartNullSafety = readFeatureFlag('codegen.enableDartNullSafety');
7778

@@ -101,7 +102,8 @@ async function generateModels(context) {
101102
emitAuthProvider,
102103
generateIndexRules,
103104
enableDartNullSafety,
104-
handleListNullabilityTransparently
105+
handleListNullabilityTransparently,
106+
usePipelinedTransformer
105107
},
106108
});
107109

packages/appsync-modelgen-plugin/src/__tests__/utils/process-connections.test.ts

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
getConnectedField,
99
} from '../../utils/process-connections';
1010
import { CodeGenModelMap, CodeGenModel } from '../../visitors/appsync-visitor';
11+
import { processConnectionsV2 } from '../../utils/process-connections-v2';
1112

1213
describe('process connection', () => {
1314
describe('Bi-Directional connection (named connection)', () => {
@@ -463,4 +464,313 @@ describe('process connection', () => {
463464
expect(getConnectedField(subordinateField, employeeModel, employeeModel)).toEqual(supervisorField);
464465
});
465466
});
467+
468+
describe('GraphQL vNext getConnectedField tests with @primaryKey and @index', () => {
469+
let hasOneWithFieldsModelMap: CodeGenModelMap;
470+
let hasOneNoFieldsModelMap: CodeGenModelMap;
471+
let v2ModelMap: CodeGenModelMap;
472+
let v2IndexModelMap: CodeGenModelMap;
473+
474+
beforeEach(() => {
475+
const hasOneWithFieldsSchema = /* GraphQL */ `
476+
type BatteryCharger @model {
477+
chargerID: ID!
478+
powerSource: PowerSource @hasOne(fields: ["chargerID"])
479+
}
480+
481+
type PowerSource @model {
482+
sourceID: ID! @primaryKey
483+
amps: Float!
484+
volts: Float!
485+
}
486+
`;
487+
488+
const hasOneNoFieldsSchema = /* GraphQL */ `
489+
type BatteryCharger @model {
490+
powerSource: PowerSource @hasOne
491+
}
492+
493+
type PowerSource @model {
494+
id: ID!
495+
amps: Float!
496+
volts: Float!
497+
}
498+
`;
499+
500+
const v2Schema = /* GraphQL */ `
501+
type Post @model {
502+
comments: [Comment] @hasMany(fields: ["id"])
503+
}
504+
505+
type Comment @model {
506+
postID: ID! @primaryKey(sortKeyFields: ["content"])
507+
content: String!
508+
post: Post @belongsTo(fields:["postID"])
509+
}
510+
`;
511+
512+
const v2IndexSchema = /* graphQL */ `
513+
type Post @model {
514+
id: ID!
515+
title: String!
516+
comments: [Comment] @hasMany(indexName: "byPost", fields: ["id"])
517+
}
518+
519+
type Comment @model {
520+
id: ID!
521+
postID: ID! @index(name: "byPost", sortKeyFields: ["content"])
522+
content: String!
523+
}
524+
`;
525+
526+
hasOneWithFieldsModelMap = {
527+
BatteryCharger: {
528+
name: 'BatteryCharger',
529+
type: 'model',
530+
directives: [],
531+
fields: [
532+
{
533+
type: 'ID',
534+
isNullable: false,
535+
isList: false,
536+
name: 'chargerID',
537+
directives: []
538+
},
539+
{
540+
type: 'PowerSource',
541+
isNullable: true,
542+
isList: false,
543+
name: 'powerSource',
544+
directives: [{ name: 'hasOne', arguments: { fields: ['chargerID'] } }],
545+
},
546+
],
547+
},
548+
PowerSource: {
549+
name: 'PowerSource',
550+
type: 'model',
551+
directives: [],
552+
fields: [
553+
{
554+
type: 'id',
555+
isNullable: false,
556+
isList: false,
557+
name: 'sourceID',
558+
directives: [{ name: 'primaryKey', arguments: {} }],
559+
},
560+
{
561+
type: 'Float',
562+
isNullable: false,
563+
isList: false,
564+
name: 'amps',
565+
directives: [],
566+
},
567+
{
568+
type: 'Float',
569+
isNullable: false,
570+
isList: false,
571+
name: 'volts',
572+
directives: [],
573+
},
574+
],
575+
},
576+
};
577+
578+
hasOneNoFieldsModelMap = {
579+
BatteryCharger: {
580+
name: 'BatteryCharger',
581+
type: 'model',
582+
directives: [],
583+
fields: [
584+
{
585+
type: 'PowerSource',
586+
isNullable: true,
587+
isList: false,
588+
name: 'powerSource',
589+
directives: [{ name: 'hasOne', arguments: {} }],
590+
},
591+
],
592+
},
593+
PowerSource: {
594+
name: 'PowerSource',
595+
type: 'model',
596+
directives: [],
597+
fields: [
598+
{
599+
type: 'ID',
600+
isNullable: false,
601+
isList: false,
602+
name: 'id',
603+
directives: []
604+
},
605+
{
606+
type: 'Float',
607+
isNullable: false,
608+
isList: false,
609+
name: 'amps',
610+
directives: [],
611+
},
612+
{
613+
type: 'Float',
614+
isNullable: false,
615+
isList: false,
616+
name: 'volts',
617+
directives: [],
618+
},
619+
],
620+
},
621+
};
622+
623+
v2ModelMap = {
624+
Post: {
625+
name: 'Post',
626+
type: 'model',
627+
directives: [],
628+
fields: [
629+
{
630+
type: 'Comment',
631+
isNullable: true,
632+
isList: true,
633+
name: 'comments',
634+
directives: [{ name: 'hasMany', arguments: { fields: ['id'] } }],
635+
},
636+
],
637+
},
638+
Comment: {
639+
name: 'Comment',
640+
type: 'model',
641+
directives: [],
642+
fields: [
643+
{
644+
type: 'id',
645+
isNullable: false,
646+
isList: false,
647+
name: 'postID',
648+
directives: [{name: 'primaryKey', arguments: { sortKeyFields: ['content'] } }],
649+
},
650+
{
651+
type: 'String',
652+
isNullable: false,
653+
isList: false,
654+
name: 'content',
655+
directives: [],
656+
},
657+
{
658+
type: 'Post',
659+
isNullable: false,
660+
isList: false,
661+
name: 'post',
662+
directives: [{ name: 'belongsTo', arguments: { fields: ['postID'] } }],
663+
},
664+
],
665+
},
666+
};
667+
668+
v2IndexModelMap = {
669+
Post: {
670+
name: 'Post',
671+
type: 'model',
672+
directives: [],
673+
fields: [
674+
{
675+
type: 'ID',
676+
isNullable: false,
677+
isList: false,
678+
name: 'id',
679+
directives: [],
680+
},
681+
{
682+
type: 'String',
683+
isNullable: false,
684+
isList: false,
685+
name: 'title',
686+
directives: [],
687+
},
688+
{
689+
type: 'Comment',
690+
isNullable: true,
691+
isList: true,
692+
name: 'comments',
693+
directives: [{ name: 'hasMany', arguments: { indexName: 'byPost', fields: ['id'] } }],
694+
},
695+
],
696+
},
697+
Comment: {
698+
name: 'Comment',
699+
type: 'model',
700+
directives: [],
701+
fields: [
702+
{
703+
type: 'ID',
704+
isNullable: false,
705+
isList: false,
706+
name: 'id',
707+
directives: [],
708+
},
709+
{
710+
type: 'ID',
711+
isNullable: false,
712+
isList: false,
713+
name: 'postID',
714+
directives: [{name: 'index', arguments: { name: 'byPost', sortKeyFields: ['content'] }}],
715+
},
716+
{
717+
type: 'String',
718+
isNullable: false,
719+
isList: false,
720+
name: 'content',
721+
directives: [],
722+
},
723+
],
724+
},
725+
};
726+
});
727+
728+
describe('Has many comparison', () => {
729+
it('should support connection with @primaryKey on BELONGS_TO side', () => {
730+
const postField = v2ModelMap.Comment.fields[2];
731+
const connectionInfo = (processConnectionsV2(postField, v2ModelMap.Post, v2ModelMap) as any) as CodeGenFieldConnectionBelongsTo;
732+
expect(connectionInfo).toBeDefined();
733+
expect(connectionInfo.kind).toEqual(CodeGenConnectionType.BELONGS_TO);
734+
expect(connectionInfo.targetName).toEqual(v2ModelMap.Comment.fields[0].name);
735+
expect(connectionInfo.isConnectingFieldAutoCreated).toEqual(false);
736+
});
737+
738+
it('should support connection with @primaryKey on HAS_MANY side', () => {
739+
const commentsField = v2ModelMap.Post.fields[0];
740+
const connectionInfo = (processConnectionsV2(commentsField, v2ModelMap.Comment, v2ModelMap) as any) as CodeGenFieldConnectionHasMany;
741+
expect(connectionInfo).toBeDefined();
742+
expect(connectionInfo.kind).toEqual(CodeGenConnectionType.HAS_MANY);
743+
expect(connectionInfo.connectedModel).toEqual(v2ModelMap.Comment);
744+
expect(connectionInfo.isConnectingFieldAutoCreated).toEqual(false);
745+
});
746+
747+
it('Should support connection with @index on BELONGS_TO side', () => {
748+
const commentsField = v2IndexModelMap.Post.fields[2];
749+
const connectionInfo = (processConnectionsV2(commentsField, v2IndexModelMap.Comment, v2IndexModelMap) as any) as CodeGenFieldConnectionHasMany;
750+
expect(connectionInfo).toBeDefined();
751+
expect(connectionInfo.kind).toEqual(CodeGenConnectionType.HAS_MANY);
752+
expect(connectionInfo.connectedModel).toEqual(v2IndexModelMap.Comment);
753+
expect(connectionInfo.isConnectingFieldAutoCreated).toEqual(false);
754+
});
755+
});
756+
757+
describe('Has one testing', () => {
758+
it('Should support @hasOne with no explicit primary key', () => {
759+
const powerSourceField = hasOneNoFieldsModelMap.BatteryCharger.fields[0];
760+
const connectionInfo = (processConnectionsV2(powerSourceField, hasOneNoFieldsModelMap.PowerSource, hasOneNoFieldsModelMap)) as CodeGenFieldConnectionHasOne;
761+
expect(connectionInfo).toBeDefined();
762+
expect(connectionInfo.kind).toEqual(CodeGenConnectionType.HAS_ONE);
763+
expect(connectionInfo.connectedModel).toEqual(hasOneNoFieldsModelMap.PowerSource);
764+
expect(connectionInfo.isConnectingFieldAutoCreated).toEqual(true);
765+
});
766+
it('Should support @hasOne with an explicit primary key', () => {
767+
const powerSourceField = hasOneWithFieldsModelMap.BatteryCharger.fields[1];
768+
const connectionInfo = (processConnectionsV2(powerSourceField, hasOneWithFieldsModelMap.PowerSource, hasOneWithFieldsModelMap)) as CodeGenFieldConnectionHasOne;
769+
expect(connectionInfo).toBeDefined();
770+
expect(connectionInfo.kind).toEqual(CodeGenConnectionType.HAS_ONE);
771+
expect(connectionInfo.connectedModel).toEqual(hasOneWithFieldsModelMap.PowerSource);
772+
expect(connectionInfo.isConnectingFieldAutoCreated).toEqual(false);
773+
});
774+
});
775+
});
466776
});

0 commit comments

Comments
 (0)