graphql-schema_comparator 0.5.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2bd04f7cdf16f7bc67fb74e219478457b180e022
4
- data.tar.gz: eb021f9745da0a4fed5fb2cedfb5a848ca1685b0
2
+ SHA256:
3
+ metadata.gz: 3ae1770b6fad8e77502e03cb613fbc5bf5546bc96d535e2af0f622c2794102c0
4
+ data.tar.gz: 5edcad6f5ce2fea8a2e83c79279e4bee868d5e3507af254176931341d7d46506
5
5
  SHA512:
6
- metadata.gz: 7a6d826fd10f0bb42eebcc9546c77d40b32242d5c6888181e5dab77b7c1f9d4ce8d4be192ef750209d98d7230ee81aa0121645f6c1482b6fc1d80e9d5287f02e
7
- data.tar.gz: f43508482f55b5b88b1627b5b9d12ce6800512a2386cb66785348f01951d25384d1142d62370dc7d339530d0593998200005ced1a4ae01402a24940676bbc62d
6
+ metadata.gz: e10aae6486a79da4eb4e9fb6e3787ac166d5d54848bf2eea37b8885839c83efe8de97af8dc84fa732d7c1582567050b0469fba5d546a85b9183b6ccdcb4582a2
7
+ data.tar.gz: 1a879654fecfb43824872cf9c4907d4edaa221645d6d91a062b7f933cb0cf0ce43587e6d840451f7027b9da8aed99c45fd8d0af84bc3403901c6a93eb2764cb4
@@ -0,0 +1,20 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push
5
+
6
+ jobs:
7
+ test:
8
+ runs-on: ubuntu-latest
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ ruby: [2.4, 2.7, '3.0']
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ bundler-cache: true
18
+ ruby-version: ${{ matrix.ruby }}
19
+ - run: bundle install
20
+ - run: bundle exec rake
data/CHANGELOG.md CHANGED
@@ -1,8 +1,39 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.1 (May 26 2021)
4
+
5
+ ### Bug Fix
6
+
7
+ - Fix comparing directives (#36)
8
+
9
+ ## 1.0.0 (January 23 2020)
10
+
11
+ ### Breaking Changes
12
+
13
+ - Add support for graphql-ruby 1.10.0+ (#28)
14
+ - Starting from 1.0.0 a minimum of graphql-ruby 1.10 is required
15
+
16
+ ## 0.6.1 (May 21rst 2019)
17
+
18
+ - Added a bunch of reasons to breaking changes (#17)
19
+ - Relaxed Thor Dependency
20
+ - Add `verify` task for CI usage which returns exit codes depending on breaking changes (#24)
21
+
22
+ ## 0.6.0 (Feb 28th 2018)
23
+
24
+ ### New Features
25
+
26
+ - Add `#path` which returns a dot-delimited path to the affected schema member. (#15)
27
+
28
+ ## 0.5.1 (Feb 15th 2018)
29
+
30
+ ### Bug Fix
31
+
32
+ - Return a better message when adding a default value, if this one was nil before.
33
+
3
34
  ## 0.5.0 (Dec 2 2017)
4
35
 
5
- ## New Features
36
+ ### New Features
6
37
 
7
38
  - `AbstractChange#criticality` now returns a criticality object which
8
39
  has a level (non_breaking, dangerous, breaking) and a reason
@@ -13,14 +44,14 @@
13
44
 
14
45
  - New CLI `schema_comparator` which includes `dangerous_changes`
15
46
 
16
- ## Breaking Changes
47
+ ### Breaking Changes
17
48
 
18
49
  - Some changes have been recategorized as dangerous
19
50
  - Some type changes now return breaking or non-breaking depending on the type kind
20
51
 
21
52
  ## 0.4.0 (Nov 27 2017)
22
53
 
23
- ## Breaking Changes
54
+ ### Breaking Changes
24
55
 
25
56
  - Argument and InputValue type changes are considered non
26
57
  breaking if type goes from Null => Non-Null
@@ -36,32 +67,32 @@ Added changes:
36
67
 
37
68
  ### Bug fixes
38
69
 
39
- Fix issue in Enum differ (https://github.com/xuorig/graphql-schema_comparator/issues/9)
70
+ - Fix issue in Enum differ (https://github.com/xuorig/graphql-schema_comparator/issues/9)
40
71
 
41
72
  ## 0.3.1 (Nov 13 2017)
42
73
 
43
74
  ### Bug Fixes
44
75
 
45
- - Fix no method breaking issue https://github.com/xuorig/graphql-schema_comparator/issues/8
76
+ - Fix no method breaking issue https://github.com/xuorig/graphql-schema_comparator/issues/8
46
77
 
47
78
  ## 0.3.0 (Oct 14 2017)
48
79
 
49
80
  ### New features
50
81
 
51
- - Top level Directive definitions are now diffed, but not directives used on definitions (Coming soon)
52
- - Base class for changes added.
82
+ - Top level Directive definitions are now diffed, but not directives used on definitions (Coming soon)
83
+ - Base class for changes added.
53
84
 
54
85
  ### breaking changes
55
86
 
56
- - `breaking` method on change objects has been renamed `breaking?` for style
87
+ - `breaking` method on change objects has been renamed `breaking?` for style
57
88
 
58
89
  ## 0.2.0 (Aug 18 2017)
59
90
 
60
91
  ### New features
61
92
 
62
- - Add `#non_breaking_changes` to get a list of non breaking changes from a comparison result. (#4)
63
- - CLI now Prints results sorted and grouped by breaking / non-breaking (#3)
93
+ - Add `#non_breaking_changes` to get a list of non breaking changes from a comparison result. (#4)
94
+ - CLI now Prints results sorted and grouped by breaking / non-breaking (#3)
64
95
 
65
96
  ### Bug fixes
66
97
 
67
- - Fix message for `EnumValueRemoved` (#5)
98
+ - Fix message for `EnumValueRemoved` (#5)
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2017 TODO: Write your name
3
+ Copyright (c) 2017 Marc-Andre Giroux
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -87,7 +87,7 @@ Possible changes are all found in [changes.rb](lib/graphql/schema_comparator/cha
87
87
 
88
88
  ### Change Criticality
89
89
 
90
- Each change object has a ``#criticality` method which returns a `Changes::Criticality` object.
90
+ Each change object has a `#criticality` method which returns a `Changes::Criticality` object.
91
91
  This objects defines how dangerous a change is to a schema.
92
92
 
93
93
  The different levels of criticality (non_breaking, dangerous, breaking) are explained here:
@@ -5,9 +5,23 @@ require "thor"
5
5
  require "graphql/schema_comparator"
6
6
 
7
7
  class GraphQLSchema < Thor
8
+ desc "verify OLD_SCHEMA NEW_SCHEMA", "Behaves exactly like `compare` but returns an exit code for CI purposes"
9
+
10
+ def verify(old_schema, new_schema)
11
+ result = run_compare(old_schema, new_schema)
12
+ exit_code = result.breaking? ? 1 : 0
13
+ exit(exit_code)
14
+ end
15
+
8
16
  desc "compare OLD_SCHEMA NEW_SCHEMA", "Compares OLD_SCHEMA with NEW_SCHEMA and returns a list of changes"
9
17
 
10
18
  def compare(old_schema, new_schema)
19
+ run_compare(old_schema, new_schema)
20
+ end
21
+
22
+ private
23
+
24
+ def run_compare(old_schema, new_schema)
11
25
  parsed_old = parse_schema(old_schema)
12
26
  parsed_new = parse_schema(new_schema)
13
27
 
@@ -22,10 +36,9 @@ class GraphQLSchema < Thor
22
36
  else
23
37
  print_changes(result)
24
38
  end
39
+ result
25
40
  end
26
41
 
27
- private
28
-
29
42
  def print_changes(result)
30
43
  say "Detected the following changes between schemas:"
31
44
  say "\n"
@@ -21,10 +21,10 @@ Gem::Specification.new do |spec|
21
21
  spec.executables = ["graphql-schema", "schema_comparator"]
22
22
  spec.require_paths = ["lib"]
23
23
 
24
- spec.add_dependency "graphql", "~> 1.6"
25
- spec.add_dependency "thor", "~> 0.19"
24
+ spec.add_dependency "graphql", "~> 1.10"
25
+ spec.add_dependency "thor", ">= 0.19", "< 2.0"
26
+ spec.add_dependency "bundler", ">= 1.14"
26
27
 
27
- spec.add_development_dependency "bundler", "~> 1.14"
28
28
  spec.add_development_dependency "rake", "~> 10.0"
29
29
  spec.add_development_dependency "minitest", "~> 5.10"
30
30
  spec.add_development_dependency "pry-byebug", "~> 3.4"
@@ -35,7 +35,7 @@ module GraphQL
35
35
  private
36
36
 
37
37
  def self.parse_schema(schema)
38
- if schema.is_a?(GraphQL::Schema)
38
+ if schema.respond_to?(:ancestors) && schema.ancestors.include?(GraphQL::Schema)
39
39
  schema
40
40
  elsif schema.is_a?(String)
41
41
  GraphQL::Schema.from_definition(schema)
@@ -12,7 +12,7 @@ module GraphQL
12
12
  raise NotImplementedError
13
13
  end
14
14
 
15
- # @return [Boolean] If the change is breaking or not
15
+ # @return [Boolean] If the change is breaking or not
16
16
  def breaking?
17
17
  criticality.breaking?
18
18
  end
@@ -31,6 +31,11 @@ module GraphQL
31
31
  def criticality
32
32
  raise NotImplementedError
33
33
  end
34
+
35
+ # @return [String] Dot-delimited path to the affected schema member.
36
+ def path
37
+ raise NotImplementedError
38
+ end
34
39
  end
35
40
 
36
41
  # Mostly breaking changes
@@ -40,11 +45,17 @@ module GraphQL
40
45
 
41
46
  def initialize(removed_type)
42
47
  @removed_type = removed_type
43
- @criticality = Changes::Criticality.breaking
48
+ @criticality = Changes::Criticality.breaking(
49
+ reason: "Removing a type is a breaking change. It is preferable to deprecate and remove all references to this type first."
50
+ )
44
51
  end
45
52
 
46
53
  def message
47
- "`#{removed_type.name}` was removed"
54
+ "Type `#{removed_type.graphql_definition}` was removed"
55
+ end
56
+
57
+ def path
58
+ removed_type.graphql_definition.to_s
48
59
  end
49
60
  end
50
61
 
@@ -57,7 +68,11 @@ module GraphQL
57
68
  end
58
69
 
59
70
  def message
60
- "`#{directive.name}` was removed"
71
+ "Directive `#{directive.graphql_name}` was removed"
72
+ end
73
+
74
+ def path
75
+ "@#{directive.graphql_name}"
61
76
  end
62
77
  end
63
78
 
@@ -67,11 +82,17 @@ module GraphQL
67
82
  def initialize(old_type, new_type)
68
83
  @old_type = old_type
69
84
  @new_type = new_type
70
- @criticality = Changes::Criticality.breaking
85
+ @criticality = Changes::Criticality.breaking(
86
+ reason: "Changing the kind of a type is a breaking change because it can cause existing queries to error. For example, turning an object type to a scalar type would break queries that define a selection set for this type."
87
+ )
71
88
  end
72
89
 
73
90
  def message
74
- "`#{old_type.name}` kind changed from `#{old_type.kind}` to `#{new_type.kind}`"
91
+ "`#{old_type.graphql_definition}` kind changed from `#{old_type.kind}` to `#{new_type.kind}`"
92
+ end
93
+
94
+ def path
95
+ old_type.graphql_definition.to_s
75
96
  end
76
97
  end
77
98
 
@@ -81,11 +102,17 @@ module GraphQL
81
102
  def initialize(enum_type, enum_value)
82
103
  @enum_value = enum_value
83
104
  @enum_type = enum_type
84
- @criticality = Changes::Criticality.breaking
105
+ @criticality = Changes::Criticality.breaking(
106
+ reason: "Removing an enum value will cause existing queries that use this enum value to error."
107
+ )
85
108
  end
86
109
 
87
110
  def message
88
- "Enum value `#{enum_value.name}` was removed from enum `#{enum_type.name}`"
111
+ "Enum value `#{enum_value.graphql_name}` was removed from enum `#{enum_type.graphql_definition}`"
112
+ end
113
+
114
+ def path
115
+ [enum_type.graphql_definition, enum_value.graphql_name].join('.')
89
116
  end
90
117
  end
91
118
 
@@ -95,11 +122,17 @@ module GraphQL
95
122
  def initialize(union_type, union_member)
96
123
  @union_member = union_member
97
124
  @union_type = union_type
98
- @criticality = Changes::Criticality.breaking
125
+ @criticality = Changes::Criticality.breaking(
126
+ reason: "Removing a union member from a union can cause existing queries that use this union member in a fragment spread to error."
127
+ )
99
128
  end
100
129
 
101
130
  def message
102
- "Union member `#{union_member.name}` was removed from Union type `#{union_type.name}`"
131
+ "Union member `#{union_member.graphql_name}` was removed from Union type `#{union_type.graphql_definition}`"
132
+ end
133
+
134
+ def path
135
+ union_type.graphql_definition.to_s
103
136
  end
104
137
  end
105
138
 
@@ -109,11 +142,17 @@ module GraphQL
109
142
  def initialize(input_object_type, field)
110
143
  @input_object_type = input_object_type
111
144
  @field = field
112
- @criticality = Changes::Criticality.breaking
145
+ @criticality = Changes::Criticality.breaking(
146
+ reason: "Removing an input field will cause existing queries that use this input field to error."
147
+ )
113
148
  end
114
149
 
115
150
  def message
116
- "Input field `#{field.name}` was removed from input object type `#{input_object_type.name}`"
151
+ "Input field `#{field.graphql_name}` was removed from input object type `#{input_object_type.graphql_definition}`"
152
+ end
153
+
154
+ def path
155
+ [input_object_type.graphql_definition, field.graphql_name].join('.')
117
156
  end
118
157
  end
119
158
 
@@ -124,11 +163,17 @@ module GraphQL
124
163
  @object_type = object_type
125
164
  @field = field
126
165
  @argument = argument
127
- @criticality = Changes::Criticality.breaking
166
+ @criticality = Changes::Criticality.breaking(
167
+ reason: "Removing a field argument is a breaking change because it will cause existing queries that use this argument to error."
168
+ )
128
169
  end
129
170
 
130
171
  def message
131
- "Argument `#{argument.name}: #{argument.type}` was removed from field `#{object_type.name}.#{field.name}`"
172
+ "Argument `#{argument.graphql_name}: #{argument.type.graphql_definition}` was removed from field `#{object_type.graphql_definition}.#{field.graphql_name}`"
173
+ end
174
+
175
+ def path
176
+ [object_type.graphql_definition, field.graphql_name, argument.graphql_name].join('.')
132
177
  end
133
178
  end
134
179
 
@@ -142,7 +187,11 @@ module GraphQL
142
187
  end
143
188
 
144
189
  def message
145
- "Argument `#{argument.name}` was removed from directive `#{directive.name}`"
190
+ "Argument `#{argument.graphql_name}` was removed from directive `#{directive.graphql_name}`"
191
+ end
192
+
193
+ def path
194
+ ["@#{directive.graphql_name}", argument.graphql_name].join('.')
146
195
  end
147
196
  end
148
197
 
@@ -156,7 +205,11 @@ module GraphQL
156
205
  end
157
206
 
158
207
  def message
159
- "Schema query root has changed from `#{old_schema.query.name}` to `#{new_schema.query.name}`"
208
+ "Schema query root has changed from `#{old_schema.query.graphql_name}` to `#{new_schema.query.graphql_name}`"
209
+ end
210
+
211
+ def path
212
+ # TODO
160
213
  end
161
214
  end
162
215
 
@@ -166,11 +219,25 @@ module GraphQL
166
219
  def initialize(object_type, field)
167
220
  @object_type = object_type
168
221
  @field = field
169
- @criticality = Changes::Criticality.breaking
222
+
223
+ if field.deprecation_reason
224
+ @criticality = Changes::Criticality.breaking(
225
+ reason: "Removing a deprecated field is a breaking change. Before removing it, you may want" \
226
+ "to look at the field's usage to see the impact of removing the field."
227
+ )
228
+ else
229
+ @criticality = Changes::Criticality.breaking(
230
+ reason: "Removing a field is a breaking change. It is preferable to deprecate the field before removing it."
231
+ )
232
+ end
170
233
  end
171
234
 
172
235
  def message
173
- "Field `#{field.name}` was removed from object type `#{object_type.name}`"
236
+ "Field `#{field.graphql_name}` was removed from object type `#{object_type.graphql_definition}`"
237
+ end
238
+
239
+ def path
240
+ [object_type.graphql_definition, field.graphql_name].join('.')
174
241
  end
175
242
  end
176
243
 
@@ -184,7 +251,11 @@ module GraphQL
184
251
  end
185
252
 
186
253
  def message
187
- "Location `#{location}` was removed from directive `#{directive.name}`"
254
+ "Location `#{location}` was removed from directive `#{directive.graphql_name}`"
255
+ end
256
+
257
+ def path
258
+ "@#{directive.graphql_name}"
188
259
  end
189
260
  end
190
261
 
@@ -194,11 +265,17 @@ module GraphQL
194
265
  def initialize(interface, object_type)
195
266
  @interface = interface
196
267
  @object_type = object_type
197
- @criticality = Changes::Criticality.breaking
268
+ @criticality = Changes::Criticality.breaking(
269
+ reason: "Removing an interface from an object type can cause existing queries that use this in a fragment spread to error."
270
+ )
198
271
  end
199
272
 
200
273
  def message
201
- "`#{object_type.name}` object type no longer implements `#{interface.name}` interface"
274
+ "`#{object_type.graphql_definition}` object type no longer implements `#{interface.graphql_name}` interface"
275
+ end
276
+
277
+ def path
278
+ object_type.graphql_definition.to_s
202
279
  end
203
280
  end
204
281
 
@@ -214,16 +291,20 @@ module GraphQL
214
291
  end
215
292
 
216
293
  def message
217
- "Field `#{type}.#{old_field.name}` changed type from `#{old_field.type}` to `#{new_field.type}`"
294
+ "Field `#{type.graphql_definition}.#{old_field.graphql_name}` changed type from `#{old_field.type.graphql_definition}` to `#{new_field.type.graphql_definition}`"
218
295
  end
219
296
 
220
297
  def criticality
221
298
  if safe_change_for_field?(old_field.type, new_field.type)
222
299
  Changes::Criticality.non_breaking
223
300
  else
224
- Changes::Criticality.breaking
301
+ Changes::Criticality.breaking # TODO - Add reason
225
302
  end
226
303
  end
304
+
305
+ def path
306
+ [type.graphql_definition, old_field.graphql_name].join('.')
307
+ end
227
308
  end
228
309
 
229
310
  class InputFieldTypeChanged < AbstractChange
@@ -237,7 +318,9 @@ module GraphQL
237
318
  reason: "Changing an input field from non-null to null is considered non-breaking"
238
319
  )
239
320
  else
240
- @criticality = Changes::Criticality.breaking
321
+ @criticality = Changes::Criticality.breaking(
322
+ reason: "Changing the type of an input field can cause existing queries that use this field to error."
323
+ )
241
324
  end
242
325
 
243
326
  @input_type = input_type
@@ -246,7 +329,11 @@ module GraphQL
246
329
  end
247
330
 
248
331
  def message
249
- "Input field `#{input_type}.#{old_input_field.name}` changed type from `#{old_input_field.type}` to `#{new_input_field.type}`"
332
+ "Input field `#{input_type.graphql_definition}.#{old_input_field.graphql_name}` changed type from `#{old_input_field.type.graphql_definition}` to `#{new_input_field.type.graphql_definition}`"
333
+ end
334
+
335
+ def path
336
+ [input_type.graphql_definition, old_input_field.graphql_name].join('.')
250
337
  end
251
338
  end
252
339
 
@@ -261,7 +348,9 @@ module GraphQL
261
348
  reason: "Changing an input field from non-null to null is considered non-breaking"
262
349
  )
263
350
  else
264
- @criticality = Changes::Criticality.breaking
351
+ @criticality = Changes::Criticality.breaking(
352
+ reason: "Changing the type of a field's argument can cause existing queries that use this argument to error."
353
+ )
265
354
  end
266
355
 
267
356
  @type = type
@@ -271,8 +360,12 @@ module GraphQL
271
360
  end
272
361
 
273
362
  def message
274
- "Type for argument `#{new_argument.name}` on field `#{type.name}.#{field.name}` changed"\
275
- " from `#{old_argument.type}` to `#{new_argument.type}`"
363
+ "Type for argument `#{new_argument.graphql_name}` on field `#{type.graphql_definition}.#{field.graphql_definition.name}` changed"\
364
+ " from `#{old_argument.type.graphql_definition}` to `#{new_argument.type.graphql_definition}`"
365
+ end
366
+
367
+ def path
368
+ [type.graphql_definition, field.graphql_definition.name, old_argument.graphql_name].join('.')
276
369
  end
277
370
  end
278
371
 
@@ -296,8 +389,12 @@ module GraphQL
296
389
  end
297
390
 
298
391
  def message
299
- "Type for argument `#{new_argument.name}` on directive `#{directive.name}` changed"\
300
- " from `#{old_argument.type}` to `#{new_argument.type}`"
392
+ "Type for argument `#{new_argument.graphql_name}` on directive `#{directive.graphql_name}` changed"\
393
+ " from `#{old_argument.type.graphql_definition}` to `#{new_argument.type.graphql_definition}`"
394
+ end
395
+
396
+ def path
397
+ ["@#{directive.graphql_name}", old_argument.graphql_name].join('.')
301
398
  end
302
399
  end
303
400
 
@@ -313,6 +410,10 @@ module GraphQL
313
410
  def message
314
411
  "Schema mutation root has changed from `#{old_schema.mutation}` to `#{new_schema.mutation}`"
315
412
  end
413
+
414
+ def path
415
+ # TODO
416
+ end
316
417
  end
317
418
 
318
419
  class SchemaSubscriptionTypeChanged < AbstractChange
@@ -327,6 +428,10 @@ module GraphQL
327
428
  def message
328
429
  "Schema subscription type has changed from `#{old_schema.subscription}` to `#{new_schema.subscription}`"
329
430
  end
431
+
432
+ def path
433
+ # TODO
434
+ end
330
435
  end
331
436
 
332
437
  # Dangerous Changes
@@ -346,8 +451,16 @@ module GraphQL
346
451
  end
347
452
 
348
453
  def message
349
- "Default value for argument `#{new_argument.name}` on field `#{type.name}.#{field.name}` changed"\
350
- " from `#{old_argument.default_value}` to `#{new_argument.default_value}`"
454
+ if old_argument.default_value.nil? || old_argument.default_value == :__no_default__
455
+ "Default value `#{new_argument.default_value}` was added to argument `#{new_argument.graphql_name}` on field `#{type.graphql_definition}.#{field.graphql_name}`"
456
+ else
457
+ "Default value for argument `#{new_argument.graphql_name}` on field `#{type.graphql_definition}.#{field.name}` changed"\
458
+ " from `#{old_argument.default_value}` to `#{new_argument.default_value}`"
459
+ end
460
+ end
461
+
462
+ def path
463
+ [type.graphql_definition, field.graphql_name, old_argument.graphql_name].join('.')
351
464
  end
352
465
  end
353
466
 
@@ -365,9 +478,13 @@ module GraphQL
365
478
  end
366
479
 
367
480
  def message
368
- "Input field `#{input_type.name}.#{old_field.name}` default changed"\
481
+ "Input field `#{input_type.graphql_definition}.#{old_field.graphql_name}` default changed"\
369
482
  " from `#{old_field.default_value}` to `#{new_field.default_value}`"
370
483
  end
484
+
485
+ def path
486
+ [input_type.graphql_definition, old_field.graphql_name].join(".")
487
+ end
371
488
  end
372
489
 
373
490
  class DirectiveArgumentDefaultChanged < AbstractChange
@@ -384,9 +501,13 @@ module GraphQL
384
501
  end
385
502
 
386
503
  def message
387
- "Default value for argument `#{new_argument.name}` on directive `#{directive.name}` changed"\
504
+ "Default value for argument `#{new_argument.graphql_name}` on directive `#{directive.graphql_name}` changed"\
388
505
  " from `#{old_argument.default_value}` to `#{new_argument.default_value}`"
389
506
  end
507
+
508
+ def path
509
+ ["@#{directive.graphql_name}", new_argument.graphql_name].join(".")
510
+ end
390
511
  end
391
512
 
392
513
  class EnumValueAdded < AbstractChange
@@ -402,7 +523,11 @@ module GraphQL
402
523
  end
403
524
 
404
525
  def message
405
- "Enum value `#{enum_value.name}` was added to enum `#{enum_type.name}`"
526
+ "Enum value `#{enum_value.graphql_name}` was added to enum `#{enum_type.graphql_definition}`"
527
+ end
528
+
529
+ def path
530
+ [enum_type.graphql_definition, enum_value.graphql_name].join(".")
406
531
  end
407
532
  end
408
533
 
@@ -419,7 +544,11 @@ module GraphQL
419
544
  end
420
545
 
421
546
  def message
422
- "Union member `#{union_member.name}` was added to Union type `#{union_type.name}`"
547
+ "Union member `#{union_member.graphql_name}` was added to Union type `#{union_type.graphql_definition}`"
548
+ end
549
+
550
+ def path
551
+ union_type.graphql_definition.to_s
423
552
  end
424
553
  end
425
554
 
@@ -436,7 +565,11 @@ module GraphQL
436
565
  end
437
566
 
438
567
  def message
439
- "`#{object_type.name}` object implements `#{interface.name}` interface"
568
+ "`#{object_type.graphql_definition}` object implements `#{interface.graphql_name}` interface"
569
+ end
570
+
571
+ def path
572
+ object_type.graphql_definition.to_s
440
573
  end
441
574
  end
442
575
 
@@ -447,7 +580,7 @@ module GraphQL
447
580
 
448
581
  def initialize(input_object_type, field)
449
582
  @criticality = if field.type.non_null?
450
- Changes::Criticality.breaking
583
+ Changes::Criticality.breaking(reason: "Adding a non-null field to an existing input type will cause existing queries that use this input type to error because they will not provide a value for this new field.")
451
584
  else
452
585
  Changes::Criticality.non_breaking
453
586
  end
@@ -457,7 +590,11 @@ module GraphQL
457
590
  end
458
591
 
459
592
  def message
460
- "Input field `#{field.name}` was added to input object type `#{input_object_type.name}`"
593
+ "Input field `#{field.graphql_name}` was added to input object type `#{input_object_type.graphql_definition}`"
594
+ end
595
+
596
+ def path
597
+ [input_object_type.graphql_definition, field.graphql_name].join(".")
461
598
  end
462
599
  end
463
600
 
@@ -466,7 +603,7 @@ module GraphQL
466
603
 
467
604
  def initialize(type, field, argument)
468
605
  @criticality = if argument.type.non_null?
469
- Changes::Criticality.breaking
606
+ Changes::Criticality.breaking(reason: "Adding a required argument to an existing field is a breaking change because it will cause existing uses of this field to error.")
470
607
  else
471
608
  Changes::Criticality.non_breaking
472
609
  end
@@ -477,7 +614,11 @@ module GraphQL
477
614
  end
478
615
 
479
616
  def message
480
- "Argument `#{argument.name}: #{argument.type}` added to field `#{type.name}.#{field.name}`"
617
+ "Argument `#{argument.graphql_name}: #{argument.type.graphql_definition}` added to field `#{type.graphql_definition}.#{field.graphql_name}`"
618
+ end
619
+
620
+ def path
621
+ [type.graphql_definition, field.graphql_name, argument.graphql_name].join(".")
481
622
  end
482
623
  end
483
624
 
@@ -490,7 +631,11 @@ module GraphQL
490
631
  end
491
632
 
492
633
  def message
493
- "Type `#{type.name}` was added"
634
+ "Type `#{type.graphql_definition}` was added"
635
+ end
636
+
637
+ def path
638
+ type.graphql_definition.to_s
494
639
  end
495
640
  end
496
641
 
@@ -503,7 +648,11 @@ module GraphQL
503
648
  end
504
649
 
505
650
  def message
506
- "Directive `#{directive.name}` was added"
651
+ "Directive `#{directive.graphql_name}` was added"
652
+ end
653
+
654
+ def path
655
+ "@#{directive.graphql_name}"
507
656
  end
508
657
  end
509
658
 
@@ -517,7 +666,11 @@ module GraphQL
517
666
  end
518
667
 
519
668
  def message
520
- "Description `#{old_type.description}` on type `#{old_type.name}` has changed to `#{new_type.description}`"
669
+ "Description `#{old_type.description}` on type `#{old_type.graphql_definition}` has changed to `#{new_type.description}`"
670
+ end
671
+
672
+ def path
673
+ old_type.graphql_definition.to_s
521
674
  end
522
675
  end
523
676
 
@@ -532,9 +685,13 @@ module GraphQL
532
685
  end
533
686
 
534
687
  def message
535
- "Description for enum value `#{enum.name}.#{new_enum_value.name}` changed from " \
688
+ "Description for enum value `#{enum.graphql_name}.#{new_enum_value.graphql_name}` changed from " \
536
689
  "`#{old_enum_value.description}` to `#{new_enum_value.description}`"
537
690
  end
691
+
692
+ def path
693
+ [enum.graphql_name, old_enum_value.graphql_name].join(".")
694
+ end
538
695
  end
539
696
 
540
697
  class EnumValueDeprecated < AbstractChange
@@ -549,13 +706,17 @@ module GraphQL
549
706
 
550
707
  def message
551
708
  if old_enum_value.deprecation_reason
552
- "Enum value `#{enum.name}.#{new_enum_value.name}` deprecation reason changed " \
709
+ "Enum value `#{enum.graphql_name}.#{new_enum_value.graphql_name}` deprecation reason changed " \
553
710
  "from `#{old_enum_value.deprecation_reason}` to `#{new_enum_value.deprecation_reason}`"
554
711
  else
555
- "Enum value `#{enum.name}.#{new_enum_value.name}` was deprecated with reason" \
712
+ "Enum value `#{enum.graphql_name}.#{new_enum_value.graphql_name}` was deprecated with reason" \
556
713
  " `#{new_enum_value.deprecation_reason}`"
557
714
  end
558
715
  end
716
+
717
+ def path
718
+ [enum.graphql_name, old_enum_value.graphql_name].join(".")
719
+ end
559
720
  end
560
721
 
561
722
  class InputFieldDescriptionChanged < AbstractChange
@@ -569,9 +730,13 @@ module GraphQL
569
730
  end
570
731
 
571
732
  def message
572
- "Input field `#{input_type.name}.#{old_field.name}` description changed"\
733
+ "Input field `#{input_type.graphql_definition}.#{old_field.graphql_name}` description changed"\
573
734
  " from `#{old_field.description}` to `#{new_field.description}`"
574
735
  end
736
+
737
+ def path
738
+ [input_type.graphql_definition, old_field.graphql_name].join(".")
739
+ end
575
740
  end
576
741
 
577
742
  class DirectiveDescriptionChanged < AbstractChange
@@ -584,9 +749,13 @@ module GraphQL
584
749
  end
585
750
 
586
751
  def message
587
- "Directive `#{new_directive.name}` description changed"\
752
+ "Directive `#{new_directive.graphql_name}` description changed"\
588
753
  " from `#{old_directive.description}` to `#{new_directive.description}`"
589
754
  end
755
+
756
+ def path
757
+ "@#{old_directive.graphql_name}"
758
+ end
590
759
  end
591
760
 
592
761
  class FieldDescriptionChanged < AbstractChange
@@ -600,9 +769,13 @@ module GraphQL
600
769
  end
601
770
 
602
771
  def message
603
- "Field `#{type.name}.#{old_field.name}` description changed"\
772
+ "Field `#{type.graphql_definition}.#{old_field.graphql_name}` description changed"\
604
773
  " from `#{old_field.description}` to `#{new_field.description}`"
605
774
  end
775
+
776
+ def path
777
+ [type.graphql_definition, old_field.graphql_name].join(".")
778
+ end
606
779
  end
607
780
 
608
781
  class FieldArgumentDescriptionChanged < AbstractChange
@@ -617,9 +790,13 @@ module GraphQL
617
790
  end
618
791
 
619
792
  def message
620
- "Description for argument `#{new_argument.name}` on field `#{type.name}.#{field.name}` changed"\
793
+ "Description for argument `#{new_argument.graphql_name}` on field `#{type.graphql_definition}.#{field.graphql_name}` changed"\
621
794
  " from `#{old_argument.description}` to `#{new_argument.description}`"
622
795
  end
796
+
797
+ def path
798
+ [type.graphql_definition, field.graphql_name, old_argument.graphql_name].join(".")
799
+ end
623
800
  end
624
801
 
625
802
  class DirectiveArgumentDescriptionChanged < AbstractChange
@@ -633,9 +810,13 @@ module GraphQL
633
810
  end
634
811
 
635
812
  def message
636
- "Description for argument `#{new_argument.name}` on directive `#{directive.name}` changed"\
813
+ "Description for argument `#{new_argument.graphql_name}` on directive `#{directive.graphql_name}` changed"\
637
814
  " from `#{old_argument.description}` to `#{new_argument.description}`"
638
815
  end
816
+
817
+ def path
818
+ ["@#{directive.graphql_name}", old_argument.graphql_name].join(".")
819
+ end
639
820
  end
640
821
 
641
822
  class FieldDeprecationChanged < AbstractChange
@@ -649,9 +830,13 @@ module GraphQL
649
830
  end
650
831
 
651
832
  def message
652
- "Deprecation reason on field `#{type.name}.#{new_field.name}` has changed "\
833
+ "Deprecation reason on field `#{type.graphql_definition}.#{new_field.graphql_name}` has changed "\
653
834
  "from `#{old_field.deprecation_reason}` to `#{new_field.deprecation_reason}`"
654
835
  end
836
+
837
+ def path
838
+ [type.graphql_definition, old_field.graphql_name].join(".")
839
+ end
655
840
  end
656
841
 
657
842
  class FieldAdded < AbstractChange
@@ -664,9 +849,12 @@ module GraphQL
664
849
  end
665
850
 
666
851
  def message
667
- "Field `#{field.name}` was added to object type `#{object_type.name}`"
852
+ "Field `#{field.graphql_name}` was added to object type `#{object_type.graphql_definition}`"
668
853
  end
669
854
 
855
+ def path
856
+ [object_type.graphql_definition, field.graphql_name].join(".")
857
+ end
670
858
  end
671
859
 
672
860
  class DirectiveLocationAdded < AbstractChange
@@ -679,7 +867,11 @@ module GraphQL
679
867
  end
680
868
 
681
869
  def message
682
- "Location `#{location}` was added to directive `#{directive.name}`"
870
+ "Location `#{location}` was added to directive `#{directive.graphql_name}`"
871
+ end
872
+
873
+ def path
874
+ "@#{directive.graphql_name}"
683
875
  end
684
876
  end
685
877
 
@@ -841,7 +1033,7 @@ module GraphQL
841
1033
  end
842
1034
 
843
1035
  def message
844
- "Argument `#{argument.name}` was added to directive `#{directive.name}`"
1036
+ "Argument `#{argument.graphql_name}` was added to directive `#{directive.graphql_name}`"
845
1037
  end
846
1038
  end
847
1039
  end
@@ -21,7 +21,7 @@ module GraphQL
21
21
  changes << Changes::FieldArgumentDefaultChanged.new(type, field, old_arg, new_arg)
22
22
  end
23
23
 
24
- if old_arg.type != new_arg.type
24
+ if old_arg.type.graphql_definition != new_arg.type.graphql_definition
25
25
  changes << Changes::FieldArgumentTypeChanged.new(type, field, old_arg, new_arg)
26
26
  end
27
27
 
@@ -49,8 +49,8 @@ module GraphQL
49
49
  def each_common_argument(&block)
50
50
  intersection = old_arguments.keys & new_arguments.keys
51
51
  intersection.each do |common_arg|
52
- old_arg = new_directive.arguments[common_arg]
53
- new_arg = old_directive.arguments[common_arg]
52
+ old_arg = old_directive.arguments[common_arg]
53
+ new_arg = new_directive.arguments[common_arg]
54
54
 
55
55
  block.call(old_arg, new_arg)
56
56
  end
@@ -19,7 +19,7 @@ module GraphQL
19
19
  changes << Changes::DirectiveArgumentDefaultChanged.new(directive, old_arg, new_arg)
20
20
  end
21
21
 
22
- if old_arg.type != new_arg.type
22
+ if old_arg.type.graphql_definition != new_arg.type.graphql_definition
23
23
  changes << Changes::DirectiveArgumentTypeChanged.new(directive, old_arg, new_arg)
24
24
  end
25
25
 
@@ -24,7 +24,7 @@ module GraphQL
24
24
  changes << Changes::FieldDeprecationChanged.new(new_type, old_field, new_field)
25
25
  end
26
26
 
27
- if old_field.type != new_field.type
27
+ if old_field.type.graphql_definition != new_field.type.graphql_definition
28
28
  changes << Changes::FieldTypeChanged.new(new_type, old_field, new_field)
29
29
  end
30
30
 
@@ -21,7 +21,7 @@ module GraphQL
21
21
  changes << Changes::InputFieldDefaultChanged.new(old_type, old_field, new_field)
22
22
  end
23
23
 
24
- if old_field.type != new_field.type
24
+ if old_field.type.graphql_definition != new_field.type.graphql_definition
25
25
  changes << Changes::InputFieldTypeChanged.new(old_type, old_field, new_field)
26
26
  end
27
27
 
@@ -3,8 +3,8 @@ module GraphQL
3
3
  module Diff
4
4
  class ObjectType
5
5
  def initialize(old_type, new_type)
6
- @old_type = old_type
7
- @new_type = new_type
6
+ @old_type = old_type.graphql_definition
7
+ @new_type = new_type.graphql_definition
8
8
 
9
9
  @old_fields = old_type.fields
10
10
  @new_fields = new_type.fields
@@ -40,15 +40,19 @@ module GraphQL
40
40
  )
41
41
 
42
42
  def interface_removals
43
- removed = old_interfaces.select { |iface| !new_interfaces.include?(iface) }
43
+ removed = filter_interfaces(old_interfaces, new_interfaces)
44
44
  removed.map { |iface| Changes::ObjectTypeInterfaceRemoved.new(iface, old_type) }
45
45
  end
46
46
 
47
47
  def interface_additions
48
- added = new_interfaces.select { |iface| !old_interfaces.include?(iface) }
48
+ added = filter_interfaces(new_interfaces, old_interfaces)
49
49
  added.map { |iface| Changes::ObjectTypeInterfaceAdded.new(iface, new_type) }
50
50
  end
51
51
 
52
+ def filter_interfaces(interfaces, excluded_interfaces)
53
+ interfaces.select { |interface| !excluded_interfaces.map(&:graphql_definition).include?(interface.graphql_definition) }
54
+ end
55
+
52
56
  def field_removals
53
57
  removed = old_fields.values.select { |field| !new_fields[field.name] }
54
58
  removed.map { |field| Changes::FieldRemoved.new(old_type, field) }
@@ -40,7 +40,7 @@ module GraphQL
40
40
  if old_type.kind != new_type.kind
41
41
  changes << Changes::TypeKindChanged.new(old_type, new_type)
42
42
  else
43
- case old_type
43
+ case old_type.graphql_definition
44
44
  when GraphQL::EnumType
45
45
  changes += Diff::Enum.new(old_type, new_type).diff
46
46
  when GraphQL::UnionType
@@ -64,15 +64,15 @@ module GraphQL
64
64
  def changes_in_schema
65
65
  changes = []
66
66
 
67
- if old_schema.query != new_schema.query
67
+ if old_schema.query&.to_graphql != new_schema.query&.to_graphql
68
68
  changes << Changes::SchemaQueryTypeChanged.new(old_schema, new_schema)
69
69
  end
70
70
 
71
- if old_schema.mutation != new_schema.mutation
71
+ if old_schema.mutation&.to_graphql != new_schema.mutation&.to_graphql
72
72
  changes << Changes::SchemaMutationTypeChanged.new(old_schema, new_schema)
73
73
  end
74
74
 
75
- if old_schema.subscription != new_schema.subscription
75
+ if old_schema.subscription&.to_graphql != new_schema.subscription&.to_graphql
76
76
  changes << Changes::SchemaSubscriptionTypeChanged.new(old_schema, new_schema)
77
77
  end
78
78
 
@@ -26,11 +26,15 @@ module GraphQL
26
26
  attr_reader :old_type, :new_type, :old_possible_types, :new_possible_types
27
27
 
28
28
  def removed_possible_types
29
- old_possible_types.select { |type| !new_possible_types.include?(type) }
29
+ filter_types(old_possible_types, new_possible_types)
30
30
  end
31
31
 
32
32
  def added_possible_types
33
- new_possible_types.select { |type| !old_possible_types.include?(type) }
33
+ filter_types(new_possible_types, old_possible_types)
34
+ end
35
+
36
+ def filter_types(types, exclude_types)
37
+ types.select { |type| !exclude_types.map(&:graphql_definition).include?(type.graphql_definition) }
34
38
  end
35
39
  end
36
40
  end
@@ -1,5 +1,5 @@
1
1
  module GraphQL
2
2
  module SchemaComparator
3
- VERSION = "0.5.0"
3
+ VERSION = "1.0.1"
4
4
  end
5
5
  end
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.5.0
4
+ version: 1.0.1
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-12-02 00:00:00.000000000 Z
11
+ date: 2021-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -16,40 +16,46 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.6'
19
+ version: '1.10'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.6'
26
+ version: '1.10'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: thor
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0.19'
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '2.0'
34
37
  type: :runtime
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
38
- - - "~>"
41
+ - - ">="
39
42
  - !ruby/object:Gem::Version
40
43
  version: '0.19'
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.0'
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: bundler
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
- - - "~>"
51
+ - - ">="
46
52
  - !ruby/object:Gem::Version
47
53
  version: '1.14'
48
- type: :development
54
+ type: :runtime
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
51
57
  requirements:
52
- - - "~>"
58
+ - - ">="
53
59
  - !ruby/object:Gem::Version
54
60
  version: '1.14'
55
61
  - !ruby/object:Gem::Dependency
@@ -104,8 +110,8 @@ executables:
104
110
  extensions: []
105
111
  extra_rdoc_files: []
106
112
  files:
113
+ - ".github/workflows/ci.yml"
107
114
  - ".gitignore"
108
- - ".travis.yml"
109
115
  - CHANGELOG.md
110
116
  - CODE_OF_CONDUCT.md
111
117
  - Gemfile
@@ -155,8 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
161
  - !ruby/object:Gem::Version
156
162
  version: '0'
157
163
  requirements: []
158
- rubyforge_project:
159
- rubygems_version: 2.6.8
164
+ rubygems_version: 3.0.3
160
165
  signing_key:
161
166
  specification_version: 4
162
167
  summary: Compare GraphQL schemas and get the changes that happened.
data/.travis.yml DELETED
@@ -1,10 +0,0 @@
1
- ---
2
- language: ruby
3
- sudo: false
4
- cache: bundler
5
- before_install:
6
- - gem update --system --no-doc
7
- - gem install bundler
8
- rvm:
9
- - 2.3.4
10
- - 2.4.1