tinygql 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,442 @@
1
+ module TinyGQL
2
+ module Visitors
3
+ module Visitor
4
+ def handle_document obj
5
+ obj.definitions.each { _1.accept self }
6
+ end
7
+ def handle_operation_definition obj
8
+ if obj.variable_definitions
9
+ obj.variable_definitions.each { _1.accept self }
10
+ end
11
+ if obj.directives
12
+ obj.directives.each { _1.accept self }
13
+ end
14
+ obj.selection_set.each { _1.accept self }
15
+ end
16
+ def handle_variable obj
17
+ end
18
+ def handle_named_type obj
19
+ end
20
+ def handle_not_null_type obj
21
+ obj.type.accept self
22
+ end
23
+ def handle_list_type obj
24
+ obj.type.accept self
25
+ end
26
+ def handle_variable_definition obj
27
+ obj.variable.accept self
28
+ obj.type.accept self
29
+ if obj.default_value
30
+ obj.default_value.accept self
31
+ end
32
+ end
33
+ def handle_value obj
34
+ end
35
+ def handle_argument obj
36
+ obj.value.accept self
37
+ end
38
+ def handle_field obj
39
+ if obj.arguments
40
+ obj.arguments.each { _1.accept self }
41
+ end
42
+ if obj.directives
43
+ obj.directives.each { _1.accept self }
44
+ end
45
+ if obj.selection_set
46
+ obj.selection_set.each { _1.accept self }
47
+ end
48
+ end
49
+ def handle_object_field obj
50
+ obj.value.accept self
51
+ end
52
+ def handle_int_value obj
53
+ end
54
+ def handle_float_value obj
55
+ end
56
+ def handle_string_value obj
57
+ end
58
+ def handle_boolean_value obj
59
+ end
60
+ def handle_null_value obj
61
+ end
62
+ def handle_enum_value obj
63
+ end
64
+ def handle_list_value obj
65
+ end
66
+ def handle_object_value obj
67
+ obj.values.each { _1.accept self }
68
+ end
69
+ def handle_directive obj
70
+ obj.arguments.each { _1.accept self }
71
+ end
72
+ def handle_type_condition obj
73
+ obj.named_type.accept self
74
+ end
75
+ def handle_inline_fragment obj
76
+ if obj.type_condition
77
+ obj.type_condition.accept self
78
+ end
79
+ if obj.directives
80
+ obj.directives.each { _1.accept self }
81
+ end
82
+ obj.selection_set.each { _1.accept self }
83
+ end
84
+ def handle_fragment_spread obj
85
+ obj.fragment_name.accept self
86
+ if obj.directives
87
+ obj.directives.each { _1.accept self }
88
+ end
89
+ end
90
+ def handle_fragment_definition obj
91
+ obj.fragment_name.accept self
92
+ obj.type_condition.accept self
93
+ if obj.directives
94
+ obj.directives.each { _1.accept self }
95
+ end
96
+ obj.selection_set.each { _1.accept self }
97
+ end
98
+ def handle_root_operation_type_definition obj
99
+ obj.operation_type.accept self
100
+ obj.named_type.accept self
101
+ end
102
+ def handle_schema_definition obj
103
+ if obj.directives
104
+ obj.directives.each { _1.accept self }
105
+ end
106
+ obj.root_operation_definitions.each { _1.accept self }
107
+ end
108
+ def handle_field_definition obj
109
+ if obj.arguments_definition
110
+ obj.arguments_definition.each { _1.accept self }
111
+ end
112
+ obj.type.accept self
113
+ if obj.directives
114
+ obj.directives.each { _1.accept self }
115
+ end
116
+ end
117
+ def handle_input_value_definition obj
118
+ obj.type.accept self
119
+ if obj.default_value
120
+ obj.default_value.accept self
121
+ end
122
+ if obj.directives
123
+ obj.directives.each { _1.accept self }
124
+ end
125
+ end
126
+ def handle_object_type_definition obj
127
+ if obj.implements_interfaces
128
+ obj.implements_interfaces.each { _1.accept self }
129
+ end
130
+ if obj.directives
131
+ obj.directives.each { _1.accept self }
132
+ end
133
+ if obj.fields_definition
134
+ obj.fields_definition.each { _1.accept self }
135
+ end
136
+ end
137
+ def handle_interface_type_definition obj
138
+ if obj.directives
139
+ obj.directives.each { _1.accept self }
140
+ end
141
+ if obj.fields_definition
142
+ obj.fields_definition.each { _1.accept self }
143
+ end
144
+ end
145
+ def handle_union_type_definition obj
146
+ if obj.directives
147
+ obj.directives.each { _1.accept self }
148
+ end
149
+ if obj.union_member_types
150
+ obj.union_member_types.each { _1.accept self }
151
+ end
152
+ end
153
+ def handle_scalar_type_definition obj
154
+ if obj.directives
155
+ obj.directives.each { _1.accept self }
156
+ end
157
+ end
158
+ def handle_enum_value_definition obj
159
+ obj.enum_value.accept self
160
+ if obj.directives
161
+ obj.directives.each { _1.accept self }
162
+ end
163
+ end
164
+ def handle_enum_type_definition obj
165
+ if obj.directives
166
+ obj.directives.each { _1.accept self }
167
+ end
168
+ if obj.enum_value_definition
169
+ obj.enum_value_definition.each { _1.accept self }
170
+ end
171
+ end
172
+ def handle_input_object_type_definition obj
173
+ if obj.directives
174
+ obj.directives.each { _1.accept self }
175
+ end
176
+ if obj.input_fields_definition
177
+ obj.input_fields_definition.each { _1.accept self }
178
+ end
179
+ end
180
+ def handle_object_type_extension obj
181
+ if obj.implements_interfaces
182
+ obj.implements_interfaces.each { _1.accept self }
183
+ end
184
+ if obj.directives
185
+ obj.directives.each { _1.accept self }
186
+ end
187
+ if obj.fields_definition
188
+ obj.fields_definition.each { _1.accept self }
189
+ end
190
+ end
191
+ def handle_executable_directive_location obj
192
+ end
193
+ def handle_type_system_directive_location obj
194
+ end
195
+ def handle_directive_definition obj
196
+ if obj.arguments_definition
197
+ obj.arguments_definition.each { _1.accept self }
198
+ end
199
+ obj.directive_locations.each { _1.accept self }
200
+ end
201
+ end
202
+
203
+ module Fold
204
+ def handle_document obj, seed
205
+ obj.definitions.each { seed = _1.fold(self, seed) }
206
+ seed
207
+ end
208
+ def handle_operation_definition obj, seed
209
+ if obj.variable_definitions
210
+ obj.variable_definitions.each { seed = _1.fold(self, seed) }
211
+ end
212
+ if obj.directives
213
+ obj.directives.each { seed = _1.fold(self, seed) }
214
+ end
215
+ obj.selection_set.each { seed = _1.fold(self, seed) }
216
+ seed
217
+ end
218
+ def handle_variable obj, seed
219
+ seed
220
+ end
221
+ def handle_named_type obj, seed
222
+ seed
223
+ end
224
+ def handle_not_null_type obj, seed
225
+ seed = obj.type.fold self, seed
226
+ seed
227
+ end
228
+ def handle_list_type obj, seed
229
+ seed = obj.type.fold self, seed
230
+ seed
231
+ end
232
+ def handle_variable_definition obj, seed
233
+ seed = obj.variable.fold self, seed
234
+ seed = obj.type.fold self, seed
235
+ if obj.default_value
236
+ seed = obj.default_value.fold self, seed
237
+ end
238
+ seed
239
+ end
240
+ def handle_value obj, seed
241
+ seed
242
+ end
243
+ def handle_argument obj, seed
244
+ seed = obj.value.fold self, seed
245
+ seed
246
+ end
247
+ def handle_field obj, seed
248
+ if obj.arguments
249
+ obj.arguments.each { seed = _1.fold(self, seed) }
250
+ end
251
+ if obj.directives
252
+ obj.directives.each { seed = _1.fold(self, seed) }
253
+ end
254
+ if obj.selection_set
255
+ obj.selection_set.each { seed = _1.fold(self, seed) }
256
+ end
257
+ seed
258
+ end
259
+ def handle_object_field obj, seed
260
+ seed = obj.value.fold self, seed
261
+ seed
262
+ end
263
+ def handle_int_value obj, seed
264
+ seed
265
+ end
266
+ def handle_float_value obj, seed
267
+ seed
268
+ end
269
+ def handle_string_value obj, seed
270
+ seed
271
+ end
272
+ def handle_boolean_value obj, seed
273
+ seed
274
+ end
275
+ def handle_null_value obj, seed
276
+ seed
277
+ end
278
+ def handle_enum_value obj, seed
279
+ seed
280
+ end
281
+ def handle_list_value obj, seed
282
+ seed
283
+ end
284
+ def handle_object_value obj, seed
285
+ obj.values.each { seed = _1.fold(self, seed) }
286
+ seed
287
+ end
288
+ def handle_directive obj, seed
289
+ obj.arguments.each { seed = _1.fold(self, seed) }
290
+ seed
291
+ end
292
+ def handle_type_condition obj, seed
293
+ seed = obj.named_type.fold self, seed
294
+ seed
295
+ end
296
+ def handle_inline_fragment obj, seed
297
+ if obj.type_condition
298
+ seed = obj.type_condition.fold self, seed
299
+ end
300
+ if obj.directives
301
+ obj.directives.each { seed = _1.fold(self, seed) }
302
+ end
303
+ obj.selection_set.each { seed = _1.fold(self, seed) }
304
+ seed
305
+ end
306
+ def handle_fragment_spread obj, seed
307
+ seed = obj.fragment_name.fold self, seed
308
+ if obj.directives
309
+ obj.directives.each { seed = _1.fold(self, seed) }
310
+ end
311
+ seed
312
+ end
313
+ def handle_fragment_definition obj, seed
314
+ seed = obj.fragment_name.fold self, seed
315
+ seed = obj.type_condition.fold self, seed
316
+ if obj.directives
317
+ obj.directives.each { seed = _1.fold(self, seed) }
318
+ end
319
+ obj.selection_set.each { seed = _1.fold(self, seed) }
320
+ seed
321
+ end
322
+ def handle_root_operation_type_definition obj, seed
323
+ seed = obj.operation_type.fold self, seed
324
+ seed = obj.named_type.fold self, seed
325
+ seed
326
+ end
327
+ def handle_schema_definition obj, seed
328
+ if obj.directives
329
+ obj.directives.each { seed = _1.fold(self, seed) }
330
+ end
331
+ obj.root_operation_definitions.each { seed = _1.fold(self, seed) }
332
+ seed
333
+ end
334
+ def handle_field_definition obj, seed
335
+ if obj.arguments_definition
336
+ obj.arguments_definition.each { seed = _1.fold(self, seed) }
337
+ end
338
+ seed = obj.type.fold self, seed
339
+ if obj.directives
340
+ obj.directives.each { seed = _1.fold(self, seed) }
341
+ end
342
+ seed
343
+ end
344
+ def handle_input_value_definition obj, seed
345
+ seed = obj.type.fold self, seed
346
+ if obj.default_value
347
+ seed = obj.default_value.fold self, seed
348
+ end
349
+ if obj.directives
350
+ obj.directives.each { seed = _1.fold(self, seed) }
351
+ end
352
+ seed
353
+ end
354
+ def handle_object_type_definition obj, seed
355
+ if obj.implements_interfaces
356
+ obj.implements_interfaces.each { seed = _1.fold(self, seed) }
357
+ end
358
+ if obj.directives
359
+ obj.directives.each { seed = _1.fold(self, seed) }
360
+ end
361
+ if obj.fields_definition
362
+ obj.fields_definition.each { seed = _1.fold(self, seed) }
363
+ end
364
+ seed
365
+ end
366
+ def handle_interface_type_definition obj, seed
367
+ if obj.directives
368
+ obj.directives.each { seed = _1.fold(self, seed) }
369
+ end
370
+ if obj.fields_definition
371
+ obj.fields_definition.each { seed = _1.fold(self, seed) }
372
+ end
373
+ seed
374
+ end
375
+ def handle_union_type_definition obj, seed
376
+ if obj.directives
377
+ obj.directives.each { seed = _1.fold(self, seed) }
378
+ end
379
+ if obj.union_member_types
380
+ obj.union_member_types.each { seed = _1.fold(self, seed) }
381
+ end
382
+ seed
383
+ end
384
+ def handle_scalar_type_definition obj, seed
385
+ if obj.directives
386
+ obj.directives.each { seed = _1.fold(self, seed) }
387
+ end
388
+ seed
389
+ end
390
+ def handle_enum_value_definition obj, seed
391
+ seed = obj.enum_value.fold self, seed
392
+ if obj.directives
393
+ obj.directives.each { seed = _1.fold(self, seed) }
394
+ end
395
+ seed
396
+ end
397
+ def handle_enum_type_definition obj, seed
398
+ if obj.directives
399
+ obj.directives.each { seed = _1.fold(self, seed) }
400
+ end
401
+ if obj.enum_value_definition
402
+ obj.enum_value_definition.each { seed = _1.fold(self, seed) }
403
+ end
404
+ seed
405
+ end
406
+ def handle_input_object_type_definition obj, seed
407
+ if obj.directives
408
+ obj.directives.each { seed = _1.fold(self, seed) }
409
+ end
410
+ if obj.input_fields_definition
411
+ obj.input_fields_definition.each { seed = _1.fold(self, seed) }
412
+ end
413
+ seed
414
+ end
415
+ def handle_object_type_extension obj, seed
416
+ if obj.implements_interfaces
417
+ obj.implements_interfaces.each { seed = _1.fold(self, seed) }
418
+ end
419
+ if obj.directives
420
+ obj.directives.each { seed = _1.fold(self, seed) }
421
+ end
422
+ if obj.fields_definition
423
+ obj.fields_definition.each { seed = _1.fold(self, seed) }
424
+ end
425
+ seed
426
+ end
427
+ def handle_executable_directive_location obj, seed
428
+ seed
429
+ end
430
+ def handle_type_system_directive_location obj, seed
431
+ seed
432
+ end
433
+ def handle_directive_definition obj, seed
434
+ if obj.arguments_definition
435
+ obj.arguments_definition.each { seed = _1.fold(self, seed) }
436
+ end
437
+ obj.directive_locations.each { seed = _1.fold(self, seed) }
438
+ seed
439
+ end
440
+ end
441
+ end
442
+ end
@@ -0,0 +1,46 @@
1
+ module TinyGQL
2
+ module Visitors
3
+ module Visitor
4
+ <%- nodes.each do |node| -%>
5
+ def handle_<%= node.human_name %> obj
6
+ <%- node.fields.find_all(&:visitable?).each do |field| -%>
7
+ <%- if field.nullable? -%>
8
+ if obj.<%= field.name %>
9
+ <%- end -%>
10
+ <%- if field.list? -%>
11
+ obj.<%= field.name %>.each { _1.accept self }
12
+ <%- end -%>
13
+ <%- if field.node? -%>
14
+ obj.<%= field.name %>.accept self
15
+ <%- end -%>
16
+ <%- if field.nullable? -%>
17
+ end
18
+ <%- end -%>
19
+ <%- end -%>
20
+ end
21
+ <%- end -%>
22
+ end
23
+
24
+ module Fold
25
+ <%- nodes.each do |node| -%>
26
+ def handle_<%= node.human_name %> obj, seed
27
+ <%- node.fields.find_all(&:visitable?).each do |field| -%>
28
+ <%- if field.nullable? -%>
29
+ if obj.<%= field.name %>
30
+ <%- end -%>
31
+ <%- if field.list? -%>
32
+ obj.<%= field.name %>.each { seed = _1.fold(self, seed) }
33
+ <%- end -%>
34
+ <%- if field.node? -%>
35
+ seed = obj.<%= field.name %>.fold self, seed
36
+ <%- end -%>
37
+ <%- if field.nullable? -%>
38
+ end
39
+ <%- end -%>
40
+ <%- end -%>
41
+ seed
42
+ end
43
+ <%- end -%>
44
+ end
45
+ end
46
+ end
data/lib/tinygql.rb ADDED
@@ -0,0 +1,10 @@
1
+ require "tinygql/parser"
2
+ require "tinygql/version"
3
+
4
+ module TinyGQL
5
+ autoload :Visitors, "tinygql/visitors"
6
+
7
+ def self.parse doc
8
+ Parser.new(doc).parse
9
+ end
10
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,14 @@
1
+ ENV["MT_NO_PLUGINS"] = "1"
2
+
3
+ require "tinygql/parser"
4
+ require "minitest/autorun"
5
+
6
+ Thread.new do
7
+ sleep 5
8
+ Process.kill "QUIT", $$
9
+ end
10
+
11
+ module TinyGQL
12
+ class Test < Minitest::Test
13
+ end
14
+ end
@@ -0,0 +1,59 @@
1
+ # Copyright (c) 2015-present, Facebook, Inc.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ query queryName($foo: ComplexType, $site: Site = MOBILE) {
7
+ whoever123is: node(id: [123, 456]) {
8
+ id ,
9
+ ... on User @defer {
10
+ field2 {
11
+ id ,
12
+ alias: field1(first:10, after:$foo,) @include(if: $foo) {
13
+ id,
14
+ ...frag
15
+ }
16
+ }
17
+ }
18
+ ... @skip(unless: $foo) {
19
+ id
20
+ }
21
+ ... {
22
+ id
23
+ }
24
+ }
25
+ }
26
+
27
+ mutation likeStory {
28
+ like(story: 123) @defer {
29
+ story {
30
+ id
31
+ }
32
+ }
33
+ }
34
+
35
+ subscription StoryLikeSubscription($input: StoryLikeSubscribeInput) {
36
+ storyLikeSubscribe(input: $input) {
37
+ story {
38
+ likers {
39
+ count
40
+ }
41
+ likeSentence {
42
+ text
43
+ }
44
+ }
45
+ }
46
+ }
47
+
48
+ fragment frag on Friend {
49
+ foo(size: $size, bar: $b, obj: {key: "value", block: """
50
+
51
+ block string uses \"""
52
+
53
+ """})
54
+ }
55
+
56
+ {
57
+ unnamed(truthy: true, falsey: false, nullish: null),
58
+ query
59
+ }
@@ -0,0 +1,93 @@
1
+ require "helper"
2
+
3
+ module TinyGQL
4
+ class LexerTest < Test
5
+ PUNC_LUT = {"!"=>[:BANG, "!"],
6
+ "$"=>[:VAR_SIGN, "$"],
7
+ "("=>[:LPAREN, "("],
8
+ ")"=>[:RPAREN, ")"],
9
+ "..."=>[:ELLIPSIS, "..."],
10
+ ":"=>[:COLON, ":"],
11
+ "="=>[:EQUALS, "="],
12
+ "@"=>[:DIR_SIGN, "@"],
13
+ "["=>[:LBRACKET, "["],
14
+ "]"=>[:RBRACKET, "]"],
15
+ "{"=>[:LCURLY, "{"],
16
+ "|"=>[:PIPE, "|"],
17
+ "}"=>[:RCURLY, "}"]}
18
+
19
+ def test_punc
20
+ %w{ ! $ ( ) ... : = @ [ ] { | } }.each do |punc|
21
+ lexer = Lexer.new punc
22
+ token = lexer.next_token
23
+ expected = PUNC_LUT[punc]
24
+ assert_equal(expected || [:ON, "on"], token)
25
+ end
26
+ end
27
+
28
+ def test_regular_string
29
+ str = "hello\n# foo\n\"world\"# lol \nlol"
30
+ lexer = Lexer.new str
31
+ assert_equal [:IDENTIFIER, "hello"], lexer.next_token
32
+ assert_equal [:STRING, "world"], lexer.next_token
33
+ assert_equal [:IDENTIFIER, "lol"], lexer.next_token
34
+ end
35
+
36
+ def test_multiline_comment
37
+ str = "hello\n# foo\n# lol \nlol"
38
+ lexer = Lexer.new str
39
+ assert_equal [:IDENTIFIER, "hello"], lexer.next_token
40
+ assert_equal [:IDENTIFIER, "lol"], lexer.next_token
41
+ end
42
+
43
+ def test_block_string
44
+ doc = <<-eos
45
+ """
46
+
47
+ block string uses \\"""
48
+
49
+ """
50
+ eos
51
+ lexer = Lexer.new doc
52
+ assert_equal :STRING, lexer.next_token.first
53
+ end
54
+
55
+ def test_tokenize
56
+ lexer = Lexer.new "on"
57
+ token = lexer.next_token
58
+ assert_equal [:ON, "on"], token
59
+ end
60
+
61
+ def test_multi_tok
62
+ doc = <<-eod
63
+ mutation {
64
+ likeStory(storyID: 12345) {
65
+ story {
66
+ likeCount
67
+ }
68
+ }
69
+ }
70
+ eod
71
+ lexer = Lexer.new doc
72
+ toks = []
73
+ while tok = lexer.next_token
74
+ toks << tok
75
+ end
76
+ assert_equal [[:MUTATION, "mutation"],
77
+ [:LCURLY, "{"],
78
+ [:IDENTIFIER, "likeStory"],
79
+ [:LPAREN, "("],
80
+ [:IDENTIFIER, "storyID"],
81
+ [:COLON, ":"],
82
+ [:INT, "12345"],
83
+ [:RPAREN, ")"],
84
+ [:LCURLY, "{"],
85
+ [:IDENTIFIER, "story"],
86
+ [:LCURLY, "{"],
87
+ [:IDENTIFIER, "likeCount"],
88
+ [:RCURLY, "}"],
89
+ [:RCURLY, "}"],
90
+ [:RCURLY, "}"]], toks
91
+ end
92
+ end
93
+ end