hq-graphql 2.0.6 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.types.each do |type|
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
@@ -1,4 +1,3 @@
1
- # typed: true
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module HQ
@@ -1,4 +1,3 @@
1
- # typed: strict
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require "hq/graphql/types/object"
@@ -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
@@ -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.[](key, *args)
12
- @types ||= Hash.new do |hash, options|
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
- @types[[key, *args]]
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
- @types = nil
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.types.detect { |t| t.model_klass == klass }&.send(method) ||
58
- ::HQ::GraphQL.types.detect { |t| t.model_klass == klass.base_class }&.send(method) ||
59
- raise(Error, Error::MISSING_TYPE_MSG % { klass: klass.name })
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
- class << self
11
- extend T::Sig
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
- def coerce_result(value, _context)
18
- validate_and_return_object(value)
19
- end
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
- class << self
11
- extend T::Sig
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
- sig { params(value: T.untyped, _context: T.untyped).returns(String) }
19
- def coerce_result(value, _context)
20
- validate_and_return_uuid(value)
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
@@ -1,8 +1,7 @@
1
- # typed: strong
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module HQ
5
4
  module GraphQL
6
- VERSION = "2.0.6"
5
+ VERSION = "2.1.0"
7
6
  end
8
7
  end
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.6
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: 2019-11-25 00:00:00.000000000 Z
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/mutation.rb
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