graphlyte 0.1.2 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ee4eed2122126ce2d651f0f63210598a48a9fb6a6919a4a20066e932fccdab3
4
- data.tar.gz: 7d74b8dc7a8c46e949a5ea035970f3595ff02020dbc55ad819b31e5bfcd2b3e0
3
+ metadata.gz: 82edd3a321164acd153524e98420c75175deb60d1fd56d28f72f52917e35dac4
4
+ data.tar.gz: '049a43943a6ba45edff3a73347c903be52f0d4e4d7e9f76a9be50e0e45ed11a6'
5
5
  SHA512:
6
- metadata.gz: bf5f9ee7465d4120a7c343954fd912c07a14e90b23ecee94dca4c9ba077be0d2c3d2853540c74b243f715f4e30cd00e90587e189abac66e043e5a30baab7ea07
7
- data.tar.gz: f31753943431a52b0296de465a6d7f2901657a2c4be1c69fc0c91f424011bfbb12f5ad5baa090e236ddf3466b70463cf5098a3ecb72e712af8290e3ea13a85e9
6
+ metadata.gz: a1a81b6258e70829db7010ce3c2ca3cdd818dadd0cdc21878c6e10eaefd7baa54d816fd3810c92f330699d905ed5ad00f7865c169f0290e96f4290dbf5cf8160
7
+ data.tar.gz: b3bc5db253642508d0f9e93c7882525706fe7c9e1ec687e4b7f506a6096a9ba8ecb2a6e6cc1653318467911b70c01243a4bf9f55d7cd22ccf2618cfff912bfbd
data/lib/graphlyte.rb CHANGED
@@ -1,174 +1,26 @@
1
1
  require 'json'
2
+ require_relative "./graphlyte/fieldset"
3
+ require_relative "./graphlyte/query"
4
+ require_relative "./graphlyte/fragment"
5
+
2
6
  module Graphlyte
3
7
  def self.query(name = nil, &block)
4
- query = Query.new(name)
5
- block.call(query) if block
6
- query
8
+ Query.new(name, builder: build(&block))
7
9
  end
8
10
 
9
- def self.fragment(fragment_name, model_name=nil, &block)
10
- fragment = Fragment.new(fragment_name, model_name)
11
- block.call(fragment) if block
12
- fragment
11
+ def self.fragment(fragment_name, model_name, &block)
12
+ Fragment.new(fragment_name, model_name, builder: build(&block))
13
13
  end
14
14
 
15
15
  def self.fieldset(model_name=nil, &block)
16
- fieldset = Fieldset.new(model_name)
17
- block.call(fieldset) if block
18
- fieldset
19
- end
20
-
21
- module Buildable
22
- def <<(buildable)
23
- raise "Must pass a Fieldset or Fragment" unless [Fragment, Fieldset].include?(buildable.class)
24
- @fields.concat(buildable._fields) if buildable.class.eql? Fieldset
25
- @fields << buildable if buildable.class.eql? Fragment
26
- end
27
-
28
- def method_missing(method, optional_fieldset_or_args=nil, hargs={}, &block)
29
- field = [Fieldset, Fragment].include?(optional_fieldset_or_args.class) ?
30
- Field.new(method, optional_fieldset_or_args, hargs) :
31
- Field.new(method, Fieldset.empty, optional_fieldset_or_args)
32
- block.call(field.value) if block
33
- @fields << field
34
- field
35
- end
16
+ Fieldset.new(model_name, builder: build(&block))
36
17
  end
37
18
 
38
- class Fieldset
39
- include Buildable
40
-
41
- def self.empty
42
- new
43
- end
44
-
45
- def initialize(model_name = nil)
46
- @model_name = model_name
47
- @fields = []
48
- end
49
-
50
- def _model_name
51
- @model_name
52
- end
53
-
54
- def _fields
55
- @fields
56
- end
57
-
58
- def empty?
59
- @fields.empty?
60
- end
61
-
62
- def can_validate?
63
- !@model_name.nil?
64
- end
65
-
66
- def to_s(indent=0)
67
- @fields.map { |field| field.to_s(indent)}.join("\n")
68
- end
69
- end
70
-
71
- class Query < Fieldset
72
-
73
- def initialize(query_name=nil)
74
- @query_name = query_name
75
- @fields = []
76
- end
77
-
78
- def to_json
79
- { query: to_s }.to_json
80
- end
81
-
82
- def to_s(indent=0)
83
- "{\n#{super(indent + 1)}\n}\n#{format_fragments}\n"
84
- end
85
-
86
- def format_fragments
87
- str = ""
88
- flatten(@fields).each do |_, fragment|
89
- str += "\nfragment #{fragment.name}"
90
- str += " on #{fragment._model_name}" unless fragment._model_name.nil?
91
- str += " {\n#{fragment._fields.map {|f| f.to_s(1) }.join("\n")}\n}"
92
- end
93
- str
94
- end
95
-
96
- def flatten(fields=@fields, new_fields = {})
97
- fields.each do |field|
98
- if field.class.eql?(Fragment)
99
- new_fields[field.name] = field
100
- unless field._fields.empty?
101
- flatten(field._fields, new_fields)
102
- end
103
- else
104
- if field.value.class.eql?(Fragment)
105
- new_fields[field.value.name] = field.value
106
- flatten(field.value._fields, new_fields) unless field.value._fields.empty?
107
- else
108
- flatten(field.value._fields, new_fields) unless field.value._fields.empty?
109
- end
110
- end
111
- end
112
- new_fields
113
- end
114
- end
115
-
116
- class Fragment < Fieldset
117
- attr_reader :fragment_name, :name
118
-
119
- def initialize(fragment_name, model_name=nil)
120
- @fragment_name = fragment_name
121
- @name = fragment_name
122
- super(model_name)
123
- end
124
-
125
- def to_s(indent=0)
126
- actual_indent = ("\s" * indent) * 2
127
- "#{actual_indent}...#{@fragment_name}#{actual_indent}"
128
- end
129
- end
130
-
131
- class FieldArguments
132
- def initialize(data)
133
- @data = data
134
- end
135
-
136
- def to_s
137
- return @data && !@data.empty? ? "(#{@data.map{|k, v| "#{k}: \"#{v}\""}.join(", ")})" : ""
138
- end
139
- end
140
-
141
- class Field
142
- attr_reader :name, :value, :inputs, :alias
143
-
144
- def initialize(name, value=nil, hargs)
145
- @name = name
146
- @value = value
147
- @inputs = FieldArguments.new(hargs)
148
- @alias = nil
149
- end
150
-
151
- def atomic?
152
- value.empty?
153
- end
154
-
155
- def alias(name, &block)
156
- @alias = name
157
- block.call(value) if block
158
- end
19
+ private
159
20
 
160
- def to_s(indent=0)
161
- str = ""
162
- actual_indent = ("\s" * indent) * 2
163
- if @alias
164
- str += "#{actual_indent}#{@alias}: #{name}"
165
- str += inputs.to_s.empty? ? "()" : inputs.to_s
166
- str += " "
167
- else
168
- str += "#{actual_indent}#{name}#{inputs.to_s}"
169
- end
170
- str += "{\n#{value.to_s(indent + 1)}#{actual_indent}\n#{actual_indent}}" unless atomic?
171
- str
172
- end
21
+ def self.build(&block)
22
+ builder = Builder.new
23
+ block.call(builder) if block
24
+ builder
173
25
  end
174
26
  end
@@ -0,0 +1,46 @@
1
+ require_relative "./value"
2
+ module Graphlyte
3
+ module Arguments
4
+ class Set
5
+
6
+ attr_reader :values
7
+
8
+ def initialize(data)
9
+ raise ArgumentError, "input #{data} must be a hash" unless data.nil? || data.is_a?(Hash)
10
+ @values = expand_arguments(data) unless data.nil?
11
+ end
12
+
13
+ def to_s(inner = false)
14
+ return "" unless values && !values.empty?
15
+ arr = values.map do |k,v|
16
+ if v.is_a?(Array)
17
+ "#{k}: [#{v.map(&:to_s).join(", ")}]"
18
+ elsif v.is_a?(Set)
19
+ "#{k}: { #{v.to_s(true)} }"
20
+ else
21
+ "#{k}: #{v.to_s}"
22
+ end
23
+ end
24
+ return arr.join(", ") if inner
25
+ "(#{arr.join(", ")})"
26
+ end
27
+
28
+ private
29
+
30
+ def expand_arguments(data)
31
+ data.inject({}) do |memo, (k, v)|
32
+ if v.is_a?(Array)
33
+ memo[k] = v.map do |item|
34
+ Value.new(item)
35
+ end
36
+ elsif v.is_a?(Hash)
37
+ memo[k] = Set.new(v)
38
+ else
39
+ memo[k] = Value.new(v)
40
+ end
41
+ memo
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,19 @@
1
+ module Graphlyte
2
+ module Arguments
3
+ class Value
4
+ attr_reader :value
5
+
6
+ def initialize(value)
7
+ raise ArgumentError, "Hash not allowed in this context" if value.is_a? Hash
8
+ @value = value
9
+ end
10
+
11
+ def to_s
12
+ return value if value.is_a? Numeric
13
+ return "\"#{value}\"" if value.is_a? String
14
+ return "null" if value.nil?
15
+ value.to_s
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,39 @@
1
+ require_relative "./field"
2
+ require_relative "./fieldset"
3
+
4
+ module Graphlyte
5
+ class Builder
6
+ def initialize
7
+ @fields = []
8
+ end
9
+
10
+ def <<(buildable)
11
+ raise "Must pass a Fieldset or Fragment" unless [Fragment, Fieldset].include?(buildable.class)
12
+
13
+ @fields.concat(buildable.fields) if buildable.class.eql? Fieldset
14
+
15
+ # todo: handle fragments better, it's not a field
16
+ @fields << buildable if buildable.class.eql? Fragment
17
+ end
18
+
19
+ def method_missing(method, fieldset_or_hargs=nil, hargs={}, &block)
20
+ # todo: camel case method
21
+
22
+ # hack for ruby bug in lower versions
23
+ if [Fieldset, Fragment].include?(fieldset_or_hargs.class)
24
+ field = Field.new(method, fieldset_or_hargs, hargs)
25
+ else
26
+ field = Field.new(method, Fieldset.empty, fieldset_or_hargs)
27
+ end
28
+
29
+ block.call(field.fieldset.builder) if block
30
+ @fields << field
31
+ field
32
+ end
33
+
34
+ # for internal use only
35
+ def >>
36
+ @fields
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,47 @@
1
+ require_relative "./arguments/set"
2
+
3
+ module Graphlyte
4
+ class Field
5
+ attr_reader :name, :fieldset, :inputs, :alias
6
+
7
+ def initialize(name, fieldset, hargs, inputs: Arguments::Set.new(hargs))
8
+ @name = to_camel_case(name.to_s)
9
+ @fieldset = fieldset
10
+ @inputs = inputs
11
+ @alias = nil
12
+ end
13
+
14
+ def atomic?
15
+ fieldset.empty?
16
+ end
17
+
18
+ def alias(name, &block)
19
+ @alias = name
20
+ block.call(fieldset.builder) if block
21
+ end
22
+
23
+ def to_s(indent=0)
24
+ str = ""
25
+ actual_indent = ("\s" * indent) * 2
26
+ if @alias
27
+ str += "#{actual_indent}#{@alias}: #{name}"
28
+ str += inputs.to_s.empty? ? "()" : inputs.to_s
29
+ else
30
+ str += "#{actual_indent}#{name}#{inputs.to_s}"
31
+ end
32
+ str += " {\n#{fieldset.to_s(indent + 1)}\n#{actual_indent}}" unless atomic?
33
+ str
34
+ end
35
+
36
+ def to_camel_case(string)
37
+ start_of_string = string.match(/(^_+)/)&.[](0)
38
+ end_of_string = string.match(/(_+$)/)&.[](0)
39
+
40
+ middle = string.split("_").reject(&:empty?).inject([]) do |memo, str|
41
+ memo << (memo.empty? ? str : str.capitalize)
42
+ end.join("")
43
+
44
+ "#{start_of_string}#{middle}#{end_of_string}"
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,36 @@
1
+ require_relative "./builder"
2
+
3
+ module Graphlyte
4
+ class Fieldset
5
+ def self.empty
6
+ new
7
+ end
8
+
9
+ attr_reader :model_name, :builder
10
+
11
+ def initialize(model_name = nil, builder: Builder.new)
12
+ @model_name = model_name
13
+ @builder = builder
14
+ end
15
+
16
+ def fields
17
+ builder.>>
18
+ end
19
+
20
+ def empty?
21
+ fields.empty?
22
+ end
23
+
24
+ def to_s(indent=0)
25
+ fields.map { |field| field.to_s(indent) }.join("\n")
26
+ end
27
+
28
+ def to_a
29
+ [ to_s ]
30
+ end
31
+
32
+ def +(fieldset)
33
+ to_s + "\n" + fieldset.to_s
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ require_relative "./fieldset"
2
+
3
+ module Graphlyte
4
+ class Fragment < Fieldset
5
+ attr_reader :fragment
6
+
7
+ def initialize(fragment_name, model_name=nil, **hargs)
8
+ @fragment = fragment_name
9
+ super(model_name, **hargs)
10
+ end
11
+
12
+ def to_s(indent=0)
13
+ actual_indent = ("\s" * indent) * 2
14
+ "#{actual_indent}...#{fragment}#{actual_indent}"
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,48 @@
1
+ module Graphlyte
2
+ class Query < Fieldset
3
+
4
+ attr_reader :name
5
+
6
+ def initialize(query_name=nil, **hargs)
7
+ @name = query_name
8
+ super(**hargs)
9
+ end
10
+
11
+ def to_json
12
+ { query: to_s }.to_json
13
+ end
14
+
15
+ def to_s(indent=0)
16
+ "{\n#{super(indent + 1)}\n}#{format_fragments}"
17
+ end
18
+
19
+ def format_fragments
20
+ str = "\n"
21
+ flatten(builder.>>).each do |_, fragment|
22
+ str += "\nfragment #{fragment.fragment}"
23
+ str += " on #{fragment.model_name}" unless fragment.model_name.nil?
24
+ str += " {\n#{fragment.fields.map {|f| f.to_s(1) }.join("\n")}\n}"
25
+ end
26
+ str
27
+ end
28
+
29
+ def flatten(fields, new_fields = {})
30
+ fields.each do |field|
31
+ if field.class.eql?(Fragment)
32
+ new_fields[field.fragment] = field
33
+ unless field.empty?
34
+ flatten(field.fields, new_fields)
35
+ end
36
+ else
37
+ if field.fieldset.class.eql?(Fragment)
38
+ new_fields[field.fieldset.fragment] = field.fieldset
39
+ flatten(field.fieldset.fields, new_fields) unless field.atomic?
40
+ else
41
+ flatten(field.fieldset.fields, new_fields) unless field.atomic?
42
+ end
43
+ end
44
+ end
45
+ new_fields
46
+ end
47
+ end
48
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphlyte
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Gregory
@@ -45,6 +45,13 @@ extensions: []
45
45
  extra_rdoc_files: []
46
46
  files:
47
47
  - lib/graphlyte.rb
48
+ - lib/graphlyte/arguments/set.rb
49
+ - lib/graphlyte/arguments/value.rb
50
+ - lib/graphlyte/builder.rb
51
+ - lib/graphlyte/field.rb
52
+ - lib/graphlyte/fieldset.rb
53
+ - lib/graphlyte/fragment.rb
54
+ - lib/graphlyte/query.rb
48
55
  homepage: https://rubygems.org/gems/graphlyte
49
56
  licenses:
50
57
  - MIT