graphql-schema_comparator 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/lib/graphql/schema_comparator.rb +13 -1
- data/lib/graphql/schema_comparator/changes.rb +381 -113
- data/lib/graphql/schema_comparator/diff/directive.rb +63 -0
- data/lib/graphql/schema_comparator/diff/directive_argument.rb +37 -0
- data/lib/graphql/schema_comparator/diff/field.rb +0 -2
- data/lib/graphql/schema_comparator/diff/has_directives.rb +0 -0
- data/lib/graphql/schema_comparator/diff/schema.rb +32 -12
- data/lib/graphql/schema_comparator/result.rb +2 -2
- data/lib/graphql/schema_comparator/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de7ab5aa8da6dcfe86369cab4a4278f4e243365e
|
4
|
+
data.tar.gz: a0cf175638ba9b983a793555514c3c51a91c6725
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc5dd38fb9f71124dd18323a1ceb8e123994476bee91a134854140e160075a515c0975fb60fc662d918ea7deac6e0b6c48a015da5afb53a14191a22de8514837
|
7
|
+
data.tar.gz: c9f9ca7b7672748246ee7519b35e06f36b49ad55fba891699249de86107518fac2f0033afe22e2ae8529b5d4f9b9ba17a31aa701a977ab9a9ae8bcdf9ba2d095
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.3.0 (Oct 14 2017)
|
4
|
+
|
5
|
+
### New features
|
6
|
+
|
7
|
+
- Top level Directive definitions are now diffed, but not directives used on definitions (Coming soon)
|
8
|
+
- Base class for changes added.
|
9
|
+
|
10
|
+
### breaking changes
|
11
|
+
|
12
|
+
- `breaking` method on change objects has been renamed `breaking?` for style
|
13
|
+
|
14
|
+
### Bug fixes
|
15
|
+
|
16
|
+
- Fix message for `EnumValueRemoved` (#5)
|
17
|
+
|
3
18
|
## 0.2.0 (Aug 18 2017)
|
4
19
|
|
5
20
|
### New features
|
@@ -1,9 +1,21 @@
|
|
1
1
|
require "graphql"
|
2
|
+
|
2
3
|
require "graphql/schema_comparator/version"
|
3
|
-
require "graphql/schema_comparator/diff/schema"
|
4
4
|
require "graphql/schema_comparator/changes"
|
5
5
|
require "graphql/schema_comparator/result"
|
6
6
|
|
7
|
+
require "graphql/schema_comparator/diff/schema"
|
8
|
+
require "graphql/schema_comparator/diff/argument"
|
9
|
+
require "graphql/schema_comparator/diff/directive"
|
10
|
+
require "graphql/schema_comparator/diff/directive_argument"
|
11
|
+
require "graphql/schema_comparator/diff/enum"
|
12
|
+
require "graphql/schema_comparator/diff/field"
|
13
|
+
require "graphql/schema_comparator/diff/input_object"
|
14
|
+
require "graphql/schema_comparator/diff/input_field"
|
15
|
+
require "graphql/schema_comparator/diff/object_type"
|
16
|
+
require "graphql/schema_comparator/diff/interface"
|
17
|
+
require "graphql/schema_comparator/diff/union"
|
18
|
+
|
7
19
|
module GraphQL
|
8
20
|
module SchemaComparator
|
9
21
|
def self.compare(old_schema, new_schema)
|
@@ -1,36 +1,52 @@
|
|
1
1
|
module GraphQL
|
2
2
|
module SchemaComparator
|
3
3
|
module Changes
|
4
|
-
|
4
|
+
class AbstractChange
|
5
|
+
def message
|
6
|
+
raise NotImplementedError
|
7
|
+
end
|
8
|
+
|
9
|
+
def breaking?
|
10
|
+
raise NotImplementedError
|
11
|
+
end
|
12
|
+
end
|
5
13
|
|
6
|
-
class TypeRemoved
|
7
|
-
attr_reader :removed_type
|
14
|
+
class TypeRemoved < AbstractChange
|
15
|
+
attr_reader :removed_type
|
8
16
|
|
9
17
|
def initialize(removed_type)
|
10
18
|
@removed_type = removed_type
|
11
19
|
@breaking = true
|
12
20
|
end
|
13
21
|
|
22
|
+
def breaking?
|
23
|
+
!!@breaking
|
24
|
+
end
|
25
|
+
|
14
26
|
def message
|
15
|
-
"
|
27
|
+
"`#{removed_type.name}` was removed"
|
16
28
|
end
|
17
29
|
end
|
18
30
|
|
19
|
-
class DirectiveRemoved
|
20
|
-
attr_reader :
|
31
|
+
class DirectiveRemoved < AbstractChange
|
32
|
+
attr_reader :directive
|
21
33
|
|
22
|
-
def initialize(
|
23
|
-
@
|
34
|
+
def initialize(directive)
|
35
|
+
@directive = directive
|
24
36
|
@breaking = true
|
25
37
|
end
|
26
38
|
|
27
39
|
def message
|
28
|
-
"
|
40
|
+
"`#{directive.name}` was removed"
|
41
|
+
end
|
42
|
+
|
43
|
+
def breaking?
|
44
|
+
!!@breaking
|
29
45
|
end
|
30
46
|
end
|
31
47
|
|
32
|
-
class TypeKindChanged
|
33
|
-
attr_reader :old_type, :new_type
|
48
|
+
class TypeKindChanged < AbstractChange
|
49
|
+
attr_reader :old_type, :new_type
|
34
50
|
|
35
51
|
def initialize(old_type, new_type)
|
36
52
|
@old_type = old_type
|
@@ -41,10 +57,14 @@ module GraphQL
|
|
41
57
|
def message
|
42
58
|
"`#{old_type.name}` kind changed from `#{old_type.kind}` to `#{new_type.kind}`"
|
43
59
|
end
|
60
|
+
|
61
|
+
def breaking?
|
62
|
+
!!@breaking
|
63
|
+
end
|
44
64
|
end
|
45
65
|
|
46
|
-
class EnumValueRemoved
|
47
|
-
attr_reader :enum_value, :enum_type
|
66
|
+
class EnumValueRemoved < AbstractChange
|
67
|
+
attr_reader :enum_value, :enum_type
|
48
68
|
|
49
69
|
def initialize(enum_type, enum_value)
|
50
70
|
@enum_value = enum_value
|
@@ -55,10 +75,14 @@ module GraphQL
|
|
55
75
|
def message
|
56
76
|
"Enum value `#{enum_value.name}` was removed from enum `#{enum_type.name}`"
|
57
77
|
end
|
78
|
+
|
79
|
+
def breaking?
|
80
|
+
!!@breaking
|
81
|
+
end
|
58
82
|
end
|
59
83
|
|
60
|
-
class UnionMemberRemoved
|
61
|
-
attr_reader :union_type, :union_member
|
84
|
+
class UnionMemberRemoved < AbstractChange
|
85
|
+
attr_reader :union_type, :union_member
|
62
86
|
|
63
87
|
def initialize(union_type, union_member)
|
64
88
|
@union_member = union_member
|
@@ -69,10 +93,14 @@ module GraphQL
|
|
69
93
|
def message
|
70
94
|
"Union member `#{union_member.name}` was removed from Union type `#{union_type.name}`"
|
71
95
|
end
|
96
|
+
|
97
|
+
def breaking?
|
98
|
+
!!@breaking
|
99
|
+
end
|
72
100
|
end
|
73
101
|
|
74
|
-
class InputFieldRemoved
|
75
|
-
attr_reader :input_object_type, :field
|
102
|
+
class InputFieldRemoved < AbstractChange
|
103
|
+
attr_reader :input_object_type, :field
|
76
104
|
|
77
105
|
def initialize(input_object_type, field)
|
78
106
|
@input_object_type = input_object_type
|
@@ -83,10 +111,14 @@ module GraphQL
|
|
83
111
|
def message
|
84
112
|
"Input field `#{field.name}` was removed from input object type `#{input_object_type.name}`"
|
85
113
|
end
|
114
|
+
|
115
|
+
def breaking?
|
116
|
+
!!@breaking
|
117
|
+
end
|
86
118
|
end
|
87
119
|
|
88
|
-
class FieldArgumentRemoved
|
89
|
-
attr_reader :object_type, :field, :argument
|
120
|
+
class FieldArgumentRemoved < AbstractChange
|
121
|
+
attr_reader :object_type, :field, :argument
|
90
122
|
|
91
123
|
def initialize(object_type, field, argument)
|
92
124
|
@object_type = object_type
|
@@ -98,14 +130,32 @@ module GraphQL
|
|
98
130
|
def message
|
99
131
|
"Argument `#{argument.name}: #{argument.type}` was removed from field `#{object_type.name}.#{field.name}`"
|
100
132
|
end
|
133
|
+
|
134
|
+
def breaking?
|
135
|
+
!!@breaking
|
136
|
+
end
|
101
137
|
end
|
102
138
|
|
103
|
-
|
104
|
-
|
105
|
-
|
139
|
+
class DirectiveArgumentRemoved < AbstractChange
|
140
|
+
attr_reader :directive, :argument
|
141
|
+
|
142
|
+
def initialize(directive, argument)
|
143
|
+
@directive = directive
|
144
|
+
@argument = argument
|
145
|
+
@breaking = true
|
146
|
+
end
|
106
147
|
|
107
|
-
|
108
|
-
|
148
|
+
def message
|
149
|
+
"Argument `#{argument.name}` was removed from directive `#{directive.name}`"
|
150
|
+
end
|
151
|
+
|
152
|
+
def breaking?
|
153
|
+
!!@breaking
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
class SchemaQueryTypeChanged < AbstractChange
|
158
|
+
attr_reader :old_schema, :new_schema
|
109
159
|
|
110
160
|
def initialize(old_schema, new_schema)
|
111
161
|
@old_schema = old_schema
|
@@ -116,10 +166,14 @@ module GraphQL
|
|
116
166
|
def message
|
117
167
|
"Schema query root has changed from `#{old_schema.query.name}` to `#{new_schema.query.name}`"
|
118
168
|
end
|
169
|
+
|
170
|
+
def breaking?
|
171
|
+
!!@breaking
|
172
|
+
end
|
119
173
|
end
|
120
174
|
|
121
|
-
class FieldRemoved
|
122
|
-
attr_reader :object_type, :field
|
175
|
+
class FieldRemoved < AbstractChange
|
176
|
+
attr_reader :object_type, :field
|
123
177
|
|
124
178
|
def initialize(object_type, field)
|
125
179
|
@object_type = object_type
|
@@ -130,14 +184,32 @@ module GraphQL
|
|
130
184
|
def message
|
131
185
|
"Field `#{field.name}` was removed from object type `#{object_type.name}`"
|
132
186
|
end
|
187
|
+
|
188
|
+
def breaking?
|
189
|
+
!!@breaking
|
190
|
+
end
|
133
191
|
end
|
134
192
|
|
135
|
-
|
136
|
-
|
137
|
-
|
193
|
+
class DirectiveLocationRemoved < AbstractChange
|
194
|
+
attr_reader :directive, :location
|
195
|
+
|
196
|
+
def initialize(directive, location)
|
197
|
+
@directive = directive
|
198
|
+
@location = location
|
199
|
+
@breaking = true
|
200
|
+
end
|
201
|
+
|
202
|
+
def message
|
203
|
+
"Location `#{location}` was removed from directive `#{directive.name}`"
|
204
|
+
end
|
205
|
+
|
206
|
+
def breaking?
|
207
|
+
!!@breaking
|
208
|
+
end
|
209
|
+
end
|
138
210
|
|
139
|
-
class ObjectTypeInterfaceRemoved
|
140
|
-
attr_reader :interface, :object_type
|
211
|
+
class ObjectTypeInterfaceRemoved < AbstractChange
|
212
|
+
attr_reader :interface, :object_type
|
141
213
|
|
142
214
|
def initialize(interface, object_type)
|
143
215
|
@interface = interface
|
@@ -148,12 +220,14 @@ module GraphQL
|
|
148
220
|
def message
|
149
221
|
"`#{object_type.name}` object type no longer implements `#{interface.name}` interface"
|
150
222
|
end
|
151
|
-
end
|
152
223
|
|
153
|
-
|
224
|
+
def breaking?
|
225
|
+
!!@breaking
|
226
|
+
end
|
227
|
+
end
|
154
228
|
|
155
|
-
class TypeAdded
|
156
|
-
attr_reader :type
|
229
|
+
class TypeAdded < AbstractChange
|
230
|
+
attr_reader :type
|
157
231
|
|
158
232
|
def initialize(type)
|
159
233
|
@type = type
|
@@ -163,18 +237,31 @@ module GraphQL
|
|
163
237
|
def message
|
164
238
|
"Type `#{type.name}` was added"
|
165
239
|
end
|
240
|
+
|
241
|
+
def breaking?
|
242
|
+
!!@breaking
|
243
|
+
end
|
166
244
|
end
|
167
245
|
|
168
|
-
class DirectiveAdded
|
169
|
-
attr_reader :
|
246
|
+
class DirectiveAdded < AbstractChange
|
247
|
+
attr_reader :directive
|
170
248
|
|
171
|
-
def initialize(
|
249
|
+
def initialize(directive)
|
250
|
+
@directive = directive
|
172
251
|
@breaking = false
|
173
252
|
end
|
253
|
+
|
254
|
+
def message
|
255
|
+
"Directive `#{directive.name}` was added"
|
256
|
+
end
|
257
|
+
|
258
|
+
def breaking?
|
259
|
+
!!@breaking
|
260
|
+
end
|
174
261
|
end
|
175
262
|
|
176
|
-
class TypeDescriptionChanged
|
177
|
-
attr_reader :old_type, :new_type
|
263
|
+
class TypeDescriptionChanged < AbstractChange
|
264
|
+
attr_reader :old_type, :new_type
|
178
265
|
|
179
266
|
def initialize(old_type, new_type)
|
180
267
|
@old_type = old_type
|
@@ -185,10 +272,14 @@ module GraphQL
|
|
185
272
|
def message
|
186
273
|
"Description `#{old_type.description}` on type `#{old_type.name}` has changed to `#{new_type.description}`"
|
187
274
|
end
|
275
|
+
|
276
|
+
def breaking?
|
277
|
+
!!@breaking
|
278
|
+
end
|
188
279
|
end
|
189
280
|
|
190
|
-
class EnumValueAdded
|
191
|
-
attr_reader :enum_type, :enum_value
|
281
|
+
class EnumValueAdded < AbstractChange
|
282
|
+
attr_reader :enum_type, :enum_value
|
192
283
|
|
193
284
|
def initialize(enum_type, enum_value)
|
194
285
|
@enum_type = enum_type
|
@@ -199,20 +290,26 @@ module GraphQL
|
|
199
290
|
def message
|
200
291
|
"Enum value `#{enum_value.name}` was added to enum `#{enum_type.name}`"
|
201
292
|
end
|
293
|
+
|
294
|
+
def breaking?
|
295
|
+
!!@breaking
|
296
|
+
end
|
202
297
|
end
|
203
298
|
|
204
|
-
|
299
|
+
# TODO
|
300
|
+
class EnumValueDescriptionChanged < AbstractChange
|
205
301
|
def initialize(*)
|
206
302
|
end
|
207
303
|
end
|
208
304
|
|
209
|
-
|
305
|
+
# TODO
|
306
|
+
class EnumValueDeprecated < AbstractChange
|
210
307
|
def initialize(*)
|
211
308
|
end
|
212
309
|
end
|
213
310
|
|
214
|
-
class UnionMemberAdded
|
215
|
-
attr_reader :union_type, :union_member
|
311
|
+
class UnionMemberAdded < AbstractChange
|
312
|
+
attr_reader :union_type, :union_member
|
216
313
|
|
217
314
|
def initialize(union_type, union_member)
|
218
315
|
@union_member = union_member
|
@@ -223,10 +320,14 @@ module GraphQL
|
|
223
320
|
def message
|
224
321
|
"Union member `#{union_member.name}` was added to Union type `#{union_type.name}`"
|
225
322
|
end
|
323
|
+
|
324
|
+
def breaking?
|
325
|
+
!!@breaking
|
326
|
+
end
|
226
327
|
end
|
227
328
|
|
228
|
-
class InputFieldDescriptionChanged
|
229
|
-
attr_reader :input_type, :old_field, :new_field
|
329
|
+
class InputFieldDescriptionChanged < AbstractChange
|
330
|
+
attr_reader :input_type, :old_field, :new_field
|
230
331
|
|
231
332
|
def initialize(input_type, old_field, new_field)
|
232
333
|
@input_type = input_type
|
@@ -239,15 +340,33 @@ module GraphQL
|
|
239
340
|
"Input field `#{input_type.name}.#{old_field.name}` description changed"\
|
240
341
|
" from `#{old_field.description}` to `#{new_field.description}`"
|
241
342
|
end
|
343
|
+
|
344
|
+
def breaking?
|
345
|
+
!!@breaking
|
346
|
+
end
|
242
347
|
end
|
243
348
|
|
244
|
-
class DirectiveDescriptionChanged
|
245
|
-
|
349
|
+
class DirectiveDescriptionChanged < AbstractChange
|
350
|
+
attr_reader :old_directive, :new_directive
|
351
|
+
|
352
|
+
def initialize(old_directive, new_directive)
|
353
|
+
@old_directive = old_directive
|
354
|
+
@new_directive = new_directive
|
355
|
+
@breaking = false
|
356
|
+
end
|
357
|
+
|
358
|
+
def message
|
359
|
+
"Directive `#{new_directive.name}` description changed"\
|
360
|
+
" from `#{old_directive.description}` to `#{new_directive.description}`"
|
361
|
+
end
|
362
|
+
|
363
|
+
def breaking?
|
364
|
+
!!@breaking
|
246
365
|
end
|
247
366
|
end
|
248
367
|
|
249
|
-
class FieldDescriptionChanged
|
250
|
-
attr_reader :type, :old_field, :new_field
|
368
|
+
class FieldDescriptionChanged < AbstractChange
|
369
|
+
attr_reader :type, :old_field, :new_field
|
251
370
|
|
252
371
|
def initialize(type, old_field, new_field)
|
253
372
|
@type = type
|
@@ -260,10 +379,14 @@ module GraphQL
|
|
260
379
|
"Field `#{type.name}.#{old_field.name}` description changed"\
|
261
380
|
" from `#{old_field.description}` to `#{new_field.description}`"
|
262
381
|
end
|
382
|
+
|
383
|
+
def breaking?
|
384
|
+
!!@breaking
|
385
|
+
end
|
263
386
|
end
|
264
387
|
|
265
|
-
class FieldArgumentDescriptionChanged
|
266
|
-
attr_reader :type, :field, :old_argument, :new_argument
|
388
|
+
class FieldArgumentDescriptionChanged < AbstractChange
|
389
|
+
attr_reader :type, :field, :old_argument, :new_argument
|
267
390
|
|
268
391
|
def initialize(type, field, old_argument, new_argument)
|
269
392
|
@type = type
|
@@ -277,15 +400,34 @@ module GraphQL
|
|
277
400
|
"Description for argument `#{new_argument.name}` on field `#{type.name}.#{field.name}` changed"\
|
278
401
|
" from `#{old_argument.description}` to `#{new_argument.description}`"
|
279
402
|
end
|
403
|
+
|
404
|
+
def breaking?
|
405
|
+
!!@breaking
|
406
|
+
end
|
280
407
|
end
|
281
408
|
|
282
|
-
class DirectiveArgumentDescriptionChanged
|
283
|
-
|
409
|
+
class DirectiveArgumentDescriptionChanged < AbstractChange
|
410
|
+
attr_reader :directive, :old_argument, :new_argument
|
411
|
+
|
412
|
+
def initialize(directive, old_argument, new_argument)
|
413
|
+
@directive = directive
|
414
|
+
@old_argument = old_argument
|
415
|
+
@new_argument = new_argument
|
416
|
+
@breaking = false
|
417
|
+
end
|
418
|
+
|
419
|
+
def message
|
420
|
+
"Description for argument `#{new_argument.name}` on directive `#{directive.name}` changed"\
|
421
|
+
" from `#{old_argument.description}` to `#{new_argument.description}`"
|
422
|
+
end
|
423
|
+
|
424
|
+
def breaking?
|
425
|
+
!!@breaking
|
284
426
|
end
|
285
427
|
end
|
286
428
|
|
287
|
-
class FieldDeprecationChanged
|
288
|
-
attr_reader :type, :old_field, :new_field
|
429
|
+
class FieldDeprecationChanged < AbstractChange
|
430
|
+
attr_reader :type, :old_field, :new_field
|
289
431
|
|
290
432
|
def initialize(type, old_field, new_field)
|
291
433
|
@type = type
|
@@ -298,10 +440,14 @@ module GraphQL
|
|
298
440
|
"Deprecation reason on field `#{type.name}.#{new_field.name}` has changed "\
|
299
441
|
"from `#{old_field.deprecation_reason}` to `#{new_field.deprecation_reason}`"
|
300
442
|
end
|
443
|
+
|
444
|
+
def breaking?
|
445
|
+
!!@breaking
|
446
|
+
end
|
301
447
|
end
|
302
448
|
|
303
|
-
class InputFieldDefaultChanged
|
304
|
-
attr_reader :input_type, :old_field, :new_field
|
449
|
+
class InputFieldDefaultChanged < AbstractChange
|
450
|
+
attr_reader :input_type, :old_field, :new_field
|
305
451
|
|
306
452
|
def initialize(input_type, old_field, new_field)
|
307
453
|
@input_type = input_type
|
@@ -314,10 +460,14 @@ module GraphQL
|
|
314
460
|
"Input field `#{input_type.name}.#{old_field.name}` default changed"\
|
315
461
|
" from `#{old_field.default_value}` to `#{new_field.default_value}`"
|
316
462
|
end
|
463
|
+
|
464
|
+
def breaking?
|
465
|
+
!!@breaking
|
466
|
+
end
|
317
467
|
end
|
318
468
|
|
319
|
-
class FieldArgumentDefaultChanged
|
320
|
-
attr_reader :type, :field, :old_argument, :new_argument
|
469
|
+
class FieldArgumentDefaultChanged < AbstractChange
|
470
|
+
attr_reader :type, :field, :old_argument, :new_argument
|
321
471
|
|
322
472
|
def initialize(type, field, old_argument, new_argument)
|
323
473
|
@type = type
|
@@ -331,15 +481,34 @@ module GraphQL
|
|
331
481
|
"Default value for argument `#{new_argument.name}` on field `#{type.name}.#{field.name}` changed"\
|
332
482
|
" from `#{old_argument.default_value}` to `#{new_argument.default_value}`"
|
333
483
|
end
|
484
|
+
|
485
|
+
def breaking?
|
486
|
+
!!@breaking
|
487
|
+
end
|
334
488
|
end
|
335
489
|
|
336
|
-
class DirectiveArgumentDefaultChanged
|
337
|
-
|
490
|
+
class DirectiveArgumentDefaultChanged < AbstractChange
|
491
|
+
attr_reader :directive, :old_argument, :new_argument
|
492
|
+
|
493
|
+
def initialize(directive, old_argument, new_argument)
|
494
|
+
@directive = directive
|
495
|
+
@old_argument = old_argument
|
496
|
+
@new_argument = new_argument
|
497
|
+
@breaking = false
|
498
|
+
end
|
499
|
+
|
500
|
+
def message
|
501
|
+
"Default value for argument `#{new_argument.name}` on directive `#{directive.name}` changed"\
|
502
|
+
" from `#{old_argument.default_value}` to `#{new_argument.default_value}`"
|
503
|
+
end
|
504
|
+
|
505
|
+
def breaking?
|
506
|
+
!!@breaking
|
338
507
|
end
|
339
508
|
end
|
340
509
|
|
341
|
-
class ObjectTypeInterfaceAdded
|
342
|
-
attr_reader :interface, :object_type
|
510
|
+
class ObjectTypeInterfaceAdded < AbstractChange
|
511
|
+
attr_reader :interface, :object_type
|
343
512
|
|
344
513
|
def initialize(interface, object_type)
|
345
514
|
@interface = interface
|
@@ -350,10 +519,14 @@ module GraphQL
|
|
350
519
|
def message
|
351
520
|
"`#{object_type.name}` object implements `#{interface.name}` interface"
|
352
521
|
end
|
522
|
+
|
523
|
+
def breaking?
|
524
|
+
!!@breaking
|
525
|
+
end
|
353
526
|
end
|
354
527
|
|
355
|
-
class FieldAdded
|
356
|
-
attr_reader :object_type, :field
|
528
|
+
class FieldAdded < AbstractChange
|
529
|
+
attr_reader :object_type, :field
|
357
530
|
|
358
531
|
def initialize(object_type, field)
|
359
532
|
@object_type = object_type
|
@@ -364,137 +537,176 @@ module GraphQL
|
|
364
537
|
def message
|
365
538
|
"Field `#{field.name}` was added to object type `#{object_type.name}`"
|
366
539
|
end
|
540
|
+
|
541
|
+
def breaking?
|
542
|
+
!!@breaking
|
543
|
+
end
|
367
544
|
end
|
368
545
|
|
369
|
-
class DirectiveLocationAdded
|
370
|
-
|
546
|
+
class DirectiveLocationAdded < AbstractChange
|
547
|
+
attr_reader :directive, :location
|
548
|
+
|
549
|
+
def initialize(directive, location)
|
550
|
+
@directive = directive
|
551
|
+
@location = location
|
552
|
+
@breaking = false
|
553
|
+
end
|
554
|
+
|
555
|
+
def message
|
556
|
+
"Location `#{location}` was added to directive `#{directive.name}`"
|
557
|
+
end
|
558
|
+
|
559
|
+
def breaking?
|
560
|
+
!!@breaking
|
371
561
|
end
|
372
562
|
end
|
373
563
|
|
374
|
-
|
564
|
+
# TODO
|
565
|
+
class FieldAstDirectiveAdded < AbstractChange
|
375
566
|
def initialize(*)
|
376
567
|
end
|
377
568
|
end
|
378
569
|
|
379
|
-
|
570
|
+
# TODO
|
571
|
+
class FieldAstDirectiveRemoved < AbstractChange
|
380
572
|
def initialize(*)
|
381
573
|
end
|
382
574
|
end
|
383
575
|
|
384
|
-
|
576
|
+
# TODO
|
577
|
+
class EnumValueAstDirectiveAdded < AbstractChange
|
385
578
|
def initialize(*)
|
386
579
|
end
|
387
580
|
end
|
388
581
|
|
389
|
-
|
582
|
+
# TODO
|
583
|
+
class EnumValueAstDirectiveRemoved < AbstractChange
|
390
584
|
def initialize(*)
|
391
585
|
end
|
392
586
|
end
|
393
587
|
|
394
|
-
|
588
|
+
# TODO
|
589
|
+
class InputFieldAstDirectiveAdded < AbstractChange
|
395
590
|
def initialize(*)
|
396
591
|
end
|
397
592
|
end
|
398
593
|
|
399
|
-
|
594
|
+
# TODO
|
595
|
+
class InputFieldAstDirectiveRemoved < AbstractChange
|
400
596
|
def initialize(*)
|
401
597
|
end
|
402
598
|
end
|
403
599
|
|
404
|
-
|
600
|
+
# TODO
|
601
|
+
class DirectiveArgumentAstDirectiveAdded < AbstractChange
|
405
602
|
def initialize(*)
|
406
603
|
end
|
407
604
|
end
|
408
605
|
|
409
|
-
|
606
|
+
# TODO
|
607
|
+
class DirectiveArgumentAstDirectiveRemoved < AbstractChange
|
410
608
|
def initialize(*)
|
411
609
|
end
|
412
610
|
end
|
413
611
|
|
414
|
-
|
612
|
+
# TODO
|
613
|
+
class FieldArgumentAstDirectiveAdded < AbstractChange
|
415
614
|
def initialize(*)
|
416
615
|
end
|
417
616
|
end
|
418
617
|
|
419
|
-
|
618
|
+
# TODO
|
619
|
+
class FieldArgumentAstDirectiveRemoved < AbstractChange
|
420
620
|
def initialize(*)
|
421
621
|
end
|
422
622
|
end
|
423
623
|
|
424
|
-
|
624
|
+
# TODO
|
625
|
+
class ObjectTypeAstDirectiveAdded < AbstractChange
|
425
626
|
def initialize(*)
|
426
627
|
end
|
427
628
|
end
|
428
629
|
|
429
|
-
|
630
|
+
# TODO
|
631
|
+
class ObjectTypeAstDirectiveRemoved < AbstractChange
|
430
632
|
def initialize(*)
|
431
633
|
end
|
432
634
|
end
|
433
635
|
|
434
|
-
|
636
|
+
# TODO
|
637
|
+
class InterfaceTypeAstDirectiveAdded < AbstractChange
|
435
638
|
def initialize(*)
|
436
639
|
end
|
437
640
|
end
|
438
641
|
|
439
|
-
|
642
|
+
# TODO
|
643
|
+
class InterfaceTypeAstDirectiveRemoved < AbstractChange
|
440
644
|
def initialize(*)
|
441
645
|
end
|
442
646
|
end
|
443
647
|
|
444
|
-
|
648
|
+
# TODO
|
649
|
+
class UnionTypeAstDirectiveAdded < AbstractChange
|
445
650
|
def initialize(*)
|
446
651
|
end
|
447
652
|
end
|
448
653
|
|
449
|
-
|
654
|
+
# TODO
|
655
|
+
class UnionTypeAstDirectiveRemoved < AbstractChange
|
450
656
|
def initialize(*)
|
451
657
|
end
|
452
658
|
end
|
453
659
|
|
454
|
-
|
660
|
+
# TODO
|
661
|
+
class EnumTypeAstDirectiveAdded < AbstractChange
|
455
662
|
def initialize(*)
|
456
663
|
end
|
457
664
|
end
|
458
665
|
|
459
|
-
|
666
|
+
# TODO
|
667
|
+
class EnumTypeAstDirectiveRemoved < AbstractChange
|
460
668
|
def initialize(*)
|
461
669
|
end
|
462
670
|
end
|
463
671
|
|
464
|
-
|
672
|
+
# TODO
|
673
|
+
class ScalarTypeAstDirectiveAdded < AbstractChange
|
465
674
|
def initialize(*)
|
466
675
|
end
|
467
676
|
end
|
468
677
|
|
469
|
-
|
678
|
+
# TODO
|
679
|
+
class ScalarTypeAstDirectiveRemoved < AbstractChange
|
470
680
|
def initialize(*)
|
471
681
|
end
|
472
682
|
end
|
473
683
|
|
474
|
-
|
684
|
+
# TODO
|
685
|
+
class InputObjectTypeAstDirectiveAdded < AbstractChange
|
475
686
|
def initialize(*)
|
476
687
|
end
|
477
688
|
end
|
478
689
|
|
479
|
-
|
690
|
+
# TODO
|
691
|
+
class InputObjectTypeAstDirectiveRemoved < AbstractChange
|
480
692
|
def initialize(*)
|
481
693
|
end
|
482
694
|
end
|
483
695
|
|
484
|
-
|
696
|
+
# TODO
|
697
|
+
class SchemaAstDirectiveAdded < AbstractChange
|
485
698
|
def initialize(*)
|
486
699
|
end
|
487
700
|
end
|
488
701
|
|
489
|
-
|
702
|
+
# TODO
|
703
|
+
class SchemaAstDirectiveRemoved < AbstractChange
|
490
704
|
def initialize(*)
|
491
705
|
end
|
492
706
|
end
|
493
707
|
|
494
|
-
|
495
|
-
|
496
|
-
class InputFieldAdded
|
497
|
-
attr_reader :input_object_type, :field, :breaking
|
708
|
+
class InputFieldAdded < AbstractChange
|
709
|
+
attr_reader :input_object_type, :field
|
498
710
|
|
499
711
|
def initialize(input_object_type, field)
|
500
712
|
@input_object_type = input_object_type
|
@@ -505,10 +717,14 @@ module GraphQL
|
|
505
717
|
def message
|
506
718
|
"Input field `#{field.name}` was added to input object type `#{input_object_type.name}`"
|
507
719
|
end
|
720
|
+
|
721
|
+
def breaking?
|
722
|
+
!!@breaking
|
723
|
+
end
|
508
724
|
end
|
509
725
|
|
510
|
-
class FieldArgumentAdded
|
511
|
-
attr_reader :type, :field, :argument
|
726
|
+
class FieldArgumentAdded < AbstractChange
|
727
|
+
attr_reader :type, :field, :argument
|
512
728
|
|
513
729
|
def initialize(type, field, argument)
|
514
730
|
@type = type
|
@@ -521,15 +737,32 @@ module GraphQL
|
|
521
737
|
def message
|
522
738
|
"Argument `#{argument.name}: #{argument.type}` added to field `#{type.name}.#{field.name}`"
|
523
739
|
end
|
740
|
+
|
741
|
+
def breaking?
|
742
|
+
!!@breaking
|
743
|
+
end
|
524
744
|
end
|
525
745
|
|
526
|
-
class DirectiveArgumentAdded
|
527
|
-
|
746
|
+
class DirectiveArgumentAdded < AbstractChange
|
747
|
+
attr_reader :directive, :argument
|
748
|
+
|
749
|
+
def initialize(directive, argument)
|
750
|
+
@directive = directive
|
751
|
+
@argument = argument
|
752
|
+
@breaking = false
|
753
|
+
end
|
754
|
+
|
755
|
+
def message
|
756
|
+
"Argument `#{argument.name}` was added to directive `#{directive.name}`"
|
757
|
+
end
|
758
|
+
|
759
|
+
def breaking?
|
760
|
+
!!@breaking
|
528
761
|
end
|
529
762
|
end
|
530
763
|
|
531
|
-
class InputFieldTypeChanged
|
532
|
-
attr_reader :input_type, :old_input_field, :new_input_field
|
764
|
+
class InputFieldTypeChanged < AbstractChange
|
765
|
+
attr_reader :input_type, :old_input_field, :new_input_field
|
533
766
|
|
534
767
|
def initialize(input_type, old_input_field, new_input_field)
|
535
768
|
@input_type = input_type
|
@@ -541,10 +774,14 @@ module GraphQL
|
|
541
774
|
def message
|
542
775
|
"Input field `#{input_type}.#{old_input_field.name}` changed type from #{old_input_field.type} to #{new_input_field.type}"
|
543
776
|
end
|
777
|
+
|
778
|
+
def breaking?
|
779
|
+
!!@breaking
|
780
|
+
end
|
544
781
|
end
|
545
782
|
|
546
|
-
class FieldArgumentTypeChanged
|
547
|
-
attr_reader :type, :field, :old_argument, :new_argument
|
783
|
+
class FieldArgumentTypeChanged < AbstractChange
|
784
|
+
attr_reader :type, :field, :old_argument, :new_argument
|
548
785
|
|
549
786
|
def initialize(type, field, old_argument, new_argument)
|
550
787
|
@type = type
|
@@ -558,15 +795,34 @@ module GraphQL
|
|
558
795
|
"Type for argument `#{new_argument.name}` on field `#{type.name}.#{field.name}` changed"\
|
559
796
|
" from `#{old_argument.type}` to `#{new_argument.type}`"
|
560
797
|
end
|
798
|
+
|
799
|
+
def breaking?
|
800
|
+
!!@breaking
|
801
|
+
end
|
561
802
|
end
|
562
803
|
|
563
|
-
class DirectiveArgumentTypeChanged
|
564
|
-
|
804
|
+
class DirectiveArgumentTypeChanged < AbstractChange
|
805
|
+
attr_reader :directive, :old_argument, :new_argument
|
806
|
+
|
807
|
+
def initialize(directive, old_argument, new_argument)
|
808
|
+
@directive = directive
|
809
|
+
@old_argument = old_argument
|
810
|
+
@new_argument = new_argument
|
811
|
+
@breaking = false
|
812
|
+
end
|
813
|
+
|
814
|
+
def message
|
815
|
+
"Type for argument `#{new_argument.name}` on directive `#{directive.name}` changed"\
|
816
|
+
" from `#{old_argument.type}` to `#{new_argument.type}`"
|
817
|
+
end
|
818
|
+
|
819
|
+
def breaking?
|
820
|
+
!!@breaking
|
565
821
|
end
|
566
822
|
end
|
567
823
|
|
568
|
-
class FieldTypeChanged
|
569
|
-
attr_reader :type, :old_field, :new_field
|
824
|
+
class FieldTypeChanged < AbstractChange
|
825
|
+
attr_reader :type, :old_field, :new_field
|
570
826
|
|
571
827
|
def initialize(type, old_field, new_field)
|
572
828
|
@type = type
|
@@ -578,10 +834,14 @@ module GraphQL
|
|
578
834
|
def message
|
579
835
|
"Field `#{type}.#{old_field.name}` changed type from `#{old_field.type}` to `#{new_field.type}`"
|
580
836
|
end
|
837
|
+
|
838
|
+
def breaking?
|
839
|
+
!!@breaking
|
840
|
+
end
|
581
841
|
end
|
582
842
|
|
583
|
-
class SchemaMutationTypeChanged
|
584
|
-
attr_reader :old_schema, :new_schema
|
843
|
+
class SchemaMutationTypeChanged < AbstractChange
|
844
|
+
attr_reader :old_schema, :new_schema
|
585
845
|
|
586
846
|
def initialize(old_schema, new_schema)
|
587
847
|
@old_schema = old_schema
|
@@ -592,9 +852,13 @@ module GraphQL
|
|
592
852
|
def message
|
593
853
|
"Schema mutation root has changed from `#{old_schema.mutation}` to `#{new_schema.mutation}`"
|
594
854
|
end
|
855
|
+
|
856
|
+
def breaking?
|
857
|
+
!!@breaking
|
858
|
+
end
|
595
859
|
end
|
596
860
|
|
597
|
-
class SchemaSubscriptionTypeChanged
|
861
|
+
class SchemaSubscriptionTypeChanged < AbstractChange
|
598
862
|
def initialize(old_schema, new_schema)
|
599
863
|
@old_schema = old_schema
|
600
864
|
@new_schema = new_schema
|
@@ -604,6 +868,10 @@ module GraphQL
|
|
604
868
|
def message
|
605
869
|
"Schema subscription type has changed from `#{old_schema.subscription}` to `#{new_schema.subscription}`"
|
606
870
|
end
|
871
|
+
|
872
|
+
def breaking?
|
873
|
+
!!@breaking
|
874
|
+
end
|
607
875
|
end
|
608
876
|
end
|
609
877
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module GraphQL
|
2
|
+
module SchemaComparator
|
3
|
+
module Diff
|
4
|
+
class Directive
|
5
|
+
def initialize(old_directive, new_directive)
|
6
|
+
@old_directive = old_directive
|
7
|
+
@new_directive = new_directive
|
8
|
+
@old_arguments = old_directive.arguments
|
9
|
+
@new_arguments = new_directive.arguments
|
10
|
+
end
|
11
|
+
|
12
|
+
def diff
|
13
|
+
changes = []
|
14
|
+
|
15
|
+
if old_directive.description != new_directive.description
|
16
|
+
changes << Changes::DirectiveDescriptionChanged.new(old_directive, new_directive)
|
17
|
+
end
|
18
|
+
|
19
|
+
changes += removed_locations.map { |location| Changes::DirectiveLocationRemoved.new(new_directive, location) }
|
20
|
+
changes += added_locations.map { |location| Changes::DirectiveLocationAdded.new(new_directive, location) }
|
21
|
+
changes += added_arguments.map { |argument| Changes::DirectiveArgumentAdded.new(new_directive, argument) }
|
22
|
+
changes += removed_arguments.map { |argument| Changes::DirectiveArgumentRemoved.new(new_directive, argument) }
|
23
|
+
|
24
|
+
each_common_argument do |old_argument, new_argument|
|
25
|
+
changes += Diff::DirectiveArgument.new(new_directive, old_argument, new_argument).diff
|
26
|
+
end
|
27
|
+
|
28
|
+
changes
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def removed_locations
|
34
|
+
(old_directive.locations - new_directive.locations)
|
35
|
+
end
|
36
|
+
|
37
|
+
def added_locations
|
38
|
+
(new_directive.locations - old_directive.locations)
|
39
|
+
end
|
40
|
+
|
41
|
+
def removed_arguments
|
42
|
+
old_arguments.values.select { |arg| !new_arguments[arg.name] }
|
43
|
+
end
|
44
|
+
|
45
|
+
def added_arguments
|
46
|
+
new_arguments.values.select { |arg| !old_arguments[arg.name] }
|
47
|
+
end
|
48
|
+
|
49
|
+
def each_common_argument(&block)
|
50
|
+
intersection = old_arguments.keys & new_arguments.keys
|
51
|
+
intersection.each do |common_arg|
|
52
|
+
old_arg = new_directive.arguments[common_arg]
|
53
|
+
new_arg = old_directive.arguments[common_arg]
|
54
|
+
|
55
|
+
block.call(old_arg, new_arg)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
attr_reader(:old_directive, :new_directive, :old_arguments, :new_arguments)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module GraphQL
|
2
|
+
module SchemaComparator
|
3
|
+
module Diff
|
4
|
+
class DirectiveArgument
|
5
|
+
def initialize(directive, old_arg, new_arg)
|
6
|
+
@directive = directive
|
7
|
+
@old_arg = old_arg
|
8
|
+
@new_arg = new_arg
|
9
|
+
end
|
10
|
+
|
11
|
+
def diff
|
12
|
+
changes = []
|
13
|
+
|
14
|
+
if old_arg.description != new_arg.description
|
15
|
+
changes << Changes::DirectiveArgumentDescriptionChanged.new(directive, old_arg, new_arg)
|
16
|
+
end
|
17
|
+
|
18
|
+
if old_arg.default_value != new_arg.default_value
|
19
|
+
changes << Changes::DirectiveArgumentDefaultChanged.new(directive, old_arg, new_arg)
|
20
|
+
end
|
21
|
+
|
22
|
+
if old_arg.type != new_arg.type
|
23
|
+
changes << Changes::DirectiveArgumentTypeChanged.new(directive, old_arg, new_arg)
|
24
|
+
end
|
25
|
+
|
26
|
+
# TODO directives on directive arguments
|
27
|
+
|
28
|
+
changes
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader(:directive, :new_arg, :old_arg)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
File without changes
|
@@ -1,12 +1,3 @@
|
|
1
|
-
require "graphql/schema_comparator/diff/enum"
|
2
|
-
require "graphql/schema_comparator/diff/union"
|
3
|
-
require "graphql/schema_comparator/diff/input_object"
|
4
|
-
require "graphql/schema_comparator/diff/input_field"
|
5
|
-
require "graphql/schema_comparator/diff/object_type"
|
6
|
-
require "graphql/schema_comparator/diff/interface"
|
7
|
-
require "graphql/schema_comparator/diff/field"
|
8
|
-
require "graphql/schema_comparator/diff/argument"
|
9
|
-
|
10
1
|
module GraphQL
|
11
2
|
module SchemaComparator
|
12
3
|
module Diff
|
@@ -17,6 +8,9 @@ module GraphQL
|
|
17
8
|
|
18
9
|
@old_types = old_schema.types
|
19
10
|
@new_types = new_schema.types
|
11
|
+
|
12
|
+
@old_directives = old_schema.directives
|
13
|
+
@new_directives = new_schema.directives
|
20
14
|
end
|
21
15
|
|
22
16
|
def diff
|
@@ -86,8 +80,16 @@ module GraphQL
|
|
86
80
|
end
|
87
81
|
|
88
82
|
def changes_in_directives
|
89
|
-
|
90
|
-
|
83
|
+
changes = []
|
84
|
+
|
85
|
+
changes += removed_directives.map { |directive| Changes::DirectiveRemoved.new(directive) }
|
86
|
+
changes += added_directives.map { |directive| Changes::DirectiveAdded.new(directive) }
|
87
|
+
|
88
|
+
each_common_directive do |old_directive, new_directive|
|
89
|
+
changes += Diff::Directive.new(old_directive, new_directive).diff
|
90
|
+
end
|
91
|
+
|
92
|
+
changes
|
91
93
|
end
|
92
94
|
|
93
95
|
private
|
@@ -110,7 +112,25 @@ module GraphQL
|
|
110
112
|
(new_types.keys - old_types.keys).map { |type_name| new_schema.types[type_name] }
|
111
113
|
end
|
112
114
|
|
113
|
-
|
115
|
+
def removed_directives
|
116
|
+
(old_directives.keys - new_directives.keys).map { |directive_name| old_schema.directives[directive_name] }
|
117
|
+
end
|
118
|
+
|
119
|
+
def added_directives
|
120
|
+
(new_directives.keys - old_directives.keys).map { |directive_name| new_schema.directives[directive_name] }
|
121
|
+
end
|
122
|
+
|
123
|
+
def each_common_directive(&block)
|
124
|
+
intersection = old_directives.keys & new_directives.keys
|
125
|
+
intersection.each do |common_directive_name|
|
126
|
+
old_directive = old_schema.directives[common_directive_name]
|
127
|
+
new_directive = new_schema.directives[common_directive_name]
|
128
|
+
|
129
|
+
block.call(old_directive, new_directive)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
attr_reader :old_schema, :new_schema, :old_types, :new_types, :old_directives, :new_directives
|
114
134
|
end
|
115
135
|
end
|
116
136
|
end
|
@@ -4,8 +4,8 @@ module GraphQL
|
|
4
4
|
attr_reader :changes, :breaking_changes, :non_breaking_changes
|
5
5
|
|
6
6
|
def initialize(changes)
|
7
|
-
@changes = changes.sort_by { |c| [c.breaking ? 1 : 2, c.message] }
|
8
|
-
@breaking_changes, @non_breaking_changes = @changes.partition(&:breaking)
|
7
|
+
@changes = changes.sort_by { |c| [c.breaking? ? 1 : 2, c.message] }
|
8
|
+
@breaking_changes, @non_breaking_changes = @changes.partition(&:breaking?)
|
9
9
|
end
|
10
10
|
|
11
11
|
def identical?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql-schema_comparator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marc-Andre Giroux
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|
@@ -118,8 +118,11 @@ files:
|
|
118
118
|
- lib/graphql/schema_comparator.rb
|
119
119
|
- lib/graphql/schema_comparator/changes.rb
|
120
120
|
- lib/graphql/schema_comparator/diff/argument.rb
|
121
|
+
- lib/graphql/schema_comparator/diff/directive.rb
|
122
|
+
- lib/graphql/schema_comparator/diff/directive_argument.rb
|
121
123
|
- lib/graphql/schema_comparator/diff/enum.rb
|
122
124
|
- lib/graphql/schema_comparator/diff/field.rb
|
125
|
+
- lib/graphql/schema_comparator/diff/has_directives.rb
|
123
126
|
- lib/graphql/schema_comparator/diff/input_field.rb
|
124
127
|
- lib/graphql/schema_comparator/diff/input_object.rb
|
125
128
|
- lib/graphql/schema_comparator/diff/interface.rb
|
@@ -149,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
152
|
version: '0'
|
150
153
|
requirements: []
|
151
154
|
rubyforge_project:
|
152
|
-
rubygems_version: 2.6.
|
155
|
+
rubygems_version: 2.6.13
|
153
156
|
signing_key:
|
154
157
|
specification_version: 4
|
155
158
|
summary: Compare GraphQL schemas and get the changes that happened.
|