tinygql 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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