graphql 2.1.5 → 2.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ab900a93fdb2a8326a75035bf03e27e4874cc959c916d9ac8f85602c78f55c53
4
- data.tar.gz: ca2c67da2b27b4a661759f5e00b49178d12ae312f77d536959e7d825ecd516af
3
+ metadata.gz: f0e3e74b44a52e45b992da7fe79d28ff53ea9871ac621517888f887c1a0bd8fb
4
+ data.tar.gz: fc0a67822082dfc133b1b7f44135df17a5181de2e8404d4b756c4ac0b69a9761
5
5
  SHA512:
6
- metadata.gz: 47639dd694f5c027bd05a2b4fae198fad2b98154ba024785f6fcd844917be5b9bf841ed82b1753061ba9890c5881a8082a62e619090492c7247b345163f45322
7
- data.tar.gz: df76cec39f5bba1ab58958595d508869fd70610feea72af54ff40c0cd4649b8a9bc6ad6d891907b9b69fc517602bf50057d86dab563223988fb5f4ccd2763c0b
6
+ metadata.gz: 00bcdc566706f6fc323b0872c5c36230e7964a518e37825dc14a49cc274cbcac099ab3dca8a24608fafb598dcdfb5c239abb2be81359fd234dbce6954530c044
7
+ data.tar.gz: efb58609553a215455f026bd686b01c699ea858a732733554198150c1c6a0b8f4b60b514c3aa0532bdc611267039c413cb82b5a63bff7a2a7f6b948a3c154814
@@ -2,6 +2,12 @@
2
2
  module GraphQL
3
3
  class Backtrace
4
4
  module Trace
5
+ def initialize(*args, **kwargs, &block)
6
+ @__backtrace_contexts = {}
7
+ @__backtrace_last_context = nil
8
+ super
9
+ end
10
+
5
11
  def validate(query:, validate:)
6
12
  if query.multiplex
7
13
  push_query_backtrace_context(query)
@@ -42,36 +48,27 @@ module GraphQL
42
48
  rescue StandardError => err
43
49
  # This is an unhandled error from execution,
44
50
  # Re-raise it with a GraphQL trace.
45
- multiplex_context = multiplex.context
46
- potential_context = multiplex_context[:last_graphql_backtrace_context]
47
-
51
+ potential_context = @__backtrace_last_context
48
52
  if potential_context.is_a?(GraphQL::Query::Context) ||
49
53
  potential_context.is_a?(Backtrace::Frame)
50
54
  raise TracedError.new(err, potential_context)
51
55
  else
52
56
  raise
53
57
  end
54
- ensure
55
- multiplex_context = multiplex.context
56
- multiplex_context.delete(:graphql_backtrace_contexts)
57
- multiplex_context.delete(:last_graphql_backtrace_context)
58
58
  end
59
59
 
60
60
  private
61
61
 
62
62
  def push_query_backtrace_context(query)
63
63
  push_data = query
64
- multiplex = query.multiplex
65
64
  push_key = []
66
- push_storage = multiplex.context[:graphql_backtrace_contexts] ||= {}
67
- push_storage[push_key] = push_data
68
- multiplex.context[:last_graphql_backtrace_context] = push_data
65
+ @__backtrace_contexts[push_key] = push_data
66
+ @__backtrace_last_context = push_data
69
67
  end
70
68
 
71
69
  def push_field_backtrace_context(field, query, ast_node, arguments, object)
72
- multiplex = query.multiplex
73
70
  push_key = query.context[:current_path]
74
- push_storage = multiplex.context[:graphql_backtrace_contexts]
71
+ push_storage = @__backtrace_contexts
75
72
  parent_frame = push_storage[push_key[0..-2]]
76
73
 
77
74
  if parent_frame.is_a?(GraphQL::Query)
@@ -87,10 +84,10 @@ module GraphQL
87
84
  arguments: arguments,
88
85
  parent_frame: parent_frame,
89
86
  )
90
-
91
87
  push_storage[push_key] = push_data
92
- multiplex.context[:last_graphql_backtrace_context] = push_data
88
+ @__backtrace_last_context = push_data
93
89
  end
90
+
94
91
  end
95
92
  end
96
93
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ # This error is raised when `Types::ISO8601Duration` is asked to return a value
4
+ # that cannot be parsed as an ISO8601-formatted duration by ActiveSupport::Duration.
5
+ #
6
+ # @see GraphQL::Types::ISO8601Duration which raises this error
7
+ class DurationEncodingError < GraphQL::RuntimeTypeError
8
+ # The value which couldn't be encoded
9
+ attr_reader :duration_value
10
+
11
+ def initialize(value)
12
+ @duration_value = value
13
+ super("Duration cannot be parsed: #{value}. \nDuration must be an ISO8601-formatted duration.")
14
+ end
15
+ end
16
+ end
@@ -25,7 +25,7 @@ module GraphQL
25
25
  queries = query_options.map do |opts|
26
26
  case opts
27
27
  when Hash
28
- GraphQL::Query.new(schema, nil, **opts)
28
+ schema.query_class.new(schema, nil, **opts)
29
29
  when GraphQL::Query
30
30
  opts
31
31
  else
@@ -47,10 +47,10 @@ module GraphQL
47
47
  end
48
48
 
49
49
  # Remove leading & trailing blank lines
50
- while lines.size > 0 && lines[0].empty?
50
+ while lines.size > 0 && contains_only_whitespace?(lines.first)
51
51
  lines.shift
52
52
  end
53
- while lines.size > 0 && lines[-1].empty?
53
+ while lines.size > 0 && contains_only_whitespace?(lines.last)
54
54
  lines.pop
55
55
  end
56
56
 
@@ -106,6 +106,10 @@ module GraphQL
106
106
 
107
107
  nil
108
108
  end
109
+
110
+ def self.contains_only_whitespace?(line)
111
+ line.match?(/^\s*$/)
112
+ end
109
113
  end
110
114
  end
111
115
  end
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
+ require "graphql/query/context"
2
3
  module GraphQL
3
4
  class Query
4
5
  # This object can be `ctx` in places where there is no query
5
- class NullContext
6
+ class NullContext < Context
6
7
  include Singleton
7
8
 
8
9
  class NullQuery
data/lib/graphql/query.rb CHANGED
@@ -115,8 +115,6 @@ module GraphQL
115
115
  if schema.trace_class <= GraphQL::Tracing::CallLegacyTracers
116
116
  context_tracers += [GraphQL::Backtrace::Tracer]
117
117
  @tracers << GraphQL::Backtrace::Tracer
118
- elsif !(current_trace.class <= GraphQL::Backtrace::Trace)
119
- raise "Invariant: `backtrace: true` should have provided a trace class with Backtrace mixed in, but it didnt. (Found: #{current_trace.class.ancestors}). This is a bug in GraphQL-Ruby, please report it on GitHub."
120
118
  end
121
119
  end
122
120
 
@@ -1,12 +1,15 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module GraphQL
3
4
  class Railtie < Rails::Railtie
4
- config.before_configuration do
5
- # Bootsnap compile cache has similar expiration properties,
6
- # so we assume that if the user has bootsnap setup it's ok
7
- # to piggy back on it.
8
- if ::Object.const_defined?("Bootsnap::CompileCache::ISeq") && Bootsnap::CompileCache::ISeq.cache_dir
9
- Language::Parser.cache ||= Language::Cache.new(Pathname.new(Bootsnap::CompileCache::ISeq.cache_dir).join('graphql'))
5
+ config.graphql = ActiveSupport::OrderedOptions.new
6
+ config.graphql.parser_cache = false
7
+
8
+ initializer("graphql.cache") do |app|
9
+ if config.graphql.parser_cache
10
+ Language::Parser.cache ||= Language::Cache.new(
11
+ app.root.join("tmp/cache/graphql")
12
+ )
10
13
  end
11
14
  end
12
15
  end
@@ -145,7 +145,7 @@ module GraphQL
145
145
  end
146
146
 
147
147
  # @api private
148
- INVALID_OBJECT_MESSAGE = "Expected %{object} to be a key-value object responding to `to_h` or `to_unsafe_h`."
148
+ INVALID_OBJECT_MESSAGE = "Expected %{object} to be a key-value object."
149
149
 
150
150
  def validate_non_null_input(input, ctx, max_errors: nil)
151
151
  warden = ctx.warden
@@ -21,7 +21,7 @@ module GraphQL
21
21
  if @reauthorize_scoped_objects != nil
22
22
  @reauthorize_scoped_objects
23
23
  else
24
- find_inherited_value(:reauthorize_scoped_objects, nil)
24
+ find_inherited_value(:reauthorize_scoped_objects, true)
25
25
  end
26
26
  else
27
27
  @reauthorize_scoped_objects = new_value
@@ -171,9 +171,9 @@ module GraphQL
171
171
  end
172
172
 
173
173
  # @return [Class] Return the trace class to use for this mode, looking one up on the superclass if this Schema doesn't have one defined.
174
- def trace_class_for(mode)
174
+ def trace_class_for(mode, build: true)
175
175
  own_trace_modes[mode] ||
176
- (superclass.respond_to?(:trace_class_for) ? superclass.trace_class_for(mode) : (own_trace_modes[mode] = build_trace_mode(mode)))
176
+ (superclass.respond_to?(:trace_class_for) ? superclass.trace_class_for(mode, build: build) : (build ? (own_trace_modes[mode] = build_trace_mode(mode)) : nil))
177
177
  end
178
178
 
179
179
  # Configure `trace_class` to be used whenever `context: { trace_mode: mode_name }` is requested.
@@ -218,7 +218,7 @@ module GraphQL
218
218
  else
219
219
  # First, see if the superclass has a custom-defined class for this.
220
220
  # Then, if it doesn't, use this class's default trace
221
- base_class = (superclass.respond_to?(:trace_class_for) && superclass.trace_class_for(mode)) || trace_class_for(:default)
221
+ base_class = (superclass.respond_to?(:trace_class_for) && superclass.trace_class_for(mode, build: false)) || trace_class_for(:default)
222
222
  # Prepare the default trace class if it hasn't been initialized yet
223
223
  base_class ||= (own_trace_modes[:default] = build_trace_mode(:default))
224
224
  mods = trace_modules_for(mode)
@@ -680,7 +680,7 @@ module GraphQL
680
680
  else
681
681
  string_or_document
682
682
  end
683
- query = GraphQL::Query.new(self, document: doc, context: context)
683
+ query = query_class.new(self, document: doc, context: context)
684
684
  validator_opts = { schema: self }
685
685
  rules && (validator_opts[:rules] = rules)
686
686
  validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
@@ -688,6 +688,14 @@ module GraphQL
688
688
  res[:errors]
689
689
  end
690
690
 
691
+ def query_class(new_query_class = NOT_CONFIGURED)
692
+ if NOT_CONFIGURED.equal?(new_query_class)
693
+ @query_class || (superclass.respond_to?(:query_class) ? superclass.query_class : GraphQL::Query)
694
+ else
695
+ @query_class = new_query_class
696
+ end
697
+ end
698
+
691
699
  attr_writer :validate_max_errors
692
700
 
693
701
  def validate_max_errors(new_validate_max_errors = nil)
@@ -35,7 +35,7 @@ module GraphQL
35
35
  # }
36
36
  #
37
37
  # result = MySchema.execute(
38
- # query: query,
38
+ # query,
39
39
  # context: context,
40
40
  # variables: variables,
41
41
  # operation_name: operation_name
@@ -126,7 +126,13 @@ module GraphQL
126
126
  when GraphQL::Schema::InputObject
127
127
  stringify_args(arg_owner, args.to_h, context)
128
128
  else
129
- args
129
+ if arg_owner.is_a?(Class) && arg_owner < GraphQL::Schema::Enum
130
+ # `prepare:` may have made the value something other than
131
+ # a defined value of this enum -- use _that_ in this case.
132
+ arg_owner.coerce_isolated_input(args) || args
133
+ else
134
+ args
135
+ end
130
136
  end
131
137
  end
132
138
 
@@ -62,7 +62,7 @@ module GraphQL
62
62
  # @return [void]
63
63
  def trigger(event_name, args, object, scope: nil, context: {})
64
64
  # Make something as context-like as possible, even though there isn't a current query:
65
- dummy_query = GraphQL::Query.new(@schema, "{ __typename }", validate: false, context: context)
65
+ dummy_query = @schema.query_class.new(@schema, "{ __typename }", validate: false, context: context)
66
66
  context = dummy_query.context
67
67
  event_name = event_name.to_s
68
68
 
@@ -234,7 +234,7 @@ module GraphQL
234
234
 
235
235
  # @return [Boolean] if true, then a query like this one would be broadcasted
236
236
  def broadcastable?(query_str, **query_options)
237
- query = GraphQL::Query.new(@schema, query_str, **query_options)
237
+ query = @schema.query_class.new(@schema, query_str, **query_options)
238
238
  if !query.valid?
239
239
  raise "Invalid query: #{query.validation_errors.map(&:to_h).inspect}"
240
240
  end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Types
4
+ # This scalar takes `Duration`s and transmits them as strings,
5
+ # using ISO 8601 format. ActiveSupport >= 5.0 must be loaded to use
6
+ # this scalar.
7
+ #
8
+ # Use it for fields or arguments as follows:
9
+ #
10
+ # field :age, GraphQL::Types::ISO8601Duration, null: false
11
+ #
12
+ # argument :interval, GraphQL::Types::ISO8601Duration, null: false
13
+ #
14
+ # Alternatively, use this built-in scalar as inspiration for your
15
+ # own Duration type.
16
+ class ISO8601Duration < GraphQL::Schema::Scalar
17
+ description "An ISO 8601-encoded duration"
18
+
19
+ # @return [Integer, nil]
20
+ def self.seconds_precision
21
+ # ActiveSupport::Duration precision defaults to whatever input was given
22
+ @seconds_precision
23
+ end
24
+
25
+ # @param [Integer, nil] value
26
+ def self.seconds_precision=(value)
27
+ @seconds_precision = value
28
+ end
29
+
30
+ # @param value [ActiveSupport::Duration, String]
31
+ # @return [String]
32
+ # @raise [GraphQL::Error] if ActiveSupport::Duration is not defined or if an incompatible object is passed
33
+ def self.coerce_result(value, _ctx)
34
+ unless defined?(ActiveSupport::Duration)
35
+ raise GraphQL::Error, "ActiveSupport >= 5.0 must be loaded to use the built-in ISO8601Duration type."
36
+ end
37
+
38
+ begin
39
+ case value
40
+ when ActiveSupport::Duration
41
+ value.iso8601(precision: seconds_precision)
42
+ when ::String
43
+ ActiveSupport::Duration.parse(value).iso8601(precision: seconds_precision)
44
+ else
45
+ # Try calling as ActiveSupport::Duration compatible as a fallback
46
+ value.iso8601(precision: seconds_precision)
47
+ end
48
+ rescue StandardError => error
49
+ raise GraphQL::Error, "An incompatible object (#{value.class}) was given to #{self}. Make sure that only ActiveSupport::Durations and well-formatted Strings are used with this type. (#{error.message})"
50
+ end
51
+ end
52
+
53
+ # @param value [String, ActiveSupport::Duration]
54
+ # @return [ActiveSupport::Duration, nil]
55
+ # @raise [GraphQL::Error] if ActiveSupport::Duration is not defined
56
+ # @raise [GraphQL::DurationEncodingError] if duration cannot be parsed
57
+ def self.coerce_input(value, ctx)
58
+ unless defined?(ActiveSupport::Duration)
59
+ raise GraphQL::Error, "ActiveSupport >= 5.0 must be loaded to use the built-in ISO8601Duration type."
60
+ end
61
+
62
+ begin
63
+ if value.is_a?(ActiveSupport::Duration)
64
+ value
65
+ elsif value.nil?
66
+ nil
67
+ else
68
+ ActiveSupport::Duration.parse(value)
69
+ end
70
+ rescue ArgumentError, TypeError
71
+ err = GraphQL::DurationEncodingError.new(value)
72
+ ctx.schema.type_error(err, ctx)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -87,6 +87,19 @@ module GraphQL
87
87
  node_type.scope_items(items, context)
88
88
  end
89
89
 
90
+ # The connection will skip auth on its nodes if the node_type is configured for that
91
+ def reauthorize_scoped_objects(new_value = nil)
92
+ if new_value.nil?
93
+ if @reauthorize_scoped_objects != nil
94
+ @reauthorize_scoped_objects
95
+ else
96
+ node_type.reauthorize_scoped_objects
97
+ end
98
+ else
99
+ @reauthorize_scoped_objects = new_value
100
+ end
101
+ end
102
+
90
103
  # Add the shortcut `nodes` field to this connection and its subclasses
91
104
  def nodes_field(node_nullable: self.node_nullable, field_options: nil)
92
105
  define_nodes_field(node_nullable, field_options: field_options)
data/lib/graphql/types.rb CHANGED
@@ -6,6 +6,7 @@ require "graphql/types/id"
6
6
  require "graphql/types/int"
7
7
  require "graphql/types/iso_8601_date"
8
8
  require "graphql/types/iso_8601_date_time"
9
+ require "graphql/types/iso_8601_duration"
9
10
  require "graphql/types/json"
10
11
  require "graphql/types/string"
11
12
  require "graphql/types/relay"
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.1.5"
3
+ VERSION = "2.1.7"
4
4
  end
data/lib/graphql.rb CHANGED
@@ -88,6 +88,7 @@ require "graphql/integer_decoding_error"
88
88
  require "graphql/integer_encoding_error"
89
89
  require "graphql/string_encoding_error"
90
90
  require "graphql/date_encoding_error"
91
+ require "graphql/duration_encoding_error"
91
92
  require "graphql/type_kinds"
92
93
  require "graphql/name_validator"
93
94
  require "graphql/language"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.5
4
+ version: 2.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-25 00:00:00.000000000 Z
11
+ date: 2023-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: racc
@@ -315,6 +315,7 @@ files:
315
315
  - lib/graphql/date_encoding_error.rb
316
316
  - lib/graphql/deprecation.rb
317
317
  - lib/graphql/dig.rb
318
+ - lib/graphql/duration_encoding_error.rb
318
319
  - lib/graphql/execution.rb
319
320
  - lib/graphql/execution/directive_checks.rb
320
321
  - lib/graphql/execution/errors.rb
@@ -584,6 +585,7 @@ files:
584
585
  - lib/graphql/types/int.rb
585
586
  - lib/graphql/types/iso_8601_date.rb
586
587
  - lib/graphql/types/iso_8601_date_time.rb
588
+ - lib/graphql/types/iso_8601_duration.rb
587
589
  - lib/graphql/types/json.rb
588
590
  - lib/graphql/types/relay.rb
589
591
  - lib/graphql/types/relay/base_connection.rb