graphql-schema_comparator 1.1.2 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/graphql/schema_comparator/changes.rb +107 -55
- data/lib/graphql/schema_comparator/diff/enum.rb +6 -4
- data/lib/graphql/schema_comparator/diff/schema.rb +28 -4
- data/lib/graphql/schema_comparator/enum_usage.rb +18 -0
- data/lib/graphql/schema_comparator/version.rb +1 -1
- data/lib/graphql/schema_comparator.rb +1 -0
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9a21994b860741a5060b7600e7473348c0bf0445ecca50ea68966762448a967f
|
4
|
+
data.tar.gz: b4197e9f75dac972f474fd578fab78588b54f77ade6d36b126ad57a3f702b85c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b637ed11e3ba28902bd61f9e082cb0ac20f0be6868450b70e6e04df56b0019cbdba4a869d750e4dcaee4af454da799ae05512d2299300cbab3497d5d09d8392
|
7
|
+
data.tar.gz: 276c28e5588937b25361937ae594ff678981f71ac84f8f370ebada3e917e8f22f44a54c8dfb32cb9cfa8bf4e58b467dc42de6eb8ef22f864446b50c23f668a1e
|
data/CHANGELOG.md
CHANGED
@@ -99,12 +99,18 @@ module GraphQL
|
|
99
99
|
class EnumValueRemoved < AbstractChange
|
100
100
|
attr_reader :enum_value, :enum_type, :criticality
|
101
101
|
|
102
|
-
def initialize(enum_type, enum_value)
|
102
|
+
def initialize(enum_type, enum_value, usage)
|
103
103
|
@enum_value = enum_value
|
104
104
|
@enum_type = enum_type
|
105
|
-
@criticality =
|
106
|
-
|
107
|
-
|
105
|
+
@criticality = if usage.input?
|
106
|
+
Changes::Criticality.breaking(
|
107
|
+
reason: "Removing an enum value will cause existing queries that use this enum value to error."
|
108
|
+
)
|
109
|
+
else
|
110
|
+
Changes::Criticality.non_breaking(
|
111
|
+
reason: "Removing an enum value for enums used only in outputs is non-breaking."
|
112
|
+
)
|
113
|
+
end
|
108
114
|
end
|
109
115
|
|
110
116
|
def message
|
@@ -195,21 +201,93 @@ module GraphQL
|
|
195
201
|
end
|
196
202
|
end
|
197
203
|
|
198
|
-
class
|
199
|
-
attr_reader :
|
204
|
+
class RootOperationTypeAdded < AbstractChange
|
205
|
+
attr_reader :new_schema, :operation_type, :criticality
|
206
|
+
|
207
|
+
def initialize(new_schema:, operation_type:)
|
208
|
+
@new_schema = new_schema
|
209
|
+
@operation_type = operation_type
|
210
|
+
@criticality = Changes::Criticality.non_breaking(
|
211
|
+
reason: "Adding a schema #{operation_type} root is considered non-breaking."
|
212
|
+
)
|
213
|
+
end
|
214
|
+
|
215
|
+
def message
|
216
|
+
"Schema #{operation_type} root `#{operation_type_name}` was added"
|
217
|
+
end
|
218
|
+
|
219
|
+
def path
|
220
|
+
operation_type_name
|
221
|
+
end
|
222
|
+
|
223
|
+
def operation_type_name
|
224
|
+
case operation_type
|
225
|
+
when :query
|
226
|
+
new_schema.query.graphql_name
|
227
|
+
when :mutation
|
228
|
+
new_schema.mutation.graphql_name
|
229
|
+
when :subscription
|
230
|
+
new_schema.subscription.graphql_name
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
class RootOperationTypeChanged < AbstractChange
|
236
|
+
attr_reader :old_schema, :new_schema, :operation_type, :criticality
|
200
237
|
|
201
|
-
def initialize(old_schema
|
238
|
+
def initialize(old_schema:, new_schema:, operation_type:)
|
202
239
|
@old_schema = old_schema
|
203
240
|
@new_schema = new_schema
|
241
|
+
@operation_type = operation_type
|
204
242
|
@criticality = Changes::Criticality.breaking
|
205
243
|
end
|
206
244
|
|
207
245
|
def message
|
208
|
-
"Schema
|
246
|
+
"Schema #{operation_type} root has changed from `#{operation_type_name(old_schema)}` to `#{operation_type_name(new_schema)}`"
|
209
247
|
end
|
210
248
|
|
211
249
|
def path
|
212
|
-
|
250
|
+
operation_type_name(old_schema)
|
251
|
+
end
|
252
|
+
|
253
|
+
def operation_type_name(schema)
|
254
|
+
case operation_type
|
255
|
+
when :query
|
256
|
+
schema.query.graphql_name
|
257
|
+
when :mutation
|
258
|
+
schema.mutation.graphql_name
|
259
|
+
when :subscription
|
260
|
+
schema.subscription.graphql_name
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
class RootOperationTypeRemoved < AbstractChange
|
266
|
+
attr_reader :old_schema, :operation_type, :criticality
|
267
|
+
|
268
|
+
def initialize(old_schema:, operation_type:)
|
269
|
+
@old_schema = old_schema
|
270
|
+
@operation_type = operation_type
|
271
|
+
@criticality = Changes::Criticality.breaking
|
272
|
+
end
|
273
|
+
|
274
|
+
def message
|
275
|
+
"Schema #{operation_type} root `#{operation_type_name}` was removed"
|
276
|
+
end
|
277
|
+
|
278
|
+
def path
|
279
|
+
operation_type_name
|
280
|
+
end
|
281
|
+
|
282
|
+
def operation_type_name
|
283
|
+
case operation_type
|
284
|
+
when :query
|
285
|
+
old_schema.query.graphql_name
|
286
|
+
when :mutation
|
287
|
+
old_schema.mutation.graphql_name
|
288
|
+
when :subscription
|
289
|
+
old_schema.subscription.graphql_name
|
290
|
+
end
|
213
291
|
end
|
214
292
|
end
|
215
293
|
|
@@ -398,42 +476,6 @@ module GraphQL
|
|
398
476
|
end
|
399
477
|
end
|
400
478
|
|
401
|
-
class SchemaMutationTypeChanged < AbstractChange
|
402
|
-
attr_reader :old_schema, :new_schema, :criticality
|
403
|
-
|
404
|
-
def initialize(old_schema, new_schema)
|
405
|
-
@old_schema = old_schema
|
406
|
-
@new_schema = new_schema
|
407
|
-
@criticality = Changes::Criticality.breaking
|
408
|
-
end
|
409
|
-
|
410
|
-
def message
|
411
|
-
"Schema mutation root has changed from `#{old_schema.mutation}` to `#{new_schema.mutation}`"
|
412
|
-
end
|
413
|
-
|
414
|
-
def path
|
415
|
-
# TODO
|
416
|
-
end
|
417
|
-
end
|
418
|
-
|
419
|
-
class SchemaSubscriptionTypeChanged < AbstractChange
|
420
|
-
attr_reader :old_schema, :new_schema, :criticality
|
421
|
-
|
422
|
-
def initialize(old_schema, new_schema)
|
423
|
-
@old_schema = old_schema
|
424
|
-
@new_schema = new_schema
|
425
|
-
@criticality = Changes::Criticality.breaking
|
426
|
-
end
|
427
|
-
|
428
|
-
def message
|
429
|
-
"Schema subscription type has changed from `#{old_schema.subscription}` to `#{new_schema.subscription}`"
|
430
|
-
end
|
431
|
-
|
432
|
-
def path
|
433
|
-
# TODO
|
434
|
-
end
|
435
|
-
end
|
436
|
-
|
437
479
|
# Dangerous Changes
|
438
480
|
|
439
481
|
class FieldArgumentDefaultChanged < AbstractChange
|
@@ -451,11 +493,11 @@ module GraphQL
|
|
451
493
|
end
|
452
494
|
|
453
495
|
def message
|
454
|
-
if old_argument.default_value
|
455
|
-
"Default value `#{new_argument.default_value}` was added to argument `#{new_argument.graphql_name}` on field `#{field.path}`"
|
456
|
-
else
|
496
|
+
if old_argument.default_value?
|
457
497
|
"Default value for argument `#{new_argument.graphql_name}` on field `#{field.path}` changed"\
|
458
498
|
" from `#{old_argument.default_value}` to `#{new_argument.default_value}`"
|
499
|
+
else
|
500
|
+
"Default value `#{new_argument.default_value}` was added to argument `#{new_argument.graphql_name}` on field `#{field.path}`"
|
459
501
|
end
|
460
502
|
end
|
461
503
|
|
@@ -501,8 +543,12 @@ module GraphQL
|
|
501
543
|
end
|
502
544
|
|
503
545
|
def message
|
504
|
-
|
505
|
-
"
|
546
|
+
if old_argument.default_value?
|
547
|
+
"Default value for argument `#{new_argument.graphql_name}` on directive `#{directive.graphql_name}` changed"\
|
548
|
+
" from `#{old_argument.default_value}` to `#{new_argument.default_value}`"
|
549
|
+
else
|
550
|
+
"Default value `#{new_argument.default_value}` was added to argument `#{new_argument.graphql_name}` on directive `#{directive.graphql_name}`"
|
551
|
+
end
|
506
552
|
end
|
507
553
|
|
508
554
|
def path
|
@@ -513,13 +559,19 @@ module GraphQL
|
|
513
559
|
class EnumValueAdded < AbstractChange
|
514
560
|
attr_reader :enum_type, :enum_value, :criticality
|
515
561
|
|
516
|
-
def initialize(enum_type, enum_value)
|
562
|
+
def initialize(enum_type, enum_value, usage)
|
517
563
|
@enum_type = enum_type
|
518
564
|
@enum_value = enum_value
|
519
|
-
@criticality =
|
520
|
-
|
521
|
-
|
522
|
-
|
565
|
+
@criticality = if usage.output?
|
566
|
+
Changes::Criticality.dangerous(
|
567
|
+
reason: "Adding an enum value may break existing clients that were not " \
|
568
|
+
"programmed defensively against an added case when querying an enum."
|
569
|
+
)
|
570
|
+
else
|
571
|
+
Changes::Criticality.non_breaking(
|
572
|
+
reason: "Adding an enum value for enums used only in inputs is non-breaking."
|
573
|
+
)
|
574
|
+
end
|
523
575
|
end
|
524
576
|
|
525
577
|
def message
|
@@ -2,19 +2,21 @@ module GraphQL
|
|
2
2
|
module SchemaComparator
|
3
3
|
module Diff
|
4
4
|
class Enum
|
5
|
-
def initialize(old_enum, new_enum)
|
5
|
+
def initialize(old_enum, new_enum, usage)
|
6
6
|
@old_enum = old_enum
|
7
7
|
@new_enum = new_enum
|
8
8
|
|
9
9
|
@old_values = old_enum.values
|
10
10
|
@new_values = new_enum.values
|
11
|
+
|
12
|
+
@usage = usage
|
11
13
|
end
|
12
14
|
|
13
15
|
def diff
|
14
16
|
changes = []
|
15
17
|
|
16
|
-
changes += removed_values.map { |value| Changes::EnumValueRemoved.new(old_enum, value) }
|
17
|
-
changes += added_values.map { |value| Changes::EnumValueAdded.new(new_enum, value) }
|
18
|
+
changes += removed_values.map { |value| Changes::EnumValueRemoved.new(old_enum, value, usage) }
|
19
|
+
changes += added_values.map { |value| Changes::EnumValueAdded.new(new_enum, value, usage) }
|
18
20
|
|
19
21
|
each_common_value do |old_value, new_value|
|
20
22
|
# TODO: Add Directive Stuff
|
@@ -33,7 +35,7 @@ module GraphQL
|
|
33
35
|
|
34
36
|
private
|
35
37
|
|
36
|
-
attr_reader :old_enum, :new_enum, :old_values, :new_values
|
38
|
+
attr_reader :old_enum, :new_enum, :old_values, :new_values, :usage
|
37
39
|
|
38
40
|
def each_common_value(&block)
|
39
41
|
intersection = old_values.keys & new_values.keys
|
@@ -42,7 +42,7 @@ module GraphQL
|
|
42
42
|
else
|
43
43
|
case old_type.kind.name
|
44
44
|
when "ENUM"
|
45
|
-
changes += Diff::Enum.new(old_type, new_type).diff
|
45
|
+
changes += Diff::Enum.new(old_type, new_type, enum_usage(new_type)).diff
|
46
46
|
when "UNION"
|
47
47
|
changes += Diff::Union.new(old_type, new_type).diff
|
48
48
|
when "INPUT_OBJECT"
|
@@ -65,15 +65,33 @@ module GraphQL
|
|
65
65
|
changes = []
|
66
66
|
|
67
67
|
if old_schema.query&.graphql_name != new_schema.query&.graphql_name
|
68
|
-
|
68
|
+
if old_schema.query.nil?
|
69
|
+
changes << Changes::RootOperationTypeAdded.new(new_schema: new_schema, operation_type: :query)
|
70
|
+
elsif new_schema.query.nil?
|
71
|
+
changes << Changes::RootOperationTypeRemoved.new(old_schema: old_schema, operation_type: :query)
|
72
|
+
else
|
73
|
+
changes << Changes::RootOperationTypeChanged.new(old_schema: old_schema, new_schema: new_schema, operation_type: :query)
|
74
|
+
end
|
69
75
|
end
|
70
76
|
|
71
77
|
if old_schema.mutation&.graphql_name != new_schema.mutation&.graphql_name
|
72
|
-
|
78
|
+
if old_schema.mutation.nil?
|
79
|
+
changes << Changes::RootOperationTypeAdded.new(new_schema: new_schema, operation_type: :mutation)
|
80
|
+
elsif new_schema.mutation.nil?
|
81
|
+
changes << Changes::RootOperationTypeRemoved.new(old_schema: old_schema, operation_type: :mutation)
|
82
|
+
else
|
83
|
+
changes << Changes::RootOperationTypeChanged.new(old_schema: old_schema, new_schema: new_schema, operation_type: :mutation)
|
84
|
+
end
|
73
85
|
end
|
74
86
|
|
75
87
|
if old_schema.subscription&.graphql_name != new_schema.subscription&.graphql_name
|
76
|
-
|
88
|
+
if old_schema.subscription.nil?
|
89
|
+
changes << Changes::RootOperationTypeAdded.new(new_schema: new_schema, operation_type: :subscription)
|
90
|
+
elsif new_schema.subscription.nil?
|
91
|
+
changes << Changes::RootOperationTypeRemoved.new(old_schema: old_schema, operation_type: :subscription)
|
92
|
+
else
|
93
|
+
changes << Changes::RootOperationTypeChanged.new(old_schema: old_schema, new_schema: new_schema, operation_type: :subscription)
|
94
|
+
end
|
77
95
|
end
|
78
96
|
|
79
97
|
changes
|
@@ -94,6 +112,12 @@ module GraphQL
|
|
94
112
|
|
95
113
|
private
|
96
114
|
|
115
|
+
def enum_usage(new_enum)
|
116
|
+
input_usage = new_schema.references_to(new_enum).any? { |member| member.is_a?(GraphQL::Schema::Argument) }
|
117
|
+
output_usage = new_schema.references_to(new_enum).any? { |member| member.is_a?(GraphQL::Schema::Field) }
|
118
|
+
EnumUsage.new(input: input_usage, output: output_usage)
|
119
|
+
end
|
120
|
+
|
97
121
|
def each_common_type(&block)
|
98
122
|
intersection = old_types.keys & new_types.keys
|
99
123
|
intersection.each do |common_type_name|
|
@@ -4,6 +4,7 @@ require "graphql/schema_comparator/version"
|
|
4
4
|
require "graphql/schema_comparator/result"
|
5
5
|
|
6
6
|
require 'graphql/schema_comparator/changes'
|
7
|
+
require 'graphql/schema_comparator/enum_usage'
|
7
8
|
|
8
9
|
require "graphql/schema_comparator/diff/schema"
|
9
10
|
require "graphql/schema_comparator/diff/argument"
|
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: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marc-Andre Giroux
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|
@@ -147,6 +147,7 @@ files:
|
|
147
147
|
- lib/graphql/schema_comparator/diff/object_type.rb
|
148
148
|
- lib/graphql/schema_comparator/diff/schema.rb
|
149
149
|
- lib/graphql/schema_comparator/diff/union.rb
|
150
|
+
- lib/graphql/schema_comparator/enum_usage.rb
|
150
151
|
- lib/graphql/schema_comparator/result.rb
|
151
152
|
- lib/graphql/schema_comparator/version.rb
|
152
153
|
- schema.graphql
|
@@ -158,7 +159,7 @@ metadata:
|
|
158
159
|
changelog_uri: https://github.com/xuorig/graphql-schema_comparator/blob/master/CHANGELOG.md
|
159
160
|
source_code_uri: https://github.com/xuorig/graphql-schema_comparator
|
160
161
|
bug_tracker_uri: https://github.com/xuorig/graphql-schema_comparator/issues
|
161
|
-
post_install_message:
|
162
|
+
post_install_message:
|
162
163
|
rdoc_options: []
|
163
164
|
require_paths:
|
164
165
|
- lib
|
@@ -173,8 +174,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
174
|
- !ruby/object:Gem::Version
|
174
175
|
version: '0'
|
175
176
|
requirements: []
|
176
|
-
rubygems_version: 3.
|
177
|
-
signing_key:
|
177
|
+
rubygems_version: 3.4.10
|
178
|
+
signing_key:
|
178
179
|
specification_version: 4
|
179
180
|
summary: Compare GraphQL schemas and get the changes that happened.
|
180
181
|
test_files: []
|