gql 0.0.4 → 0.0.5
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/README.md +1 -1
- data/lib/gql.rb +16 -2
- data/lib/gql/call.rb +4 -3
- data/lib/gql/config.rb +4 -0
- data/lib/gql/errors.rb +11 -11
- data/lib/gql/executor.rb +2 -0
- data/lib/gql/field.rb +3 -2
- data/lib/gql/fields/array.rb +4 -1
- data/lib/gql/fields/connection.rb +2 -1
- data/lib/gql/fields/integer.rb +1 -3
- data/lib/gql/fields/object.rb +2 -1
- data/lib/gql/fields/string.rb +3 -11
- data/lib/gql/node.rb +34 -36
- data/lib/gql/parser.rb +3 -3
- data/lib/gql/parser.y +3 -3
- data/lib/gql/schema/call.rb +20 -0
- data/lib/gql/schema/connection.rb +7 -0
- data/lib/gql/schema/field.rb +20 -0
- data/lib/gql/schema/node.rb +17 -0
- data/lib/gql/schema/parameter.rb +32 -0
- data/lib/gql/schema/placeholder.rb +6 -0
- data/lib/gql/version.rb +1 -1
- metadata +7 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96bce7d738e7b21e2253ec10315f64b4fb33408e
|
4
|
+
data.tar.gz: c28e4961a061063f51703cd714eb646efb8465ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8069bf344b4c87f43b718f4b0b0a8ad2c30be35f186bf4d1f1e2f1119f356feef3c8a126982a177c860817d32dfa5b1c63d4268c96486f2272691e7f1593f59c
|
7
|
+
data.tar.gz: 18e1efe2c211f3579b12b808fdd842eb938c8f45f2b0b50049582e819adb6fe4f99eb33a2c0e6bb6a642b69acd20a04deb72f7054edc96001821f940cb2e237d
|
data/README.md
CHANGED
data/lib/gql.rb
CHANGED
@@ -11,7 +11,7 @@ module GQL
|
|
11
11
|
|
12
12
|
module Errors
|
13
13
|
autoload :InvalidNodeClass, 'gql/errors'
|
14
|
-
autoload :
|
14
|
+
autoload :SyntaxError, 'gql/errors'
|
15
15
|
autoload :UndefinedCall, 'gql/errors'
|
16
16
|
autoload :UndefinedField, 'gql/errors'
|
17
17
|
autoload :UndefinedNodeClass, 'gql/errors'
|
@@ -29,6 +29,15 @@ module GQL
|
|
29
29
|
autoload :String, 'gql/fields/string'
|
30
30
|
end
|
31
31
|
|
32
|
+
module Schema
|
33
|
+
autoload :Call, 'gql/schema/call'
|
34
|
+
autoload :Connection, 'gql/schema/connection'
|
35
|
+
autoload :Field, 'gql/schema/field'
|
36
|
+
autoload :Node, 'gql/schema/node'
|
37
|
+
autoload :Parameter, 'gql/schema/parameter'
|
38
|
+
autoload :Placeholder, 'gql/schema/placeholder'
|
39
|
+
end
|
40
|
+
|
32
41
|
extend(Module.new {
|
33
42
|
def config
|
34
43
|
Thread.current[:gql_config] ||= Config.new
|
@@ -69,9 +78,14 @@ module GQL
|
|
69
78
|
tokenizer = Tokenizer.new
|
70
79
|
tokenizer.scan_setup input
|
71
80
|
|
81
|
+
result = []
|
82
|
+
|
72
83
|
while token = tokenizer.next_token
|
73
|
-
|
84
|
+
result << token
|
85
|
+
yield token if block_given?
|
74
86
|
end
|
87
|
+
|
88
|
+
result
|
75
89
|
end
|
76
90
|
})
|
77
91
|
|
data/lib/gql/call.rb
CHANGED
@@ -12,10 +12,10 @@ module GQL
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
class_attribute :
|
15
|
+
class_attribute :id, :result_class, :method, instance_accessor: false, instance_predicate: false
|
16
16
|
|
17
17
|
class << self
|
18
|
-
def build_class(result_class, method)
|
18
|
+
def build_class(id, result_class, method)
|
19
19
|
if result_class.is_a? Array
|
20
20
|
result_class.unshift Connection if result_class.size == 1
|
21
21
|
result_class.unshift Fields::Connection if result_class.size == 2
|
@@ -27,12 +27,13 @@ module GQL
|
|
27
27
|
end
|
28
28
|
|
29
29
|
options = { connection_class: connection_class, node_class: node_class }
|
30
|
-
result_class = field_type_class.build_class(nil, options)
|
30
|
+
result_class = field_type_class.build_class(:result, nil, options)
|
31
31
|
elsif result_class && !(result_class <= Node)
|
32
32
|
raise Errors::InvalidNodeClass.new(result_class, Node)
|
33
33
|
end
|
34
34
|
|
35
35
|
Class.new(self).tap do |call_class|
|
36
|
+
call_class.id = id.to_s
|
36
37
|
call_class.method = method
|
37
38
|
call_class.result_class = result_class
|
38
39
|
end
|
data/lib/gql/config.rb
CHANGED
data/lib/gql/errors.rb
CHANGED
@@ -25,35 +25,35 @@ module GQL
|
|
25
25
|
end
|
26
26
|
|
27
27
|
class UndefinedFieldType < Error
|
28
|
-
def initialize(
|
29
|
-
types = GQL.field_types.keys.sort.map { |
|
28
|
+
def initialize(id)
|
29
|
+
types = GQL.field_types.keys.sort.map { |id| "`#{id}`" }
|
30
30
|
types = types.size > 0 ? " Available types: #{types.to_sentence}." : ''
|
31
31
|
|
32
|
-
super("The field type `#{
|
32
|
+
super("The field type `#{id}` is undefined. Define it with `GQL.field_types[:#{id}] = My#{id.to_s.camelize}`.#{types}")
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
class UndefinedCall < Error
|
37
|
-
def initialize(
|
38
|
-
calls = node_class.
|
37
|
+
def initialize(id, node_class)
|
38
|
+
calls = node_class.calls.keys.sort.map { |id| "`#{id}`" }
|
39
39
|
calls = calls.size > 0 ? " Available calls: #{calls.to_sentence}." : ''
|
40
40
|
|
41
|
-
super("#{node_class} has no call named `#{
|
41
|
+
super("#{node_class} has no call named `#{id}`.#{calls}")
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
45
|
class UndefinedField < Error
|
46
|
-
def initialize(
|
47
|
-
fields = node_class.
|
46
|
+
def initialize(id, node_class)
|
47
|
+
fields = node_class.fields.keys.sort.map { |id| "`#{id}`" }
|
48
48
|
fields = fields.size > 0 ? " Available fields: #{fields.to_sentence}." : ''
|
49
49
|
|
50
|
-
super("#{node_class} has no field named `#{
|
50
|
+
super("#{node_class} has no field named `#{id}`.#{fields}")
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
-
class
|
54
|
+
class SyntaxError < Error
|
55
55
|
def initialize(value, token)
|
56
|
-
token = '
|
56
|
+
token = 'character' if token == 'error' || token == %Q{"#{value}"}
|
57
57
|
|
58
58
|
super("Unexpected #{token}: `#{value}`.")
|
59
59
|
end
|
data/lib/gql/executor.rb
CHANGED
data/lib/gql/field.rb
CHANGED
@@ -14,11 +14,12 @@ module GQL
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
class_attribute :method, instance_accessor: false, instance_predicate: false
|
17
|
+
class_attribute :id, :method, instance_accessor: false, instance_predicate: false
|
18
18
|
|
19
19
|
class << self
|
20
|
-
def build_class(method, options = {})
|
20
|
+
def build_class(id, method, options = {})
|
21
21
|
Class.new(self).tap do |field_class|
|
22
|
+
field_class.id = id.to_s
|
22
23
|
field_class.method = method
|
23
24
|
end
|
24
25
|
end
|
data/lib/gql/fields/array.rb
CHANGED
@@ -6,7 +6,7 @@ module GQL
|
|
6
6
|
class_attribute :node_class, instance_accessor: false, instance_predicate: false
|
7
7
|
|
8
8
|
class << self
|
9
|
-
def build_class(method, options = {})
|
9
|
+
def build_class(id, method, options = {})
|
10
10
|
node_class = options[:node_class] || self.node_class
|
11
11
|
|
12
12
|
if node_class.nil?
|
@@ -18,12 +18,15 @@ module GQL
|
|
18
18
|
end
|
19
19
|
|
20
20
|
Class.new(self).tap do |field_class|
|
21
|
+
field_class.id = id.to_s
|
21
22
|
field_class.method = method
|
22
23
|
field_class.node_class = node_class
|
23
24
|
end
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
28
|
+
call :size, Integer, -> { target.size }
|
29
|
+
|
27
30
|
def value
|
28
31
|
target.map do |item|
|
29
32
|
node = self.class.node_class.new(ast_node, item, variables, context)
|
@@ -7,7 +7,7 @@ module GQL
|
|
7
7
|
self.connection_class = GQL::Connection
|
8
8
|
|
9
9
|
class << self
|
10
|
-
def build_class(method, options = {})
|
10
|
+
def build_class(id, method, options = {})
|
11
11
|
connection_class = options[:connection_class] || self.connection_class
|
12
12
|
|
13
13
|
if connection_class.nil?
|
@@ -19,6 +19,7 @@ module GQL
|
|
19
19
|
end
|
20
20
|
|
21
21
|
Class.new(self).tap do |field_class|
|
22
|
+
field_class.id = id.to_s
|
22
23
|
field_class.method = method
|
23
24
|
field_class.connection_class = connection_class.build_class(options[:node_class])
|
24
25
|
end
|
data/lib/gql/fields/integer.rb
CHANGED
data/lib/gql/fields/object.rb
CHANGED
@@ -6,7 +6,7 @@ module GQL
|
|
6
6
|
class_attribute :node_class, instance_accessor: false, instance_predicate: false
|
7
7
|
|
8
8
|
class << self
|
9
|
-
def build_class(method, options = {})
|
9
|
+
def build_class(id, method, options = {})
|
10
10
|
node_class = options[:node_class] || self.node_class
|
11
11
|
|
12
12
|
if node_class.nil?
|
@@ -18,6 +18,7 @@ module GQL
|
|
18
18
|
end
|
19
19
|
|
20
20
|
Class.new(self).tap do |field_class|
|
21
|
+
field_class.id = id.to_s
|
21
22
|
field_class.method = method
|
22
23
|
field_class.node_class = node_class
|
23
24
|
end
|
data/lib/gql/fields/string.rb
CHANGED
@@ -1,17 +1,9 @@
|
|
1
1
|
module GQL
|
2
2
|
module Fields
|
3
3
|
class String < Field
|
4
|
-
call :upcase
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
call :downcase do
|
9
|
-
target.downcase
|
10
|
-
end
|
11
|
-
|
12
|
-
call :length, returns: Integer do
|
13
|
-
target.size
|
14
|
-
end
|
4
|
+
call :upcase, -> { target.upcase }
|
5
|
+
call :downcase, -> { target.downcase }
|
6
|
+
call :length, Integer, -> { target.size }
|
15
7
|
|
16
8
|
# These are just example calls, monkeypatch to add your own.
|
17
9
|
end
|
data/lib/gql/node.rb
CHANGED
@@ -4,59 +4,57 @@ require 'active_support/core_ext/array/extract_options'
|
|
4
4
|
|
5
5
|
module GQL
|
6
6
|
class Node
|
7
|
-
class_attribute :
|
7
|
+
class_attribute :calls, :fields, instance_accessor: false, instance_predicate: false
|
8
8
|
|
9
|
-
self.
|
10
|
-
self.
|
9
|
+
self.calls = {}
|
10
|
+
self.fields = {}
|
11
11
|
|
12
12
|
class << self
|
13
|
-
def call(
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
names_with_result_class[name] = nil
|
13
|
+
def call(id, result_class = nil, body = nil)
|
14
|
+
if body.nil? && result_class.is_a?(Proc)
|
15
|
+
body = result_class
|
16
|
+
result_class = nil
|
18
17
|
end
|
19
18
|
|
20
|
-
|
21
|
-
method = block || lambda { |*args| target.public_send(name, *args) }
|
22
|
-
call_class = Call.build_class(result_class, method)
|
19
|
+
body ||= lambda { |*args| target.public_send(id, *args) }
|
23
20
|
|
24
|
-
|
25
|
-
|
26
|
-
|
21
|
+
call_class = Call.build_class(id, result_class, body)
|
22
|
+
|
23
|
+
self.const_set "#{id.to_s.camelize}Call", call_class
|
24
|
+
self.calls = calls.merge(id.to_sym => call_class)
|
27
25
|
end
|
28
26
|
|
29
|
-
def field(*
|
30
|
-
options =
|
27
|
+
def field(*ids, &block)
|
28
|
+
options = ids.extract_options!
|
31
29
|
|
32
|
-
|
33
|
-
method = block || lambda { target.public_send(
|
30
|
+
ids.each do |id|
|
31
|
+
method = block || lambda { target.public_send(id) }
|
34
32
|
field_type_class = options.delete(:field_type_class) || Field
|
35
33
|
|
36
34
|
unless field_type_class <= Field
|
37
35
|
raise Errors::InvalidNodeClass.new(field_type_class, Field)
|
38
36
|
end
|
39
37
|
|
40
|
-
field_class = field_type_class.build_class(method, options)
|
38
|
+
field_class = field_type_class.build_class(id, method, options)
|
41
39
|
|
42
|
-
self.const_set "#{
|
43
|
-
self.
|
40
|
+
self.const_set "#{id.to_s.camelize}Field", field_class
|
41
|
+
self.fields = fields.merge(id.to_sym => field_class)
|
44
42
|
end
|
45
43
|
end
|
46
44
|
|
47
|
-
def cursor(
|
48
|
-
if
|
49
|
-
field :cursor, &-> { target.public_send(
|
45
|
+
def cursor(id = nil, &block)
|
46
|
+
if id
|
47
|
+
field :cursor, &-> { target.public_send(id) }
|
50
48
|
elsif block_given?
|
51
49
|
field :cursor, &block
|
52
50
|
end
|
53
51
|
end
|
54
52
|
|
55
|
-
def method_missing(method, *
|
53
|
+
def method_missing(method, *ids, &block)
|
56
54
|
if field_type_class = GQL.field_types[method]
|
57
|
-
options =
|
55
|
+
options = ids.extract_options!
|
58
56
|
|
59
|
-
field(*
|
57
|
+
field(*ids, options.merge(field_type_class: field_type_class), &block)
|
60
58
|
else
|
61
59
|
super
|
62
60
|
end
|
@@ -83,10 +81,10 @@ module GQL
|
|
83
81
|
end
|
84
82
|
|
85
83
|
def value_of_call(ast_call)
|
86
|
-
call_class = self.class.
|
84
|
+
call_class = self.class.calls[ast_call.id]
|
87
85
|
|
88
86
|
if call_class.nil?
|
89
|
-
raise Errors::UndefinedCall.new(ast_call.
|
87
|
+
raise Errors::UndefinedCall.new(ast_call.id, self.class)
|
90
88
|
end
|
91
89
|
|
92
90
|
call = call_class.new(self, ast_call, target, variables, context)
|
@@ -95,28 +93,28 @@ module GQL
|
|
95
93
|
|
96
94
|
def value_of_fields(ast_fields)
|
97
95
|
ast_fields.reduce({}) do |memo, ast_field|
|
98
|
-
key = ast_field.
|
96
|
+
key = ast_field.alias_id || ast_field.id
|
99
97
|
|
100
98
|
memo.merge key => value_of_field(ast_field)
|
101
99
|
end
|
102
100
|
end
|
103
101
|
|
104
102
|
def value_of_field(ast_field)
|
105
|
-
case ast_field.
|
103
|
+
case ast_field.id
|
106
104
|
when :node
|
107
105
|
field = self.class.new(ast_field, target, variables, context)
|
108
106
|
field.value
|
109
107
|
else
|
110
|
-
|
111
|
-
field_class = self.class.field_classes[ast_field.name]
|
108
|
+
field_class = self.class.fields[ast_field.id]
|
112
109
|
|
113
110
|
if field_class.nil?
|
114
|
-
raise Errors::UndefinedField.new(ast_field.
|
111
|
+
raise Errors::UndefinedField.new(ast_field.id, self.class)
|
115
112
|
end
|
116
113
|
|
117
|
-
|
114
|
+
method = Field::Method.new(target, context)
|
115
|
+
target = method.execute(field_class.method)
|
118
116
|
|
119
|
-
field = field_class.new(ast_field,
|
117
|
+
field = field_class.new(ast_field, target, variables, context)
|
120
118
|
field.value
|
121
119
|
end
|
122
120
|
end
|
data/lib/gql/parser.rb
CHANGED
@@ -21,10 +21,10 @@ module_eval(<<'...end parser.y/module_eval...', 'parser.y', 133)
|
|
21
21
|
class Node < Struct.new(:call, :fields)
|
22
22
|
end
|
23
23
|
|
24
|
-
class Field < Struct.new(:
|
24
|
+
class Field < Struct.new(:id, :alias_id, :call, :fields)
|
25
25
|
end
|
26
26
|
|
27
|
-
class Call < Struct.new(:
|
27
|
+
class Call < Struct.new(:id, :arguments, :call, :fields)
|
28
28
|
end
|
29
29
|
|
30
30
|
UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
|
@@ -62,7 +62,7 @@ module_eval(<<'...end parser.y/module_eval...', 'parser.y', 133)
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def on_error(token, value, vstack)
|
65
|
-
raise Errors::
|
65
|
+
raise Errors::SyntaxError.new(value, token_to_str(token))
|
66
66
|
end
|
67
67
|
|
68
68
|
private
|
data/lib/gql/parser.y
CHANGED
@@ -137,10 +137,10 @@ require 'active_support/core_ext/object/blank'
|
|
137
137
|
class Node < Struct.new(:call, :fields)
|
138
138
|
end
|
139
139
|
|
140
|
-
class Field < Struct.new(:
|
140
|
+
class Field < Struct.new(:id, :alias_id, :call, :fields)
|
141
141
|
end
|
142
142
|
|
143
|
-
class Call < Struct.new(:
|
143
|
+
class Call < Struct.new(:id, :arguments, :call, :fields)
|
144
144
|
end
|
145
145
|
|
146
146
|
UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
|
@@ -178,7 +178,7 @@ require 'active_support/core_ext/object/blank'
|
|
178
178
|
end
|
179
179
|
|
180
180
|
def on_error(token, value, vstack)
|
181
|
-
raise Errors::
|
181
|
+
raise Errors::SyntaxError.new(value, token_to_str(token))
|
182
182
|
end
|
183
183
|
|
184
184
|
private
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module GQL
|
2
|
+
module Schema
|
3
|
+
class Call < GQL::Node
|
4
|
+
cursor :id
|
5
|
+
string :id
|
6
|
+
|
7
|
+
array :parameters, :node_class => Parameter do
|
8
|
+
target.method.parameters
|
9
|
+
end
|
10
|
+
|
11
|
+
string :type do
|
12
|
+
target.name
|
13
|
+
end
|
14
|
+
|
15
|
+
object :result_class, :node_class => Node do
|
16
|
+
target.result_class || Placeholder
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module GQL
|
2
|
+
module Schema
|
3
|
+
class Field < GQL::Node
|
4
|
+
cursor :id
|
5
|
+
string :id
|
6
|
+
|
7
|
+
string :type do
|
8
|
+
target.name
|
9
|
+
end
|
10
|
+
|
11
|
+
connection :calls, :connection_class => Connection, :node_class => Call do
|
12
|
+
target.calls.values
|
13
|
+
end
|
14
|
+
|
15
|
+
connection :fields, :connection_class => Connection, :node_class => Field do
|
16
|
+
target.fields.values
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module GQL
|
2
|
+
module Schema
|
3
|
+
class Node < GQL::Node
|
4
|
+
string :type do
|
5
|
+
target.name
|
6
|
+
end
|
7
|
+
|
8
|
+
connection :calls, :connection_class => Connection, :node_class => Call do
|
9
|
+
target.calls.values
|
10
|
+
end
|
11
|
+
|
12
|
+
connection :fields, :connection_class => Connection, :node_class => Field do
|
13
|
+
target.fields.values
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module GQL
|
2
|
+
module Schema
|
3
|
+
class Parameter < GQL::Node
|
4
|
+
cursor { target[1].to_s }
|
5
|
+
|
6
|
+
string :id do
|
7
|
+
target[1].to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
string :mode do
|
11
|
+
case target[0]
|
12
|
+
when :req
|
13
|
+
'required'
|
14
|
+
when :opt
|
15
|
+
'optional'
|
16
|
+
when :rest
|
17
|
+
'rest'
|
18
|
+
when :keyreq
|
19
|
+
'required keyword'
|
20
|
+
when :key
|
21
|
+
'optional keyword'
|
22
|
+
when :keyrest
|
23
|
+
'keyword rest'
|
24
|
+
when :block
|
25
|
+
'block'
|
26
|
+
else
|
27
|
+
target[0].to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/gql/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Andert
|
@@ -126,6 +126,12 @@ files:
|
|
126
126
|
- lib/gql/node.rb
|
127
127
|
- lib/gql/parser.rb
|
128
128
|
- lib/gql/parser.y
|
129
|
+
- lib/gql/schema/call.rb
|
130
|
+
- lib/gql/schema/connection.rb
|
131
|
+
- lib/gql/schema/field.rb
|
132
|
+
- lib/gql/schema/node.rb
|
133
|
+
- lib/gql/schema/parameter.rb
|
134
|
+
- lib/gql/schema/placeholder.rb
|
129
135
|
- lib/gql/tokenizer.rb
|
130
136
|
- lib/gql/tokenizer.rex
|
131
137
|
- lib/gql/version.rb
|