import * as p1 from "./" ; import { Graph , json } from "graphlib" ; export type Edge = { name : string ; link : "INLINE" | "TABLE" | "" ; type : "hasOne" | "hasMany" ; from : p1 . ObjectTypeDefinition ; to : p1 . ObjectTypeDefinition ; fromField : p1 . FieldDefinition ; toField : p1 . FieldDefinition ; } ; export function load ( schema ) { const graph = new Graph ( { directed : true } ) ; const defs = schema . definitions ; for ( let def of defs ) { if ( def instanceof p1 . ObjectTypeDefinition ) { for ( let field of def . fields ) { graph . setNode ( def . name + "." + field . name , def ) ; } } else if ( def instanceof p1 . EnumTypeDefinition ) { graph . setNode ( def . name , def ) ; } } for ( let from of defs ) { if ( ! ( from instanceof p1 . ObjectTypeDefinition ) ) { continue ; } for ( let fromField of from . fields ) { if ( ! fromField . type . isReference ( ) ) { continue ; } const to = schema . findObject ( ( o ) => o . name === fromField . type . named ( ) ) ; if ( ! to ) { continue ; } const version = schema . version ( ) ; let toField ; for ( let field of to . fields ) { const isDM1Primary = version === "1.0" && field . type . named ( ) === "ID" && field . findDirective ( ( d ) => d . name === "unique" ) ; const isDM11Primary = version === "1.1" && field . findDirective ( ( d ) => d . name === "id" ) ; if ( isDM1Primary || isDM11Primary ) { toField = field ; break ; } } if ( ! toField ) { continue ; } const fromFullName = from . name + "." + fromField . name ; const toFullName = to . name + "." + toField . name ; let link = version === "1.0" ? "TABLE" : "" ; const relation = fromField . directives . find ( ( d ) => d . name === "relation" ) ; let relationName = "" ; if ( relation ) { if ( version !== "1.0" ) { const arg = relation . arguments . find ( ( a ) => a . name === "link" ) ; if ( arg && "value" in arg . value && arg . value . value === "TABLE" ) { link = "TABLE" ; } else { link = "INLINE" ; } } const nameArg = relation . findArgument ( ( a ) => a . name === "name" ) ; if ( nameArg && nameArg . value . kind === "StringValue" ) { relationName = nameArg . value . value ; } } if ( ! graph . hasNode ( toFullName ) ) { throw new Error ( `graph doesn't have a "${ toFullName }" node` ) ; } else if ( ! graph . hasNode ( fromFullName ) ) { throw new Error ( `graph doesn't have a "${ fromFullName }" node` ) ; } if ( hasOne ( fromField . type ) ) { graph . setEdge ( fromFullName , toFullName , < Edge > { name : relationName , type : "hasOne" , link : link , from : from , to : to , fromField : fromField , toField : toField , } ) ; continue ; } if ( hasMany ( fromField . type ) ) { graph . setEdge ( fromFullName , toFullName , < Edge > { name : relationName , type : "hasMany" , link : link , from : from , to : to , fromField : fromField , toField : toField , } ) ; continue ; } } } return graph ; } export function print ( g ) { return JSON . stringify ( json . write ( g ) , null , "  " ) ; } function hasOne ( dt ) { switch ( dt . kind ) { case "ListType" : return false ; case "NonNullType" : return hasOne ( dt . inner ( ) ) ; case "NamedType" : return true ; } } function hasMany ( dt ) { switch ( dt . kind ) { case "ListType" : return true ; case "NonNullType" : return hasMany ( dt . inner ( ) ) ; case "NamedType" : return false ; } }