graphql 1.11.4 → 1.11.5

This diff has not been reviewed by any users.
Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/templates/union.erb +1 -1
  3. data/lib/graphql.rb +16 -0
  4. data/lib/graphql/argument.rb +3 -3
  5. data/lib/graphql/backtrace/tracer.rb +2 -1
  6. data/lib/graphql/execution/interpreter.rb +10 -0
  7. data/lib/graphql/execution/interpreter/arguments.rb +1 -1
  8. data/lib/graphql/execution/interpreter/runtime.rb +32 -18
  9. data/lib/graphql/introspection.rb +96 -0
  10. data/lib/graphql/introspection/field_type.rb +7 -3
  11. data/lib/graphql/introspection/input_value_type.rb +6 -0
  12. data/lib/graphql/introspection/introspection_query.rb +6 -92
  13. data/lib/graphql/introspection/type_type.rb +7 -3
  14. data/lib/graphql/language/block_string.rb +24 -5
  15. data/lib/graphql/language/lexer.rb +7 -3
  16. data/lib/graphql/language/lexer.rl +7 -3
  17. data/lib/graphql/language/nodes.rb +1 -1
  18. data/lib/graphql/language/parser.rb +107 -103
  19. data/lib/graphql/language/parser.y +4 -0
  20. data/lib/graphql/language/sanitized_printer.rb +59 -26
  21. data/lib/graphql/name_validator.rb +6 -7
  22. data/lib/graphql/pagination/connections.rb +2 -0
  23. data/lib/graphql/query.rb +2 -2
  24. data/lib/graphql/query/context.rb +10 -2
  25. data/lib/graphql/schema.rb +30 -16
  26. data/lib/graphql/schema/argument.rb +56 -5
  27. data/lib/graphql/schema/build_from_definition.rb +60 -35
  28. data/lib/graphql/schema/directive/deprecated.rb +1 -1
  29. data/lib/graphql/schema/field.rb +10 -4
  30. data/lib/graphql/schema/input_object.rb +5 -3
  31. data/lib/graphql/schema/interface.rb +1 -1
  32. data/lib/graphql/schema/late_bound_type.rb +2 -2
  33. data/lib/graphql/schema/loader.rb +1 -0
  34. data/lib/graphql/schema/member/build_type.rb +14 -4
  35. data/lib/graphql/schema/member/has_arguments.rb +3 -1
  36. data/lib/graphql/schema/member/type_system_helpers.rb +2 -2
  37. data/lib/graphql/schema/relay_classic_mutation.rb +3 -1
  38. data/lib/graphql/schema/timeout.rb +29 -15
  39. data/lib/graphql/schema/validation.rb +8 -0
  40. data/lib/graphql/static_validation/validator.rb +7 -4
  41. data/lib/graphql/subscriptions.rb +1 -3
  42. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -7
  43. data/lib/graphql/version.rb +1 -1
  44. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c5bf42de25927dab863bd600879d33d204c54bdf124b2b4cc5b27c4c16d4f28b
4
- data.tar.gz: 58b21a4dd5ba80ec0f6c3362013a6adb07c2f1af243e5a851d4c3f08554fe09d
3
+ metadata.gz: 003526dc3efe3c95425607d76c4beffa6777cb71458e7b5ddbc1deecfc5973df
4
+ data.tar.gz: 0aa562c5b69dd2a8294bc90540af71cc4b6e7b8f701f71b3f18a0f47dcf9594b
5
5
  SHA512:
6
- metadata.gz: f199d24a190910e44b189340b6a3d2a3c121ab56ba10ec6cf44d8801107db8d73541f24788b00b13ee7dd357f7bfe6ecff7001f053fe417c777bca59db5851db
7
- data.tar.gz: fd0955c7f67b20370ea376d6a286fdf0ac7272ac5b243d6c309d2159a780cd0b8f92fd0e06ca312a69a16b7c8ad0ebd7bb4587feac9dc77b27da507c9a44cd8f
6
+ metadata.gz: 8563c973af0d9060ae1a90e39affb7b2b8afec3233181f4cb00277d3c754a9446c3f994b8bb9c81689a1d1db92e19f91195b8e2e14a21fec7e2c43c93fc18840
7
+ data.tar.gz: 3e61b7f17cc56bb1873e4efe5b6c5b0e8142b2ec7ea211632476411acf6112876fa554f4a12b56b538480367a4f4f174dd089cd8f24a032257974f9b4079876e
@@ -1,7 +1,7 @@
1
1
  <% module_namespacing_when_supported do -%>
2
2
  module Types
3
3
  class <%= type_ruby_name.split('::')[-1] %> < Types::BaseUnion
4
- <% if possible_types.any? %> possible_types [<%= normalized_possible_types.join(", ") %>]
4
+ <% if possible_types.any? %> possible_types <%= normalized_possible_types.join(", ") %>
5
5
  <% end %> end
6
6
  end
7
7
  <% end -%>
@@ -21,6 +21,14 @@ module GraphQL
21
21
  class RequiredImplementationMissingError < Error
22
22
  end
23
23
 
24
+ class << self
25
+ def default_parser
26
+ @default_parser ||= GraphQL::Language::Parser
27
+ end
28
+
29
+ attr_writer :default_parser
30
+ end
31
+
24
32
  # Turn a query string or schema definition into an AST
25
33
  # @param graphql_string [String] a GraphQL query string or schema definition
26
34
  # @return [GraphQL::Language::Nodes::Document]
@@ -61,6 +69,14 @@ module GraphQL
61
69
  end
62
70
  end
63
71
  end
72
+
73
+ module StringMatchBackport
74
+ refine String do
75
+ def match?(pattern)
76
+ self =~ pattern
77
+ end
78
+ end
79
+ end
64
80
  end
65
81
 
66
82
  # Order matters for these:
@@ -3,14 +3,14 @@ module GraphQL
3
3
  # @api deprecated
4
4
  class Argument
5
5
  include GraphQL::Define::InstanceDefinable
6
- accepts_definitions :name, :type, :description, :default_value, :as, :prepare, :method_access
6
+ accepts_definitions :name, :type, :description, :default_value, :as, :prepare, :method_access, :deprecation_reason
7
7
  attr_reader :default_value
8
- attr_accessor :description, :name, :as
8
+ attr_accessor :description, :name, :as, :deprecation_reason
9
9
  attr_accessor :ast_node
10
10
  attr_accessor :method_access
11
11
  alias :graphql_name :name
12
12
 
13
- ensure_defined(:name, :description, :default_value, :type=, :type, :as, :expose_as, :prepare, :method_access)
13
+ ensure_defined(:name, :description, :default_value, :type=, :type, :as, :expose_as, :prepare, :method_access, :deprecation_reason)
14
14
 
15
15
  # @api private
16
16
  module DefaultPrepare
@@ -15,7 +15,8 @@ module GraphQL
15
15
  when "validate", "analyze_query", "execute_query", "execute_query_lazy"
16
16
  metadata[:query] || metadata[:queries]
17
17
  when "execute_field", "execute_field_lazy"
18
- metadata[:context]
18
+ # The interpreter passes `query:`, legacy passes `context:`
19
+ metadata[:context] || ((q = metadata[:query]) && q.context)
19
20
  else
20
21
  # Custom key, no backtrace data for this
21
22
  nil
@@ -93,6 +93,16 @@ module GraphQL
93
93
  tracer.trace("execute_query_lazy", {multiplex: multiplex, query: query}) do
94
94
  Interpreter::Resolve.resolve_all(final_values)
95
95
  end
96
+ queries.each do |query|
97
+ runtime = query.context.namespace(:interpreter)[:runtime]
98
+ if runtime
99
+ runtime.delete_interpreter_context(:current_path)
100
+ runtime.delete_interpreter_context(:current_field)
101
+ runtime.delete_interpreter_context(:current_object)
102
+ runtime.delete_interpreter_context(:current_arguments)
103
+ end
104
+ end
105
+ nil
96
106
  end
97
107
 
98
108
  class ListResultFailedError < GraphQL::Error
@@ -24,7 +24,7 @@ module GraphQL
24
24
  # @return [Hash{Symbol => ArgumentValue}]
25
25
  attr_reader :argument_values
26
26
 
27
- def_delegators :@keyword_arguments, :key?, :[], :keys, :each, :values
27
+ def_delegators :@keyword_arguments, :key?, :[], :fetch, :keys, :each, :values
28
28
  def_delegators :@argument_values, :each_value
29
29
 
30
30
  def inspect
@@ -43,23 +43,25 @@ module GraphQL
43
43
  # might be stored up in lazies.
44
44
  # @return [void]
45
45
  def run_eager
46
-
47
46
  root_operation = query.selected_operation
48
47
  root_op_type = root_operation.operation_type || "query"
49
48
  root_type = schema.root_type_for_operation(root_op_type)
50
49
  path = []
51
- @interpreter_context[:current_object] = query.root_value
52
- @interpreter_context[:current_path] = path
50
+ set_interpreter_context(:current_object, query.root_value)
51
+ set_interpreter_context(:current_path, path)
53
52
  object_proxy = authorized_new(root_type, query.root_value, context, path)
54
53
  object_proxy = schema.sync_lazy(object_proxy)
55
54
  if object_proxy.nil?
56
55
  # Root .authorized? returned false.
57
56
  write_in_response(path, nil)
58
- nil
59
57
  else
60
58
  evaluate_selections(path, context.scoped_context, object_proxy, root_type, root_operation.selections, root_operation_type: root_op_type)
61
- nil
62
59
  end
60
+ delete_interpreter_context(:current_path)
61
+ delete_interpreter_context(:current_field)
62
+ delete_interpreter_context(:current_object)
63
+ delete_interpreter_context(:current_arguments)
64
+ nil
63
65
  end
64
66
 
65
67
  def gather_selections(owner_object, owner_type, selections, selections_by_name)
@@ -117,8 +119,8 @@ module GraphQL
117
119
  end
118
120
 
119
121
  def evaluate_selections(path, scoped_context, owner_object, owner_type, selections, root_operation_type: nil)
120
- @interpreter_context[:current_object] = owner_object
121
- @interpreter_context[:current_path] = path
122
+ set_interpreter_context(:current_object, owner_object)
123
+ set_interpreter_context(:current_path, path)
122
124
  selections_by_name = {}
123
125
  gather_selections(owner_object, owner_type, selections, selections_by_name)
124
126
  selections_by_name.each do |result_name, field_ast_nodes_or_ast_node|
@@ -157,8 +159,8 @@ module GraphQL
157
159
  # to propagate `null`
158
160
  set_type_at_path(next_path, return_type)
159
161
  # Set this before calling `run_with_directives`, so that the directive can have the latest path
160
- @interpreter_context[:current_path] = next_path
161
- @interpreter_context[:current_field] = field_defn
162
+ set_interpreter_context(:current_path, next_path)
163
+ set_interpreter_context(:current_field, field_defn)
162
164
 
163
165
  context.scoped_context = scoped_context
164
166
  object = owner_object
@@ -206,7 +208,7 @@ module GraphQL
206
208
  end
207
209
  end
208
210
 
209
- @interpreter_context[:current_arguments] = kwarg_arguments
211
+ set_interpreter_context(:current_arguments, kwarg_arguments)
210
212
 
211
213
  # Optimize for the case that field is selected only once
212
214
  if field_ast_nodes.nil? || field_ast_nodes.size == 1
@@ -419,16 +421,16 @@ module GraphQL
419
421
  # @param trace [Boolean] If `false`, don't wrap this with field tracing
420
422
  # @return [GraphQL::Execution::Lazy, Object] If loading `object` will be deferred, it's a wrapper over it.
421
423
  def after_lazy(lazy_obj, owner:, field:, path:, scoped_context:, owner_object:, arguments:, eager: false, trace: true, &block)
422
- @interpreter_context[:current_object] = owner_object
423
- @interpreter_context[:current_arguments] = arguments
424
- @interpreter_context[:current_path] = path
425
- @interpreter_context[:current_field] = field
424
+ set_interpreter_context(:current_object, owner_object)
425
+ set_interpreter_context(:current_arguments, arguments)
426
+ set_interpreter_context(:current_path, path)
427
+ set_interpreter_context(:current_field, field)
426
428
  if schema.lazy?(lazy_obj)
427
429
  lazy = GraphQL::Execution::Lazy.new(path: path, field: field) do
428
- @interpreter_context[:current_path] = path
429
- @interpreter_context[:current_field] = field
430
- @interpreter_context[:current_object] = owner_object
431
- @interpreter_context[:current_arguments] = arguments
430
+ set_interpreter_context(:current_path, path)
431
+ set_interpreter_context(:current_field, field)
432
+ set_interpreter_context(:current_object, owner_object)
433
+ set_interpreter_context(:current_arguments, arguments)
432
434
  context.scoped_context = scoped_context
433
435
  # Wrap the execution of _this_ method with tracing,
434
436
  # but don't wrap the continuation below
@@ -539,6 +541,18 @@ module GraphQL
539
541
  res && res[:__dead]
540
542
  end
541
543
 
544
+ # Set this pair in the Query context, but also in the interpeter namespace,
545
+ # for compatibility.
546
+ def set_interpreter_context(key, value)
547
+ @interpreter_context[key] = value
548
+ @context[key] = value
549
+ end
550
+
551
+ def delete_interpreter_context(key)
552
+ @interpreter_context.delete(key)
553
+ @context.delete(key)
554
+ end
555
+
542
556
  def resolve_type(type, value, path)
543
557
  trace_payload = { context: context, type: type, object: value, path: path }
544
558
  resolved_type, resolved_value = query.trace("resolve_type", trace_payload) do
@@ -1,6 +1,102 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module Introspection
4
+ def self.query(include_deprecated_args: false)
5
+ # The introspection query to end all introspection queries, copied from
6
+ # https://github.com/graphql/graphql-js/blob/master/src/utilities/introspectionQuery.js
7
+ <<-QUERY
8
+ query IntrospectionQuery {
9
+ __schema {
10
+ queryType { name }
11
+ mutationType { name }
12
+ subscriptionType { name }
13
+ types {
14
+ ...FullType
15
+ }
16
+ directives {
17
+ name
18
+ description
19
+ locations
20
+ args {
21
+ ...InputValue
22
+ }
23
+ }
24
+ }
25
+ }
26
+ fragment FullType on __Type {
27
+ kind
28
+ name
29
+ description
30
+ fields(includeDeprecated: true) {
31
+ name
32
+ description
33
+ args#{include_deprecated_args ? '(includeDeprecated: true)' : ''} {
34
+ ...InputValue
35
+ }
36
+ type {
37
+ ...TypeRef
38
+ }
39
+ isDeprecated
40
+ deprecationReason
41
+ }
42
+ inputFields#{include_deprecated_args ? '(includeDeprecated: true)' : ''} {
43
+ ...InputValue
44
+ }
45
+ interfaces {
46
+ ...TypeRef
47
+ }
48
+ enumValues(includeDeprecated: true) {
49
+ name
50
+ description
51
+ isDeprecated
52
+ deprecationReason
53
+ }
54
+ possibleTypes {
55
+ ...TypeRef
56
+ }
57
+ }
58
+ fragment InputValue on __InputValue {
59
+ name
60
+ description
61
+ type { ...TypeRef }
62
+ defaultValue
63
+ #{include_deprecated_args ? 'isDeprecated' : ''}
64
+ #{include_deprecated_args ? 'deprecationReason' : ''}
65
+ }
66
+ fragment TypeRef on __Type {
67
+ kind
68
+ name
69
+ ofType {
70
+ kind
71
+ name
72
+ ofType {
73
+ kind
74
+ name
75
+ ofType {
76
+ kind
77
+ name
78
+ ofType {
79
+ kind
80
+ name
81
+ ofType {
82
+ kind
83
+ name
84
+ ofType {
85
+ kind
86
+ name
87
+ ofType {
88
+ kind
89
+ name
90
+ }
91
+ }
92
+ }
93
+ }
94
+ }
95
+ }
96
+ }
97
+ }
98
+ QUERY
99
+ end
4
100
  end
5
101
  end
6
102
 
@@ -7,7 +7,9 @@ module GraphQL
7
7
  "a name, potentially a list of arguments, and a return type."
8
8
  field :name, String, null: false
9
9
  field :description, String, null: true
10
- field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false
10
+ field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
11
+ argument :include_deprecated, Boolean, required: false, default_value: false
12
+ end
11
13
  field :type, GraphQL::Schema::LateBoundType.new("__Type"), null: false
12
14
  field :is_deprecated, Boolean, null: false
13
15
  field :deprecation_reason, String, null: true
@@ -16,8 +18,10 @@ module GraphQL
16
18
  !!@object.deprecation_reason
17
19
  end
18
20
 
19
- def args
20
- @context.warden.arguments(@object)
21
+ def args(include_deprecated:)
22
+ args = @context.warden.arguments(@object)
23
+ args = args.reject(&:deprecation_reason) unless include_deprecated
24
+ args
21
25
  end
22
26
  end
23
27
  end
@@ -10,6 +10,12 @@ module GraphQL
10
10
  field :description, String, null: true
11
11
  field :type, GraphQL::Schema::LateBoundType.new("__Type"), null: false
12
12
  field :default_value, String, "A GraphQL-formatted string representing the default value for this input value.", null: true
13
+ field :is_deprecated, Boolean, null: false
14
+ field :deprecation_reason, String, null: true
15
+
16
+ def is_deprecated
17
+ !!@object.deprecation_reason
18
+ end
13
19
 
14
20
  def default_value
15
21
  if @object.default_value?
@@ -1,93 +1,7 @@
1
1
  # frozen_string_literal: true
2
- # The introspection query to end all introspection queries, copied from
3
- # https://github.com/graphql/graphql-js/blob/master/src/utilities/introspectionQuery.js
4
- GraphQL::Introspection::INTROSPECTION_QUERY = "
5
- query IntrospectionQuery {
6
- __schema {
7
- queryType { name }
8
- mutationType { name }
9
- subscriptionType { name }
10
- types {
11
- ...FullType
12
- }
13
- directives {
14
- name
15
- description
16
- locations
17
- args {
18
- ...InputValue
19
- }
20
- }
21
- }
22
- }
23
- fragment FullType on __Type {
24
- kind
25
- name
26
- description
27
- fields(includeDeprecated: true) {
28
- name
29
- description
30
- args {
31
- ...InputValue
32
- }
33
- type {
34
- ...TypeRef
35
- }
36
- isDeprecated
37
- deprecationReason
38
- }
39
- inputFields {
40
- ...InputValue
41
- }
42
- interfaces {
43
- ...TypeRef
44
- }
45
- enumValues(includeDeprecated: true) {
46
- name
47
- description
48
- isDeprecated
49
- deprecationReason
50
- }
51
- possibleTypes {
52
- ...TypeRef
53
- }
54
- }
55
- fragment InputValue on __InputValue {
56
- name
57
- description
58
- type { ...TypeRef }
59
- defaultValue
60
- }
61
- fragment TypeRef on __Type {
62
- kind
63
- name
64
- ofType {
65
- kind
66
- name
67
- ofType {
68
- kind
69
- name
70
- ofType {
71
- kind
72
- name
73
- ofType {
74
- kind
75
- name
76
- ofType {
77
- kind
78
- name
79
- ofType {
80
- kind
81
- name
82
- ofType {
83
- kind
84
- name
85
- }
86
- }
87
- }
88
- }
89
- }
90
- }
91
- }
92
- }
93
- "
2
+
3
+ # This query is used by graphql-client so don't add the includeDeprecated
4
+ # argument for inputFields since the server may not support it. Two stage
5
+ # introspection queries will be required to handle this in clients.
6
+ GraphQL::Introspection::INTROSPECTION_QUERY = GraphQL::Introspection.query
7
+