graphql 2.3.14 → 2.4.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.
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