graphql 1.11.6 → 1.12.3
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.
- checksums.yaml +4 -4
- data/lib/generators/graphql/install_generator.rb +5 -5
- data/lib/generators/graphql/object_generator.rb +2 -0
- data/lib/generators/graphql/relay_generator.rb +63 -0
- data/lib/generators/graphql/templates/base_connection.erb +8 -0
- data/lib/generators/graphql/templates/base_edge.erb +8 -0
- data/lib/generators/graphql/templates/node_type.erb +9 -0
- data/lib/generators/graphql/templates/object.erb +1 -1
- data/lib/generators/graphql/templates/query_type.erb +1 -3
- data/lib/generators/graphql/templates/schema.erb +8 -35
- data/lib/graphql.rb +39 -4
- data/lib/graphql/analysis/analyze_query.rb +7 -0
- data/lib/graphql/analysis/ast.rb +11 -2
- data/lib/graphql/analysis/ast/visitor.rb +9 -1
- data/lib/graphql/backtrace.rb +28 -19
- data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
- data/lib/graphql/backtrace/table.rb +22 -2
- data/lib/graphql/backtrace/tracer.rb +40 -9
- data/lib/graphql/backwards_compatibility.rb +2 -1
- data/lib/graphql/base_type.rb +1 -1
- data/lib/graphql/compatibility/execution_specification.rb +1 -0
- data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
- data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
- data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
- data/lib/graphql/dataloader.rb +198 -0
- data/lib/graphql/dataloader/null_dataloader.rb +21 -0
- data/lib/graphql/dataloader/request.rb +24 -0
- data/lib/graphql/dataloader/request_all.rb +22 -0
- data/lib/graphql/dataloader/source.rb +93 -0
- data/lib/graphql/define/assign_global_id_field.rb +1 -1
- data/lib/graphql/define/instance_definable.rb +32 -2
- data/lib/graphql/define/type_definer.rb +5 -5
- data/lib/graphql/deprecated_dsl.rb +7 -2
- data/lib/graphql/deprecation.rb +13 -0
- data/lib/graphql/enum_type.rb +2 -0
- data/lib/graphql/execution/errors.rb +4 -0
- data/lib/graphql/execution/execute.rb +7 -0
- data/lib/graphql/execution/interpreter.rb +10 -6
- data/lib/graphql/execution/interpreter/arguments.rb +57 -5
- data/lib/graphql/execution/interpreter/arguments_cache.rb +8 -0
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +0 -7
- data/lib/graphql/execution/interpreter/runtime.rb +219 -117
- data/lib/graphql/execution/multiplex.rb +20 -6
- data/lib/graphql/function.rb +4 -0
- data/lib/graphql/input_object_type.rb +2 -0
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/interface_type.rb +3 -1
- data/lib/graphql/internal_representation/document.rb +2 -2
- data/lib/graphql/internal_representation/rewrite.rb +1 -1
- data/lib/graphql/invalid_null_error.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +50 -23
- data/lib/graphql/object_type.rb +2 -0
- data/lib/graphql/pagination/connection.rb +5 -1
- data/lib/graphql/pagination/connections.rb +6 -16
- data/lib/graphql/query.rb +6 -1
- data/lib/graphql/query/arguments.rb +1 -1
- data/lib/graphql/query/context.rb +8 -1
- data/lib/graphql/query/serial_execution.rb +1 -0
- data/lib/graphql/query/validation_pipeline.rb +1 -1
- data/lib/graphql/relay/array_connection.rb +2 -2
- data/lib/graphql/relay/base_connection.rb +7 -0
- data/lib/graphql/relay/connection_instrumentation.rb +4 -4
- data/lib/graphql/relay/connection_type.rb +1 -1
- data/lib/graphql/relay/mutation.rb +1 -0
- data/lib/graphql/relay/node.rb +3 -0
- data/lib/graphql/relay/type_extensions.rb +2 -0
- data/lib/graphql/scalar_type.rb +2 -0
- data/lib/graphql/schema.rb +80 -29
- data/lib/graphql/schema/argument.rb +25 -7
- data/lib/graphql/schema/build_from_definition.rb +139 -51
- data/lib/graphql/schema/default_type_error.rb +2 -0
- data/lib/graphql/schema/directive.rb +76 -0
- data/lib/graphql/schema/directive/flagged.rb +57 -0
- data/lib/graphql/schema/enum.rb +3 -0
- data/lib/graphql/schema/enum_value.rb +12 -6
- data/lib/graphql/schema/field.rb +50 -22
- data/lib/graphql/schema/field/connection_extension.rb +3 -2
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/input_object.rb +33 -22
- data/lib/graphql/schema/interface.rb +1 -0
- data/lib/graphql/schema/member.rb +4 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +1 -0
- data/lib/graphql/schema/member/build_type.rb +3 -3
- data/lib/graphql/schema/member/has_arguments.rb +67 -50
- data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
- data/lib/graphql/schema/member/has_directives.rb +98 -0
- data/lib/graphql/schema/member/has_validators.rb +31 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
- data/lib/graphql/schema/middleware_chain.rb +1 -1
- data/lib/graphql/schema/object.rb +11 -0
- data/lib/graphql/schema/printer.rb +5 -4
- data/lib/graphql/schema/relay_classic_mutation.rb +1 -1
- data/lib/graphql/schema/resolver.rb +7 -0
- data/lib/graphql/schema/resolver/has_payload_type.rb +2 -0
- data/lib/graphql/schema/subscription.rb +19 -1
- data/lib/graphql/schema/timeout_middleware.rb +3 -1
- data/lib/graphql/schema/validation.rb +4 -2
- data/lib/graphql/schema/validator.rb +163 -0
- data/lib/graphql/schema/validator/exclusion_validator.rb +31 -0
- data/lib/graphql/schema/validator/format_validator.rb +49 -0
- data/lib/graphql/schema/validator/inclusion_validator.rb +33 -0
- data/lib/graphql/schema/validator/length_validator.rb +57 -0
- data/lib/graphql/schema/validator/numericality_validator.rb +71 -0
- data/lib/graphql/schema/validator/required_validator.rb +68 -0
- data/lib/graphql/static_validation.rb +1 -0
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +25 -17
- data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
- data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
- data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
- data/lib/graphql/static_validation/validator.rb +32 -9
- data/lib/graphql/subscriptions.rb +17 -20
- data/lib/graphql/subscriptions/subscription_root.rb +1 -1
- data/lib/graphql/tracing.rb +2 -2
- data/lib/graphql/tracing/appoptics_tracing.rb +3 -1
- data/lib/graphql/tracing/platform_tracing.rb +4 -2
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
- data/lib/graphql/tracing/skylight_tracing.rb +1 -1
- data/lib/graphql/types/int.rb +9 -2
- data/lib/graphql/types/relay.rb +11 -3
- data/lib/graphql/types/relay/base_connection.rb +2 -91
- data/lib/graphql/types/relay/base_edge.rb +2 -34
- data/lib/graphql/types/relay/connection_behaviors.rb +123 -0
- data/lib/graphql/types/relay/default_relay.rb +27 -0
- data/lib/graphql/types/relay/edge_behaviors.rb +42 -0
- data/lib/graphql/types/relay/has_node_field.rb +41 -0
- data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
- data/lib/graphql/types/relay/node.rb +2 -4
- data/lib/graphql/types/relay/node_behaviors.rb +15 -0
- data/lib/graphql/types/relay/node_field.rb +1 -19
- data/lib/graphql/types/relay/nodes_field.rb +1 -19
- data/lib/graphql/types/relay/page_info.rb +2 -14
- data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
- data/lib/graphql/types/string.rb +7 -1
- data/lib/graphql/union_type.rb +2 -0
- data/lib/graphql/upgrader/member.rb +1 -0
- data/lib/graphql/upgrader/schema.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -1
- metadata +53 -9
- data/lib/graphql/types/relay/base_field.rb +0 -22
- data/lib/graphql/types/relay/base_interface.rb +0 -29
- data/lib/graphql/types/relay/base_object.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62556f55d1ce711780044cff00313dedc21f9c07ff69538127f3f96c52c1921c
|
4
|
+
data.tar.gz: 66f0329f3a61cdddd758159e344d1cf9781b5e21e6adf1c37380188c60c73025
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5365accd8e35b1b016de61d9e5c2cf5605d0cb26c0d4baa4d31a4f479b6e91e7d49875fd9837bd426236a23ac52eb3dbb6a57f392ae0ebf25dc191c0e36786f
|
7
|
+
data.tar.gz: 228843044ed696075f3daa6e43a51a518607007417c47f1da3690d2d8e5c5dce0233c702c4101f9d7b94159499d0251fc27a164dc0f5105d6e9674dd4c1565f0
|
@@ -43,9 +43,6 @@ module Graphql
|
|
43
43
|
# post "/graphql", to: "graphql#execute"
|
44
44
|
# ```
|
45
45
|
#
|
46
|
-
# Accept a `--relay` option which adds
|
47
|
-
# The root `node(id: ID!)` field.
|
48
|
-
#
|
49
46
|
# Accept a `--batch` option which adds `GraphQL::Batch` setup.
|
50
47
|
#
|
51
48
|
# Use `--no-graphiql` to skip `graphiql-rails` installation.
|
@@ -79,8 +76,8 @@ module Graphql
|
|
79
76
|
|
80
77
|
class_option :relay,
|
81
78
|
type: :boolean,
|
82
|
-
default:
|
83
|
-
desc: "Include
|
79
|
+
default: true,
|
80
|
+
desc: "Include installation of Relay conventions (nodes, connections, edges)"
|
84
81
|
|
85
82
|
class_option :batch,
|
86
83
|
type: :boolean,
|
@@ -164,7 +161,10 @@ if Rails.env.development?
|
|
164
161
|
RUBY
|
165
162
|
end
|
166
163
|
end
|
164
|
+
end
|
167
165
|
|
166
|
+
if options[:relay]
|
167
|
+
generate("graphql:relay")
|
168
168
|
end
|
169
169
|
|
170
170
|
if gemfile_modified?
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'rails/generators/base'
|
3
|
+
require_relative 'core'
|
4
|
+
|
5
|
+
module Graphql
|
6
|
+
module Generators
|
7
|
+
class RelayGenerator < Rails::Generators::Base
|
8
|
+
include Core
|
9
|
+
|
10
|
+
desc "Add base types and fields for Relay-style nodes and connections"
|
11
|
+
source_root File.expand_path('../templates', __FILE__)
|
12
|
+
|
13
|
+
def install_relay
|
14
|
+
# Add Node, `node(id:)`, and `nodes(ids:)`
|
15
|
+
template("node_type.erb", "#{options[:directory]}/types/node_type.rb")
|
16
|
+
in_root do
|
17
|
+
fields = " # Add `node(id: ID!) and `nodes(ids: [ID!]!)`\n include GraphQL::Types::Relay::HasNodeField\n include GraphQL::Types::Relay::HasNodesField\n\n"
|
18
|
+
inject_into_file "#{options[:directory]}/types/query_type.rb", fields, after: /class .*QueryType\s*<\s*[^\s]+?\n/m, force: false
|
19
|
+
end
|
20
|
+
|
21
|
+
# Add connections and edges
|
22
|
+
template("base_connection.erb", "#{options[:directory]}/types/base_connection.rb")
|
23
|
+
template("base_edge.erb", "#{options[:directory]}/types/base_edge.rb")
|
24
|
+
connectionable_type_files = {
|
25
|
+
"#{options[:directory]}/types/base_object.rb" => /class .*BaseObject\s*<\s*[^\s]+?\n/m,
|
26
|
+
"#{options[:directory]}/types/base_union.rb" => /class .*BaseUnion\s*<\s*[^\s]+?\n/m,
|
27
|
+
"#{options[:directory]}/types/base_interface.rb" => /include GraphQL::Schema::Interface\n/m,
|
28
|
+
}
|
29
|
+
in_root do
|
30
|
+
connectionable_type_files.each do |type_class_file, sentinel|
|
31
|
+
inject_into_file type_class_file, " connection_type_class(Types::BaseConnection)\n", after: sentinel, force: false
|
32
|
+
inject_into_file type_class_file, " edge_type_class(Types::BaseEdge)\n", after: sentinel, force: false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Add object ID hooks & connection plugin
|
37
|
+
schema_code = <<-RUBY
|
38
|
+
|
39
|
+
# Relay-style Object Identification:
|
40
|
+
|
41
|
+
# Return a string UUID for `object`
|
42
|
+
def self.id_from_object(object, type_definition, query_ctx)
|
43
|
+
# Here's a simple implementation which:
|
44
|
+
# - joins the type name & object.id
|
45
|
+
# - encodes it with base64:
|
46
|
+
# GraphQL::Schema::UniqueWithinType.encode(type_definition.name, object.id)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Given a string UUID, find the object
|
50
|
+
def self.object_from_id(id, query_ctx)
|
51
|
+
# For example, to decode the UUIDs generated above:
|
52
|
+
# type_name, item_id = GraphQL::Schema::UniqueWithinType.decode(id)
|
53
|
+
#
|
54
|
+
# Then, based on `type_name` and `id`
|
55
|
+
# find an object in your application
|
56
|
+
# ...
|
57
|
+
end
|
58
|
+
RUBY
|
59
|
+
inject_into_file schema_file_path, schema_code, before: /^end\n/m, force: false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<% module_namespacing_when_supported do -%>
|
2
|
+
module Types
|
3
|
+
class BaseConnection < Types::BaseObject
|
4
|
+
# add `nodes` and `pageInfo` fields, as well as `edge_type(...)` and `node_nullable(...)` overrides
|
5
|
+
include GraphQL::Types::Relay::ConnectionBehaviors
|
6
|
+
end
|
7
|
+
end
|
8
|
+
<% end -%>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<% module_namespacing_when_supported do -%>
|
2
2
|
module Types
|
3
3
|
class <%= type_ruby_name.split('::')[-1] %> < Types::BaseObject
|
4
|
-
<% if options.node %> implements GraphQL::Relay::Node
|
4
|
+
<% if options.node %> implements GraphQL::Types::Relay::Node
|
5
5
|
<% end %><% normalized_fields.each do |f| %> <%= f.to_ruby %>
|
6
6
|
<% end %> end
|
7
7
|
end
|
@@ -1,42 +1,15 @@
|
|
1
1
|
<% module_namespacing_when_supported do -%>
|
2
2
|
class <%= schema_name %> < GraphQL::Schema
|
3
3
|
query(Types::QueryType)
|
4
|
-
|
5
|
-
#
|
6
|
-
use GraphQL::
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
use GraphQL::Pagination::Connections
|
11
|
-
<% if options[:relay] %>
|
12
|
-
# Relay Object Identification:
|
13
|
-
|
14
|
-
# Return a string UUID for `object`
|
15
|
-
def self.id_from_object(object, type_definition, query_ctx)
|
16
|
-
# Here's a simple implementation which:
|
17
|
-
# - joins the type name & object.id
|
18
|
-
# - encodes it with base64:
|
19
|
-
# GraphQL::Schema::UniqueWithinType.encode(type_definition.name, object.id)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Given a string UUID, find the object
|
23
|
-
def self.object_from_id(id, query_ctx)
|
24
|
-
# For example, to decode the UUIDs generated above:
|
25
|
-
# type_name, item_id = GraphQL::Schema::UniqueWithinType.decode(id)
|
26
|
-
#
|
27
|
-
# Then, based on `type_name` and `id`
|
28
|
-
# find an object in your application
|
29
|
-
# ...
|
30
|
-
end
|
31
|
-
|
32
|
-
# Object Resolution
|
33
|
-
def self.resolve_type(type, obj, ctx)
|
4
|
+
<% if options[:batch] %>
|
5
|
+
# GraphQL::Batch setup:
|
6
|
+
use GraphQL::Batch
|
7
|
+
<% end %>
|
8
|
+
# Union and Interface Resolution
|
9
|
+
def self.resolve_type(abstract_type, obj, ctx)
|
34
10
|
# TODO: Implement this function
|
35
|
-
# to return the correct type for `obj`
|
11
|
+
# to return the correct object type for `obj`
|
36
12
|
raise(GraphQL::RequiredImplementationMissingError)
|
37
13
|
end
|
38
|
-
|
39
|
-
# GraphQL::Batch setup:
|
40
|
-
use GraphQL::Batch
|
41
|
-
<% end %>end
|
14
|
+
end
|
42
15
|
<% end -%>
|
data/lib/graphql.rb
CHANGED
@@ -110,6 +110,7 @@ require "graphql/execution"
|
|
110
110
|
require "graphql/runtime_type_error"
|
111
111
|
require "graphql/unresolved_type_error"
|
112
112
|
require "graphql/invalid_null_error"
|
113
|
+
require "graphql/pagination"
|
113
114
|
require "graphql/schema"
|
114
115
|
require "graphql/query"
|
115
116
|
require "graphql/directive"
|
@@ -124,19 +125,20 @@ require "graphql/string_type"
|
|
124
125
|
require "graphql/schema/built_in_types"
|
125
126
|
require "graphql/schema/loader"
|
126
127
|
require "graphql/schema/printer"
|
128
|
+
require "graphql/filter"
|
129
|
+
require "graphql/internal_representation"
|
130
|
+
require "graphql/static_validation"
|
127
131
|
require "graphql/introspection"
|
128
132
|
|
129
133
|
require "graphql/analysis_error"
|
130
134
|
require "graphql/coercion_error"
|
131
135
|
require "graphql/invalid_name_error"
|
136
|
+
require "graphql/integer_decoding_error"
|
132
137
|
require "graphql/integer_encoding_error"
|
133
138
|
require "graphql/string_encoding_error"
|
134
|
-
require "graphql/internal_representation"
|
135
|
-
require "graphql/static_validation"
|
136
139
|
require "graphql/version"
|
137
140
|
require "graphql/compatibility"
|
138
141
|
require "graphql/function"
|
139
|
-
require "graphql/filter"
|
140
142
|
require "graphql/subscriptions"
|
141
143
|
require "graphql/parse_error"
|
142
144
|
require "graphql/backtrace"
|
@@ -146,4 +148,37 @@ require "graphql/authorization"
|
|
146
148
|
require "graphql/unauthorized_error"
|
147
149
|
require "graphql/unauthorized_field_error"
|
148
150
|
require "graphql/load_application_object_failed_error"
|
149
|
-
require "graphql/
|
151
|
+
require "graphql/dataloader"
|
152
|
+
require "graphql/deprecation"
|
153
|
+
|
154
|
+
module GraphQL
|
155
|
+
# Ruby has `deprecate_constant`,
|
156
|
+
# but I don't see a way to give a nice error message in that case,
|
157
|
+
# so I'm doing this instead.
|
158
|
+
DEPRECATED_INT_TYPE = INT_TYPE
|
159
|
+
DEPRECATED_FLOAT_TYPE = FLOAT_TYPE
|
160
|
+
DEPRECATED_STRING_TYPE = STRING_TYPE
|
161
|
+
DEPRECATED_BOOLEAN_TYPE = BOOLEAN_TYPE
|
162
|
+
DEPRECATED_ID_TYPE = ID_TYPE
|
163
|
+
|
164
|
+
remove_const :INT_TYPE
|
165
|
+
remove_const :FLOAT_TYPE
|
166
|
+
remove_const :STRING_TYPE
|
167
|
+
remove_const :BOOLEAN_TYPE
|
168
|
+
remove_const :ID_TYPE
|
169
|
+
|
170
|
+
def self.const_missing(const_name)
|
171
|
+
deprecated_const_name = :"DEPRECATED_#{const_name}"
|
172
|
+
if const_defined?(deprecated_const_name)
|
173
|
+
deprecated_type = const_get(deprecated_const_name)
|
174
|
+
deprecated_caller = caller(1, 1).first
|
175
|
+
# Don't warn about internal uses, like `types.Int`
|
176
|
+
if !deprecated_caller.include?("lib/graphql")
|
177
|
+
warn "GraphQL::#{const_name} is deprecated and will be removed in GraphQL-Ruby 2.0, use GraphQL::Types::#{deprecated_type.graphql_name} instead. (from #{deprecated_caller})"
|
178
|
+
end
|
179
|
+
deprecated_type
|
180
|
+
else
|
181
|
+
super
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -3,6 +3,11 @@ module GraphQL
|
|
3
3
|
module Analysis
|
4
4
|
module_function
|
5
5
|
|
6
|
+
def use(schema_class)
|
7
|
+
schema = schema_class.is_a?(Class) ? schema_class : schema_class.target
|
8
|
+
schema.analysis_engine = self
|
9
|
+
end
|
10
|
+
|
6
11
|
# @return [void]
|
7
12
|
def analyze_multiplex(multiplex, analyzers)
|
8
13
|
multiplex.trace("analyze_multiplex", { multiplex: multiplex }) do
|
@@ -38,6 +43,8 @@ module GraphQL
|
|
38
43
|
# @param analyzers [Array<#call>] Objects that respond to `#call(memo, visit_type, irep_node)`
|
39
44
|
# @return [Array<Any>] Results from those analyzers
|
40
45
|
def analyze_query(query, analyzers, multiplex_states: [])
|
46
|
+
GraphQL::Deprecation.warn "Legacy analysis will be removed in GraphQL-Ruby 2.0, please upgrade to AST Analysis: https://graphql-ruby.org/queries/ast_analysis.html (schema: #{query.schema})"
|
47
|
+
|
41
48
|
query.trace("analyze_query", { query: query }) do
|
42
49
|
analyzers_to_run = analyzers.select do |analyzer|
|
43
50
|
if analyzer.respond_to?(:analyze?)
|
data/lib/graphql/analysis/ast.rb
CHANGED
@@ -13,7 +13,12 @@ module GraphQL
|
|
13
13
|
module_function
|
14
14
|
|
15
15
|
def use(schema_class)
|
16
|
-
schema_class.analysis_engine
|
16
|
+
if schema_class.analysis_engine == self
|
17
|
+
definition_line = caller(2, 1).first
|
18
|
+
GraphQL::Deprecation.warn("GraphQL::Analysis::AST is now the default; remove `use GraphQL::Analysis::AST` from the schema definition (#{definition_line})")
|
19
|
+
else
|
20
|
+
schema_class.analysis_engine = self
|
21
|
+
end
|
17
22
|
end
|
18
23
|
|
19
24
|
# Analyze a multiplex, and all queries within.
|
@@ -67,7 +72,11 @@ module GraphQL
|
|
67
72
|
|
68
73
|
visitor.visit
|
69
74
|
|
70
|
-
|
75
|
+
if visitor.rescued_errors.any?
|
76
|
+
visitor.rescued_errors
|
77
|
+
else
|
78
|
+
query_analyzers.map(&:result)
|
79
|
+
end
|
71
80
|
else
|
72
81
|
[]
|
73
82
|
end
|
@@ -19,6 +19,7 @@ module GraphQL
|
|
19
19
|
@field_definitions = []
|
20
20
|
@argument_definitions = []
|
21
21
|
@directive_definitions = []
|
22
|
+
@rescued_errors = []
|
22
23
|
@query = query
|
23
24
|
@schema = query.schema
|
24
25
|
@response_path = []
|
@@ -32,6 +33,9 @@ module GraphQL
|
|
32
33
|
# @return [Array<GraphQL::ObjectType>] Types whose scope we've entered
|
33
34
|
attr_reader :object_types
|
34
35
|
|
36
|
+
# @return [Array<GraphQL::AnalysisError]
|
37
|
+
attr_reader :rescued_errors
|
38
|
+
|
35
39
|
def visit
|
36
40
|
return unless @document
|
37
41
|
super
|
@@ -239,7 +243,11 @@ module GraphQL
|
|
239
243
|
|
240
244
|
def call_analyzers(method, node, parent)
|
241
245
|
@analyzers.each do |analyzer|
|
242
|
-
|
246
|
+
begin
|
247
|
+
analyzer.public_send(method, node, parent, self)
|
248
|
+
rescue AnalysisError => err
|
249
|
+
@rescued_errors << err
|
250
|
+
end
|
243
251
|
end
|
244
252
|
end
|
245
253
|
|
data/lib/graphql/backtrace.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "graphql/backtrace/inspect_result"
|
3
|
+
require "graphql/backtrace/legacy_tracer"
|
3
4
|
require "graphql/backtrace/table"
|
4
5
|
require "graphql/backtrace/traced_error"
|
5
6
|
require "graphql/backtrace/tracer"
|
@@ -9,13 +10,12 @@ module GraphQL
|
|
9
10
|
# {TracedError} provides a GraphQL backtrace with arguments and return values.
|
10
11
|
# The underlying error is available as {TracedError#cause}.
|
11
12
|
#
|
12
|
-
# WARNING: {.enable} is not threadsafe because {GraphQL::Tracing.install} is not threadsafe.
|
13
|
-
#
|
14
13
|
# @example toggling backtrace annotation
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
14
|
+
# class MySchema < GraphQL::Schema
|
15
|
+
# if Rails.env.development? || Rails.env.test?
|
16
|
+
# use GraphQL::Backtrace
|
17
|
+
# end
|
18
|
+
# end
|
19
19
|
#
|
20
20
|
class Backtrace
|
21
21
|
include Enumerable
|
@@ -23,19 +23,13 @@ module GraphQL
|
|
23
23
|
|
24
24
|
def_delegators :to_a, :each, :[]
|
25
25
|
|
26
|
-
def self.
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
GraphQL::Tracing.uninstall(Backtrace::Tracer)
|
34
|
-
nil
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.use(schema_defn)
|
38
|
-
schema_defn.tracer(self::Tracer)
|
26
|
+
def self.use(schema_defn, legacy: false)
|
27
|
+
tracer = if legacy
|
28
|
+
self::LegacyTracer
|
29
|
+
else
|
30
|
+
self::Tracer
|
31
|
+
end
|
32
|
+
schema_defn.tracer(tracer)
|
39
33
|
end
|
40
34
|
|
41
35
|
def initialize(context, value: nil)
|
@@ -51,5 +45,20 @@ module GraphQL
|
|
51
45
|
def to_a
|
52
46
|
@table.to_backtrace
|
53
47
|
end
|
48
|
+
|
49
|
+
# Used for internal bookkeeping
|
50
|
+
# @api private
|
51
|
+
class Frame
|
52
|
+
attr_reader :path, :query, :ast_node, :object, :field, :arguments, :parent_frame
|
53
|
+
def initialize(path:, query:, ast_node:, object:, field:, arguments:, parent_frame:)
|
54
|
+
@path = path
|
55
|
+
@query = query
|
56
|
+
@ast_node = ast_node
|
57
|
+
@field = field
|
58
|
+
@object = object
|
59
|
+
@arguments = arguments
|
60
|
+
@parent_frame = parent_frame
|
61
|
+
end
|
62
|
+
end
|
54
63
|
end
|
55
64
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class Backtrace
|
4
|
+
module LegacyTracer
|
5
|
+
module_function
|
6
|
+
|
7
|
+
# Implement the {GraphQL::Tracing} API.
|
8
|
+
def trace(key, metadata)
|
9
|
+
case key
|
10
|
+
when "lex", "parse"
|
11
|
+
# No context here, don't have a query yet
|
12
|
+
nil
|
13
|
+
when "execute_multiplex", "analyze_multiplex"
|
14
|
+
# No query context yet
|
15
|
+
nil
|
16
|
+
when "validate", "analyze_query", "execute_query", "execute_query_lazy"
|
17
|
+
query = metadata[:query] || metadata[:queries].first
|
18
|
+
push_data = query
|
19
|
+
multiplex = query.multiplex
|
20
|
+
when "execute_field", "execute_field_lazy"
|
21
|
+
# The interpreter passes `query:`, legacy passes `context:`
|
22
|
+
context = metadata[:context] || ((q = metadata[:query]) && q.context)
|
23
|
+
push_data = context
|
24
|
+
multiplex = context.query.multiplex
|
25
|
+
else
|
26
|
+
# Custom key, no backtrace data for this
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
if push_data
|
31
|
+
multiplex.context[:last_graphql_backtrace_context] = push_data
|
32
|
+
end
|
33
|
+
|
34
|
+
if key == "execute_multiplex"
|
35
|
+
begin
|
36
|
+
yield
|
37
|
+
rescue StandardError => err
|
38
|
+
# This is an unhandled error from execution,
|
39
|
+
# Re-raise it with a GraphQL trace.
|
40
|
+
potential_context = metadata[:multiplex].context[:last_graphql_backtrace_context]
|
41
|
+
|
42
|
+
if potential_context.is_a?(GraphQL::Query::Context) || potential_context.is_a?(GraphQL::Query::Context::FieldResolutionContext)
|
43
|
+
raise TracedError.new(err, potential_context)
|
44
|
+
else
|
45
|
+
raise
|
46
|
+
end
|
47
|
+
ensure
|
48
|
+
metadata[:multiplex].context.delete(:last_graphql_backtrace_context)
|
49
|
+
end
|
50
|
+
else
|
51
|
+
yield
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|