import { CodeGenField , CodeGenFieldDirective , CodeGenModel , CodeGenModelMap } from '../visitors/appsync-visitor' ; import { CodeGenFieldConnection , DEFAULT_HASH_KEY_FIELD , flattenFieldDirectives , makeConnectionAttributeName } from './process-connections' ; import { processHasOneConnection } from './process-has-one' ; import { processBelongsToConnection , getBelongsToConnectedField } from './process-belongs-to' ; import { processHasManyConnection } from './process-has-many' ; import { getDirective } from './fieldUtils' ; export function getConnectedFieldV2 ( field , model , connectedModel , directiveName , shouldUseModelNameFieldInHasManyAndBelongsTo = false ) { const connectionInfo = getDirective ( field ) ( directiveName ) ; if ( ! connectionInfo ) { throw new Error ( `The ${ field . name } on model ${ model . name } is not connected` ) ; } if ( connectionInfo . name === 'belongsTo' ) { let connectedFieldBelongsTo = getBelongsToConnectedField ( field , model , connectedModel ) ; if ( connectedFieldBelongsTo ) { return connectedFieldBelongsTo ; } } const indexName = connectionInfo . arguments . indexName ; const connectionFields = connectionInfo . arguments . fields ; if ( connectionFields || directiveName === 'hasOne' ) { let connectionDirective ; if ( indexName ) { connectionDirective = flattenFieldDirectives ( connectedModel ) . find ( dir => { return dir . name === 'index' && dir . arguments . name === indexName ; } ) ; if ( ! connectionDirective ) { throw new Error ( `Error processing @${ connectionInfo . name } directive on ${ model . name }.${ field . name }, @index directive with name ${ indexName } was not found in connected model ${ connectedModel . name }` ) ; } } else { connectionDirective = flattenFieldDirectives ( connectedModel ) . find ( dir => { return dir . name === 'primaryKey' ; } ) ; } const getOtherSideBelongsToField = ( type , otherSideModel ) => { return otherSideModel . fields . filter ( f => f . type === type ) . find ( f => f . directives . find ( d => d . name === 'belongsTo' ) ) ?. name ; } ; let connectedFieldName = DEFAULT_HASH_KEY_FIELD ; if ( connectionDirective ) { connectedFieldName = ( ( fieldDir ) => { return fieldDir . fieldName ; } ) ( connectionDirective as CodeGenFieldDirective ) ; } else { const otherSideBelongsToField = getOtherSideBelongsToField ( model . name , connectedModel ) ; if ( otherSideBelongsToField ) { connectedFieldName = otherSideBelongsToField ; } } const otherSideConnectedField = connectedModel . fields . filter ( f => f . type === model . name ) . find ( f => f . directives . find ( d => ( d . name === 'belongsTo' || d . name === 'hasOne' || d . name === 'hasMany' ) && d . arguments . fields && d . arguments . fields [ 0 ] === connectedFieldName ) ) ; if ( otherSideConnectedField ) { return otherSideConnectedField ; } const connectedField = connectedModel . fields . find ( f => f . name === connectedFieldName ) ; if ( ! connectedField ) { throw new Error ( `Can not find key field ${ connectedFieldName } in ${ connectedModel . name }` ) ; } return connectedField ; } if ( shouldUseModelNameFieldInHasManyAndBelongsTo ) { const otherSideConnectedField = connectedModel . fields . filter ( f => f . type === model . name ) . find ( f => f . directives . find ( d => ( d . name === 'belongsTo' || d . name === 'hasOne' || d . name === 'hasMany' ) ) ) ; if ( otherSideConnectedField ) { return otherSideConnectedField ; } } const connectedFieldName = makeConnectionAttributeName ( model . name , field . name ) ; const connectedField = connectedModel . fields . find ( f => f . name === connectedFieldName ) ; return connectedField ? connectedField : { name : connectedFieldName , directives : [ ] , type : 'ID' , isList : false , isNullable : true , } ; } export function processConnectionsV2 ( field , model , modelMap , shouldUseModelNameFieldInHasManyAndBelongsTo ) { const connectionDirective = field . directives . find ( d => d . name === 'hasOne' || d . name === 'hasMany' || d . name === 'belongsTo' ) ; if ( connectionDirective ) { switch ( connectionDirective . name ) { case 'hasOne' : return processHasOneConnection ( field , model , modelMap , connectionDirective ) ; case 'belongsTo' : return processBelongsToConnection ( field , model , modelMap , connectionDirective ) ; case 'hasMany' : return processHasManyConnection ( field , model , modelMap , connectionDirective , shouldUseModelNameFieldInHasManyAndBelongsTo ) ; default : break ; } } }