graphql-schema_comparator 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 16377eaa74c85158d06801b8224c09d863de9e36
4
+ data.tar.gz: 9f1cf164f223b30cc7acd3620aa46e843ed04ea9
5
+ SHA512:
6
+ metadata.gz: 72e276a27111484f51ee9bdf9a6b17a5420438c8db32601cdacda917677e0e3e1f0a4f9858e8a3e2a5dc00e3b6310b9587ffa248e2cd33ad79b364ee7d959043
7
+ data.tar.gz: be997a8f471e654a341d7a72d95e2940ec9f7eb2811dd73e73b4f657b67af4a6e628bf37ff411ff3a82ba059717bc058c28750326c2587098eac97d11ae7c7aa
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at mgiroux0@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in graphql-schema_comparator.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 TODO: Write your name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # GraphQL::SchemaComparator
2
+
3
+ `GraphQL::SchemaComparator` is a GraphQL Schema comparator. What does that mean? `GraphQL::SchemaComparator` takes
4
+ two GraphQL schemas and outputs a list of changes that happened between the two versions. This is useful for many things:
5
+
6
+ - Breaking Change detection
7
+ - Applying custom rules to schema changes
8
+ - Building automated tools like linters
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'graphql-schema_comparator'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ $ bundle
21
+
22
+ Or install it yourself as:
23
+
24
+ $ gem install graphql-schema_comparator
25
+
26
+ ## CLI
27
+
28
+ `GraphQL::SchemaComparator` comes with a handy CLI to help compare two schemas using
29
+ the commandline.
30
+
31
+ After a `gem install graphql-schema_comparator`, use the CLI this way:
32
+
33
+ ```
34
+ Commands:
35
+ graphql-schema compare OLD_SCHEMA NEW_SCHEMA # Compares OLD_SCHEMA with NEW_SCHEMA and returns a list of changes
36
+ graphql-schema help [COMMAND] # Describe available commands or one specific command
37
+ ```
38
+
39
+ Where OLD_SCHEMA and NEW_SCHEMA can be a string containing a schema IDL or a filename where that IDL is located.
40
+
41
+ ### Example
42
+
43
+ ![comparator result](http://i.imgur.com/FnItukM.png)
44
+
45
+ ## Usage
46
+
47
+ `GraphQL::SchemaComparator`, provides a simple api for Ruby applications to use.
48
+
49
+ ### GraphQL::SchemaComparator.compare
50
+
51
+ The compare method takes two arguments, `old_schema` and `new_schema`, the two schemas to compare.
52
+
53
+ You may provide schema IDL as strings, or provide instances of `GraphQL::Schema`.
54
+
55
+ The result of `compare` returns a `SchemaComparator::Result` object, from which you can
56
+ access information on the changes between the two schemas.
57
+
58
+ - `result.breaking?` returns true if any breaking changes were found between the two schemas
59
+ - `result.identical?` returns true if the two schemas were identical
60
+ - `result.breaking_changes` returns the list of breaking changes found between schemas.
61
+ - `result.changes` returns the full list of change objects.
62
+
63
+ ### Change Objects
64
+
65
+ Change objects are considered any objects that respond to `message` and `breaking` and they
66
+ are all namespaced under the `Changes` module.
67
+
68
+ Possible changes are all found in [changes.rb](lib/graphql/schema_comparator/changes.rb).
69
+
70
+ ## TODO
71
+
72
+ - [ ] Handle changes in schema directives
73
+ - [ ] Test each differ
74
+
75
+ ## Development
76
+
77
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
78
+
79
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
80
+
81
+ ## Contributing
82
+
83
+ Bug reports and pull requests are welcome on GitHub at https://github.com/xuorig/graphql-schema_comparator. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
84
+
85
+
86
+ ## License
87
+
88
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'lib'
8
+ t.libs << 'test'
9
+ t.test_files = FileList[
10
+ 'test/lib/graphql/schema_comparator/*/*_test.rb',
11
+ 'test/lib/graphql/schema_comparator/*_test.rb',
12
+ 'test/lib/graphql/*_test.rb'
13
+ ]
14
+ t.verbose = true
15
+ end
16
+
17
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "graphql/schema_comparator"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "thor"
5
+ require "graphql/schema_comparator"
6
+
7
+ class GraphQLSchema < Thor
8
+ desc "compare OLD_SCHEMA NEW_SCHEMA", "Compares OLD_SCHEMA with NEW_SCHEMA and returns a list of changes"
9
+
10
+ def compare(old_schema, new_schema)
11
+ parsed_old = parse_schema(old_schema)
12
+ parsed_new = parse_schema(new_schema)
13
+
14
+ say "🤖 Checking for changes..."
15
+ result = GraphQL::SchemaComparator.compare(parsed_old, parsed_new)
16
+
17
+ say "🎉 Done! Result:"
18
+ say "\n"
19
+
20
+ if result.identical?
21
+ say "✅ Schemas are identical"
22
+ else
23
+ print_changes(result)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def print_changes(result)
30
+ say "Detected the following changes between schemas:"
31
+ say "\n"
32
+
33
+ result.changes.each do |change|
34
+ if change.breaking
35
+ say "⚠️ #{change.message}", :yellow
36
+ else
37
+ say "✅ #{change.message}", :green
38
+ end
39
+ end
40
+ end
41
+
42
+ def parse_schema(schema)
43
+ if File.file?(schema)
44
+ File.read(schema)
45
+ elsif schema.is_a?(String)
46
+ schema
47
+ else
48
+ raise ArgumentError, "Invalid argument #{schema}. Must be an IDL string or file containing the schema IDL."
49
+ end
50
+ end
51
+ end
52
+
53
+ GraphQLSchema.start(ARGV)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'graphql/schema_comparator/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "graphql-schema_comparator"
8
+ spec.version = GraphQL::SchemaComparator::VERSION
9
+ spec.authors = ["Marc-Andre Giroux"]
10
+ spec.email = ["mgiroux0@gmail.com"]
11
+
12
+ spec.summary = %q{Compare GraphQL schemas and get the changes that happened.}
13
+ spec.description = %q{GraphQL::SchemaComparator compares two GraphQL schemas given their IDL and returns a list of changes.}
14
+ spec.homepage = "http://mgiroux.me"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "bin"
21
+ spec.executables = ["graphql-schema"]
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_dependency "graphql", "~> 1.6"
25
+ spec.add_dependency "thor", "~> 0.19"
26
+
27
+ spec.add_development_dependency "bundler", "~> 1.14"
28
+ spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency "minitest"
30
+ spec.add_development_dependency "pry-byebug"
31
+ end
@@ -0,0 +1,29 @@
1
+ require "graphql"
2
+ require "graphql/schema_comparator/version"
3
+ require "graphql/schema_comparator/diff/schema"
4
+ require "graphql/schema_comparator/changes"
5
+ require "graphql/schema_comparator/result"
6
+
7
+ module GraphQL
8
+ module SchemaComparator
9
+ def self.compare(old_schema, new_schema)
10
+ parsed_old = parse_schema(old_schema)
11
+ parsed_new = parse_schema(new_schema)
12
+
13
+ changes = Diff::Schema.new(parsed_old, parsed_new).diff
14
+ Result.new(changes)
15
+ end
16
+
17
+ private
18
+
19
+ def self.parse_schema(schema)
20
+ if schema.is_a?(GraphQL::Schema)
21
+ schema
22
+ elsif schema.is_a?(String)
23
+ GraphQL::Schema.from_definition(schema)
24
+ else
25
+ raise ArgumentError, "Invalid Schema #{schema}. Expected a valid IDL or GraphQL::Schema object."
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,608 @@
1
+ module GraphQL
2
+ module SchemaComparator
3
+ module Changes
4
+ # Breaking Changes
5
+
6
+ class TypeRemoved
7
+ attr_reader :removed_type, :breaking
8
+
9
+ def initialize(removed_type)
10
+ @removed_type = removed_type
11
+ @breaking = true
12
+ end
13
+
14
+ def message
15
+ "#{removed_type.name} was removed"
16
+ end
17
+ end
18
+
19
+ class DirectiveRemoved
20
+ attr_reader :removed_directive, :breaking
21
+
22
+ def initialize(removed_directive)
23
+ @removed_directive = removed_directive
24
+ @breaking = true
25
+ end
26
+
27
+ def message
28
+ "#{removed_directive.name} was removed"
29
+ end
30
+ end
31
+
32
+ class TypeKindChanged
33
+ attr_reader :old_type, :new_type, :breaking
34
+
35
+ def initialize(old_type, new_type)
36
+ @old_type = old_type
37
+ @new_type = new_type
38
+ @breaking = true
39
+ end
40
+
41
+ def message
42
+ "`#{old_type.name}` kind changed from `#{old_type.kind}` to `#{new_type.kind}`"
43
+ end
44
+ end
45
+
46
+ class EnumValueRemoved
47
+ attr_reader :enum_value, :enum_type, :breaking
48
+
49
+ def initialize(enum_value, enum_type)
50
+ @enum_value = enum_value
51
+ @enum_type = enum_type
52
+ @breaking = true
53
+ end
54
+
55
+ def message
56
+ "Enum Value #{enum_value.name} was removed from Enum #{enum_type.name}"
57
+ end
58
+ end
59
+
60
+ class UnionMemberRemoved
61
+ attr_reader :union_type, :union_member, :breaking
62
+
63
+ def initialize(union_type, union_member)
64
+ @union_member = union_member
65
+ @union_type = union_type
66
+ @breaking = true
67
+ end
68
+
69
+ def message
70
+ "Union member `#{union_member.name}` was removed from Union type `#{union_type.name}`"
71
+ end
72
+ end
73
+
74
+ class InputFieldRemoved
75
+ attr_reader :input_object_type, :field, :breaking
76
+
77
+ def initialize(input_object_type, field)
78
+ @input_object_type = input_object_type
79
+ @field = field
80
+ @breaking = true
81
+ end
82
+
83
+ def message
84
+ "Input field `#{field.name}` was removed from input object type `#{input_object_type.name}`"
85
+ end
86
+ end
87
+
88
+ class FieldArgumentRemoved
89
+ attr_reader :object_type, :field, :argument, :breaking
90
+
91
+ def initialize(object_type, field, argument)
92
+ @object_type = object_type
93
+ @field = field
94
+ @argument = argument
95
+ @breaking = true
96
+ end
97
+
98
+ def message
99
+ "Argument `#{argument.name}: #{argument.type}` was removed from field `#{object_type.name}.#{field.name}`"
100
+ end
101
+ end
102
+
103
+ # TODO
104
+ # class DirectiveArgumentRemoved
105
+ # end
106
+
107
+ class SchemaQueryTypeChanged
108
+ attr_reader :old_schema, :new_schema, :breaking
109
+
110
+ def initialize(old_schema, new_schema)
111
+ @old_schema = old_schema
112
+ @new_schema = new_schema
113
+ @breaking = true
114
+ end
115
+
116
+ def message
117
+ "Schema query root has changed from `#{old_schema.query.name}` to `#{new_schema.query.name}`"
118
+ end
119
+ end
120
+
121
+ class FieldRemoved
122
+ attr_reader :object_type, :field, :breaking
123
+
124
+ def initialize(object_type, field)
125
+ @object_type = object_type
126
+ @field = field
127
+ @breaking = true
128
+ end
129
+
130
+ def message
131
+ "Field `#{field.name}` was removed from object type `#{object_type.name}`"
132
+ end
133
+ end
134
+
135
+ # TODO
136
+ # class DirectiveLocationRemoved
137
+ # end
138
+
139
+ class ObjectTypeInterfaceRemoved
140
+ attr_reader :interface, :object_type, :breaking
141
+
142
+ def initialize(interface, object_type)
143
+ @interface = interface
144
+ @object_type = object_type
145
+ @breaking = true
146
+ end
147
+
148
+ def message
149
+ "`#{object_type.name}` object type no longer implements `#{interface.name}` interface"
150
+ end
151
+ end
152
+
153
+ # Non-Breaking Changes
154
+
155
+ class TypeAdded
156
+ attr_reader :type, :breaking
157
+
158
+ def initialize(type)
159
+ @type = type
160
+ @breaking = false
161
+ end
162
+
163
+ def message
164
+ "Type `#{type.name}` was added"
165
+ end
166
+ end
167
+
168
+ class DirectiveAdded
169
+ attr_reader :breaking
170
+
171
+ def initialize(*)
172
+ @breaking = false
173
+ end
174
+ end
175
+
176
+ class TypeDescriptionChanged
177
+ attr_reader :old_type, :new_type, :breaking
178
+
179
+ def initialize(old_type, new_type)
180
+ @old_type = old_type
181
+ @new_type = new_type
182
+ @breaking = false
183
+ end
184
+
185
+ def message
186
+ "Description `#{old_type.description}` on type `#{old_type.name}` has changed to `#{new_type.description}`"
187
+ end
188
+ end
189
+
190
+ class EnumValueAdded
191
+ attr_reader :enum_type, :enum_value, :breaking
192
+
193
+ def initialize(enum_type, enum_value)
194
+ @enum_type = enum_type
195
+ @enum_value = enum_value
196
+ @breaking = false
197
+ end
198
+
199
+ def message
200
+ "Enum value #{enum_value.name} was added on enum type #{enum_type.name}"
201
+ end
202
+ end
203
+
204
+ class EnumValueDescriptionChanged
205
+ def initialize(*)
206
+ end
207
+ end
208
+
209
+ class EnumValueDeprecated
210
+ def initialize(*)
211
+ end
212
+ end
213
+
214
+ class UnionMemberAdded
215
+ attr_reader :union_type, :union_member, :breaking
216
+
217
+ def initialize(union_type, union_member)
218
+ @union_member = union_member
219
+ @union_type = union_type
220
+ @breaking = false
221
+ end
222
+
223
+ def message
224
+ "Union member `#{union_member.name}` was added to Union type `#{union_type.name}`"
225
+ end
226
+ end
227
+
228
+ class InputFieldDescriptionChanged
229
+ attr_reader :input_type, :old_field, :new_field, :breaking
230
+
231
+ def initialize(input_type, old_field, new_field)
232
+ @input_type = input_type
233
+ @old_field = old_field
234
+ @new_field = new_field
235
+ @breaking = false
236
+ end
237
+
238
+ def message
239
+ "Input field `#{input_type.name}.#{old_field.name}` description changed"\
240
+ " from `#{old_field.description}` to `#{new_field.description}`"
241
+ end
242
+ end
243
+
244
+ class DirectiveDescriptionChanged
245
+ def initialize(*)
246
+ end
247
+ end
248
+
249
+ class FieldDescriptionChanged
250
+ attr_reader :type, :old_field, :new_field, :breaking
251
+
252
+ def initialize(type, old_field, new_field)
253
+ @type = type
254
+ @old_field = old_field
255
+ @new_field = new_field
256
+ @breaking = false
257
+ end
258
+
259
+ def message
260
+ "Field `#{type.name}.#{old_field.name}` description changed"\
261
+ " from `#{old_field.description}` to `#{new_field.description}`"
262
+ end
263
+ end
264
+
265
+ class FieldArgumentDescriptionChanged
266
+ attr_reader :type, :field, :old_argument, :new_argument, :breaking
267
+
268
+ def initialize(type, field, old_argument, new_argument)
269
+ @type = type
270
+ @field = field
271
+ @old_argument = old_argument
272
+ @new_argument = new_argument
273
+ @breaking = false
274
+ end
275
+
276
+ def message
277
+ "Description for argument `#{new_argument.name}` on field `#{type.name}.#{field.name}` changed"\
278
+ " from `#{old_argument.description}` to `#{new_argument.description}`"
279
+ end
280
+ end
281
+
282
+ class DirectiveArgumentDescriptionChanged
283
+ def initialize(*)
284
+ end
285
+ end
286
+
287
+ class FieldDeprecationChanged
288
+ attr_reader :type, :old_field, :new_field, :breaking
289
+
290
+ def initialize(type, old_field, new_field)
291
+ @type = type
292
+ @old_field = old_field
293
+ @new_field = new_field
294
+ @breaking = false
295
+ end
296
+
297
+ def message
298
+ "Deprecation reason on field `#{type.name}.#{new_field.name}` has changed "\
299
+ "from `#{old_field.deprecation_reason}` to `#{new_field.deprecation_reason}`"
300
+ end
301
+ end
302
+
303
+ class InputFieldDefaultChanged
304
+ attr_reader :input_type, :old_field, :new_field, :breaking
305
+
306
+ def initialize(input_type, old_field, new_field)
307
+ @input_type = input_type
308
+ @old_field = old_field
309
+ @new_field = new_field
310
+ @breaking = false
311
+ end
312
+
313
+ def message
314
+ "Input field `#{input_type.name}.#{old_field.name}` default changed"\
315
+ " from `#{old_field.default_value}` to `#{new_field.default_value}`"
316
+ end
317
+ end
318
+
319
+ class FieldArgumentDefaultChanged
320
+ attr_reader :type, :field, :old_argument, :new_argument, :breaking
321
+
322
+ def initialize(type, field, old_argument, new_argument)
323
+ @type = type
324
+ @field = field
325
+ @old_argument = old_argument
326
+ @new_argument = new_argument
327
+ @breaking = false
328
+ end
329
+
330
+ def message
331
+ "Default value for argument `#{new_argument.name}` on field `#{type.name}.#{field.name}` changed"\
332
+ " from `#{old_argument.default_value}` to `#{new_argument.default_value}`"
333
+ end
334
+ end
335
+
336
+ class DirectiveArgumentDefaultChanged
337
+ def initialize(*)
338
+ end
339
+ end
340
+
341
+ class ObjectTypeInterfaceAdded
342
+ attr_reader :interface, :object_type, :breaking
343
+
344
+ def initialize(interface, object_type)
345
+ @interface = interface
346
+ @object_type = object_type
347
+ @breaking = false
348
+ end
349
+
350
+ def message
351
+ "`#{object_type.name}` object implements `#{interface.name}` interface"
352
+ end
353
+ end
354
+
355
+ class FieldAdded
356
+ attr_reader :object_type, :field, :breaking
357
+
358
+ def initialize(object_type, field)
359
+ @object_type = object_type
360
+ @field = field
361
+ @breaking = false
362
+ end
363
+
364
+ def message
365
+ "Field `#{field.name}` was added to object type `#{object_type.name}`"
366
+ end
367
+ end
368
+
369
+ class DirectiveLocationAdded
370
+ def initialize(*)
371
+ end
372
+ end
373
+
374
+ class FieldAstDirectiveAdded
375
+ def initialize(*)
376
+ end
377
+ end
378
+
379
+ class FieldAstDirectiveRemoved
380
+ def initialize(*)
381
+ end
382
+ end
383
+
384
+ class EnumValueAstDirectiveAdded
385
+ def initialize(*)
386
+ end
387
+ end
388
+
389
+ class EnumValueAstDirectiveRemoved
390
+ def initialize(*)
391
+ end
392
+ end
393
+
394
+ class InputFieldAstDirectiveAdded
395
+ def initialize(*)
396
+ end
397
+ end
398
+
399
+ class InputFieldAstDirectiveRemoved
400
+ def initialize(*)
401
+ end
402
+ end
403
+
404
+ class DirectiveArgumentAstDirectiveAdded
405
+ def initialize(*)
406
+ end
407
+ end
408
+
409
+ class DirectiveArgumentAstDirectiveRemoved
410
+ def initialize(*)
411
+ end
412
+ end
413
+
414
+ class FieldArgumentAstDirectiveAdded
415
+ def initialize(*)
416
+ end
417
+ end
418
+
419
+ class FieldArgumentAstDirectiveRemoved
420
+ def initialize(*)
421
+ end
422
+ end
423
+
424
+ class ObjectTypeAstDirectiveAdded
425
+ def initialize(*)
426
+ end
427
+ end
428
+
429
+ class ObjectTypeAstDirectiveRemoved
430
+ def initialize(*)
431
+ end
432
+ end
433
+
434
+ class InterfaceTypeAstDirectiveAdded
435
+ def initialize(*)
436
+ end
437
+ end
438
+
439
+ class InterfaceTypeAstDirectiveRemoved
440
+ def initialize(*)
441
+ end
442
+ end
443
+
444
+ class UnionTypeAstDirectiveAdded
445
+ def initialize(*)
446
+ end
447
+ end
448
+
449
+ class UnionTypeAstDirectiveRemoved
450
+ def initialize(*)
451
+ end
452
+ end
453
+
454
+ class EnumTypeAstDirectiveAdded
455
+ def initialize(*)
456
+ end
457
+ end
458
+
459
+ class EnumTypeAstDirectiveRemoved
460
+ def initialize(*)
461
+ end
462
+ end
463
+
464
+ class ScalarTypeAstDirectiveAdded
465
+ def initialize(*)
466
+ end
467
+ end
468
+
469
+ class ScalarTypeAstDirectiveRemoved
470
+ def initialize(*)
471
+ end
472
+ end
473
+
474
+ class InputObjectTypeAstDirectiveAdded
475
+ def initialize(*)
476
+ end
477
+ end
478
+
479
+ class InputObjectTypeAstDirectiveRemoved
480
+ def initialize(*)
481
+ end
482
+ end
483
+
484
+ class SchemaAstDirectiveAdded
485
+ def initialize(*)
486
+ end
487
+ end
488
+
489
+ class SchemaAstDirectiveRemoved
490
+ def initialize(*)
491
+ end
492
+ end
493
+
494
+ # Maybe Breaking
495
+
496
+ class InputFieldAdded
497
+ attr_reader :input_object_type, :field, :breaking
498
+
499
+ def initialize(input_object_type, field)
500
+ @input_object_type = input_object_type
501
+ @field = field
502
+ end
503
+
504
+ def message
505
+ "Input field `#{field.name}` was added to input object type `#{input_object_type.name}`"
506
+ end
507
+ end
508
+
509
+ class FieldArgumentAdded
510
+ attr_reader :type, :field, :argument, :breaking
511
+
512
+ def initialize(type, field, argument)
513
+ @type = type
514
+ @field = field
515
+ @argument = argument
516
+ @breaking = false
517
+ end
518
+
519
+ def message
520
+ "Argument `#{argument.name}: #{argument.type}` added to field `#{type.name}.#{field.name}`"
521
+ end
522
+ end
523
+
524
+ class DirectiveArgumentAdded
525
+ def initialize(*)
526
+ end
527
+ end
528
+
529
+ class InputFieldTypeChanged
530
+ attr_reader :input_type, :old_input_field, :new_input_field, :breaking
531
+
532
+ def initialize(input_type, old_input_field, new_input_field)
533
+ @input_type = input_type
534
+ @old_input_field = old_input_field
535
+ @new_input_field = new_input_field
536
+ @breaking = true
537
+ end
538
+
539
+ def message
540
+ "Input field `#{input_type}.#{old_input_field.name}` changed type from #{old_input_field.type} to #{new_input_field.type}"
541
+ end
542
+ end
543
+
544
+ class FieldArgumentTypeChanged
545
+ attr_reader :type, :field, :old_argument, :new_argument, :breaking
546
+
547
+ def initialize(type, field, old_argument, new_argument)
548
+ @type = type
549
+ @field = field
550
+ @old_argument = old_argument
551
+ @new_argument = new_argument
552
+ @breaking = true
553
+ end
554
+
555
+ def message
556
+ "Type for argument `#{new_argument.name}` on field `#{type.name}.#{field.name}` changed"\
557
+ " from `#{old_argument.type}` to `#{new_argument.type}`"
558
+ end
559
+ end
560
+
561
+ class DirectiveArgumentTypeChanged
562
+ def initialize(*)
563
+ end
564
+ end
565
+
566
+ class FieldTypeChanged
567
+ attr_reader :type, :old_field, :new_field, :breaking
568
+
569
+ def initialize(type, old_field, new_field)
570
+ @type = type
571
+ @old_field = old_field
572
+ @new_field = new_field
573
+ @breaking = true
574
+ end
575
+
576
+ def message
577
+ "Field `#{type}.#{old_field.name}` changed type from `#{old_field.type}` to `#{new_field.type}`"
578
+ end
579
+ end
580
+
581
+ class SchemaMutationTypeChanged
582
+ attr_reader :old_schema, :new_schema, :breaking
583
+
584
+ def initialize(old_schema, new_schema)
585
+ @old_schema = old_schema
586
+ @new_schema = new_schema
587
+ @breaking = false
588
+ end
589
+
590
+ def message
591
+ "Schema mutation root has changed from `#{old_schema.mutation}` to `#{new_schema.mutation}`"
592
+ end
593
+ end
594
+
595
+ class SchemaSubscriptionTypeChanged
596
+ def initialize(old_schema, new_schema)
597
+ @old_schema = old_schema
598
+ @new_schema = new_schema
599
+ @breaking = false
600
+ end
601
+
602
+ def message
603
+ "Schema subscription type has changed from `#{old_schema.subscription}` to `#{new_schema.subscription}`"
604
+ end
605
+ end
606
+ end
607
+ end
608
+ end