@@ -296,7 +296,7 @@ export class AppSyncModelVisitor<
296296 }
297297 processDirectives (
298298 // TODO: Remove us when we have a fix to roll-forward.
299- shouldUseModelNameFieldInHasManyAndBelongsTo : boolean
299+ shouldUseModelNameFieldInHasManyAndBelongsTo : boolean ,
300300 ) {
301301 if ( this . config . usePipelinedTransformer || this . config . transformerVersion === 2 ) {
302302 this . processV2KeyDirectives ( ) ;
@@ -551,15 +551,12 @@ export class AppSyncModelVisitor<
551551 } ) ;
552552 }
553553
554- protected generateIntermediateModel (
555- firstModel : CodeGenModel ,
556- secondModel : CodeGenModel ,
557- firstField : CodeGenField ,
558- secondField : CodeGenField ,
559- relationName : string ,
560- ) {
554+ protected generateIntermediateModel ( firstModel : CodeGenModel , secondModel : CodeGenModel , relationName : string ) {
561555 const firstModelKeyFieldName = `${ camelCase ( firstModel . name ) } ID` ;
556+ const firstModelSortKeyFields : CodeGenField [ ] = this . getSortKeyFields ( firstModel ) ;
562557 const secondModelKeyFieldName = `${ camelCase ( secondModel . name ) } ID` ;
558+ const secondModelSortKeyFields : CodeGenField [ ] = this . getSortKeyFields ( secondModel ) ;
559+
563560 let intermediateModel : CodeGenModel = {
564561 name : relationName ,
565562 type : 'model' ,
@@ -577,15 +574,49 @@ export class AppSyncModelVisitor<
577574 isNullable : false ,
578575 isList : false ,
579576 name : firstModelKeyFieldName ,
580- directives : [ { name : 'index' , arguments : { name : 'by' + firstModel . name , sortKeyFields : [ secondModelKeyFieldName ] } } ] ,
577+ directives : [
578+ {
579+ name : 'index' ,
580+ arguments : {
581+ name : 'by' + firstModel . name ,
582+ sortKeyFields : firstModelSortKeyFields . map ( f => this . generateIntermediateModelSortKeyFieldName ( firstModel , f ) ) ,
583+ } ,
584+ } ,
585+ ] ,
581586 } ,
587+ ...firstModelSortKeyFields . map ( field => {
588+ return {
589+ type : field . type ,
590+ isNullable : false ,
591+ isList : field . isList ,
592+ name : this . generateIntermediateModelSortKeyFieldName ( firstModel , field ) ,
593+ directives : [ ] ,
594+ } ;
595+ } ) ,
582596 {
583597 type : 'ID' ,
584598 isNullable : false ,
585599 isList : false ,
586600 name : secondModelKeyFieldName ,
587- directives : [ { name : 'index' , arguments : { name : 'by' + secondModel . name , sortKeyFields : [ firstModelKeyFieldName ] } } ] ,
601+ directives : [
602+ {
603+ name : 'index' ,
604+ arguments : {
605+ name : 'by' + secondModel . name ,
606+ sortKeyFields : secondModelSortKeyFields . map ( f => this . generateIntermediateModelSortKeyFieldName ( secondModel , f ) ) ,
607+ } ,
608+ } ,
609+ ] ,
588610 } ,
611+ ...secondModelSortKeyFields . map ( field => {
612+ return {
613+ type : field . type ,
614+ isNullable : false ,
615+ isList : field . isList ,
616+ name : this . generateIntermediateModelSortKeyFieldName ( secondModel , field ) ,
617+ directives : [ ] ,
618+ } ;
619+ } ) ,
589620 {
590621 type : firstModel . name ,
591622 isNullable : false ,
@@ -606,6 +637,18 @@ export class AppSyncModelVisitor<
606637 return intermediateModel ;
607638 }
608639
640+ protected generateIntermediateModelSortKeyFieldName ( model : CodeGenModel , sortKeyField : CodeGenField ) : string {
641+ const modelName = model . name . charAt ( 0 ) . toLocaleLowerCase ( ) + model . name . slice ( 1 ) ;
642+ return `${ modelName } ${ sortKeyField . name } ` ;
643+ }
644+
645+ protected getSortKeyFields ( model : CodeGenModel ) : CodeGenField [ ] {
646+ const keyDirective = model . directives . find ( d => d . name === 'key' && ! d . arguments . name ) ;
647+ return keyDirective
648+ ? ( keyDirective . arguments . fields as string [ ] ) . slice ( 1 ) . map ( fieldName => model . fields . find ( f => f . name === fieldName ) ! )
649+ : [ ] ;
650+ }
651+
609652 protected determinePrimaryKeyFieldname ( model : CodeGenModel ) : string {
610653 let primaryKeyFieldName = 'id' ;
611654 model . fields . forEach ( field => {
@@ -664,12 +707,13 @@ export class AppSyncModelVisitor<
664707 let intermediateModel = this . generateIntermediateModel (
665708 value [ 0 ] . model ,
666709 value [ 1 ] . model ,
667- value [ 0 ] . field ,
668- value [ 1 ] . field ,
669710 graphqlName ( toUpper ( value [ 0 ] . directive . arguments . relationName ) ) ,
670711 ) ;
671712 const modelDirective = intermediateModel . directives . find ( directive => directive . name === 'model' ) ;
672713 if ( modelDirective ) {
714+ // Maps @primaryKey and @index of intermediate model to old @key
715+ processPrimaryKey ( intermediateModel ) ;
716+ processIndex ( intermediateModel ) ;
673717 this . ensureIdField ( intermediateModel ) ;
674718 this . addTimestampFields ( intermediateModel , modelDirective ) ;
675719 this . sortFields ( intermediateModel ) ;
@@ -682,7 +726,7 @@ export class AppSyncModelVisitor<
682726
683727 protected processConnectionDirectivesV2 (
684728 // TODO: Remove us when we have a fix to roll-forward.
685- shouldUseModelNameFieldInHasManyAndBelongsTo : boolean
729+ shouldUseModelNameFieldInHasManyAndBelongsTo : boolean ,
686730 ) : void {
687731 this . processManyToManyDirectives ( ) ;
688732
@@ -726,15 +770,17 @@ export class AppSyncModelVisitor<
726770 Object . values ( this . modelMap ) . forEach ( model => {
727771 model . fields . forEach ( field => {
728772 const connectionInfo = field . connectionInfo ;
729- if ( connectionInfo
730- && connectionInfo . kind !== CodeGenConnectionType . HAS_MANY
731- && connectionInfo . kind !== CodeGenConnectionType . HAS_ONE
732- && connectionInfo . targetName !== 'id' ) {
773+ if (
774+ connectionInfo &&
775+ connectionInfo . kind !== CodeGenConnectionType . HAS_MANY &&
776+ connectionInfo . kind !== CodeGenConnectionType . HAS_ONE &&
777+ connectionInfo . targetName !== 'id'
778+ ) {
733779 // Need to remove the field that is targetName
734780 removeFieldFromModel ( model , connectionInfo . targetName ) ;
735781 }
736782 } ) ;
737- } )
783+ } ) ;
738784 }
739785
740786 protected processV2KeyDirectives ( ) : void {
0 commit comments