graphiti_gql 0.2.1 → 0.2.2
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/lib/graphiti_gql/active_resource.rb +210 -0
- data/lib/graphiti_gql/engine.rb +16 -1
- data/lib/graphiti_gql/schema/fields/stats.rb +2 -2
- data/lib/graphiti_gql/schema/query.rb +1 -2
- data/lib/graphiti_gql/schema/resource_type.rb +1 -1
- data/lib/graphiti_gql/schema.rb +15 -0
- data/lib/graphiti_gql/spec_helper.rb +23 -128
- data/lib/graphiti_gql/version.rb +1 -1
- data/lib/graphiti_gql.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 899580a6d3577a31dc7356d894eab26756c2c9876636db69ce5ece2d5eeee3ce
|
4
|
+
data.tar.gz: faf261a7614a0565c9dc3e45b4a9d14d75962aa6665b7302752733584abb5bdc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: becebe36d5aabea0a75ba3e617f9f62d0830d3f4a35e5becdacef1fbe10f4991621f061521f10bc4c0e527bdc834d5380e9f38ff0b9cc2388a66a7cf25bb33b8
|
7
|
+
data.tar.gz: 37a9a4221261f112100e32f06832a948c30cbef5a06ffcb786f080538c1b9f3894bd3f7f8fc32394f0c2cb122e94c1b1e58cd6b8c38b6e0feab08a30d55bbfb5
|
@@ -0,0 +1,210 @@
|
|
1
|
+
module GraphitiGql
|
2
|
+
module ActiveResource
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
class Node < OpenStruct
|
6
|
+
def initialize(resource, hash)
|
7
|
+
@resource = resource
|
8
|
+
hash.each_pair do |key, value|
|
9
|
+
if value.is_a?(Hash)
|
10
|
+
if (sideload = resource.sideload(key))
|
11
|
+
if value.key?(:edges)
|
12
|
+
hash[key] = value[:edges].map { |v| Node.new(sideload.resource.class, v[:node]) }
|
13
|
+
else
|
14
|
+
hash[key] = Node.new(sideload.resource.class, value)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
super(hash)
|
20
|
+
end
|
21
|
+
|
22
|
+
def decoded_id
|
23
|
+
Base64.decode64(self.id)
|
24
|
+
end
|
25
|
+
|
26
|
+
def int_id
|
27
|
+
decoded_id.to_i
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Proxy
|
32
|
+
def initialize(resource, params, ctx)
|
33
|
+
@resource = resource
|
34
|
+
@ctx = ctx
|
35
|
+
@params = params.deep_transform_keys { |key| key.to_s.camelize(:lower).to_sym }
|
36
|
+
(@params[:sort] || []).each do |sort|
|
37
|
+
sort[:att] = sort[:att].to_s.camelize(:lower)
|
38
|
+
sort[:dir] = sort[:dir].to_s
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_h(symbolize_keys: true)
|
43
|
+
result = GraphitiGql.run(query, @params, @ctx)
|
44
|
+
result = result.deep_symbolize_keys if symbolize_keys
|
45
|
+
@response = result
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
def nodes
|
50
|
+
return [] unless data
|
51
|
+
nodes = edges.map { |e| underscore(e[:node]) }
|
52
|
+
nodes.map { |n| Node.new(@resource, n) }
|
53
|
+
end
|
54
|
+
alias :to_a :nodes
|
55
|
+
|
56
|
+
def response
|
57
|
+
@response ||= to_h
|
58
|
+
end
|
59
|
+
|
60
|
+
def data
|
61
|
+
if response.key?(:data)
|
62
|
+
response[:data]
|
63
|
+
else
|
64
|
+
raise "Tried to access 'data', but these errors were returned instead: #{error_messages.join(". ")}."
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def errors
|
69
|
+
response[:errors]
|
70
|
+
end
|
71
|
+
|
72
|
+
def error_messages
|
73
|
+
response[:errors].map { |e| e[:message] }
|
74
|
+
end
|
75
|
+
|
76
|
+
def edges
|
77
|
+
data[data.keys.first][:edges]
|
78
|
+
end
|
79
|
+
|
80
|
+
def stats
|
81
|
+
underscore(data[data.keys.first][:stats])
|
82
|
+
end
|
83
|
+
|
84
|
+
def page_info
|
85
|
+
underscore(data[data.keys.first][:pageInfo])
|
86
|
+
end
|
87
|
+
|
88
|
+
def query
|
89
|
+
name = Schema.registry.key_for(@resource)
|
90
|
+
filter_bang = "!" if @resource.filters.values.any? { |f| f[:required] }
|
91
|
+
sortvar = "$sort: [#{name}Sort!]," if @resource.sorts.any?
|
92
|
+
|
93
|
+
if !(fields = @params[:fields])
|
94
|
+
fields = []
|
95
|
+
@resource.attributes.each_pair do |name, config|
|
96
|
+
(fields << name) if config[:readable]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
q = %|
|
101
|
+
query #{name} (
|
102
|
+
$filter: #{name}Filter#{filter_bang},
|
103
|
+
#{sortvar}
|
104
|
+
$first: Int,
|
105
|
+
$last: Int,
|
106
|
+
$before: String,
|
107
|
+
$after: String,
|
108
|
+
) {
|
109
|
+
#{@resource.graphql_entrypoint} (
|
110
|
+
filter: $filter,
|
111
|
+
#{ 'sort: $sort,' if sortvar }
|
112
|
+
first: $first,
|
113
|
+
last: $last,
|
114
|
+
before: $before,
|
115
|
+
after: $after,
|
116
|
+
) {
|
117
|
+
edges {
|
118
|
+
node {|
|
119
|
+
|
120
|
+
fields.each do |name|
|
121
|
+
q << %|
|
122
|
+
#{name.to_s.camelize(:lower)}|
|
123
|
+
end
|
124
|
+
|
125
|
+
if @params[:include]
|
126
|
+
includes = Array(@params[:include])
|
127
|
+
# NB HASH (?)
|
128
|
+
includes.each do |inc|
|
129
|
+
sideload = @resource.sideload(inc.to_sym)
|
130
|
+
to_one = [:belongs_to, :has_one, :polymorphic_belongs_to].include?(sideload.type)
|
131
|
+
indent = " " if !to_one
|
132
|
+
q << %|
|
133
|
+
#{inc.to_s.camelize(:lower)} {|
|
134
|
+
if !to_one
|
135
|
+
q << %|
|
136
|
+
edges {
|
137
|
+
node {|
|
138
|
+
end
|
139
|
+
|
140
|
+
r = @resource.sideload(inc.to_sym).resource
|
141
|
+
r.attributes.each_pair do |name, config|
|
142
|
+
next unless config[:readable]
|
143
|
+
q << %|
|
144
|
+
#{indent}#{name.to_s.camelize(:lower)}|
|
145
|
+
end
|
146
|
+
|
147
|
+
if to_one
|
148
|
+
q << %|
|
149
|
+
}|
|
150
|
+
else
|
151
|
+
q << %|
|
152
|
+
}
|
153
|
+
}
|
154
|
+
}|
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
q << %|
|
160
|
+
}
|
161
|
+
}
|
162
|
+
pageInfo {
|
163
|
+
startCursor
|
164
|
+
endCursor
|
165
|
+
hasNextPage
|
166
|
+
hasPreviousPage
|
167
|
+
}|
|
168
|
+
|
169
|
+
if @params[:stats]
|
170
|
+
q << %|
|
171
|
+
stats {|
|
172
|
+
@params[:stats].each_pair do |name, calculations|
|
173
|
+
q << %|
|
174
|
+
#{name.to_s.camelize(:lower)} {|
|
175
|
+
Array(calculations).each do |calc|
|
176
|
+
q << %|
|
177
|
+
#{calc.to_s.camelize(:lower)}|
|
178
|
+
end
|
179
|
+
|
180
|
+
q << %|
|
181
|
+
}|
|
182
|
+
end
|
183
|
+
q << %|
|
184
|
+
}|
|
185
|
+
end
|
186
|
+
|
187
|
+
q << %|
|
188
|
+
}
|
189
|
+
}
|
190
|
+
|
|
191
|
+
|
192
|
+
q
|
193
|
+
end
|
194
|
+
|
195
|
+
private
|
196
|
+
|
197
|
+
def underscore(hash)
|
198
|
+
hash.deep_transform_keys { |k| k.to_s.underscore.to_sym }
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
class_methods do
|
203
|
+
def gql(params = {}, ctx = {})
|
204
|
+
Proxy.new(self, params, ctx)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
Graphiti::Resource.send(:include, GraphitiGql::ActiveResource)
|
data/lib/graphiti_gql/engine.rb
CHANGED
@@ -9,9 +9,18 @@ module GraphitiGql
|
|
9
9
|
GraphitiGql.schema!
|
10
10
|
end
|
11
11
|
|
12
|
+
module ControllerContext
|
13
|
+
def graphql_context
|
14
|
+
ctx = { controller: self }
|
15
|
+
ctx[:current_user] = current_user if respond_to?(:current_user)
|
16
|
+
ctx
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
12
20
|
initializer "graphiti_gql.define_controller" do
|
13
21
|
require "#{Rails.root}/app/controllers/application_controller"
|
14
22
|
app_controller = GraphitiGql.config.application_controller || ::ApplicationController
|
23
|
+
app_controller.send(:include, ControllerContext)
|
15
24
|
|
16
25
|
# rubocop:disable Lint/ConstantDefinitionInBlock(Standard)
|
17
26
|
class GraphitiGql::ExecutionController < app_controller
|
@@ -20,9 +29,15 @@ module GraphitiGql
|
|
20
29
|
variables = params[:variables] || {}
|
21
30
|
result = GraphitiGql.run params[:query],
|
22
31
|
params[:variables],
|
23
|
-
|
32
|
+
graphql_context
|
24
33
|
render json: result
|
25
34
|
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def default_context
|
39
|
+
defined?(:current_user)
|
40
|
+
end
|
26
41
|
end
|
27
42
|
end
|
28
43
|
end
|
@@ -29,7 +29,7 @@ module GraphitiGql
|
|
29
29
|
name = Registry.instance.key_for(@resource)
|
30
30
|
stat_graphql_name = "#{name}Stats"
|
31
31
|
return Registry.instance[stat_graphql_name][:type] if Registry.instance[stat_graphql_name]
|
32
|
-
klass = Class.new(
|
32
|
+
klass = Class.new(Schema.base_object)
|
33
33
|
klass.graphql_name(stat_graphql_name)
|
34
34
|
@resource.stats.each_pair do |name, config|
|
35
35
|
calc_class = build_calc_class(stat_graphql_name, name, config.calculations.keys)
|
@@ -41,7 +41,7 @@ module GraphitiGql
|
|
41
41
|
|
42
42
|
def build_calc_class(stat_graphql_name, stat_name, calculations)
|
43
43
|
name = "#{stat_graphql_name}#{stat_name}Calculations"
|
44
|
-
klass = Class.new(
|
44
|
+
klass = Class.new(Schema.base_object)
|
45
45
|
klass.graphql_name(name)
|
46
46
|
calculations.each do |calc|
|
47
47
|
klass.field calc, Float, null: false
|
@@ -3,9 +3,8 @@ module GraphitiGql
|
|
3
3
|
class Query
|
4
4
|
def initialize(resources, existing_query: nil)
|
5
5
|
@resources = resources
|
6
|
-
@query_class = Class.new(existing_query ||
|
6
|
+
@query_class = Class.new(existing_query || Schema.base_object)
|
7
7
|
@query_class.graphql_name "Query"
|
8
|
-
@query_class.field_class ::GraphQL::Schema::Field
|
9
8
|
end
|
10
9
|
|
11
10
|
def build
|
data/lib/graphiti_gql/schema.rb
CHANGED
@@ -32,6 +32,21 @@ module GraphitiGql
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
def self.base_object
|
36
|
+
klass = Class.new(GraphQL::Schema::Object)
|
37
|
+
# TODO make this config maybe
|
38
|
+
if defined?(ActionView)
|
39
|
+
klass.send(:include, ActionView::Helpers::TranslationHelper)
|
40
|
+
klass.class_eval do
|
41
|
+
def initialize(*)
|
42
|
+
super
|
43
|
+
@virtual_path = "."
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
klass
|
48
|
+
end
|
49
|
+
|
35
50
|
def self.registry
|
36
51
|
Registry.instance
|
37
52
|
end
|
@@ -2,149 +2,44 @@ module GraphitiGql
|
|
2
2
|
module SpecHelper
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
5
|
+
included do
|
6
|
+
extend Forwardable
|
7
|
+
def_delegators :result,
|
8
|
+
:page_info,
|
9
|
+
:errors,
|
10
|
+
:error_messages,
|
11
|
+
:nodes,
|
12
|
+
:stats
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
if defined?(RSpec)
|
15
|
+
let(:params) { {} }
|
16
|
+
let(:resource) { described_class }
|
17
|
+
let(:ctx) { {} }
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
$sort: [#{name}Sort!],
|
27
|
-
$first: Int,
|
28
|
-
$last: Int,
|
29
|
-
$before: String,
|
30
|
-
$after: String,
|
31
|
-
) {
|
32
|
-
#{resource.graphql_entrypoint} (
|
33
|
-
filter: $filter,
|
34
|
-
sort: $sort,
|
35
|
-
first: $first,
|
36
|
-
last: $last,
|
37
|
-
before: $before,
|
38
|
-
after: $after,
|
39
|
-
) {
|
40
|
-
edges {
|
41
|
-
node {|
|
42
|
-
|
43
|
-
fields.each do |name|
|
44
|
-
q << %|
|
45
|
-
#{name.to_s.camelize(:lower)}|
|
46
|
-
end
|
47
|
-
|
48
|
-
q << %|
|
49
|
-
}
|
50
|
-
}
|
51
|
-
pageInfo {
|
52
|
-
startCursor
|
53
|
-
endCursor
|
54
|
-
hasNextPage
|
55
|
-
hasPreviousPage
|
56
|
-
}|
|
57
|
-
|
58
|
-
if params[:stats]
|
59
|
-
q << %|
|
60
|
-
stats {|
|
61
|
-
params[:stats].each_pair do |name, calculations|
|
62
|
-
q << %|
|
63
|
-
#{name.to_s.camelize(:lower)} {|
|
64
|
-
Array(calculations).each do |calc|
|
65
|
-
q << %|
|
66
|
-
#{calc.to_s.camelize(:lower)}|
|
67
|
-
end
|
68
|
-
|
69
|
-
q << %|
|
70
|
-
}|
|
71
|
-
end
|
72
|
-
q << %|
|
73
|
-
}|
|
21
|
+
def gql_datetime(timestamp, precise = false)
|
22
|
+
if precise
|
23
|
+
timestamp.utc.round(10).iso8601(6)
|
24
|
+
else
|
25
|
+
DateTime.parse(timestamp.to_s).iso8601
|
74
26
|
end
|
75
|
-
|
76
|
-
q << %|
|
77
|
-
}
|
78
|
-
}
|
79
|
-
|
|
80
|
-
|
81
|
-
q
|
82
27
|
end
|
83
28
|
|
84
29
|
def run
|
85
30
|
lambda do
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
sort[:dir] = sort[:dir].to_s
|
90
|
-
end
|
91
|
-
GraphitiGql.run(query, gql_params, ctx).deep_symbolize_keys
|
31
|
+
proxy = resource.gql(params, ctx)
|
32
|
+
proxy.to_h
|
33
|
+
proxy
|
92
34
|
end
|
93
35
|
end
|
94
36
|
|
95
37
|
def run!
|
96
|
-
@
|
97
|
-
end
|
98
|
-
|
99
|
-
def response
|
100
|
-
@response ||= run!
|
101
|
-
end
|
102
|
-
|
103
|
-
def errors
|
104
|
-
response[:errors]
|
105
|
-
end
|
106
|
-
|
107
|
-
def error_messages
|
108
|
-
response[:errors].map { |e| e[:message] }
|
38
|
+
@result = run.call
|
109
39
|
end
|
110
40
|
|
111
|
-
def
|
112
|
-
|
113
|
-
nodes = edges.map { |e| Util.underscore(e[:node]) }
|
114
|
-
nodes.map { |n| ::GraphitiGql::SpecHelper::Node.new(n) }
|
115
|
-
end
|
116
|
-
|
117
|
-
def data
|
118
|
-
if response.key?(:data)
|
119
|
-
response[:data]
|
120
|
-
else
|
121
|
-
raise "Tried to access 'data', but these errors were returned instead: #{error_messages.join(". ")}."
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
def edges
|
126
|
-
data[data.keys.first][:edges]
|
127
|
-
end
|
128
|
-
|
129
|
-
def stats
|
130
|
-
Util.underscore(data[data.keys.first][:stats])
|
131
|
-
end
|
132
|
-
|
133
|
-
def page_info
|
134
|
-
Util.underscore(data[data.keys.first][:pageInfo])
|
135
|
-
end
|
136
|
-
|
137
|
-
included do
|
138
|
-
let(:params) { {} }
|
139
|
-
let(:resource) { described_class }
|
140
|
-
let(:ctx) { {} }
|
141
|
-
let(:fields) do
|
142
|
-
fields = []
|
143
|
-
resource.attributes.each_pair do |name, config|
|
144
|
-
(fields << name) if config[:readable]
|
145
|
-
end
|
146
|
-
fields
|
147
|
-
end
|
41
|
+
def result
|
42
|
+
@result ||= run!
|
148
43
|
end
|
149
44
|
end
|
150
45
|
end
|
data/lib/graphiti_gql/version.rb
CHANGED
data/lib/graphiti_gql.rb
CHANGED
@@ -24,6 +24,7 @@ require "graphiti_gql/schema/fields/to_many"
|
|
24
24
|
require "graphiti_gql/schema/fields/to_one"
|
25
25
|
require "graphiti_gql/schema/fields/attribute"
|
26
26
|
require "graphiti_gql/schema/fields/stats"
|
27
|
+
require "graphiti_gql/active_resource"
|
27
28
|
require "graphiti_gql/engine" if defined?(Rails)
|
28
29
|
|
29
30
|
module GraphitiGql
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphiti_gql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lee Richmond
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-06-
|
11
|
+
date: 2022-06-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|
@@ -137,6 +137,7 @@ files:
|
|
137
137
|
- config/routes.rb
|
138
138
|
- graphiti_gql.gemspec
|
139
139
|
- lib/graphiti_gql.rb
|
140
|
+
- lib/graphiti_gql/active_resource.rb
|
140
141
|
- lib/graphiti_gql/engine.rb
|
141
142
|
- lib/graphiti_gql/errors.rb
|
142
143
|
- lib/graphiti_gql/graphiti_hax.rb
|