8000 Allow schema diff to use SDL document rather than requiring introspec… · graphql-java/graphql-java@4b8537f · GitHub 8000
[go: up one dir, main page]

Skip to content

Commit 4b8537f

Browse files
committed
Allow schema diff to use SDL document rather than requiring introspection result in order to enforce directives in schema diff
1 parent aae3069 commit 4b8537f

File tree

6 files changed

+509
-234
lines changed

6 files changed

+509
-234
lines changed

src/main/java/graphql/schema/diff/DiffSet.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
package graphql.schema.diff;
22

3-
import graphql.Assert;
4-
import graphql.ExecutionResult;
5-
import graphql.GraphQL;
6-
import graphql.PublicApi;
3+
import graphql.*;
74
import graphql.introspection.IntrospectionQuery;
5+
import graphql.introspection.IntrospectionResultToSchema;
6+
import graphql.language.Document;
87
import graphql.schema.GraphQLSchema;
98

109
import java.util.Map;
@@ -15,6 +14,8 @@
1514
* {@link graphql.introspection.IntrospectionQuery}.
1615
*/
1716
@PublicApi
17+
@Deprecated
18+
@DeprecatedAt("2023-10-04")
1819
public class DiffSet {
1920

2021
private final Map<String, Object> introspectionOld;
@@ -39,7 +40,6 @@ public Map<String, Object> getNew() {
3940
return introspectionNew;
4041
}
4142

42-
4343
/**
4444
* Creates a diff set out of the result of 2 introspection queries.
4545
*
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package graphql.schema.diff;
2+
3+
import graphql.Assert;
4+
import graphql.ExecutionResult;
5+
import graphql.GraphQL;
6+
import graphql.PublicApi;
7+
import graphql.introspection.IntrospectionQuery;
8+
import graphql.introspection.IntrospectionResultToSchema;
9+
import graphql.language.Document;
10+
import graphql.schema.GraphQLSchema;
11+
12+
import java.util.Map;
13+
14+
/**
15+
* Represents 2 schemas that can be diffed. The {@link SchemaDiff} code
16+
* assumes that that schemas to be diffed are the result of a
17+
* {@link graphql.introspection.IntrospectionQuery}.
18+
*/
19+
@PublicApi
20+
public class IntrospectionSchemaDiffSet implements SchemaDiffSet {
21+
22+
private final Map<String, Object> introspectionOld;
23+
private final Map<String, Object> introspectionNew;
24+
25+
public IntrospectionSchemaDiffSet(Map<String, Object> introspectionOld, Map<String, Object> introspectionNew) {
26+
this.introspectionOld = introspectionOld;
27+
this.introspectionNew = introspectionNew;
28+
}
29+
30+
/**
31+
* @return The IDL Document representing the old schema as defined by the old introspection result map.
32+
*/
33+
@Override
34+
public Document getOldSchemaDefinitionDoc() {
35+
return new IntrospectionResultToSchema().createSchemaDefinition(this.introspectionOld);
36+
}
37+
38+
/**
39+
* @return The IDL Document representing the new schema as defined by the new introspection result map.
40+
*/
41+
@Override
42+
public Document getNewSchemaDefinitionDoc() {
43+
return new IntrospectionResultToSchema().createSchemaDefinition(this.introspectionNew);
44+
}
45+
46+
/**
47+
* Since introspection does not identify what directives are applied on which schema elements, this diff set does not
48+
* support enforcing directives.
49+
* @return False
50+
*/
51+
@Override
52+
public boolean supportsEnforcingDirectives() {
53+
return false;
54+
}
55+
56+
/**
57+
* Creates an introspection schema diff set out of the result of 2 introspection queries.
58+
*
59+
* @param introspectionOld the older introspection query
60+
* @param introspectionNew the newer introspection query
61+
*
62+
* @return a diff set representing them
63+
*/
64+
public static IntrospectionSchemaDiffSet diffSet(Map<String, Object> introspectionOld, Map<String, Object> introspectionNew) {
65+
return new IntrospectionSchemaDiffSet(introspectionOld, introspectionNew);
66+
}
67+
68+
/**
69+
* Creates an introspection schema diff set out of the result of 2 schemas.
70+
*
71+
* @param schemaOld the older schema
72+
* @param schemaNew the newer schema
73+
*
74+
* @return a diff set representing them
75+
*/
76+
public static IntrospectionSchemaDiffSet diffSet(GraphQLSchema schemaOld, GraphQLSchema schemaNew) {
77+
Map<String, Object> introspectionOld = introspect(schemaOld);
78+
Map<String, Object> introspectionNew = introspect(schemaNew);
79+
return diffSet(introspectionOld, introspectionNew);
80+
}
81+
82+
private static Map<String, Object> introspect(GraphQLSchema schema) {
83+
GraphQL gql = GraphQL.newGraphQL(schema).build();
84+
ExecutionResult result = gql.execute(IntrospectionQuery.INTROSPECTION_QUERY);
85+
Assert.assertTrue(result.getErrors().size() == 0, () -> "The schema has errors during Introspection");
86+
return result.getData();
87+
}
88+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package graphql.schema.diff;
2+
3+
import graphql.PublicApi;
4+
import graphql.language.Document;
5+
import graphql.parser.Parser;
6+
import graphql.schema.GraphQLSchema;
7+
import graphql.schema.idl.SchemaPrinter;
8+
9+
/**
10+
* Represents 2 schemas that can be diffed which are defined in SDL.
11+
*/
12+
@PublicApi
13+
public class SDLSchemaDiffSet implements SchemaDiffSet {
14+
15+
private final String oldSchemaSdl;
16+
17+
private final String newSchemaSdl;
18+
19+
public SDLSchemaDiffSet(final String oldSchemaSdl, final String newSchemaSdl) {
20+
this.oldSchemaSdl = oldSchemaSdl;
21+
this.newSchemaSdl = newSchemaSdl;
22+
}
23+
24+
/**
25+
* @return The IDL Document representing the old schema as defined by the old schema sdl.
26+
*/
27+
@Override
28+
public Document getOldSchemaDefinitionDoc() {
29+
return Parser.parse(this.oldSchemaSdl);
30+
}
31+
32+
/**
33+
* @return The IDL Document representing the old schema as defined by the new schema sdl.
34+
*/
35+
@Override
36+
public Document getNewSchemaDefinitionDoc() {
37+
return Parser.parse(this.newSchemaSdl);
38+
}
39+
40+
/**
41+
* Since SDL will identify which directives are applied on elements in the schema, this diff set supports enforcing
42+
* directives.
43+
* @return True
44+
*/
45+
@Override
46+
public boolean supportsEnforcingDirectives() {
47+
return true;
48+
}
49+
50+
/**
51+
* Creates an sdl schema diff set out of the two sdl definitions.
52+
*
53+
* @param oldSchemaSdl the older schema sdl string.
54+
* @param newSchemaSdl the newer schema sdl string.
55+
*
56+
* @return a diff set representing them
57+
*/
58+
public static SDLSchemaDiffSet diffSet(String oldSchemaSdl, String newSchemaSdl) {
59+
return new SDLSchemaDiffSet(oldSchemaSdl, newSchemaSdl);
60+
}
61+
62+
/**
63+
* Creates an introspection schema diff set out of the result of 2 schemas.
64+
*
65+
* @param schemaOld the older schema
66+
* @param schemaNew the newer schema
67+
*
68+
* @return a diff set representing them
69+
*/
70+
public static SDLSchemaDiffSet diffSet(GraphQLSchema schemaOld, GraphQLSchema schemaNew) {
71+
SchemaPrinter printer = new SchemaPrinter(SchemaPrinter.Options.defaultOptions());
72+
return diffSet(printer.print(schemaOld), printer.print(schemaNew));
73+
}
74+
}

src/main/java/graphql/schema/diff/SchemaDiff.java

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package graphql.schema.diff;
22

3+
import graphql.Assert;
4+
import graphql.DeprecatedAt;
35
import graphql.PublicSpi;
46
import graphql.introspection.IntrospectionResultToSchema;
57
import graphql.language.Argument;
@@ -119,27 +121,43 @@ public SchemaDiff(Options options) {
119121
*
120122
* @return the number of API breaking changes
121123
*/
124+
@Deprecated
125+
@DeprecatedAt("2023-10-04")
122126
@SuppressWarnings("unchecked")
123127
public int diffSchema(DiffSet diffSet, DifferenceReporter reporter) {
124-
125128
CountingReporter countingReporter = new CountingReporter(reporter);
126-
diffSchemaImpl(diffSet, countingReporter);
129+
Document oldDoc = new IntrospectionResultToSchema().createSchemaDefinition(diffSet.getOld());
130+
Document newDoc = new IntrospectionResultToSchema().createSchemaDefinition(diffSet.getNew());
131+
diffSchemaImpl(oldDoc, newDoc, countingReporter);
127132
return countingReporter.breakingCount;
128133
}
129134

130-
private void diffSchemaImpl(DiffSet diffSet, DifferenceReporter reporter) {
131-
Map<String, Object> oldApi = diffSet.getOld();
132-
Map<String, Object> newApi = diffSet.getNew();
135+
/**
136+
* This will perform a difference on the two schemas. The reporter callback
137+
* interface will be called when differences are encountered.
138+
*
139+
* @param schemaDiffSet the two schemas to compare for difference
140+
* @param reporter the place to report difference events to
141+
*
142+
* @return the number of API breaking changes
143+
*/
144+
@SuppressWarnings("unchecked")
145+
public int diffSchema(SchemaDiffSet schemaDiffSet, DifferenceReporter reporter) {
146+
if (options.enforceDirectives) {
147+
Assert.assertTrue(schemaDiffSet.supportsEnforcingDirectives(), () ->
148+
"The provided schema diff set implementation does not supporting enforcing directives during schema diff.");
149+
}
133150

134-
Document oldDoc = new IntrospectionResultToSchema().createSchemaDefinition(oldApi);
135-
Document newDoc = new IntrospectionResultToSchema().createSchemaDefinition(newApi);
151+
CountingReporter countingReporter = new CountingReporter(reporter);
152+
diffSchemaImpl(schemaDiffSet.getOldSchemaDefinitionDoc(), schemaDiffSet.getNewSchemaDefinitionDoc(), countingReporter);
153+
return countingReporter.breakingCount;
154+
}
136155

156+
private void diffSchemaImpl(Document oldDoc, Document newDoc, DifferenceReporter reporter) {
137157
DiffCtx ctx = new DiffCtx(reporter, oldDoc, newDoc);
138-
139158
Optional<SchemaDefinition> oldSchemaDef = getSchemaDef(oldDoc);
140159
Optional<SchemaDefinition> newSchemaDef = getSchemaDef(newDoc);
141160

142-
143161
// check query operation
144162
checkOperation(ctx, "query", oldSchemaDef, newSchemaDef);
145163
checkOperation(ctx, "mutation", oldSchemaDef, newSchemaDef);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package graphql.schema.diff;
2+
3+
import graphql.PublicApi;
4+
import graphql.language.Document;
5+
6+
/**
7+
* Interface used to define 2 schemas that can be diffed by the {@link SchemaDiff} operation.
8+
*/
9+
@PublicApi
10+
public interface SchemaDiffSet {
11+
12+
/**
13+
* @return Returns a IDL document that represents the old schema as part of a SchemaDiff operation.
14+
*/
15+
Document getOldSchemaDefinitionDoc();
16+
17+
/**
18+
* @return Returns a IDL document that represents the new schema created from the introspection result.
19+
*/
20+
Document getNewSchemaDefinitionDoc();
21+
22+
/**
23+
* @return Flag indicating whether this diffset implementation can be used to enforce directives when performing schema diff.
24+
*/
25+
boolean supportsEnforcingDirectives();
26+
}

0 commit comments

Comments
 (0)
0