graphql 2.3.6 → 2.3.8

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.

Potentially problematic release.


This version of graphql might be problematic. Click here for more details.

Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/analysis/field_usage.rb +1 -1
  3. data/lib/graphql/analysis/query_complexity.rb +3 -3
  4. data/lib/graphql/analysis/visitor.rb +7 -6
  5. data/lib/graphql/execution/interpreter/runtime.rb +6 -6
  6. data/lib/graphql/execution/lookahead.rb +10 -10
  7. data/lib/graphql/introspection/directive_type.rb +1 -1
  8. data/lib/graphql/introspection/entry_points.rb +2 -2
  9. data/lib/graphql/introspection/field_type.rb +1 -1
  10. data/lib/graphql/introspection/schema_type.rb +13 -3
  11. data/lib/graphql/introspection/type_type.rb +5 -5
  12. data/lib/graphql/language/document_from_schema_definition.rb +19 -26
  13. data/lib/graphql/language/lexer.rb +0 -3
  14. data/lib/graphql/language/sanitized_printer.rb +1 -1
  15. data/lib/graphql/language.rb +0 -1
  16. data/lib/graphql/query/context.rb +4 -0
  17. data/lib/graphql/query/null_context.rb +4 -0
  18. data/lib/graphql/query.rb +26 -3
  19. data/lib/graphql/schema/always_visible.rb +1 -0
  20. data/lib/graphql/schema/enum.rb +4 -4
  21. data/lib/graphql/schema/field.rb +7 -3
  22. data/lib/graphql/schema/has_single_input_argument.rb +2 -1
  23. data/lib/graphql/schema/input_object.rb +8 -7
  24. data/lib/graphql/schema/introspection_system.rb +2 -14
  25. data/lib/graphql/schema/member/has_arguments.rb +7 -6
  26. data/lib/graphql/schema/member/has_fields.rb +6 -4
  27. data/lib/graphql/schema/resolver.rb +4 -5
  28. data/lib/graphql/schema/subset.rb +397 -0
  29. data/lib/graphql/schema/type_expression.rb +2 -2
  30. data/lib/graphql/schema/validator/all_validator.rb +60 -0
  31. data/lib/graphql/schema/validator.rb +2 -0
  32. data/lib/graphql/schema/warden.rb +88 -1
  33. data/lib/graphql/schema.rb +44 -15
  34. data/lib/graphql/static_validation/base_visitor.rb +6 -5
  35. data/lib/graphql/static_validation/literal_validator.rb +4 -4
  36. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
  37. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
  38. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -2
  39. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
  40. data/lib/graphql/static_validation/rules/fields_will_merge.rb +7 -7
  41. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  42. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
  43. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
  44. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
  45. data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
  46. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +3 -3
  47. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +3 -3
  48. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
  49. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +1 -1
  50. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  51. data/lib/graphql/static_validation/validation_context.rb +2 -2
  52. data/lib/graphql/subscriptions/broadcast_analyzer.rb +10 -4
  53. data/lib/graphql/subscriptions/event.rb +1 -1
  54. data/lib/graphql/subscriptions.rb +2 -2
  55. data/lib/graphql/testing/helpers.rb +2 -2
  56. data/lib/graphql/types/relay/connection_behaviors.rb +10 -0
  57. data/lib/graphql/types/relay/edge_behaviors.rb +10 -0
  58. data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
  59. data/lib/graphql/version.rb +1 -1
  60. metadata +4 -4
  61. data/lib/graphql/language/token.rb +0 -34
  62. data/lib/graphql/schema/invalid_type_error.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 96871397d0d4258c406b0492a304ca71129cc3be7effb2892ee225896e8e266f
4
- data.tar.gz: b3d7b30d09f4e19505549ce6292cdc7643971cfe285f498be98f585531ae8c3c
3
+ metadata.gz: 47e1762bc5aa144c21841bf1671a63b2180b8dacd4145688bc6f131ceb2a8f4a
4
+ data.tar.gz: 9dd05b04b955e83c95cb4ad5d959fb68a49796417ca1759606be21cabc7bfd39
5
5
  SHA512:
6
- metadata.gz: 6b79b06fecef3325b8df579183a0cf71c137b77a27003fead0abb6a198731243aa6b55d43c022b62cac1dbc2f6544c3d28dc5fadfa97f33b2043a6e8a18020a8
7
- data.tar.gz: b79eeb7912a70ddb7b072d095d2b61e1e8cc84cf50a975e0227dbd6f0f17728fa61d17f0269fbaa1ebdd219d13a3453e1b67b59ede085d020e3ca105de94186a
6
+ metadata.gz: 3bfe0cf261815aed7f739eb797f0c400c5ec97d4caf4f2ab760a67392fb51be2fceefcde7f45ad62d49d5216d7ea19ccf43b8360162a4862d70268115b7395cd
7
+ data.tar.gz: 50a2a283a121761a4aae7174587e312b9ed39215101f18e9a14ce006844ca22b81572381a9636d63ecee9e7d7a15c62c996f6e736479b80aaec77684904cd392
@@ -72,7 +72,7 @@ module GraphQL
72
72
  end
73
73
 
74
74
  def extract_deprecated_enum_value(enum_type, value)
75
- enum_value = @query.warden.enum_values(enum_type).find { |ev| ev.value == value }
75
+ enum_value = @query.types.enum_values(enum_type).find { |ev| ev.value == value }
76
76
  if enum_value&.deprecation_reason
77
77
  @used_deprecated_enum_values << enum_value.path
78
78
  end
@@ -98,7 +98,7 @@ module GraphQL
98
98
  possible_scope_types.keys.each do |possible_scope_type|
99
99
  next unless possible_scope_type.kind.abstract?
100
100
 
101
- query.possible_types(possible_scope_type).each do |impl_type|
101
+ query.types.possible_types(possible_scope_type).each do |impl_type|
102
102
  possible_scope_types[impl_type] ||= true
103
103
  end
104
104
  possible_scope_types.delete(possible_scope_type)
@@ -123,8 +123,8 @@ module GraphQL
123
123
  def types_intersect?(query, a, b)
124
124
  return true if a == b
125
125
 
126
- a_types = query.possible_types(a)
127
- query.possible_types(b).any? { |t| a_types.include?(t) }
126
+ a_types = query.types.possible_types(a)
127
+ query.types.possible_types(b).any? { |t| a_types.include?(t) }
128
128
  end
129
129
 
130
130
  # A hook which is called whenever a field's max complexity is calculated.
@@ -21,6 +21,7 @@ module GraphQL
21
21
  @rescued_errors = []
22
22
  @query = query
23
23
  @schema = query.schema
24
+ @types = query.types
24
25
  @response_path = []
25
26
  @skip_stack = [false]
26
27
  super(query.selected_operation)
@@ -131,7 +132,7 @@ module GraphQL
131
132
  @response_path.push(node.alias || node.name)
132
133
  parent_type = @object_types.last
133
134
  # This could be nil if the previous field wasn't found:
134
- field_definition = parent_type && @schema.get_field(parent_type, node.name, @query.context)
135
+ field_definition = parent_type && @types.field(parent_type, node.name)
135
136
  @field_definitions.push(field_definition)
136
137
  if !field_definition.nil?
137
138
  next_object_type = field_definition.type.unwrap
@@ -167,14 +168,14 @@ module GraphQL
167
168
  argument_defn = if (arg = @argument_definitions.last)
168
169
  arg_type = arg.type.unwrap
169
170
  if arg_type.kind.input_object?
170
- arg_type.get_argument(node.name, @query.context)
171
+ @types.argument(arg_type, node.name)
171
172
  else
172
173
  nil
173
174
  end
174
175
  elsif (directive_defn = @directive_definitions.last)
175
- directive_defn.get_argument(node.name, @query.context)
176
+ @types.argument(directive_defn, node.name)
176
177
  elsif (field_defn = @field_definitions.last)
177
- field_defn.get_argument(node.name, @query.context)
178
+ @types.argument(field_defn, node.name)
178
179
  else
179
180
  nil
180
181
  end
@@ -245,7 +246,7 @@ module GraphQL
245
246
  fragment_def = query.fragments[fragment_spread.name]
246
247
 
247
248
  object_type = if fragment_def.type
248
- @query.warden.get_type(fragment_def.type.name)
249
+ @types.type(fragment_def.type.name)
249
250
  else
250
251
  object_types.last
251
252
  end
@@ -268,7 +269,7 @@ module GraphQL
268
269
 
269
270
  def on_fragment_with_type(node)
270
271
  object_type = if node.type
271
- @query.warden.get_type(node.type.name)
272
+ @types.type(node.type.name)
272
273
  else
273
274
  @object_types.last
274
275
  end
@@ -160,9 +160,9 @@ module GraphQL
160
160
  case node
161
161
  when GraphQL::Language::Nodes::InlineFragment
162
162
  if node.type
163
- type_defn = schema.get_type(node.type.name, context)
163
+ type_defn = query.types.type(node.type.name)
164
164
 
165
- if query.warden.possible_types(type_defn).include?(owner_type)
165
+ if query.types.possible_types(type_defn).include?(owner_type)
166
166
  result = gather_selections(owner_object, owner_type, node.selections, selections_to_run, next_selections)
167
167
  if !result.equal?(next_selections)
168
168
  selections_to_run = result
@@ -177,8 +177,8 @@ module GraphQL
177
177
  end
178
178
  when GraphQL::Language::Nodes::FragmentSpread
179
179
  fragment_def = query.fragments[node.name]
180
- type_defn = query.get_type(fragment_def.type.name)
181
- if query.warden.possible_types(type_defn).include?(owner_type)
180
+ type_defn = query.types.type(fragment_def.type.name)
181
+ if query.types.possible_types(type_defn).include?(owner_type)
182
182
  result = gather_selections(owner_object, owner_type, fragment_def.selections, selections_to_run, next_selections)
183
183
  if !result.equal?(next_selections)
184
184
  selections_to_run = result
@@ -245,7 +245,7 @@ module GraphQL
245
245
  end
246
246
  field_name = ast_node.name
247
247
  owner_type = selections_result.graphql_result_type
248
- field_defn = query.warden.get_field(owner_type, field_name)
248
+ field_defn = query.types.field(owner_type, field_name)
249
249
 
250
250
  # Set this before calling `run_with_directives`, so that the directive can have the latest path
251
251
  runtime_state = get_current_runtime_state
@@ -579,7 +579,7 @@ module GraphQL
579
579
  resolved_value = value
580
580
  end
581
581
 
582
- possible_types = query.possible_types(current_type)
582
+ possible_types = query.types.possible_types(current_type)
583
583
  if !possible_types.include?(resolved_type)
584
584
  parent_type = field.owner_type
585
585
  err_class = current_type::UnresolvedTypeError
@@ -108,16 +108,16 @@ module GraphQL
108
108
  def selection(field_name, selected_type: @selected_type, arguments: nil)
109
109
  next_field_defn = case field_name
110
110
  when String
111
- @query.get_field(selected_type, field_name)
111
+ @query.types.field(selected_type, field_name)
112
112
  when Symbol
113
113
  # Try to avoid the `.to_s` below, if possible
114
114
  all_fields = if selected_type.kind.fields?
115
- @query.warden.fields(selected_type)
115
+ @query.types.fields(selected_type)
116
116
  else
117
117
  # Handle unions by checking possible
118
- @query.warden
118
+ @query.types
119
119
  .possible_types(selected_type)
120
- .map { |t| @query.warden.fields(t) }
120
+ .map { |t| @query.types.fields(t) }
121
121
  .tap(&:flatten!)
122
122
  end
123
123
 
@@ -128,7 +128,7 @@ module GraphQL
128
128
  # Symbol#name is only present on 3.0+
129
129
  sym_s = field_name.respond_to?(:name) ? field_name.name : field_name.to_s
130
130
  guessed_name = Schema::Member::BuildType.camelize(sym_s)
131
- @query.get_field(selected_type, guessed_name)
131
+ @query.types.field(selected_type, guessed_name)
132
132
  end
133
133
  end
134
134
  lookahead_for_selection(next_field_defn, selected_type, arguments)
@@ -144,7 +144,7 @@ module GraphQL
144
144
  alias_node = lookup_alias_node(ast_nodes, alias_name)
145
145
  return NULL_LOOKAHEAD unless alias_node
146
146
 
147
- next_field_defn = @query.get_field(selected_type, alias_node.name)
147
+ next_field_defn = @query.types.field(selected_type, alias_node.name)
148
148
 
149
149
  alias_arguments = @query.arguments_for(alias_node, next_field_defn)
150
150
  if alias_arguments.is_a?(::GraphQL::Execution::Interpreter::Arguments)
@@ -183,7 +183,7 @@ module GraphQL
183
183
 
184
184
  subselections_by_type.each do |type, ast_nodes_by_response_key|
185
185
  ast_nodes_by_response_key.each do |response_key, ast_nodes|
186
- field_defn = @query.get_field(type, ast_nodes.first.name)
186
+ field_defn = @query.types.field(type, ast_nodes.first.name)
187
187
  lookahead = Lookahead.new(query: @query, ast_nodes: ast_nodes, field: field_defn, owner_type: type)
188
188
  subselections.push(lookahead)
189
189
  end
@@ -266,7 +266,7 @@ module GraphQL
266
266
  elsif arguments.nil? || arguments.empty?
267
267
  selections_on_type[response_key] = [ast_selection]
268
268
  else
269
- field_defn = @query.get_field(selected_type, ast_selection.name)
269
+ field_defn = @query.types.field(selected_type, ast_selection.name)
270
270
  if arguments_match?(arguments, field_defn, ast_selection)
271
271
  selections_on_type[response_key] = [ast_selection]
272
272
  end
@@ -276,14 +276,14 @@ module GraphQL
276
276
  subselections_on_type = selections_on_type
277
277
  if (t = ast_selection.type)
278
278
  # Assuming this is valid, that `t` will be found.
279
- on_type = @query.get_type(t.name)
279
+ on_type = @query.types.type(t.name)
280
280
  subselections_on_type = subselections_by_type[on_type] ||= {}
281
281
  end
282
282
  find_selections(subselections_by_type, subselections_on_type, on_type, ast_selection.selections, arguments)
283
283
  when GraphQL::Language::Nodes::FragmentSpread
284
284
  frag_defn = lookup_fragment(ast_selection)
285
285
  # Again, assuming a valid AST
286
- on_type = @query.get_type(frag_defn.type.name)
286
+ on_type = @query.types.type(frag_defn.type.name)
287
287
  subselections_on_type = subselections_by_type[on_type] ||= {}
288
288
  find_selections(subselections_by_type, subselections_on_type, on_type, frag_defn.selections, arguments)
289
289
  else
@@ -22,7 +22,7 @@ module GraphQL
22
22
  field :is_repeatable, Boolean, method: :repeatable?
23
23
 
24
24
  def args(include_deprecated:)
25
- args = @context.warden.arguments(@object)
25
+ args = @context.types.arguments(@object)
26
26
  args = args.reject(&:deprecation_reason) unless include_deprecated
27
27
  args
28
28
  end
@@ -15,8 +15,8 @@ module GraphQL
15
15
  end
16
16
 
17
17
  def __type(name:)
18
- if context.warden.reachable_type?(name)
19
- context.warden.get_type(name)
18
+ if context.types.reachable_type?(name)
19
+ context.types.type(name)
20
20
  elsif (type = context.schema.extra_types.find { |t| t.graphql_name == name })
21
21
  type
22
22
  else
@@ -19,7 +19,7 @@ module GraphQL
19
19
  end
20
20
 
21
21
  def args(include_deprecated:)
22
- args = @context.warden.arguments(@object)
22
+ args = @context.types.arguments(@object)
23
23
  args = args.reject(&:deprecation_reason) unless include_deprecated
24
24
  args
25
25
  end
@@ -20,7 +20,8 @@ module GraphQL
20
20
  end
21
21
 
22
22
  def types
23
- types = context.warden.reachable_types + context.schema.extra_types
23
+ query_types = context.types.all_types
24
+ types = query_types + context.schema.extra_types
24
25
  types.sort_by!(&:graphql_name)
25
26
  types
26
27
  end
@@ -38,13 +39,22 @@ module GraphQL
38
39
  end
39
40
 
40
41
  def directives
41
- @context.warden.directives
42
+ @context.types.directives
42
43
  end
43
44
 
44
45
  private
45
46
 
46
47
  def permitted_root_type(op_type)
47
- @context.warden.root_type_for_operation(op_type)
48
+ case op_type
49
+ when "query"
50
+ @context.types.query_root
51
+ when "mutation"
52
+ @context.types.mutation_root
53
+ when "subcription"
54
+ @context.types.subscription_root
55
+ else
56
+ nil
57
+ end
48
58
  end
49
59
  end
50
60
  end
@@ -52,7 +52,7 @@ module GraphQL
52
52
  if !@object.kind.enum?
53
53
  nil
54
54
  else
55
- enum_values = @context.warden.enum_values(@object)
55
+ enum_values = @context.types.enum_values(@object)
56
56
 
57
57
  if !include_deprecated
58
58
  enum_values = enum_values.select {|f| !f.deprecation_reason }
@@ -64,7 +64,7 @@ module GraphQL
64
64
 
65
65
  def interfaces
66
66
  if @object.kind.object? || @object.kind.interface?
67
- @context.warden.interfaces(@object).sort_by(&:graphql_name)
67
+ @context.types.interfaces(@object).sort_by(&:graphql_name)
68
68
  else
69
69
  nil
70
70
  end
@@ -72,7 +72,7 @@ module GraphQL
72
72
 
73
73
  def input_fields(include_deprecated:)
74
74
  if @object.kind.input_object?
75
- args = @context.warden.arguments(@object)
75
+ args = @context.types.arguments(@object)
76
76
  args = args.reject(&:deprecation_reason) unless include_deprecated
77
77
  args
78
78
  else
@@ -82,7 +82,7 @@ module GraphQL
82
82
 
83
83
  def possible_types
84
84
  if @object.kind.abstract?
85
- @context.warden.possible_types(@object).sort_by(&:graphql_name)
85
+ @context.types.possible_types(@object).sort_by(&:graphql_name)
86
86
  else
87
87
  nil
88
88
  end
@@ -92,7 +92,7 @@ module GraphQL
92
92
  if !@object.kind.fields?
93
93
  nil
94
94
  else
95
- fields = @context.warden.fields(@object)
95
+ fields = @context.types.fields(@object)
96
96
  if !include_deprecated
97
97
  fields = fields.select {|f| !f.deprecation_reason }
98
98
  end
@@ -24,15 +24,8 @@ module GraphQL
24
24
  @include_built_in_directives = include_built_in_directives
25
25
  @include_one_of = false
26
26
 
27
- schema_context = schema.context_class.new(query: nil, schema: schema, values: context)
28
-
29
-
30
- @warden = @schema.warden_class.new(
31
- schema: @schema,
32
- context: schema_context,
33
- )
34
-
35
- schema_context.warden = @warden
27
+ dummy_query = @schema.query_class.new(@schema, "{ __typename }", validate: false, context: context)
28
+ @types = dummy_query.types # rubocop:disable Development/ContextIsPassedCop
36
29
  end
37
30
 
38
31
  def document
@@ -44,9 +37,9 @@ module GraphQL
44
37
  def build_schema_node
45
38
  if !schema_respects_root_name_conventions?(@schema)
46
39
  GraphQL::Language::Nodes::SchemaDefinition.new(
47
- query: (q = warden.root_type_for_operation("query")) && q.graphql_name,
48
- mutation: (m = warden.root_type_for_operation("mutation")) && m.graphql_name,
49
- subscription: (s = warden.root_type_for_operation("subscription")) && s.graphql_name,
40
+ query: @types.query_root&.graphql_name,
41
+ mutation: @types.mutation_root&.graphql_name,
42
+ subscription: @types.subscription_root&.graphql_name,
50
43
  directives: definition_directives(@schema, :schema_directives)
51
44
  )
52
45
  else
@@ -57,7 +50,7 @@ module GraphQL
57
50
  end
58
51
 
59
52
  def build_object_type_node(object_type)
60
- ints = warden.interfaces(object_type)
53
+ ints = @types.interfaces(object_type)
61
54
  if ints.any?
62
55
  ints.sort_by!(&:graphql_name)
63
56
  ints.map! { |iface| build_type_name_node(iface) }
@@ -66,7 +59,7 @@ module GraphQL
66
59
  GraphQL::Language::Nodes::ObjectTypeDefinition.new(
67
60
  name: object_type.graphql_name,
68
61
  interfaces: ints,
69
- fields: build_field_nodes(warden.fields(object_type)),
62
+ fields: build_field_nodes(@types.fields(object_type)),
70
63
  description: object_type.description,
71
64
  directives: directives(object_type),
72
65
  )
@@ -75,7 +68,7 @@ module GraphQL
75
68
  def build_field_node(field)
76
69
  GraphQL::Language::Nodes::FieldDefinition.new(
77
70
  name: field.graphql_name,
78
- arguments: build_argument_nodes(warden.arguments(field)),
71
+ arguments: build_argument_nodes(@types.arguments(field)),
79
72
  type: build_type_name_node(field.type),
80
73
  description: field.description,
81
74
  directives: directives(field),
@@ -86,7 +79,7 @@ module GraphQL
86
79
  GraphQL::Language::Nodes::UnionTypeDefinition.new(
87
80
  name: union_type.graphql_name,
88
81
  description: union_type.description,
89
- types: warden.possible_types(union_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
82
+ types: @types.possible_types(union_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
90
83
  directives: directives(union_type),
91
84
  )
92
85
  end
@@ -94,9 +87,9 @@ module GraphQL
94
87
  def build_interface_type_node(interface_type)
95
88
  GraphQL::Language::Nodes::InterfaceTypeDefinition.new(
96
89
  name: interface_type.graphql_name,
97
- interfaces: warden.interfaces(interface_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
90
+ interfaces: @types.interfaces(interface_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
98
91
  description: interface_type.description,
99
- fields: build_field_nodes(warden.fields(interface_type)),
92
+ fields: build_field_nodes(@types.fields(interface_type)),
100
93
  directives: directives(interface_type),
101
94
  )
102
95
  end
@@ -104,7 +97,7 @@ module GraphQL
104
97
  def build_enum_type_node(enum_type)
105
98
  GraphQL::Language::Nodes::EnumTypeDefinition.new(
106
99
  name: enum_type.graphql_name,
107
- values: warden.enum_values(enum_type).sort_by(&:graphql_name).map do |enum_value|
100
+ values: @types.enum_values(enum_type).sort_by(&:graphql_name).map do |enum_value|
108
101
  build_enum_value_node(enum_value)
109
102
  end,
110
103
  description: enum_type.description,
@@ -149,7 +142,7 @@ module GraphQL
149
142
  def build_input_object_node(input_object)
150
143
  GraphQL::Language::Nodes::InputObjectTypeDefinition.new(
151
144
  name: input_object.graphql_name,
152
- fields: build_argument_nodes(warden.arguments(input_object)),
145
+ fields: build_argument_nodes(@types.arguments(input_object)),
153
146
  description: input_object.description,
154
147
  directives: directives(input_object),
155
148
  )
@@ -159,7 +152,7 @@ module GraphQL
159
152
  GraphQL::Language::Nodes::DirectiveDefinition.new(
160
153
  name: directive.graphql_name,
161
154
  repeatable: directive.repeatable?,
162
- arguments: build_argument_nodes(warden.arguments(directive)),
155
+ arguments: build_argument_nodes(@types.arguments(directive)),
163
156
  locations: build_directive_location_nodes(directive.locations),
164
157
  description: directive.description,
165
158
  )
@@ -204,7 +197,7 @@ module GraphQL
204
197
  when "INPUT_OBJECT"
205
198
  GraphQL::Language::Nodes::InputObject.new(
206
199
  arguments: default_value.to_h.map do |arg_name, arg_value|
207
- args = @warden.arguments(type)
200
+ args = @types.arguments(type)
208
201
  arg = args.find { |a| a.keyword.to_s == arg_name.to_s }
209
202
  if arg.nil?
210
203
  raise ArgumentError, "No argument definition on #{type.graphql_name} for argument: #{arg_name.inspect} (expected one of: #{args.map(&:keyword)})"
@@ -260,13 +253,13 @@ module GraphQL
260
253
  end
261
254
 
262
255
  def build_definition_nodes
263
- dirs_to_build = warden.directives
256
+ dirs_to_build = @types.directives
264
257
  if !include_built_in_directives
265
258
  dirs_to_build = dirs_to_build.reject { |directive| directive.default_directive? }
266
259
  end
267
260
  definitions = build_directive_nodes(dirs_to_build)
268
-
269
- type_nodes = build_type_definition_nodes(warden.reachable_types + schema.extra_types)
261
+ all_types = @types.all_types
262
+ type_nodes = build_type_definition_nodes(all_types + schema.extra_types)
270
263
  if @include_one_of
271
264
  # This may have been set to true when iterating over all types
272
265
  definitions.concat(build_directive_nodes([GraphQL::Schema::Directive::OneOf]))
@@ -351,7 +344,7 @@ module GraphQL
351
344
  dirs
352
345
  end
353
346
 
354
- attr_reader :schema, :warden, :always_include_schema,
347
+ attr_reader :schema, :always_include_schema,
355
348
  :include_introspection_types, :include_built_in_directives, :include_built_in_scalars
356
349
  end
357
350
  end
@@ -345,17 +345,14 @@ module GraphQL
345
345
  def self.tokenize(string)
346
346
  lexer = GraphQL::Language::Lexer.new(string)
347
347
  tokens = []
348
- prev_token = nil
349
348
  while (token_name = lexer.advance)
350
349
  new_token = [
351
350
  token_name,
352
351
  lexer.line_number,
353
352
  lexer.column_number,
354
353
  lexer.debug_token_value(token_name),
355
- prev_token,
356
354
  ]
357
355
  tokens << new_token
358
- prev_token = new_token
359
356
  end
360
357
  tokens
361
358
  end
@@ -113,7 +113,7 @@ module GraphQL
113
113
  end
114
114
 
115
115
  def print_field(field, indent: "")
116
- @current_field = query.get_field(@current_type, field.name)
116
+ @current_field = query.types.field(@current_type, field.name)
117
117
  old_type = @current_type
118
118
  @current_type = @current_field.type.unwrap
119
119
  super
@@ -9,7 +9,6 @@ require "graphql/language/nodes"
9
9
  require "graphql/language/cache"
10
10
  require "graphql/language/parser"
11
11
  require "graphql/language/static_visitor"
12
- require "graphql/language/token"
13
12
  require "graphql/language/visitor"
14
13
  require "graphql/language/definition_slice"
15
14
  require "strscan"
@@ -84,6 +84,10 @@ module GraphQL
84
84
 
85
85
  def_delegators :@query, :trace, :interpreter?
86
86
 
87
+ def types
88
+ @query.types
89
+ end
90
+
87
91
  RUNTIME_METADATA_KEYS = Set.new([:current_object, :current_arguments, :current_field, :current_path])
88
92
  # @!method []=(key, value)
89
93
  # Reassign `key` to the hash passed to {Schema#execute} as `context:`
@@ -30,6 +30,10 @@ module GraphQL
30
30
  def interpreter?
31
31
  true
32
32
  end
33
+
34
+ def types
35
+ @types ||= GraphQL::Schema::Warden::SchemaSubset.new(@warden)
36
+ end
33
37
  end
34
38
  end
35
39
  end
data/lib/graphql/query.rb CHANGED
@@ -95,12 +95,24 @@ module GraphQL
95
95
  # @param root_value [Object] the object used to resolve fields on the root type
96
96
  # @param max_depth [Numeric] the maximum number of nested selections allowed for this query (falls back to schema-level value)
97
97
  # @param max_complexity [Numeric] the maximum field complexity for this query (falls back to schema-level value)
98
- def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, static_validator: nil, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, warden: nil)
98
+ def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, static_validator: nil, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, warden: nil, use_schema_subset: nil)
99
99
  # Even if `variables: nil` is passed, use an empty hash for simpler logic
100
100
  variables ||= {}
101
101
  @schema = schema
102
102
  @context = schema.context_class.new(query: self, values: context)
103
- @warden = warden
103
+
104
+ if use_schema_subset.nil?
105
+ use_schema_subset = warden ? false : schema.use_schema_subset?
106
+ end
107
+
108
+ if use_schema_subset
109
+ @schema_subset = @schema.subset_class.new(self)
110
+ @warden = Schema::Warden::NullWarden.new(context: self, schema: @schema)
111
+ else
112
+ @schema_subset = nil
113
+ @warden = warden
114
+ end
115
+
104
116
  @subscription_topic = subscription_topic
105
117
  @root_value = root_value
106
118
  @fragments = nil
@@ -195,7 +207,14 @@ module GraphQL
195
207
  def lookahead
196
208
  @lookahead ||= begin
197
209
  ast_node = selected_operation
198
- root_type = warden.root_type_for_operation(ast_node.operation_type || "query")
210
+ root_type = case ast_node.operation_type
211
+ when nil, "query"
212
+ types.query_root # rubocop:disable Development/ContextIsPassedCop
213
+ when "mutation"
214
+ types.mutation_root # rubocop:disable Development/ContextIsPassedCop
215
+ when "subscription"
216
+ types.subscription_root # rubocop:disable Development/ContextIsPassedCop
217
+ end
199
218
  GraphQL::Execution::Lookahead.new(query: self, root_type: root_type, ast_nodes: [ast_node])
200
219
  end
201
220
  end
@@ -330,6 +349,10 @@ module GraphQL
330
349
 
331
350
  def_delegators :warden, :get_type, :get_field, :possible_types, :root_type_for_operation
332
351
 
352
+ def types
353
+ @schema_subset || warden.schema_subset
354
+ end
355
+
333
356
  # @param abstract_type [GraphQL::UnionType, GraphQL::InterfaceType]
334
357
  # @param value [Object] Any runtime value
335
358
  # @return [GraphQL::ObjectType, nil] The runtime type of `value` from {Schema#resolve_type}
@@ -4,6 +4,7 @@ module GraphQL
4
4
  class AlwaysVisible
5
5
  def self.use(schema, **opts)
6
6
  schema.warden_class = GraphQL::Schema::Warden::NullWarden
7
+ schema.subset_class = GraphQL::Schema::Warden::NullWarden::NullSubset
7
8
  end
8
9
  end
9
10
  end
@@ -130,7 +130,7 @@ module GraphQL
130
130
  end
131
131
 
132
132
  def validate_non_null_input(value_name, ctx, max_errors: nil)
133
- allowed_values = ctx.warden.enum_values(self)
133
+ allowed_values = ctx.types.enum_values(self)
134
134
  matching_value = allowed_values.find { |v| v.graphql_name == value_name }
135
135
 
136
136
  if matching_value.nil?
@@ -141,8 +141,8 @@ module GraphQL
141
141
  end
142
142
 
143
143
  def coerce_result(value, ctx)
144
- warden = ctx.warden
145
- all_values = warden ? warden.enum_values(self) : values.each_value
144
+ types = ctx.types
145
+ all_values = types ? types.enum_values(self) : values.each_value
146
146
  enum_value = all_values.find { |val| val.value == value }
147
147
  if enum_value
148
148
  enum_value.graphql_name
@@ -152,7 +152,7 @@ module GraphQL
152
152
  end
153
153
 
154
154
  def coerce_input(value_name, ctx)
155
- all_values = ctx.warden ? ctx.warden.enum_values(self) : values.each_value
155
+ all_values = ctx.types ? ctx.types.enum_values(self) : values.each_value
156
156
 
157
157
  if v = all_values.find { |val| val.graphql_name == value_name }
158
158
  v.value
@@ -42,8 +42,12 @@ module GraphQL
42
42
  end
43
43
 
44
44
  def directives
45
- if @resolver_class
46
- @resolver_class.directives
45
+ if @resolver_class && (r_dirs = @resolver_class.directives).any?
46
+ if (own_dirs = super).any?
47
+ own_dirs + r_dirs
48
+ else
49
+ r_dirs
50
+ end
47
51
  else
48
52
  super
49
53
  end
@@ -614,7 +618,7 @@ module GraphQL
614
618
  using_arg_values = false
615
619
  end
616
620
 
617
- args = context.warden.arguments(self)
621
+ args = context.types.arguments(self)
618
622
  args.each do |arg|
619
623
  arg_key = arg.keyword
620
624
  if arg_values.key?(arg_key)
@@ -149,7 +149,8 @@ module GraphQL
149
149
 
150
150
  def authorize_arguments(args, values)
151
151
  # remove the `input` wrapper to match values
152
- input_args = args["input"].type.unwrap.arguments(context)
152
+ input_type = args.find { |a| a.graphql_name == "input" }.type.unwrap
153
+ input_args = context.types.arguments(input_type)
153
154
  super(input_args, values)
154
155
  end
155
156
  end