graphql 2.3.14 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/orm_mutations_base.rb +1 -1
  3. data/lib/generators/graphql/templates/base_resolver.erb +2 -0
  4. data/lib/generators/graphql/type_generator.rb +1 -1
  5. data/lib/graphql/analysis.rb +1 -1
  6. data/lib/graphql/dataloader/async_dataloader.rb +3 -2
  7. data/lib/graphql/dataloader/source.rb +1 -1
  8. data/lib/graphql/dataloader.rb +31 -10
  9. data/lib/graphql/execution/interpreter/resolve.rb +10 -6
  10. data/lib/graphql/invalid_null_error.rb +1 -1
  11. data/lib/graphql/language/comment.rb +18 -0
  12. data/lib/graphql/language/document_from_schema_definition.rb +38 -4
  13. data/lib/graphql/language/lexer.rb +15 -12
  14. data/lib/graphql/language/nodes.rb +22 -14
  15. data/lib/graphql/language/parser.rb +5 -0
  16. data/lib/graphql/language/printer.rb +23 -7
  17. data/lib/graphql/language.rb +6 -5
  18. data/lib/graphql/query/null_context.rb +1 -1
  19. data/lib/graphql/query.rb +49 -16
  20. data/lib/graphql/rubocop/graphql/field_type_in_block.rb +23 -8
  21. data/lib/graphql/schema/always_visible.rb +6 -3
  22. data/lib/graphql/schema/argument.rb +14 -1
  23. data/lib/graphql/schema/build_from_definition.rb +1 -0
  24. data/lib/graphql/schema/enum.rb +3 -0
  25. data/lib/graphql/schema/enum_value.rb +9 -1
  26. data/lib/graphql/schema/field.rb +35 -14
  27. data/lib/graphql/schema/input_object.rb +20 -7
  28. data/lib/graphql/schema/interface.rb +1 -0
  29. data/lib/graphql/schema/member/base_dsl_methods.rb +15 -0
  30. data/lib/graphql/schema/member/has_arguments.rb +2 -2
  31. data/lib/graphql/schema/member/has_fields.rb +2 -2
  32. data/lib/graphql/schema/printer.rb +1 -0
  33. data/lib/graphql/schema/resolver.rb +3 -4
  34. data/lib/graphql/schema/validator/required_validator.rb +28 -4
  35. data/lib/graphql/schema/visibility/migration.rb +186 -0
  36. data/lib/graphql/schema/visibility/profile.rb +523 -0
  37. data/lib/graphql/schema/visibility.rb +75 -0
  38. data/lib/graphql/schema/warden.rb +77 -15
  39. data/lib/graphql/schema.rb +203 -61
  40. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +2 -1
  41. data/lib/graphql/static_validation/rules/directives_are_defined.rb +2 -1
  42. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
  43. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +2 -1
  44. data/lib/graphql/static_validation/rules/fields_will_merge.rb +1 -0
  45. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +11 -1
  46. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +10 -1
  47. data/lib/graphql/static_validation/validation_context.rb +15 -0
  48. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +2 -1
  49. data/lib/graphql/subscriptions.rb +3 -1
  50. data/lib/graphql/testing/helpers.rb +2 -1
  51. data/lib/graphql/tracing/notifications_trace.rb +2 -2
  52. data/lib/graphql/version.rb +1 -1
  53. metadata +11 -9
  54. data/lib/graphql/schema/subset.rb +0 -509
  55. data/lib/graphql/schema/types_migration.rb +0 -187
@@ -1,187 +0,0 @@
1
- # frozen_string_literal: true
2
- module GraphQL
3
- class Schema
4
- # You can add this plugin to your schema to see how {GraphQL::Schema::Warden} and {GraphQL::Schema::Subset}
5
- # handle `.visible?` differently in your schema.
6
- #
7
- # This plugin runs the same method on both implementations and raises an error when the results diverge.
8
- #
9
- # To fix the error, modify your schema so that both implementations return the same thing.
10
- # Or, open an issue on GitHub to discuss the difference.
11
- #
12
- # This plugin adds overhead to runtime and may cause unexpected crashes -- **don't** use it in production!
13
- #
14
- # This plugin adds two keys to `context` when running:
15
- #
16
- # - `types_migration_running: true`
17
- # - For the {Warden} which it instantiates, it adds `types_migration_warden_running: true`.
18
- #
19
- # Use those keys to modify your `visible?` behavior as needed.
20
- #
21
- # Also, in a pinch, you can set `skip_types_migration_error: true` in context to turn off this plugin's behavior per-query.
22
- # (In that case, it uses {Subset} directly.)
23
- #
24
- # @example Adding this plugin
25
- #
26
- # if !Rails.env.production?
27
- # use GraphQL::Schema::TypesMigration
28
- # end
29
- class TypesMigration < GraphQL::Schema::Subset
30
- def self.use(schema)
31
- schema.subset_class = self
32
- end
33
-
34
- class RuntimeTypesMismatchError < GraphQL::Error
35
- def initialize(method_called, warden_result, subset_result, method_args)
36
- super(<<~ERR)
37
- Mismatch in types for `##{method_called}(#{method_args.map(&:inspect).join(", ")})`:
38
-
39
- #{compare_results(warden_result, subset_result)}
40
-
41
- Update your `.visible?` implementation to make these implementations return the same value.
42
-
43
- See: https://graphql-ruby.org/authorization/visibility_migration.html
44
- ERR
45
- end
46
-
47
- private
48
- def compare_results(warden_result, subset_result)
49
- if warden_result.is_a?(Array) && subset_result.is_a?(Array)
50
- all_results = warden_result | subset_result
51
- all_results.sort_by!(&:graphql_name)
52
-
53
- entries_text = all_results.map { |entry| "#{entry.graphql_name} (#{entry})"}
54
- width = entries_text.map(&:size).max
55
- yes = " ✔ "
56
- no = " "
57
- res = "".dup
58
- res << "#{"Result".center(width)} Warden Subset \n"
59
- all_results.each_with_index do |entry, idx|
60
- res << "#{entries_text[idx].ljust(width)}#{warden_result.include?(entry) ? yes : no}#{subset_result.include?(entry) ? yes : no}\n"
61
- end
62
- res << "\n"
63
- else
64
- "- Warden returned: #{humanize(warden_result)}\n\n- Subset returned: #{humanize(subset_result)}"
65
- end
66
- end
67
- def humanize(val)
68
- case val
69
- when Array
70
- "#{val.size}: #{val.map { |v| humanize(v) }.sort.inspect}"
71
- when Module
72
- if val.respond_to?(:graphql_name)
73
- "#{val.graphql_name} (#{val.inspect})"
74
- else
75
- val.inspect
76
- end
77
- else
78
- val.inspect
79
- end
80
- end
81
- end
82
-
83
- def initialize(context:, schema:)
84
- @skip_error = context[:skip_types_migration_error]
85
- context[:types_migration_running] = true
86
- @subset_types = GraphQL::Schema::Subset.new(context: context, schema: schema)
87
- if !@skip_error
88
- warden_ctx_vals = context.to_h.dup
89
- warden_ctx_vals[:types_migration_warden_running] = true
90
- if defined?(schema::WardenCompatSchema)
91
- warden_schema = schema::WardenCompatSchema
92
- else
93
- warden_schema = Class.new(schema)
94
- warden_schema.use_schema_subset = false
95
- # TODO public API
96
- warden_schema.send(:add_type_and_traverse, [warden_schema.query, warden_schema.mutation, warden_schema.subscription].compact, root: true)
97
- warden_schema.send(:add_type_and_traverse, warden_schema.directives.values + warden_schema.orphan_types, root: false)
98
- end
99
- warden_ctx = GraphQL::Query::Context.new(query: context.query, values: warden_ctx_vals)
100
- example_warden = GraphQL::Schema::Warden.new(schema: warden_schema, context: warden_ctx)
101
- @warden_types = example_warden.schema_subset
102
- warden_ctx.warden = example_warden
103
- warden_ctx.types = @warden_types
104
- end
105
- end
106
-
107
- def loaded_types
108
- @subset_types.loaded_types
109
- end
110
-
111
- PUBLIC_SUBSET_METHODS = [
112
- :enum_values,
113
- :interfaces,
114
- :all_types,
115
- :fields,
116
- :loadable?,
117
- :type,
118
- :arguments,
119
- :argument,
120
- :directive_exists?,
121
- :directives,
122
- :field,
123
- :query_root,
124
- :mutation_root,
125
- :possible_types,
126
- :subscription_root,
127
- :reachable_type?
128
- ]
129
-
130
- PUBLIC_SUBSET_METHODS.each do |subset_method|
131
- define_method(subset_method) do |*args|
132
- call_method_and_compare(subset_method, args)
133
- end
134
- end
135
-
136
- def call_method_and_compare(method, args)
137
- res_1 = @subset_types.public_send(method, *args)
138
- if @skip_error
139
- return res_1
140
- end
141
-
142
- res_2 = @warden_types.public_send(method, *args)
143
- normalized_res_1 = res_1.is_a?(Array) ? Set.new(res_1) : res_1
144
- normalized_res_2 = res_2.is_a?(Array) ? Set.new(res_2) : res_2
145
- if !equivalent_schema_members?(normalized_res_1, normalized_res_2)
146
- # Raise the errors with the orignally returned values:
147
- err = RuntimeTypesMismatchError.new(method, res_2, res_1, args)
148
- raise err
149
- else
150
- res_1
151
- end
152
- end
153
-
154
- def equivalent_schema_members?(member1, member2)
155
- if member1.class != member2.class
156
- return false
157
- end
158
-
159
- case member1
160
- when Set
161
- member1_array = member1.to_a.sort_by(&:graphql_name)
162
- member2_array = member2.to_a.sort_by(&:graphql_name)
163
- member1_array.each_with_index do |inner_member1, idx|
164
- inner_member2 = member2_array[idx]
165
- equivalent_schema_members?(inner_member1, inner_member2)
166
- end
167
- when GraphQL::Schema::Field
168
- member1.ensure_loaded
169
- member2.ensure_loaded
170
- if member1.introspection? && member2.introspection?
171
- member1.inspect == member2.inspect
172
- else
173
- member1 == member2
174
- end
175
- when Module
176
- if member1.introspection? && member2.introspection?
177
- member1.graphql_name == member2.graphql_name
178
- else
179
- member1 == member2
180
- end
181
- else
182
- member1 == member2
183
- end
184
- end
185
- end
186
- end
187
- end