hq-graphql 2.0.6 → 2.1.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/README.md +28 -0
- data/lib/hq-graphql.rb +0 -2
- data/lib/hq/graphql.rb +29 -20
- data/lib/hq/graphql/active_record_extensions.rb +23 -27
- data/lib/hq/graphql/association_loader.rb +49 -0
- data/lib/hq/graphql/comparator.rb +1 -6
- data/lib/hq/graphql/config.rb +17 -11
- data/lib/hq/graphql/engine.rb +0 -1
- data/lib/hq/graphql/enum.rb +78 -0
- data/lib/hq/graphql/enum/sort_by.rb +8 -0
- data/lib/hq/graphql/enum/sort_order.rb +8 -0
- data/lib/hq/graphql/field.rb +26 -6
- data/lib/hq/graphql/input_object.rb +8 -7
- data/lib/hq/graphql/inputs.rb +4 -3
- data/lib/hq/graphql/mutation.rb +0 -1
- data/lib/hq/graphql/object.rb +15 -4
- data/lib/hq/graphql/paginated_association_loader.rb +138 -0
- data/lib/hq/graphql/resource.rb +47 -156
- data/lib/hq/graphql/resource/auto_mutation.rb +159 -0
- data/lib/hq/graphql/root_mutation.rb +1 -2
- data/lib/hq/graphql/root_query.rb +0 -1
- data/lib/hq/graphql/scalars.rb +0 -1
- data/lib/hq/graphql/schema.rb +22 -0
- data/lib/hq/graphql/types.rb +19 -8
- data/lib/hq/graphql/types/object.rb +7 -11
- data/lib/hq/graphql/types/uuid.rb +7 -14
- data/lib/hq/graphql/version.rb +1 -2
- metadata +9 -39
- data/lib/hq/graphql/loaders.rb +0 -4
- data/lib/hq/graphql/loaders/association.rb +0 -52
- data/lib/hq/graphql/resource/mutation.rb +0 -39
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module HQ
|
|
4
|
+
module GraphQL
|
|
5
|
+
module Resource
|
|
6
|
+
module AutoMutation
|
|
7
|
+
def build_create
|
|
8
|
+
scoped_self = self
|
|
9
|
+
|
|
10
|
+
build_mutation(action: :create) do
|
|
11
|
+
define_method(:resolve) do |**args|
|
|
12
|
+
resource = scoped_self.new_record(context)
|
|
13
|
+
resource.assign_attributes(args[:attributes].format_nested_attributes)
|
|
14
|
+
if resource.save
|
|
15
|
+
{
|
|
16
|
+
resource: resource,
|
|
17
|
+
errors: {},
|
|
18
|
+
}
|
|
19
|
+
else
|
|
20
|
+
{
|
|
21
|
+
resource: nil,
|
|
22
|
+
errors: errors_from_resource(resource)
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
lazy_load do
|
|
28
|
+
argument :attributes, ::HQ::GraphQL::Inputs[scoped_self.model_name], required: true
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def build_update
|
|
34
|
+
scoped_self = self
|
|
35
|
+
|
|
36
|
+
build_mutation(action: :update, require_primary_key: true) do
|
|
37
|
+
define_method(:resolve) do |**args|
|
|
38
|
+
resource = scoped_self.find_record(args, context)
|
|
39
|
+
|
|
40
|
+
if resource
|
|
41
|
+
resource.assign_attributes(args[:attributes].format_nested_attributes)
|
|
42
|
+
if resource.save
|
|
43
|
+
{
|
|
44
|
+
resource: resource,
|
|
45
|
+
errors: {},
|
|
46
|
+
}
|
|
47
|
+
else
|
|
48
|
+
{
|
|
49
|
+
resource: nil,
|
|
50
|
+
errors: errors_from_resource(resource)
|
|
51
|
+
}
|
|
52
|
+
end
|
|
53
|
+
else
|
|
54
|
+
{
|
|
55
|
+
resource: nil,
|
|
56
|
+
errors: { resource: "Unable to find #{self.class.graphql_name}" }
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
lazy_load do
|
|
62
|
+
argument :attributes, ::HQ::GraphQL::Inputs[scoped_self.model_name], required: true
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def build_copy
|
|
68
|
+
scoped_self = self
|
|
69
|
+
|
|
70
|
+
build_mutation(action: :copy, require_primary_key: true, nil_klass: true) do
|
|
71
|
+
define_method(:resolve) do |**args|
|
|
72
|
+
resource = scoped_self.find_record(args, context)
|
|
73
|
+
|
|
74
|
+
if resource
|
|
75
|
+
copy = resource.copy
|
|
76
|
+
if copy.save
|
|
77
|
+
{
|
|
78
|
+
resource: copy,
|
|
79
|
+
errors: {},
|
|
80
|
+
}
|
|
81
|
+
else
|
|
82
|
+
{
|
|
83
|
+
resource: copy,
|
|
84
|
+
errors: errors_from_resource(copy)
|
|
85
|
+
}
|
|
86
|
+
end
|
|
87
|
+
else
|
|
88
|
+
{
|
|
89
|
+
resource: nil,
|
|
90
|
+
errors: { resource: "Unable to find #{self.class.graphql_name}" }
|
|
91
|
+
}
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def build_destroy
|
|
98
|
+
scoped_self = self
|
|
99
|
+
|
|
100
|
+
build_mutation(action: :destroy, require_primary_key: true) do
|
|
101
|
+
define_method(:resolve) do |**attrs|
|
|
102
|
+
resource = scoped_self.find_record(attrs, context)
|
|
103
|
+
|
|
104
|
+
if resource
|
|
105
|
+
if resource.destroy
|
|
106
|
+
{
|
|
107
|
+
resource: resource,
|
|
108
|
+
errors: {},
|
|
109
|
+
}
|
|
110
|
+
else
|
|
111
|
+
{
|
|
112
|
+
resource: nil,
|
|
113
|
+
errors: errors_from_resource(resource)
|
|
114
|
+
}
|
|
115
|
+
end
|
|
116
|
+
else
|
|
117
|
+
{
|
|
118
|
+
resource: nil,
|
|
119
|
+
errors: { resource: "Unable to find #{self.class.graphql_name}" }
|
|
120
|
+
}
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def build_mutation(action:, require_primary_key: false, nil_klass: false, &block)
|
|
127
|
+
gql_name = "#{graphql_name}#{action.to_s.titleize}"
|
|
128
|
+
scoped_model_name = model_name
|
|
129
|
+
Class.new(::HQ::GraphQL::Mutation) do
|
|
130
|
+
graphql_name gql_name
|
|
131
|
+
|
|
132
|
+
define_method(:ready?) do |*args|
|
|
133
|
+
super(*args) && ::HQ::GraphQL.authorized?(action, scoped_model_name, context)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
lazy_load do
|
|
137
|
+
field :errors, ::HQ::GraphQL::Types::Object, null: false
|
|
138
|
+
field :resource, ::HQ::GraphQL::Types[scoped_model_name, nil_klass], null: true
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
instance_eval(&block)
|
|
142
|
+
|
|
143
|
+
if require_primary_key
|
|
144
|
+
lazy_load do
|
|
145
|
+
klass = scoped_model_name.constantize
|
|
146
|
+
primary_key = klass.primary_key
|
|
147
|
+
argument primary_key, ::GraphQL::Types::ID, required: true
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def errors_from_resource(resource)
|
|
152
|
+
resource.errors.to_h.deep_transform_keys { |k| k.to_s.camelize(:lower) }
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# typed: true
|
|
2
1
|
# frozen_string_literal: true
|
|
3
2
|
|
|
4
3
|
module HQ
|
|
@@ -8,7 +7,7 @@ module HQ
|
|
|
8
7
|
super
|
|
9
8
|
base.class_eval do
|
|
10
9
|
lazy_load do
|
|
11
|
-
::HQ::GraphQL.
|
|
10
|
+
::HQ::GraphQL.resources.each do |type|
|
|
12
11
|
type.mutation_klasses.each do |mutation_name, klass|
|
|
13
12
|
field mutation_name, mutation: klass
|
|
14
13
|
end
|
data/lib/hq/graphql/scalars.rb
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module HQ
|
|
4
|
+
module GraphQL
|
|
5
|
+
class Schema < ::GraphQL::Schema
|
|
6
|
+
class << self
|
|
7
|
+
def dump_directory(directory = Rails.root.join("app/graphql"))
|
|
8
|
+
@dump_directory ||= directory
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def dump_filename(filename = "#{self.name.underscore}.graphql")
|
|
12
|
+
@dump_filename ||= filename
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def dump
|
|
16
|
+
::FileUtils.mkdir_p(dump_directory)
|
|
17
|
+
::File.open(::File.join(dump_directory, dump_filename), "w") { |file| file.write(self.to_definition) }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/hq/graphql/types.rb
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# typed: true
|
|
2
1
|
# frozen_string_literal: true
|
|
3
2
|
|
|
4
3
|
module HQ
|
|
@@ -8,12 +7,23 @@ module HQ
|
|
|
8
7
|
MISSING_TYPE_MSG = "The GraphQL type for `%{klass}` is missing."
|
|
9
8
|
end
|
|
10
9
|
|
|
11
|
-
def self.
|
|
12
|
-
@
|
|
10
|
+
def self.registry
|
|
11
|
+
@registry ||= Hash.new do |hash, options|
|
|
13
12
|
klass, nil_klass = Array(options)
|
|
14
13
|
hash[klass] = nil_klass ? nil_query_klass(klass) : klass_for(klass)
|
|
15
14
|
end
|
|
16
|
-
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.register(k, v)
|
|
18
|
+
self[k] = v
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.[]=(key, is_nil = false, value)
|
|
22
|
+
registry[[key, is_nil]] = value
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.[](key, is_nil = false)
|
|
26
|
+
registry[[key, is_nil]]
|
|
17
27
|
end
|
|
18
28
|
|
|
19
29
|
def self.type_from_column(column)
|
|
@@ -38,7 +48,7 @@ module HQ
|
|
|
38
48
|
|
|
39
49
|
# Only being used in testing
|
|
40
50
|
def self.reset!
|
|
41
|
-
@
|
|
51
|
+
@registry = nil
|
|
42
52
|
end
|
|
43
53
|
|
|
44
54
|
class << self
|
|
@@ -54,9 +64,10 @@ module HQ
|
|
|
54
64
|
|
|
55
65
|
def find_klass(klass_or_string, method)
|
|
56
66
|
klass = klass_or_string.is_a?(String) ? klass_or_string.constantize : klass_or_string
|
|
57
|
-
::HQ::GraphQL.
|
|
58
|
-
|
|
59
|
-
|
|
67
|
+
resource = ::HQ::GraphQL.lookup_resource(klass)
|
|
68
|
+
|
|
69
|
+
raise(Error, Error::MISSING_TYPE_MSG % { klass: klass.name }) if !resource
|
|
70
|
+
resource.send(method)
|
|
60
71
|
end
|
|
61
72
|
end
|
|
62
73
|
end
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# typed: true
|
|
2
1
|
# frozen_string_literal: true
|
|
3
2
|
|
|
4
3
|
module HQ
|
|
@@ -7,17 +6,15 @@ module HQ
|
|
|
7
6
|
class Object < ::GraphQL::Schema::Scalar
|
|
8
7
|
description "Object"
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def coerce_input(value, _context)
|
|
14
|
-
validate_and_return_object(value)
|
|
15
|
-
end
|
|
9
|
+
def self.coerce_input(value, _context)
|
|
10
|
+
validate_and_return_object(value)
|
|
11
|
+
end
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
def self.coerce_result(value, _context)
|
|
14
|
+
validate_and_return_object(value)
|
|
15
|
+
end
|
|
20
16
|
|
|
17
|
+
class << self
|
|
21
18
|
private
|
|
22
19
|
|
|
23
20
|
def validate_and_return_object(value)
|
|
@@ -28,7 +25,6 @@ module HQ
|
|
|
28
25
|
end
|
|
29
26
|
end
|
|
30
27
|
|
|
31
|
-
sig { params(value: T.untyped).returns(T::Boolean) }
|
|
32
28
|
def validate_object(value)
|
|
33
29
|
value.is_a?(Hash)
|
|
34
30
|
end
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# typed: strict
|
|
2
1
|
# frozen_string_literal: true
|
|
3
2
|
|
|
4
3
|
module HQ
|
|
@@ -7,22 +6,17 @@ module HQ
|
|
|
7
6
|
class UUID < ::GraphQL::Schema::Scalar
|
|
8
7
|
description "UUID"
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
sig { params(value: T.untyped, _context: T.untyped).returns(String) }
|
|
14
|
-
def coerce_input(value, _context)
|
|
15
|
-
validate_and_return_uuid(value)
|
|
16
|
-
end
|
|
9
|
+
def self.coerce_input(value, _context)
|
|
10
|
+
validate_and_return_uuid(value)
|
|
11
|
+
end
|
|
17
12
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
end
|
|
13
|
+
def self.coerce_result(value, _context)
|
|
14
|
+
validate_and_return_uuid(value)
|
|
15
|
+
end
|
|
22
16
|
|
|
17
|
+
class << self
|
|
23
18
|
private
|
|
24
19
|
|
|
25
|
-
sig { params(value: T.untyped).returns(String) }
|
|
26
20
|
def validate_and_return_uuid(value)
|
|
27
21
|
if validate_uuid(value)
|
|
28
22
|
value
|
|
@@ -31,7 +25,6 @@ module HQ
|
|
|
31
25
|
end
|
|
32
26
|
end
|
|
33
27
|
|
|
34
|
-
sig { params(value: T.untyped).returns(T::Boolean) }
|
|
35
28
|
def validate_uuid(value)
|
|
36
29
|
!!value.to_s.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/)
|
|
37
30
|
end
|
data/lib/hq/graphql/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hq-graphql
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0
|
|
4
|
+
version: 2.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Danny Jones
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2020-06-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -29,9 +29,6 @@ dependencies:
|
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: '1.0'
|
|
34
|
-
- - ">="
|
|
35
32
|
- !ruby/object:Gem::Version
|
|
36
33
|
version: 1.9.6
|
|
37
34
|
type: :runtime
|
|
@@ -39,9 +36,6 @@ dependencies:
|
|
|
39
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
40
37
|
requirements:
|
|
41
38
|
- - "~>"
|
|
42
|
-
- !ruby/object:Gem::Version
|
|
43
|
-
version: '1.0'
|
|
44
|
-
- - ">="
|
|
45
39
|
- !ruby/object:Gem::Version
|
|
46
40
|
version: 1.9.6
|
|
47
41
|
- !ruby/object:Gem::Dependency
|
|
@@ -86,20 +80,6 @@ dependencies:
|
|
|
86
80
|
- - "~>"
|
|
87
81
|
- !ruby/object:Gem::Version
|
|
88
82
|
version: '1.1'
|
|
89
|
-
- !ruby/object:Gem::Dependency
|
|
90
|
-
name: sorbet-runtime
|
|
91
|
-
requirement: !ruby/object:Gem::Requirement
|
|
92
|
-
requirements:
|
|
93
|
-
- - ">="
|
|
94
|
-
- !ruby/object:Gem::Version
|
|
95
|
-
version: '0'
|
|
96
|
-
type: :runtime
|
|
97
|
-
prerelease: false
|
|
98
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
99
|
-
requirements:
|
|
100
|
-
- - ">="
|
|
101
|
-
- !ruby/object:Gem::Version
|
|
102
|
-
version: '0'
|
|
103
83
|
- !ruby/object:Gem::Dependency
|
|
104
84
|
name: sprockets
|
|
105
85
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -254,20 +234,6 @@ dependencies:
|
|
|
254
234
|
- - "~>"
|
|
255
235
|
- !ruby/object:Gem::Version
|
|
256
236
|
version: '2.3'
|
|
257
|
-
- !ruby/object:Gem::Dependency
|
|
258
|
-
name: sorbet
|
|
259
|
-
requirement: !ruby/object:Gem::Requirement
|
|
260
|
-
requirements:
|
|
261
|
-
- - ">="
|
|
262
|
-
- !ruby/object:Gem::Version
|
|
263
|
-
version: '0'
|
|
264
|
-
type: :development
|
|
265
|
-
prerelease: false
|
|
266
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
267
|
-
requirements:
|
|
268
|
-
- - ">="
|
|
269
|
-
- !ruby/object:Gem::Version
|
|
270
|
-
version: '0'
|
|
271
237
|
description: OneHQ GraphQL Library
|
|
272
238
|
email:
|
|
273
239
|
- dpjones09@gmail.com
|
|
@@ -281,21 +247,25 @@ files:
|
|
|
281
247
|
- lib/hq-graphql.rb
|
|
282
248
|
- lib/hq/graphql.rb
|
|
283
249
|
- lib/hq/graphql/active_record_extensions.rb
|
|
250
|
+
- lib/hq/graphql/association_loader.rb
|
|
284
251
|
- lib/hq/graphql/comparator.rb
|
|
285
252
|
- lib/hq/graphql/config.rb
|
|
286
253
|
- lib/hq/graphql/engine.rb
|
|
254
|
+
- lib/hq/graphql/enum.rb
|
|
255
|
+
- lib/hq/graphql/enum/sort_by.rb
|
|
256
|
+
- lib/hq/graphql/enum/sort_order.rb
|
|
287
257
|
- lib/hq/graphql/field.rb
|
|
288
258
|
- lib/hq/graphql/input_object.rb
|
|
289
259
|
- lib/hq/graphql/inputs.rb
|
|
290
|
-
- lib/hq/graphql/loaders.rb
|
|
291
|
-
- lib/hq/graphql/loaders/association.rb
|
|
292
260
|
- lib/hq/graphql/mutation.rb
|
|
293
261
|
- lib/hq/graphql/object.rb
|
|
262
|
+
- lib/hq/graphql/paginated_association_loader.rb
|
|
294
263
|
- lib/hq/graphql/resource.rb
|
|
295
|
-
- lib/hq/graphql/resource/
|
|
264
|
+
- lib/hq/graphql/resource/auto_mutation.rb
|
|
296
265
|
- lib/hq/graphql/root_mutation.rb
|
|
297
266
|
- lib/hq/graphql/root_query.rb
|
|
298
267
|
- lib/hq/graphql/scalars.rb
|
|
268
|
+
- lib/hq/graphql/schema.rb
|
|
299
269
|
- lib/hq/graphql/types.rb
|
|
300
270
|
- lib/hq/graphql/types/object.rb
|
|
301
271
|
- lib/hq/graphql/types/uuid.rb
|