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.
- checksums.yaml +7 -0
- data/.github/workflows/main.yml +23 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.rubocop.yml +44 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +64 -0
- data/LICENSE.txt +21 -0
- data/README.md +899 -0
- data/Rakefile +6 -0
- data/bin/console +15 -0
- data/bin/setup +7 -0
- data/graphql-dsl.gemspec +38 -0
- data/lib/graphql/dsl/constants.rb +9 -0
- data/lib/graphql/dsl/error.rb +32 -0
- data/lib/graphql/dsl/formatter/arguments.rb +26 -0
- data/lib/graphql/dsl/formatter/directives.rb +52 -0
- data/lib/graphql/dsl/formatter/executable_document.rb +22 -0
- data/lib/graphql/dsl/formatter/field.rb +49 -0
- data/lib/graphql/dsl/formatter/formatter.rb +41 -0
- data/lib/graphql/dsl/formatter/fragment_operation.rb +41 -0
- data/lib/graphql/dsl/formatter/fragment_spread.rb +25 -0
- data/lib/graphql/dsl/formatter/inline_fragment.rb +43 -0
- data/lib/graphql/dsl/formatter/operation.rb +60 -0
- data/lib/graphql/dsl/formatter/values.rb +146 -0
- data/lib/graphql/dsl/formatter/variable_definitions.rb +43 -0
- data/lib/graphql/dsl/nodes/containers/directive.rb +46 -0
- data/lib/graphql/dsl/nodes/containers/variable_definition.rb +52 -0
- data/lib/graphql/dsl/nodes/executable_document.rb +69 -0
- data/lib/graphql/dsl/nodes/field.rb +39 -0
- data/lib/graphql/dsl/nodes/fragment_operation.rb +36 -0
- data/lib/graphql/dsl/nodes/fragment_spread.rb +24 -0
- data/lib/graphql/dsl/nodes/inline_fragment.rb +34 -0
- data/lib/graphql/dsl/nodes/mixins/selection_set.rb +106 -0
- data/lib/graphql/dsl/nodes/node.rb +39 -0
- data/lib/graphql/dsl/nodes/operation.rb +61 -0
- data/lib/graphql/dsl/version.rb +9 -0
- data/lib/graphql/dsl.rb +230 -0
- data/lib/graphql-dsl.rb +3 -0
- data/lib/graphql_dsl.rb +36 -0
- data/tasks/readme/update.rake +143 -0
- metadata +173 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module DSL
|
5
|
+
##
|
6
|
+
# Container for directive
|
7
|
+
class Directive
|
8
|
+
##
|
9
|
+
# @return [String, Symbol, nil] directive name
|
10
|
+
attr_reader :name
|
11
|
+
|
12
|
+
##
|
13
|
+
# @return [Hash] arguments
|
14
|
+
attr_reader :arguments
|
15
|
+
|
16
|
+
##
|
17
|
+
# Create directive container
|
18
|
+
#
|
19
|
+
# @param name [String, Symbol] directive name
|
20
|
+
# @param arguments [Hash] arguments
|
21
|
+
def initialize(name, arguments = {})
|
22
|
+
raise Error, 'Variable name must be specified' if name.nil? || name.empty?
|
23
|
+
|
24
|
+
@name = name
|
25
|
+
@arguments = arguments
|
26
|
+
end
|
27
|
+
|
28
|
+
class << self
|
29
|
+
##
|
30
|
+
# Create directive container from argument value
|
31
|
+
#
|
32
|
+
# @param value [] argument value
|
33
|
+
#
|
34
|
+
# @return [Directive] directive container
|
35
|
+
def from(value)
|
36
|
+
case value
|
37
|
+
when Directive then value
|
38
|
+
when Symbol, String then new(value)
|
39
|
+
else
|
40
|
+
raise Error.new('Unsupported format of directive', class: value.class.name, value: value)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module DSL
|
5
|
+
##
|
6
|
+
# Container for variable definition
|
7
|
+
class VariableDefinition
|
8
|
+
##
|
9
|
+
# @return [String, Symbol, nil] variable type
|
10
|
+
attr_reader :type
|
11
|
+
|
12
|
+
##
|
13
|
+
# @return [Object, nil] default value of variable
|
14
|
+
attr_reader :default
|
15
|
+
|
16
|
+
##
|
17
|
+
# @return [Array<Directive>] list of directives
|
18
|
+
attr_reader :directives
|
19
|
+
|
20
|
+
##
|
21
|
+
# Create variable definition container
|
22
|
+
#
|
23
|
+
# @param type [String, Symbol] variable type
|
24
|
+
# @param default [Object, nil] default value
|
25
|
+
# @param directives [Array<Directive, Hash, Array>] list of directives
|
26
|
+
def initialize(type, default = UNDEFINED, directives = [])
|
27
|
+
raise Error, 'Variable type must be specified' if type.nil? || type.empty?
|
28
|
+
|
29
|
+
@type = type
|
30
|
+
@default = default
|
31
|
+
@directives = directives.map { |directive| Directive.from(directive) }
|
32
|
+
end
|
33
|
+
|
34
|
+
class << self
|
35
|
+
##
|
36
|
+
# Create variable definition container from argument value
|
37
|
+
#
|
38
|
+
# @param value [] argument value
|
39
|
+
#
|
40
|
+
# @return [VariableDefinition] variable definition container
|
41
|
+
def from(value)
|
42
|
+
case value
|
43
|
+
when VariableDefinition then value
|
44
|
+
when Symbol, String then new(value)
|
45
|
+
else
|
46
|
+
raise Error.new('Unsupported format of variable definition', class: value.class.name, value: value)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module DSL
|
5
|
+
##
|
6
|
+
# Executable document GraphQL node
|
7
|
+
class ExecutableDocument < Node
|
8
|
+
##
|
9
|
+
# Create executable document
|
10
|
+
#
|
11
|
+
# @param block [Proc] declare DSL for operations
|
12
|
+
def initialize(&block)
|
13
|
+
super(nil, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
##
|
17
|
+
# Create GraphQL query operation
|
18
|
+
#
|
19
|
+
# @param name [String, Symbol, nil] query name
|
20
|
+
# @param variable_definitions [Hash] variable definitions
|
21
|
+
# @param directives [Array<Directive, Hash, Array>] list of directives
|
22
|
+
# @param block [Proc] declare DSL for sub-fields
|
23
|
+
#
|
24
|
+
# @return [void]
|
25
|
+
def query(name = nil, variable_definitions = {}, directives = [], &block)
|
26
|
+
@__nodes << Operation.new(:query, name, variable_definitions, directives, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Create GraphQL mutation operation
|
31
|
+
#
|
32
|
+
# @param name [String, Symbol, nil] mutation name
|
33
|
+
# @param variable_definitions [Hash] variable definitions
|
34
|
+
# @param directives [Array<Directive, Hash, Array>] list of directives
|
35
|
+
# @param block [Proc] declare DSL for sub-fields
|
36
|
+
#
|
37
|
+
# @return [void]
|
38
|
+
def mutation(name = nil, variable_definitions = {}, directives = [], &block)
|
39
|
+
@__nodes << Operation.new(:mutation, name, variable_definitions, directives, &block)
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Create GraphQL subscription operation
|
44
|
+
#
|
45
|
+
# @param name [String, Symbol, nil] subscription name
|
46
|
+
# @param variable_definitions [Hash] variable definitions
|
47
|
+
# @param directives [Array<Directive, Hash, Array>] list of directives
|
48
|
+
# @param block [Proc] declare DSL for sub-fields
|
49
|
+
#
|
50
|
+
# @return [void]
|
51
|
+
def subscription(name = nil, variable_definitions = {}, directives = [], &block)
|
52
|
+
@__nodes << Operation.new(:subscription, name, variable_definitions, directives, &block)
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Create GraphQL fragment operation
|
57
|
+
#
|
58
|
+
# @param name [String, Symbol] fragment name
|
59
|
+
# @param type [String, Symbol] fragment type or interface
|
60
|
+
# @param directives [Array<Directive, Hash, Array>] list of directives
|
61
|
+
# @param block [Proc] declare DSL for sub-fields
|
62
|
+
#
|
63
|
+
# @return [void]
|
64
|
+
def fragment(name, type, directives = [], &block)
|
65
|
+
@__nodes << FragmentOperation.new(name, type, directives, &block)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module DSL
|
5
|
+
##
|
6
|
+
# Field GraphQL node
|
7
|
+
class Field < Node
|
8
|
+
include SelectionSet
|
9
|
+
|
10
|
+
##
|
11
|
+
# @return [String, Symbol, nil] field alias
|
12
|
+
attr_reader :__alias
|
13
|
+
|
14
|
+
##
|
15
|
+
# @return [Hash] list of filed arguments
|
16
|
+
attr_reader :__arguments
|
17
|
+
|
18
|
+
##
|
19
|
+
# @return [Array<Directive>] list of directives
|
20
|
+
attr_reader :__directives
|
21
|
+
|
22
|
+
##
|
23
|
+
# Create field
|
24
|
+
#
|
25
|
+
# @param field_name [String, Symbol] field name
|
26
|
+
# @param field_alias [String, Symbol, nil] field alias
|
27
|
+
# @param arguments [Hash] field arguments
|
28
|
+
# @param directives [Array<Directive, Hash, Array>] list of directives
|
29
|
+
# @param block [Proc] declare DSL for sub-fields
|
30
|
+
def initialize(field_name, field_alias = nil, arguments = {}, directives = [], &block)
|
31
|
+
@__alias = field_alias
|
32
|
+
@__arguments = arguments
|
33
|
+
@__directives = directives.map { |directive| Directive.from(directive) }
|
34
|
+
|
35
|
+
super(field_name, &block)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module DSL
|
5
|
+
##
|
6
|
+
# Fragment operation GraphQL node
|
7
|
+
class FragmentOperation < Node
|
8
|
+
include SelectionSet
|
9
|
+
|
10
|
+
##
|
11
|
+
# @return [String, Symbol] fragment type or interface
|
12
|
+
attr_reader :__type
|
13
|
+
|
14
|
+
##
|
15
|
+
# @return [Array<Directive>] list of directives
|
16
|
+
attr_reader :__directives
|
17
|
+
|
18
|
+
##
|
19
|
+
# Create fragment operation
|
20
|
+
#
|
21
|
+
# @param name [String, Symbol] fragment name
|
22
|
+
# @param type [String, Symbol] fragment type or interface
|
23
|
+
# @param directives [Array<Directive, Hash, Array>] list of directives
|
24
|
+
# @param block [Proc] declare DSL for sub-fields
|
25
|
+
def initialize(name, type, directives = [], &block)
|
26
|
+
raise Error, '`name` must be specified' if name.nil? || name.empty?
|
27
|
+
raise Error, '`type` must be specified' if type.nil? || type.empty?
|
28
|
+
|
29
|
+
@__type = type
|
30
|
+
@__directives = directives.map { |directive| Directive.from(directive) }
|
31
|
+
|
32
|
+
super(name, &block)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module DSL
|
5
|
+
##
|
6
|
+
# Fragment spread GraphQL node
|
7
|
+
class FragmentSpread < Node
|
8
|
+
##
|
9
|
+
# @return [Array<Directive>] list of directives
|
10
|
+
attr_reader :__directives
|
11
|
+
|
12
|
+
##
|
13
|
+
# Create fragment spread
|
14
|
+
#
|
15
|
+
# @param name [String, Symbol] fragment name
|
16
|
+
# @param directives [Array<Hash, Array, Directive>] list of directives
|
17
|
+
def initialize(name, directives = [])
|
18
|
+
@__directives = directives.map { |directive| Directive.from(directive) }
|
19
|
+
|
20
|
+
super(name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module DSL
|
5
|
+
##
|
6
|
+
# Inline fragment GraphQL node
|
7
|
+
class InlineFragment < Node
|
8
|
+
include SelectionSet
|
9
|
+
|
10
|
+
##
|
11
|
+
# @return [String, Symbol, nil] inline fragment type or interface
|
12
|
+
attr_reader :__type
|
13
|
+
|
14
|
+
##
|
15
|
+
# @return [Array<Directive>] list of directives
|
16
|
+
attr_reader :__directives
|
17
|
+
|
18
|
+
##
|
19
|
+
# Create inline fragment
|
20
|
+
#
|
21
|
+
# @param type [String, Symbol, nil] fragment type
|
22
|
+
# @param directives [Array<Directive, Hash, Array>] list of directives
|
23
|
+
# @param block [Proc] declare DSL for sub-fields
|
24
|
+
def initialize(type = nil, directives = [], &block)
|
25
|
+
raise Error, 'Sub-fields must be specified for inline fragment' if block.nil?
|
26
|
+
|
27
|
+
@__type = type
|
28
|
+
@__directives = directives.map { |directive| Directive.from(directive) }
|
29
|
+
|
30
|
+
super(nil, &block)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module DSL
|
5
|
+
##
|
6
|
+
# This mixin help to reuse selections sets
|
7
|
+
module SelectionSet
|
8
|
+
##
|
9
|
+
# Declare new GraphQL field
|
10
|
+
#
|
11
|
+
# This method can help to avoid name collisions i.e. +__field(:object_id)+
|
12
|
+
#
|
13
|
+
# @param name [String, Symbol] field name
|
14
|
+
# @param __alias [String, Symbol, nil] field alias
|
15
|
+
# @param __directives [Array] list of directives
|
16
|
+
# @param arguments [Hash] field arguments
|
17
|
+
# @param block [Proc] declare sub-fields
|
18
|
+
#
|
19
|
+
# @return [void]
|
20
|
+
#
|
21
|
+
# @example Declare fields use __field method (i.e. use GraphQL query)
|
22
|
+
# query = GraphQL::DSL.query {
|
23
|
+
# __field(:field1, id: 1) {
|
24
|
+
# __field(:subfield1, id: 1)
|
25
|
+
# __field(:subfield2, id: 2)
|
26
|
+
# }
|
27
|
+
# }
|
28
|
+
#
|
29
|
+
# @example Declare fields use DSL (i.e. use GraphQL query)
|
30
|
+
# query = GraphQL::DSL.query {
|
31
|
+
# field1 id: 1 {
|
32
|
+
# subfield1 id: 1
|
33
|
+
# subfield2 id: 2
|
34
|
+
# }
|
35
|
+
# }
|
36
|
+
def __field(name, __alias: nil, __directives: [], **arguments, &block) # rubocop:disable Lint/UnderscorePrefixedVariableName
|
37
|
+
@__nodes << Field.new(name, __alias, arguments, __directives, &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
###
|
41
|
+
# Insert GraphQL fragment
|
42
|
+
#
|
43
|
+
# @param name [String, Symbol] fragment name
|
44
|
+
# @param __directives [Array] list of directives
|
45
|
+
#
|
46
|
+
# @return [void]
|
47
|
+
#
|
48
|
+
# @example Insert fragment with +fragment1+ name
|
49
|
+
# query = GraphQL::DSL.query {
|
50
|
+
# field1 id: 1 {
|
51
|
+
# __fragment :fragment1
|
52
|
+
# }
|
53
|
+
# }
|
54
|
+
def __fragment(name, __directives: []) # rubocop:disable Lint/UnderscorePrefixedVariableName
|
55
|
+
@__nodes << FragmentSpread.new(name, __directives)
|
56
|
+
end
|
57
|
+
|
58
|
+
###
|
59
|
+
# Insert GraphQL inline fragment
|
60
|
+
#
|
61
|
+
# @param type [String, Symbol, nil] fragment type
|
62
|
+
# @param __directives [Array] list of directives
|
63
|
+
# @param block [Proc] declare DSL for sub-fields
|
64
|
+
#
|
65
|
+
# @return [void]
|
66
|
+
def __inline_fragment(type, __directives: [], &block) # rubocop:disable Lint/UnderscorePrefixedVariableName
|
67
|
+
@__nodes << InlineFragment.new(type, __directives, &block)
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
##
|
73
|
+
# Allow to respond to method missing at any case.
|
74
|
+
def respond_to_missing?(_method_name, _include_private = false)
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# Declare new GraphQL field
|
80
|
+
#
|
81
|
+
# @example Declare fields (i.e. use GraphQL query)
|
82
|
+
# query = GraphQL::DSL.query {
|
83
|
+
# items {
|
84
|
+
# id
|
85
|
+
# title
|
86
|
+
# }
|
87
|
+
# }
|
88
|
+
#
|
89
|
+
# puts query.to_gql
|
90
|
+
# # {
|
91
|
+
# # items
|
92
|
+
# # {
|
93
|
+
# # id
|
94
|
+
# # title
|
95
|
+
# # }
|
96
|
+
# # }
|
97
|
+
#
|
98
|
+
# @see #__field
|
99
|
+
def method_missing(name, *args, &block)
|
100
|
+
arguments = args.empty? ? {} : args[0]
|
101
|
+
|
102
|
+
__field(name, **arguments, &block)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module DSL
|
5
|
+
##
|
6
|
+
# @abstract Base class for all GraphQL DSL nodes
|
7
|
+
class Node
|
8
|
+
##
|
9
|
+
# @return [String, Symbol, nil] node name
|
10
|
+
attr_reader :__name
|
11
|
+
|
12
|
+
# @return [Array<Node>] list of sub-nodes
|
13
|
+
attr_reader :__nodes
|
14
|
+
|
15
|
+
##
|
16
|
+
# Create node
|
17
|
+
#
|
18
|
+
# @param name [String, Symbol, nil] node name
|
19
|
+
# @param block [Proc] declare DSL for sub-nodes
|
20
|
+
def initialize(name = nil, &block)
|
21
|
+
@__name = name
|
22
|
+
@__nodes = []
|
23
|
+
|
24
|
+
instance_eval(&block) if block
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Generate GraphQL query
|
29
|
+
#
|
30
|
+
# @param level [Integer] indent level
|
31
|
+
# @param formatter [Formatter] GraphQL query formatter
|
32
|
+
#
|
33
|
+
# @return [String] GraphQL query string
|
34
|
+
def to_gql(level = 0, formatter = Formatter.new)
|
35
|
+
formatter.format_node(self, level)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module DSL
|
5
|
+
##
|
6
|
+
# Operation GraphQL node
|
7
|
+
class Operation < Node
|
8
|
+
include SelectionSet
|
9
|
+
|
10
|
+
##
|
11
|
+
# @return [Symbol] operation type (see {#initialize})
|
12
|
+
attr_reader :__operation_type
|
13
|
+
|
14
|
+
##
|
15
|
+
# @return [Hash<Symbol, VariableDefinition>] variable definitions
|
16
|
+
attr_reader :__variable_definitions
|
17
|
+
|
18
|
+
##
|
19
|
+
# @return [Array<Directive>] list of directives
|
20
|
+
attr_reader :__directives
|
21
|
+
|
22
|
+
##
|
23
|
+
# Create operation (query, mutation, subscription)
|
24
|
+
#
|
25
|
+
# @param operation_type [Symbol] operation type
|
26
|
+
# @option operation_type [Symbol] :query query operation
|
27
|
+
# @option operation_type [Symbol] :mutation mutation operation
|
28
|
+
# @option operation_type [Symbol] :subscription subscription operation
|
29
|
+
# @param name [String, Symbol, nil] operation name
|
30
|
+
# @param variable_definitions [Hash] variable definitions
|
31
|
+
# @param directives [Array<Directive, Hash, Array>] list of directives
|
32
|
+
# @param block [Proc] declare DSL for sub-fields
|
33
|
+
def initialize(operation_type, name = nil, variable_definitions = {}, directives = [], &block)
|
34
|
+
variable_definitions.each do |variable_name, _|
|
35
|
+
raise Error, 'Variable name must be specified' if variable_name.nil? || variable_name.empty?
|
36
|
+
end
|
37
|
+
|
38
|
+
@__operation_type = operation_type
|
39
|
+
@__variable_definitions = variable_definitions.transform_values do |variable_definition|
|
40
|
+
VariableDefinition.from(variable_definition)
|
41
|
+
end
|
42
|
+
@__directives = directives.map { |directive| Directive.from(directive) }
|
43
|
+
|
44
|
+
super(name, &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Declare operation variable
|
49
|
+
#
|
50
|
+
# @param name [Symbol, String] variable name
|
51
|
+
# @param type [Symbol, String] variable type
|
52
|
+
# @param directives [Array<Directive, Hash, Array>] variable directives
|
53
|
+
# @param default [Object] variable default value
|
54
|
+
#
|
55
|
+
# @return [void]
|
56
|
+
def __var(name, type, default: UNDEFINED, directives: [])
|
57
|
+
@__variable_definitions[name] = VariableDefinition.new(type, default, directives)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|