rails-graphql 0.2.1 → 1.0.0.beta

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.
Files changed (297) hide show
  1. checksums.yaml +4 -4
  2. data/ext/console.rb +18 -0
  3. data/ext/extconf.h +3 -0
  4. data/ext/extconf.rb +1 -54
  5. data/ext/gql_parser.c +646 -0
  6. data/ext/shared.c +482 -0
  7. data/ext/shared.h +177 -0
  8. data/lib/gql_parser.so +0 -0
  9. data/lib/rails/graphql/adapters/mysql_adapter.rb +59 -0
  10. data/lib/rails/graphql/adapters/pg_adapter.rb +25 -22
  11. data/lib/rails/graphql/adapters/sqlite_adapter.rb +17 -14
  12. data/lib/rails/graphql/alternative/field_set.rb +36 -0
  13. data/lib/rails/graphql/alternative/mutation.rb +17 -0
  14. data/lib/rails/graphql/alternative/query.rb +93 -0
  15. data/lib/rails/graphql/alternative/subscription.rb +17 -0
  16. data/lib/rails/graphql/alternative.rb +20 -0
  17. data/lib/rails/graphql/argument.rb +21 -24
  18. data/lib/rails/graphql/callback.rb +24 -9
  19. data/lib/rails/graphql/collectors/hash_collector.rb +14 -6
  20. data/lib/rails/graphql/collectors/idented_collector.rb +10 -7
  21. data/lib/rails/graphql/collectors/json_collector.rb +22 -17
  22. data/lib/rails/graphql/collectors.rb +4 -4
  23. data/lib/rails/graphql/config.rb +130 -15
  24. data/lib/rails/graphql/directive/cached_directive.rb +33 -0
  25. data/lib/rails/graphql/directive/deprecated_directive.rb +10 -10
  26. data/lib/rails/graphql/directive/include_directive.rb +5 -4
  27. data/lib/rails/graphql/directive/skip_directive.rb +5 -4
  28. data/lib/rails/graphql/directive.rb +118 -63
  29. data/lib/rails/graphql/errors.rb +33 -4
  30. data/lib/rails/graphql/event.rb +16 -5
  31. data/lib/rails/graphql/field/authorized_field.rb +19 -3
  32. data/lib/rails/graphql/field/input_field.rb +11 -10
  33. data/lib/rails/graphql/field/mutation_field.rb +42 -7
  34. data/lib/rails/graphql/field/output_field.rb +102 -13
  35. data/lib/rails/graphql/field/proxied_field.rb +31 -22
  36. data/lib/rails/graphql/field/resolved_field.rb +26 -24
  37. data/lib/rails/graphql/field/scoped_config.rb +10 -4
  38. data/lib/rails/graphql/field/subscription_field.rb +140 -0
  39. data/lib/rails/graphql/field/typed_field.rb +43 -22
  40. data/lib/rails/graphql/field.rb +70 -56
  41. data/lib/rails/graphql/global_id.rb +85 -0
  42. data/lib/rails/graphql/helpers/attribute_delegator.rb +5 -5
  43. data/lib/rails/graphql/helpers/inherited_collection/array.rb +50 -0
  44. data/lib/rails/graphql/helpers/inherited_collection/base.rb +43 -0
  45. data/lib/rails/graphql/helpers/inherited_collection/hash.rb +87 -0
  46. data/lib/rails/graphql/helpers/inherited_collection.rb +25 -76
  47. data/lib/rails/graphql/helpers/instantiable.rb +15 -0
  48. data/lib/rails/graphql/helpers/leaf_from_ar.rb +7 -7
  49. data/lib/rails/graphql/helpers/registerable.rb +44 -62
  50. data/lib/rails/graphql/helpers/unregisterable.rb +16 -0
  51. data/lib/rails/graphql/helpers/with_arguments.rb +31 -27
  52. data/lib/rails/graphql/helpers/with_assignment.rb +6 -6
  53. data/lib/rails/graphql/helpers/with_callbacks.rb +25 -8
  54. data/lib/rails/graphql/helpers/with_description.rb +71 -0
  55. data/lib/rails/graphql/helpers/with_directives.rb +54 -30
  56. data/lib/rails/graphql/helpers/with_events.rb +21 -23
  57. data/lib/rails/graphql/helpers/with_fields.rb +76 -22
  58. data/lib/rails/graphql/helpers/with_global_id.rb +22 -0
  59. data/lib/rails/graphql/helpers/with_name.rb +43 -0
  60. data/lib/rails/graphql/helpers/with_namespace.rb +7 -4
  61. data/lib/rails/graphql/helpers/with_owner.rb +8 -7
  62. data/lib/rails/graphql/helpers/with_schema_fields.rb +137 -55
  63. data/lib/rails/graphql/helpers/with_validator.rb +9 -9
  64. data/lib/rails/graphql/helpers.rb +10 -3
  65. data/lib/rails/graphql/introspection.rb +43 -36
  66. data/lib/rails/graphql/railtie.rb +88 -33
  67. data/lib/rails/graphql/railties/base_generator.rb +3 -9
  68. data/lib/rails/graphql/railties/channel.rb +157 -0
  69. data/lib/rails/graphql/railties/controller.rb +62 -17
  70. data/lib/rails/graphql/railties/controller_runtime.rb +5 -5
  71. data/lib/rails/graphql/railties/log_subscriber.rb +81 -14
  72. data/lib/rails/graphql/request/arguments.rb +24 -49
  73. data/lib/rails/graphql/request/backtrace.rb +191 -0
  74. data/lib/rails/graphql/request/component/field.rb +86 -65
  75. data/lib/rails/graphql/request/component/fragment.rb +72 -24
  76. data/lib/rails/graphql/request/component/operation/subscription.rb +164 -4
  77. data/lib/rails/graphql/request/component/operation.rb +63 -31
  78. data/lib/rails/graphql/request/component/spread.rb +68 -25
  79. data/lib/rails/graphql/request/component/typename.rb +27 -12
  80. data/lib/rails/graphql/request/component.rb +75 -36
  81. data/lib/rails/graphql/request/context.rb +18 -8
  82. data/lib/rails/graphql/request/errors.rb +16 -6
  83. data/lib/rails/graphql/request/event.rb +19 -8
  84. data/lib/rails/graphql/request/helpers/directives.rb +68 -27
  85. data/lib/rails/graphql/request/helpers/selection_set.rb +51 -25
  86. data/lib/rails/graphql/request/helpers/value_writers.rb +18 -16
  87. data/lib/rails/graphql/request/prepared_data.rb +98 -0
  88. data/lib/rails/graphql/request/steps/authorizable.rb +24 -14
  89. data/lib/rails/graphql/request/steps/organizable.rb +110 -48
  90. data/lib/rails/graphql/request/steps/{prepareable.rb → preparable.rb} +20 -7
  91. data/lib/rails/graphql/request/steps/{resolveable.rb → resolvable.rb} +15 -6
  92. data/lib/rails/graphql/request/strategy/cached_strategy.rb +64 -0
  93. data/lib/rails/graphql/request/strategy/dynamic_instance.rb +6 -6
  94. data/lib/rails/graphql/request/strategy/multi_query_strategy.rb +6 -13
  95. data/lib/rails/graphql/request/strategy/sequenced_strategy.rb +9 -9
  96. data/lib/rails/graphql/request/strategy.rb +131 -75
  97. data/lib/rails/graphql/request/subscription.rb +80 -0
  98. data/lib/rails/graphql/request.rb +305 -86
  99. data/lib/rails/graphql/schema.rb +240 -48
  100. data/lib/rails/graphql/shortcuts.rb +22 -3
  101. data/lib/rails/graphql/source/active_record/builders.rb +49 -35
  102. data/lib/rails/graphql/source/active_record_source.rb +70 -54
  103. data/lib/rails/graphql/source/base.rb +111 -0
  104. data/lib/rails/graphql/source/builder.rb +128 -0
  105. data/lib/rails/graphql/source/scoped_arguments.rb +31 -19
  106. data/lib/rails/graphql/source.rb +89 -213
  107. data/lib/rails/graphql/subscription/provider/action_cable.rb +112 -0
  108. data/lib/rails/graphql/subscription/provider/base.rb +191 -0
  109. data/lib/rails/graphql/subscription/provider.rb +18 -0
  110. data/lib/rails/graphql/subscription/store/base.rb +145 -0
  111. data/lib/rails/graphql/subscription/store/memory.rb +127 -0
  112. data/lib/rails/graphql/subscription/store.rb +19 -0
  113. data/lib/rails/graphql/subscription.rb +17 -0
  114. data/lib/rails/graphql/to_gql.rb +29 -32
  115. data/lib/rails/graphql/type/enum/directive_location_enum.rb +11 -11
  116. data/lib/rails/graphql/type/enum/type_kind_enum.rb +3 -3
  117. data/lib/rails/graphql/type/enum.rb +34 -48
  118. data/lib/rails/graphql/type/input.rb +74 -23
  119. data/lib/rails/graphql/type/interface.rb +16 -26
  120. data/lib/rails/graphql/type/object/directive_object.rb +4 -4
  121. data/lib/rails/graphql/type/object/enum_value_object.rb +3 -3
  122. data/lib/rails/graphql/type/object/field_object.rb +24 -6
  123. data/lib/rails/graphql/type/object/input_value_object.rb +3 -3
  124. data/lib/rails/graphql/type/object/schema_object.rb +5 -8
  125. data/lib/rails/graphql/type/object/type_object.rb +29 -19
  126. data/lib/rails/graphql/type/object.rb +26 -23
  127. data/lib/rails/graphql/type/scalar/any_scalar.rb +30 -0
  128. data/lib/rails/graphql/type/scalar/bigint_scalar.rb +5 -5
  129. data/lib/rails/graphql/type/scalar/binary_scalar.rb +3 -3
  130. data/lib/rails/graphql/type/scalar/boolean_scalar.rb +8 -8
  131. data/lib/rails/graphql/type/scalar/date_scalar.rb +3 -3
  132. data/lib/rails/graphql/type/scalar/date_time_scalar.rb +3 -3
  133. data/lib/rails/graphql/type/scalar/decimal_scalar.rb +3 -3
  134. data/lib/rails/graphql/type/scalar/float_scalar.rb +5 -5
  135. data/lib/rails/graphql/type/scalar/id_scalar.rb +6 -5
  136. data/lib/rails/graphql/type/scalar/int_scalar.rb +6 -5
  137. data/lib/rails/graphql/type/scalar/json_scalar.rb +39 -0
  138. data/lib/rails/graphql/type/scalar/string_scalar.rb +18 -4
  139. data/lib/rails/graphql/type/scalar/time_scalar.rb +5 -5
  140. data/lib/rails/graphql/type/scalar.rb +25 -22
  141. data/lib/rails/graphql/type/union.rb +14 -16
  142. data/lib/rails/graphql/type.rb +34 -25
  143. data/lib/rails/graphql/type_map.rb +256 -164
  144. data/lib/rails/graphql/uri.rb +166 -0
  145. data/lib/rails/graphql/version.rb +15 -3
  146. data/lib/rails/graphql.rake +3 -0
  147. data/lib/rails/graphql.rb +85 -52
  148. data/lib/rails-graphql.rb +1 -1
  149. data/test/assets/en.yml +29 -0
  150. data/test/assets/introspection-mem.txt +1 -1
  151. data/test/assets/mem.gql +18 -45
  152. data/test/assets/mysql.gql +392 -0
  153. data/test/assets/sqlite.gql +21 -12
  154. data/test/assets/translate.gql +335 -0
  155. data/test/config.rb +18 -8
  156. data/test/graphql/schema_test.rb +12 -19
  157. data/test/graphql/source_test.rb +8 -75
  158. data/test/graphql/type/enum_test.rb +207 -203
  159. data/test/graphql/type/input_test.rb +14 -9
  160. data/test/graphql/type/interface_test.rb +4 -4
  161. data/test/graphql/type/scalar/any_scalar_test.rb +38 -0
  162. data/test/graphql/type/scalar/boolean_scalar_test.rb +6 -3
  163. data/test/graphql/type/scalar/json_scalar_test.rb +23 -0
  164. data/test/graphql/type_map_test.rb +51 -66
  165. data/test/graphql/type_test.rb +0 -19
  166. data/test/graphql_test.rb +1 -1
  167. data/test/integration/{authorization/authorization_test.rb → authorization_test.rb} +40 -14
  168. data/test/integration/config.rb +36 -3
  169. data/test/integration/customization_test.rb +39 -0
  170. data/test/integration/global_id_test.rb +99 -0
  171. data/test/integration/memory/star_wars_introspection_test.rb +24 -16
  172. data/test/integration/memory/star_wars_query_test.rb +54 -3
  173. data/test/integration/memory/star_wars_validation_test.rb +1 -1
  174. data/test/integration/mysql/star_wars_introspection_test.rb +25 -0
  175. data/test/integration/persisted_query_test.rb +87 -0
  176. data/test/integration/resolver_precedence_test.rb +154 -0
  177. data/test/integration/schemas/memory.rb +22 -7
  178. data/test/integration/schemas/mysql.rb +62 -0
  179. data/test/integration/schemas/sqlite.rb +21 -12
  180. data/test/integration/sqlite/star_wars_global_id_test.rb +83 -0
  181. data/test/integration/sqlite/star_wars_introspection_test.rb +10 -0
  182. data/test/integration/sqlite/star_wars_query_test.rb +14 -1
  183. data/test/integration/translate_test.rb +61 -0
  184. data/test/test_ext.rb +16 -13
  185. metadata +108 -157
  186. data/ext/depend +0 -3
  187. data/ext/graphqlparser/Ast.cpp +0 -346
  188. data/ext/graphqlparser/Ast.h +0 -1214
  189. data/ext/graphqlparser/AstNode.h +0 -36
  190. data/ext/graphqlparser/AstVisitor.h +0 -137
  191. data/ext/graphqlparser/GraphQLParser.cpp +0 -76
  192. data/ext/graphqlparser/GraphQLParser.h +0 -55
  193. data/ext/graphqlparser/JsonVisitor.cpp +0 -161
  194. data/ext/graphqlparser/JsonVisitor.cpp.inc +0 -456
  195. data/ext/graphqlparser/JsonVisitor.h +0 -121
  196. data/ext/graphqlparser/JsonVisitor.h.inc +0 -110
  197. data/ext/graphqlparser/VERSION +0 -1
  198. data/ext/graphqlparser/c/GraphQLAst.cpp +0 -324
  199. data/ext/graphqlparser/c/GraphQLAst.h +0 -180
  200. data/ext/graphqlparser/c/GraphQLAstForEachConcreteType.h +0 -44
  201. data/ext/graphqlparser/c/GraphQLAstNode.cpp +0 -25
  202. data/ext/graphqlparser/c/GraphQLAstNode.h +0 -33
  203. data/ext/graphqlparser/c/GraphQLAstToJSON.cpp +0 -21
  204. data/ext/graphqlparser/c/GraphQLAstToJSON.h +0 -24
  205. data/ext/graphqlparser/c/GraphQLAstVisitor.cpp +0 -55
  206. data/ext/graphqlparser/c/GraphQLAstVisitor.h +0 -53
  207. data/ext/graphqlparser/c/GraphQLParser.cpp +0 -35
  208. data/ext/graphqlparser/c/GraphQLParser.h +0 -54
  209. data/ext/graphqlparser/dump_json_ast.cpp +0 -48
  210. data/ext/graphqlparser/lexer.lpp +0 -324
  211. data/ext/graphqlparser/parser.ypp +0 -693
  212. data/ext/graphqlparser/parsergen/lexer.cpp +0 -2633
  213. data/ext/graphqlparser/parsergen/lexer.h +0 -528
  214. data/ext/graphqlparser/parsergen/location.hh +0 -189
  215. data/ext/graphqlparser/parsergen/parser.tab.cpp +0 -3300
  216. data/ext/graphqlparser/parsergen/parser.tab.hpp +0 -646
  217. data/ext/graphqlparser/parsergen/position.hh +0 -179
  218. data/ext/graphqlparser/parsergen/stack.hh +0 -156
  219. data/ext/graphqlparser/syntaxdefs.h +0 -19
  220. data/ext/libgraphqlparser/AstNode.h +0 -36
  221. data/ext/libgraphqlparser/CMakeLists.txt +0 -148
  222. data/ext/libgraphqlparser/CONTRIBUTING.md +0 -23
  223. data/ext/libgraphqlparser/GraphQLParser.cpp +0 -76
  224. data/ext/libgraphqlparser/GraphQLParser.h +0 -55
  225. data/ext/libgraphqlparser/JsonVisitor.cpp +0 -161
  226. data/ext/libgraphqlparser/JsonVisitor.h +0 -121
  227. data/ext/libgraphqlparser/LICENSE +0 -22
  228. data/ext/libgraphqlparser/README.clang-tidy +0 -7
  229. data/ext/libgraphqlparser/README.md +0 -84
  230. data/ext/libgraphqlparser/ast/ast.ast +0 -203
  231. data/ext/libgraphqlparser/ast/ast.py +0 -61
  232. data/ext/libgraphqlparser/ast/c.py +0 -100
  233. data/ext/libgraphqlparser/ast/c.pyc +0 -0
  234. data/ext/libgraphqlparser/ast/c_impl.py +0 -61
  235. data/ext/libgraphqlparser/ast/c_impl.pyc +0 -0
  236. data/ext/libgraphqlparser/ast/c_visitor_impl.py +0 -39
  237. data/ext/libgraphqlparser/ast/c_visitor_impl.pyc +0 -0
  238. data/ext/libgraphqlparser/ast/casing.py +0 -26
  239. data/ext/libgraphqlparser/ast/casing.pyc +0 -0
  240. data/ext/libgraphqlparser/ast/cxx.py +0 -197
  241. data/ext/libgraphqlparser/ast/cxx.pyc +0 -0
  242. data/ext/libgraphqlparser/ast/cxx_impl.py +0 -61
  243. data/ext/libgraphqlparser/ast/cxx_impl.pyc +0 -0
  244. data/ext/libgraphqlparser/ast/cxx_json_visitor_header.py +0 -42
  245. data/ext/libgraphqlparser/ast/cxx_json_visitor_header.pyc +0 -0
  246. data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.py +0 -80
  247. data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.pyc +0 -0
  248. data/ext/libgraphqlparser/ast/cxx_visitor.py +0 -64
  249. data/ext/libgraphqlparser/ast/cxx_visitor.pyc +0 -0
  250. data/ext/libgraphqlparser/ast/js.py +0 -65
  251. data/ext/libgraphqlparser/ast/license.py +0 -10
  252. data/ext/libgraphqlparser/ast/license.pyc +0 -0
  253. data/ext/libgraphqlparser/c/GraphQLAstNode.cpp +0 -25
  254. data/ext/libgraphqlparser/c/GraphQLAstNode.h +0 -33
  255. data/ext/libgraphqlparser/c/GraphQLAstToJSON.cpp +0 -21
  256. data/ext/libgraphqlparser/c/GraphQLAstToJSON.h +0 -24
  257. data/ext/libgraphqlparser/c/GraphQLAstVisitor.cpp +0 -55
  258. data/ext/libgraphqlparser/c/GraphQLAstVisitor.h +0 -53
  259. data/ext/libgraphqlparser/c/GraphQLParser.cpp +0 -35
  260. data/ext/libgraphqlparser/c/GraphQLParser.h +0 -54
  261. data/ext/libgraphqlparser/clang-tidy-all.sh +0 -3
  262. data/ext/libgraphqlparser/cmake/version.cmake +0 -16
  263. data/ext/libgraphqlparser/dump_json_ast.cpp +0 -48
  264. data/ext/libgraphqlparser/go/README.md +0 -20
  265. data/ext/libgraphqlparser/go/callbacks.go +0 -18
  266. data/ext/libgraphqlparser/go/gotest.go +0 -64
  267. data/ext/libgraphqlparser/lexer.lpp +0 -324
  268. data/ext/libgraphqlparser/libgraphqlparser.pc.in +0 -11
  269. data/ext/libgraphqlparser/parser.ypp +0 -693
  270. data/ext/libgraphqlparser/parsergen/lexer.cpp +0 -2633
  271. data/ext/libgraphqlparser/parsergen/lexer.h +0 -528
  272. data/ext/libgraphqlparser/parsergen/location.hh +0 -189
  273. data/ext/libgraphqlparser/parsergen/parser.tab.cpp +0 -3300
  274. data/ext/libgraphqlparser/parsergen/parser.tab.hpp +0 -646
  275. data/ext/libgraphqlparser/parsergen/position.hh +0 -179
  276. data/ext/libgraphqlparser/parsergen/stack.hh +0 -156
  277. data/ext/libgraphqlparser/python/CMakeLists.txt +0 -14
  278. data/ext/libgraphqlparser/python/README.md +0 -5
  279. data/ext/libgraphqlparser/python/example.py +0 -31
  280. data/ext/libgraphqlparser/syntaxdefs.h +0 -19
  281. data/ext/libgraphqlparser/test/BuildCAPI.c +0 -5
  282. data/ext/libgraphqlparser/test/CMakeLists.txt +0 -25
  283. data/ext/libgraphqlparser/test/JsonVisitorTests.cpp +0 -28
  284. data/ext/libgraphqlparser/test/ParserTests.cpp +0 -352
  285. data/ext/libgraphqlparser/test/kitchen-sink.graphql +0 -59
  286. data/ext/libgraphqlparser/test/kitchen-sink.json +0 -1
  287. data/ext/libgraphqlparser/test/schema-kitchen-sink.graphql +0 -78
  288. data/ext/libgraphqlparser/test/schema-kitchen-sink.json +0 -1
  289. data/ext/libgraphqlparser/test/valgrind.supp +0 -33
  290. data/ext/version.cpp +0 -21
  291. data/lib/graphqlparser.so +0 -0
  292. data/lib/rails/graphql/native/functions.rb +0 -38
  293. data/lib/rails/graphql/native/location.rb +0 -41
  294. data/lib/rails/graphql/native/pointers.rb +0 -23
  295. data/lib/rails/graphql/native/visitor.rb +0 -349
  296. data/lib/rails/graphql/native.rb +0 -56
  297. data/test/integration/schemas/authorization.rb +0 -12
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module GraphQL
5
+ # Based on:
6
+ # SELECT DISTINCT data_type FROM information_schema.columns;
7
+ # And https://www.mysqltutorial.org/mysql-data-types.aspx
8
+ type_map.register_alias 'mysql:varchar', :string
9
+ type_map.register_alias 'mysql:bit', :bool
10
+ type_map.register_alias 'mysql:int', :int
11
+ type_map.register_alias 'mysql:bigint', :bigint
12
+ type_map.register_alias 'mysql:json', :json
13
+ type_map.register_alias 'mysql:date', :date
14
+ type_map.register_alias 'mysql:timestamp', :date_time
15
+ type_map.register_alias 'mysql:binary', :binary
16
+ type_map.register_alias 'mysql:float', :float
17
+ type_map.register_alias 'mysql:decimal', :decimal
18
+ type_map.register_alias 'mysql:time', :time
19
+
20
+ type_map.register_alias 'mysql:set', 'mysql:varchar'
21
+ type_map.register_alias 'mysql:text', 'mysql:varchar'
22
+ type_map.register_alias 'mysql:enum', 'mysql:varchar'
23
+ type_map.register_alias 'mysql:char', 'mysql:varchar'
24
+ type_map.register_alias 'mysql:tinytext', 'mysql:text'
25
+ type_map.register_alias 'mysql:mediumtext', 'mysql:text'
26
+ type_map.register_alias 'mysql:longtext', 'mysql:text'
27
+ type_map.register_alias 'mysql:datetime', 'mysql:timestamp'
28
+ type_map.register_alias 'mysql:varbinary', 'mysql:binary'
29
+ type_map.register_alias 'mysql:blob', 'mysql:binary'
30
+ type_map.register_alias 'mysql:tinyblob', 'mysql:blob'
31
+ type_map.register_alias 'mysql:mediumblob', 'mysql:blob'
32
+ type_map.register_alias 'mysql:longblob', 'mysql:blob'
33
+ type_map.register_alias 'mysql:tinyint', 'mysql:int'
34
+ type_map.register_alias 'mysql:smallint', 'mysql:int'
35
+ type_map.register_alias 'mysql:mediumint', 'mysql:int'
36
+ type_map.register_alias 'mysql:double', 'mysql:float'
37
+
38
+ module MySQL
39
+ module SourceMethods
40
+ protected
41
+
42
+ def mysql_attributes
43
+ model.columns_hash.each_value do |column|
44
+ next yield(column.name, find_type!(:id)) if id_columns.include?(column.name)
45
+
46
+ base_type, size = column.sql_type_metadata.sql_type.split(/(\(\d+\))/)
47
+ type_name = base_type.end_with?('int') && size == '(1)' ? 'bit' : base_type
48
+
49
+ type = find_type!("mysql:#{type_name}", fallback: :string)
50
+
51
+ yield(column.name, type, array: (base_type == 'set'))
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ Source::ActiveRecordSource.extend(MySQL::SourceMethods)
58
+ end
59
+ end
@@ -1,45 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Rails # :nodoc:
4
- module GraphQL # :nodoc:
3
+ module Rails
4
+ module GraphQL
5
5
  # Based on:
6
6
  # SELECT t.oid, t.typname, format_type(t.oid, NULL) AS sql_type
7
7
  # FROM pg_type t
8
8
  # WHERE typtype = 'b'
9
- # AND typcategory IN ('B', 'D', 'G', 'I', 'N', 'S', 'T', 'V')
9
+ # AND typcategory IN ('B', 'D', 'G', 'I', 'N', 'S', 'T', 'U', 'V')
10
10
  # AND typowner = 10;
11
- type_map.register_alias 'pg:boolean', :boolean
12
- type_map.register_alias 'pg:integer', :int
13
- type_map.register_alias 'pg:date', :date
14
-
15
- type_map.register_alias 'pg:char', :string
16
11
  type_map.register_alias 'pg:bigint', :bigint
17
- type_map.register_alias 'pg:smallint', :int
12
+ type_map.register_alias 'pg:boolean', :boolean
18
13
  type_map.register_alias 'pg:text', :string
19
- type_map.register_alias 'pg:oid', :int
14
+ type_map.register_alias 'pg:date', :date
15
+ type_map.register_alias 'pg:integer', :int
16
+ type_map.register_alias 'pg:json', :json
17
+ type_map.register_alias 'pg:numeric', :decimal
20
18
  type_map.register_alias 'pg:real', :float
21
- type_map.register_alias 'pg:double precision', :float
22
- type_map.register_alias 'pg:money', :decimal
23
- type_map.register_alias 'pg:character', :string
24
- type_map.register_alias 'pg:character varying', :string
25
- type_map.register_alias 'pg:timestamp', :date_time
26
- type_map.register_alias 'pg:timestamp without time zone', :date_time
27
- type_map.register_alias 'pg:timestamp with time zone', :date_time
28
19
  type_map.register_alias 'pg:time without time zone', :time
29
- type_map.register_alias 'pg:time with time zone', :time
30
- type_map.register_alias 'pg:numeric', :decimal
20
+ type_map.register_alias 'pg:timestamp', :date_time
21
+
22
+ type_map.register_alias 'pg:char', 'pg:text'
23
+ type_map.register_alias 'pg:smallint', 'pg:integer'
24
+ type_map.register_alias 'pg:oid', 'pg:integer'
25
+ type_map.register_alias 'pg:double precision', 'pg:real'
26
+ type_map.register_alias 'pg:money', 'pg:numeric'
27
+ type_map.register_alias 'pg:character', 'pg:text'
28
+ type_map.register_alias 'pg:character varying', 'pg:text'
29
+ type_map.register_alias 'pg:timestamp without time zone', 'pg:timestamp'
30
+ type_map.register_alias 'pg:timestamp with time zone', 'pg:timestamp'
31
+ type_map.register_alias 'pg:time with time zone', 'pg:time without time zone'
32
+ type_map.register_alias 'pg:jsonb', 'pg:json'
31
33
 
32
- module PG # :nodoc: all
34
+ module PG
33
35
  module SourceMethods
34
36
  protected
35
37
 
36
38
  def pg_attributes
37
39
  model.columns_hash.each_value do |column|
40
+ next yield(column.name, find_type!(:id)) if id_columns.include?(column.name)
41
+
38
42
  type_name = column.sql_type_metadata.sql_type
39
43
  type = find_type!('pg:' + type_name.gsub(/(\(|\[).*/, ''), fallback: :string)
40
44
 
41
- options = { array: type_name.include?('[]') }
42
- yield column.name, type, options
45
+ yield(column.name, type, array: type_name.include?('[]'))
43
46
  end
44
47
  end
45
48
  end
@@ -1,34 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Rails # :nodoc:
4
- module GraphQL # :nodoc:
3
+ module Rails
4
+ module GraphQL
5
5
 
6
6
  # Based on:
7
7
  # https://github.com/rails/rails/blob/v6.0.0/activerecord/lib/active_record/
8
8
  # connection_adapters/sqlite3_adapter.rb#L64
9
+ type_map.register_alias 'sqlite:binary', :binary
10
+ type_map.register_alias 'sqlite:boolean', :boolean
11
+ type_map.register_alias 'sqlite:date', :date
12
+ type_map.register_alias 'sqlite:datetime', :date_time
13
+ type_map.register_alias 'sqlite:decimal', :decimal
14
+ type_map.register_alias 'sqlite:float', :float
15
+ type_map.register_alias 'sqlite:integer', :int
16
+ type_map.register_alias 'sqlite:json', :json
9
17
  type_map.register_alias 'sqlite:primary_key', :id
10
18
  type_map.register_alias 'sqlite:string', :string
11
- type_map.register_alias 'sqlite:text', :string
12
- type_map.register_alias 'sqlite:integer', :int
13
- type_map.register_alias 'sqlite:float', :float
14
- type_map.register_alias 'sqlite:decimal', :decimal
15
- type_map.register_alias 'sqlite:datetime', :date_time
16
19
  type_map.register_alias 'sqlite:time', :time
17
- type_map.register_alias 'sqlite:date', :date
18
- type_map.register_alias 'sqlite:binary', :binary
19
- type_map.register_alias 'sqlite:boolean', :boolean
20
- # TODO: Add support to JSON type
21
- # type_map.register_alias 'pg:json', :json
22
20
 
23
- module SQLite # :nodoc: all
21
+ type_map.register_alias 'sqlite:varchar', 'sqlite:string'
22
+ type_map.register_alias 'sqlite:text', 'sqlite:string'
23
+
24
+ module SQLite
24
25
  module SourceMethods
25
26
  protected
26
27
 
27
28
  def sqlite_attributes
28
29
  model.columns_hash.each_value do |column|
30
+ next yield(column.name, find_type!(:id)) if id_columns.include?(column.name)
31
+
29
32
  type_name = column.sql_type_metadata.sql_type
30
33
  type = find_type!("sqlite:#{type_name}", fallback: :string)
31
- yield column.name, type
34
+ yield(column.name, type)
32
35
  end
33
36
  end
34
37
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module GraphQL
5
+ module Alternative
6
+ # = GraphQL Alternative Field Set
7
+ #
8
+ # A simple way to store fields that share some logic with each other
9
+ class FieldSet
10
+ extend Helpers::WithNamespace
11
+ extend Helpers::WithFields
12
+
13
+ include Helpers::Instantiable
14
+
15
+ self.field_type = Field::OutputField
16
+ self.valid_field_types = Type::Object.valid_field_types
17
+
18
+ def self.inspect
19
+ +"#<#{self.class.name} @fields=#{fields.inspect}>"
20
+ end
21
+ end
22
+
23
+ # = GraphQL Alternative Mutation Set
24
+ #
25
+ # Same as a +FieldSet+ but for mutation fields
26
+ MutationSet = Class.new(FieldSet)
27
+ MutationSet.field_type = Field::MutationField
28
+
29
+ # = GraphQL Alternative Subscription Set
30
+ #
31
+ # Same as a +FieldSet+ but for subscription fields
32
+ SubscriptionSet = Class.new(FieldSet)
33
+ SubscriptionSet.field_type = Field::SubscriptionField
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module GraphQL
5
+ # = GraphQL Alternative Mutation
6
+ #
7
+ # Same as it's parent class, but for mutations
8
+ class Alternative::Mutation < Alternative::Query
9
+ redefine_singleton_method(:type_field_class) { :mutation }
10
+ self.abstract = true
11
+
12
+ class << self
13
+ delegate :perform, to: :@field, allow_nil: true
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module GraphQL
5
+ # = GraphQL Alternative Query
6
+ #
7
+ # This object acts like a field, but is organized as an object for extended
8
+ # resolvers or really complex fields.
9
+ class Alternative::Query
10
+ extend Helpers::WithNamespace
11
+ include Helpers::Instantiable
12
+
13
+ # An abstract class will not have its field imported
14
+ class_attribute :abstract, instance_accessor: false, default: false
15
+ self.abstract = true
16
+
17
+ class << self
18
+ delegate :gql_name, :to_sym, :desc, :argument, :ref_argument, :id_argument,
19
+ :use, :internal?, :disabled?, :enabled?, :disable!, :enable!, :rename!,
20
+ :authorize, :on, :description=, :description, to: :field
21
+
22
+ # Returns the type of the field class
23
+ def type_field_class
24
+ :query
25
+ end
26
+
27
+ # Alias does not work because of the override
28
+ def i18n_scope(*)
29
+ type_field_class
30
+ end
31
+
32
+ # Stores the underlying field of the object
33
+ def field
34
+ return @field if defined?(@field)
35
+ return define_field unless superclass.instance_variable_defined?(:@field)
36
+ import_field(superclass.field)
37
+ end
38
+
39
+ def inspect
40
+ defined?(@field) ? @field.inspect : super
41
+ end
42
+
43
+ protected
44
+
45
+ # Mark the given class to be pending of registration
46
+ def inherited(subclass)
47
+ subclass.abstract = false
48
+ super if defined? super
49
+ end
50
+
51
+ # Create a new field for the class
52
+ def define_field(field_name = nil, type = :any, **xargs, &blcok)
53
+ field_name ||= anonymous? ? '_anonymous' : begin
54
+ type_module = type_field_class.to_s.classify.pluralize
55
+ user_name = name.split(+"#{type_module}::")[1]
56
+ user_name ||= name.delete_prefix('GraphQL::')
57
+ user_name.tr(':', '')
58
+ end
59
+
60
+ # Save the generated field ensuring the owner
61
+ @field = field_class.new(field_name, type, **xargs, owner: self, &blcok)
62
+ end
63
+
64
+ # Import the field from a given source
65
+ def import_field(other_field, **xargs, &blcok)
66
+ @field = other_field.to_proxy(**xargs, owner: self, &blcok)
67
+ end
68
+
69
+ # Change the return type of the field
70
+ def returns(type, **xargs)
71
+ full = xargs.fetch(:full, false)
72
+ null = full ? false : xargs.fetch(:null, true)
73
+ array = full ? true : xargs.fetch(:array, false)
74
+ nullable = full ? false : xargs.fetch(:nullable, true)
75
+
76
+ field.send(:assign_type, type)
77
+ field.instance_variable_set(:@null, null)
78
+ field.instance_variable_set(:@array, array)
79
+ field.instance_variable_set(:@nullable, nullable)
80
+ end
81
+
82
+ private
83
+
84
+ # Return the class of the underlying field
85
+ def field_class
86
+ return @field.class if defined?(@field)
87
+ list = Helpers::WithSchemaFields::TYPE_FIELD_CLASS
88
+ GraphQL::Field.const_get(list[type_field_class])
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module GraphQL
5
+ # = GraphQL Alternative Subscription
6
+ #
7
+ # Same as it's parent class, but for subscription
8
+ class Alternative::Subscription < Alternative::Query
9
+ redefine_singleton_method(:type_field_class) { :subscription }
10
+ self.abstract = true
11
+
12
+ class << self
13
+ delegate :scope, :trigger, to: :@field, allow_nil: true
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module GraphQL
5
+ # Several alternatives to declare GraphQL objects
6
+ module Alternative
7
+ extend ActiveSupport::Autoload
8
+
9
+ autoload :Query
10
+ autoload :Mutation
11
+ autoload :Subscription
12
+
13
+ autoload_at "#{__dir__}/alternative/field_set" do
14
+ autoload :FieldSet
15
+ autoload :MutationSet
16
+ autoload :SubscriptionSet
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Rails # :nodoc:
4
- module GraphQL # :nodoc:
3
+ module Rails
4
+ module GraphQL
5
5
  # = GraphQL Argument
6
6
  #
7
7
  # This represents an item from the ArgumentsDefinition, which was supposed
@@ -31,6 +31,7 @@ module Rails # :nodoc:
31
31
  # (defaults to nil).
32
32
  class Argument
33
33
  include Helpers::WithValidator
34
+ include Helpers::WithDescription
34
35
 
35
36
  # TODO: When arguments are attached to output fields they can have
36
37
  # directives so add this possibility
@@ -67,7 +68,8 @@ module Rails # :nodoc:
67
68
  @nullable = full ? false : nullable
68
69
 
69
70
  @default = default
70
- @desc = desc&.strip_heredoc&.chomp
71
+ @default = deserialize(@default) if @default.is_a?(::GQLParser::Token)
72
+ self.description = desc
71
73
  end
72
74
 
73
75
  def initialize_copy(*)
@@ -114,14 +116,9 @@ module Rails # :nodoc:
114
116
  !!@nullable
115
117
  end
116
118
 
117
- # Return the description of the argument
118
- def description
119
- @desc
120
- end
121
-
122
- # Checks if a description was provided
123
- def description?
124
- !!@desc
119
+ # Override to add the kind
120
+ def description(namespace = nil, *)
121
+ super(namespace || owner.try(:namespaces), :argument)
125
122
  end
126
123
 
127
124
  # Checks if a given default value was provided
@@ -149,7 +146,7 @@ module Rails # :nodoc:
149
146
 
150
147
  # Turn the given value into a ruby object through deserialization
151
148
  def deserialize(value = nil)
152
- value = @default if value.nil?
149
+ value = as_json if value.nil?
153
150
 
154
151
  return if value.nil?
155
152
  return type_klass.deserialize(value) unless array?
@@ -174,19 +171,19 @@ module Rails # :nodoc:
174
171
  def validate!(*)
175
172
  super if defined? super
176
173
 
177
- raise NameError, <<~MSG.squish if gql_name.start_with?('__')
174
+ raise NameError, (+<<~MSG).squish if gql_name.start_with?('__')
178
175
  The name "#{gql_name}" is invalid. Argument names cannot start with "__".
179
176
  MSG
180
177
 
181
- raise ArgumentError, <<~MSG.squish unless type_klass.is_a?(Module)
178
+ raise ArgumentError, (+<<~MSG).squish unless type_klass.is_a?(Module)
182
179
  Unable to find the "#{type.inspect}" input type on GraphQL context.
183
180
  MSG
184
181
 
185
- raise ArgumentError, <<~MSG.squish unless type_klass.input_type?
182
+ raise ArgumentError, (+<<~MSG).squish unless type_klass.input_type?
186
183
  The "#{type_klass.gql_name}" is not a valid input type.
187
184
  MSG
188
185
 
189
- raise ArgumentError, <<~MSG.squish unless default.nil? || valid?(default)
186
+ raise ArgumentError, (+<<~MSG).squish unless default.nil? || valid?(as_json(default))
190
187
  The given default value "#{default.inspect}" is not valid for this argument.
191
188
  MSG
192
189
  end
@@ -198,14 +195,14 @@ module Rails # :nodoc:
198
195
 
199
196
  alias_method :&, :+
200
197
 
201
- def inspect # :nodoc:
202
- result = "#{name}: "
203
- result += '[' if array?
204
- result += type_klass.gql_name
205
- result += '!' if array? && !nullable?
206
- result += ']' if array?
207
- result += '!' unless null?
208
- result += " = #{to_hash.inspect}" if default_value?
198
+ def inspect
199
+ result = +"#{name}: "
200
+ result << '[' if array?
201
+ result << type_klass.gql_name
202
+ result << '!' if array? && !nullable?
203
+ result << ']' if array?
204
+ result << '!' unless null?
205
+ result << " = #{as_json.inspect}" if default_value?
209
206
  result
210
207
  end
211
208
 
@@ -1,12 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Rails # :nodoc:
4
- module GraphQL # :nodoc:
3
+ module Rails
4
+ module GraphQL
5
5
  # = Rails GraphQL Callback
6
6
  #
7
7
  # An extra powerfull proc that can handle way more situations than the
8
8
  # original block caller
9
9
  class Callback
10
+ EXCLUSIVE_ARGUMENT = :exclusive_callback
11
+
10
12
  attr_reader :event_name, :block, :target, :filters
11
13
 
12
14
  delegate :event_filters, to: :target
@@ -19,7 +21,7 @@ module Rails # :nodoc:
19
21
  end
20
22
 
21
23
  def initialize(target, event_name, *args, **xargs, &block)
22
- raise ::ArgumentError, <<~MSG.squish if block.nil? && !args.first.present?
24
+ raise ::ArgumentError, (+<<~MSG).squish if block.nil? && !args.first.present?
23
25
  Either provide a block or a method name when setting a #{event_name}
24
26
  callback on #{target.inspect}.
25
27
  MSG
@@ -27,7 +29,7 @@ module Rails # :nodoc:
27
29
  if block.nil?
28
30
  block = args.shift
29
31
  valid_format = block.is_a?(Symbol) || block.is_a?(Proc)
30
- raise ::ArgumentError, <<~MSG.squish unless valid_format
32
+ raise ::ArgumentError, (+<<~MSG).squish unless valid_format
31
33
  The given #{block.class.name} class is not a valid callback.
32
34
  MSG
33
35
  end
@@ -35,11 +37,13 @@ module Rails # :nodoc:
35
37
  @target = target
36
38
  @event_name = event_name
37
39
 
40
+ @exclusive = xargs.delete(EXCLUSIVE_ARGUMENT)
41
+ @exclusive = target.try(:default_exclusive?, event_name) if @exclusive.nil?
42
+ @exclusive = true if @exclusive.nil?
43
+
38
44
  @pre_args = args
39
45
  @pre_xargs = xargs.slice!(*event_filters.keys)
40
- @filters = xargs.map do |key, value|
41
- [key, event_filters[key][:sanitizer]&.call(value) || value]
42
- end.to_h
46
+ @filters = xargs
43
47
 
44
48
  @block = block
45
49
  end
@@ -54,10 +58,16 @@ module Rails # :nodoc:
54
58
  : call_proc(event, _callback_context, *args, **xargs)
55
59
  end
56
60
 
61
+ # Return if this event is exclusive, so that only the original source of
62
+ # the callback will be allowed to receive it
63
+ def exclusive?
64
+ @exclusive
65
+ end
66
+
57
67
  # Get a described source location for the callback
58
68
  def source_location
59
69
  block.is_a?(Proc) ? block.source_location : [
60
- "(symbolized-callback/#{target.inspect})",
70
+ +"(symbolized-callback/#{target.inspect})",
61
71
  block,
62
72
  ]
63
73
  end
@@ -80,10 +90,15 @@ module Rails # :nodoc:
80
90
 
81
91
  # Using the filters, check if the current callback can be executed
82
92
  def can_run?(event)
83
- filters.all? { |key, options| event_filters[key][:block].call(options, event) }
93
+ return false if exclusive? && !event.same_source?(target)
94
+
95
+ filters.all? do |key, options|
96
+ target.instance_exec(options, event, &event_filters[key])
97
+ end
84
98
  end
85
99
 
86
100
  # Call the callback block as a symbol
101
+ # TODO: Maybe black calling non-public events
87
102
  def call_symbol(event, *args, **xargs)
88
103
  event.on_instance(owner) do |instance|
89
104
  block = instance.method(@block)
@@ -1,6 +1,10 @@
1
- module Rails # :nodoc:
2
- module GraphQL # :nodoc:
3
- module Collectors # :nodoc:
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module GraphQL
5
+ module Collectors
6
+ # = GraphQL Hash Collector
7
+ #
4
8
  # This collector helps building a JSON response using the hash approach,
5
9
  # where the value is kept as an hash and later turn into a string
6
10
  class HashCollector
@@ -24,7 +28,7 @@ module Rails # :nodoc:
24
28
 
25
29
  # Add the given +value+ to the given +key+.
26
30
  def add(key, value)
27
- @data.is_a?(Array) ? @data << value : @data[key.to_s] = value
31
+ @data.is_a?(::Array) ? @data << value : @data[key.to_s] = value
28
32
  end
29
33
 
30
34
  alias safe_add add
@@ -36,7 +40,7 @@ module Rails # :nodoc:
36
40
 
37
41
  # Mark the start of a new element on the array.
38
42
  def next
39
- return unless @stack.last.is_a?(Array)
43
+ return unless @stack.last.is_a?(::Array)
40
44
  @stack.last << @data
41
45
  @data = {}
42
46
  end
@@ -45,7 +49,7 @@ module Rails # :nodoc:
45
49
  # request process
46
50
  def append_errors(errors)
47
51
  return if errors.empty?
48
- @data['errors'] = errors.to_a
52
+ @data['errors'] = errors.as_json
49
53
  end
50
54
 
51
55
  # Return the generated object
@@ -53,6 +57,8 @@ module Rails # :nodoc:
53
57
  @data
54
58
  end
55
59
 
60
+ alias as_json to_h
61
+
56
62
  # Generate the JSON string result
57
63
  def to_s
58
64
  GraphQL.config.encode_with_active_support? \
@@ -60,6 +66,8 @@ module Rails # :nodoc:
60
66
  : ::JSON.generate(@data)
61
67
  end
62
68
 
69
+ alias to_json to_s
70
+
63
71
  private
64
72
 
65
73
  # Start a new part of the collector. When set +as_array+, the result
@@ -1,11 +1,14 @@
1
- module Rails # :nodoc:
2
- module GraphQL # :nodoc:
3
- module Collectors # :nodoc:
4
- # This collector helps building a indented string
1
+ module Rails
2
+ module GraphQL
3
+ module Collectors
4
+ # = GraphQL Idented Collector
5
+ #
6
+ # This collector helps building a indented string, most used for
7
+ # displaying a GraphQL schema
5
8
  class IdentedCollector
6
9
  def initialize(initial = 0, size = 2, auto_eol: true)
7
10
  @size = size
8
- @val = [[initial, '']]
11
+ @val = [[initial, +'']]
9
12
  @auto_eol = auto_eol
10
13
  end
11
14
 
@@ -50,13 +53,13 @@ module Rails # :nodoc:
50
53
 
51
54
  def indent
52
55
  return @val.last[0] += @size if blank?
53
- @val << [last_ident + @size, '']
56
+ @val << [last_ident + @size, +'']
54
57
  self
55
58
  end
56
59
 
57
60
  def unindent
58
61
  return @val.last[0] -= @size if blank?
59
- @val << [last_ident - @size, '']
62
+ @val << [last_ident - @size, +'']
60
63
  self
61
64
  end
62
65