graphql 1.9.7 → 1.9.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.
- checksums.yaml +4 -4
- data/lib/generators/graphql/install_generator.rb +2 -1
- data/lib/generators/graphql/templates/base_argument.erb +4 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +1 -0
- data/lib/graphql/analysis/ast/query_complexity.rb +34 -18
- data/lib/graphql/argument.rb +8 -2
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +1 -1
- data/lib/graphql/language/lexer.rb +24 -13
- data/lib/graphql/language/lexer.rl +23 -13
- data/lib/graphql/query/arguments.rb +16 -15
- data/lib/graphql/schema.rb +105 -48
- data/lib/graphql/schema/argument.rb +12 -1
- data/lib/graphql/schema/build_from_definition.rb +3 -0
- data/lib/graphql/schema/field.rb +3 -8
- data/lib/graphql/schema/find_inherited_value.rb +20 -0
- data/lib/graphql/schema/input_object.rb +1 -3
- data/lib/graphql/schema/loader.rb +1 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +7 -18
- data/lib/graphql/schema/member/has_arguments.rb +4 -9
- data/lib/graphql/schema/member/has_fields.rb +14 -0
- data/lib/graphql/schema/member/relay_shortcuts.rb +2 -2
- data/lib/graphql/schema/resolver.rb +31 -8
- data/lib/graphql/schema/resolver/has_payload_type.rb +3 -2
- data/lib/graphql/schema/subscription.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/spec/graphql/analysis/analyze_query_spec.rb +14 -25
- data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +7 -19
- data/spec/graphql/analysis/ast/max_query_depth_spec.rb +5 -12
- data/spec/graphql/analysis/max_query_complexity_spec.rb +12 -20
- data/spec/graphql/analysis/max_query_depth_spec.rb +6 -13
- data/spec/graphql/language/lexer_spec.rb +19 -1
- data/spec/graphql/schema/argument_spec.rb +1 -1
- data/spec/graphql/schema/build_from_definition_spec.rb +10 -0
- data/spec/graphql/schema/catchall_middleware_spec.rb +6 -9
- data/spec/graphql/schema/input_object_spec.rb +25 -0
- data/spec/graphql/schema/loader_spec.rb +65 -1
- data/spec/graphql/schema/object_spec.rb +21 -0
- data/spec/graphql/schema/resolver_spec.rb +30 -1
- data/spec/graphql/schema_spec.rb +135 -0
- data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +25 -0
- data/spec/integration/rails/generators/graphql/install_generator_spec.rb +20 -0
- data/spec/integration/tmp/app/graphql/types/page_type.rb +5 -0
- data/spec/support/dummy/schema.rb +1 -1
- data/spec/support/lazy_helpers.rb +1 -1
- data/spec/support/parser/filename_example_invalid_utf8.graphql +1 -0
- metadata +10 -132
- data/spec/integration/tmp/app/graphql/types/date_type.rb +0 -14
- data/spec/integration/tmp/dummy/Gemfile +0 -50
- data/spec/integration/tmp/dummy/README.md +0 -24
- data/spec/integration/tmp/dummy/Rakefile +0 -6
- data/spec/integration/tmp/dummy/app/assets/config/manifest.js +0 -3
- data/spec/integration/tmp/dummy/app/assets/javascripts/application.js +0 -16
- data/spec/integration/tmp/dummy/app/assets/javascripts/cable.js +0 -13
- data/spec/integration/tmp/dummy/app/assets/stylesheets/application.css +0 -15
- data/spec/integration/tmp/dummy/app/channels/application_cable/channel.rb +0 -5
- data/spec/integration/tmp/dummy/app/channels/application_cable/connection.rb +0 -5
- data/spec/integration/tmp/dummy/app/controllers/application_controller.rb +0 -4
- data/spec/integration/tmp/dummy/app/controllers/graphql_controller.rb +0 -44
- data/spec/integration/tmp/dummy/app/helpers/application_helper.rb +0 -3
- data/spec/integration/tmp/dummy/app/jobs/application_job.rb +0 -3
- data/spec/integration/tmp/dummy/app/mailers/application_mailer.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/dummy_schema.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/mutations/update_name.rb +0 -15
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_enum.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_input_object.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_interface.rb +0 -6
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_object.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_scalar.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_union.rb +0 -5
- data/spec/integration/tmp/dummy/app/mydirectory/types/mutation_type.rb +0 -12
- data/spec/integration/tmp/dummy/app/mydirectory/types/query_type.rb +0 -14
- data/spec/integration/tmp/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/integration/tmp/dummy/app/views/layouts/mailer.html.erb +0 -13
- data/spec/integration/tmp/dummy/app/views/layouts/mailer.text.erb +0 -1
- data/spec/integration/tmp/dummy/bin/bundle +0 -3
- data/spec/integration/tmp/dummy/bin/rails +0 -4
- data/spec/integration/tmp/dummy/bin/rake +0 -4
- data/spec/integration/tmp/dummy/bin/setup +0 -34
- data/spec/integration/tmp/dummy/bin/update +0 -29
- data/spec/integration/tmp/dummy/config.ru +0 -5
- data/spec/integration/tmp/dummy/config/application.rb +0 -26
- data/spec/integration/tmp/dummy/config/boot.rb +0 -4
- data/spec/integration/tmp/dummy/config/cable.yml +0 -9
- data/spec/integration/tmp/dummy/config/environment.rb +0 -6
- data/spec/integration/tmp/dummy/config/environments/development.rb +0 -52
- data/spec/integration/tmp/dummy/config/environments/production.rb +0 -84
- data/spec/integration/tmp/dummy/config/environments/test.rb +0 -43
- data/spec/integration/tmp/dummy/config/initializers/application_controller_renderer.rb +0 -9
- data/spec/integration/tmp/dummy/config/initializers/assets.rb +0 -12
- data/spec/integration/tmp/dummy/config/initializers/backtrace_silencers.rb +0 -8
- data/spec/integration/tmp/dummy/config/initializers/cookies_serializer.rb +0 -6
- data/spec/integration/tmp/dummy/config/initializers/filter_parameter_logging.rb +0 -5
- data/spec/integration/tmp/dummy/config/initializers/inflections.rb +0 -17
- data/spec/integration/tmp/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/integration/tmp/dummy/config/initializers/new_framework_defaults.rb +0 -24
- data/spec/integration/tmp/dummy/config/initializers/session_store.rb +0 -4
- data/spec/integration/tmp/dummy/config/initializers/wrap_parameters.rb +0 -10
- data/spec/integration/tmp/dummy/config/locales/en.yml +0 -23
- data/spec/integration/tmp/dummy/config/puma.rb +0 -48
- data/spec/integration/tmp/dummy/config/routes.rb +0 -9
- data/spec/integration/tmp/dummy/config/secrets.yml +0 -22
- data/spec/integration/tmp/dummy/db/seeds.rb +0 -8
- data/spec/integration/tmp/dummy/log/test.log +0 -0
- data/spec/integration/tmp/dummy/public/404.html +0 -67
- data/spec/integration/tmp/dummy/public/422.html +0 -67
- data/spec/integration/tmp/dummy/public/500.html +0 -66
- data/spec/integration/tmp/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/integration/tmp/dummy/public/apple-touch-icon.png +0 -0
- data/spec/integration/tmp/dummy/public/favicon.ico +0 -0
- data/spec/integration/tmp/dummy/public/robots.txt +0 -5
- data/spec/integration/tmp/dummy/test/test_helper.rb +0 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8b6424d74c67296edb56f74eb9214313dd9556f1c1ba5e5797c58099afea8958
|
|
4
|
+
data.tar.gz: ae10d626a73f8dc873f2b9b2678bfc3ffc1cd80301ddd15a255e4447c728d285
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 51b253d7218b850a4189affeee6e298d1367e8781289ca2f828ab6bbd70d6a1de205f29531ff697d70807d8107f62c3b9cbfc6325f7847116836ab4f500206ce
|
|
7
|
+
data.tar.gz: f9a81a828f9835ce1222021d0ae3f251c576eba5845df2034e8330456765d2920a28850fa24b7f58cbc7d3e1442bd405995cc3a4bf8d7e17277a73ba8fdb8ab6
|
|
@@ -13,6 +13,7 @@ module Graphql
|
|
|
13
13
|
# - graphql/
|
|
14
14
|
# - resolvers/
|
|
15
15
|
# - types/
|
|
16
|
+
# - base_argument.rb
|
|
16
17
|
# - base_field.rb
|
|
17
18
|
# - base_enum.rb
|
|
18
19
|
# - base_input_object.rb
|
|
@@ -94,7 +95,7 @@ module Graphql
|
|
|
94
95
|
create_dir("#{options[:directory]}/types")
|
|
95
96
|
template("schema.erb", schema_file_path)
|
|
96
97
|
|
|
97
|
-
["base_object", "base_field", "base_enum", "base_input_object", "base_interface", "base_scalar", "base_union"].each do |base_type|
|
|
98
|
+
["base_object", "base_argument", "base_field", "base_enum", "base_input_object", "base_interface", "base_scalar", "base_union"].each do |base_type|
|
|
98
99
|
template("#{base_type}.erb", "#{options[:directory]}/types/#{base_type}.rb")
|
|
99
100
|
end
|
|
100
101
|
|
|
@@ -4,11 +4,11 @@ module GraphQL
|
|
|
4
4
|
# Calculate the complexity of a query, using {Field#complexity} values.
|
|
5
5
|
module AST
|
|
6
6
|
class QueryComplexity < Analyzer
|
|
7
|
-
# State for the query complexity
|
|
7
|
+
# State for the query complexity calculation:
|
|
8
8
|
# - `complexities_on_type` holds complexity scores for each type in an IRep node
|
|
9
9
|
def initialize(query)
|
|
10
10
|
super
|
|
11
|
-
@complexities_on_type = [
|
|
11
|
+
@complexities_on_type = [ConcreteTypeComplexity.new]
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
# Overide this method to use the complexity result
|
|
@@ -22,7 +22,11 @@ module GraphQL
|
|
|
22
22
|
return if visitor.visiting_fragment_definition?
|
|
23
23
|
return if visitor.skipping?
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
if visitor.type_definition.kind.abstract?
|
|
26
|
+
@complexities_on_type.push(AbstractTypeComplexity.new)
|
|
27
|
+
else
|
|
28
|
+
@complexities_on_type.push(ConcreteTypeComplexity.new)
|
|
29
|
+
end
|
|
26
30
|
end
|
|
27
31
|
|
|
28
32
|
def on_leave_field(node, parent, visitor)
|
|
@@ -35,17 +39,14 @@ module GraphQL
|
|
|
35
39
|
child_complexity = type_complexities.max_possible_complexity
|
|
36
40
|
own_complexity = get_complexity(node, visitor.field_definition, child_complexity, visitor)
|
|
37
41
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
if @complexities_on_type.last.is_a?(AbstractTypeComplexity)
|
|
43
|
+
key = selection_key(visitor.response_path, visitor.query)
|
|
44
|
+
parent_type = visitor.parent_type_definition
|
|
45
|
+
query.possible_types(parent_type).each do |type|
|
|
46
|
+
@complexities_on_type.last.merge(type, key, own_complexity)
|
|
47
|
+
end
|
|
41
48
|
else
|
|
42
|
-
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
key = selection_key(visitor.response_path, visitor.query)
|
|
46
|
-
|
|
47
|
-
possible_types.each do |type|
|
|
48
|
-
@complexities_on_type.last.merge(type, key, own_complexity)
|
|
49
|
+
@complexities_on_type.last.merge(own_complexity)
|
|
49
50
|
end
|
|
50
51
|
end
|
|
51
52
|
|
|
@@ -68,7 +69,7 @@ module GraphQL
|
|
|
68
69
|
# We add the query object id to support multiplex queries
|
|
69
70
|
# even if they have the same response path, they should
|
|
70
71
|
# always be added.
|
|
71
|
-
response_path.join(".")
|
|
72
|
+
"#{response_path.join(".")}-#{query.object_id}"
|
|
72
73
|
end
|
|
73
74
|
|
|
74
75
|
# Get a complexity value for a field,
|
|
@@ -91,16 +92,19 @@ module GraphQL
|
|
|
91
92
|
|
|
92
93
|
# Selections on an object may apply differently depending on what is _actually_ returned by the resolve function.
|
|
93
94
|
# Find the maximum possible complexity among those combinations.
|
|
94
|
-
class
|
|
95
|
+
class AbstractTypeComplexity
|
|
95
96
|
def initialize
|
|
96
97
|
@types = Hash.new { |h, k| h[k] = {} }
|
|
97
98
|
end
|
|
98
99
|
|
|
99
100
|
# Return the max possible complexity for types in this selection
|
|
100
101
|
def max_possible_complexity
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
max = 0
|
|
103
|
+
@types.each_value do |fields|
|
|
104
|
+
complexity = fields.each_value.inject(:+)
|
|
105
|
+
max = complexity if complexity > max
|
|
106
|
+
end
|
|
107
|
+
max
|
|
104
108
|
end
|
|
105
109
|
|
|
106
110
|
# Store the complexity for the branch on `type_defn`.
|
|
@@ -109,6 +113,18 @@ module GraphQL
|
|
|
109
113
|
@types[type_defn][key] = complexity
|
|
110
114
|
end
|
|
111
115
|
end
|
|
116
|
+
|
|
117
|
+
class ConcreteTypeComplexity
|
|
118
|
+
attr_reader :max_possible_complexity
|
|
119
|
+
|
|
120
|
+
def initialize
|
|
121
|
+
@max_possible_complexity = 0
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def merge(complexity)
|
|
125
|
+
@max_possible_complexity += complexity
|
|
126
|
+
end
|
|
127
|
+
end
|
|
112
128
|
end
|
|
113
129
|
end
|
|
114
130
|
end
|
data/lib/graphql/argument.rb
CHANGED
|
@@ -35,13 +35,14 @@ module GraphQL
|
|
|
35
35
|
|
|
36
36
|
class Argument
|
|
37
37
|
include GraphQL::Define::InstanceDefinable
|
|
38
|
-
accepts_definitions :name, :type, :description, :default_value, :as, :prepare
|
|
38
|
+
accepts_definitions :name, :type, :description, :default_value, :as, :prepare, :method_access
|
|
39
39
|
attr_reader :default_value
|
|
40
40
|
attr_accessor :description, :name, :as
|
|
41
41
|
attr_accessor :ast_node
|
|
42
|
+
attr_accessor :method_access
|
|
42
43
|
alias :graphql_name :name
|
|
43
44
|
|
|
44
|
-
ensure_defined(:name, :description, :default_value, :type=, :type, :as, :expose_as, :prepare)
|
|
45
|
+
ensure_defined(:name, :description, :default_value, :type=, :type, :as, :expose_as, :prepare, :method_access)
|
|
45
46
|
|
|
46
47
|
# @api private
|
|
47
48
|
module DefaultPrepare
|
|
@@ -60,6 +61,11 @@ module GraphQL
|
|
|
60
61
|
!!@has_default_value
|
|
61
62
|
end
|
|
62
63
|
|
|
64
|
+
def method_access?
|
|
65
|
+
# Treat unset as true -- only `false` should override
|
|
66
|
+
@method_access != false
|
|
67
|
+
end
|
|
68
|
+
|
|
63
69
|
def default_value=(new_default_value)
|
|
64
70
|
if new_default_value == NO_DEFAULT_VALUE
|
|
65
71
|
@has_default_value = false
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module GraphQL
|
|
2
4
|
module Language
|
|
3
5
|
module Lexer
|
|
@@ -1369,7 +1371,7 @@ end
|
|
|
1369
1371
|
def self.record_comment(ts, te, meta)
|
|
1370
1372
|
token = GraphQL::Language::Token.new(
|
|
1371
1373
|
name: :COMMENT,
|
|
1372
|
-
value: meta[:data][ts
|
|
1374
|
+
value: meta[:data][ts, te - ts].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING),
|
|
1373
1375
|
line: meta[:line],
|
|
1374
1376
|
col: meta[:col],
|
|
1375
1377
|
prev_token: meta[:previous_token],
|
|
@@ -1383,7 +1385,7 @@ end
|
|
|
1383
1385
|
def self.emit(token_name, ts, te, meta)
|
|
1384
1386
|
meta[:tokens] << token = GraphQL::Language::Token.new(
|
|
1385
1387
|
name: token_name,
|
|
1386
|
-
value: meta[:data][ts
|
|
1388
|
+
value: meta[:data][ts, te - ts].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING),
|
|
1387
1389
|
line: meta[:line],
|
|
1388
1390
|
col: meta[:col],
|
|
1389
1391
|
prev_token: meta[:previous_token],
|
|
@@ -1415,16 +1417,15 @@ UTF_8_ENCODING = "UTF-8"
|
|
|
1415
1417
|
|
|
1416
1418
|
def self.emit_string(ts, te, meta, block:)
|
|
1417
1419
|
quotes_length = block ? 3 : 1
|
|
1418
|
-
ts
|
|
1419
|
-
value = meta[:data][ts...te - quotes_length].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING)
|
|
1420
|
+
value = meta[:data][ts + quotes_length, te - ts - 2 * quotes_length].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING) || ''
|
|
1420
1421
|
line_incr = 0
|
|
1421
|
-
if block
|
|
1422
|
+
if block && !value.length.zero?
|
|
1422
1423
|
line_incr = value.count("\n")
|
|
1423
1424
|
value = GraphQL::Language::BlockString.trim_whitespace(value)
|
|
1424
1425
|
end
|
|
1425
1426
|
# TODO: replace with `String#match?` when we support only Ruby 2.4+
|
|
1426
1427
|
# (It's faster: https://bugs.ruby-lang.org/issues/8110)
|
|
1427
|
-
if value !~ VALID_STRING
|
|
1428
|
+
if !value.valid_encoding? || value !~ VALID_STRING
|
|
1428
1429
|
meta[:tokens] << token = GraphQL::Language::Token.new(
|
|
1429
1430
|
name: :BAD_UNICODE_ESCAPE,
|
|
1430
1431
|
value: value,
|
|
@@ -1435,13 +1436,23 @@ prev_token: meta[:previous_token],
|
|
|
1435
1436
|
else
|
|
1436
1437
|
replace_escaped_characters_in_place(value)
|
|
1437
1438
|
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1439
|
+
if !value.valid_encoding?
|
|
1440
|
+
meta[:tokens] << token = GraphQL::Language::Token.new(
|
|
1441
|
+
name: :BAD_UNICODE_ESCAPE,
|
|
1442
|
+
value: value,
|
|
1443
|
+
line: meta[:line],
|
|
1444
|
+
col: meta[:col],
|
|
1445
|
+
prev_token: meta[:previous_token],
|
|
1446
|
+
)
|
|
1447
|
+
else
|
|
1448
|
+
meta[:tokens] << token = GraphQL::Language::Token.new(
|
|
1449
|
+
name: :STRING,
|
|
1450
|
+
value: value,
|
|
1451
|
+
line: meta[:line],
|
|
1452
|
+
col: meta[:col],
|
|
1453
|
+
prev_token: meta[:previous_token],
|
|
1454
|
+
)
|
|
1455
|
+
end
|
|
1445
1456
|
end
|
|
1446
1457
|
|
|
1447
1458
|
meta[:previous_token] = token
|
|
@@ -105,6 +105,7 @@
|
|
|
105
105
|
*|;
|
|
106
106
|
}%%
|
|
107
107
|
|
|
108
|
+
# frozen_string_literal: true
|
|
108
109
|
|
|
109
110
|
module GraphQL
|
|
110
111
|
module Language
|
|
@@ -152,7 +153,7 @@ module GraphQL
|
|
|
152
153
|
def self.record_comment(ts, te, meta)
|
|
153
154
|
token = GraphQL::Language::Token.new(
|
|
154
155
|
name: :COMMENT,
|
|
155
|
-
value: meta[:data][ts
|
|
156
|
+
value: meta[:data][ts, te - ts].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING),
|
|
156
157
|
line: meta[:line],
|
|
157
158
|
col: meta[:col],
|
|
158
159
|
prev_token: meta[:previous_token],
|
|
@@ -166,7 +167,7 @@ module GraphQL
|
|
|
166
167
|
def self.emit(token_name, ts, te, meta)
|
|
167
168
|
meta[:tokens] << token = GraphQL::Language::Token.new(
|
|
168
169
|
name: token_name,
|
|
169
|
-
value: meta[:data][ts
|
|
170
|
+
value: meta[:data][ts, te - ts].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING),
|
|
170
171
|
line: meta[:line],
|
|
171
172
|
col: meta[:col],
|
|
172
173
|
prev_token: meta[:previous_token],
|
|
@@ -198,16 +199,15 @@ module GraphQL
|
|
|
198
199
|
|
|
199
200
|
def self.emit_string(ts, te, meta, block:)
|
|
200
201
|
quotes_length = block ? 3 : 1
|
|
201
|
-
ts
|
|
202
|
-
value = meta[:data][ts...te - quotes_length].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING)
|
|
202
|
+
value = meta[:data][ts + quotes_length, te - ts - 2 * quotes_length].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING) || ''
|
|
203
203
|
line_incr = 0
|
|
204
|
-
if block
|
|
204
|
+
if block && !value.length.zero?
|
|
205
205
|
line_incr = value.count("\n")
|
|
206
206
|
value = GraphQL::Language::BlockString.trim_whitespace(value)
|
|
207
207
|
end
|
|
208
208
|
# TODO: replace with `String#match?` when we support only Ruby 2.4+
|
|
209
209
|
# (It's faster: https://bugs.ruby-lang.org/issues/8110)
|
|
210
|
-
if value !~ VALID_STRING
|
|
210
|
+
if !value.valid_encoding? || value !~ VALID_STRING
|
|
211
211
|
meta[:tokens] << token = GraphQL::Language::Token.new(
|
|
212
212
|
name: :BAD_UNICODE_ESCAPE,
|
|
213
213
|
value: value,
|
|
@@ -218,13 +218,23 @@ module GraphQL
|
|
|
218
218
|
else
|
|
219
219
|
replace_escaped_characters_in_place(value)
|
|
220
220
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
221
|
+
if !value.valid_encoding?
|
|
222
|
+
meta[:tokens] << token = GraphQL::Language::Token.new(
|
|
223
|
+
name: :BAD_UNICODE_ESCAPE,
|
|
224
|
+
value: value,
|
|
225
|
+
line: meta[:line],
|
|
226
|
+
col: meta[:col],
|
|
227
|
+
prev_token: meta[:previous_token],
|
|
228
|
+
)
|
|
229
|
+
else
|
|
230
|
+
meta[:tokens] << token = GraphQL::Language::Token.new(
|
|
231
|
+
name: :STRING,
|
|
232
|
+
value: value,
|
|
233
|
+
line: meta[:line],
|
|
234
|
+
col: meta[:col],
|
|
235
|
+
prev_token: meta[:previous_token],
|
|
236
|
+
)
|
|
237
|
+
end
|
|
228
238
|
end
|
|
229
239
|
|
|
230
240
|
meta[:previous_token] = token
|
|
@@ -14,21 +14,22 @@ module GraphQL
|
|
|
14
14
|
self.argument_definitions = argument_definitions
|
|
15
15
|
|
|
16
16
|
argument_definitions.each do |_arg_name, arg_definition|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
17
|
+
if arg_definition.method_access?
|
|
18
|
+
expose_as = arg_definition.expose_as.to_s.freeze
|
|
19
|
+
expose_as_underscored = GraphQL::Schema::Member::BuildType.underscore(expose_as).freeze
|
|
20
|
+
method_names = [expose_as, expose_as_underscored].uniq
|
|
21
|
+
method_names.each do |method_name|
|
|
22
|
+
# Don't define a helper method if it would override something.
|
|
23
|
+
if method_defined?(method_name)
|
|
24
|
+
warn(
|
|
25
|
+
"Unable to define a helper for argument with name '#{method_name}' "\
|
|
26
|
+
"as this is a reserved name. Add `method_access: false` to stop this warning."
|
|
27
|
+
)
|
|
28
|
+
else
|
|
29
|
+
define_method(method_name) do
|
|
30
|
+
# Always use `expose_as` here, since #[] doesn't accept underscored names
|
|
31
|
+
self[expose_as]
|
|
32
|
+
end
|
|
32
33
|
end
|
|
33
34
|
end
|
|
34
35
|
end
|
data/lib/graphql/schema.rb
CHANGED
|
@@ -3,6 +3,7 @@ require "graphql/schema/base_64_encoder"
|
|
|
3
3
|
require "graphql/schema/catchall_middleware"
|
|
4
4
|
require "graphql/schema/default_parse_error"
|
|
5
5
|
require "graphql/schema/default_type_error"
|
|
6
|
+
require "graphql/schema/find_inherited_value"
|
|
6
7
|
require "graphql/schema/finder"
|
|
7
8
|
require "graphql/schema/invalid_type_error"
|
|
8
9
|
require "graphql/schema/introspection_system"
|
|
@@ -81,6 +82,8 @@ module GraphQL
|
|
|
81
82
|
extend Forwardable
|
|
82
83
|
extend GraphQL::Schema::Member::AcceptsDefinition
|
|
83
84
|
include GraphQL::Define::InstanceDefinable
|
|
85
|
+
extend GraphQL::Schema::FindInheritedValue
|
|
86
|
+
|
|
84
87
|
accepts_definitions \
|
|
85
88
|
:query, :mutation, :subscription,
|
|
86
89
|
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
|
@@ -159,7 +162,9 @@ module GraphQL
|
|
|
159
162
|
# @see {Query#tracers} for query-specific tracers
|
|
160
163
|
attr_reader :tracers
|
|
161
164
|
|
|
162
|
-
DYNAMIC_FIELDS = ["__type", "__typename", "__schema"]
|
|
165
|
+
DYNAMIC_FIELDS = ["__type", "__typename", "__schema"].freeze
|
|
166
|
+
EMPTY_ARRAY = [].freeze
|
|
167
|
+
EMPTY_HASH = {}.freeze
|
|
163
168
|
|
|
164
169
|
attr_reader :static_validator, :object_from_id_proc, :id_from_object_proc, :resolve_type_proc
|
|
165
170
|
|
|
@@ -728,11 +733,11 @@ module GraphQL
|
|
|
728
733
|
end
|
|
729
734
|
|
|
730
735
|
def use(plugin, options = {})
|
|
731
|
-
|
|
736
|
+
own_plugins << [plugin, options]
|
|
732
737
|
end
|
|
733
738
|
|
|
734
739
|
def plugins
|
|
735
|
-
|
|
740
|
+
find_inherited_value(:plugins, EMPTY_ARRAY) + own_plugins
|
|
736
741
|
end
|
|
737
742
|
|
|
738
743
|
def to_graphql
|
|
@@ -746,7 +751,7 @@ module GraphQL
|
|
|
746
751
|
schema_defn.max_depth = max_depth
|
|
747
752
|
schema_defn.default_max_page_size = default_max_page_size
|
|
748
753
|
schema_defn.orphan_types = orphan_types
|
|
749
|
-
schema_defn.disable_introspection_entry_points =
|
|
754
|
+
schema_defn.disable_introspection_entry_points = disable_introspection_entry_points?
|
|
750
755
|
|
|
751
756
|
prepped_dirs = {}
|
|
752
757
|
directives.each { |k, v| prepped_dirs[k] = v.graphql_definition}
|
|
@@ -758,15 +763,15 @@ module GraphQL
|
|
|
758
763
|
schema_defn.type_error = method(:type_error)
|
|
759
764
|
schema_defn.context_class = context_class
|
|
760
765
|
schema_defn.cursor_encoder = cursor_encoder
|
|
761
|
-
schema_defn.tracers.concat(
|
|
762
|
-
schema_defn.query_analyzers.concat(
|
|
766
|
+
schema_defn.tracers.concat(tracers)
|
|
767
|
+
schema_defn.query_analyzers.concat(query_analyzers)
|
|
763
768
|
|
|
764
|
-
schema_defn.middleware.concat(
|
|
765
|
-
schema_defn.multiplex_analyzers.concat(
|
|
769
|
+
schema_defn.middleware.concat(all_middleware)
|
|
770
|
+
schema_defn.multiplex_analyzers.concat(multiplex_analyzers)
|
|
766
771
|
schema_defn.query_execution_strategy = query_execution_strategy
|
|
767
772
|
schema_defn.mutation_execution_strategy = mutation_execution_strategy
|
|
768
773
|
schema_defn.subscription_execution_strategy = subscription_execution_strategy
|
|
769
|
-
|
|
774
|
+
all_instrumenters.each do |step, insts|
|
|
770
775
|
insts.each do |inst|
|
|
771
776
|
schema_defn.instrumenters[step] << inst
|
|
772
777
|
end
|
|
@@ -774,10 +779,8 @@ module GraphQL
|
|
|
774
779
|
lazy_classes.each do |lazy_class, value_method|
|
|
775
780
|
schema_defn.lazy_methods.set(lazy_class, value_method)
|
|
776
781
|
end
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
schema_defn.rescue_from(err_class, &handler)
|
|
780
|
-
end
|
|
782
|
+
rescues.each do |err_class, handler|
|
|
783
|
+
schema_defn.rescue_from(err_class, &handler)
|
|
781
784
|
end
|
|
782
785
|
|
|
783
786
|
if plugins.any?
|
|
@@ -806,7 +809,8 @@ module GraphQL
|
|
|
806
809
|
if new_query_object
|
|
807
810
|
@query_object = new_query_object
|
|
808
811
|
else
|
|
809
|
-
|
|
812
|
+
query_object = @query_object || find_inherited_value(:query)
|
|
813
|
+
query_object.respond_to?(:graphql_definition) ? query_object.graphql_definition : query_object
|
|
810
814
|
end
|
|
811
815
|
end
|
|
812
816
|
|
|
@@ -814,7 +818,8 @@ module GraphQL
|
|
|
814
818
|
if new_mutation_object
|
|
815
819
|
@mutation_object = new_mutation_object
|
|
816
820
|
else
|
|
817
|
-
|
|
821
|
+
mutation_object = @mutation_object || find_inherited_value(:mutation)
|
|
822
|
+
mutation_object.respond_to?(:graphql_definition) ? mutation_object.graphql_definition : mutation_object
|
|
818
823
|
end
|
|
819
824
|
end
|
|
820
825
|
|
|
@@ -822,7 +827,8 @@ module GraphQL
|
|
|
822
827
|
if new_subscription_object
|
|
823
828
|
@subscription_object = new_subscription_object
|
|
824
829
|
else
|
|
825
|
-
|
|
830
|
+
subscription_object = @subscription_object || find_inherited_value(:subscription)
|
|
831
|
+
subscription_object.respond_to?(:graphql_definition) ? subscription_object.graphql_definition : subscription_object
|
|
826
832
|
end
|
|
827
833
|
end
|
|
828
834
|
|
|
@@ -830,7 +836,7 @@ module GraphQL
|
|
|
830
836
|
if new_introspection_namespace
|
|
831
837
|
@introspection = new_introspection_namespace
|
|
832
838
|
else
|
|
833
|
-
@introspection
|
|
839
|
+
@introspection || find_inherited_value(:introspection)
|
|
834
840
|
end
|
|
835
841
|
end
|
|
836
842
|
|
|
@@ -838,14 +844,14 @@ module GraphQL
|
|
|
838
844
|
if new_encoder
|
|
839
845
|
@cursor_encoder = new_encoder
|
|
840
846
|
end
|
|
841
|
-
@cursor_encoder || Base64Encoder
|
|
847
|
+
@cursor_encoder || find_inherited_value(:cursor_encoder, Base64Encoder)
|
|
842
848
|
end
|
|
843
849
|
|
|
844
850
|
def default_max_page_size(new_default_max_page_size = nil)
|
|
845
851
|
if new_default_max_page_size
|
|
846
852
|
@default_max_page_size = new_default_max_page_size
|
|
847
853
|
else
|
|
848
|
-
@default_max_page_size
|
|
854
|
+
@default_max_page_size || find_inherited_value(:default_max_page_size)
|
|
849
855
|
end
|
|
850
856
|
end
|
|
851
857
|
|
|
@@ -853,7 +859,7 @@ module GraphQL
|
|
|
853
859
|
if new_query_execution_strategy
|
|
854
860
|
@query_execution_strategy = new_query_execution_strategy
|
|
855
861
|
else
|
|
856
|
-
@query_execution_strategy || self.default_execution_strategy
|
|
862
|
+
@query_execution_strategy || find_inherited_value(:query_execution_strategy, self.default_execution_strategy)
|
|
857
863
|
end
|
|
858
864
|
end
|
|
859
865
|
|
|
@@ -861,7 +867,7 @@ module GraphQL
|
|
|
861
867
|
if new_mutation_execution_strategy
|
|
862
868
|
@mutation_execution_strategy = new_mutation_execution_strategy
|
|
863
869
|
else
|
|
864
|
-
@mutation_execution_strategy || self.default_execution_strategy
|
|
870
|
+
@mutation_execution_strategy || find_inherited_value(:mutation_execution_strategy, self.default_execution_strategy)
|
|
865
871
|
end
|
|
866
872
|
end
|
|
867
873
|
|
|
@@ -869,7 +875,7 @@ module GraphQL
|
|
|
869
875
|
if new_subscription_execution_strategy
|
|
870
876
|
@subscription_execution_strategy = new_subscription_execution_strategy
|
|
871
877
|
else
|
|
872
|
-
@subscription_execution_strategy || self.default_execution_strategy
|
|
878
|
+
@subscription_execution_strategy || find_inherited_value(:subscription_execution_strategy, self.default_execution_strategy)
|
|
873
879
|
end
|
|
874
880
|
end
|
|
875
881
|
|
|
@@ -877,7 +883,7 @@ module GraphQL
|
|
|
877
883
|
if max_complexity
|
|
878
884
|
@max_complexity = max_complexity
|
|
879
885
|
else
|
|
880
|
-
@max_complexity
|
|
886
|
+
@max_complexity || find_inherited_value(:max_complexity)
|
|
881
887
|
end
|
|
882
888
|
end
|
|
883
889
|
|
|
@@ -885,7 +891,7 @@ module GraphQL
|
|
|
885
891
|
if !new_error_bubbling.nil?
|
|
886
892
|
@error_bubbling = new_error_bubbling
|
|
887
893
|
else
|
|
888
|
-
@error_bubbling
|
|
894
|
+
@error_bubbling.nil? ? find_inherited_value(:error_bubbling) : @error_bubbling
|
|
889
895
|
end
|
|
890
896
|
end
|
|
891
897
|
|
|
@@ -893,7 +899,7 @@ module GraphQL
|
|
|
893
899
|
if new_max_depth
|
|
894
900
|
@max_depth = new_max_depth
|
|
895
901
|
else
|
|
896
|
-
@max_depth
|
|
902
|
+
@max_depth || find_inherited_value(:max_depth)
|
|
897
903
|
end
|
|
898
904
|
end
|
|
899
905
|
|
|
@@ -901,12 +907,20 @@ module GraphQL
|
|
|
901
907
|
@disable_introspection_entry_points = true
|
|
902
908
|
end
|
|
903
909
|
|
|
910
|
+
def disable_introspection_entry_points?
|
|
911
|
+
if instance_variable_defined?(:@disable_introspection_entry_points)
|
|
912
|
+
@disable_introspection_entry_points
|
|
913
|
+
else
|
|
914
|
+
find_inherited_value(:disable_introspection_entry_points?, false)
|
|
915
|
+
end
|
|
916
|
+
end
|
|
917
|
+
|
|
904
918
|
def orphan_types(*new_orphan_types)
|
|
905
919
|
if new_orphan_types.any?
|
|
906
|
-
|
|
907
|
-
else
|
|
908
|
-
@orphan_types || []
|
|
920
|
+
own_orphan_types.concat(new_orphan_types.flatten)
|
|
909
921
|
end
|
|
922
|
+
|
|
923
|
+
find_inherited_value(:orphan_types, EMPTY_ARRAY) + own_orphan_types
|
|
910
924
|
end
|
|
911
925
|
|
|
912
926
|
def default_execution_strategy
|
|
@@ -921,17 +935,20 @@ module GraphQL
|
|
|
921
935
|
if new_context_class
|
|
922
936
|
@context_class = new_context_class
|
|
923
937
|
else
|
|
924
|
-
@context_class || GraphQL::Query::Context
|
|
938
|
+
@context_class || find_inherited_value(:context_class, GraphQL::Query::Context)
|
|
925
939
|
end
|
|
926
940
|
end
|
|
927
941
|
|
|
928
942
|
def rescue_from(*err_classes, &handler_block)
|
|
929
|
-
@rescues ||= {}
|
|
930
943
|
err_classes.each do |err_class|
|
|
931
|
-
|
|
944
|
+
own_rescues[err_class] = handler_block
|
|
932
945
|
end
|
|
933
946
|
end
|
|
934
947
|
|
|
948
|
+
def rescues
|
|
949
|
+
find_inherited_value(:rescues, EMPTY_HASH).merge(own_rescues)
|
|
950
|
+
end
|
|
951
|
+
|
|
935
952
|
def resolve_type(type, obj, ctx)
|
|
936
953
|
if type.kind.object?
|
|
937
954
|
type
|
|
@@ -1017,19 +1034,20 @@ module GraphQL
|
|
|
1017
1034
|
else
|
|
1018
1035
|
instrument_step
|
|
1019
1036
|
end
|
|
1020
|
-
|
|
1037
|
+
|
|
1038
|
+
own_instrumenters[step] << instrumenter
|
|
1021
1039
|
end
|
|
1022
1040
|
|
|
1023
1041
|
def directives(new_directives = nil)
|
|
1024
1042
|
if new_directives
|
|
1025
|
-
|
|
1043
|
+
new_directives.each {|d| directive(d) }
|
|
1026
1044
|
end
|
|
1027
1045
|
|
|
1028
|
-
|
|
1046
|
+
find_inherited_value(:directives, default_directives).merge(own_directives)
|
|
1029
1047
|
end
|
|
1030
1048
|
|
|
1031
1049
|
def directive(new_directive)
|
|
1032
|
-
|
|
1050
|
+
own_directives[new_directive.graphql_name] = new_directive
|
|
1033
1051
|
end
|
|
1034
1052
|
|
|
1035
1053
|
def default_directives
|
|
@@ -1041,26 +1059,38 @@ module GraphQL
|
|
|
1041
1059
|
end
|
|
1042
1060
|
|
|
1043
1061
|
def tracer(new_tracer)
|
|
1044
|
-
|
|
1062
|
+
own_tracers << new_tracer
|
|
1063
|
+
end
|
|
1064
|
+
|
|
1065
|
+
def tracers
|
|
1066
|
+
find_inherited_value(:tracers, EMPTY_ARRAY) + own_tracers
|
|
1045
1067
|
end
|
|
1046
1068
|
|
|
1047
1069
|
def query_analyzer(new_analyzer)
|
|
1048
1070
|
if new_analyzer == GraphQL::Authorization::Analyzer
|
|
1049
1071
|
warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
|
|
1050
1072
|
end
|
|
1051
|
-
|
|
1073
|
+
own_query_analyzers << new_analyzer
|
|
1074
|
+
end
|
|
1075
|
+
|
|
1076
|
+
def query_analyzers
|
|
1077
|
+
find_inherited_value(:query_analyzers, EMPTY_ARRAY) + own_query_analyzers
|
|
1052
1078
|
end
|
|
1053
1079
|
|
|
1054
1080
|
def middleware(new_middleware = nil)
|
|
1055
1081
|
if new_middleware
|
|
1056
|
-
|
|
1082
|
+
own_middleware << new_middleware
|
|
1057
1083
|
else
|
|
1058
1084
|
graphql_definition.middleware
|
|
1059
1085
|
end
|
|
1060
1086
|
end
|
|
1061
1087
|
|
|
1062
1088
|
def multiplex_analyzer(new_analyzer)
|
|
1063
|
-
|
|
1089
|
+
own_multiplex_analyzers << new_analyzer
|
|
1090
|
+
end
|
|
1091
|
+
|
|
1092
|
+
def multiplex_analyzers
|
|
1093
|
+
find_inherited_value(:multiplex_analyzers, EMPTY_ARRAY) + own_multiplex_analyzers
|
|
1064
1094
|
end
|
|
1065
1095
|
|
|
1066
1096
|
private
|
|
@@ -1069,24 +1099,51 @@ module GraphQL
|
|
|
1069
1099
|
@lazy_classes ||= {}
|
|
1070
1100
|
end
|
|
1071
1101
|
|
|
1072
|
-
def
|
|
1073
|
-
@
|
|
1102
|
+
def own_plugins
|
|
1103
|
+
@own_plugins ||= []
|
|
1104
|
+
end
|
|
1105
|
+
|
|
1106
|
+
def own_rescues
|
|
1107
|
+
@own_rescues ||= {}
|
|
1074
1108
|
end
|
|
1075
1109
|
|
|
1076
|
-
def
|
|
1077
|
-
@
|
|
1110
|
+
def own_orphan_types
|
|
1111
|
+
@own_orphan_types ||= []
|
|
1078
1112
|
end
|
|
1079
1113
|
|
|
1080
|
-
def
|
|
1114
|
+
def own_directives
|
|
1115
|
+
@own_directives ||= {}
|
|
1116
|
+
end
|
|
1117
|
+
|
|
1118
|
+
def all_instrumenters
|
|
1119
|
+
inherited_instrumenters = find_inherited_value(:all_instrumenters) || Hash.new { |h,k| h[k] = [] }
|
|
1120
|
+
inherited_instrumenters.merge(own_instrumenters) do |_step, inherited, own|
|
|
1121
|
+
inherited + own
|
|
1122
|
+
end
|
|
1123
|
+
end
|
|
1124
|
+
|
|
1125
|
+
def own_instrumenters
|
|
1126
|
+
@own_instrumenters ||= Hash.new { |h,k| h[k] = [] }
|
|
1127
|
+
end
|
|
1128
|
+
|
|
1129
|
+
def own_tracers
|
|
1130
|
+
@own_tracers ||= []
|
|
1131
|
+
end
|
|
1132
|
+
|
|
1133
|
+
def own_query_analyzers
|
|
1081
1134
|
@defined_query_analyzers ||= []
|
|
1082
1135
|
end
|
|
1083
1136
|
|
|
1084
|
-
def
|
|
1085
|
-
|
|
1137
|
+
def all_middleware
|
|
1138
|
+
find_inherited_value(:all_middleware, EMPTY_ARRAY) + own_middleware
|
|
1139
|
+
end
|
|
1140
|
+
|
|
1141
|
+
def own_middleware
|
|
1142
|
+
@own_middleware ||= []
|
|
1086
1143
|
end
|
|
1087
1144
|
|
|
1088
|
-
def
|
|
1089
|
-
@
|
|
1145
|
+
def own_multiplex_analyzers
|
|
1146
|
+
@own_multiplex_analyzers ||= []
|
|
1090
1147
|
end
|
|
1091
1148
|
|
|
1092
1149
|
# Given this schema member, find the class-based definition object
|