graphql-dsl 1.0.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.
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