graphql-schema_comparator 1.1.2 → 1.2.1
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 +13 -0
- data/lib/graphql/schema_comparator/changes.rb +111 -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: aa337e772bf6a06c8ee1043b482e556d0536bbdc20df463ac8281e98ed8b970e
|
4
|
+
data.tar.gz: 1de6b8f0b37cab53d2c20481ea62099e1e09ed382d1c8bccfcf3f2a0c3e58401
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b08bf90193cd6fe2858c369c86d02cfbe6903aae1535743eb75b966de8303da0f7d6901dda33343c36ebbebf28c9e73d2f115713125f93e5aa88cd7e62a8d18f
|
7
|
+
data.tar.gz: db81019920724822356558d021097a2af6a3440d3fb744c8b73c19d9eec58f7745a236fb36afebd08c264b5965650ad31c0021d3d04b522931ac56edb427c862
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.2.1 (October 27 2023)
|
4
|
+
|
5
|
+
### Bug Fix
|
6
|
+
|
7
|
+
- Add support for path on `DirectiveArgumentAdded` (#57)
|
8
|
+
|
9
|
+
## 1.2.0 (October 18 2023)
|
10
|
+
|
11
|
+
### Bug Fix
|
12
|
+
|
13
|
+
- More selective detection of breaking/dangerous enum value changes (#54)
|
14
|
+
- Improve schema root operation type changes (#55)
|
15
|
+
|
3
16
|
## 1.1.2 (September 15 2022)
|
4
17
|
|
5
18
|
### Bug Fix
|
@@ -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
|
200
218
|
|
201
|
-
def
|
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
|
237
|
+
|
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
|
@@ -1034,6 +1086,10 @@ module GraphQL
|
|
1034
1086
|
def message
|
1035
1087
|
"Argument `#{argument.graphql_name}` was added to directive `#{directive.graphql_name}`"
|
1036
1088
|
end
|
1089
|
+
|
1090
|
+
def path
|
1091
|
+
["@#{directive.graphql_name}", argument.graphql_name].join('.')
|
1092
|
+
end
|
1037
1093
|
end
|
1038
1094
|
end
|
1039
1095
|
end
|
@@ -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.1
|
4
|
+
version: 1.2.1
|
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-27 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: []
|