graphql 1.9.17 → 1.11.7

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.

Files changed (230) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +18 -2
  3. data/lib/generators/graphql/install_generator.rb +27 -0
  4. data/lib/generators/graphql/object_generator.rb +52 -8
  5. data/lib/generators/graphql/templates/base_argument.erb +2 -0
  6. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  7. data/lib/generators/graphql/templates/base_field.erb +2 -0
  8. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  9. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  10. data/lib/generators/graphql/templates/base_mutation.erb +2 -0
  11. data/lib/generators/graphql/templates/base_object.erb +2 -0
  12. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  13. data/lib/generators/graphql/templates/base_union.erb +2 -0
  14. data/lib/generators/graphql/templates/enum.erb +2 -0
  15. data/lib/generators/graphql/templates/graphql_controller.erb +14 -10
  16. data/lib/generators/graphql/templates/interface.erb +2 -0
  17. data/lib/generators/graphql/templates/loader.erb +2 -0
  18. data/lib/generators/graphql/templates/mutation.erb +2 -0
  19. data/lib/generators/graphql/templates/mutation_type.erb +2 -0
  20. data/lib/generators/graphql/templates/object.erb +2 -0
  21. data/lib/generators/graphql/templates/query_type.erb +2 -0
  22. data/lib/generators/graphql/templates/scalar.erb +2 -0
  23. data/lib/generators/graphql/templates/schema.erb +10 -0
  24. data/lib/generators/graphql/templates/union.erb +3 -1
  25. data/lib/graphql/analysis/ast/field_usage.rb +1 -1
  26. data/lib/graphql/analysis/ast/query_complexity.rb +178 -67
  27. data/lib/graphql/analysis/ast/visitor.rb +3 -3
  28. data/lib/graphql/analysis/ast.rb +12 -11
  29. data/lib/graphql/argument.rb +10 -38
  30. data/lib/graphql/backtrace/table.rb +10 -2
  31. data/lib/graphql/backtrace/tracer.rb +2 -1
  32. data/lib/graphql/base_type.rb +4 -0
  33. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +2 -2
  34. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +5 -9
  35. data/lib/graphql/define/assign_enum_value.rb +1 -1
  36. data/lib/graphql/define/assign_global_id_field.rb +2 -2
  37. data/lib/graphql/define/assign_object_field.rb +3 -3
  38. data/lib/graphql/define/defined_object_proxy.rb +3 -0
  39. data/lib/graphql/define/instance_definable.rb +18 -108
  40. data/lib/graphql/directive/deprecated_directive.rb +1 -12
  41. data/lib/graphql/directive.rb +8 -1
  42. data/lib/graphql/enum_type.rb +5 -71
  43. data/lib/graphql/execution/directive_checks.rb +2 -2
  44. data/lib/graphql/execution/errors.rb +2 -3
  45. data/lib/graphql/execution/execute.rb +1 -1
  46. data/lib/graphql/execution/instrumentation.rb +1 -1
  47. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  48. data/lib/graphql/execution/interpreter/arguments.rb +51 -0
  49. data/lib/graphql/execution/interpreter/arguments_cache.rb +79 -0
  50. data/lib/graphql/execution/interpreter/handles_raw_value.rb +25 -0
  51. data/lib/graphql/execution/interpreter/runtime.rb +227 -254
  52. data/lib/graphql/execution/interpreter.rb +34 -11
  53. data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
  54. data/lib/graphql/execution/lookahead.rb +39 -114
  55. data/lib/graphql/execution/multiplex.rb +14 -5
  56. data/lib/graphql/field.rb +14 -118
  57. data/lib/graphql/filter.rb +1 -1
  58. data/lib/graphql/function.rb +1 -30
  59. data/lib/graphql/input_object_type.rb +6 -24
  60. data/lib/graphql/integer_decoding_error.rb +17 -0
  61. data/lib/graphql/interface_type.rb +7 -23
  62. data/lib/graphql/internal_representation/scope.rb +2 -2
  63. data/lib/graphql/internal_representation/visit.rb +2 -2
  64. data/lib/graphql/introspection/base_object.rb +2 -5
  65. data/lib/graphql/introspection/directive_type.rb +1 -1
  66. data/lib/graphql/introspection/entry_points.rb +7 -7
  67. data/lib/graphql/introspection/field_type.rb +7 -3
  68. data/lib/graphql/introspection/input_value_type.rb +33 -9
  69. data/lib/graphql/introspection/introspection_query.rb +6 -92
  70. data/lib/graphql/introspection/schema_type.rb +4 -9
  71. data/lib/graphql/introspection/type_type.rb +11 -7
  72. data/lib/graphql/introspection.rb +96 -0
  73. data/lib/graphql/invalid_null_error.rb +18 -0
  74. data/lib/graphql/language/block_string.rb +24 -5
  75. data/lib/graphql/language/definition_slice.rb +21 -10
  76. data/lib/graphql/language/document_from_schema_definition.rb +89 -64
  77. data/lib/graphql/language/lexer.rb +7 -3
  78. data/lib/graphql/language/lexer.rl +7 -3
  79. data/lib/graphql/language/nodes.rb +52 -91
  80. data/lib/graphql/language/parser.rb +719 -717
  81. data/lib/graphql/language/parser.y +104 -98
  82. data/lib/graphql/language/printer.rb +1 -1
  83. data/lib/graphql/language/sanitized_printer.rb +222 -0
  84. data/lib/graphql/language/visitor.rb +2 -2
  85. data/lib/graphql/language.rb +2 -1
  86. data/lib/graphql/name_validator.rb +6 -7
  87. data/lib/graphql/non_null_type.rb +0 -10
  88. data/lib/graphql/object_type.rb +45 -56
  89. data/lib/graphql/pagination/active_record_relation_connection.rb +41 -0
  90. data/lib/graphql/pagination/array_connection.rb +77 -0
  91. data/lib/graphql/pagination/connection.rb +208 -0
  92. data/lib/graphql/pagination/connections.rb +145 -0
  93. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  94. data/lib/graphql/pagination/relation_connection.rb +185 -0
  95. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  96. data/lib/graphql/pagination.rb +6 -0
  97. data/lib/graphql/query/arguments.rb +4 -2
  98. data/lib/graphql/query/context.rb +36 -9
  99. data/lib/graphql/query/fingerprint.rb +26 -0
  100. data/lib/graphql/query/input_validation_result.rb +23 -6
  101. data/lib/graphql/query/literal_input.rb +30 -10
  102. data/lib/graphql/query/null_context.rb +5 -1
  103. data/lib/graphql/query/validation_pipeline.rb +4 -1
  104. data/lib/graphql/query/variable_validation_error.rb +1 -1
  105. data/lib/graphql/query/variables.rb +16 -7
  106. data/lib/graphql/query.rb +64 -15
  107. data/lib/graphql/rake_task/validate.rb +3 -0
  108. data/lib/graphql/rake_task.rb +9 -9
  109. data/lib/graphql/relay/array_connection.rb +10 -12
  110. data/lib/graphql/relay/base_connection.rb +23 -13
  111. data/lib/graphql/relay/connection_type.rb +2 -1
  112. data/lib/graphql/relay/edge_type.rb +1 -0
  113. data/lib/graphql/relay/edges_instrumentation.rb +1 -1
  114. data/lib/graphql/relay/mutation.rb +1 -86
  115. data/lib/graphql/relay/node.rb +2 -2
  116. data/lib/graphql/relay/range_add.rb +14 -5
  117. data/lib/graphql/relay/relation_connection.rb +8 -10
  118. data/lib/graphql/scalar_type.rb +15 -59
  119. data/lib/graphql/schema/argument.rb +113 -11
  120. data/lib/graphql/schema/base_64_encoder.rb +2 -0
  121. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
  122. data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
  123. data/lib/graphql/schema/build_from_definition.rb +212 -190
  124. data/lib/graphql/schema/built_in_types.rb +5 -5
  125. data/lib/graphql/schema/default_type_error.rb +2 -0
  126. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  127. data/lib/graphql/schema/directive/include.rb +1 -1
  128. data/lib/graphql/schema/directive/skip.rb +1 -1
  129. data/lib/graphql/schema/directive.rb +34 -3
  130. data/lib/graphql/schema/enum.rb +52 -4
  131. data/lib/graphql/schema/enum_value.rb +6 -1
  132. data/lib/graphql/schema/field/connection_extension.rb +44 -20
  133. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  134. data/lib/graphql/schema/field.rb +200 -129
  135. data/lib/graphql/schema/find_inherited_value.rb +13 -0
  136. data/lib/graphql/schema/finder.rb +13 -11
  137. data/lib/graphql/schema/input_object.rb +131 -22
  138. data/lib/graphql/schema/interface.rb +26 -8
  139. data/lib/graphql/schema/introspection_system.rb +108 -37
  140. data/lib/graphql/schema/late_bound_type.rb +3 -2
  141. data/lib/graphql/schema/list.rb +47 -0
  142. data/lib/graphql/schema/loader.rb +134 -96
  143. data/lib/graphql/schema/member/base_dsl_methods.rb +29 -12
  144. data/lib/graphql/schema/member/build_type.rb +19 -5
  145. data/lib/graphql/schema/member/cached_graphql_definition.rb +5 -0
  146. data/lib/graphql/schema/member/has_arguments.rb +105 -5
  147. data/lib/graphql/schema/member/has_ast_node.rb +20 -0
  148. data/lib/graphql/schema/member/has_fields.rb +20 -10
  149. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  150. data/lib/graphql/schema/member/type_system_helpers.rb +2 -2
  151. data/lib/graphql/schema/member/validates_input.rb +33 -0
  152. data/lib/graphql/schema/member.rb +6 -0
  153. data/lib/graphql/schema/mutation.rb +5 -1
  154. data/lib/graphql/schema/non_null.rb +30 -0
  155. data/lib/graphql/schema/object.rb +65 -12
  156. data/lib/graphql/schema/possible_types.rb +9 -4
  157. data/lib/graphql/schema/printer.rb +0 -15
  158. data/lib/graphql/schema/relay_classic_mutation.rb +5 -3
  159. data/lib/graphql/schema/resolver/has_payload_type.rb +5 -2
  160. data/lib/graphql/schema/resolver.rb +26 -18
  161. data/lib/graphql/schema/scalar.rb +27 -3
  162. data/lib/graphql/schema/subscription.rb +8 -18
  163. data/lib/graphql/schema/timeout.rb +29 -15
  164. data/lib/graphql/schema/traversal.rb +1 -1
  165. data/lib/graphql/schema/type_expression.rb +21 -13
  166. data/lib/graphql/schema/type_membership.rb +2 -2
  167. data/lib/graphql/schema/union.rb +37 -3
  168. data/lib/graphql/schema/unique_within_type.rb +1 -2
  169. data/lib/graphql/schema/validation.rb +10 -2
  170. data/lib/graphql/schema/warden.rb +115 -29
  171. data/lib/graphql/schema.rb +903 -195
  172. data/lib/graphql/static_validation/all_rules.rb +1 -0
  173. data/lib/graphql/static_validation/base_visitor.rb +10 -6
  174. data/lib/graphql/static_validation/literal_validator.rb +52 -27
  175. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +43 -83
  176. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +17 -5
  177. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +33 -25
  178. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
  179. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
  180. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
  181. data/lib/graphql/static_validation/rules/fields_will_merge.rb +29 -21
  182. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  183. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  184. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  185. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +2 -2
  186. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +4 -5
  187. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
  188. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +5 -6
  189. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  190. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
  191. data/lib/graphql/static_validation/type_stack.rb +2 -2
  192. data/lib/graphql/static_validation/validation_context.rb +1 -1
  193. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  194. data/lib/graphql/static_validation/validator.rb +30 -8
  195. data/lib/graphql/static_validation.rb +1 -0
  196. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +89 -19
  197. data/lib/graphql/subscriptions/broadcast_analyzer.rb +84 -0
  198. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
  199. data/lib/graphql/subscriptions/event.rb +23 -5
  200. data/lib/graphql/subscriptions/instrumentation.rb +10 -5
  201. data/lib/graphql/subscriptions/serialize.rb +22 -4
  202. data/lib/graphql/subscriptions/subscription_root.rb +15 -5
  203. data/lib/graphql/subscriptions.rb +108 -35
  204. data/lib/graphql/tracing/active_support_notifications_tracing.rb +14 -10
  205. data/lib/graphql/tracing/appoptics_tracing.rb +171 -0
  206. data/lib/graphql/tracing/appsignal_tracing.rb +8 -0
  207. data/lib/graphql/tracing/data_dog_tracing.rb +8 -0
  208. data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
  209. data/lib/graphql/tracing/platform_tracing.rb +53 -9
  210. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  211. data/lib/graphql/tracing/prometheus_tracing.rb +8 -0
  212. data/lib/graphql/tracing/scout_tracing.rb +19 -0
  213. data/lib/graphql/tracing/skylight_tracing.rb +8 -0
  214. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  215. data/lib/graphql/tracing.rb +14 -34
  216. data/lib/graphql/types/big_int.rb +1 -1
  217. data/lib/graphql/types/int.rb +9 -2
  218. data/lib/graphql/types/iso_8601_date.rb +3 -3
  219. data/lib/graphql/types/iso_8601_date_time.rb +25 -10
  220. data/lib/graphql/types/relay/base_connection.rb +11 -7
  221. data/lib/graphql/types/relay/base_edge.rb +2 -1
  222. data/lib/graphql/types/string.rb +7 -1
  223. data/lib/graphql/unauthorized_error.rb +1 -1
  224. data/lib/graphql/union_type.rb +13 -28
  225. data/lib/graphql/unresolved_type_error.rb +2 -2
  226. data/lib/graphql/version.rb +1 -1
  227. data/lib/graphql.rb +31 -6
  228. data/readme.md +1 -1
  229. metadata +34 -9
  230. data/lib/graphql/literal_validation_error.rb +0 -6
@@ -23,11 +23,11 @@ module GraphQL
23
23
 
24
24
  # Traverse a node in a rewritten query tree,
25
25
  # visiting the node itself and each of its typed children.
26
- def each_node(node)
26
+ def each_node(node, &block)
27
27
  yield(node)
28
28
  node.typed_children.each do |obj_type, children|
29
29
  children.each do |name, node|
30
- each_node(node) { |n| yield(n) }
30
+ each_node(node, &block)
31
31
  end
32
32
  end
33
33
  end
@@ -2,15 +2,12 @@
2
2
  module GraphQL
3
3
  module Introspection
4
4
  class BaseObject < GraphQL::Schema::Object
5
+ introspection(true)
6
+
5
7
  def self.field(*args, **kwargs, &block)
6
8
  kwargs[:introspection] = true
7
9
  super(*args, **kwargs, &block)
8
10
  end
9
-
10
- def self.inherited(child_class)
11
- child_class.introspection(true)
12
- super
13
- end
14
11
  end
15
12
  end
16
13
  end
@@ -9,7 +9,7 @@ module GraphQL
9
9
  "in ways field arguments will not suffice, such as conditionally including or "\
10
10
  "skipping a field. Directives provide this by describing additional information "\
11
11
  "to the executor."
12
- field :name, String, null: false
12
+ field :name, String, null: false, method: :graphql_name
13
13
  field :description, String, null: true
14
14
  field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false
15
15
  field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false
@@ -10,23 +10,23 @@ module GraphQL
10
10
  def __schema
11
11
  # Apply wrapping manually since this field isn't wrapped by instrumentation
12
12
  schema = @context.query.schema
13
- schema_type = schema.introspection_system.schema_type
14
- schema_type.metadata[:type_class].authorized_new(schema, @context)
13
+ schema_type = schema.introspection_system.types["__Schema"]
14
+ schema_type.type_class.authorized_new(schema, @context)
15
15
  end
16
16
 
17
17
  def __type(name:)
18
18
  return unless context.warden.reachable_type?(name)
19
-
20
19
  type = context.warden.get_type(name)
21
- if type && context.interpreter?
22
- type = type.metadata[:type_class] || raise("Invariant: interpreter requires class-based type for #{name}")
20
+
21
+ if type && context.interpreter? && !type.is_a?(Module)
22
+ type = type.type_class || raise("Invariant: interpreter requires class-based type for #{name}")
23
23
  end
24
24
 
25
25
  # The interpreter provides this wrapping, other execution doesnt, so support both.
26
26
  if type && !context.interpreter?
27
27
  # Apply wrapping manually since this field isn't wrapped by instrumentation
28
- type_type = context.schema.introspection_system.type_type
29
- type = type_type.metadata[:type_class].authorized_new(type, context)
28
+ type_type = context.schema.introspection_system.types["__Type"]
29
+ type = type_type.type_class.authorized_new(type, context)
30
30
  end
31
31
  type
32
32
  end
@@ -7,7 +7,9 @@ module GraphQL
7
7
  "a name, potentially a list of arguments, and a return type."
8
8
  field :name, String, null: false
9
9
  field :description, String, null: true
10
- field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false
10
+ field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
11
+ argument :include_deprecated, Boolean, required: false, default_value: false
12
+ end
11
13
  field :type, GraphQL::Schema::LateBoundType.new("__Type"), null: false
12
14
  field :is_deprecated, Boolean, null: false
13
15
  field :deprecation_reason, String, null: true
@@ -16,8 +18,10 @@ module GraphQL
16
18
  !!@object.deprecation_reason
17
19
  end
18
20
 
19
- def args
20
- @context.warden.arguments(@object)
21
+ def args(include_deprecated:)
22
+ args = @context.warden.arguments(@object)
23
+ args = args.reject(&:deprecation_reason) unless include_deprecated
24
+ args
21
25
  end
22
26
  end
23
27
  end
@@ -10,6 +10,12 @@ module GraphQL
10
10
  field :description, String, null: true
11
11
  field :type, GraphQL::Schema::LateBoundType.new("__Type"), null: false
12
12
  field :default_value, String, "A GraphQL-formatted string representing the default value for this input value.", null: true
13
+ field :is_deprecated, Boolean, null: false
14
+ field :deprecation_reason, String, null: true
15
+
16
+ def is_deprecated
17
+ !!@object.deprecation_reason
18
+ end
13
19
 
14
20
  def default_value
15
21
  if @object.default_value?
@@ -18,20 +24,38 @@ module GraphQL
18
24
  'null'
19
25
  else
20
26
  coerced_default_value = @object.type.coerce_result(value, @context)
21
- if @object.type.unwrap.is_a?(GraphQL::EnumType)
22
- if @object.type.list?
23
- "[#{coerced_default_value.join(", ")}]"
24
- else
25
- coerced_default_value
26
- end
27
- else
28
- GraphQL::Language.serialize(coerced_default_value)
29
- end
27
+ serialize_default_value(coerced_default_value, @object.type)
30
28
  end
31
29
  else
32
30
  nil
33
31
  end
34
32
  end
33
+
34
+
35
+ private
36
+
37
+ # Recursively serialize, taking care not to add quotes to enum values
38
+ def serialize_default_value(value, type)
39
+ if value.nil?
40
+ 'null'
41
+ elsif type.kind.list?
42
+ inner_type = type.of_type
43
+ "[" + value.map { |v| serialize_default_value(v, inner_type) }.join(", ") + "]"
44
+ elsif type.kind.non_null?
45
+ serialize_default_value(value, type.of_type)
46
+ elsif type.kind.enum?
47
+ value
48
+ elsif type.kind.input_object?
49
+ "{" +
50
+ value.map do |k, v|
51
+ arg_defn = type.arguments[k]
52
+ "#{k}: #{serialize_default_value(v, arg_defn.type)}"
53
+ end.join(", ") +
54
+ "}"
55
+ else
56
+ GraphQL::Language.serialize(value)
57
+ end
58
+ end
35
59
  end
36
60
  end
37
61
  end
@@ -1,93 +1,7 @@
1
1
  # frozen_string_literal: true
2
- # The introspection query to end all introspection queries, copied from
3
- # https://github.com/graphql/graphql-js/blob/master/src/utilities/introspectionQuery.js
4
- GraphQL::Introspection::INTROSPECTION_QUERY = "
5
- query IntrospectionQuery {
6
- __schema {
7
- queryType { name }
8
- mutationType { name }
9
- subscriptionType { name }
10
- types {
11
- ...FullType
12
- }
13
- directives {
14
- name
15
- description
16
- locations
17
- args {
18
- ...InputValue
19
- }
20
- }
21
- }
22
- }
23
- fragment FullType on __Type {
24
- kind
25
- name
26
- description
27
- fields(includeDeprecated: true) {
28
- name
29
- description
30
- args {
31
- ...InputValue
32
- }
33
- type {
34
- ...TypeRef
35
- }
36
- isDeprecated
37
- deprecationReason
38
- }
39
- inputFields {
40
- ...InputValue
41
- }
42
- interfaces {
43
- ...TypeRef
44
- }
45
- enumValues(includeDeprecated: true) {
46
- name
47
- description
48
- isDeprecated
49
- deprecationReason
50
- }
51
- possibleTypes {
52
- ...TypeRef
53
- }
54
- }
55
- fragment InputValue on __InputValue {
56
- name
57
- description
58
- type { ...TypeRef }
59
- defaultValue
60
- }
61
- fragment TypeRef on __Type {
62
- kind
63
- name
64
- ofType {
65
- kind
66
- name
67
- ofType {
68
- kind
69
- name
70
- ofType {
71
- kind
72
- name
73
- ofType {
74
- kind
75
- name
76
- ofType {
77
- kind
78
- name
79
- ofType {
80
- kind
81
- name
82
- ofType {
83
- kind
84
- name
85
- }
86
- }
87
- }
88
- }
89
- }
90
- }
91
- }
92
- }
93
- "
2
+
3
+ # This query is used by graphql-client so don't add the includeDeprecated
4
+ # argument for inputFields since the server may not support it. Two stage
5
+ # introspection queries will be required to handle this in clients.
6
+ GraphQL::Introspection::INTROSPECTION_QUERY = GraphQL::Introspection.query
7
+
@@ -9,18 +9,13 @@ module GraphQL
9
9
  "query, mutation, and subscription operations."
10
10
 
11
11
  field :types, [GraphQL::Schema::LateBoundType.new("__Type")], "A list of all types supported by this server.", null: false
12
- field :queryType, GraphQL::Schema::LateBoundType.new("__Type"), "The type that query operations will be rooted at.", null: false
13
- field :mutationType, GraphQL::Schema::LateBoundType.new("__Type"), "If this server supports mutation, the type that mutation operations will be rooted at.", null: true
14
- field :subscriptionType, GraphQL::Schema::LateBoundType.new("__Type"), "If this server support subscription, the type that subscription operations will be rooted at.", null: true
12
+ field :query_type, GraphQL::Schema::LateBoundType.new("__Type"), "The type that query operations will be rooted at.", null: false
13
+ field :mutation_type, GraphQL::Schema::LateBoundType.new("__Type"), "If this server supports mutation, the type that mutation operations will be rooted at.", null: true
14
+ field :subscription_type, GraphQL::Schema::LateBoundType.new("__Type"), "If this server support subscription, the type that subscription operations will be rooted at.", null: true
15
15
  field :directives, [GraphQL::Schema::LateBoundType.new("__Directive")], "A list of all directives supported by this server.", null: false
16
16
 
17
17
  def types
18
- types = @context.warden.reachable_types.sort_by(&:graphql_name)
19
- if context.interpreter?
20
- types.map { |t| t.metadata[:type_class] || raise("Invariant: can't introspect non-class-based type: #{t}") }
21
- else
22
- types
23
- end
18
+ @context.warden.reachable_types.sort_by(&:graphql_name)
24
19
  end
25
20
 
26
21
  def query_type
@@ -22,7 +22,9 @@ module GraphQL
22
22
  field :enum_values, [GraphQL::Schema::LateBoundType.new("__EnumValue")], null: true do
23
23
  argument :include_deprecated, Boolean, required: false, default_value: false
24
24
  end
25
- field :input_fields, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: true
25
+ field :input_fields, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: true do
26
+ argument :include_deprecated, Boolean, required: false, default_value: false
27
+ end
26
28
  field :of_type, GraphQL::Schema::LateBoundType.new("__Type"), null: true
27
29
 
28
30
  def name
@@ -37,7 +39,7 @@ module GraphQL
37
39
  if !@object.kind.enum?
38
40
  nil
39
41
  else
40
- enum_values = @context.warden.enum_values(@object.graphql_definition)
42
+ enum_values = @context.warden.enum_values(@object)
41
43
 
42
44
  if !include_deprecated
43
45
  enum_values = enum_values.select {|f| !f.deprecation_reason }
@@ -49,15 +51,17 @@ module GraphQL
49
51
 
50
52
  def interfaces
51
53
  if @object.kind == GraphQL::TypeKinds::OBJECT
52
- @context.warden.interfaces(@object.graphql_definition)
54
+ @context.warden.interfaces(@object)
53
55
  else
54
56
  nil
55
57
  end
56
58
  end
57
59
 
58
- def input_fields
60
+ def input_fields(include_deprecated:)
59
61
  if @object.kind.input_object?
60
- @context.warden.arguments(@object.graphql_definition)
62
+ args = @context.warden.arguments(@object)
63
+ args = args.reject(&:deprecation_reason) unless include_deprecated
64
+ args
61
65
  else
62
66
  nil
63
67
  end
@@ -65,7 +69,7 @@ module GraphQL
65
69
 
66
70
  def possible_types
67
71
  if @object.kind.abstract?
68
- @context.warden.possible_types(@object.graphql_definition)
72
+ @context.warden.possible_types(@object).sort_by(&:graphql_name)
69
73
  else
70
74
  nil
71
75
  end
@@ -75,7 +79,7 @@ module GraphQL
75
79
  if !@object.kind.fields?
76
80
  nil
77
81
  else
78
- fields = @context.warden.fields(@object.graphql_definition)
82
+ fields = @context.warden.fields(@object)
79
83
  if !include_deprecated
80
84
  fields = fields.select {|f| !f.deprecation_reason }
81
85
  end
@@ -1,6 +1,102 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  module Introspection
4
+ def self.query(include_deprecated_args: false)
5
+ # The introspection query to end all introspection queries, copied from
6
+ # https://github.com/graphql/graphql-js/blob/master/src/utilities/introspectionQuery.js
7
+ <<-QUERY
8
+ query IntrospectionQuery {
9
+ __schema {
10
+ queryType { name }
11
+ mutationType { name }
12
+ subscriptionType { name }
13
+ types {
14
+ ...FullType
15
+ }
16
+ directives {
17
+ name
18
+ description
19
+ locations
20
+ args {
21
+ ...InputValue
22
+ }
23
+ }
24
+ }
25
+ }
26
+ fragment FullType on __Type {
27
+ kind
28
+ name
29
+ description
30
+ fields(includeDeprecated: true) {
31
+ name
32
+ description
33
+ args#{include_deprecated_args ? '(includeDeprecated: true)' : ''} {
34
+ ...InputValue
35
+ }
36
+ type {
37
+ ...TypeRef
38
+ }
39
+ isDeprecated
40
+ deprecationReason
41
+ }
42
+ inputFields#{include_deprecated_args ? '(includeDeprecated: true)' : ''} {
43
+ ...InputValue
44
+ }
45
+ interfaces {
46
+ ...TypeRef
47
+ }
48
+ enumValues(includeDeprecated: true) {
49
+ name
50
+ description
51
+ isDeprecated
52
+ deprecationReason
53
+ }
54
+ possibleTypes {
55
+ ...TypeRef
56
+ }
57
+ }
58
+ fragment InputValue on __InputValue {
59
+ name
60
+ description
61
+ type { ...TypeRef }
62
+ defaultValue
63
+ #{include_deprecated_args ? 'isDeprecated' : ''}
64
+ #{include_deprecated_args ? 'deprecationReason' : ''}
65
+ }
66
+ fragment TypeRef on __Type {
67
+ kind
68
+ name
69
+ ofType {
70
+ kind
71
+ name
72
+ ofType {
73
+ kind
74
+ name
75
+ ofType {
76
+ kind
77
+ name
78
+ ofType {
79
+ kind
80
+ name
81
+ ofType {
82
+ kind
83
+ name
84
+ ofType {
85
+ kind
86
+ name
87
+ ofType {
88
+ kind
89
+ name
90
+ }
91
+ }
92
+ }
93
+ }
94
+ }
95
+ }
96
+ }
97
+ }
98
+ QUERY
99
+ end
4
100
  end
5
101
  end
6
102
 
@@ -28,5 +28,23 @@ module GraphQL
28
28
  def parent_error?
29
29
  false
30
30
  end
31
+
32
+ class << self
33
+ attr_accessor :parent_class
34
+
35
+ def subclass_for(parent_class)
36
+ subclass = Class.new(self)
37
+ subclass.parent_class = parent_class
38
+ subclass
39
+ end
40
+
41
+ def inspect
42
+ if (name.nil? || parent_class.name.nil?) && parent_class.respond_to?(:mutation) && (mutation = parent_class.mutation)
43
+ "#{mutation.inspect}::#{parent_class.graphql_name}::InvalidNullError"
44
+ else
45
+ super
46
+ end
47
+ end
48
+ end
31
49
  end
32
50
  end
@@ -2,10 +2,21 @@
2
2
  module GraphQL
3
3
  module Language
4
4
  module BlockString
5
+ if !String.method_defined?(:match?)
6
+ using GraphQL::StringMatchBackport
7
+ end
8
+
5
9
  # Remove leading and trailing whitespace from a block string.
6
10
  # See "Block Strings" in https://github.com/facebook/graphql/blob/master/spec/Section%202%20--%20Language.md
7
11
  def self.trim_whitespace(str)
8
- lines = str.split("\n")
12
+ # Early return for the most common cases:
13
+ if str == ""
14
+ return ""
15
+ elsif !(has_newline = str.include?("\n")) && !(str.start_with?(" "))
16
+ return str
17
+ end
18
+
19
+ lines = has_newline ? str.split("\n") : [str]
9
20
  common_indent = nil
10
21
 
11
22
  # find the common whitespace
@@ -14,19 +25,27 @@ module GraphQL
14
25
  next
15
26
  end
16
27
  line_length = line.size
17
- line_indent = line[/\A */].size
28
+ line_indent = if line.match?(/\A [^ ]/)
29
+ 2
30
+ elsif line.match?(/\A [^ ]/)
31
+ 4
32
+ elsif line.match?(/\A[^ ]/)
33
+ 0
34
+ else
35
+ line[/\A */].size
36
+ end
18
37
  if line_indent < line_length && (common_indent.nil? || line_indent < common_indent)
19
38
  common_indent = line_indent
20
39
  end
21
40
  end
22
41
 
23
42
  # Remove the common whitespace
24
- if common_indent
43
+ if common_indent && common_indent > 0
25
44
  lines.each_with_index do |line, idx|
26
45
  if idx == 0
27
46
  next
28
47
  else
29
- line[0, common_indent] = ""
48
+ line.slice!(0, common_indent)
30
49
  end
31
50
  end
32
51
  end
@@ -40,7 +59,7 @@ module GraphQL
40
59
  end
41
60
 
42
61
  # Rebuild the string
43
- lines.join("\n")
62
+ lines.size > 1 ? lines.join("\n") : (lines.first || "")
44
63
  end
45
64
 
46
65
  def self.print(str, indent: '')
@@ -7,23 +7,34 @@ module GraphQL
7
7
  def slice(document, name)
8
8
  definitions = {}
9
9
  document.definitions.each { |d| definitions[d.name] = d }
10
- names = find_definition_dependencies(definitions, name)
10
+ names = Set.new
11
+ DependencyVisitor.find_definition_dependencies(definitions, name, names)
11
12
  definitions = document.definitions.select { |d| names.include?(d.name) }
12
13
  Nodes::Document.new(definitions: definitions)
13
14
  end
14
15
 
15
16
  private
16
17
 
17
- def find_definition_dependencies(definitions, name)
18
- names = Set.new([name])
19
- visitor = Visitor.new(definitions[name])
20
- visitor[Nodes::FragmentSpread] << ->(node, parent) {
21
- if fragment = definitions[node.name]
22
- names.merge(find_definition_dependencies(definitions, fragment.name))
18
+ class DependencyVisitor < GraphQL::Language::Visitor
19
+ def initialize(doc, definitions, names)
20
+ @names = names
21
+ @definitions = definitions
22
+ super(doc)
23
+ end
24
+
25
+ def on_fragment_spread(node, parent)
26
+ if fragment = @definitions[node.name]
27
+ self.class.find_definition_dependencies(@definitions, fragment.name, @names)
23
28
  end
24
- }
25
- visitor.visit
26
- names
29
+ super
30
+ end
31
+
32
+ def self.find_definition_dependencies(definitions, name, names)
33
+ names.add(name)
34
+ visitor = self.new(definitions[name], definitions, names)
35
+ visitor.visit
36
+ nil
37
+ end
27
38
  end
28
39
  end
29
40
  end