rails-graphql 0.2.1 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (315) 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 +631 -0
  6. data/ext/gql_parser.h +21 -0
  7. data/ext/shared.c +477 -0
  8. data/ext/shared.h +177 -0
  9. data/lib/generators/graphql/channel_generator.rb +27 -0
  10. data/lib/generators/graphql/controller_generator.rb +9 -4
  11. data/lib/generators/graphql/install_generator.rb +49 -0
  12. data/lib/generators/graphql/schema_generator.rb +9 -4
  13. data/lib/generators/graphql/templates/channel.erb +7 -0
  14. data/lib/generators/graphql/templates/config.rb +97 -0
  15. data/lib/generators/graphql/templates/controller.erb +2 -0
  16. data/lib/generators/graphql/templates/schema.erb +5 -3
  17. data/lib/gql_parser.so +0 -0
  18. data/lib/rails/graphql/adapters/mysql_adapter.rb +59 -0
  19. data/lib/rails/graphql/adapters/pg_adapter.rb +25 -22
  20. data/lib/rails/graphql/adapters/sqlite_adapter.rb +17 -14
  21. data/lib/rails/graphql/alternative/field_set.rb +48 -0
  22. data/lib/rails/graphql/alternative/mutation.rb +17 -0
  23. data/lib/rails/graphql/alternative/query.rb +98 -0
  24. data/lib/rails/graphql/alternative/subscription.rb +18 -0
  25. data/lib/rails/graphql/alternative.rb +20 -0
  26. data/lib/rails/graphql/argument.rb +25 -26
  27. data/lib/rails/graphql/callback.rb +30 -14
  28. data/lib/rails/graphql/collectors/hash_collector.rb +26 -7
  29. data/lib/rails/graphql/collectors/idented_collector.rb +10 -7
  30. data/lib/rails/graphql/collectors/json_collector.rb +43 -17
  31. data/lib/rails/graphql/collectors.rb +4 -4
  32. data/lib/rails/graphql/config.rb +154 -23
  33. data/lib/rails/graphql/directive/cached_directive.rb +33 -0
  34. data/lib/rails/graphql/directive/deprecated_directive.rb +10 -10
  35. data/lib/rails/graphql/directive/include_directive.rb +4 -4
  36. data/lib/rails/graphql/directive/skip_directive.rb +4 -4
  37. data/lib/rails/graphql/directive/specified_by_directive.rb +24 -0
  38. data/lib/rails/graphql/directive.rb +134 -73
  39. data/lib/rails/graphql/errors.rb +33 -4
  40. data/lib/rails/graphql/event.rb +21 -9
  41. data/lib/rails/graphql/field/authorized_field.rb +17 -6
  42. data/lib/rails/graphql/field/input_field.rb +8 -12
  43. data/lib/rails/graphql/field/mutation_field.rb +43 -9
  44. data/lib/rails/graphql/field/output_field.rb +112 -12
  45. data/lib/rails/graphql/field/proxied_field.rb +35 -26
  46. data/lib/rails/graphql/field/resolved_field.rb +27 -25
  47. data/lib/rails/graphql/field/scoped_config.rb +10 -4
  48. data/lib/rails/graphql/field/subscription_field.rb +123 -0
  49. data/lib/rails/graphql/field/typed_field.rb +69 -24
  50. data/lib/rails/graphql/field.rb +89 -74
  51. data/lib/rails/graphql/global_id.rb +89 -0
  52. data/lib/rails/graphql/helpers/attribute_delegator.rb +5 -5
  53. data/lib/rails/graphql/helpers/inherited_collection/array.rb +51 -0
  54. data/lib/rails/graphql/helpers/inherited_collection/base.rb +45 -0
  55. data/lib/rails/graphql/helpers/inherited_collection/hash.rb +88 -0
  56. data/lib/rails/graphql/helpers/inherited_collection.rb +25 -76
  57. data/lib/rails/graphql/helpers/instantiable.rb +15 -0
  58. data/lib/rails/graphql/helpers/leaf_from_ar.rb +7 -7
  59. data/lib/rails/graphql/helpers/registerable.rb +44 -62
  60. data/lib/rails/graphql/helpers/unregisterable.rb +16 -0
  61. data/lib/rails/graphql/helpers/with_arguments.rb +33 -28
  62. data/lib/rails/graphql/helpers/with_assignment.rb +6 -6
  63. data/lib/rails/graphql/helpers/with_callbacks.rb +28 -11
  64. data/lib/rails/graphql/helpers/with_description.rb +73 -0
  65. data/lib/rails/graphql/helpers/with_directives.rb +58 -30
  66. data/lib/rails/graphql/helpers/with_events.rb +22 -23
  67. data/lib/rails/graphql/helpers/with_fields.rb +86 -26
  68. data/lib/rails/graphql/helpers/with_global_id.rb +22 -0
  69. data/lib/rails/graphql/helpers/with_name.rb +44 -0
  70. data/lib/rails/graphql/helpers/with_namespace.rb +7 -4
  71. data/lib/rails/graphql/helpers/with_owner.rb +8 -7
  72. data/lib/rails/graphql/helpers/with_schema_fields.rb +162 -56
  73. data/lib/rails/graphql/helpers/with_validator.rb +9 -9
  74. data/lib/rails/graphql/helpers.rb +10 -3
  75. data/lib/rails/graphql/introspection.rb +43 -36
  76. data/lib/rails/graphql/railtie.rb +89 -33
  77. data/lib/rails/graphql/railties/app/base_channel.rb +10 -0
  78. data/lib/rails/graphql/railties/app/base_controller.rb +12 -0
  79. data/lib/rails/graphql/railties/app/views/_cable.js.erb +56 -0
  80. data/lib/rails/graphql/railties/app/views/_fetch.js.erb +20 -0
  81. data/lib/rails/graphql/railties/app/views/graphiql.html.erb +101 -0
  82. data/lib/rails/graphql/railties/base_generator.rb +5 -17
  83. data/lib/rails/graphql/railties/channel.rb +157 -0
  84. data/lib/rails/graphql/railties/controller.rb +91 -25
  85. data/lib/rails/graphql/railties/controller_runtime.rb +5 -5
  86. data/lib/rails/graphql/railties/log_subscriber.rb +81 -14
  87. data/lib/rails/graphql/request/arguments.rb +26 -50
  88. data/lib/rails/graphql/request/backtrace.rb +212 -0
  89. data/lib/rails/graphql/request/component/field.rb +98 -70
  90. data/lib/rails/graphql/request/component/fragment.rb +80 -26
  91. data/lib/rails/graphql/request/component/operation/subscription.rb +162 -4
  92. data/lib/rails/graphql/request/component/operation.rb +73 -34
  93. data/lib/rails/graphql/request/component/spread.rb +79 -27
  94. data/lib/rails/graphql/request/component/typename.rb +28 -13
  95. data/lib/rails/graphql/request/component.rb +77 -36
  96. data/lib/rails/graphql/request/context.rb +19 -9
  97. data/lib/rails/graphql/request/errors.rb +16 -6
  98. data/lib/rails/graphql/request/event.rb +23 -8
  99. data/lib/rails/graphql/request/helpers/directives.rb +69 -27
  100. data/lib/rails/graphql/request/helpers/selection_set.rb +57 -25
  101. data/lib/rails/graphql/request/helpers/value_writers.rb +24 -19
  102. data/lib/rails/graphql/request/prepared_data.rb +100 -0
  103. data/lib/rails/graphql/request/steps/authorizable.rb +24 -14
  104. data/lib/rails/graphql/request/steps/organizable.rb +111 -49
  105. data/lib/rails/graphql/request/steps/{prepareable.rb → preparable.rb} +21 -8
  106. data/lib/rails/graphql/request/steps/{resolveable.rb → resolvable.rb} +16 -7
  107. data/lib/rails/graphql/request/strategy/cached_strategy.rb +64 -0
  108. data/lib/rails/graphql/request/strategy/dynamic_instance.rb +6 -6
  109. data/lib/rails/graphql/request/strategy/multi_query_strategy.rb +6 -13
  110. data/lib/rails/graphql/request/strategy/sequenced_strategy.rb +9 -9
  111. data/lib/rails/graphql/request/strategy.rb +147 -77
  112. data/lib/rails/graphql/request/subscription.rb +82 -0
  113. data/lib/rails/graphql/request.rb +353 -104
  114. data/lib/rails/graphql/schema.rb +251 -106
  115. data/lib/rails/graphql/shortcuts.rb +33 -8
  116. data/lib/rails/graphql/source/active_record/builders.rb +64 -51
  117. data/lib/rails/graphql/source/active_record_source.rb +158 -82
  118. data/lib/rails/graphql/source/base.rb +83 -0
  119. data/lib/rails/graphql/source/builder.rb +115 -0
  120. data/lib/rails/graphql/source/scoped_arguments.rb +39 -21
  121. data/lib/rails/graphql/source.rb +90 -228
  122. data/lib/rails/graphql/subscription/provider/action_cable.rb +113 -0
  123. data/lib/rails/graphql/subscription/provider/base.rb +192 -0
  124. data/lib/rails/graphql/subscription/provider.rb +18 -0
  125. data/lib/rails/graphql/subscription/store/base.rb +141 -0
  126. data/lib/rails/graphql/subscription/store/memory.rb +136 -0
  127. data/lib/rails/graphql/subscription/store.rb +19 -0
  128. data/lib/rails/graphql/subscription.rb +17 -0
  129. data/lib/rails/graphql/to_gql.rb +29 -32
  130. data/lib/rails/graphql/type/creator.rb +196 -0
  131. data/lib/rails/graphql/type/enum/directive_location_enum.rb +11 -11
  132. data/lib/rails/graphql/type/enum/type_kind_enum.rb +3 -3
  133. data/lib/rails/graphql/type/enum.rb +44 -50
  134. data/lib/rails/graphql/type/input.rb +92 -25
  135. data/lib/rails/graphql/type/interface.rb +29 -28
  136. data/lib/rails/graphql/type/object/directive_object.rb +10 -9
  137. data/lib/rails/graphql/type/object/enum_value_object.rb +3 -3
  138. data/lib/rails/graphql/type/object/field_object.rb +24 -6
  139. data/lib/rails/graphql/type/object/input_value_object.rb +6 -7
  140. data/lib/rails/graphql/type/object/schema_object.rb +5 -8
  141. data/lib/rails/graphql/type/object/type_object.rb +62 -25
  142. data/lib/rails/graphql/type/object.rb +34 -26
  143. data/lib/rails/graphql/type/scalar/any_scalar.rb +30 -0
  144. data/lib/rails/graphql/type/scalar/bigint_scalar.rb +5 -5
  145. data/lib/rails/graphql/type/scalar/binary_scalar.rb +5 -3
  146. data/lib/rails/graphql/type/scalar/boolean_scalar.rb +8 -8
  147. data/lib/rails/graphql/type/scalar/date_scalar.rb +5 -3
  148. data/lib/rails/graphql/type/scalar/date_time_scalar.rb +5 -3
  149. data/lib/rails/graphql/type/scalar/decimal_scalar.rb +5 -3
  150. data/lib/rails/graphql/type/scalar/float_scalar.rb +5 -5
  151. data/lib/rails/graphql/type/scalar/id_scalar.rb +6 -5
  152. data/lib/rails/graphql/type/scalar/int_scalar.rb +6 -5
  153. data/lib/rails/graphql/type/scalar/json_scalar.rb +41 -0
  154. data/lib/rails/graphql/type/scalar/string_scalar.rb +18 -4
  155. data/lib/rails/graphql/type/scalar/time_scalar.rb +8 -6
  156. data/lib/rails/graphql/type/scalar.rb +26 -23
  157. data/lib/rails/graphql/type/union.rb +21 -18
  158. data/lib/rails/graphql/type.rb +43 -26
  159. data/lib/rails/graphql/type_map.rb +268 -165
  160. data/lib/rails/graphql/uri.rb +167 -0
  161. data/lib/rails/graphql/version.rb +19 -3
  162. data/lib/rails/graphql.rake +3 -0
  163. data/lib/rails/graphql.rb +91 -56
  164. data/lib/rails-graphql.rb +1 -1
  165. data/test/assets/en.yml +29 -0
  166. data/test/assets/introspection-mem.txt +1 -1
  167. data/test/assets/introspection.gql +2 -0
  168. data/test/assets/mem.gql +86 -99
  169. data/test/assets/mysql.gql +406 -0
  170. data/test/assets/sqlite.gql +96 -73
  171. data/test/assets/translate.gql +346 -0
  172. data/test/config.rb +19 -8
  173. data/test/graphql/schema_test.rb +14 -50
  174. data/test/graphql/source_test.rb +8 -85
  175. data/test/graphql/type/enum_test.rb +207 -203
  176. data/test/graphql/type/input_test.rb +14 -9
  177. data/test/graphql/type/interface_test.rb +12 -9
  178. data/test/graphql/type/object_test.rb +8 -2
  179. data/test/graphql/type/scalar/any_scalar_test.rb +38 -0
  180. data/test/graphql/type/scalar/boolean_scalar_test.rb +6 -3
  181. data/test/graphql/type/scalar/json_scalar_test.rb +23 -0
  182. data/test/graphql/type_map_test.rb +63 -81
  183. data/test/graphql/type_test.rb +0 -19
  184. data/test/graphql_test.rb +1 -1
  185. data/test/integration/{authorization/authorization_test.rb → authorization_test.rb} +40 -14
  186. data/test/integration/config.rb +36 -3
  187. data/test/integration/customization_test.rb +39 -0
  188. data/test/integration/global_id_test.rb +99 -0
  189. data/test/integration/memory/star_wars_introspection_test.rb +24 -16
  190. data/test/integration/memory/star_wars_query_test.rb +54 -3
  191. data/test/integration/memory/star_wars_validation_test.rb +3 -3
  192. data/test/integration/mysql/star_wars_introspection_test.rb +25 -0
  193. data/test/integration/persisted_query_test.rb +87 -0
  194. data/test/integration/resolver_precedence_test.rb +154 -0
  195. data/test/integration/schemas/memory.rb +24 -10
  196. data/test/integration/schemas/mysql.rb +62 -0
  197. data/test/integration/schemas/sqlite.rb +21 -12
  198. data/test/integration/sqlite/star_wars_global_id_test.rb +89 -0
  199. data/test/integration/sqlite/star_wars_introspection_test.rb +10 -0
  200. data/test/integration/sqlite/star_wars_query_test.rb +14 -1
  201. data/test/integration/translate_test.rb +73 -0
  202. data/test/test_ext.rb +16 -13
  203. metadata +125 -161
  204. data/ext/depend +0 -3
  205. data/ext/graphqlparser/Ast.cpp +0 -346
  206. data/ext/graphqlparser/Ast.h +0 -1214
  207. data/ext/graphqlparser/AstNode.h +0 -36
  208. data/ext/graphqlparser/AstVisitor.h +0 -137
  209. data/ext/graphqlparser/GraphQLParser.cpp +0 -76
  210. data/ext/graphqlparser/GraphQLParser.h +0 -55
  211. data/ext/graphqlparser/JsonVisitor.cpp +0 -161
  212. data/ext/graphqlparser/JsonVisitor.cpp.inc +0 -456
  213. data/ext/graphqlparser/JsonVisitor.h +0 -121
  214. data/ext/graphqlparser/JsonVisitor.h.inc +0 -110
  215. data/ext/graphqlparser/VERSION +0 -1
  216. data/ext/graphqlparser/c/GraphQLAst.cpp +0 -324
  217. data/ext/graphqlparser/c/GraphQLAst.h +0 -180
  218. data/ext/graphqlparser/c/GraphQLAstForEachConcreteType.h +0 -44
  219. data/ext/graphqlparser/c/GraphQLAstNode.cpp +0 -25
  220. data/ext/graphqlparser/c/GraphQLAstNode.h +0 -33
  221. data/ext/graphqlparser/c/GraphQLAstToJSON.cpp +0 -21
  222. data/ext/graphqlparser/c/GraphQLAstToJSON.h +0 -24
  223. data/ext/graphqlparser/c/GraphQLAstVisitor.cpp +0 -55
  224. data/ext/graphqlparser/c/GraphQLAstVisitor.h +0 -53
  225. data/ext/graphqlparser/c/GraphQLParser.cpp +0 -35
  226. data/ext/graphqlparser/c/GraphQLParser.h +0 -54
  227. data/ext/graphqlparser/dump_json_ast.cpp +0 -48
  228. data/ext/graphqlparser/lexer.lpp +0 -324
  229. data/ext/graphqlparser/parser.ypp +0 -693
  230. data/ext/graphqlparser/parsergen/lexer.cpp +0 -2633
  231. data/ext/graphqlparser/parsergen/lexer.h +0 -528
  232. data/ext/graphqlparser/parsergen/location.hh +0 -189
  233. data/ext/graphqlparser/parsergen/parser.tab.cpp +0 -3300
  234. data/ext/graphqlparser/parsergen/parser.tab.hpp +0 -646
  235. data/ext/graphqlparser/parsergen/position.hh +0 -179
  236. data/ext/graphqlparser/parsergen/stack.hh +0 -156
  237. data/ext/graphqlparser/syntaxdefs.h +0 -19
  238. data/ext/libgraphqlparser/AstNode.h +0 -36
  239. data/ext/libgraphqlparser/CMakeLists.txt +0 -148
  240. data/ext/libgraphqlparser/CONTRIBUTING.md +0 -23
  241. data/ext/libgraphqlparser/GraphQLParser.cpp +0 -76
  242. data/ext/libgraphqlparser/GraphQLParser.h +0 -55
  243. data/ext/libgraphqlparser/JsonVisitor.cpp +0 -161
  244. data/ext/libgraphqlparser/JsonVisitor.h +0 -121
  245. data/ext/libgraphqlparser/LICENSE +0 -22
  246. data/ext/libgraphqlparser/README.clang-tidy +0 -7
  247. data/ext/libgraphqlparser/README.md +0 -84
  248. data/ext/libgraphqlparser/ast/ast.ast +0 -203
  249. data/ext/libgraphqlparser/ast/ast.py +0 -61
  250. data/ext/libgraphqlparser/ast/c.py +0 -100
  251. data/ext/libgraphqlparser/ast/c.pyc +0 -0
  252. data/ext/libgraphqlparser/ast/c_impl.py +0 -61
  253. data/ext/libgraphqlparser/ast/c_impl.pyc +0 -0
  254. data/ext/libgraphqlparser/ast/c_visitor_impl.py +0 -39
  255. data/ext/libgraphqlparser/ast/c_visitor_impl.pyc +0 -0
  256. data/ext/libgraphqlparser/ast/casing.py +0 -26
  257. data/ext/libgraphqlparser/ast/casing.pyc +0 -0
  258. data/ext/libgraphqlparser/ast/cxx.py +0 -197
  259. data/ext/libgraphqlparser/ast/cxx.pyc +0 -0
  260. data/ext/libgraphqlparser/ast/cxx_impl.py +0 -61
  261. data/ext/libgraphqlparser/ast/cxx_impl.pyc +0 -0
  262. data/ext/libgraphqlparser/ast/cxx_json_visitor_header.py +0 -42
  263. data/ext/libgraphqlparser/ast/cxx_json_visitor_header.pyc +0 -0
  264. data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.py +0 -80
  265. data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.pyc +0 -0
  266. data/ext/libgraphqlparser/ast/cxx_visitor.py +0 -64
  267. data/ext/libgraphqlparser/ast/cxx_visitor.pyc +0 -0
  268. data/ext/libgraphqlparser/ast/js.py +0 -65
  269. data/ext/libgraphqlparser/ast/license.py +0 -10
  270. data/ext/libgraphqlparser/ast/license.pyc +0 -0
  271. data/ext/libgraphqlparser/c/GraphQLAstNode.cpp +0 -25
  272. data/ext/libgraphqlparser/c/GraphQLAstNode.h +0 -33
  273. data/ext/libgraphqlparser/c/GraphQLAstToJSON.cpp +0 -21
  274. data/ext/libgraphqlparser/c/GraphQLAstToJSON.h +0 -24
  275. data/ext/libgraphqlparser/c/GraphQLAstVisitor.cpp +0 -55
  276. data/ext/libgraphqlparser/c/GraphQLAstVisitor.h +0 -53
  277. data/ext/libgraphqlparser/c/GraphQLParser.cpp +0 -35
  278. data/ext/libgraphqlparser/c/GraphQLParser.h +0 -54
  279. data/ext/libgraphqlparser/clang-tidy-all.sh +0 -3
  280. data/ext/libgraphqlparser/cmake/version.cmake +0 -16
  281. data/ext/libgraphqlparser/dump_json_ast.cpp +0 -48
  282. data/ext/libgraphqlparser/go/README.md +0 -20
  283. data/ext/libgraphqlparser/go/callbacks.go +0 -18
  284. data/ext/libgraphqlparser/go/gotest.go +0 -64
  285. data/ext/libgraphqlparser/lexer.lpp +0 -324
  286. data/ext/libgraphqlparser/libgraphqlparser.pc.in +0 -11
  287. data/ext/libgraphqlparser/parser.ypp +0 -693
  288. data/ext/libgraphqlparser/parsergen/lexer.cpp +0 -2633
  289. data/ext/libgraphqlparser/parsergen/lexer.h +0 -528
  290. data/ext/libgraphqlparser/parsergen/location.hh +0 -189
  291. data/ext/libgraphqlparser/parsergen/parser.tab.cpp +0 -3300
  292. data/ext/libgraphqlparser/parsergen/parser.tab.hpp +0 -646
  293. data/ext/libgraphqlparser/parsergen/position.hh +0 -179
  294. data/ext/libgraphqlparser/parsergen/stack.hh +0 -156
  295. data/ext/libgraphqlparser/python/CMakeLists.txt +0 -14
  296. data/ext/libgraphqlparser/python/README.md +0 -5
  297. data/ext/libgraphqlparser/python/example.py +0 -31
  298. data/ext/libgraphqlparser/syntaxdefs.h +0 -19
  299. data/ext/libgraphqlparser/test/BuildCAPI.c +0 -5
  300. data/ext/libgraphqlparser/test/CMakeLists.txt +0 -25
  301. data/ext/libgraphqlparser/test/JsonVisitorTests.cpp +0 -28
  302. data/ext/libgraphqlparser/test/ParserTests.cpp +0 -352
  303. data/ext/libgraphqlparser/test/kitchen-sink.graphql +0 -59
  304. data/ext/libgraphqlparser/test/kitchen-sink.json +0 -1
  305. data/ext/libgraphqlparser/test/schema-kitchen-sink.graphql +0 -78
  306. data/ext/libgraphqlparser/test/schema-kitchen-sink.json +0 -1
  307. data/ext/libgraphqlparser/test/valgrind.supp +0 -33
  308. data/ext/version.cpp +0 -21
  309. data/lib/graphqlparser.so +0 -0
  310. data/lib/rails/graphql/native/functions.rb +0 -38
  311. data/lib/rails/graphql/native/location.rb +0 -41
  312. data/lib/rails/graphql/native/pointers.rb +0 -23
  313. data/lib/rails/graphql/native/visitor.rb +0 -349
  314. data/lib/rails/graphql/native.rb +0 -56
  315. data/test/integration/schemas/authorization.rb +0 -12
data/ext/shared.c ADDED
@@ -0,0 +1,477 @@
1
+ #include "ruby.h"
2
+ #include "shared.h"
3
+
4
+ const char *GQL_VALUE_KEYWORDS[] = {
5
+ "true",
6
+ "false",
7
+ "null"
8
+ };
9
+
10
+ const char *GQL_EXECUTION_KEYWORDS[] = {
11
+ "query",
12
+ "mutation",
13
+ "subscription",
14
+ "fragment",
15
+ "on"
16
+ };
17
+
18
+ const char *GQL_DEFINITION_KEYWORDS[] = {
19
+ "schema",
20
+ "directive",
21
+ "enum",
22
+ "input",
23
+ "interface",
24
+ "scalar",
25
+ "type",
26
+ "union",
27
+ "extend",
28
+ "implements",
29
+ "repeatable"
30
+ };
31
+
32
+ /* INTERNAL HELPERS */
33
+ // Just a helper to print things on the console while testing/debugging
34
+ void gql_debug_print(const char *message)
35
+ {
36
+ rb_funcall(rb_mKernel, rb_intern("puts"), 1, rb_str_new2(message));
37
+ }
38
+
39
+ // Initialize a new scanner
40
+ struct gql_scanner gql_new_scanner(VALUE source)
41
+ {
42
+ char *doc = RSTRING_PTR(source);
43
+ struct gql_scanner scanner = {
44
+ .start_pos = 1, // Set to 1 just to begin different from the current position
45
+ .current_pos = 0,
46
+ .current_line = 1,
47
+ .last_ln_at = 0,
48
+ .current = doc[0],
49
+ .doc = doc};
50
+
51
+ return scanner;
52
+ }
53
+
54
+ // Returns the base index of the lexeme from where the upgrade should move from
55
+ enum gql_lexeme gql_upgrade_basis(const char *upgrade_from[])
56
+ {
57
+ if (*upgrade_from == *GQL_VALUE_KEYWORDS)
58
+ return gql_iv_true;
59
+ else if (*upgrade_from == *GQL_EXECUTION_KEYWORDS)
60
+ return gql_ie_query;
61
+ else if (*upgrade_from == *GQL_DEFINITION_KEYWORDS)
62
+ return gql_id_schema;
63
+ else
64
+ return gql_i_unknown;
65
+ }
66
+
67
+ // This checks if the identifier in the scanner should be upgraded to a keyword
68
+ enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *upgrade_from[])
69
+ {
70
+ unsigned long pos, len = GQL_SCAN_SIZE(scanner);
71
+ unsigned int valid = 0, i = 0;
72
+ const char *keyword;
73
+
74
+ // Check until it finds the end of the array
75
+ while ((keyword = upgrade_from[i]) != 0)
76
+ {
77
+ // Move ot the next item and check the current for different size
78
+ if(strlen(keyword) == len)
79
+ {
80
+ // We cannot use the normal strcomp because we are comparing a mid part of the string
81
+ for (pos = 0, valid = 1; valid == 1 && pos < len; pos++)
82
+ {
83
+ if (keyword[pos] != scanner->doc[scanner->start_pos + pos])
84
+ valid = 0;
85
+ }
86
+
87
+ // Only return if valid was kept as true
88
+ if (valid == 1) return gql_upgrade_basis(upgrade_from) + i;
89
+ }
90
+
91
+ // Move to the next index
92
+ i++;
93
+ }
94
+
95
+ // Return name if was not able to upgrade to a keyword
96
+ return gql_i_name;
97
+ }
98
+
99
+ /* SCANNER HELPERS */
100
+ enum gql_lexeme gql_read_name(struct gql_scanner *scanner)
101
+ {
102
+ // Read all the chars and digits
103
+ GQL_SCAN_WHILE(scanner, GQL_S_CHARACTER(scanner->current) || GQL_S_DIGIT(scanner->current));
104
+ return gql_i_name;
105
+ }
106
+
107
+ enum gql_lexeme gql_read_comment(struct gql_scanner *scanner)
108
+ {
109
+ // Move forward until it finds a new line, change the line indicator and return
110
+ GQL_SCAN_WHILE(scanner, scanner->current != '\n');
111
+ GQL_SCAN_NEW_LINE(scanner);
112
+ return gql_i_comment;
113
+ }
114
+
115
+ enum gql_lexeme gql_read_hash(struct gql_scanner *scanner)
116
+ {
117
+ // Start with 1 curly open and get the next
118
+ int curly_opens = 1;
119
+ GQL_SCAN_NEXT(scanner);
120
+
121
+ while (curly_opens > 0)
122
+ {
123
+ // EOF returns unknown, { adds to the open, } removes from the open, " reads as string
124
+ if (scanner->current == '\0')
125
+ return gql_i_unknown;
126
+ else if (scanner->current == '"' && gql_read_string(scanner, 0) != gql_iv_string)
127
+ return gql_i_unknown;
128
+ else if (scanner->current == '{')
129
+ curly_opens++;
130
+ else if (scanner->current == '}')
131
+ curly_opens--;
132
+ else if (scanner->current == '\n')
133
+ GQL_SCAN_NEW_LINE(scanner);
134
+
135
+ // Just move to the next char
136
+ GQL_SCAN_NEXT(scanner);
137
+ }
138
+
139
+ // Save the last position, move to the next and return as hash
140
+ return gql_iv_hash;
141
+ }
142
+
143
+ enum gql_lexeme gql_read_float(struct gql_scanner *scanner)
144
+ {
145
+ // If what made it get in here was an '.', then it can recurse to the exponent of a fraction
146
+ int at_fraction = scanner->current == '.';
147
+
148
+ // Skip the float mark and maybe
149
+ GQL_SCAN_NEXT(scanner);
150
+
151
+ // Skip the exponent sign if possible
152
+ if (!at_fraction && (scanner->current == '+' || scanner->current == '-'))
153
+ GQL_SCAN_NEXT(scanner);
154
+
155
+ // If the current char is not a digit, we have an unknown
156
+ if (!GQL_S_DIGIT(scanner->current)) return gql_i_unknown;
157
+ GQL_SCAN_NEXT(scanner);
158
+
159
+ // Read all the numbers
160
+ GQL_SCAN_WHILE(scanner, GQL_S_DIGIT(scanner->current));
161
+
162
+ // If it is at fraction and the next is an exponent marker, then recurse
163
+ if (at_fraction && (scanner->current == 'e' || scanner->current == 'E'))
164
+ return gql_read_float(scanner);
165
+
166
+ // Otherwise save the last position and just finish the float
167
+ return gql_iv_float;
168
+ }
169
+
170
+ enum gql_lexeme gql_read_number(struct gql_scanner *scanner)
171
+ {
172
+ // Pass over the negative sign
173
+ if (scanner->current == '-') GQL_SCAN_NEXT(scanner);
174
+
175
+ // If begins with zero, it can only be 0 or error
176
+ if (scanner->current == '0')
177
+ return (GQL_S_DIGIT(GQL_SCAN_LOOK(scanner, 1))) ? gql_i_unknown : gql_iv_integer;
178
+
179
+ // Read all the numbers
180
+ GQL_SCAN_WHILE(scanner, GQL_S_DIGIT(scanner->current));
181
+
182
+ // Save the last position and halt the process if it's not a float marker
183
+ return (GQL_S_FLOAT_MARK(scanner->current)) ? gql_read_float(scanner) : gql_iv_integer;
184
+ }
185
+
186
+ enum gql_lexeme gql_read_string(struct gql_scanner *scanner, int allow_heredoc)
187
+ {
188
+ int start_size, end_size = 0;
189
+ unsigned long start = scanner->current_pos;
190
+
191
+ // Read all the initial quotes and save the size
192
+ GQL_SCAN_WHILE(scanner, scanner->current == '"');
193
+ start_size = (int)(scanner->current_pos - start);
194
+
195
+ // 4, 5, or more than 6 means an invalid triple-quotes block
196
+ if (start_size == 4 || start_size == 5 || start_size > 6)
197
+ return gql_i_unknown;
198
+
199
+ // 3 but not accepting heredoc returns an unknown
200
+ if (allow_heredoc == 0 && start_size == 3)
201
+ return gql_i_unknown;
202
+
203
+ // 2 or 6 means empty string
204
+ if (start_size == 2 || start_size == 6)
205
+ return gql_iv_string;
206
+
207
+ // Read until the start and end number of quotes matches
208
+ while (start_size != end_size)
209
+ {
210
+ // If it is a quote, add to end and move ot the next
211
+ if (scanner->current == '"')
212
+ {
213
+ end_size++;
214
+ }
215
+ else
216
+ {
217
+ // Anything that is not a quote reset the end size
218
+ end_size = 0;
219
+
220
+ // If we get to the end of the file, return an unknown
221
+ if (scanner->current == '\0')
222
+ return gql_i_unknown;
223
+
224
+ // Make sure to mark any new lines
225
+ if (scanner->current == '\n')
226
+ GQL_SCAN_NEW_LINE(scanner);
227
+
228
+ // Skip one extra character, which means it is skipping the escaped char
229
+ if (scanner->current == '\\')
230
+ GQL_SCAN_NEXT(scanner);
231
+ }
232
+
233
+ // Move the cursor
234
+ GQL_SCAN_NEXT(scanner);
235
+ }
236
+
237
+ // Regardless if a quote comes next, this is now a valid string
238
+ return (start_size == 3) ? gql_iv_heredoc : gql_iv_string;
239
+ }
240
+
241
+ /* MOST IMPORTANT TOKEN READ FUNCTION */
242
+ void gql_next_lexeme(struct gql_scanner *scanner)
243
+ {
244
+ // Do not move forward if it is unknown
245
+ if (scanner->lexeme == gql_i_unknown)
246
+ return;
247
+
248
+ // Temporary save the end line and end column
249
+ GQL_SCAN_SET_END(scanner, 0);
250
+
251
+ // Skip everything that can be ignored
252
+ GQL_SCAN_WHILE(scanner, GQL_S_IGNORE(scanner->current));
253
+
254
+ // Mark where the new interesting thing has started
255
+ scanner->start_pos = scanner->current_pos;
256
+ scanner->begin_line = scanner->current_line;
257
+ scanner->begin_column = scanner->current_pos - scanner->last_ln_at;
258
+
259
+ // Find what might be the next interesting thing
260
+ if (scanner->current == '\0')
261
+ scanner->lexeme = gql_i_eof;
262
+ else if (GQL_S_CHARACTER(scanner->current))
263
+ scanner->lexeme = gql_read_name(scanner);
264
+ else if (scanner->current == '#')
265
+ scanner->lexeme = gql_read_comment(scanner);
266
+ else if (GQL_S_DIGIT(scanner->current) || scanner->current == '-')
267
+ scanner->lexeme = gql_read_number(scanner);
268
+ else if (scanner->current == '"')
269
+ scanner->lexeme = gql_read_string(scanner, 1);
270
+ else if (scanner->current == '[')
271
+ scanner->lexeme = gql_is_op_brack;
272
+ else if (scanner->current == '{')
273
+ scanner->lexeme = gql_is_op_curly;
274
+ else if (scanner->current == '}')
275
+ scanner->lexeme = gql_is_cl_curly;
276
+ else if (scanner->current == '(')
277
+ scanner->lexeme = gql_is_op_paren;
278
+ else if (scanner->current == ')')
279
+ scanner->lexeme = gql_is_cl_paren;
280
+ else if (scanner->current == ':')
281
+ scanner->lexeme = gql_is_colon;
282
+ else if (scanner->current == '=')
283
+ scanner->lexeme = gql_is_equal;
284
+ else if (scanner->current == '.')
285
+ scanner->lexeme = gql_is_period;
286
+ else if (scanner->current == '@')
287
+ scanner->lexeme = gql_i_directive;
288
+ else if (scanner->current == '$')
289
+ scanner->lexeme = gql_i_variable;
290
+ else
291
+ scanner->lexeme = gql_i_unknown;
292
+ }
293
+
294
+ // Skip all comment lexemes
295
+ void gql_next_lexeme_no_comments(struct gql_scanner *scanner)
296
+ {
297
+ do
298
+ {
299
+ gql_next_lexeme(scanner);
300
+ } while (scanner->lexeme == gql_i_comment);
301
+ }
302
+
303
+ /* TOKEN CLASS HELPERS AND METHODS */
304
+ // Simply add the type of the token and return self for simplicity
305
+ VALUE gql_set_token_type(VALUE self, const char *type)
306
+ {
307
+ rb_iv_set(self, "@type", ID2SYM(rb_intern(type)));
308
+ return self;
309
+ }
310
+
311
+ // Just simply format the string with the token prefix
312
+ VALUE gql_inspect_token(VALUE self)
313
+ {
314
+ VALUE text = rb_call_super(0, 0);
315
+
316
+ if (rb_ivar_defined(self, rb_intern("@type")) == Qfalse)
317
+ return rb_sprintf("<GQLParser::Token %" PRIsVALUE ">", text);
318
+
319
+ VALUE type = rb_iv_get(self, "@type");
320
+ return rb_sprintf("<GQLParser::Token [%" PRIsVALUE "] %" PRIsVALUE ">", type, text);
321
+ }
322
+
323
+ // Check if the token is of the given type
324
+ VALUE gql_token_of_type_check(VALUE self, VALUE other)
325
+ {
326
+ VALUE type = rb_iv_get(self, "@type");
327
+ return rb_equal(type, other);
328
+ }
329
+
330
+ // Add the token module to the object and assign its location information
331
+ VALUE gql_as_token(VALUE self, struct gql_scanner *scanner, int save_type)
332
+ {
333
+ // Initialize the instance
334
+ VALUE instance = rb_class_new_instance(1, &self, QLGParserToken);
335
+
336
+ // Add the location instance variables
337
+ int offset = scanner->begin_line == 1 ? 1 : 0;
338
+ rb_iv_set(instance, "@begin_line", ULONG2NUM(scanner->begin_line));
339
+ rb_iv_set(instance, "@begin_column", ULONG2NUM(scanner->begin_column + offset));
340
+
341
+ offset = scanner->end_line == 1 ? 1 : 0;
342
+ rb_iv_set(instance, "@end_line", ULONG2NUM(scanner->end_line));
343
+ rb_iv_set(instance, "@end_column", ULONG2NUM(scanner->end_column + offset));
344
+
345
+ // Check if it has to save the type
346
+ if (save_type == 1)
347
+ {
348
+ // This only covers value types
349
+ if (scanner->lexeme == gql_iv_integer)
350
+ gql_set_token_type(instance, "int");
351
+ else if (scanner->lexeme == gql_iv_float)
352
+ gql_set_token_type(instance, "float");
353
+ else if (scanner->lexeme == gql_iv_string)
354
+ gql_set_token_type(instance, "string");
355
+ else if (scanner->lexeme == gql_iv_true)
356
+ gql_set_token_type(instance, "boolean");
357
+ else if (scanner->lexeme == gql_iv_false)
358
+ gql_set_token_type(instance, "boolean");
359
+ else if (scanner->lexeme == gql_iv_enum)
360
+ gql_set_token_type(instance, "enum");
361
+ else if (scanner->lexeme == gql_iv_array)
362
+ gql_set_token_type(instance, "array");
363
+ else if (scanner->lexeme == gql_iv_hash)
364
+ gql_set_token_type(instance, "hash");
365
+ else if (scanner->lexeme == gql_iv_heredoc)
366
+ gql_set_token_type(instance, "heredoc");
367
+ }
368
+
369
+ // Return the token instance
370
+ return instance;
371
+ }
372
+
373
+ /* RUBY-BASED HELPERS */
374
+ // Creates a Ruby String from the scanner
375
+ VALUE gql_scanner_to_s(struct gql_scanner *scanner)
376
+ {
377
+ return rb_str_new(scanner->doc + scanner->start_pos, GQL_SCAN_SIZE(scanner));
378
+ }
379
+
380
+ // Same as the above, but already extend it to a parser token
381
+ VALUE gql_scanner_to_token(struct gql_scanner *scanner)
382
+ {
383
+ return gql_as_token(gql_scanner_to_s(scanner), scanner, 0);
384
+ }
385
+
386
+ // Goes over an array and grab all the elements
387
+ VALUE gql_array_to_rb(struct gql_scanner *scanner)
388
+ {
389
+ // Start the array and the temporary element
390
+ VALUE result = rb_ary_new();
391
+ VALUE element;
392
+
393
+ // Save the scan and grab the next char
394
+ GQL_SCAN_NEXT(scanner);
395
+
396
+ // Iterate until it finds the end of the array
397
+ while (scanner->current != ']')
398
+ {
399
+ // If we got to the end of the file and the array was not closed, then we have something wrong
400
+ if (scanner->current == '\0')
401
+ {
402
+ scanner->lexeme = gql_i_unknown;
403
+ return Qnil;
404
+ }
405
+
406
+ // Save the element as an rb token, because we may need the type of each element afterwards
407
+ element = gql_value_to_token(scanner, 0);
408
+
409
+ // If it found an unknown, then we bubble the problem up
410
+ if (scanner->lexeme == gql_i_unknown)
411
+ return Qnil;
412
+
413
+ // Add the value to the array and scan through everything ignorable
414
+ rb_ary_push(result, element);
415
+ GQL_SCAN_WHILE(scanner, GQL_S_IGNORE(scanner->current));
416
+ }
417
+
418
+ // Save where the array has actually ended, change the lexeme and return
419
+ GQL_SCAN_SET_END(scanner, 0);
420
+ scanner->lexeme = gql_iv_array;
421
+ return result;
422
+ }
423
+
424
+ // Turn the current lexeme into its proper ruby object
425
+ VALUE gql_value_to_rb(struct gql_scanner *scanner, int accept_var)
426
+ {
427
+ // EXPERIMENTAL! Skip all the comments
428
+ gql_next_lexeme_no_comments(scanner);
429
+
430
+ // If got a variable and accepts variables,
431
+ // then it's fine and it won't be resolved in here
432
+ if (accept_var == 1 && scanner->lexeme == gql_i_variable)
433
+ return Qnil;
434
+
435
+ // Make sure to save the end position of the value
436
+ GQL_SCAN_SET_END(scanner, 0);
437
+
438
+ // If it's a name, then it can be a keyword or a enum value
439
+ if (scanner->lexeme == gql_i_name)
440
+ {
441
+ scanner->lexeme = gql_name_to_keyword(scanner, GQL_VALUE_KEYWORDS);
442
+ if (scanner->lexeme == gql_iv_true)
443
+ return Qtrue;
444
+ else if (scanner->lexeme == gql_iv_false)
445
+ return Qfalse;
446
+ else if (scanner->lexeme == gql_iv_null)
447
+ return Qnil;
448
+ else
449
+ scanner->lexeme = gql_iv_enum;
450
+ }
451
+
452
+ // Dealing with an array is way more complex, because you have to turn each
453
+ // individual value as an rb value
454
+ if (scanner->lexeme == gql_is_op_brack)
455
+ return gql_array_to_rb(scanner);
456
+
457
+ // If it is a hash, then we can just read through it and later get as a string
458
+ if (scanner->lexeme == gql_is_op_curly)
459
+ scanner->lexeme = gql_read_hash(scanner);
460
+
461
+ // By getting here with a proper value, just return the string of it, which
462
+ // will be dealt in the request
463
+ if (GQL_I_VALUE(scanner->lexeme))
464
+ return gql_scanner_to_s(scanner);
465
+
466
+ // If it got to this point, then it's an unknown
467
+ scanner->lexeme = gql_i_unknown;
468
+ return Qnil;
469
+ }
470
+
471
+ // Same as the above, but already extend it to a parser token
472
+ // IMPORTANT! This might generate a problem because nil, true, and false won't
473
+ // become parser tokens
474
+ VALUE gql_value_to_token(struct gql_scanner *scanner, int accept_var)
475
+ {
476
+ return gql_as_token(gql_value_to_rb(scanner, accept_var), scanner, 1);
477
+ }
data/ext/shared.h ADDED
@@ -0,0 +1,177 @@
1
+ #include "ruby.h"
2
+
3
+ #if !defined RB_INT_PARSE_DEFAULT
4
+ #define RB_INT_PARSE_DEFAULT 0x07
5
+ #endif
6
+
7
+ #define GQL_PUTS(...) gql_debug_print(RSTRING_PTR(rb_sprintf(__VA_ARGS__)))
8
+
9
+ #define GQL_I_STRUCTURE_FST 0x10
10
+ #define GQL_I_STRUCTURE_LST 0x1f
11
+
12
+ #define GQL_I_VALUE_FST 0x20
13
+ #define GQL_I_VALUE_LST 0x2f
14
+
15
+ #define GQL_I_EXECUTION_FST 0x30
16
+ #define GQL_I_EXECUTION_LST 0x3f
17
+
18
+ #define GQL_I_OPERATIONS_FST 0x30
19
+ #define GQL_I_OPERATIONS_LST 0x32
20
+
21
+ #define GQL_I_DEFINITION_FST 0x40
22
+ #define GQL_I_DEFINITION_LST 0x4f
23
+
24
+ #define GQL_I_STRUCTURE(x) (x >= GQL_I_STRUCTURE_FST && x <= GQL_I_STRUCTURE_LST)
25
+ #define GQL_I_VALUE(x) (x >= GQL_I_VALUE_FST && x <= GQL_I_VALUE_LST)
26
+ #define GQL_I_EXECUTION(x) (x >= GQL_I_EXECUTION_FST && x <= GQL_I_EXECUTION_LST)
27
+ #define QGL_I_OPERATION(x) (x >= GQL_I_OPERATIONS_FST && x <= GQL_I_OPERATIONS_LST)
28
+ #define GQL_I_DEFINITION(x) (x >= GQL_I_DEFINITION_FST && x <= GQL_I_DEFINITION_LST)
29
+
30
+ // https://www.asciitable.com/
31
+ #define GQL_S_IGNORE(x) (x == ' ' || x == ',' || x == '\n' || x == '\r' || x == '\t' || x == '\f' || x == '\b')
32
+ #define GQL_S_CHARACTER(x) ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || x == '_')
33
+ #define GQL_S_DIGIT(x) (x >= '0' && x <= '9')
34
+ #define GQL_S_FLOAT_MARK(x) (x == '.' || x == 'e' || x == 'E')
35
+
36
+ #define GQL_SCAN_ERROR(scanner) (scanner->lexeme == gql_i_eof || scanner->lexeme == gql_i_unknown)
37
+ #define GQL_SCAN_SIZE(scanner) (scanner->current_pos - scanner->start_pos)
38
+ #define GQL_SCAN_CHAR(scanner) (scanner->doc[scanner->current_pos])
39
+ #define GQL_SCAN_LOOK(scanner, bytes) (scanner->doc[scanner->current_pos + bytes])
40
+ #define GQL_SCAN_NEXT(scanner) ({ \
41
+ scanner->current_pos++; \
42
+ scanner->current = GQL_SCAN_CHAR(scanner); \
43
+ })
44
+ #define GQL_SCAN_NEW_LINE(scanner) ({ \
45
+ scanner->last_ln_at = scanner->current_pos; \
46
+ scanner->current_line++; \
47
+ })
48
+ #define GQL_SCAN_WHILE(scanner, check) ({ \
49
+ while (check) \
50
+ { \
51
+ if (GQL_SCAN_CHAR(scanner) == '\n') \
52
+ { \
53
+ GQL_SCAN_NEW_LINE(scanner); \
54
+ } \
55
+ GQL_SCAN_NEXT(scanner); \
56
+ } \
57
+ })
58
+ #define GQL_SCAN_SET_END(scanner, offset) ({ \
59
+ scanner->end_line = scanner->begin_line; \
60
+ scanner->end_column = scanner->current_pos - offset - scanner->last_ln_at; \
61
+ })
62
+ #define GQL_SCAN_SAVE(scanner, memory) ({ \
63
+ memory[0] = scanner->begin_line; \
64
+ memory[1] = scanner->begin_column; \
65
+ })
66
+
67
+ #define GQL_SAFE_PUSH(source, value) ({ \
68
+ if (NIL_P(source)) \
69
+ source = rb_ary_new(); \
70
+ rb_ary_push(source, value); \
71
+ })
72
+
73
+ enum gql_lexeme
74
+ {
75
+ // Basic identifiers
76
+ gql_i_eof = 0x00,
77
+ gql_i_name = 0x01,
78
+ gql_i_comment = 0x02,
79
+ gql_i_variable = 0x03,
80
+ gql_i_directive = 0x04,
81
+
82
+ // Structure identifiers
83
+ gql_is_op_curly = 0x10,
84
+ gql_is_cl_curly = 0x11,
85
+ gql_is_op_paren = 0x12,
86
+ gql_is_cl_paren = 0x13,
87
+ gql_is_op_brack = 0x14,
88
+ gql_is_cl_brack = 0x15,
89
+ gql_is_colon = 0x16,
90
+ gql_is_equal = 0x17,
91
+ gql_is_period = 0x18,
92
+
93
+ // Value based types
94
+ gql_iv_integer = 0x20,
95
+ gql_iv_float = 0x21,
96
+ gql_iv_string = 0x22,
97
+ gql_iv_true = 0x23,
98
+ gql_iv_false = 0x24,
99
+ gql_iv_null = 0x25,
100
+ gql_iv_enum = 0x26,
101
+ gql_iv_array = 0x27,
102
+ gql_iv_hash = 0x28,
103
+ gql_iv_heredoc = 0x2f,
104
+
105
+ // Execution keywords
106
+ gql_ie_query = 0x30,
107
+ gql_ie_mutation = 0x31,
108
+ gql_ie_subscription = 0x32,
109
+ gql_ie_fragment = 0x33,
110
+ gql_ie_on = 0x34,
111
+
112
+ // Definition keywords
113
+ gql_id_schema = 0x40,
114
+ gql_id_directive = 0x41,
115
+ gql_id_enum = 0x42,
116
+ gql_id_input = 0x43,
117
+ gql_id_interface = 0x44,
118
+ gql_id_scalar = 0x45,
119
+ gql_id_type = 0x46,
120
+ gql_id_union = 0x47,
121
+ gql_id_extend = 0x48,
122
+ gql_id_implements = 0x49,
123
+ gql_id_repeatable = 0x4a,
124
+
125
+ // Something went wrong
126
+ gql_i_unknown = 0xff
127
+ };
128
+
129
+ struct gql_scanner
130
+ {
131
+ unsigned long start_pos;
132
+ unsigned long current_pos;
133
+ unsigned long current_line;
134
+ unsigned long last_ln_at;
135
+ unsigned long begin_line;
136
+ unsigned long begin_column;
137
+ unsigned long end_line;
138
+ unsigned long end_column;
139
+ char *doc;
140
+ char current;
141
+ enum gql_lexeme lexeme;
142
+ };
143
+
144
+ extern VALUE GQLParser;
145
+ extern VALUE QLGParserToken;
146
+ extern VALUE gql_eParserError;
147
+
148
+ extern const char *GQL_VALUE_KEYWORDS[3];
149
+ extern const char *GQL_EXECUTION_KEYWORDS[5];
150
+ extern const char *GQL_DEFINITION_KEYWORDS[12];
151
+
152
+ void gql_debug_print(const char *message);
153
+ struct gql_scanner gql_new_scanner(VALUE source);
154
+
155
+ enum gql_lexeme gql_upgrade_basis(const char *upgrade_from[]);
156
+ enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *upgrade_from[]);
157
+
158
+ enum gql_lexeme gql_read_name(struct gql_scanner *scanner);
159
+ enum gql_lexeme gql_read_comment(struct gql_scanner *scanner);
160
+ enum gql_lexeme gql_read_hash(struct gql_scanner *scanner);
161
+ enum gql_lexeme gql_read_float(struct gql_scanner *scanner);
162
+ enum gql_lexeme gql_read_number(struct gql_scanner *scanner);
163
+ enum gql_lexeme gql_read_string(struct gql_scanner *scanner, int allow_heredoc);
164
+
165
+ void gql_next_lexeme(struct gql_scanner *scanner);
166
+ void gql_next_lexeme_no_comments(struct gql_scanner *scanner);
167
+
168
+ VALUE gql_set_token_type(VALUE self, const char *type);
169
+ VALUE gql_inspect_token(VALUE self);
170
+ VALUE gql_token_of_type_check(VALUE self, VALUE other);
171
+ VALUE gql_as_token(VALUE self, struct gql_scanner *scanner, int save_type);
172
+
173
+ VALUE gql_scanner_to_s(struct gql_scanner *scanner);
174
+ VALUE gql_scanner_to_token(struct gql_scanner *scanner);
175
+ VALUE gql_array_to_rb(struct gql_scanner *scanner);
176
+ VALUE gql_value_to_rb(struct gql_scanner *scanner, int accept_var);
177
+ VALUE gql_value_to_token(struct gql_scanner *scanner, int accept_var);
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators/base'
4
+
5
+ module GraphQL
6
+ module Generators
7
+ class ChannelGenerator < Rails::Generators::Base # :nodoc:
8
+ include Rails::GraphQL::BaseGenerator
9
+
10
+ desc 'Add a new action cable channel that operates with GraphQL'
11
+
12
+ argument :name, type: :string, optional: true,
13
+ default: "GraphQLChannel",
14
+ desc: 'The name for the channel'
15
+
16
+ def create_channel_file
17
+ template 'channel.erb', "app/channels/#{channel_name.underscore}.rb"
18
+ end
19
+
20
+ private
21
+
22
+ def channel_name
23
+ @channel_name ||= options.fetch(:name, 'GraphQLChannel').classify
24
+ end
25
+ end
26
+ end
27
+ end
@@ -8,15 +8,20 @@ module GraphQL
8
8
  include Rails::GraphQL::BaseGenerator
9
9
 
10
10
  desc 'Add a new controller that operates with GraphQL'
11
- argument :name, type: :string, optional: true
11
+
12
+ argument :name, type: :string, optional: true,
13
+ default: "GraphQLController",
14
+ desc: 'The name for the controller'
12
15
 
13
16
  def create_controller_file
14
17
  template 'controller.erb', "app/controllers/#{controller_name.underscore}.rb"
15
18
  end
16
19
 
17
- def controller_name
18
- @controller_name ||= (options[:name].presence&.classify || 'GraphQL') + 'Controller'
19
- end
20
+ private
21
+
22
+ def controller_name
23
+ @controller_name ||= options.fetch(:name, 'GraphQLController').classify
24
+ end
20
25
  end
21
26
  end
22
27
  end