graphql 2.4.14 → 2.4.16
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/graphql/backtrace/table.rb +37 -14
- data/lib/graphql/dashboard/detailed_traces.rb +47 -0
- data/lib/graphql/dashboard/installable.rb +22 -0
- data/lib/graphql/dashboard/limiters.rb +93 -0
- data/lib/graphql/dashboard/operation_store.rb +199 -0
- data/lib/graphql/dashboard/statics/charts.min.css +1 -0
- data/lib/graphql/dashboard/statics/dashboard.css +27 -0
- data/lib/graphql/dashboard/statics/dashboard.js +74 -9
- data/lib/graphql/dashboard/subscriptions.rb +96 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/detailed_traces/traces/index.html.erb +45 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/limiters/limiters/show.html.erb +62 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/not_installed.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/_form.html.erb +23 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/edit.html.erb +21 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/index.html.erb +69 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/new.html.erb +7 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/index.html.erb +39 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/show.html.erb +32 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/index.html.erb +81 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/show.html.erb +71 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/subscriptions/show.html.erb +41 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/index.html.erb +55 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/show.html.erb +40 -0
- data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +49 -1
- data/lib/graphql/dashboard.rb +45 -29
- data/lib/graphql/execution/interpreter/runtime.rb +11 -1
- data/lib/graphql/execution/interpreter.rb +4 -2
- data/lib/graphql/execution/multiplex.rb +1 -1
- data/lib/graphql/language/parser.rb +13 -6
- data/lib/graphql/query.rb +2 -1
- data/lib/graphql/schema/argument.rb +4 -3
- data/lib/graphql/schema/build_from_definition.rb +91 -46
- data/lib/graphql/schema/input_object.rb +9 -8
- data/lib/graphql/schema.rb +3 -1
- data/lib/graphql/testing/helpers.rb +5 -2
- data/lib/graphql/tracing/perfetto_trace.rb +4 -4
- data/lib/graphql/version.rb +1 -1
- metadata +23 -35
- data/lib/graphql/dashboard/views/graphql/dashboard/traces/index.html.erb +0 -63
@@ -0,0 +1,71 @@
|
|
1
|
+
<% content_for(:title, "View #{params[:digest]}") %>
|
2
|
+
<% if @operation.nil? %>
|
3
|
+
<div class="row">
|
4
|
+
<div class="col">
|
5
|
+
<p>No stored operation found for <code><%= params[:digest] %></code>
|
6
|
+
</div>
|
7
|
+
</div>
|
8
|
+
<% else %>
|
9
|
+
<div class="row">
|
10
|
+
<div class="col">
|
11
|
+
<h2>
|
12
|
+
<%= @operation.name %>
|
13
|
+
<% if @operation.is_archived %><small> (archived)</small><% end %>
|
14
|
+
</h2>
|
15
|
+
</div>
|
16
|
+
</div>
|
17
|
+
<div class="row mt-3">
|
18
|
+
<div class="col">
|
19
|
+
<p>Aliases</p>
|
20
|
+
<% if @client_operations.empty? %>
|
21
|
+
<p><em>None</em></p>
|
22
|
+
<% else %>
|
23
|
+
<ul>
|
24
|
+
<% @client_operations.each do |cl_op| %>
|
25
|
+
<li>
|
26
|
+
<code><%= cl_op.operation_alias %></code>
|
27
|
+
<%= link_to(cl_op.client_name, graphql_dashboard.operation_store_client_operations_path(client_name: cl_op.client_name)) %>
|
28
|
+
<%= cl_op.is_archived ? " (archived)" : "" %>
|
29
|
+
</li>
|
30
|
+
<% end %>
|
31
|
+
</ul>
|
32
|
+
<% end %>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
<div class="row">
|
36
|
+
<div class="col">
|
37
|
+
<p>Last Used At</p>
|
38
|
+
<p><code><%= @operation.last_used_at %></code></p>
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
<div class="row">
|
42
|
+
<div class="col">
|
43
|
+
<p>Source</p>
|
44
|
+
<%= textarea_tag "_source", @graphql_source, class: "graphql-highlight form-control", disabled: true, rows: @graphql_source.count("\n") + 1 %>
|
45
|
+
</div>
|
46
|
+
</div>
|
47
|
+
<div class="row mt-3">
|
48
|
+
<div class="col">
|
49
|
+
<p>References</p>
|
50
|
+
<ul>
|
51
|
+
<% @entries.each do |entry| %>
|
52
|
+
<li>
|
53
|
+
<%= link_to(entry.name, graphql_dashboard.operation_store_index_entry_path(name: entry.name)) %>
|
54
|
+
</li>
|
55
|
+
<% end %>
|
56
|
+
</ul>
|
57
|
+
</div>
|
58
|
+
</div>
|
59
|
+
<div class="row mt-3">
|
60
|
+
<div class="col">
|
61
|
+
<p>Digest</p>
|
62
|
+
<p><code><%= @operation.digest %></code></p>
|
63
|
+
</div>
|
64
|
+
</div>
|
65
|
+
<div class="row mt-3">
|
66
|
+
<div class="col">
|
67
|
+
<p>Minified Source</p>
|
68
|
+
<%= textarea_tag "_source", @operation.body, class: "graphql-highlight form-control", disabled: true, rows: @operation.body.count("\n") + 1 %>
|
69
|
+
</div>
|
70
|
+
</div>
|
71
|
+
<% end %>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<% content_for(:title, "Subscription #{params[:id]}") %>
|
2
|
+
<div class="row mt-3">
|
3
|
+
<div class="col">
|
4
|
+
<h3>Subscription: <code><%= params[:id] %></code></h3>
|
5
|
+
</div>
|
6
|
+
</div>
|
7
|
+
|
8
|
+
<% if @query_data.nil? %>
|
9
|
+
<div class="row">
|
10
|
+
<div class="col">
|
11
|
+
<p class="muted"><i>This subscription was not found or is no longer active.</i></p>
|
12
|
+
</div>
|
13
|
+
</div>
|
14
|
+
<% else %>
|
15
|
+
<div class="row">
|
16
|
+
<div class="col">
|
17
|
+
<p>Created at <%= @query_data[:created_at] %>, last triggered at <%= @query_data[:last_triggered_at] || "--" %></p>
|
18
|
+
|
19
|
+
<p>Subscribed? <code><%= @still_subscribed ? "YES" : "NO" %></code></p>
|
20
|
+
<p>Broadcast? <code><%= @is_broadcast ? "YES" : "NO" %></code> <% if @is_broadcast %>
|
21
|
+
<small class="muted"><% if @subscribers_count.nil? %>
|
22
|
+
This subscription may have multiple subscribers.
|
23
|
+
<% else %>
|
24
|
+
(<%= pluralize(@subscribers_count, "subscriber") %>)
|
25
|
+
<% end %></small>
|
26
|
+
<% end %></p>
|
27
|
+
|
28
|
+
<p>Context:</p>
|
29
|
+
<pre><%= @query_data[:context].inspect %></pre>
|
30
|
+
|
31
|
+
<p>Variables:</p>
|
32
|
+
<pre><%= @query_data[:variables].inspect %></pre>
|
33
|
+
|
34
|
+
<p>Operation Name:</p>
|
35
|
+
<pre><%= @query_data[:operation_name].inspect %></pre>
|
36
|
+
|
37
|
+
<p>Query String:</p>
|
38
|
+
<%= textarea_tag "_source", @query_data[:query_string], class: "graphql-highlight form-control", disabled: true, rows: @query_data[:query_string].count("\n") + 1 %>
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
<% end %>
|
@@ -0,0 +1,55 @@
|
|
1
|
+
<% content_for(:title, "Subscriptions - Topics") %>
|
2
|
+
<div class="row mt-3 justify-content-between">
|
3
|
+
<div class="col-auto">
|
4
|
+
<h3>
|
5
|
+
<%= pluralize(@all_topics_count, "Subscription Topic") %>
|
6
|
+
</h3>
|
7
|
+
</div>
|
8
|
+
<div class="col-auto">
|
9
|
+
<%= button_tag "Clear All", class: "btn btn-outline-danger", data: { subscriptions_delete_all: graphql_dashboard.subscriptions_clear_all_path } %>
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
<table class="table table-striped">
|
14
|
+
<thead>
|
15
|
+
<tr>
|
16
|
+
<th>Name</th>
|
17
|
+
<th># Subscriptions</th>
|
18
|
+
<th>Last Triggered At</th>
|
19
|
+
</tr>
|
20
|
+
</thead>
|
21
|
+
<tbody>
|
22
|
+
<% if @all_topics_count == 0 %>
|
23
|
+
<tr>
|
24
|
+
<td colspan="3" class="text-center">
|
25
|
+
<em>There aren't any subscriptions right now.</em>
|
26
|
+
</td>
|
27
|
+
</tr>
|
28
|
+
<% else %>
|
29
|
+
<% @topics.each do |topic| %>
|
30
|
+
<tr>
|
31
|
+
<td><%= link_to(topic.name, graphql_dashboard.subscriptions_topic_path(name: topic.name)) %></td>
|
32
|
+
<td><%= topic.subscriptions_count %></td>
|
33
|
+
<td><%= topic.last_triggered_at || "--" %></td>
|
34
|
+
</tr>
|
35
|
+
<% end %>
|
36
|
+
<% end %>
|
37
|
+
</tbody>
|
38
|
+
</table>
|
39
|
+
|
40
|
+
<div class="row">
|
41
|
+
<div class="col-auto">
|
42
|
+
<% if @page > 1 %>
|
43
|
+
<%= link_to("« prev", graphql_dashboard.subscriptions_topics_path(per_page: params[:per_page], page: @page - 1), class: "btn btn-outline-secondary") %>
|
44
|
+
<% else %>
|
45
|
+
<button class="btn btn-outline-secondary" disabled>« prev</button>
|
46
|
+
<% end %>
|
47
|
+
</div>
|
48
|
+
<div class="col-auto">
|
49
|
+
<% if @has_next_page %>
|
50
|
+
<%= link_to("next »", graphql_dashboard.subscriptions_topics_path(per_page: params[:per_page], page: @page + 1), class: "btn btn-outline-secondary") %>
|
51
|
+
<% else %>
|
52
|
+
<button class="btn btn-outline-secondary" disabled>next »</button>
|
53
|
+
<% end %>
|
54
|
+
</div>
|
55
|
+
</div>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<%= content_for(:title, "Subscriptions - #{params[:name]}") %>
|
2
|
+
<div class="row mt-3">
|
3
|
+
<div class="col">
|
4
|
+
<h3>Topic: <code><%= params[:name] %></code></h3>
|
5
|
+
</div>
|
6
|
+
</div>
|
7
|
+
|
8
|
+
<div class="row">
|
9
|
+
<div class="col">
|
10
|
+
<p>Last triggered: <%= @topic_last_triggered_at || "none" %></p>
|
11
|
+
<p><%= pluralize(@subscriptions_count, "Subscription") %></p>
|
12
|
+
<div>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<div class="row">
|
16
|
+
<div class="col">
|
17
|
+
<table class="table table-striped">
|
18
|
+
<thead>
|
19
|
+
<tr>
|
20
|
+
<th>Subscription ID</th>
|
21
|
+
<th>Created At</th>
|
22
|
+
<th>Subscribed?</th>
|
23
|
+
<th>Broadcast?</th>
|
24
|
+
<% if @show_broadcast_subscribers_count %><th>Subscribers</th><% end %>
|
25
|
+
</tr>
|
26
|
+
</thead>
|
27
|
+
<tbody>
|
28
|
+
<% @subscriptions.each do |subscription| %>
|
29
|
+
<tr>
|
30
|
+
<td><%= link_to(subscription[:id], graphql_dashboard.subscriptions_subscription_path(subscription[:id])) %></td>
|
31
|
+
<td><%= subscription[:created_at] %></td>
|
32
|
+
<td><code><%= subscription[:still_subscribed] ? "YES" : "NO" %></code></td>
|
33
|
+
<td><code><%= subscription[:is_broadcast] ? "YES" : "NO" %></code></td>
|
34
|
+
<% if @show_broadcast_subscribers_count %><td><%= subscription[:subscribers_count] %></td><% end %>
|
35
|
+
</tr>
|
36
|
+
<% end %>
|
37
|
+
</tbody>
|
38
|
+
</table>
|
39
|
+
</div>
|
40
|
+
</div>
|
@@ -6,6 +6,7 @@
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
7
7
|
<title>GraphQL Dashboard <%= content_for?(:title) ? " · #{content_for(:title)}" : "" %> </title>
|
8
8
|
<%= stylesheet_link_tag graphql_dashboard.static_path("bootstrap-5.3.3.min.css") %>
|
9
|
+
<%= stylesheet_link_tag graphql_dashboard.static_path("charts.min.css") %>
|
9
10
|
<%= stylesheet_link_tag graphql_dashboard.static_path("dashboard.css") %>
|
10
11
|
<%= javascript_include_tag graphql_dashboard.static_path("bootstrap-5.3.3.min.js") %>
|
11
12
|
<%= javascript_include_tag graphql_dashboard.static_path("dashboard.js") %>
|
@@ -27,7 +28,44 @@
|
|
27
28
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
28
29
|
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
29
30
|
<li class="nav-item">
|
30
|
-
<%= link_to "Traces", graphql_dashboard.
|
31
|
+
<%= link_to "Traces", graphql_dashboard.detailed_traces_traces_path, class: "nav-link #{params[:controller] == "graphql/dashboard/detailed_traces" ? "active" : ""}" %>
|
32
|
+
</li>
|
33
|
+
<li class="nav-item dropdown">
|
34
|
+
<a class="nav-link dropdown-toggle <%= params[:controller].include?("operation_store") ? "active" : "" %>" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
35
|
+
Persisted Operations
|
36
|
+
</a>
|
37
|
+
<ul class="dropdown-menu">
|
38
|
+
<li>
|
39
|
+
<%= link_to "Clients", graphql_dashboard.operation_store_clients_path, class: "dropdown-item" %>
|
40
|
+
</li>
|
41
|
+
<li>
|
42
|
+
<%= link_to "Operations", graphql_dashboard.operation_store_operations_path, class: "dropdown-item" %>
|
43
|
+
</li>
|
44
|
+
<li>
|
45
|
+
<%= link_to "Index", graphql_dashboard.operation_store_index_entries_path, class: "dropdown-item" %>
|
46
|
+
</li>
|
47
|
+
</ul>
|
48
|
+
</li>
|
49
|
+
<li class="nav-item">
|
50
|
+
<%= link_to "Subscriptions", graphql_dashboard.subscriptions_topics_path, class: "nav-link #{params[:controller] == "graphql/dashboard/subscriptions" ? "active" : ""}" %>
|
51
|
+
</li>
|
52
|
+
<li class="nav-item dropdown">
|
53
|
+
<a class="nav-link dropdown-toggle <%= params[:controller].include?("limiters") ? "active" : "" %>" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
54
|
+
Rate Limiters
|
55
|
+
</a>
|
56
|
+
<ul class="dropdown-menu">
|
57
|
+
<li>
|
58
|
+
<%= link_to "Runtime", graphql_dashboard.limiters_limiter_path("runtime", chart: params[:chart]), class: "dropdown-item" %>
|
59
|
+
</li>
|
60
|
+
<li>
|
61
|
+
<%= link_to "Active Operations", graphql_dashboard.limiters_limiter_path("active_operations", chart: params[:chart]), class: "dropdown-item" %>
|
62
|
+
</li>
|
63
|
+
<% if schema_class.respond_to?(:enterprise_mutation_limiter) && schema_class.enterprise_mutation_limiter %>
|
64
|
+
<li>
|
65
|
+
<%= link_to "Mutations", graphql_dashboard.limiters_limiter_path("mutations", chart: params[:chart]), class: "dropdown-item" %>
|
66
|
+
</li>
|
67
|
+
<% end %>
|
68
|
+
</ul>
|
31
69
|
</li>
|
32
70
|
</ul>
|
33
71
|
<span class="navbar-text pe-2">
|
@@ -38,6 +76,16 @@
|
|
38
76
|
</nav>
|
39
77
|
</div>
|
40
78
|
</div>
|
79
|
+
<% flash.each do |flash_type, flash_message| %>
|
80
|
+
<div class="row mt-2">
|
81
|
+
<div class="col">
|
82
|
+
<div class="alert alert-<%= flash_type %> alert-dismissible fade show" role="alert">
|
83
|
+
<%= flash_message %>
|
84
|
+
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
85
|
+
</div>
|
86
|
+
</div>
|
87
|
+
</div>
|
88
|
+
<% end %>
|
41
89
|
</div>
|
42
90
|
<div class="container-fluid">
|
43
91
|
<%= yield %>
|
data/lib/graphql/dashboard.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require 'rails/engine'
|
3
|
-
|
4
3
|
module Graphql
|
5
4
|
# `GraphQL::Dashboard` is a `Rails::Engine`-based dashboard for viewing metadata about your GraphQL schema.
|
6
5
|
#
|
@@ -38,8 +37,45 @@ module Graphql
|
|
38
37
|
routes.draw do
|
39
38
|
root "landings#show"
|
40
39
|
resources :statics, only: :show, constraints: { id: /[0-9A-Za-z\-.]+/ }
|
41
|
-
|
42
|
-
|
40
|
+
|
41
|
+
namespace :detailed_traces do
|
42
|
+
resources :traces, only: [:index, :show, :destroy] do
|
43
|
+
collection do
|
44
|
+
delete :delete_all, to: "traces#delete_all", as: :delete_all
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
namespace :limiters do
|
50
|
+
resources :limiters, only: [:show, :update], param: :name
|
51
|
+
end
|
52
|
+
|
53
|
+
namespace :operation_store do
|
54
|
+
resources :clients, param: :name do
|
55
|
+
resources :operations, param: :digest, only: [:index] do
|
56
|
+
collection do
|
57
|
+
get :archived, to: "operations#index", archived_status: :archived, as: :archived
|
58
|
+
post :archive, to: "operations#update", modification: :archive, as: :archive
|
59
|
+
post :unarchive, to: "operations#update", modification: :unarchive, as: :unarchive
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
resources :operations, param: :digest, only: [:index, :show] do
|
65
|
+
collection do
|
66
|
+
get :archived, to: "operations#index", archived_status: :archived, as: :archived
|
67
|
+
post :archive, to: "operations#update", modification: :archive, as: :archive
|
68
|
+
post :unarchive, to: "operations#update", modification: :unarchive, as: :unarchive
|
69
|
+
end
|
70
|
+
end
|
71
|
+
resources :index_entries, only: [:index, :show], param: :name, constraints: { name: /[A-Za-z0-9_.]+/}
|
72
|
+
end
|
73
|
+
|
74
|
+
namespace :subscriptions do
|
75
|
+
resources :topics, only: [:index, :show], param: :name, constraints: { name: /.*/ }
|
76
|
+
resources :subscriptions, only: [:show], constraints: { id: /[a-zA-Z0-9\-]+/ }
|
77
|
+
post "/subscriptions/clear_all", to: "subscriptions#clear_all", as: :clear_all
|
78
|
+
end
|
43
79
|
end
|
44
80
|
|
45
81
|
class ApplicationController < ActionController::Base
|
@@ -80,32 +116,6 @@ module Graphql
|
|
80
116
|
end
|
81
117
|
end
|
82
118
|
|
83
|
-
class TracesController < ApplicationController
|
84
|
-
def index
|
85
|
-
@detailed_trace_installed = !!schema_class.detailed_trace
|
86
|
-
if @detailed_trace_installed
|
87
|
-
@last = params[:last]&.to_i || 50
|
88
|
-
@before = params[:before]&.to_i
|
89
|
-
@traces = schema_class.detailed_trace.traces(last: @last, before: @before)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def show
|
94
|
-
trace = schema_class.detailed_trace.find_trace(params[:id].to_i)
|
95
|
-
send_data(trace.trace_data)
|
96
|
-
end
|
97
|
-
|
98
|
-
def destroy
|
99
|
-
schema_class.detailed_trace.delete_trace(params[:id])
|
100
|
-
head :no_content
|
101
|
-
end
|
102
|
-
|
103
|
-
def delete_all
|
104
|
-
schema_class.detailed_trace.delete_all_traces
|
105
|
-
head :no_content
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
119
|
class StaticsController < ApplicationController
|
110
120
|
skip_after_action :verify_same_origin_request
|
111
121
|
# Use an explicit list of files to avoid any chance of reading other files from disk
|
@@ -114,6 +124,7 @@ module Graphql
|
|
114
124
|
[
|
115
125
|
"icon.png",
|
116
126
|
"header-icon.png",
|
127
|
+
"charts.min.css",
|
117
128
|
"dashboard.css",
|
118
129
|
"dashboard.js",
|
119
130
|
"bootstrap-5.3.3.min.css",
|
@@ -134,6 +145,11 @@ module Graphql
|
|
134
145
|
end
|
135
146
|
end
|
136
147
|
|
148
|
+
require 'graphql/dashboard/detailed_traces'
|
149
|
+
require 'graphql/dashboard/limiters'
|
150
|
+
require 'graphql/dashboard/operation_store'
|
151
|
+
require 'graphql/dashboard/subscriptions'
|
152
|
+
|
137
153
|
# Rails expects the engine to be called `Graphql::Dashboard`,
|
138
154
|
# but `GraphQL::Dashboard` is consistent with this gem's naming.
|
139
155
|
# So define both constants to refer to the same class.
|
@@ -587,7 +587,17 @@ module GraphQL
|
|
587
587
|
set_result(selection_result, result_name, r, false, is_non_null)
|
588
588
|
r
|
589
589
|
when "UNION", "INTERFACE"
|
590
|
-
resolved_type_or_lazy =
|
590
|
+
resolved_type_or_lazy = begin
|
591
|
+
resolve_type(current_type, value)
|
592
|
+
rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => ex_err
|
593
|
+
return continue_value(ex_err, field, is_non_null, ast_node, result_name, selection_result)
|
594
|
+
rescue StandardError => err
|
595
|
+
begin
|
596
|
+
query.handle_or_reraise(err)
|
597
|
+
rescue GraphQL::ExecutionError => ex_err
|
598
|
+
return continue_value(ex_err, field, is_non_null, ast_node, result_name, selection_result)
|
599
|
+
end
|
600
|
+
end
|
591
601
|
after_lazy(resolved_type_or_lazy, ast_node: ast_node, field: field, owner_object: owner_object, arguments: arguments, trace: false, result_name: result_name, result: selection_result, runtime_state: runtime_state) do |resolved_type_result, runtime_state|
|
592
602
|
if resolved_type_result.is_a?(Array) && resolved_type_result.length == 2
|
593
603
|
resolved_type, resolved_value = resolved_type_result
|
@@ -23,7 +23,7 @@ module GraphQL
|
|
23
23
|
# @return [Array<GraphQL::Query::Result>] One result per query
|
24
24
|
def run_all(schema, query_options, context: {}, max_complexity: schema.max_complexity)
|
25
25
|
queries = query_options.map do |opts|
|
26
|
-
case opts
|
26
|
+
query = case opts
|
27
27
|
when Hash
|
28
28
|
schema.query_class.new(schema, nil, **opts)
|
29
29
|
when GraphQL::Query
|
@@ -31,12 +31,14 @@ module GraphQL
|
|
31
31
|
else
|
32
32
|
raise "Expected Hash or GraphQL::Query, not #{opts.class} (#{opts.inspect})"
|
33
33
|
end
|
34
|
+
query
|
34
35
|
end
|
35
36
|
|
37
|
+
return GraphQL::EmptyObjects::EMPTY_ARRAY if queries.empty?
|
36
38
|
|
37
39
|
multiplex = Execution::Multiplex.new(schema: schema, queries: queries, context: context, max_complexity: max_complexity)
|
38
|
-
Fiber[:__graphql_current_multiplex] = multiplex
|
39
40
|
trace = multiplex.current_trace
|
41
|
+
Fiber[:__graphql_current_multiplex] = multiplex
|
40
42
|
trace.begin_execute_multiplex(multiplex)
|
41
43
|
trace.execute_multiplex(multiplex: multiplex) do
|
42
44
|
schema = multiplex.schema
|
@@ -32,10 +32,10 @@ module GraphQL
|
|
32
32
|
@queries = queries
|
33
33
|
@queries.each { |q| q.multiplex = self }
|
34
34
|
@context = context
|
35
|
-
@current_trace = @context[:trace] || schema.new_trace(multiplex: self)
|
36
35
|
@dataloader = @context[:dataloader] ||= @schema.dataloader_class.new
|
37
36
|
@tracers = schema.tracers + (context[:tracers] || [])
|
38
37
|
@max_complexity = max_complexity
|
38
|
+
@current_trace = context[:trace] ||= schema.new_trace(multiplex: self)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -488,26 +488,33 @@ module GraphQL
|
|
488
488
|
end
|
489
489
|
|
490
490
|
def type
|
491
|
-
|
491
|
+
parsed_type = case token_name
|
492
492
|
when :IDENTIFIER
|
493
493
|
parse_type_name
|
494
494
|
when :LBRACKET
|
495
495
|
list_type
|
496
|
+
else
|
497
|
+
nil
|
496
498
|
end
|
497
499
|
|
498
|
-
if at?(:BANG)
|
499
|
-
|
500
|
+
if at?(:BANG) && parsed_type
|
501
|
+
parsed_type = Nodes::NonNullType.new(pos: pos, of_type: parsed_type, source: self)
|
500
502
|
expect_token(:BANG)
|
501
503
|
end
|
502
|
-
|
504
|
+
parsed_type
|
503
505
|
end
|
504
506
|
|
505
507
|
def list_type
|
506
508
|
loc = pos
|
507
509
|
expect_token(:LBRACKET)
|
508
|
-
|
510
|
+
inner_type = self.type
|
511
|
+
parsed_list_type = if inner_type
|
512
|
+
Nodes::ListType.new(pos: loc, of_type: inner_type, source: self)
|
513
|
+
else
|
514
|
+
nil
|
515
|
+
end
|
509
516
|
expect_token(:RBRACKET)
|
510
|
-
|
517
|
+
parsed_list_type
|
511
518
|
end
|
512
519
|
|
513
520
|
def parse_operation_type
|
data/lib/graphql/query.rb
CHANGED
@@ -98,9 +98,10 @@ module GraphQL
|
|
98
98
|
# @param max_depth [Numeric] the maximum number of nested selections allowed for this query (falls back to schema-level value)
|
99
99
|
# @param max_complexity [Numeric] the maximum field complexity for this query (falls back to schema-level value)
|
100
100
|
# @param visibility_profile [Symbol] Another way to assign `context[:visibility_profile]`
|
101
|
-
def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, static_validator: nil, visibility_profile: nil, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, warden: nil, use_visibility_profile: nil)
|
101
|
+
def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, multiplex: nil, validate: true, static_validator: nil, visibility_profile: nil, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, warden: nil, use_visibility_profile: nil)
|
102
102
|
# Even if `variables: nil` is passed, use an empty hash for simpler logic
|
103
103
|
variables ||= {}
|
104
|
+
@multiplex = multiplex
|
104
105
|
@schema = schema
|
105
106
|
@context = schema.context_class.new(query: self, values: context)
|
106
107
|
if visibility_profile
|
@@ -217,7 +217,7 @@ module GraphQL
|
|
217
217
|
# @api private
|
218
218
|
def prepare_value(obj, value, context: nil)
|
219
219
|
if type.unwrap.kind.input_object?
|
220
|
-
value = recursively_prepare_input_object(value, type)
|
220
|
+
value = recursively_prepare_input_object(value, type, context)
|
221
221
|
end
|
222
222
|
|
223
223
|
Schema::Validator.validate!(validators, obj, context, value)
|
@@ -398,15 +398,16 @@ module GraphQL
|
|
398
398
|
|
399
399
|
private
|
400
400
|
|
401
|
-
def recursively_prepare_input_object(value, type)
|
401
|
+
def recursively_prepare_input_object(value, type, context)
|
402
402
|
if type.non_null?
|
403
403
|
type = type.of_type
|
404
404
|
end
|
405
405
|
|
406
406
|
if type.list? && !value.nil?
|
407
407
|
inner_type = type.of_type
|
408
|
-
value.map { |v| recursively_prepare_input_object(v, inner_type) }
|
408
|
+
value.map { |v| recursively_prepare_input_object(v, inner_type, context) }
|
409
409
|
elsif value.is_a?(GraphQL::Schema::InputObject)
|
410
|
+
value.validate_for(context)
|
410
411
|
value.prepare
|
411
412
|
else
|
412
413
|
value
|