gqli 0.3.0 → 0.4.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 +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +4 -0
- data/README.md +28 -0
- data/lib/gqli/enum_value.rb +17 -0
- data/lib/gqli/node.rb +15 -2
- data/lib/gqli/validation.rb +20 -2
- data/lib/gqli/version.rb +1 -1
- data/spec/lib/gqli/dsl_spec.rb +14 -0
- data/spec/lib/gqli/introspection_spec.rb +93 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 972ad0f4a3e57ffe7e87a9492805b5d206ff0825ac335dbbf4a24b4981aed375
|
4
|
+
data.tar.gz: d60e39618526584c5291bfe1fa050e1639cc458e01d1038bb62e88693764c833
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40b7e0a94c6c543993131280bb00dc56e9d7600c9dc698970f66ccb3ff67613820c35199d60f74d7c2ec75417f52bd73ce528b9263193b70ed7e5a6498bc835f
|
7
|
+
data.tar.gz: 00c23e2e51019bcf85a608507062d0fb46662b008674e09c546aa6151bedbb45d3c4098fd0e7fcc247d39794d96315003544429a9dd097dda172bec6ee2f36d1
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -291,6 +291,34 @@ query = GQLi::DSL.query {
|
|
291
291
|
}
|
292
292
|
```
|
293
293
|
|
294
|
+
### Directives
|
295
|
+
|
296
|
+
In GraphQL, nodes can be selectively included or removed by the usage of directives, there are 2 directives available for the querying specification to do this: `@include` and `@skip`.
|
297
|
+
|
298
|
+
```ruby
|
299
|
+
query = GQLi::DSL.query {
|
300
|
+
someNode(:@include => {if: object.includes_some_node?})
|
301
|
+
}
|
302
|
+
```
|
303
|
+
|
304
|
+
This will get transformed to:
|
305
|
+
|
306
|
+
```graphql
|
307
|
+
query {
|
308
|
+
someNode @include(if: true) # or false
|
309
|
+
}
|
310
|
+
```
|
311
|
+
|
312
|
+
This behaviour is equivalent to using native Ruby to include/exclude a field from the query:
|
313
|
+
|
314
|
+
```ruby
|
315
|
+
query = GQLi::DSL.query {
|
316
|
+
someNode if object.includes_some_node?
|
317
|
+
}
|
318
|
+
```
|
319
|
+
|
320
|
+
The difference is that by using the native implementation, in case of the condition not being met, the node will be completely not included in the outgoing query.
|
321
|
+
|
294
322
|
## Yet to be implemented
|
295
323
|
|
296
324
|
* Mutation queries
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GQLi
|
4
|
+
# Wrapper for Enum values
|
5
|
+
class EnumValue
|
6
|
+
attr_reader :value
|
7
|
+
|
8
|
+
def initialize(value)
|
9
|
+
@value = value
|
10
|
+
end
|
11
|
+
|
12
|
+
# Serializes the enum value to string
|
13
|
+
def to_s
|
14
|
+
value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/gqli/node.rb
CHANGED
@@ -15,7 +15,7 @@ module GQLi
|
|
15
15
|
# Serializes to a GraphQL string
|
16
16
|
def to_gql
|
17
17
|
result = ' ' * __depth + __name
|
18
|
-
result +=
|
18
|
+
result += __params_to_s(__params, true) unless __params.empty?
|
19
19
|
unless __nodes.empty?
|
20
20
|
result += " {\n"
|
21
21
|
result += __nodes.map(&:to_gql).join("\n")
|
@@ -27,14 +27,27 @@ module GQLi
|
|
27
27
|
|
28
28
|
private
|
29
29
|
|
30
|
+
def __directive?(params)
|
31
|
+
params.size == 1 && params.keys.first.to_s.start_with?('@')
|
32
|
+
end
|
33
|
+
|
34
|
+
def __directive(params)
|
35
|
+
params.first.tap do |directive, directive_params|
|
36
|
+
return " #{directive}#{__params_to_s(directive_params, true)}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
30
40
|
def __params_to_s(params, initial = false)
|
31
41
|
case params
|
32
42
|
when ::Hash
|
43
|
+
return __directive(params) if __directive?(params)
|
44
|
+
|
33
45
|
result = params.map do |k, v|
|
34
46
|
"#{k}: #{__params_to_s(v)}"
|
35
47
|
end.join(', ')
|
36
48
|
|
37
|
-
return result if initial
|
49
|
+
return "(#{result})" if initial
|
50
|
+
|
38
51
|
"{#{result}}"
|
39
52
|
when ::Array
|
40
53
|
"[#{params.map { |p| __params_to_s(p) }.join(', ')}]"
|
data/lib/gqli/validation.rb
CHANGED
@@ -44,7 +44,7 @@ module GQLi
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def validate_node(parent_type, node)
|
47
|
-
|
47
|
+
validate_directives(node)
|
48
48
|
|
49
49
|
return valid_match_node?(parent_type, node) if node.__name.start_with?('... on')
|
50
50
|
|
@@ -66,8 +66,26 @@ module GQLi
|
|
66
66
|
fail "Match type '#{node.__name.gsub('... on ', '')}' invalid"
|
67
67
|
end
|
68
68
|
|
69
|
+
def validate_directives(node)
|
70
|
+
return unless node.__params.size == 1
|
71
|
+
node.__params.first.tap do |k, v|
|
72
|
+
break unless k.to_s.start_with?('@')
|
73
|
+
|
74
|
+
fail "Directive unknown '#{k}'" unless %i[@include @skip].include?(k)
|
75
|
+
fail "Missing arguments for directive '#{k}'" if v.nil? || !v.is_a?(::Hash) || v.empty?
|
76
|
+
v.each do |arg, value|
|
77
|
+
begin
|
78
|
+
fail "Invalid argument '#{arg}' for directive '#{k}'" if arg.to_s != 'if'
|
79
|
+
fail "Invalid value for 'if`, must be a boolean" if value != !!value
|
80
|
+
rescue StandardError => e
|
81
|
+
errors << e
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
69
87
|
def validate_params(node_type, node)
|
70
|
-
node.__params.each do |param, value|
|
88
|
+
node.__params.reject { |p, _| p.to_s.start_with?('@') }.each do |param, value|
|
71
89
|
begin
|
72
90
|
arg = node_type.fetch('args', []).find { |a| a.name == param.to_s }
|
73
91
|
fail "Invalid argument '#{param}'" if arg.nil?
|
data/lib/gqli/version.rb
CHANGED
data/spec/lib/gqli/dsl_spec.rb
CHANGED
@@ -116,6 +116,20 @@ describe GQLi::DSL do
|
|
116
116
|
GRAPHQL
|
117
117
|
end
|
118
118
|
|
119
|
+
it 'nodes can have directives' do
|
120
|
+
query = subject.query {
|
121
|
+
someNode(:@include => {if: true})
|
122
|
+
otherNode(:@skip => {if: false})
|
123
|
+
}
|
124
|
+
|
125
|
+
expect(query.to_gql).to eq <<~GRAPHQL
|
126
|
+
query {
|
127
|
+
someNode @include(if: true)
|
128
|
+
otherNode @skip(if: false)
|
129
|
+
}
|
130
|
+
GRAPHQL
|
131
|
+
end
|
132
|
+
|
119
133
|
it 'nodes can have arbitrarily nested nodes' do
|
120
134
|
query = subject.query {
|
121
135
|
aNode {
|
@@ -155,5 +155,98 @@ describe GQLi::Introspection do
|
|
155
155
|
expect(validation.errors).not_to be_empty
|
156
156
|
expect(validation.errors.map(&:to_s)).to include("Value is 'String, Enum or ID', but should be 'Int' for 'limit'")
|
157
157
|
end
|
158
|
+
|
159
|
+
describe 'directives' do
|
160
|
+
it 'can create a query with a directive and validations should not fail' do
|
161
|
+
query = dsl.query {
|
162
|
+
catCollection {
|
163
|
+
items {
|
164
|
+
name(:@include => { if: true })
|
165
|
+
}
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
validation = subject.validate(query)
|
170
|
+
expect(validation.valid?).to be_truthy
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'unknown directives will fail' do
|
174
|
+
query = dsl.query {
|
175
|
+
catCollection(:@unknownDirective => nil)
|
176
|
+
}
|
177
|
+
|
178
|
+
validation = subject.validate(query)
|
179
|
+
expect(validation.valid?).to be_falsey
|
180
|
+
expect(validation.errors).not_to be_empty
|
181
|
+
expect(validation.errors.map(&:to_s)).to include("Directive unknown '@unknownDirective'")
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'known directive will fail if no arguments are passed' do
|
185
|
+
query = dsl.query {
|
186
|
+
catCollection(:@include => nil)
|
187
|
+
}
|
188
|
+
|
189
|
+
validation = subject.validate(query)
|
190
|
+
expect(validation.valid?).to be_falsey
|
191
|
+
expect(validation.errors).not_to be_empty
|
192
|
+
expect(validation.errors.map(&:to_s)).to include("Missing arguments for directive '@include'")
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'known directive will fail if arguments are empty' do
|
196
|
+
query = dsl.query {
|
197
|
+
catCollection(:@include => {})
|
198
|
+
}
|
199
|
+
|
200
|
+
validation = subject.validate(query)
|
201
|
+
expect(validation.valid?).to be_falsey
|
202
|
+
expect(validation.errors).not_to be_empty
|
203
|
+
expect(validation.errors.map(&:to_s)).to include("Missing arguments for directive '@include'")
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'known directive will fail if arguments is not if' do
|
207
|
+
query = dsl.query {
|
208
|
+
catCollection {
|
209
|
+
items {
|
210
|
+
name(:@include => { else: true })
|
211
|
+
}
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
validation = subject.validate(query)
|
216
|
+
expect(validation.valid?).to be_falsey
|
217
|
+
expect(validation.errors).not_to be_empty
|
218
|
+
expect(validation.errors.map(&:to_s)).to include("Invalid argument 'else' for directive '@include'")
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'known directive will fail when if value is not boolean' do
|
222
|
+
query = dsl.query {
|
223
|
+
catCollection {
|
224
|
+
items {
|
225
|
+
name(:@include => { if: 123 })
|
226
|
+
}
|
227
|
+
}
|
228
|
+
}
|
229
|
+
|
230
|
+
validation = subject.validate(query)
|
231
|
+
expect(validation.valid?).to be_falsey
|
232
|
+
expect(validation.errors).not_to be_empty
|
233
|
+
expect(validation.errors.map(&:to_s)).to include("Invalid value for 'if`, must be a boolean")
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'known directive will fail when multiple arguments are passed' do
|
237
|
+
query = dsl.query {
|
238
|
+
catCollection {
|
239
|
+
items {
|
240
|
+
name(:@include => { if: true, else: false })
|
241
|
+
}
|
242
|
+
}
|
243
|
+
}
|
244
|
+
|
245
|
+
validation = subject.validate(query)
|
246
|
+
expect(validation.valid?).to be_falsey
|
247
|
+
expect(validation.errors).not_to be_empty
|
248
|
+
expect(validation.errors.map(&:to_s)).to include("Invalid argument 'else' for directive '@include'")
|
249
|
+
end
|
250
|
+
end
|
158
251
|
end
|
159
252
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gqli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Contentful GmbH (David Litvak Bruno)
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http
|
@@ -311,6 +311,7 @@ files:
|
|
311
311
|
- doc/GQLi/Base.html
|
312
312
|
- doc/GQLi/Client.html
|
313
313
|
- doc/GQLi/DSL.html
|
314
|
+
- doc/GQLi/EnumValue.html
|
314
315
|
- doc/GQLi/Fragment.html
|
315
316
|
- doc/GQLi/Introspection.html
|
316
317
|
- doc/GQLi/Node.html
|
@@ -338,6 +339,7 @@ files:
|
|
338
339
|
- lib/gqli/base.rb
|
339
340
|
- lib/gqli/client.rb
|
340
341
|
- lib/gqli/dsl.rb
|
342
|
+
- lib/gqli/enum_value.rb
|
341
343
|
- lib/gqli/fragment.rb
|
342
344
|
- lib/gqli/introspection.rb
|
343
345
|
- lib/gqli/node.rb
|