graphql 1.11.6 → 1.13.19

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 (293) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +3 -8
  3. data/lib/generators/graphql/enum_generator.rb +4 -10
  4. data/lib/generators/graphql/field_extractor.rb +31 -0
  5. data/lib/generators/graphql/input_generator.rb +50 -0
  6. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  7. data/lib/generators/graphql/install_generator.rb +17 -7
  8. data/lib/generators/graphql/interface_generator.rb +7 -7
  9. data/lib/generators/graphql/loader_generator.rb +1 -0
  10. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  11. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  12. data/lib/generators/graphql/mutation_generator.rb +6 -30
  13. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  14. data/lib/generators/graphql/object_generator.rb +12 -38
  15. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  16. data/lib/generators/graphql/relay.rb +63 -0
  17. data/lib/generators/graphql/relay_generator.rb +21 -0
  18. data/lib/generators/graphql/scalar_generator.rb +4 -2
  19. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  20. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  21. data/lib/generators/graphql/templates/enum.erb +5 -1
  22. data/lib/generators/graphql/templates/graphql_controller.erb +2 -2
  23. data/lib/generators/graphql/templates/input.erb +9 -0
  24. data/lib/generators/graphql/templates/interface.erb +4 -2
  25. data/lib/generators/graphql/templates/mutation.erb +1 -1
  26. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  27. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  28. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  29. data/lib/generators/graphql/templates/node_type.erb +9 -0
  30. data/lib/generators/graphql/templates/object.erb +5 -3
  31. data/lib/generators/graphql/templates/query_type.erb +1 -3
  32. data/lib/generators/graphql/templates/scalar.erb +3 -1
  33. data/lib/generators/graphql/templates/schema.erb +19 -34
  34. data/lib/generators/graphql/templates/union.erb +4 -2
  35. data/lib/generators/graphql/type_generator.rb +47 -10
  36. data/lib/generators/graphql/union_generator.rb +5 -5
  37. data/lib/graphql/analysis/analyze_query.rb +7 -0
  38. data/lib/graphql/analysis/ast/field_usage.rb +28 -1
  39. data/lib/graphql/analysis/ast/query_complexity.rb +10 -14
  40. data/lib/graphql/analysis/ast/visitor.rb +14 -5
  41. data/lib/graphql/analysis/ast.rb +11 -2
  42. data/lib/graphql/argument.rb +1 -1
  43. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  44. data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
  45. data/lib/graphql/backtrace/table.rb +34 -3
  46. data/lib/graphql/backtrace/traced_error.rb +0 -1
  47. data/lib/graphql/backtrace/tracer.rb +40 -10
  48. data/lib/graphql/backtrace.rb +28 -19
  49. data/lib/graphql/backwards_compatibility.rb +2 -1
  50. data/lib/graphql/base_type.rb +6 -4
  51. data/lib/graphql/boolean_type.rb +1 -1
  52. data/lib/graphql/compatibility/execution_specification.rb +1 -0
  53. data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
  54. data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
  55. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
  56. data/lib/graphql/dataloader/null_dataloader.rb +22 -0
  57. data/lib/graphql/dataloader/request.rb +19 -0
  58. data/lib/graphql/dataloader/request_all.rb +19 -0
  59. data/lib/graphql/dataloader/source.rb +155 -0
  60. data/lib/graphql/dataloader.rb +308 -0
  61. data/lib/graphql/date_encoding_error.rb +16 -0
  62. data/lib/graphql/define/assign_global_id_field.rb +1 -1
  63. data/lib/graphql/define/instance_definable.rb +48 -3
  64. data/lib/graphql/define/type_definer.rb +5 -5
  65. data/lib/graphql/deprecated_dsl.rb +18 -5
  66. data/lib/graphql/deprecation.rb +9 -0
  67. data/lib/graphql/directive/deprecated_directive.rb +1 -1
  68. data/lib/graphql/directive/include_directive.rb +1 -1
  69. data/lib/graphql/directive/skip_directive.rb +1 -1
  70. data/lib/graphql/directive.rb +1 -5
  71. data/lib/graphql/enum_type.rb +9 -3
  72. data/lib/graphql/execution/errors.rb +110 -7
  73. data/lib/graphql/execution/execute.rb +8 -1
  74. data/lib/graphql/execution/interpreter/arguments.rb +57 -5
  75. data/lib/graphql/execution/interpreter/arguments_cache.rb +49 -15
  76. data/lib/graphql/execution/interpreter/handles_raw_value.rb +0 -7
  77. data/lib/graphql/execution/interpreter/resolve.rb +37 -25
  78. data/lib/graphql/execution/interpreter/runtime.rb +670 -294
  79. data/lib/graphql/execution/interpreter.rb +16 -16
  80. data/lib/graphql/execution/lazy.rb +5 -1
  81. data/lib/graphql/execution/lookahead.rb +2 -2
  82. data/lib/graphql/execution/multiplex.rb +39 -23
  83. data/lib/graphql/field.rb +1 -1
  84. data/lib/graphql/float_type.rb +1 -1
  85. data/lib/graphql/function.rb +4 -0
  86. data/lib/graphql/id_type.rb +1 -1
  87. data/lib/graphql/input_object_type.rb +3 -1
  88. data/lib/graphql/int_type.rb +1 -1
  89. data/lib/graphql/integer_decoding_error.rb +17 -0
  90. data/lib/graphql/integer_encoding_error.rb +18 -2
  91. data/lib/graphql/interface_type.rb +4 -2
  92. data/lib/graphql/internal_representation/document.rb +2 -2
  93. data/lib/graphql/internal_representation/rewrite.rb +1 -1
  94. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  95. data/lib/graphql/introspection/directive_type.rb +11 -5
  96. data/lib/graphql/introspection/entry_points.rb +2 -2
  97. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  98. data/lib/graphql/introspection/field_type.rb +3 -3
  99. data/lib/graphql/introspection/input_value_type.rb +10 -4
  100. data/lib/graphql/introspection/schema_type.rb +10 -5
  101. data/lib/graphql/introspection/type_type.rb +18 -12
  102. data/lib/graphql/introspection.rb +5 -2
  103. data/lib/graphql/invalid_null_error.rb +1 -1
  104. data/lib/graphql/language/block_string.rb +2 -6
  105. data/lib/graphql/language/cache.rb +37 -0
  106. data/lib/graphql/language/document_from_schema_definition.rb +60 -26
  107. data/lib/graphql/language/lexer.rb +50 -28
  108. data/lib/graphql/language/lexer.rl +2 -4
  109. data/lib/graphql/language/nodes.rb +14 -4
  110. data/lib/graphql/language/parser.rb +856 -825
  111. data/lib/graphql/language/parser.y +28 -11
  112. data/lib/graphql/language/printer.rb +10 -1
  113. data/lib/graphql/language/sanitized_printer.rb +5 -5
  114. data/lib/graphql/language/token.rb +0 -4
  115. data/lib/graphql/language.rb +1 -0
  116. data/lib/graphql/name_validator.rb +0 -4
  117. data/lib/graphql/object_type.rb +4 -4
  118. data/lib/graphql/pagination/active_record_relation_connection.rb +47 -3
  119. data/lib/graphql/pagination/connection.rb +19 -1
  120. data/lib/graphql/pagination/connections.rb +45 -30
  121. data/lib/graphql/pagination/relation_connection.rb +69 -28
  122. data/lib/graphql/parse_error.rb +0 -1
  123. data/lib/graphql/query/arguments.rb +2 -2
  124. data/lib/graphql/query/arguments_cache.rb +1 -2
  125. data/lib/graphql/query/context.rb +22 -4
  126. data/lib/graphql/query/executor.rb +0 -1
  127. data/lib/graphql/query/input_validation_result.rb +9 -0
  128. data/lib/graphql/query/literal_input.rb +1 -1
  129. data/lib/graphql/query/null_context.rb +21 -9
  130. data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
  131. data/lib/graphql/query/serial_execution.rb +1 -0
  132. data/lib/graphql/query/validation_pipeline.rb +3 -4
  133. data/lib/graphql/query/variable_validation_error.rb +3 -3
  134. data/lib/graphql/query/variables.rb +35 -4
  135. data/lib/graphql/query.rb +20 -8
  136. data/lib/graphql/railtie.rb +9 -1
  137. data/lib/graphql/rake_task.rb +3 -0
  138. data/lib/graphql/relay/array_connection.rb +2 -2
  139. data/lib/graphql/relay/base_connection.rb +7 -0
  140. data/lib/graphql/relay/connection_instrumentation.rb +4 -4
  141. data/lib/graphql/relay/connection_type.rb +16 -3
  142. data/lib/graphql/relay/edges_instrumentation.rb +0 -1
  143. data/lib/graphql/relay/global_id_resolve.rb +1 -2
  144. data/lib/graphql/relay/mutation.rb +2 -1
  145. data/lib/graphql/relay/node.rb +3 -0
  146. data/lib/graphql/relay/page_info.rb +1 -1
  147. data/lib/graphql/relay/range_add.rb +14 -5
  148. data/lib/graphql/relay/type_extensions.rb +2 -0
  149. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  150. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  151. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  152. data/lib/graphql/rubocop.rb +4 -0
  153. data/lib/graphql/scalar_type.rb +3 -1
  154. data/lib/graphql/schema/addition.rb +247 -0
  155. data/lib/graphql/schema/argument.rb +177 -21
  156. data/lib/graphql/schema/build_from_definition.rb +150 -55
  157. data/lib/graphql/schema/default_type_error.rb +2 -0
  158. data/lib/graphql/schema/directive/feature.rb +1 -1
  159. data/lib/graphql/schema/directive/flagged.rb +57 -0
  160. data/lib/graphql/schema/directive/include.rb +1 -1
  161. data/lib/graphql/schema/directive/skip.rb +1 -1
  162. data/lib/graphql/schema/directive/transform.rb +14 -2
  163. data/lib/graphql/schema/directive.rb +103 -4
  164. data/lib/graphql/schema/enum.rb +72 -11
  165. data/lib/graphql/schema/enum_value.rb +18 -6
  166. data/lib/graphql/schema/field/connection_extension.rb +4 -2
  167. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  168. data/lib/graphql/schema/field.rb +332 -111
  169. data/lib/graphql/schema/field_extension.rb +89 -2
  170. data/lib/graphql/schema/find_inherited_value.rb +4 -1
  171. data/lib/graphql/schema/finder.rb +5 -5
  172. data/lib/graphql/schema/input_object.rb +79 -55
  173. data/lib/graphql/schema/interface.rb +12 -20
  174. data/lib/graphql/schema/introspection_system.rb +1 -1
  175. data/lib/graphql/schema/list.rb +21 -4
  176. data/lib/graphql/schema/loader.rb +11 -0
  177. data/lib/graphql/schema/member/accepts_definition.rb +15 -3
  178. data/lib/graphql/schema/member/base_dsl_methods.rb +5 -16
  179. data/lib/graphql/schema/member/build_type.rb +4 -7
  180. data/lib/graphql/schema/member/cached_graphql_definition.rb +29 -2
  181. data/lib/graphql/schema/member/has_arguments.rb +166 -74
  182. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  183. data/lib/graphql/schema/member/has_directives.rb +98 -0
  184. data/lib/graphql/schema/member/has_fields.rb +77 -22
  185. data/lib/graphql/schema/member/has_interfaces.rb +100 -0
  186. data/lib/graphql/schema/member/has_validators.rb +31 -0
  187. data/lib/graphql/schema/member/instrumentation.rb +0 -1
  188. data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
  189. data/lib/graphql/schema/member/validates_input.rb +2 -2
  190. data/lib/graphql/schema/member.rb +5 -0
  191. data/lib/graphql/schema/middleware_chain.rb +1 -1
  192. data/lib/graphql/schema/non_null.rb +9 -3
  193. data/lib/graphql/schema/object.rb +40 -80
  194. data/lib/graphql/schema/printer.rb +16 -20
  195. data/lib/graphql/schema/relay_classic_mutation.rb +38 -4
  196. data/lib/graphql/schema/resolver/has_payload_type.rb +29 -2
  197. data/lib/graphql/schema/resolver.rb +110 -64
  198. data/lib/graphql/schema/scalar.rb +18 -2
  199. data/lib/graphql/schema/subscription.rb +55 -9
  200. data/lib/graphql/schema/timeout_middleware.rb +3 -1
  201. data/lib/graphql/schema/traversal.rb +1 -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 +8 -1
  205. data/lib/graphql/schema/validation.rb +4 -2
  206. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  207. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  208. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  209. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  210. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  211. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  212. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  213. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  214. data/lib/graphql/schema/validator.rb +171 -0
  215. data/lib/graphql/schema/warden.rb +126 -53
  216. data/lib/graphql/schema.rb +262 -281
  217. data/lib/graphql/static_validation/all_rules.rb +2 -0
  218. data/lib/graphql/static_validation/base_visitor.rb +9 -6
  219. data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
  220. data/lib/graphql/static_validation/error.rb +3 -1
  221. data/lib/graphql/static_validation/literal_validator.rb +1 -1
  222. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +4 -2
  223. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +6 -2
  224. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
  225. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  226. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
  227. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
  228. data/lib/graphql/static_validation/rules/fields_will_merge.rb +90 -47
  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/query_root_exists.rb +17 -0
  234. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  235. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -2
  236. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
  237. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
  238. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +14 -8
  239. data/lib/graphql/static_validation/validation_context.rb +12 -2
  240. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  241. data/lib/graphql/static_validation/validator.rb +41 -10
  242. data/lib/graphql/static_validation.rb +1 -0
  243. data/lib/graphql/string_encoding_error.rb +13 -3
  244. data/lib/graphql/string_type.rb +1 -1
  245. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +39 -8
  246. data/lib/graphql/subscriptions/broadcast_analyzer.rb +0 -3
  247. data/lib/graphql/subscriptions/event.rb +68 -32
  248. data/lib/graphql/subscriptions/instrumentation.rb +0 -1
  249. data/lib/graphql/subscriptions/serialize.rb +34 -5
  250. data/lib/graphql/subscriptions/subscription_root.rb +1 -1
  251. data/lib/graphql/subscriptions.rb +34 -39
  252. data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -21
  253. data/lib/graphql/tracing/appoptics_tracing.rb +3 -1
  254. data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
  255. data/lib/graphql/tracing/data_dog_tracing.rb +24 -2
  256. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  257. data/lib/graphql/tracing/platform_tracing.rb +24 -12
  258. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  259. data/lib/graphql/tracing/skylight_tracing.rb +1 -1
  260. data/lib/graphql/tracing.rb +2 -2
  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 +13 -5
  264. data/lib/graphql/types/iso_8601_date_time.rb +8 -1
  265. data/lib/graphql/types/relay/base_connection.rb +6 -91
  266. data/lib/graphql/types/relay/base_edge.rb +2 -34
  267. data/lib/graphql/types/relay/connection_behaviors.rb +174 -0
  268. data/lib/graphql/types/relay/default_relay.rb +31 -0
  269. data/lib/graphql/types/relay/edge_behaviors.rb +64 -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 +3 -22
  275. data/lib/graphql/types/relay/nodes_field.rb +16 -18
  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 +1 -1
  281. data/lib/graphql/union_type.rb +3 -1
  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 +68 -37
  286. data/readme.md +3 -6
  287. metadata +83 -113
  288. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  289. data/lib/graphql/types/relay/base_field.rb +0 -22
  290. data/lib/graphql/types/relay/base_interface.rb +0 -29
  291. data/lib/graphql/types/relay/base_object.rb +0 -26
  292. /data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +0 -0
  293. /data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b6e1d6fb5063c843becb61784cb776964a380af5a2fc5a98054d2554ddf4caa
4
- data.tar.gz: c41027cdf69f8c07bed157075c70e95936f3d26922f0b1d38f7759352a35ab43
3
+ metadata.gz: c21327429549138738debab2d522197133548eb4b275a5f67086154e08469149
4
+ data.tar.gz: ec61107f4f45aaf1de25c6674d7fcf3b8e19b1245fdbf2a1bd1b0f7f1dd9b0aa
5
5
  SHA512:
6
- metadata.gz: 3dc4e13b30d51c32775785b9ed4a11940bc2cb541866877e6eef48bc621956700ddf057c597d2bc5a9fa09ca863e01ba84295e414e488e22ee03b94c28bc4003
7
- data.tar.gz: 70f5ba8c04e13b83af431db1e8edea297a3c43acc6f6356668094349b577fe7de4e8cdb029aaf8ce70cc243664915ac7dac38612badd0acb720ce57464769cec
6
+ metadata.gz: 5b56c3aaa86b6d758b53d49a7906de483375c54f40db9126b96d791f41c7bba6407d9b59205a4d47215cef1391cd5ebbc03d5eb76825747cbfc1d0f6baf1f0ef
7
+ data.tar.gz: 7f7cb3b2e4fa8c26b355ea4adf01803ab32e2d97036475469071e2cf67d06431ab0486f0daf8ab28433deb95bb8642ea0a2b52739abe6d0ad06bb22b4fdcb2cc
@@ -19,17 +19,12 @@ module Graphql
19
19
  sentinel = /< GraphQL::Schema\s*\n/m
20
20
 
21
21
  in_root do
22
- inject_into_file schema_file_path, " #{type}(Types::#{name})\n", after: sentinel, verbose: false, force: false
22
+ if File.exist?(schema_file_path)
23
+ inject_into_file schema_file_path, " #{type}(Types::#{name})\n", after: sentinel, verbose: false, force: false
24
+ end
23
25
  end
24
26
  end
25
27
 
26
- def create_mutation_root_type
27
- create_dir("#{options[:directory]}/mutations")
28
- template("base_mutation.erb", "#{options[:directory]}/mutations/base_mutation.rb", { skip: true })
29
- template("mutation_type.erb", "#{options[:directory]}/types/mutation_type.rb", { skip: true })
30
- insert_root_type('mutation', 'MutationType')
31
- end
32
-
33
28
  def schema_file_path
34
29
  "#{options[:directory]}/#{schema_name.underscore}.rb"
35
30
  end
@@ -13,20 +13,14 @@ module Graphql
13
13
  desc "Create a GraphQL::EnumType with the given name and values"
14
14
  source_root File.expand_path('../templates', __FILE__)
15
15
 
16
- argument :values,
17
- type: :array,
18
- default: [],
19
- banner: "value{:ruby_value} value{:ruby_value} ...",
20
- desc: "Values for this enum (if present, ruby_value will be inserted verbatim)"
16
+ private
21
17
 
22
- def create_type_file
23
- template "enum.erb", "#{options[:directory]}/types/#{type_file_name}.rb"
18
+ def graphql_type
19
+ "enum"
24
20
  end
25
21
 
26
- private
27
-
28
22
  def prepared_values
29
- values.map { |v| v.split(":", 2) }
23
+ custom_fields.map { |v| v.split(":", 2) }
30
24
  end
31
25
  end
32
26
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+ require 'rails/generators/base'
3
+
4
+ module Graphql
5
+ module Generators
6
+ module FieldExtractor
7
+ def fields
8
+ columns = []
9
+ columns += (klass&.columns&.map { |c| generate_column_string(c) } || [])
10
+ columns + custom_fields
11
+ end
12
+
13
+ def generate_column_string(column)
14
+ name = column.name
15
+ required = column.null ? "" : "!"
16
+ type = column_type_string(column)
17
+ "#{name}:#{required}#{type}"
18
+ end
19
+
20
+ def column_type_string(column)
21
+ column.name == "id" ? "ID" : column.type.to_s.camelize
22
+ end
23
+
24
+ def klass
25
+ @klass ||= Module.const_get(name.camelize)
26
+ rescue NameError
27
+ @klass = nil
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ require 'generators/graphql/type_generator'
3
+ require 'generators/graphql/field_extractor'
4
+
5
+ module Graphql
6
+ module Generators
7
+ # Generate an input type by name,
8
+ # with the specified fields.
9
+ #
10
+ # ```
11
+ # rails g graphql:object PostType name:string!
12
+ # ```
13
+ class InputGenerator < TypeGeneratorBase
14
+ desc "Create a GraphQL::InputObjectType with the given name and fields"
15
+ source_root File.expand_path('../templates', __FILE__)
16
+ include FieldExtractor
17
+
18
+ def self.normalize_type_expression(type_expression, mode:, null: true)
19
+ case type_expression.camelize
20
+ when "Text", "Citext"
21
+ ["String", null]
22
+ when "Decimal"
23
+ ["Float", null]
24
+ when "DateTime", "Datetime"
25
+ ["GraphQL::Types::ISO8601DateTime", null]
26
+ when "Date"
27
+ ["GraphQL::Types::ISO8601Date", null]
28
+ when "Json", "Jsonb", "Hstore"
29
+ ["GraphQL::Types::JSON", null]
30
+ else
31
+ super
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def graphql_type
38
+ "input"
39
+ end
40
+
41
+ def type_ruby_name
42
+ super.gsub(/Type\z/, "InputType")
43
+ end
44
+
45
+ def type_file_name
46
+ super.gsub(/_type\z/, "_input_type")
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/base"
4
+ require_relative "../core"
5
+
6
+ module Graphql
7
+ module Generators
8
+ module Install
9
+ class MutationRootGenerator < Rails::Generators::Base
10
+ include Core
11
+
12
+ desc "Create mutation base type, mutation root tipe, and adds the latter to the schema"
13
+ source_root File.expand_path('../templates', __FILE__)
14
+
15
+ class_option :schema,
16
+ type: :string,
17
+ default: nil,
18
+ desc: "Name for the schema constant (default: {app_name}Schema)"
19
+
20
+ class_option :skip_keeps,
21
+ type: :boolean,
22
+ default: false,
23
+ desc: "Skip .keep files for source control"
24
+
25
+ def generate
26
+ create_dir("#{options[:directory]}/mutations")
27
+ template("base_mutation.erb", "#{options[:directory]}/mutations/base_mutation.rb", { skip: true })
28
+ template("mutation_type.erb", "#{options[:directory]}/types/mutation_type.rb", { skip: true })
29
+ insert_root_type('mutation', 'MutationType')
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
+ require 'rails/generators'
2
3
  require 'rails/generators/base'
3
4
  require_relative 'core'
5
+ require_relative 'relay'
4
6
 
5
7
  module Graphql
6
8
  module Generators
@@ -43,9 +45,6 @@ module Graphql
43
45
  # post "/graphql", to: "graphql#execute"
44
46
  # ```
45
47
  #
46
- # Accept a `--relay` option which adds
47
- # The root `node(id: ID!)` field.
48
- #
49
48
  # Accept a `--batch` option which adds `GraphQL::Batch` setup.
50
49
  #
51
50
  # Use `--no-graphiql` to skip `graphiql-rails` installation.
@@ -53,6 +52,7 @@ module Graphql
53
52
  # TODO: also add base classes
54
53
  class InstallGenerator < Rails::Generators::Base
55
54
  include Core
55
+ include Relay
56
56
 
57
57
  desc "Install GraphQL folder structure and boilerplate code"
58
58
  source_root File.expand_path('../templates', __FILE__)
@@ -79,8 +79,8 @@ module Graphql
79
79
 
80
80
  class_option :relay,
81
81
  type: :boolean,
82
- default: false,
83
- desc: "Include GraphQL::Relay installation"
82
+ default: true,
83
+ desc: "Include installation of Relay conventions (nodes, connections, edges)"
84
84
 
85
85
  class_option :batch,
86
86
  type: :boolean,
@@ -109,7 +109,7 @@ module Graphql
109
109
  template("query_type.erb", "#{options[:directory]}/types/query_type.rb")
110
110
  insert_root_type('query', 'QueryType')
111
111
 
112
- create_mutation_root_type unless options.skip_mutation_root_type?
112
+ invoke "graphql:install:mutation_root" unless options.skip_mutation_root_type?
113
113
 
114
114
  template("graphql_controller.erb", "app/controllers/graphql_controller.rb")
115
115
  route('post "/graphql", to: "graphql#execute"')
@@ -123,7 +123,14 @@ module Graphql
123
123
  say("Skipped graphiql, as this rails project is API only")
124
124
  say(" You may wish to use GraphiQL.app for development: https://github.com/skevy/graphiql-app")
125
125
  elsif !options[:skip_graphiql]
126
- gem("graphiql-rails", group: :development)
126
+ # `gem(...)` uses `gsub_file(...)` under the hood, which is a no-op for `rails destroy...` (when `behavior == :revoke`).
127
+ # So handle that case by calling `gsub_file` with `force: true`.
128
+ if behavior == :invoke && !File.read(Rails.root.join("Gemfile")).include?("graphiql-rails")
129
+ gem("graphiql-rails", group: :development)
130
+ elsif behavior == :revoke
131
+ gemfile_pattern = /\n\s*gem ('|")graphiql-rails('|"), :?group(:| =>) :development/
132
+ gsub_file Rails.root.join("Gemfile"), gemfile_pattern, "", { force: true }
133
+ end
127
134
 
128
135
  # This is a little cheat just to get cleaner shell output:
129
136
  log :route, 'graphiql-rails'
@@ -164,7 +171,10 @@ if Rails.env.development?
164
171
  RUBY
165
172
  end
166
173
  end
174
+ end
167
175
 
176
+ if options[:relay]
177
+ install_relay
168
178
  end
169
179
 
170
180
  if gemfile_modified?
@@ -13,14 +13,14 @@ module Graphql
13
13
  desc "Create a GraphQL::InterfaceType with the given name and fields"
14
14
  source_root File.expand_path('../templates', __FILE__)
15
15
 
16
- argument :fields,
17
- type: :array,
18
- default: [],
19
- banner: "name:type name:type ...",
20
- desc: "Fields for this interface (type may be expressed as Ruby or GraphQL)"
16
+ private
21
17
 
22
- def create_type_file
23
- template "interface.erb", "#{options[:directory]}/types/#{type_file_name}.rb"
18
+ def graphql_type
19
+ "interface"
20
+ end
21
+
22
+ def fields
23
+ custom_fields
24
24
  end
25
25
  end
26
26
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ require 'rails/generators'
2
3
  require "rails/generators/named_base"
3
4
  require_relative "core"
4
5
 
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'orm_mutations_base'
3
+
4
+ module Graphql
5
+ module Generators
6
+ # TODO: What other options should be supported?
7
+ #
8
+ # @example Generate a `GraphQL::Schema::RelayClassicMutation` by name
9
+ # rails g graphql:mutation CreatePostMutation
10
+ class MutationCreateGenerator < OrmMutationsBase
11
+
12
+ desc "Scaffold a Relay Classic ORM create mutation for the given model class"
13
+ source_root File.expand_path('../templates', __FILE__)
14
+
15
+ private
16
+
17
+ def operation_type
18
+ "create"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'orm_mutations_base'
3
+
4
+ module Graphql
5
+ module Generators
6
+ # TODO: What other options should be supported?
7
+ #
8
+ # @example Generate a `GraphQL::Schema::RelayClassicMutation` by name
9
+ # rails g graphql:mutation CreatePostMutation
10
+ class MutationDeleteGenerator < OrmMutationsBase
11
+
12
+ desc "Scaffold a Relay Classic ORM delete mutation for the given model class"
13
+ source_root File.expand_path('../templates', __FILE__)
14
+
15
+ private
16
+
17
+ def operation_type
18
+ "delete"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ require 'rails/generators'
2
3
  require 'rails/generators/named_base'
3
4
  require_relative 'core'
4
5
 
@@ -8,47 +9,22 @@ module Graphql
8
9
  #
9
10
  # @example Generate a `GraphQL::Schema::RelayClassicMutation` by name
10
11
  # rails g graphql:mutation CreatePostMutation
11
- class MutationGenerator < Rails::Generators::Base
12
+ class MutationGenerator < Rails::Generators::NamedBase
12
13
  include Core
13
14
 
14
15
  desc "Create a Relay Classic mutation by name"
15
16
  source_root File.expand_path('../templates', __FILE__)
16
17
 
17
- argument :name, type: :string
18
-
19
- def initialize(args, *options) #:nodoc:
20
- # Unfreeze name in case it's given as a frozen string
21
- args[0] = args[0].dup if args[0].is_a?(String) && args[0].frozen?
22
- super
23
-
24
- assign_names!(name)
25
- end
26
-
27
- attr_reader :file_name, :mutation_name, :field_name
28
-
29
18
  def create_mutation_file
30
- unless @behavior == :revoke
31
- create_mutation_root_type
32
- else
33
- log :gsub, "#{options[:directory]}/types/mutation_type.rb"
34
- end
35
-
36
- template "mutation.erb", "#{options[:directory]}/mutations/#{file_name}.rb"
19
+ template "mutation.erb", File.join(options[:directory], "/mutations/", class_path, "#{file_name}.rb")
37
20
 
38
21
  sentinel = /class .*MutationType\s*<\s*[^\s]+?\n/m
39
22
  in_root do
40
- gsub_file "#{options[:directory]}/types/mutation_type.rb", / \# TODO\: Add Mutations as fields\s*\n/m, ""
41
- inject_into_file "#{options[:directory]}/types/mutation_type.rb", " field :#{field_name}, mutation: Mutations::#{mutation_name}\n", after: sentinel, verbose: false, force: false
23
+ path = "#{options[:directory]}/types/mutation_type.rb"
24
+ invoke "graphql:install:mutation_root" unless File.exist?(path)
25
+ inject_into_file "#{options[:directory]}/types/mutation_type.rb", " field :#{file_name}, mutation: Mutations::#{class_name}\n", after: sentinel, verbose: false, force: false
42
26
  end
43
27
  end
44
-
45
- private
46
-
47
- def assign_names!(name)
48
- @field_name = name.camelize.underscore
49
- @mutation_name = name.camelize(:upper)
50
- @file_name = name.camelize.underscore
51
- end
52
28
  end
53
29
  end
54
30
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'orm_mutations_base'
3
+
4
+ module Graphql
5
+ module Generators
6
+ # TODO: What other options should be supported?
7
+ #
8
+ # @example Generate a `GraphQL::Schema::RelayClassicMutation` by name
9
+ # rails g graphql:mutation CreatePostMutation
10
+ class MutationUpdateGenerator < OrmMutationsBase
11
+
12
+ desc "Scaffold a Relay Classic ORM update mutation for the given model class"
13
+ source_root File.expand_path('../templates', __FILE__)
14
+
15
+ private
16
+
17
+ def operation_type
18
+ "update"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require 'generators/graphql/type_generator'
3
+ require 'generators/graphql/field_extractor'
3
4
 
4
5
  module Graphql
5
6
  module Generators
@@ -12,38 +13,28 @@ module Graphql
12
13
  #
13
14
  # Add the Node interface with `--node`.
14
15
  class ObjectGenerator < TypeGeneratorBase
15
- desc "Create a GraphQL::ObjectType with the given name and fields"
16
+ desc "Create a GraphQL::ObjectType with the given name and fields." \
17
+ "If the given type name matches an existing ActiveRecord model, the generated type will automatically include fields for the models database columns."
16
18
  source_root File.expand_path('../templates', __FILE__)
17
-
18
- argument :custom_fields,
19
- type: :array,
20
- default: [],
21
- banner: "name:type name:type ...",
22
- desc: "Fields for this object (type may be expressed as Ruby or GraphQL)"
19
+ include FieldExtractor
23
20
 
24
21
  class_option :node,
25
22
  type: :boolean,
26
23
  default: false,
27
24
  desc: "Include the Relay Node interface"
28
25
 
29
- def create_type_file
30
- template "object.erb", "#{options[:directory]}/types/#{type_file_name}.rb"
31
- end
32
-
33
- def fields
34
- columns = []
35
- columns += klass.columns.map { |c| generate_column_string(c) } if class_exists?
36
- columns + custom_fields
37
- end
38
-
39
26
  def self.normalize_type_expression(type_expression, mode:, null: true)
40
- case type_expression
41
- when "Text"
27
+ case type_expression.camelize
28
+ when "Text", "Citext"
42
29
  ["String", null]
30
+ when "Decimal"
31
+ ["Float", null]
43
32
  when "DateTime", "Datetime"
44
33
  ["GraphQL::Types::ISO8601DateTime", null]
45
34
  when "Date"
46
35
  ["GraphQL::Types::ISO8601Date", null]
36
+ when "Json", "Jsonb", "Hstore"
37
+ ["GraphQL::Types::JSON", null]
47
38
  else
48
39
  super
49
40
  end
@@ -51,25 +42,8 @@ module Graphql
51
42
 
52
43
  private
53
44
 
54
- def generate_column_string(column)
55
- name = column.name
56
- required = column.null ? "" : "!"
57
- type = column_type_string(column)
58
- "#{name}:#{required}#{type}"
59
- end
60
-
61
- def column_type_string(column)
62
- column.name == "id" ? "ID" : column.type.to_s.camelize
63
- end
64
-
65
- def class_exists?
66
- klass.is_a?(Class) && klass.ancestors.include?(ActiveRecord::Base)
67
- rescue NameError
68
- return false
69
- end
70
-
71
- def klass
72
- @klass ||= Module.const_get(type_name.camelize)
45
+ def graphql_type
46
+ "object"
73
47
  end
74
48
  end
75
49
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+ require 'rails/generators'
3
+ require 'rails/generators/named_base'
4
+ require_relative 'core'
5
+
6
+ module Graphql
7
+ module Generators
8
+ # TODO: What other options should be supported?
9
+ #
10
+ # @example Generate a `GraphQL::Schema::RelayClassicMutation` by name
11
+ # rails g graphql:mutation CreatePostMutation
12
+ class OrmMutationsBase < Rails::Generators::NamedBase
13
+ include Core
14
+ include Rails::Generators::ResourceHelpers
15
+
16
+ desc "Create a Relay Classic mutation by name"
17
+
18
+ class_option :orm, banner: "NAME", type: :string, required: true,
19
+ desc: "ORM to generate the controller for"
20
+
21
+ class_option 'namespaced_types',
22
+ type: :boolean,
23
+ required: false,
24
+ default: false,
25
+ banner: "Namespaced",
26
+ desc: "If the generated types will be namespaced"
27
+
28
+ def create_mutation_file
29
+ template "mutation_#{operation_type}.erb", File.join(options[:directory], "/mutations/", class_path, "#{file_name}_#{operation_type}.rb")
30
+
31
+ sentinel = /class .*MutationType\s*<\s*[^\s]+?\n/m
32
+ in_root do
33
+ path = "#{options[:directory]}/types/mutation_type.rb"
34
+ invoke "graphql:install:mutation_root" unless File.exist?(path)
35
+ inject_into_file "#{options[:directory]}/types/mutation_type.rb", " field :#{file_name}_#{operation_type}, mutation: Mutations::#{class_name}#{operation_type.classify}\n", after: sentinel, verbose: false, force: false
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+ module Graphql
3
+ module Generators
4
+ module Relay
5
+ def install_relay
6
+ # Add Node, `node(id:)`, and `nodes(ids:)`
7
+ template("node_type.erb", "#{options[:directory]}/types/node_type.rb")
8
+ in_root do
9
+ fields = " # Add `node(id: ID!) and `nodes(ids: [ID!]!)`\n include GraphQL::Types::Relay::HasNodeField\n include GraphQL::Types::Relay::HasNodesField\n\n"
10
+ inject_into_file "#{options[:directory]}/types/query_type.rb", fields, after: /class .*QueryType\s*<\s*[^\s]+?\n/m, force: false
11
+ end
12
+
13
+ # Add connections and edges
14
+ template("base_connection.erb", "#{options[:directory]}/types/base_connection.rb")
15
+ template("base_edge.erb", "#{options[:directory]}/types/base_edge.rb")
16
+ connectionable_type_files = {
17
+ "#{options[:directory]}/types/base_object.rb" => /class .*BaseObject\s*<\s*[^\s]+?\n/m,
18
+ "#{options[:directory]}/types/base_union.rb" => /class .*BaseUnion\s*<\s*[^\s]+?\n/m,
19
+ "#{options[:directory]}/types/base_interface.rb" => /include GraphQL::Schema::Interface\n/m,
20
+ }
21
+ in_root do
22
+ connectionable_type_files.each do |type_class_file, sentinel|
23
+ inject_into_file type_class_file, " connection_type_class(Types::BaseConnection)\n", after: sentinel, force: false
24
+ inject_into_file type_class_file, " edge_type_class(Types::BaseEdge)\n", after: sentinel, force: false
25
+ end
26
+ end
27
+
28
+ # Add object ID hooks & connection plugin
29
+ schema_code = <<-RUBY
30
+
31
+ # Relay-style Object Identification:
32
+
33
+ # Return a string UUID for `object`
34
+ def self.id_from_object(object, type_definition, query_ctx)
35
+ # For example, use Rails' GlobalID library (https://github.com/rails/globalid):
36
+ object_id = object.to_global_id.to_s
37
+ # Remove this redundant prefix to make IDs shorter:
38
+ object_id = object_id.sub("gid://\#{GlobalID.app}/", "")
39
+ encoded_id = Base64.urlsafe_encode64(object_id)
40
+ # Remove the "=" padding
41
+ encoded_id = encoded_id.sub(/=+/, "")
42
+ # Add a type hint
43
+ type_hint = type_definition.graphql_name.first
44
+ "\#{type_hint}_\#{encoded_id}"
45
+ end
46
+
47
+ # Given a string UUID, find the object
48
+ def self.object_from_id(encoded_id_with_hint, query_ctx)
49
+ # For example, use Rails' GlobalID library (https://github.com/rails/globalid):
50
+ # Split off the type hint
51
+ _type_hint, encoded_id = encoded_id_with_hint.split("_", 2)
52
+ # Decode the ID
53
+ id = Base64.urlsafe_decode64(encoded_id)
54
+ # Rebuild it for Rails then find the object:
55
+ full_global_id = "gid://\#{GlobalID.app}/\#{id}"
56
+ GlobalID::Locator.locate(full_global_id)
57
+ end
58
+ RUBY
59
+ inject_into_file schema_file_path, schema_code, before: /^end\n/m, force: false
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+ require 'rails/generators'
3
+ require 'rails/generators/base'
4
+ require_relative 'core'
5
+ require_relative 'relay'
6
+
7
+ module Graphql
8
+ module Generators
9
+ class RelayGenerator < Rails::Generators::Base
10
+ include Core
11
+ include Relay
12
+
13
+ desc "Add base types and fields for Relay-style nodes and connections"
14
+ source_root File.expand_path('../templates', __FILE__)
15
+
16
+ def install_relay
17
+ super
18
+ end
19
+ end
20
+ end
21
+ end
@@ -12,8 +12,10 @@ module Graphql
12
12
  desc "Create a GraphQL::ScalarType with the given name"
13
13
  source_root File.expand_path('../templates', __FILE__)
14
14
 
15
- def create_type_file
16
- template "scalar.erb", "#{options[:directory]}/types/#{type_file_name}.rb"
15
+ private
16
+
17
+ def graphql_type
18
+ "scalar"
17
19
  end
18
20
  end
19
21
  end
@@ -0,0 +1,8 @@
1
+ <% module_namespacing_when_supported do -%>
2
+ module Types
3
+ class BaseConnection < Types::BaseObject
4
+ # add `nodes` and `pageInfo` fields, as well as `edge_type(...)` and `node_nullable(...)` overrides
5
+ include GraphQL::Types::Relay::ConnectionBehaviors
6
+ end
7
+ end
8
+ <% end -%>
@@ -0,0 +1,8 @@
1
+ <% module_namespacing_when_supported do -%>
2
+ module Types
3
+ class BaseEdge < Types::BaseObject
4
+ # add `node` and `cursor` fields, as well as `node_type(...)` override
5
+ include GraphQL::Types::Relay::EdgeBehaviors
6
+ end
7
+ end
8
+ <% end -%>
@@ -1,6 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  <% module_namespacing_when_supported do -%>
2
4
  module Types
3
- class <%= type_ruby_name.split('::')[-1] %> < Types::BaseEnum
5
+ class <%= ruby_class_name %> < Types::BaseEnum
6
+ description "<%= human_name %> enum"
7
+
4
8
  <% prepared_values.each do |v| %> value "<%= v[0] %>"<%= v.length > 1 ? ", value: #{v[1]}" : "" %>
5
9
  <% end %> end
6
10
  end