graphql 2.5.16 → 2.5.17

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 92559d0138e0b495e6bc3e571fb804c6ace53a9b60facf3711323bafe3f7970a
4
- data.tar.gz: 1acd789d92c34070bbe768d4f390f58a540e99627e9d3171b25b423d2a0356f1
3
+ metadata.gz: d40b5d01a8893953acba37211831016d36fc8637d3fbf7b9b78fa9a4b96c2acc
4
+ data.tar.gz: 0f4e8eb596248a416ab52aec42f2842c7cbdd87db60fc3c50cf8f2e9dcdcdb14
5
5
  SHA512:
6
- metadata.gz: 2c72b2c1092240a9c5e25e331fed78a24da102e1cb0afa998c503010ced4359333ea24f735c705dfed6d3fb33307215d15e12202064ad4ee1b9bd8a1f7b57acc
7
- data.tar.gz: 2606dd0c0a569c263c357873bcf7fe53bd19f990ac8b20cbaab0ef06daedb52ffdbac4cc483d6256066513895a64056312c56a51d7f483a7882b5cf57c99a0e9
6
+ metadata.gz: c7003f8c0b10a3670a4ab01a631914ad08ee8294742cae7f06361b091b1d35997bbbabcd1f88685ad8962e5b7073e47f448f2c8bdc96eb15aaf25a151b1a6f7f
7
+ data.tar.gz: 309018d1992edfd95ff8da13e43b5ade86b42e12f80dce32c4743fa66592e61334af6a2bedfb5eb206e52ee54280937fe44a244a6eb30fe7a05aabf45370be5a
@@ -20,4 +20,5 @@
20
20
  <div class="col-auto">
21
21
  <%= link_to "Back", graphql_dashboard.operation_store_clients_path, class: "btn btn-outline-secondary" %>
22
22
  </div>
23
+ </div>
23
24
  <% end %>
@@ -3,10 +3,10 @@
3
3
  <div class="col">
4
4
  <h1>Edit <%= @client.name %></h1>
5
5
  </div>
6
- <div>
6
+ </div>
7
7
  <%= render partial: "graphql/dashboard/operation_store/clients/form" %>
8
8
 
9
- <hr class="mt-5"/>
9
+ <hr class="mt-5">
10
10
  <div class="row mt-5">
11
11
  <div class="col">
12
12
  <div class="alert alert-danger">
@@ -33,7 +33,7 @@
33
33
  <td><%= link_to(client.name, graphql_dashboard.edit_operation_store_client_path(name: client.name)) %></td>
34
34
  <td>
35
35
  <%= link_to(graphql_dashboard.operation_store_client_operations_path(client_name: client.name)) do %>
36
- <%= client.operations_count %><% if client.archived_operations_count > 0 %> <span class="muted">(<%=client.archived_operations_count%> archived)</span><% end %>
36
+ <%= client.operations_count %><% if client.archived_operations_count > 0 %> <span class="muted">(<%= client.archived_operations_count %> archived)</span><% end %>
37
37
  <% end %>
38
38
  </td>
39
39
  <td><%= client.created_at %></td>
@@ -3,5 +3,5 @@
3
3
  <div class="col">
4
4
  <h1>New Client</h1>
5
5
  </div>
6
- <div>
6
+ </div>
7
7
  <%= render partial: "graphql/dashboard/operation_store/clients/form" %>
@@ -10,7 +10,7 @@
10
10
  <form method="GET" action="<%= graphql_dashboard.operation_store_index_entries_path %>" style="margin-left: auto; margin-top:-5px;">
11
11
  <div class="input-group">
12
12
  <%= text_field_tag "q", @search_term, class: "form-control", placeholder: "Find types, fields, arguments, or enum values" %>
13
- <input type="submit" value="Search" class="btn btn-outline-primary btn-sm"/>
13
+ <input type="submit" value="Search" class="btn btn-outline-primary btn-sm">
14
14
  </div>
15
15
  </form>
16
16
  </div>
@@ -2,7 +2,7 @@
2
2
  <% if @operation.nil? %>
3
3
  <div class="row">
4
4
  <div class="col">
5
- <p>No stored operation found for <code><%= params[:digest] %></code>
5
+ <p>No stored operation found for <code><%= params[:digest] %></code></p>
6
6
  </div>
7
7
  </div>
8
8
  <% else %>
@@ -9,7 +9,7 @@
9
9
  <div class="col">
10
10
  <p>Last triggered: <%= @topic_last_triggered_at || "none" %></p>
11
11
  <p><%= pluralize(@subscriptions_count, "Subscription") %></p>
12
- <div>
12
+ </div>
13
13
  </div>
14
14
 
15
15
  <div class="row">
@@ -1,7 +1,7 @@
1
1
  <!doctype html>
2
2
  <html lang="en" class="h-100" >
3
3
  <head>
4
- <link rel="icon" type="image/png" href="<%= graphql_dashboard.static_path("icon.png") %>" />
4
+ <link rel="icon" type="image/png" href="<%= graphql_dashboard.static_path("icon.png") %>">
5
5
  <meta charset="utf-8">
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1">
7
7
  <title>GraphQL Dashboard <%= content_for?(:title) ? " · #{content_for(:title)}" : "" %> </title>
@@ -20,7 +20,7 @@
20
20
  <nav class="navbar navbar-expand-lg bg-body-tertiary">
21
21
  <div class="container-fluid">
22
22
  <%= link_to graphql_dashboard.root_path, class: "navbar-brand" do %>
23
- <img id="header-icon" src="<%= graphql_dashboard.static_path("header-icon.png") %>" alt="GraphQL-Ruby" />
23
+ <img id="header-icon" src="<%= graphql_dashboard.static_path("header-icon.png") %>" alt="GraphQL-Ruby">
24
24
  <% end %>
25
25
  <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
26
26
  <span class="navbar-toggler-icon"></span>
@@ -34,7 +34,7 @@ module Graphql
34
34
  class Dashboard < Rails::Engine
35
35
  engine_name "graphql_dashboard"
36
36
  isolate_namespace(Graphql::Dashboard)
37
- routes.draw do
37
+ routes do
38
38
  root "landings#show"
39
39
  resources :statics, only: :show, constraints: { id: /[0-9A-Za-z\-.]+/ }
40
40
 
@@ -76,6 +76,8 @@ module Graphql
76
76
  resources :subscriptions, only: [:show], constraints: { id: /[a-zA-Z0-9\-]+/ }
77
77
  post "/subscriptions/clear_all", to: "subscriptions#clear_all", as: :clear_all
78
78
  end
79
+
80
+ ApplicationController.include(Dashboard.routes.url_helpers)
79
81
  end
80
82
 
81
83
  class ApplicationController < ActionController::Base
@@ -77,21 +77,30 @@ module GraphQL
77
77
  new_query_str || query_str
78
78
  end
79
79
 
80
+ LEADING_REGEX = Regexp.union(" ", *Lexer::Punctuation.constants.map { |const| Lexer::Punctuation.const_get(const) })
81
+
82
+ # Optimized pattern using:
83
+ # - Possessive quantifiers (*+, ++) to prevent backtracking in number patterns
84
+ # - Atomic group (?>...) for IGNORE to prevent backtracking
85
+ # - Single unified number pattern instead of three alternatives
86
+ EFFICIENT_NUMBER_REGEXP = /-?(?:0|[1-9][0-9]*+)(?:\.[0-9]++)?(?:[eE][+-]?[0-9]++)?/
87
+ EFFICIENT_IGNORE_REGEXP = /(?>[, \r\n\t]+|\#[^\n]*$)*/
88
+
89
+ MAYBE_INVALID_NUMBER = /\d[_a-zA-Z]/
90
+
80
91
  INVALID_NUMBER_FOLLOWED_BY_NAME_REGEXP = %r{
81
- (
82
- ((?<num>#{Lexer::INT_REGEXP}(#{Lexer::FLOAT_EXP_REGEXP})?)(?<name>#{Lexer::IDENTIFIER_REGEXP})#{Lexer::IGNORE_REGEXP}:)
83
- |
84
- ((?<num>#{Lexer::INT_REGEXP}#{Lexer::FLOAT_DECIMAL_REGEXP}#{Lexer::FLOAT_EXP_REGEXP})(?<name>#{Lexer::IDENTIFIER_REGEXP})#{Lexer::IGNORE_REGEXP}:)
85
- |
86
- ((?<num>#{Lexer::INT_REGEXP}#{Lexer::FLOAT_DECIMAL_REGEXP})(?<name>#{Lexer::IDENTIFIER_REGEXP})#{Lexer::IGNORE_REGEXP}:)
87
- )}x
92
+ (?<leading>#{LEADING_REGEX})
93
+ (?<num>#{EFFICIENT_NUMBER_REGEXP})
94
+ (?<name>#{Lexer::IDENTIFIER_REGEXP})
95
+ #{EFFICIENT_IGNORE_REGEXP}
96
+ :
97
+ }x
88
98
 
89
99
  def self.add_space_between_numbers_and_names(query_str)
90
- if query_str.match?(INVALID_NUMBER_FOLLOWED_BY_NAME_REGEXP)
91
- query_str.gsub(INVALID_NUMBER_FOLLOWED_BY_NAME_REGEXP, "\\k<num> \\k<name>:")
92
- else
93
- query_str
94
- end
100
+ # Fast check for digit followed by identifier char. If this doesn't match, skip the more expensive regexp entirely.
101
+ return query_str unless query_str.match?(MAYBE_INVALID_NUMBER)
102
+ return query_str unless query_str.match?(INVALID_NUMBER_FOLLOWED_BY_NAME_REGEXP)
103
+ query_str.gsub(INVALID_NUMBER_FOLLOWED_BY_NAME_REGEXP, "\\k<leading>\\k<num> \\k<name>:")
95
104
  end
96
105
  end
97
106
  end
@@ -39,9 +39,14 @@ module GraphQL
39
39
  # @param arg_name [Symbol]
40
40
  # @param type_expr
41
41
  # @param desc [String]
42
+ # @param type [Class, Array<Class>] Input type; positional argument also accepted
43
+ # @param name [Symbol] positional argument also accepted # @param loads [Class, Array<Class>] A GraphQL type to load for the given ID when one is present
44
+ # @param definition_block [Proc] Called with the newly-created {Argument}
45
+ # @param owner [Class] Private, used by GraphQL-Ruby during schema definition
42
46
  # @param required [Boolean, :nullable] if true, this argument is non-null; if false, this argument is nullable. If `:nullable`, then the argument must be provided, though it may be `null`.
43
47
  # @param description [String]
44
48
  # @param default_value [Object]
49
+ # @param loads [Class, Array<Class>] A GraphQL type to load for the given ID when one is present
45
50
  # @param as [Symbol] Override the keyword name when passed to a method
46
51
  # @param prepare [Symbol] A method to call to transform this argument's valuebefore sending it to field resolution
47
52
  # @param camelize [Boolean] if true, the name will be camelized when building the schema
@@ -50,6 +55,8 @@ module GraphQL
50
55
  # @param deprecation_reason [String]
51
56
  # @param validates [Hash, nil] Options for building validators, if any should be applied
52
57
  # @param replace_null_with_default [Boolean] if `true`, incoming values of `null` will be replaced with the configured `default_value`
58
+ # @param comment [String] Private, used by GraphQL-Ruby when parsing GraphQL schema files
59
+ # @param ast_node [GraphQL::Language::Nodes::InputValueDefinition] Private, used by GraphQL-Ruby when parsing schema files
53
60
  def initialize(arg_name = nil, type_expr = nil, desc = nil, required: true, type: nil, name: nil, loads: nil, description: nil, comment: nil, ast_node: nil, default_value: NOT_CONFIGURED, as: nil, from_resolver: false, camelize: true, prepare: nil, owner:, validates: nil, directives: nil, deprecation_reason: nil, replace_null_with_default: false, &definition_block)
54
61
  arg_name ||= name
55
62
  @name = -(camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s)
@@ -109,52 +109,6 @@ module GraphQL
109
109
  end
110
110
  attr_writer :subscription_scope
111
111
 
112
- # Create a field instance from a list of arguments, keyword arguments, and a block.
113
- #
114
- # This method implements prioritization between the `resolver` or `mutation` defaults
115
- # and the local overrides via other keywords.
116
- #
117
- # It also normalizes positional arguments into keywords for {Schema::Field#initialize}.
118
- # @param resolver [Class] A {GraphQL::Schema::Resolver} class to use for field configuration
119
- # @param mutation [Class] A {GraphQL::Schema::Mutation} class to use for field configuration
120
- # @param subscription [Class] A {GraphQL::Schema::Subscription} class to use for field configuration
121
- # @return [GraphQL::Schema:Field] an instance of `self`
122
- # @see {.initialize} for other options
123
- def self.from_options(name = nil, type = nil, desc = nil, comment: nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
124
- if (resolver_class = resolver || mutation || subscription)
125
- # Add a reference to that parent class
126
- kwargs[:resolver_class] = resolver_class
127
- end
128
-
129
- if name
130
- kwargs[:name] = name
131
- end
132
-
133
- if comment
134
- kwargs[:comment] = comment
135
- end
136
-
137
- if !type.nil?
138
- if desc
139
- if kwargs[:description]
140
- raise ArgumentError, "Provide description as a positional argument or `description:` keyword, but not both (#{desc.inspect}, #{kwargs[:description].inspect})"
141
- end
142
-
143
- kwargs[:description] = desc
144
- kwargs[:type] = type
145
- elsif (resolver || mutation) && type.is_a?(String)
146
- # The return type should be copied from the resolver, and the second positional argument is the description
147
- kwargs[:description] = type
148
- else
149
- kwargs[:type] = type
150
- end
151
- if type.is_a?(Class) && type < GraphQL::Schema::Mutation
152
- raise ArgumentError, "Use `field #{name.inspect}, mutation: Mutation, ...` to provide a mutation to this field instead"
153
- end
154
- end
155
- new(**kwargs, &block)
156
- end
157
-
158
112
  # Can be set with `connection: true|false` or inferred from a type name ending in `*Connection`
159
113
  # @return [Boolean] if true, this field will be wrapped with Relay connection behavior
160
114
  def connection?
@@ -255,6 +209,11 @@ module GraphQL
255
209
  # @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
256
210
  # @param validates [Array<Hash>] Configurations for validating this field
257
211
  # @param fallback_value [Object] A fallback value if the method is not defined
212
+ # @param dynamic_introspection [Boolean] (Private, used by GraphQL-Ruby)
213
+ # @param relay_node_field [Boolean] (Private, used by GraphQL-Ruby)
214
+ # @param relay_nodes_field [Boolean] (Private, used by GraphQL-Ruby)
215
+ # @param extras [Array<:ast_node, :parent, :lookahead, :owner, :execution_errors, :graphql_name, :argument_details, Symbol>] Extra arguments to be injected into the resolver for this field
216
+ # @param definition_block [Proc] an additional block for configuring the field. Receive the field as a block param, or, if no block params are defined, then the block is `instance_eval`'d on the new {Field}.
258
217
  def initialize(type: nil, name: nil, owner: nil, null: nil, description: NOT_CONFIGURED, comment: NOT_CONFIGURED, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, connection: nil, max_page_size: NOT_CONFIGURED, default_page_size: NOT_CONFIGURED, scope: nil, introspection: false, camelize: true, trace: nil, complexity: nil, ast_node: nil, extras: EMPTY_ARRAY, extensions: EMPTY_ARRAY, connection_extension: self.class.connection_extension, resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, method_conflict_warning: true, broadcastable: NOT_CONFIGURED, arguments: EMPTY_HASH, directives: EMPTY_HASH, validates: EMPTY_ARRAY, fallback_value: NOT_CONFIGURED, dynamic_introspection: false, &definition_block)
259
218
  if name.nil?
260
219
  raise ArgumentError, "missing first `name` argument or keyword `name:`"
@@ -347,7 +306,7 @@ module GraphQL
347
306
 
348
307
  @extensions = EMPTY_ARRAY
349
308
  @call_after_define = false
350
- set_pagination_extensions(connection_extension: connection_extension)
309
+ set_pagination_extensions(connection_extension: NOT_CONFIGURED.equal?(connection_extension) ? self.class.connection_extension : connection_extension)
351
310
  # Do this last so we have as much context as possible when initializing them:
352
311
  if !extensions.empty?
353
312
  self.extensions(extensions)
@@ -14,29 +14,52 @@ module GraphQL
14
14
  cls.extend(ClassConfigured)
15
15
  end
16
16
 
17
- # @see {GraphQL::Schema::Argument#initialize} for parameters
18
- # @return [GraphQL::Schema::Argument] An instance of {argument_class}, created from `*args`
19
- def argument(*args, **kwargs, &block)
20
- kwargs[:owner] = self
21
- loads = kwargs[:loads]
22
- if loads
23
- name = args[0]
24
- name_as_string = name.to_s
25
-
26
- inferred_arg_name = case name_as_string
17
+ # @param arg_name [Symbol] The underscore-cased name of this argument, `name:` keyword also accepted
18
+ # @param type_expr The GraphQL type of this argument; `type:` keyword also accepted
19
+ # @param desc [String] Argument description, `description:` keyword also accepted
20
+ # @option kwargs [Boolean, :nullable] :required if true, this argument is non-null; if false, this argument is nullable. If `:nullable`, then the argument must be provided, though it may be `null`.
21
+ # @option kwargs [String] :description Positional argument also accepted
22
+ # @option kwargs [Class, Array<Class>] :type Input type; positional argument also accepted
23
+ # @option kwargs [Symbol] :name positional argument also accepted
24
+ # @option kwargs [Object] :default_value
25
+ # @option kwargs [Class, Array<Class>] :loads A GraphQL type to load for the given ID when one is present
26
+ # @option kwargs [Symbol] :as Override the keyword name when passed to a method
27
+ # @option kwargs [Symbol] :prepare A method to call to transform this argument's valuebefore sending it to field resolution
28
+ # @option kwargs [Boolean] :camelize if true, the name will be camelized when building the schema
29
+ # @option kwargs [Boolean] :from_resolver if true, a Resolver class defined this argument
30
+ # @option kwargs [Hash{Class => Hash}] :directives
31
+ # @option kwargs [String] :deprecation_reason
32
+ # @option kwargs [String] :comment Private, used by GraphQL-Ruby when parsing GraphQL schema files
33
+ # @option kwargs [GraphQL::Language::Nodes::InputValueDefinition] :ast_node Private, used by GraphQL-Ruby when parsing schema files
34
+ # @option kwargs [Hash, nil] :validates Options for building validators, if any should be applied
35
+ # @option kwargs [Boolean] :replace_null_with_default if `true`, incoming values of `null` will be replaced with the configured `default_value`
36
+ # @param definition_block [Proc] Called with the newly-created {Argument}
37
+ # @param kwargs [Hash] Keywords for defining an argument. Any keywords not documented here must be handled by your base Argument class.
38
+ # @return [GraphQL::Schema::Argument] An instance of {argument_class} created from these arguments
39
+ def argument(arg_name = nil, type_expr = nil, desc = nil, **kwargs, &definition_block)
40
+ if kwargs[:loads]
41
+ loads_name = arg_name || kwargs[:name]
42
+ loads_name_as_string = loads_name.to_s
43
+
44
+ inferred_arg_name = case loads_name_as_string
27
45
  when /_id$/
28
- name_as_string.sub(/_id$/, "").to_sym
46
+ loads_name_as_string.sub(/_id$/, "").to_sym
29
47
  when /_ids$/
30
- name_as_string.sub(/_ids$/, "")
48
+ loads_name_as_string.sub(/_ids$/, "")
31
49
  .sub(/([^s])$/, "\\1s")
32
50
  .to_sym
33
51
  else
34
- name
52
+ loads_name
35
53
  end
36
54
 
37
55
  kwargs[:as] ||= inferred_arg_name
38
56
  end
39
- arg_defn = self.argument_class.new(*args, **kwargs, &block)
57
+ kwargs[:owner] = self
58
+ arg_defn = self.argument_class.new(
59
+ arg_name, type_expr, desc,
60
+ **kwargs,
61
+ &definition_block
62
+ )
40
63
  add_argument(arg_defn)
41
64
  arg_defn
42
65
  end
@@ -5,11 +5,83 @@ module GraphQL
5
5
  class Member
6
6
  # Shared code for Objects, Interfaces, Mutations, Subscriptions
7
7
  module HasFields
8
+ include EmptyObjects
8
9
  # Add a field to this object or interface with the given definition
9
- # @see {GraphQL::Schema::Field#initialize} for method signature
10
+ # @param name_positional [Symbol] The underscore-cased version of this field name (will be camelized for the GraphQL API); `name:` keyword is also accepted
11
+ # @param type_positional [Class, GraphQL::BaseType, Array] The return type of this field; `type:` keyword is also accepted
12
+ # @param desc_positional [String] Field description; `description:` keyword is also accepted
13
+ # @option kwargs [Symbol] :name The underscore-cased version of this field name (will be camelized for the GraphQL API); positional argument also accepted
14
+ # @option kwargs [Class, GraphQL::BaseType, Array] :type The return type of this field; positional argument is also accepted
15
+ # @option kwargs [Boolean] :null (defaults to `true`) `true` if this field may return `null`, `false` if it is never `null`
16
+ # @option kwargs [String] :description Field description; positional argument also accepted
17
+ # @option kwargs [String] :comment Field comment
18
+ # @option kwargs [String] :deprecation_reason If present, the field is marked "deprecated" with this message
19
+ # @option kwargs [Symbol] :method The method to call on the underlying object to resolve this field (defaults to `name`)
20
+ # @option kwargs [String, Symbol] :hash_key The hash key to lookup on the underlying object (if its a Hash) to resolve this field (defaults to `name` or `name.to_s`)
21
+ # @option kwargs [Array<String, Symbol>] :dig The nested hash keys to lookup on the underlying hash to resolve this field using dig
22
+ # @option kwargs [Symbol] :resolver_method The method on the type to call to resolve this field (defaults to `name`)
23
+ # @option kwargs [Boolean] :connection `true` if this field should get automagic connection behavior; default is to infer by `*Connection` in the return type name
24
+ # @option kwargs [Class] :connection_extension The extension to add, to implement connections. If `nil`, no extension is added.
25
+ # @option kwargs [Integer, nil] :max_page_size For connections, the maximum number of items to return from this field, or `nil` to allow unlimited results.
26
+ # @option kwargs [Integer, nil] :default_page_size For connections, the default number of items to return from this field, or `nil` to return unlimited results.
27
+ # @option kwargs [Boolean] :introspection If true, this field will be marked as `#introspection?` and the name may begin with `__`
28
+ # @option kwargs [{String=>GraphQL::Schema::Argument, Hash}] :arguments Arguments for this field (may be added in the block, also)
29
+ # @option kwargs [Boolean] :camelize If true, the field name will be camelized when building the schema
30
+ # @option kwargs [Numeric] :complexity When provided, set the complexity for this field
31
+ # @option kwargs [Boolean] :scope If true, the return type's `.scope_items` method will be called on the return value
32
+ # @option kwargs [Symbol, String] :subscription_scope A key in `context` which will be used to scope subscription payloads
33
+ # @option kwargs [Array<Class, Hash<Class => Object>>] :extensions Named extensions to apply to this field (see also {#extension})
34
+ # @option kwargs [Hash{Class => Hash}] :directives Directives to apply to this field
35
+ # @option kwargs [Boolean] :trace If true, a {GraphQL::Tracing} tracer will measure this scalar field
36
+ # @option kwargs [Boolean] :broadcastable Whether or not this field can be distributed in subscription broadcasts
37
+ # @option kwargs [Language::Nodes::FieldDefinition, nil] :ast_node If this schema was parsed from definition, this AST node defined the field
38
+ # @option kwargs [Boolean] :method_conflict_warning If false, skip the warning if this field's method conflicts with a built-in method
39
+ # @option kwargs [Array<Hash>] :validates Configurations for validating this field
40
+ # @option kwargs [Object] :fallback_value A fallback value if the method is not defined
41
+ # @option kwargs [Class<GraphQL::Schema::Mutation>] :mutation
42
+ # @option kwargs [Class<GraphQL::Schema::Resolver>] :resolver
43
+ # @option kwargs [Class<GraphQL::Schema::Subscription>] :subscription
44
+ # @option kwargs [Boolean] :dynamic_introspection (Private, used by GraphQL-Ruby)
45
+ # @option kwargs [Boolean] :relay_node_field (Private, used by GraphQL-Ruby)
46
+ # @option kwargs [Boolean] :relay_nodes_field (Private, used by GraphQL-Ruby)
47
+ # @option kwargs [Array<:ast_node, :parent, :lookahead, :owner, :execution_errors, :graphql_name, :argument_details, Symbol>] :extras Extra arguments to be injected into the resolver for this field
48
+ # @param kwargs [Hash] Keywords for defining the field. Any not documented here will be passed to your base field class where they must be handled.
49
+ # @param definition_block [Proc] an additional block for configuring the field. Receive the field as a block param, or, if no block params are defined, then the block is `instance_eval`'d on the new {Field}.
50
+ # @yieldparam field [GraphQL::Schema::Field] The newly-created field instance
51
+ # @yieldreturn [void]
10
52
  # @return [GraphQL::Schema::Field]
11
- def field(*args, **kwargs, &block)
12
- field_defn = field_class.from_options(*args, owner: self, **kwargs, &block)
53
+ def field(name_positional = nil, type_positional = nil, desc_positional = nil, **kwargs, &definition_block)
54
+ resolver = kwargs.delete(:resolver)
55
+ mutation = kwargs.delete(:mutation)
56
+ subscription = kwargs.delete(:subscription)
57
+ if (resolver_class = resolver || mutation || subscription)
58
+ # Add a reference to that parent class
59
+ kwargs[:resolver_class] = resolver_class
60
+ end
61
+
62
+ kwargs[:name] ||= name_positional
63
+ if !type_positional.nil?
64
+ if desc_positional
65
+ if kwargs[:description]
66
+ raise ArgumentError, "Provide description as a positional argument or `description:` keyword, but not both (#{desc_positional.inspect}, #{kwargs[:description].inspect})"
67
+ end
68
+
69
+ kwargs[:description] = desc_positional
70
+ kwargs[:type] = type_positional
71
+ elsif (resolver || mutation) && type_positional.is_a?(String)
72
+ # The return type should be copied from the resolver, and the second positional argument is the description
73
+ kwargs[:description] = type_positional
74
+ else
75
+ kwargs[:type] = type_positional
76
+ end
77
+
78
+ if type_positional.is_a?(Class) && type_positional < GraphQL::Schema::Mutation
79
+ raise ArgumentError, "Use `field #{name_positional.inspect}, mutation: Mutation, ...` to provide a mutation to this field instead"
80
+ end
81
+ end
82
+
83
+ kwargs[:owner] = self
84
+ field_defn = field_class.new(**kwargs, &definition_block)
13
85
  add_field(field_defn)
14
86
  field_defn
15
87
  end
@@ -232,7 +304,7 @@ module GraphQL
232
304
  end
233
305
  end
234
306
 
235
- # @param [GraphQL::Schema::Field]
307
+ # @param field_defn [GraphQL::Schema::Field]
236
308
  # @return [String] A warning to give when this field definition might conflict with a built-in method
237
309
  def conflict_field_name_warning(field_defn)
238
310
  "#{self.graphql_name}'s `field :#{field_defn.original_name}` conflicts with a built-in method, use `resolver_method:` to pick a different resolver method for this field (for example, `resolver_method: :resolve_#{field_defn.resolver_method}` and `def resolve_#{field_defn.resolver_method}`). Or use `method_conflict_warning: false` to suppress this warning."
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.5.16"
3
+ VERSION = "2.5.17"
4
4
  end
data/lib/graphql.rb CHANGED
@@ -126,7 +126,10 @@ This is probably a bug in GraphQL-Ruby, please report this error on GitHub: http
126
126
  autoload :Testing, "graphql/testing"
127
127
  autoload :Current, "graphql/current"
128
128
  if defined?(::Rails::Engine)
129
- autoload :Dashboard, 'graphql/dashboard'
129
+ # This needs to be defined before Rails runs `add_routing_paths`,
130
+ # otherwise GraphQL::Dashboard's routes won't have been gathered for loading
131
+ # when that initializer runs.
132
+ require 'graphql/dashboard'
130
133
  end
131
134
  end
132
135
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.16
4
+ version: 2.5.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-12-10 00:00:00.000000000 Z
10
+ date: 2026-01-21 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: base64