graphql 1.10.1 → 1.13.0

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 (292) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +18 -2
  3. data/lib/generators/graphql/install_generator.rb +36 -6
  4. data/lib/generators/graphql/loader_generator.rb +1 -0
  5. data/lib/generators/graphql/mutation_generator.rb +2 -1
  6. data/lib/generators/graphql/object_generator.rb +54 -9
  7. data/lib/generators/graphql/relay.rb +63 -0
  8. data/lib/generators/graphql/relay_generator.rb +21 -0
  9. data/lib/generators/graphql/templates/base_argument.erb +2 -0
  10. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  11. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  12. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  13. data/lib/generators/graphql/templates/base_field.erb +2 -0
  14. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  15. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  16. data/lib/generators/graphql/templates/base_mutation.erb +2 -0
  17. data/lib/generators/graphql/templates/base_object.erb +2 -0
  18. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  19. data/lib/generators/graphql/templates/base_union.erb +2 -0
  20. data/lib/generators/graphql/templates/enum.erb +2 -0
  21. data/lib/generators/graphql/templates/graphql_controller.erb +16 -12
  22. data/lib/generators/graphql/templates/interface.erb +2 -0
  23. data/lib/generators/graphql/templates/loader.erb +2 -0
  24. data/lib/generators/graphql/templates/mutation.erb +2 -0
  25. data/lib/generators/graphql/templates/mutation_type.erb +2 -0
  26. data/lib/generators/graphql/templates/node_type.erb +9 -0
  27. data/lib/generators/graphql/templates/object.erb +3 -1
  28. data/lib/generators/graphql/templates/query_type.erb +3 -3
  29. data/lib/generators/graphql/templates/scalar.erb +2 -0
  30. data/lib/generators/graphql/templates/schema.erb +21 -33
  31. data/lib/generators/graphql/templates/union.erb +3 -1
  32. data/lib/generators/graphql/type_generator.rb +1 -1
  33. data/lib/graphql/analysis/analyze_query.rb +7 -0
  34. data/lib/graphql/analysis/ast/field_usage.rb +24 -1
  35. data/lib/graphql/analysis/ast/query_complexity.rb +126 -109
  36. data/lib/graphql/analysis/ast/visitor.rb +13 -5
  37. data/lib/graphql/analysis/ast.rb +11 -2
  38. data/lib/graphql/argument.rb +3 -3
  39. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  40. data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
  41. data/lib/graphql/backtrace/table.rb +34 -3
  42. data/lib/graphql/backtrace/traced_error.rb +0 -1
  43. data/lib/graphql/backtrace/tracer.rb +40 -9
  44. data/lib/graphql/backtrace.rb +28 -19
  45. data/lib/graphql/backwards_compatibility.rb +2 -1
  46. data/lib/graphql/base_type.rb +1 -1
  47. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +2 -2
  48. data/lib/graphql/compatibility/execution_specification.rb +1 -0
  49. data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
  50. data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
  51. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
  52. data/lib/graphql/dataloader/null_dataloader.rb +22 -0
  53. data/lib/graphql/dataloader/request.rb +19 -0
  54. data/lib/graphql/dataloader/request_all.rb +19 -0
  55. data/lib/graphql/dataloader/source.rb +155 -0
  56. data/lib/graphql/dataloader.rb +308 -0
  57. data/lib/graphql/define/assign_global_id_field.rb +2 -2
  58. data/lib/graphql/define/defined_object_proxy.rb +1 -1
  59. data/lib/graphql/define/instance_definable.rb +34 -4
  60. data/lib/graphql/define/type_definer.rb +5 -5
  61. data/lib/graphql/deprecated_dsl.rb +18 -5
  62. data/lib/graphql/deprecation.rb +9 -0
  63. data/lib/graphql/directive.rb +4 -4
  64. data/lib/graphql/enum_type.rb +7 -1
  65. data/lib/graphql/execution/errors.rb +110 -7
  66. data/lib/graphql/execution/execute.rb +8 -1
  67. data/lib/graphql/execution/instrumentation.rb +1 -1
  68. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  69. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  70. data/lib/graphql/execution/interpreter/arguments_cache.rb +103 -0
  71. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  72. data/lib/graphql/execution/interpreter/resolve.rb +37 -25
  73. data/lib/graphql/execution/interpreter/runtime.rb +685 -421
  74. data/lib/graphql/execution/interpreter.rb +42 -13
  75. data/lib/graphql/execution/lazy.rb +5 -1
  76. data/lib/graphql/execution/lookahead.rb +25 -110
  77. data/lib/graphql/execution/multiplex.rb +37 -25
  78. data/lib/graphql/field.rb +5 -1
  79. data/lib/graphql/function.rb +4 -0
  80. data/lib/graphql/input_object_type.rb +6 -0
  81. data/lib/graphql/integer_decoding_error.rb +17 -0
  82. data/lib/graphql/integer_encoding_error.rb +18 -2
  83. data/lib/graphql/interface_type.rb +7 -0
  84. data/lib/graphql/internal_representation/document.rb +2 -2
  85. data/lib/graphql/internal_representation/rewrite.rb +1 -1
  86. data/lib/graphql/internal_representation/scope.rb +2 -2
  87. data/lib/graphql/internal_representation/visit.rb +2 -2
  88. data/lib/graphql/introspection/directive_type.rb +8 -4
  89. data/lib/graphql/introspection/entry_points.rb +2 -2
  90. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  91. data/lib/graphql/introspection/field_type.rb +9 -5
  92. data/lib/graphql/introspection/input_value_type.rb +15 -3
  93. data/lib/graphql/introspection/introspection_query.rb +6 -92
  94. data/lib/graphql/introspection/schema_type.rb +4 -4
  95. data/lib/graphql/introspection/type_type.rb +16 -12
  96. data/lib/graphql/introspection.rb +96 -0
  97. data/lib/graphql/invalid_null_error.rb +18 -0
  98. data/lib/graphql/language/block_string.rb +20 -5
  99. data/lib/graphql/language/cache.rb +37 -0
  100. data/lib/graphql/language/document_from_schema_definition.rb +73 -25
  101. data/lib/graphql/language/lexer.rb +4 -3
  102. data/lib/graphql/language/lexer.rl +3 -3
  103. data/lib/graphql/language/nodes.rb +51 -89
  104. data/lib/graphql/language/parser.rb +552 -530
  105. data/lib/graphql/language/parser.y +114 -99
  106. data/lib/graphql/language/printer.rb +7 -2
  107. data/lib/graphql/language/sanitized_printer.rb +222 -0
  108. data/lib/graphql/language/token.rb +0 -4
  109. data/lib/graphql/language/visitor.rb +2 -2
  110. data/lib/graphql/language.rb +2 -0
  111. data/lib/graphql/name_validator.rb +2 -7
  112. data/lib/graphql/object_type.rb +44 -35
  113. data/lib/graphql/pagination/active_record_relation_connection.rb +14 -1
  114. data/lib/graphql/pagination/array_connection.rb +2 -2
  115. data/lib/graphql/pagination/connection.rb +75 -20
  116. data/lib/graphql/pagination/connections.rb +83 -31
  117. data/lib/graphql/pagination/relation_connection.rb +34 -14
  118. data/lib/graphql/parse_error.rb +0 -1
  119. data/lib/graphql/query/arguments.rb +4 -3
  120. data/lib/graphql/query/arguments_cache.rb +1 -2
  121. data/lib/graphql/query/context.rb +42 -7
  122. data/lib/graphql/query/executor.rb +0 -1
  123. data/lib/graphql/query/fingerprint.rb +26 -0
  124. data/lib/graphql/query/input_validation_result.rb +23 -6
  125. data/lib/graphql/query/literal_input.rb +1 -1
  126. data/lib/graphql/query/null_context.rb +24 -8
  127. data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
  128. data/lib/graphql/query/serial_execution.rb +1 -0
  129. data/lib/graphql/query/validation_pipeline.rb +5 -2
  130. data/lib/graphql/query/variable_validation_error.rb +1 -1
  131. data/lib/graphql/query/variables.rb +14 -4
  132. data/lib/graphql/query.rb +68 -13
  133. data/lib/graphql/railtie.rb +9 -1
  134. data/lib/graphql/rake_task.rb +12 -9
  135. data/lib/graphql/relay/array_connection.rb +10 -12
  136. data/lib/graphql/relay/base_connection.rb +26 -13
  137. data/lib/graphql/relay/connection_instrumentation.rb +4 -4
  138. data/lib/graphql/relay/connection_type.rb +1 -1
  139. data/lib/graphql/relay/edges_instrumentation.rb +0 -1
  140. data/lib/graphql/relay/mutation.rb +1 -0
  141. data/lib/graphql/relay/node.rb +3 -0
  142. data/lib/graphql/relay/range_add.rb +23 -9
  143. data/lib/graphql/relay/relation_connection.rb +8 -10
  144. data/lib/graphql/relay/type_extensions.rb +2 -0
  145. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  146. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  147. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  148. data/lib/graphql/rubocop.rb +4 -0
  149. data/lib/graphql/scalar_type.rb +16 -1
  150. data/lib/graphql/schema/addition.rb +247 -0
  151. data/lib/graphql/schema/argument.rb +210 -12
  152. data/lib/graphql/schema/base_64_encoder.rb +2 -0
  153. data/lib/graphql/schema/build_from_definition/resolve_map.rb +3 -1
  154. data/lib/graphql/schema/build_from_definition.rb +213 -86
  155. data/lib/graphql/schema/default_type_error.rb +2 -0
  156. data/lib/graphql/schema/directive/deprecated.rb +1 -1
  157. data/lib/graphql/schema/directive/feature.rb +1 -1
  158. data/lib/graphql/schema/directive/flagged.rb +57 -0
  159. data/lib/graphql/schema/directive/include.rb +1 -1
  160. data/lib/graphql/schema/directive/skip.rb +1 -1
  161. data/lib/graphql/schema/directive/transform.rb +14 -2
  162. data/lib/graphql/schema/directive.rb +78 -2
  163. data/lib/graphql/schema/enum.rb +80 -9
  164. data/lib/graphql/schema/enum_value.rb +17 -6
  165. data/lib/graphql/schema/field/connection_extension.rb +46 -30
  166. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  167. data/lib/graphql/schema/field.rb +285 -133
  168. data/lib/graphql/schema/find_inherited_value.rb +4 -1
  169. data/lib/graphql/schema/finder.rb +5 -5
  170. data/lib/graphql/schema/input_object.rb +97 -89
  171. data/lib/graphql/schema/interface.rb +24 -19
  172. data/lib/graphql/schema/late_bound_type.rb +2 -2
  173. data/lib/graphql/schema/list.rb +7 -1
  174. data/lib/graphql/schema/loader.rb +137 -103
  175. data/lib/graphql/schema/member/accepts_definition.rb +8 -1
  176. data/lib/graphql/schema/member/base_dsl_methods.rb +15 -19
  177. data/lib/graphql/schema/member/build_type.rb +14 -7
  178. data/lib/graphql/schema/member/has_arguments.rb +205 -12
  179. data/lib/graphql/schema/member/has_ast_node.rb +4 -1
  180. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  181. data/lib/graphql/schema/member/has_directives.rb +98 -0
  182. data/lib/graphql/schema/member/has_fields.rb +95 -30
  183. data/lib/graphql/schema/member/has_interfaces.rb +90 -0
  184. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  185. data/lib/graphql/schema/member/has_validators.rb +31 -0
  186. data/lib/graphql/schema/member/instrumentation.rb +0 -1
  187. data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
  188. data/lib/graphql/schema/member.rb +6 -0
  189. data/lib/graphql/schema/middleware_chain.rb +1 -1
  190. data/lib/graphql/schema/mutation.rb +4 -0
  191. data/lib/graphql/schema/non_null.rb +5 -0
  192. data/lib/graphql/schema/object.rb +47 -46
  193. data/lib/graphql/schema/possible_types.rb +9 -4
  194. data/lib/graphql/schema/printer.rb +16 -34
  195. data/lib/graphql/schema/relay_classic_mutation.rb +32 -4
  196. data/lib/graphql/schema/resolver/has_payload_type.rb +34 -4
  197. data/lib/graphql/schema/resolver.rb +123 -63
  198. data/lib/graphql/schema/scalar.rb +11 -1
  199. data/lib/graphql/schema/subscription.rb +57 -21
  200. data/lib/graphql/schema/timeout.rb +29 -15
  201. data/lib/graphql/schema/timeout_middleware.rb +3 -1
  202. data/lib/graphql/schema/type_expression.rb +1 -1
  203. data/lib/graphql/schema/type_membership.rb +18 -4
  204. data/lib/graphql/schema/union.rb +41 -1
  205. data/lib/graphql/schema/unique_within_type.rb +1 -2
  206. data/lib/graphql/schema/validation.rb +12 -2
  207. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  208. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  209. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  210. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  211. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  212. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  213. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  214. data/lib/graphql/schema/validator/required_validator.rb +68 -0
  215. data/lib/graphql/schema/validator.rb +174 -0
  216. data/lib/graphql/schema/warden.rb +153 -28
  217. data/lib/graphql/schema.rb +364 -330
  218. data/lib/graphql/static_validation/all_rules.rb +1 -0
  219. data/lib/graphql/static_validation/base_visitor.rb +8 -5
  220. data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
  221. data/lib/graphql/static_validation/error.rb +3 -1
  222. data/lib/graphql/static_validation/literal_validator.rb +51 -26
  223. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +44 -87
  224. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +22 -6
  225. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +28 -22
  226. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  227. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
  228. data/lib/graphql/static_validation/rules/fields_will_merge.rb +79 -43
  229. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  230. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  231. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  232. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  233. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -1
  234. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +6 -7
  235. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +9 -10
  236. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +8 -8
  237. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +4 -2
  238. data/lib/graphql/static_validation/validation_context.rb +9 -3
  239. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  240. data/lib/graphql/static_validation/validator.rb +42 -8
  241. data/lib/graphql/static_validation.rb +1 -0
  242. data/lib/graphql/string_encoding_error.rb +13 -3
  243. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +118 -19
  244. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  245. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
  246. data/lib/graphql/subscriptions/event.rb +81 -30
  247. data/lib/graphql/subscriptions/instrumentation.rb +0 -1
  248. data/lib/graphql/subscriptions/serialize.rb +33 -6
  249. data/lib/graphql/subscriptions/subscription_root.rb +15 -4
  250. data/lib/graphql/subscriptions.rb +88 -45
  251. data/lib/graphql/tracing/active_support_notifications_tracing.rb +2 -1
  252. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  253. data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
  254. data/lib/graphql/tracing/new_relic_tracing.rb +1 -12
  255. data/lib/graphql/tracing/platform_tracing.rb +43 -17
  256. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  257. data/lib/graphql/tracing/scout_tracing.rb +11 -0
  258. data/lib/graphql/tracing/skylight_tracing.rb +1 -1
  259. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  260. data/lib/graphql/tracing.rb +9 -33
  261. data/lib/graphql/types/big_int.rb +5 -1
  262. data/lib/graphql/types/int.rb +10 -3
  263. data/lib/graphql/types/iso_8601_date.rb +3 -3
  264. data/lib/graphql/types/iso_8601_date_time.rb +25 -10
  265. data/lib/graphql/types/relay/base_connection.rb +6 -90
  266. data/lib/graphql/types/relay/base_edge.rb +2 -34
  267. data/lib/graphql/types/relay/connection_behaviors.rb +156 -0
  268. data/lib/graphql/types/relay/default_relay.rb +27 -0
  269. data/lib/graphql/types/relay/edge_behaviors.rb +53 -0
  270. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  271. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  272. data/lib/graphql/types/relay/node.rb +2 -4
  273. data/lib/graphql/types/relay/node_behaviors.rb +15 -0
  274. data/lib/graphql/types/relay/node_field.rb +2 -20
  275. data/lib/graphql/types/relay/nodes_field.rb +2 -20
  276. data/lib/graphql/types/relay/page_info.rb +2 -14
  277. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  278. data/lib/graphql/types/relay.rb +11 -3
  279. data/lib/graphql/types/string.rb +8 -2
  280. data/lib/graphql/unauthorized_error.rb +2 -2
  281. data/lib/graphql/union_type.rb +2 -0
  282. data/lib/graphql/upgrader/member.rb +1 -0
  283. data/lib/graphql/upgrader/schema.rb +1 -0
  284. data/lib/graphql/version.rb +1 -1
  285. data/lib/graphql.rb +65 -31
  286. data/readme.md +3 -6
  287. metadata +77 -112
  288. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  289. data/lib/graphql/literal_validation_error.rb +0 -6
  290. data/lib/graphql/types/relay/base_field.rb +0 -22
  291. data/lib/graphql/types/relay/base_interface.rb +0 -29
  292. data/lib/graphql/types/relay/base_object.rb +0 -26
@@ -6,18 +6,22 @@ module GraphQL
6
6
  description "Object and Interface types are described by a list of Fields, each of which has "\
7
7
  "a name, potentially a list of arguments, and a return type."
8
8
  field :name, String, null: false
9
- field :description, String, null: true
10
- field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false
9
+ field :description, String
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
- field :deprecation_reason, String, null: true
15
+ field :deprecation_reason, String
14
16
 
15
17
  def is_deprecated
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
@@ -7,9 +7,15 @@ module GraphQL
7
7
  "InputObject are represented as Input Values which describe their type and "\
8
8
  "optionally a default value."
9
9
  field :name, String, null: false
10
- field :description, String, null: true
10
+ field :description, String
11
11
  field :type, GraphQL::Schema::LateBoundType.new("__Type"), null: false
12
- field :default_value, String, "A GraphQL-formatted string representing the default value for this input value.", null: true
12
+ field :default_value, String, "A GraphQL-formatted string representing the default value for this input value."
13
+ field :is_deprecated, Boolean, null: false
14
+ field :deprecation_reason, String
15
+
16
+ def is_deprecated
17
+ !!@object.deprecation_reason
18
+ end
13
19
 
14
20
  def default_value
15
21
  if @object.default_value?
@@ -17,6 +23,12 @@ module GraphQL
17
23
  if value.nil?
18
24
  'null'
19
25
  else
26
+ if (@object.type.kind.list? || (@object.type.kind.non_null? && @object.type.of_type.kind.list?)) && !value.respond_to?(:map)
27
+ # This is a bit odd -- we expect the default value to be an application-style value, so we use coerce result below.
28
+ # But coerce_result doesn't wrap single-item lists, which are valid inputs to list types.
29
+ # So, apply that wrapper here if needed.
30
+ value = [value]
31
+ end
20
32
  coerced_default_value = @object.type.coerce_result(value, @context)
21
33
  serialize_default_value(coerced_default_value, @object.type)
22
34
  end
@@ -42,7 +54,7 @@ module GraphQL
42
54
  elsif type.kind.input_object?
43
55
  "{" +
44
56
  value.map do |k, v|
45
- arg_defn = type.arguments[k]
57
+ arg_defn = type.get_argument(k, context)
46
58
  "#{k}: #{serialize_default_value(v, arg_defn.type)}"
47
59
  end.join(", ") +
48
60
  "}"
@@ -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,9 +9,9 @@ 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."
14
+ field :subscription_type, GraphQL::Schema::LateBoundType.new("__Type"), "If this server support subscription, the type that subscription operations will be rooted at."
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
@@ -31,7 +31,7 @@ module GraphQL
31
31
  end
32
32
 
33
33
  def directives
34
- context.schema.directives.values
34
+ @context.warden.directives
35
35
  end
36
36
 
37
37
  private
@@ -12,18 +12,20 @@ module GraphQL
12
12
  "possible at runtime. List and NonNull types compose other types."
13
13
 
14
14
  field :kind, GraphQL::Schema::LateBoundType.new("__TypeKind"), null: false
15
- field :name, String, null: true
16
- field :description, String, null: true
17
- field :fields, [GraphQL::Schema::LateBoundType.new("__Field")], null: true do
15
+ field :name, String
16
+ field :description, String
17
+ field :fields, [GraphQL::Schema::LateBoundType.new("__Field")] do
18
18
  argument :include_deprecated, Boolean, required: false, default_value: false
19
19
  end
20
- field :interfaces, [GraphQL::Schema::LateBoundType.new("__Type")], null: true
21
- field :possible_types, [GraphQL::Schema::LateBoundType.new("__Type")], null: true
22
- field :enum_values, [GraphQL::Schema::LateBoundType.new("__EnumValue")], null: true do
20
+ field :interfaces, [GraphQL::Schema::LateBoundType.new("__Type")]
21
+ field :possible_types, [GraphQL::Schema::LateBoundType.new("__Type")]
22
+ field :enum_values, [GraphQL::Schema::LateBoundType.new("__EnumValue")] 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
26
- field :of_type, GraphQL::Schema::LateBoundType.new("__Type"), null: true
25
+ field :input_fields, [GraphQL::Schema::LateBoundType.new("__InputValue")] do
26
+ argument :include_deprecated, Boolean, required: false, default_value: false
27
+ end
28
+ field :of_type, GraphQL::Schema::LateBoundType.new("__Type")
27
29
 
28
30
  def name
29
31
  object.graphql_name
@@ -48,16 +50,18 @@ module GraphQL
48
50
  end
49
51
 
50
52
  def interfaces
51
- if @object.kind == GraphQL::TypeKinds::OBJECT
52
- @context.warden.interfaces(@object)
53
+ if @object.kind.object? || @object.kind.interface?
54
+ @context.warden.interfaces(@object).sort_by(&:graphql_name)
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)
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
@@ -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#{include_deprecated_args ? '(includeDeprecated: true)' : ''} {
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
@@ -5,7 +5,14 @@ module GraphQL
5
5
  # Remove leading and trailing whitespace from a block string.
6
6
  # See "Block Strings" in https://github.com/facebook/graphql/blob/master/spec/Section%202%20--%20Language.md
7
7
  def self.trim_whitespace(str)
8
- lines = str.split("\n")
8
+ # Early return for the most common cases:
9
+ if str == ""
10
+ return ""
11
+ elsif !(has_newline = str.include?("\n")) && !(str.start_with?(" "))
12
+ return str
13
+ end
14
+
15
+ lines = has_newline ? str.split("\n") : [str]
9
16
  common_indent = nil
10
17
 
11
18
  # find the common whitespace
@@ -14,19 +21,27 @@ module GraphQL
14
21
  next
15
22
  end
16
23
  line_length = line.size
17
- line_indent = line[/\A */].size
24
+ line_indent = if line.match?(/\A [^ ]/)
25
+ 2
26
+ elsif line.match?(/\A [^ ]/)
27
+ 4
28
+ elsif line.match?(/\A[^ ]/)
29
+ 0
30
+ else
31
+ line[/\A */].size
32
+ end
18
33
  if line_indent < line_length && (common_indent.nil? || line_indent < common_indent)
19
34
  common_indent = line_indent
20
35
  end
21
36
  end
22
37
 
23
38
  # Remove the common whitespace
24
- if common_indent
39
+ if common_indent && common_indent > 0
25
40
  lines.each_with_index do |line, idx|
26
41
  if idx == 0
27
42
  next
28
43
  else
29
- line[0, common_indent] = ""
44
+ line.slice!(0, common_indent)
30
45
  end
31
46
  end
32
47
  end
@@ -40,7 +55,7 @@ module GraphQL
40
55
  end
41
56
 
42
57
  # Rebuild the string
43
- lines.join("\n")
58
+ lines.size > 1 ? lines.join("\n") : (lines.first || "")
44
59
  end
45
60
 
46
61
  def self.print(str, indent: '')
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql/version'
4
+ require 'digest/sha2'
5
+
6
+ module GraphQL
7
+ module Language
8
+ class Cache
9
+ def initialize(path)
10
+ @path = path
11
+ end
12
+
13
+ DIGEST = Digest::SHA256.new << GraphQL::VERSION
14
+ def fetch(filename)
15
+ hash = DIGEST.dup << filename
16
+ begin
17
+ hash << File.mtime(filename).to_i.to_s
18
+ rescue SystemCallError
19
+ return yield
20
+ end
21
+ cache_path = @path.join(hash.to_s)
22
+
23
+ if cache_path.exist?
24
+ Marshal.load(cache_path.read)
25
+ else
26
+ payload = yield
27
+ tmp_path = "#{cache_path}.#{rand}"
28
+
29
+ @path.mkpath
30
+ File.binwrite(tmp_path, Marshal.dump(payload))
31
+ File.rename(tmp_path, cache_path.to_s)
32
+ payload
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -34,6 +34,7 @@ module GraphQL
34
34
  schema: @schema,
35
35
  context: schema_context,
36
36
  )
37
+ schema_context.warden = @warden
37
38
  end
38
39
 
39
40
  def document
@@ -49,7 +50,9 @@ module GraphQL
49
50
  subscription: (s = warden.root_type_for_operation("subscription")) && s.graphql_name,
50
51
  # This only supports directives from parsing,
51
52
  # use a custom printer to add to this list.
52
- directives: @schema.ast_node ? @schema.ast_node.directives : [],
53
+ #
54
+ # `@schema.directives` is covered by `build_definition_nodes`
55
+ directives: ast_directives(@schema),
53
56
  )
54
57
  end
55
58
 
@@ -59,40 +62,36 @@ module GraphQL
59
62
  interfaces: warden.interfaces(object_type).sort_by(&:graphql_name).map { |iface| build_type_name_node(iface) },
60
63
  fields: build_field_nodes(warden.fields(object_type)),
61
64
  description: object_type.description,
65
+ directives: directives(object_type),
62
66
  )
63
67
  end
64
68
 
65
69
  def build_field_node(field)
66
- field_node = GraphQL::Language::Nodes::FieldDefinition.new(
70
+ GraphQL::Language::Nodes::FieldDefinition.new(
67
71
  name: field.graphql_name,
68
72
  arguments: build_argument_nodes(warden.arguments(field)),
69
73
  type: build_type_name_node(field.type),
70
74
  description: field.description,
75
+ directives: directives(field),
71
76
  )
72
-
73
- if field.deprecation_reason
74
- field_node = field_node.merge_directive(
75
- name: GraphQL::Directive::DeprecatedDirective.graphql_name,
76
- arguments: [GraphQL::Language::Nodes::Argument.new(name: "reason", value: field.deprecation_reason)]
77
- )
78
- end
79
-
80
- field_node
81
77
  end
82
78
 
83
79
  def build_union_type_node(union_type)
84
80
  GraphQL::Language::Nodes::UnionTypeDefinition.new(
85
81
  name: union_type.graphql_name,
86
82
  description: union_type.description,
87
- types: warden.possible_types(union_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) }
83
+ types: warden.possible_types(union_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
84
+ directives: directives(union_type),
88
85
  )
89
86
  end
90
87
 
91
88
  def build_interface_type_node(interface_type)
92
89
  GraphQL::Language::Nodes::InterfaceTypeDefinition.new(
93
90
  name: interface_type.graphql_name,
91
+ interfaces: warden.interfaces(interface_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
94
92
  description: interface_type.description,
95
- fields: build_field_nodes(warden.fields(interface_type))
93
+ fields: build_field_nodes(warden.fields(interface_type)),
94
+ directives: directives(interface_type),
96
95
  )
97
96
  end
98
97
 
@@ -103,29 +102,23 @@ module GraphQL
103
102
  build_enum_value_node(enum_value)
104
103
  end,
105
104
  description: enum_type.description,
105
+ directives: directives(enum_type),
106
106
  )
107
107
  end
108
108
 
109
109
  def build_enum_value_node(enum_value)
110
- enum_value_node = GraphQL::Language::Nodes::EnumValueDefinition.new(
110
+ GraphQL::Language::Nodes::EnumValueDefinition.new(
111
111
  name: enum_value.graphql_name,
112
112
  description: enum_value.description,
113
+ directives: directives(enum_value),
113
114
  )
114
-
115
- if enum_value.deprecation_reason
116
- enum_value_node = enum_value_node.merge_directive(
117
- name: GraphQL::Directive::DeprecatedDirective.graphql_name,
118
- arguments: [GraphQL::Language::Nodes::Argument.new(name: "reason", value: enum_value.deprecation_reason)]
119
- )
120
- end
121
-
122
- enum_value_node
123
115
  end
124
116
 
125
117
  def build_scalar_type_node(scalar_type)
126
118
  GraphQL::Language::Nodes::ScalarTypeDefinition.new(
127
119
  name: scalar_type.graphql_name,
128
120
  description: scalar_type.description,
121
+ directives: directives(scalar_type),
129
122
  )
130
123
  end
131
124
 
@@ -141,6 +134,7 @@ module GraphQL
141
134
  description: argument.description,
142
135
  type: build_type_name_node(argument.type),
143
136
  default_value: default_value,
137
+ directives: directives(argument),
144
138
  )
145
139
 
146
140
  argument_node
@@ -151,6 +145,7 @@ module GraphQL
151
145
  name: input_object.graphql_name,
152
146
  fields: build_argument_nodes(warden.arguments(input_object)),
153
147
  description: input_object.description,
148
+ directives: directives(input_object),
154
149
  )
155
150
  end
156
151
 
@@ -164,7 +159,7 @@ module GraphQL
164
159
  end
165
160
 
166
161
  def build_directive_location_nodes(locations)
167
- locations.map { |location| build_directive_location_node(location) }
162
+ locations.sort.map { |location| build_directive_location_node(location) }
168
163
  end
169
164
 
170
165
  def build_directive_location_node(location)
@@ -201,7 +196,7 @@ module GraphQL
201
196
  when "INPUT_OBJECT"
202
197
  GraphQL::Language::Nodes::InputObject.new(
203
198
  arguments: default_value.to_h.map do |arg_name, arg_value|
204
- arg_type = type.arguments.fetch(arg_name.to_s).type
199
+ arg_type = @warden.arguments(type).find { |a| a.graphql_name == arg_name.to_s }.type
205
200
  GraphQL::Language::Nodes::Argument.new(
206
201
  name: arg_name.to_s,
207
202
  value: build_default_value(arg_value, arg_type)
@@ -292,6 +287,59 @@ module GraphQL
292
287
  (schema.subscription.nil? || schema.subscription.graphql_name == 'Subscription')
293
288
  end
294
289
 
290
+ def directives(member)
291
+ definition_directives(member)
292
+ end
293
+
294
+ def definition_directives(member)
295
+ dirs = if !member.respond_to?(:directives) || member.directives.empty?
296
+ []
297
+ else
298
+ member.directives.map do |dir|
299
+ args = []
300
+ dir.arguments.argument_values.each_value do |arg_value| # rubocop:disable Development/ContextIsPassedCop -- directive instance method
301
+ arg_defn = arg_value.definition
302
+ if arg_defn.default_value? && arg_value.value == arg_defn.default_value
303
+ next
304
+ else
305
+ value_node = build_default_value(arg_value.value, arg_value.definition.type)
306
+ args << GraphQL::Language::Nodes::Argument.new(
307
+ name: arg_value.definition.name,
308
+ value: value_node,
309
+ )
310
+ end
311
+ end
312
+ GraphQL::Language::Nodes::Directive.new(
313
+ name: dir.class.graphql_name,
314
+ arguments: args
315
+ )
316
+ end
317
+ end
318
+
319
+ # This is just for printing legacy `.define { ... }` schemas, where `deprecation_reason` isn't added to `.directives`.
320
+ if !member.respond_to?(:directives) && member.respond_to?(:deprecation_reason) && (reason = member.deprecation_reason)
321
+ arguments = []
322
+
323
+ if reason != GraphQL::Schema::Directive::DEFAULT_DEPRECATION_REASON
324
+ arguments << GraphQL::Language::Nodes::Argument.new(
325
+ name: "reason",
326
+ value: reason
327
+ )
328
+ end
329
+
330
+ dirs << GraphQL::Language::Nodes::Directive.new(
331
+ name: GraphQL::Directive::DeprecatedDirective.graphql_name,
332
+ arguments: arguments
333
+ )
334
+ end
335
+
336
+ dirs
337
+ end
338
+
339
+ def ast_directives(member)
340
+ member.ast_node ? member.ast_node.directives : []
341
+ end
342
+
295
343
  attr_reader :schema, :warden, :always_include_schema,
296
344
  :include_introspection_types, :include_built_in_directives, :include_built_in_scalars
297
345
  end
@@ -3,6 +3,7 @@
3
3
  module GraphQL
4
4
  module Language
5
5
  module Lexer
6
+
6
7
  def self.tokenize(query_string)
7
8
  run_lexer(query_string)
8
9
  end
@@ -163,7 +164,7 @@ end
163
164
  self.graphql_lexer_en_main = 23;
164
165
 
165
166
  def self.run_lexer(query_string)
166
- data = query_string.unpack("c*")
167
+ data = query_string.unpack(PACK_DIRECTIVE)
167
168
  eof = data.length
168
169
 
169
170
  # Since `Lexer` is a module, store all lexer state
@@ -1421,13 +1422,13 @@ def self.emit_string(ts, te, meta, block:)
1421
1422
  quotes_length = block ? 3 : 1
1422
1423
  value = meta[:data][ts + quotes_length, te - ts - 2 * quotes_length].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING) || ''
1423
1424
  line_incr = 0
1424
- if block && !value.length.zero?
1425
+ if block && !value.empty?
1425
1426
  line_incr = value.count("\n")
1426
1427
  value = GraphQL::Language::BlockString.trim_whitespace(value)
1427
1428
  end
1428
1429
  # TODO: replace with `String#match?` when we support only Ruby 2.4+
1429
1430
  # (It's faster: https://bugs.ruby-lang.org/issues/8110)
1430
- if !value.valid_encoding? || value !~ VALID_STRING
1431
+ if !value.valid_encoding? || !value.match?(VALID_STRING)
1431
1432
  meta[:tokens] << token = GraphQL::Language::Token.new(
1432
1433
  :BAD_UNICODE_ESCAPE,
1433
1434
  value,