graphql-dsl 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +23 -0
  3. data/.gitignore +12 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +44 -0
  6. data/.ruby-version +1 -0
  7. data/.yardopts +1 -0
  8. data/CODE_OF_CONDUCT.md +84 -0
  9. data/Gemfile +6 -0
  10. data/Gemfile.lock +64 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +899 -0
  13. data/Rakefile +6 -0
  14. data/bin/console +15 -0
  15. data/bin/setup +7 -0
  16. data/graphql-dsl.gemspec +38 -0
  17. data/lib/graphql/dsl/constants.rb +9 -0
  18. data/lib/graphql/dsl/error.rb +32 -0
  19. data/lib/graphql/dsl/formatter/arguments.rb +26 -0
  20. data/lib/graphql/dsl/formatter/directives.rb +52 -0
  21. data/lib/graphql/dsl/formatter/executable_document.rb +22 -0
  22. data/lib/graphql/dsl/formatter/field.rb +49 -0
  23. data/lib/graphql/dsl/formatter/formatter.rb +41 -0
  24. data/lib/graphql/dsl/formatter/fragment_operation.rb +41 -0
  25. data/lib/graphql/dsl/formatter/fragment_spread.rb +25 -0
  26. data/lib/graphql/dsl/formatter/inline_fragment.rb +43 -0
  27. data/lib/graphql/dsl/formatter/operation.rb +60 -0
  28. data/lib/graphql/dsl/formatter/values.rb +146 -0
  29. data/lib/graphql/dsl/formatter/variable_definitions.rb +43 -0
  30. data/lib/graphql/dsl/nodes/containers/directive.rb +46 -0
  31. data/lib/graphql/dsl/nodes/containers/variable_definition.rb +52 -0
  32. data/lib/graphql/dsl/nodes/executable_document.rb +69 -0
  33. data/lib/graphql/dsl/nodes/field.rb +39 -0
  34. data/lib/graphql/dsl/nodes/fragment_operation.rb +36 -0
  35. data/lib/graphql/dsl/nodes/fragment_spread.rb +24 -0
  36. data/lib/graphql/dsl/nodes/inline_fragment.rb +34 -0
  37. data/lib/graphql/dsl/nodes/mixins/selection_set.rb +106 -0
  38. data/lib/graphql/dsl/nodes/node.rb +39 -0
  39. data/lib/graphql/dsl/nodes/operation.rb +61 -0
  40. data/lib/graphql/dsl/version.rb +9 -0
  41. data/lib/graphql/dsl.rb +230 -0
  42. data/lib/graphql-dsl.rb +3 -0
  43. data/lib/graphql_dsl.rb +36 -0
  44. data/tasks/readme/update.rake +143 -0
  45. metadata +173 -0
data/README.md ADDED
@@ -0,0 +1,899 @@
1
+ <h1 align="center">✨ GraphQL DSL ✨</h1>
2
+
3
+ <p align="center">
4
+ <a href="https://github.com/maxd/graphql-dsl/actions/workflows/main.yml"><img src="https://github.com/maxd/graphql-dsl/actions/workflows/main.yml/badge.svg" alt="main" /></a>
5
+ <a href="https://www.ruby-lang.org/en/"><img src="https://img.shields.io/static/v1?label=language&message=Ruby&color=CC342D&style=flat&logo=ruby&logoColor=CC342D" alt="ruby" /></a>
6
+ <a href="https://graphql.org/"><img src="https://img.shields.io/static/v1?label=language&message=GraphQL&color=E10098&style=flat&logo=graphql&logoColor=E10098" alt="GraphQL" /></a>
7
+ </p>
8
+
9
+ `graphql-dsl` lets you easy create GraphQL queries by code:
10
+
11
+ ```ruby
12
+ extend GraphQL::DSL # Include DSL methods like `query`, `mutation`, etc.
13
+ using GraphQL::DSL # Include refine methods like `variable` and `directive` if required.
14
+
15
+ # Query alive characters from Rick and Morty unofficial GraphQL API:
16
+ # https://rickandmortyapi.com/graphql
17
+ puts query(:aliveCharacters, species: variable(:String!, 'Human')) {
18
+ characters(filter: { status: 'Alive', species: :$species }) {
19
+ results {
20
+ name
21
+ image
22
+ }
23
+ }
24
+ }.to_gql
25
+ ```
26
+
27
+ ```graphql
28
+ query aliveCharacters($species: String! = "Human")
29
+ {
30
+ characters(filter: {status: "Alive", species: $species})
31
+ {
32
+ results
33
+ {
34
+ name
35
+ image
36
+ }
37
+ }
38
+ }
39
+ ```
40
+
41
+ ## 🧩 Supported GraphQL features
42
+
43
+ The GraphQL DSL base on [draft](https://spec.graphql.org/draft/) version of GraphQL specification (updated at Wed, Sep 15, 2021)
44
+ and support these features:
45
+
46
+ - [x] Executable Documents (exclude type system definition documents)
47
+ - [x] All operations (`query`, `mutation`, `subscription`) and their features (variable, directives, selection sets, etc.)
48
+ - [x] All field features (aliases, arguments, directives, etc.)
49
+ - [x] Fragments (include inline fragments)
50
+
51
+ ## ⚙️ Installation
52
+
53
+ Add this line to your application's Gemfile:
54
+
55
+ ```ruby
56
+ gem 'graphql-dsl', '~> 1.0.0'
57
+ ```
58
+
59
+ And then execute `bundle install`.
60
+
61
+ ## ⚡️ Getting Started
62
+
63
+ Choose an appropriate way to use GraphQL DSL:
64
+
65
+ 1. Call methods of `GraphQL::DSL` module directly
66
+
67
+ ```ruby
68
+ rockets_query = GraphQL::DSL.query {
69
+ rockets {
70
+ name
71
+ }
72
+ }.to_gql
73
+
74
+ puts rockets_query
75
+ ```
76
+
77
+ <details>
78
+ <summary>STDOUT</summary>
79
+
80
+ ```graphql
81
+ {
82
+ rockets
83
+ {
84
+ name
85
+ }
86
+ }
87
+ ```
88
+ </details>
89
+
90
+ 1. Extend class or module use `GraphQL::DSL` module
91
+
92
+ ```ruby
93
+ module SpaceXQueries
94
+ extend GraphQL::DSL
95
+
96
+ # Create constant with GraphQL query
97
+ ROCKETS = query {
98
+ rockets {
99
+ name
100
+ }
101
+ }.to_gql
102
+ end
103
+
104
+ puts SpaceXQueries::ROCKETS
105
+ ```
106
+
107
+ <details>
108
+ <summary>STDOUT</summary>
109
+
110
+ ```graphql
111
+ {
112
+ rockets
113
+ {
114
+ name
115
+ }
116
+ }
117
+ ```
118
+ </details>
119
+
120
+ ```ruby
121
+ module SpaceXQueries
122
+ extend GraphQL::DSL
123
+
124
+ # `extend self` or `module_function` required to
125
+ # call of `SpaceXQueries.rockets`
126
+ extend self
127
+
128
+ # use memorization or lazy initialization
129
+ # to avoid generation of query on each method call
130
+ def rockets
131
+ query {
132
+ rockets {
133
+ name
134
+ }
135
+ }.to_gql
136
+ end
137
+ end
138
+
139
+ puts SpaceXQueries.rockets
140
+ ```
141
+
142
+ <details>
143
+ <summary>STDOUT</summary>
144
+
145
+ ```graphql
146
+ {
147
+ rockets
148
+ {
149
+ name
150
+ }
151
+ }
152
+ ```
153
+ </details>
154
+
155
+ 1. Include `GraphQL::DSL` module to class
156
+
157
+ ```ruby
158
+ class SpaceXQueries
159
+ include GraphQL::DSL
160
+
161
+ # use memorization or lazy initialization
162
+ # to avoid generation of query on each method call
163
+ def rockets
164
+ query {
165
+ rockets {
166
+ name
167
+ }
168
+ }.to_gql
169
+ end
170
+ end
171
+
172
+ queries = SpaceXQueries.new
173
+ puts queries.rockets
174
+ ```
175
+
176
+ <details>
177
+ <summary>STDOUT</summary>
178
+
179
+ ```graphql
180
+ {
181
+ rockets
182
+ {
183
+ name
184
+ }
185
+ }
186
+ ```
187
+ </details>
188
+
189
+ ## 👀 Examples
190
+
191
+ :bulb: _Non-official SpaceX GraphQL and Rick and Morty APIs are using for most of examples.
192
+ So, you can test generated GraphQL queries [here](https://api.spacex.land/graphql/) and [here](https://rickandmortyapi.com/graphql)._
193
+
194
+ ### Operations
195
+
196
+ The GraphQL support three types of operations:
197
+
198
+ * `query` - for fetch data.
199
+ * `mutation` - for update data.
200
+ * `subscription` - for fetch stream of data during a log time.
201
+
202
+ To create these operations use correspond GraphQL DSL methods:
203
+
204
+ * `GraphQL::DSL#query`
205
+ * `GraphQL::DSL#mutation`
206
+ * `GraphQL::DSL#subscription`
207
+
208
+ :bulb: _All of them have the same signatures therefore all examples below will use `query` operation._
209
+
210
+ #### Anonymous operations
211
+
212
+ Call correspond `GraphQL::DSL` method without any arguments to create anonymous operation:
213
+
214
+ ```ruby
215
+ puts GraphQL::DSL.query {
216
+ rockets {
217
+ name
218
+ }
219
+ }.to_gql
220
+ ```
221
+
222
+ <details>
223
+ <summary>STDOUT</summary>
224
+
225
+ ```graphql
226
+ {
227
+ rockets
228
+ {
229
+ name
230
+ }
231
+ }
232
+ ```
233
+ </details>
234
+
235
+ #### Named operations
236
+
237
+ Use string or symbol to specify operation name:
238
+
239
+ ```ruby
240
+ puts GraphQL::DSL.query(:rockets) {
241
+ rockets {
242
+ name
243
+ }
244
+ }.to_gql
245
+ ```
246
+
247
+ <details>
248
+ <summary>STDOUT</summary>
249
+
250
+ ```graphql
251
+ query rockets
252
+ {
253
+ rockets
254
+ {
255
+ name
256
+ }
257
+ }
258
+ ```
259
+ </details>
260
+
261
+ #### Parameterized operations
262
+
263
+ Pass variable definitions to second argument of correspond `GraphQL::DSL` method:
264
+
265
+ ```ruby
266
+ using GraphQL::DSL # Include refined `variable` method
267
+
268
+ puts GraphQL::DSL.query(:capsules, type: :String, status: variable(:String!, 'active')) {
269
+ capsules(find: { type: :$type, status: :$status }) {
270
+ type
271
+ status
272
+ landings
273
+ }
274
+ }.to_gql
275
+ ```
276
+
277
+ <details>
278
+ <summary>STDOUT</summary>
279
+
280
+ ```graphql
281
+ query capsules($type: String, $status: String! = "active")
282
+ {
283
+ capsules(find: {type: $type, status: $status})
284
+ {
285
+ type
286
+ status
287
+ landings
288
+ }
289
+ }
290
+ ```
291
+ </details>
292
+
293
+ Choose appropriate notation to define variable type, default value and directives:
294
+
295
+ :bulb: _See more about types definition [here](#types)._
296
+
297
+ <details>
298
+ <summary>Use <code>Symbol</code> or <code>String</code></summary>
299
+
300
+ ```ruby
301
+ # <variable name>: <type>, ...
302
+
303
+ puts GraphQL::DSL.query(:capsules, status: :String!) {
304
+ capsules(find: { status: :$status }) {
305
+ type
306
+ status
307
+ landings
308
+ }
309
+ }.to_gql
310
+ ```
311
+
312
+ ```graphql
313
+ query capsules($status: String!)
314
+ {
315
+ capsules(find: {status: $status})
316
+ {
317
+ type
318
+ status
319
+ landings
320
+ }
321
+ }
322
+ ```
323
+ </details>
324
+
325
+ <details>
326
+ <summary>Use <code>variable</code> refined method</summary>
327
+
328
+ ```ruby
329
+ # <variable name>: variable(<type>, [<default value>], [<directives>]), ...
330
+
331
+ using GraphQL::DSL # Required to refine `variable` method
332
+
333
+ puts GraphQL::DSL.query(:capsules, status: variable(:String!, 'active')) {
334
+ capsules(find: { status: :$status }) {
335
+ type
336
+ status
337
+ landings
338
+ }
339
+ }.to_gql
340
+ ```
341
+
342
+ ```graphql
343
+ query capsules($status: String! = "active")
344
+ {
345
+ capsules(find: {status: $status})
346
+ {
347
+ type
348
+ status
349
+ landings
350
+ }
351
+ }
352
+ ```
353
+ </details>
354
+
355
+ <details>
356
+ <summary>Use <code>__var</code> method</summary>
357
+
358
+ ```ruby
359
+ # __var <variable name>, <type>, [default: <default value>], [directives: <directives>]
360
+
361
+ puts GraphQL::DSL.query(:capsules) {
362
+ __var :status, :String!, default: "active"
363
+
364
+ capsules(find: { status: :$status }) {
365
+ type
366
+ status
367
+ landings
368
+ }
369
+ }.to_gql
370
+ ```
371
+
372
+ ```graphql
373
+ query capsules($status: String! = "active")
374
+ {
375
+ capsules(find: {status: $status})
376
+ {
377
+ type
378
+ status
379
+ landings
380
+ }
381
+ }
382
+ ```
383
+ </details>
384
+
385
+ :bulb: _More information about directives you can find [here](#directives)._
386
+
387
+ #### Operation's directives
388
+
389
+ Pass operation's directives to third argument of correspond `GraphQL::DSL` method:
390
+
391
+ ```ruby
392
+ using GraphQL::DSL # Include refined `variable` and `directive` methods
393
+
394
+ puts GraphQL::DSL.query(:capsules, { status: variable(:String!, 'active') }, [ directive(:priority, level: :LOW) ]) {
395
+ capsules(find: { status: :$status }) {
396
+ type
397
+ status
398
+ landings
399
+ }
400
+ }.to_gql
401
+ ```
402
+
403
+ <details>
404
+ <summary>STDOUT</summary>
405
+
406
+ ```graphql
407
+ query capsules($status: String! = "active") @priority(level: LOW)
408
+ {
409
+ capsules(find: {status: $status})
410
+ {
411
+ type
412
+ status
413
+ landings
414
+ }
415
+ }
416
+ ```
417
+ </details>
418
+
419
+ :bulb: _More information about directives you can find [here](#directives)._
420
+
421
+ ### Selection Sets
422
+
423
+ [Selection Set](https://spec.graphql.org/draft/#sec-Selection-Sets) is a block that contains fields, spread or
424
+ internal fragments. Operations (`query`, `mutation`, `subscription`), fragment operations, spread and internal fragments
425
+ must have `Selection Set` for select or update (in case of mutation) data. Even a field can contains `Selection Set`.
426
+
427
+ ```ruby
428
+ puts GraphQL::DSL.query { # this is `Selection Set` of query
429
+ company { # this is `Selection Set` of `company` field
430
+ name
431
+ ceo
432
+ cto
433
+ }
434
+ }.to_gql
435
+ ```
436
+
437
+ <details>
438
+ <summary>STDOUT</summary>
439
+
440
+ ```graphql
441
+ {
442
+ company
443
+ {
444
+ name
445
+ ceo
446
+ cto
447
+ }
448
+ }
449
+ ```
450
+ </details>
451
+
452
+ ### Fields
453
+
454
+ [Selection Set](#selection-set) should contains one or more fields to select or update (in case of mutation) data.
455
+
456
+ To create field just declare it name inside of `Selection Set` block:
457
+
458
+ ```ruby
459
+ puts GraphQL::DSL.query {
460
+ company { # this is `company` field
461
+ name # this is `name` fields declared in `Selection Set` of `company` field
462
+ }
463
+ }.to_gql
464
+ ```
465
+
466
+ <details>
467
+ <summary>STDOUT</summary>
468
+
469
+ ```graphql
470
+ {
471
+ company
472
+ {
473
+ name
474
+ }
475
+ }
476
+ ```
477
+ </details>
478
+
479
+ As you can see above some fields can have `Selection Set` and allow to declare sub-fields.
480
+
481
+ In rare cases will be impossible to declare field in such way because its name can conflict with Ruby's keywords and
482
+ methods. In this case you can declare field use `__field` method:
483
+
484
+ ```ruby
485
+ # __field <name>, [__alias: <alias name>], [__directives: <directives>], [<arguments>]
486
+
487
+ puts GraphQL::DSL.query {
488
+ __field(:class) { # `class` is Ruby's keyword
489
+ __field(:object_id) # `object_id` is `Object` method
490
+ }
491
+ }.to_gql
492
+ ```
493
+
494
+ <details>
495
+ <summary>STDOUT</summary>
496
+
497
+ ```graphql
498
+ {
499
+ class
500
+ {
501
+ object_id
502
+ }
503
+ }
504
+ ```
505
+ </details>
506
+
507
+ To rename field in GraphQL response specify alias in `__alias` argument:
508
+
509
+ ```ruby
510
+ puts GraphQL::DSL.query {
511
+ company {
512
+ name __alias: :businessName
513
+ }
514
+ }.to_gql
515
+ ```
516
+
517
+ <details>
518
+ <summary>STDOUT</summary>
519
+
520
+ ```graphql
521
+ {
522
+ company
523
+ {
524
+ businessName: name
525
+ }
526
+ }
527
+ ```
528
+ </details>
529
+
530
+ Some field can accept arguments and change their data base on them:
531
+
532
+ ```ruby
533
+ puts GraphQL::DSL.query {
534
+ company {
535
+ revenue currency: :RUB # convert revenue value to Russian Rubles
536
+ }
537
+ }.to_gql
538
+ ```
539
+
540
+ <details>
541
+ <summary>STDOUT</summary>
542
+
543
+ ```graphql
544
+ {
545
+ company
546
+ {
547
+ revenue(currency: RUB)
548
+ }
549
+ }
550
+ ```
551
+ </details>
552
+
553
+ Any field can have directives. Pass them though `__directives` argument:
554
+
555
+ ```ruby
556
+ using GraphQL::DSL # Required to refine `directive` method
557
+
558
+ puts GraphQL::DSL.query(:company, additionalInfo: :Boolean) {
559
+ company {
560
+ name
561
+ revenue __directives: [ directive(:include, if: :$additionalInfo) ]
562
+ }
563
+ }.to_gql
564
+ ```
565
+
566
+ <details>
567
+ <summary>STDOUT</summary>
568
+
569
+ ```graphql
570
+ query company($additionalInfo: Boolean)
571
+ {
572
+ company
573
+ {
574
+ name
575
+ revenue @include(if: $additionalInfo)
576
+ }
577
+ }
578
+ ```
579
+ </details>
580
+
581
+ ### Executable Documents
582
+
583
+ Executable Document helps to union several operations or fragments to one request:
584
+
585
+ ```ruby
586
+ puts GraphQL::DSL.executable_document {
587
+ query(:companies) {
588
+ company {
589
+ name
590
+ }
591
+ }
592
+
593
+ query(:rockets) {
594
+ rockets {
595
+ name
596
+ }
597
+ }
598
+ }.to_gql
599
+ ```
600
+
601
+ <details>
602
+ <summary>STDOUT</summary>
603
+
604
+ ```graphql
605
+ query companies
606
+ {
607
+ company
608
+ {
609
+ name
610
+ }
611
+ }
612
+
613
+ query rockets
614
+ {
615
+ rockets
616
+ {
617
+ name
618
+ }
619
+ }
620
+ ```
621
+ </details>
622
+
623
+ ### Fragments
624
+
625
+ Fragments may contains common repeated selections of fields and can be reused in different operations.
626
+ Each fragment must have a name, type and optional directives.
627
+
628
+ :bulb: _See more about type definitions [here](#types)._
629
+
630
+ ```ruby
631
+ # fragment(<fragment name>, <type>, [<directives>])
632
+
633
+ fragment(:ship, :Ship) {
634
+ id
635
+ name
636
+ }
637
+ ```
638
+
639
+ Fragment spread is using to insert fragment to other operations or fragments. Use `__frgment` command to create fragment
640
+ spread and insert fragment by its name.
641
+
642
+ ```ruby
643
+ # __fragment(<fragment name>, [__directives: <directives>])
644
+
645
+ puts GraphQL::DSL.executable_document {
646
+ query(:cargo_ships) {
647
+ ships(find: { type: "Cargo" }) {
648
+ __fragment :ship
649
+ }
650
+ }
651
+ query(:barges) {
652
+ ships(find: { type: "Barge" }) {
653
+ __fragment :ship
654
+ }
655
+ }
656
+
657
+ fragment(:ship, :Ship) {
658
+ id
659
+ name
660
+ }
661
+ }.to_gql
662
+ ```
663
+
664
+ <details>
665
+ <summary>STDOUT</summary>
666
+
667
+ ```graphql
668
+ query cargo_ships
669
+ {
670
+ ships(find: {type: "Cargo"})
671
+ {
672
+ ...ship
673
+ }
674
+ }
675
+
676
+ query barges
677
+ {
678
+ ships(find: {type: "Barge"})
679
+ {
680
+ ...ship
681
+ }
682
+ }
683
+
684
+ fragment ship on Ship
685
+ {
686
+ id
687
+ name
688
+ }
689
+ ```
690
+ </details>
691
+
692
+ ### Inline fragments
693
+
694
+ Inline fragments helps to define fields from heterogeneous collections
695
+ (collections which can contains different types of objects). Use `__inline_fragment` to insert inline fragment
696
+ to operation or fragment.
697
+
698
+ :bulb: _See more about type definitions [here](#types)._
699
+
700
+ ```ruby
701
+ # __inline_fragment([<type>]) { Selections Set }
702
+
703
+ puts GraphQL::DSL.query {
704
+ messages {
705
+ __inline_fragment(:AdSection) {
706
+ title
707
+ image
708
+ }
709
+
710
+ __inline_fragment(:MessageSection) {
711
+ title
712
+ message
713
+ author
714
+ }
715
+ }
716
+ }.to_gql
717
+ ```
718
+
719
+ <details>
720
+ <summary>STDOUT</summary>
721
+
722
+ ```graphql
723
+ {
724
+ messages
725
+ {
726
+ ... on AdSection
727
+ {
728
+ title
729
+ image
730
+ }
731
+ ... on MessageSection
732
+ {
733
+ title
734
+ message
735
+ author
736
+ }
737
+ }
738
+ }
739
+ ```
740
+ </details>
741
+
742
+ Inline fragments may also be used to apply a directive to a group of fields:
743
+
744
+ ```ruby
745
+ using GraphQL::DSL # Required to refine `directive` method
746
+
747
+ # __inline_fragment([<type>]) { Selections Set }
748
+
749
+ puts GraphQL::DSL.query(:company, additionalInfo: :Boolean) {
750
+ company {
751
+ name
752
+
753
+ __inline_fragment(nil, __directives: [ directive(:include, if: :$additionalInfo) ]) {
754
+ revenue
755
+ valuation
756
+ }
757
+ }
758
+ }.to_gql
759
+ ```
760
+
761
+ <details>
762
+ <summary>STDOUT</summary>
763
+
764
+ ```graphql
765
+ query company($additionalInfo: Boolean)
766
+ {
767
+ company
768
+ {
769
+ name
770
+ ... @include(if: $additionalInfo)
771
+ {
772
+ revenue
773
+ valuation
774
+ }
775
+ }
776
+ }
777
+ ```
778
+ </details>
779
+
780
+ ### Directives
781
+
782
+ :warning: Non-official SpaceX GraphQL API doesn't support any directives therefore examples below will be fail with error.
783
+
784
+ Choose appropriate notation to define directive:
785
+
786
+ <details>
787
+ <summary>Use <code>Symbol</code> or <code>String</code></summary>
788
+
789
+ ```ruby
790
+ # (:<name> | "name"), ...
791
+
792
+ puts GraphQL::DSL.query(:rockets, {}, [ :lowPriority ]) {
793
+ rockets {
794
+ name
795
+ }
796
+ }.to_gql
797
+ ```
798
+
799
+ ```graphql
800
+ query rockets @lowPriority
801
+ {
802
+ rockets
803
+ {
804
+ name
805
+ }
806
+ }
807
+ ```
808
+ </details>
809
+
810
+ <details>
811
+ <summary>Use refined <code>directive</code> method</summary>
812
+
813
+ ```ruby
814
+ # directive(<directive name>, [<arguments>]), ...
815
+
816
+ using GraphQL::DSL # Include refined `directive` method
817
+
818
+ puts GraphQL::DSL.query(:rockets, {}, [ directive(:lowPriority) ]) {
819
+ rockets {
820
+ name
821
+ }
822
+ }.to_gql
823
+ ```
824
+
825
+ ```graphql
826
+ query rockets @lowPriority
827
+ {
828
+ rockets
829
+ {
830
+ name
831
+ }
832
+ }
833
+ ```
834
+ </details>
835
+
836
+ ### Types
837
+
838
+ Types for operation variables and fragments may be declared in several ways in GraphQL DSL.
839
+
840
+ #### Named Types
841
+
842
+ Named Type can be declared like a symbol or string, for instance: `:Int`, `'Int'`
843
+
844
+ #### List Types
845
+
846
+ List Type can be declared like a string only, for instance: `'[Int]'`
847
+
848
+ #### Not Null Types
849
+
850
+ Not Null Type can be declared like a string or symbol, for instance: `:Int!`, `'Int!'`, `'[Int!]!'`
851
+
852
+ ## 🚲 Example
853
+
854
+ [graphql-dsl-example](https://github.com/maxd/graphql-dsl-example) shows how to use GraphQL DSL in Ruby applications.
855
+
856
+ ## Roadmap
857
+
858
+ * [ ] `[Fearure]` Implement `ExecutableDocument#include` to include external operations
859
+ * [ ] `[Fearure]` Strict validation of any argument
860
+ * [ ] `[Fearure]` Compact format of GraphQL queries
861
+ * [ ] `[Improvement]` Overload `__inline_fragment` for signature without type
862
+
863
+ ## 💻 Development
864
+
865
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests.
866
+ You can also run `bin/console` for an interactive prompt that will allow you to experiment.
867
+
868
+ To release a new version:
869
+
870
+ * update the version number in `lib/graphql/dsl/version.rb` file
871
+ * run `bundle exec rake readme:update` to update `README.md` file
872
+ * run `bundle exec rake release` to create a git tag for the version, push git commits and the created tag,
873
+ and push the `.gem` file to [rubygems.org](https://rubygems.org).
874
+
875
+ ## 👍 Contributing
876
+
877
+ Contributions are what make the open source community such an amazing place to learn, inspire, and create.
878
+ Any contributions you make are **greatly appreciated**.
879
+
880
+ 1. Fork the Project
881
+ 2. Create your Feature Branch (`git checkout -b feature/NewFeature`)
882
+ 3. Commit your Changes (`git commit -m 'Add some NewFeature'`)
883
+ 4. Push to the Branch (`git push origin feature/NewFeature`)
884
+ 5. Open a Pull Request
885
+
886
+ ## 📜 License
887
+
888
+ Distributed under the MIT License. See `LICENSE` for more information.
889
+
890
+ ## 🥰 Code of Conduct
891
+
892
+ Everyone interacting in the GraphQL DSL project's codebases and issue trackers is expected to
893
+ follow the [code of conduct](https://github.com/maxd/graphql-dsl/blob/master/CODE_OF_CONDUCT.md).
894
+
895
+ ## 📚 Resources
896
+
897
+ * [Introduction to GraphQL](https://graphql.org/learn/)
898
+ * [GraphQL Specification](https://spec.graphql.org/)
899
+ * Inspired by [gqli.rb](https://github.com/contentful-labs/gqli.rb) gem