1- import { ParserField , ParserTree , TypeSystemDefinition } from '@/Models' ;
1+ import { ParserField , ParserTree , TypeDefinition , TypeSystemDefinition } from '@/Models' ;
22import { Parser } from '@/Parser' ;
3+ import { mergeArguments } from '@/TreeOperations/merge/arguments' ;
4+ import { MergeError , ErrorConflict } from '@/TreeOperations/merge/common' ;
35import { isExtensionNode } from '@/TreeOperations/shared' ;
46import { TreeToGraphQL } from '@/TreeToGraphQL' ;
5- import { generateNodeId } from '@/shared' ;
7+ import { generateNodeId , getTypeName } from '@/shared' ;
68
9+ const detectConflictOnBaseNode = ( n1 : ParserField , n2 : ParserField ) => {
10+ if ( n1 . data . type !== n2 . data . type )
11+ throw new MergeError ( {
12+ conflictingNode : n1 . name ,
13+ message : `Data type conflict of nodes ${ n1 . name } and ${ n2 . name } ` ,
14+ } ) ;
15+ if ( JSON . stringify ( n1 . interfaces ) !== JSON . stringify ( n2 . interfaces ) )
16+ throw new MergeError ( {
17+ conflictingNode : n1 . name ,
18+ message : `Data type conflict of nodes ${ n1 . name } and ${ n2 . name } ` ,
19+ } ) ;
20+ } ;
21+
22+ const detectConflictOnFieldNode = ( parentName : string , f1 : ParserField , f2 : ParserField ) => {
23+ const [ f1Type , f2Type ] = [ getTypeName ( f1 . type . fieldType ) , getTypeName ( f2 . type . fieldType ) ] ;
24+ if ( f1Type !== f2Type )
25+ throw new MergeError ( {
26+ conflictingNode : parentName ,
27+ conflictingField : f1 . name ,
28+ message : `Data type conflict of node ${ parentName } field ${ f1 . name } ` ,
29+ } ) ;
30+ } ;
731const addFromLibrary = ( n : ParserField ) : ParserField => ( { ...n , fromLibrary : true } ) ;
832
33+ const mergeFields = ( parentName : string , fields1 : ParserField [ ] , fields2 : ParserField [ ] ) => {
34+ const mergedCommonFieldsAndF1Fields = fields1
35+ . map ( ( f1 ) => {
36+ const commonField = fields2 . find ( ( f2 ) => f2 . name === f1 . name ) ;
37+ if ( ! commonField ) return f1 ;
38+ detectConflictOnFieldNode ( parentName , f1 , commonField ) ;
39+ const mergedField : ParserField = {
40+ ...f1 ,
41+ args : mergeArguments ( f1 . name , f1 . args , commonField . args ) ,
42+ } ;
43+ return mergedField ;
44+ } )
45+ . filter ( < T > ( f : T | undefined ) : f is T => ! ! f ) ;
46+ const otherF2Fields = fields2 . filter ( ( f2 ) => ! fields1 . find ( ( f1 ) => f1 . name === f2 . name ) ) ;
47+ return [ ...mergedCommonFieldsAndF1Fields , ...otherF2Fields ] ;
48+ } ;
49+
950const mergeNode = ( n1 : ParserField , n2 : ParserField ) => {
10- const args = [ ...n1 . args , ...n2 . args . map ( addFromLibrary ) ] ;
51+ detectConflictOnBaseNode ( n1 , n2 ) ;
52+ const args =
53+ n1 . data . type === TypeDefinition . InputObjectTypeDefinition
54+ ? mergeArguments ( n1 . name , n1 . args , n2 . args )
55+ : mergeFields ( n1 . name , n1 . args , n2 . args . map ( addFromLibrary ) ) ;
56+
1157 const mergedNode = {
1258 ...n1 ,
1359 id : generateNodeId ( n1 . name , n1 . data . type , args ) ,
1460 args,
1561 directives : [ ...n1 . directives , ...n2 . directives . map ( addFromLibrary ) ] ,
1662 interfaces : [ ...n1 . interfaces , ...n2 . interfaces ] ,
1763 } as ParserField ;
18- //dedupe
19- mergedNode . args = mergedNode . args . filter ( ( a , i ) => mergedNode . args . findIndex ( ( aa ) => aa . name === a . name ) === i ) ;
64+
2065 mergedNode . directives = mergedNode . directives . filter (
2166 ( a , i ) => mergedNode . directives . findIndex ( ( aa ) => aa . name === a . name ) === i ,
2267 ) ;
@@ -30,7 +75,7 @@ export const mergeTrees = (tree1: ParserTree, tree2: ParserTree) => {
3075 const mergedNodesT1 : ParserField [ ] = [ ] ;
3176 const mergedNodesT2 : ParserField [ ] = [ ] ;
3277 const mergeResultNodes : ParserField [ ] = [ ] ;
33- const errors : Array < { conflictingNode : string ; conflictingField : string } > = [ ] ;
78+ const errors : Array < ErrorConflict > = [ ] ;
3479 const filteredTree2Nodes = tree2 . nodes . filter ( ( t ) => t . data . type !== TypeSystemDefinition . SchemaDefinition ) ;
3580 // merge nodes
3681 tree1 . nodes . forEach ( ( t1n ) => {
@@ -48,23 +93,19 @@ export const mergeTrees = (tree1: ParserTree, tree2: ParserTree) => {
4893 }
4994 }
5095 } ) ;
51- } else {
52- // Check if arg named same and different typings -> throw
53- mergedNodesT1 . push ( t1n ) ;
54- mergedNodesT2 . push ( matchingNode ) ;
55- t1n . args . forEach ( ( t1nA ) => {
56- const matchingArg = matchingNode . args . find ( ( mNA ) => mNA . name === t1nA . name ) ;
57- if ( matchingArg ) {
58- if ( JSON . stringify ( matchingArg ) !== JSON . stringify ( t1nA ) ) {
59- errors . push ( {
60- conflictingField : t1nA . name ,
61- conflictingNode : t1n . name ,
62- } ) ;
63- }
64- }
65- } ) ;
66- if ( ! errors . length ) {
67- mergeResultNodes . push ( mergeNode ( t1n , matchingNode ) ) ;
96+ return ;
97+ }
98+ mergedNodesT1 . push ( t1n ) ;
99+ mergedNodesT2 . push ( matchingNode ) ;
100+ try {
101+ const mergeNodeResult = mergeNode ( t1n , matchingNode ) ;
102+ mergeResultNodes . push ( mergeNodeResult ) ;
103+ } catch ( error ) {
104+ if ( error instanceof MergeError ) {
105+ errors . push ( {
106+ conflictingNode : error . errorParams . conflictingNode ,
107+ conflictingField : error . errorParams . conflictingField ,
108+ } ) ;
68109 }
69110 }
70111 }
0 commit comments