Skip to content

Commit f70cc88

Browse files
committed
3.0.3 -merge
1 parent 9bb8a0f commit f70cc88

File tree

3 files changed

+132
-45
lines changed

3 files changed

+132
-45
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "graphql-js-tree",
3-
"version": "3.0.2",
3+
"version": "3.0.3",
44
"private": false,
55
"license": "MIT",
66
"description": "GraphQL Parser providing simplier structure",
@@ -42,4 +42,4 @@
4242
"peerDependencies": {
4343
"graphql": "^16.0.0 || ^17.0.0"
4444
}
45-
}
45+
}

src/TreeOperations/merge/merge.ts

Lines changed: 128 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { ParserField, ParserTree, TypeDefinition, TypeSystemDefinition } from '@/Models';
1+
import { Options, ParserField, ParserTree, TypeDefinition, TypeSystemDefinition } from '@/Models';
22
import { Parser } from '@/Parser';
33
import { mergeArguments } from '@/TreeOperations/merge/arguments';
44
import { MergeError, ErrorConflict } from '@/TreeOperations/merge/common';
55
import { isExtensionNode } from '@/TreeOperations/shared';
66
import { TreeToGraphQL } from '@/TreeToGraphQL';
7-
import { generateNodeId, getTypeName } from '@/shared';
7+
import { createSchemaDefinition, generateNodeId, getTypeName } from '@/shared';
88

99
const detectConflictOnBaseNode = (n1: ParserField, n2: ParserField) => {
1010
if (n1.data.type !== n2.data.type)
@@ -116,22 +116,142 @@ export const mergeTrees = (tree1: ParserTree, tree2: ParserTree) => {
116116
errors,
117117
};
118118
}
119-
const t1Nodes = tree1.nodes.filter((t1n) => !mergedNodesT1.find((mtn1) => mtn1 === t1n));
119+
const t1Nodes = tree1.nodes
120+
.filter((t1n) => !mergedNodesT1.find((mtn1) => mtn1 === t1n))
121+
.filter((t) => t.data.type !== TypeSystemDefinition.SchemaDefinition);
120122
const t2Nodes = filteredTree2Nodes
121123
.filter((t2n) => !mergedNodesT2.find((mtn2) => mtn2 === t2n))
122-
.map((n) => ({ ...n, fromLibrary: true }));
124+
.map((n) => ({ ...n, fromLibrary: true }))
125+
.filter((t) => t.data.type !== TypeSystemDefinition.SchemaDefinition);
126+
127+
const schemaDefinitionT1Query = tree1.nodes
128+
.find((n) => n.data.type === TypeSystemDefinition.SchemaDefinition)
129+
?.args.find((a) => a.name === 'query');
130+
const schemaDefinitionT1QueryName =
131+
schemaDefinitionT1Query?.type.fieldType.type === Options.name && schemaDefinitionT1Query?.type.fieldType.name;
132+
const queryNodeT1 =
133+
schemaDefinitionT1QueryName ||
134+
tree1.nodes.find((n) => n.data.type === TypeDefinition.ObjectTypeDefinition && n.name === 'Query')?.name;
135+
136+
const schemaDefinitionT2Query = tree2.nodes
137+
.find((n) => n.data.type === TypeSystemDefinition.SchemaDefinition)
138+
?.args.find((a) => a.name === 'query');
139+
const schemaDefinitionT2QueryName =
140+
schemaDefinitionT2Query?.type.fieldType.type === Options.name && schemaDefinitionT2Query?.type.fieldType.name;
141+
const queryNodeT2 =
142+
schemaDefinitionT2QueryName ||
143+
tree2.nodes.find((n) => n.data.type === TypeDefinition.ObjectTypeDefinition && n.name === 'Query')?.name;
144+
145+
const schemaDefinitionT1Mutation = tree1.nodes
146+
.find((n) => n.data.type === TypeSystemDefinition.SchemaDefinition)
147+
?.args.find((a) => a.name === 'mutation');
148+
const schemaDefinitionT1MutationName =
149+
schemaDefinitionT1Mutation?.type.fieldType.type === Options.name && schemaDefinitionT1Mutation?.type.fieldType.name;
150+
const mutationNodeT1 =
151+
schemaDefinitionT1MutationName ||
152+
tree1.nodes.find((n) => n.data.type === TypeDefinition.ObjectTypeDefinition && n.name === 'Mutation')?.name;
153+
154+
const schemaDefinitionT2Mutation = tree2.nodes
155+
.find((n) => n.data.type === TypeSystemDefinition.SchemaDefinition)
156+
?.args.find((a) => a.name === 'mutation');
157+
const schemaDefinitionT2MutationName =
158+
schemaDefinitionT2Mutation?.type.fieldType.type === Options.name && schemaDefinitionT2Mutation?.type.fieldType.name;
159+
const mutationNodeT2 =
160+
schemaDefinitionT2MutationName ||
161+
tree2.nodes.find((n) => n.data.type === TypeDefinition.ObjectTypeDefinition && n.name === 'Mutation')?.name;
162+
163+
const schemaDefinitionT1Subscription = tree1.nodes
164+
.find((n) => n.data.type === TypeSystemDefinition.SchemaDefinition)
165+
?.args.find((a) => a.name === 'subscription');
166+
const schemaDefinitionT1SubscriptionName =
167+
schemaDefinitionT1Subscription?.type.fieldType.type === Options.name &&
168+
schemaDefinitionT1Subscription?.type.fieldType.name;
169+
const subscriptionNodeT1 =
170+
schemaDefinitionT1SubscriptionName ||
171+
tree1.nodes.find((n) => n.data.type === TypeDefinition.ObjectTypeDefinition && n.name === 'Subscription')?.name;
172+
173+
const schemaDefinitionT2Subscription = tree2.nodes
174+
.find((n) => n.data.type === TypeSystemDefinition.SchemaDefinition)
175+
?.args.find((a) => a.name === 'subscription');
176+
const schemaDefinitionT2SubscriptionName =
177+
schemaDefinitionT2Subscription?.type.fieldType.type === Options.name &&
178+
schemaDefinitionT2Subscription?.type.fieldType.name;
179+
const subscriptionNodeT2 =
180+
schemaDefinitionT2SubscriptionName ||
181+
tree2.nodes.find((n) => n.data.type === TypeDefinition.ObjectTypeDefinition && n.name === 'Subscription')?.name;
182+
183+
if (queryNodeT1 && queryNodeT2) {
184+
if (queryNodeT1 !== queryNodeT2) {
185+
return {
186+
__typename: 'error' as const,
187+
errors: [
188+
{
189+
conflictingNode: 'Schema',
190+
conflictingField: 'query',
191+
},
192+
],
193+
};
194+
}
195+
}
196+
if (mutationNodeT1 && mutationNodeT2) {
197+
if (mutationNodeT1 !== mutationNodeT2) {
198+
return {
199+
__typename: 'error' as const,
200+
errors: [
201+
{
202+
conflictingNode: 'Schema',
203+
conflictingField: 'mutation',
204+
},
205+
],
206+
};
207+
}
208+
}
209+
if (subscriptionNodeT1 && subscriptionNodeT2) {
210+
if (subscriptionNodeT1 !== subscriptionNodeT2) {
211+
return {
212+
__typename: 'error' as const,
213+
errors: [
214+
{
215+
conflictingNode: 'Schema',
216+
conflictingField: 'subscription',
217+
},
218+
],
219+
};
220+
}
221+
}
222+
const resultSchemaDefinitionNode: ParserField = createSchemaDefinition({
223+
operations: {
224+
...(queryNodeT1 && { query: queryNodeT1 }),
225+
...(mutationNodeT1 && { mutation: mutationNodeT1 }),
226+
...(subscriptionNodeT1 && { subscription: subscriptionNodeT1 }),
227+
...(queryNodeT2 && { query: queryNodeT2 }),
228+
...(mutationNodeT2 && { mutation: mutationNodeT2 }),
229+
...(subscriptionNodeT2 && { subscription: subscriptionNodeT2 }),
230+
},
231+
});
123232
return {
124233
__typename: 'success' as const,
125-
nodes: [...t1Nodes, ...mergeResultNodes, ...t2Nodes],
234+
nodes: [
235+
...t1Nodes,
236+
...mergeResultNodes.filter((t) => t.data.type !== TypeSystemDefinition.SchemaDefinition),
237+
...t2Nodes,
238+
...(resultSchemaDefinitionNode.args.length ? [resultSchemaDefinitionNode] : []),
239+
],
126240
};
127241
};
128242

129243
export const mergeSDLs = (sdl1: string, sdl2: string) => {
130244
const t1 = Parser.parse(sdl1);
131245
const t2 = Parser.parse(sdl2);
132-
const mergeResult = mergeTrees(t1, {
133-
nodes: t2.nodes.filter((n) => n.data.type !== TypeSystemDefinition.SchemaDefinition),
134-
});
246+
// find query node in t1
247+
const mergeResult = mergeTrees(
248+
{
249+
nodes: [...t1.nodes],
250+
},
251+
{
252+
nodes: [...t2.nodes],
253+
},
254+
);
135255
if (mergeResult.__typename === 'success') {
136256
const sdl = TreeToGraphQL.parse(mergeResult);
137257
return {

src/__tests__/TreeOperations/merge/merge.spec.ts

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -119,22 +119,7 @@ describe('Merging GraphQL Schemas', () => {
119119
}
120120
`;
121121
const t1 = mergeSDLs(baseSchema, mergingSchema);
122-
if (t1.__typename === 'error') throw new Error('Invalid parse');
123-
expectTrimmedEqual(
124-
t1.sdl,
125-
`
126-
type DDD{
127-
firstName: String
128-
health: String
129-
}
130-
schema{
131-
query: DDD
132-
}
133-
type Query{
134-
lastName: String
135-
}
136-
`,
137-
);
122+
expect(t1.__typename).toEqual('error');
138123
});
139124
it('Should merge schemas but maintain original schema node', () => {
140125
const baseSchema = `
@@ -156,24 +141,6 @@ describe('Merging GraphQL Schemas', () => {
156141
}
157142
`;
158143
const t1 = mergeSDLs(baseSchema, mergingSchema);
159-
if (t1.__typename === 'error') throw new Error('Invalid parse');
160-
expectTrimmedEqual(
161-
t1.sdl,
162-
`
163-
type DDD{
164-
firstName: String
165-
health: String
166-
}
167-
schema{
168-
query: DDD
169-
}
170-
type Query{
171-
lastName: String
172-
}
173-
type Mutation{
174-
ddd: String
175-
}
176-
`,
177-
);
144+
expect(t1.__typename).toEqual('error');
178145
});
179146
});

0 commit comments

Comments
 (0)