hq-graphql 2.1.12 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,104 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hq/graphql/active_record_extensions"
4
- require "hq/graphql/inputs"
5
- require "hq/graphql/types"
6
-
7
- module HQ
8
- module GraphQL
9
- class InputObject < ::GraphQL::Schema::InputObject
10
- include Scalars
11
- include ::HQ::GraphQL::ActiveRecordExtensions
12
-
13
- # Recursively format attributes so that they are compatible with `accepts_nested_attributes_for`
14
- def format_nested_attributes
15
- self.each.inject({}) do |formatted_attrs, (key, value) |
16
- if self.class.nested_attributes.include?(key.to_s)
17
- formatted_value =
18
- if value.is_a?(Array)
19
- value.map(&:format_nested_attributes)
20
- elsif value
21
- value.format_nested_attributes
22
- end
23
-
24
- formatted_attrs[:"#{key}_attributes"] = formatted_value if formatted_value
25
- elsif key.to_s == "x"
26
- formatted_attrs[:X] = value
27
- else
28
- formatted_attrs[key] = value
29
- end
30
- formatted_attrs
31
- end
32
- end
33
-
34
- #### Class Methods ####
35
- def self.with_model(model_name, attributes: true, associations: false, enums: true, excluded_inputs: [])
36
- self.model_name = model_name
37
- self.auto_load_attributes = attributes
38
- self.auto_load_associations = associations
39
- self.auto_load_enums = enums
40
-
41
- lazy_load do
42
- excluded_inputs += ::HQ::GraphQL.excluded_inputs
43
-
44
- model_columns.each do |column|
45
- argument_from_column(column) unless excluded_inputs.include?(column.name.to_sym)
46
- end
47
-
48
- model_associations.each do |association|
49
- argument_from_association(association) unless excluded_inputs.include?(association.name.to_sym)
50
- end
51
-
52
- argument :X, String, required: false
53
- end
54
- end
55
-
56
- def self.nested_attributes
57
- @nested_attributes ||= Set.new
58
- end
59
-
60
- def self.to_graphql
61
- lazy_load!
62
- super
63
- end
64
-
65
- class << self
66
- private
67
-
68
- def argument_from_association(association)
69
- is_enum = is_enum?(association)
70
- input_or_type = is_enum ? ::HQ::GraphQL::Types[association.klass] : ::HQ::GraphQL::Inputs[association.klass]
71
- name = association.name
72
- return if argument_exists?(name)
73
-
74
- case association.macro
75
- when :has_many
76
- argument name, [input_or_type], required: false
77
- else
78
- argument name, input_or_type, required: false
79
- end
80
-
81
- return if is_enum
82
-
83
- if !model_klass.nested_attributes_options.key?(name.to_sym)
84
- model_klass.accepts_nested_attributes_for name, allow_destroy: true
85
- end
86
-
87
- nested_attributes << name.to_s
88
- rescue ::HQ::GraphQL::Inputs::Error
89
- nil
90
- end
91
-
92
- def argument_from_column(column)
93
- name = column.name
94
- return if argument_exists?(name)
95
- argument name, ::HQ::GraphQL::Types.type_from_column(column), required: false
96
- end
97
-
98
- def argument_exists?(name)
99
- !!arguments[camelize(name)]
100
- end
101
- end
102
- end
103
- end
104
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module HQ
4
- module GraphQL
5
- class Mutation < ::GraphQL::Schema::Mutation
6
- include Scalars
7
- include ::HQ::GraphQL::ActiveRecordExtensions
8
-
9
- def self.generate_payload_type
10
- lazy_load!
11
- super
12
- end
13
- end
14
- end
15
- end
@@ -1,120 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hq/graphql/active_record_extensions"
4
- require "hq/graphql/field"
5
- require "hq/graphql/field_extension/association_loader_extension"
6
- require "hq/graphql/field_extension/paginated_arguments"
7
- require "hq/graphql/field_extension/paginated_loader"
8
- require "hq/graphql/object_association"
9
- require "hq/graphql/types"
10
-
11
- module HQ
12
- module GraphQL
13
- class Object < ::GraphQL::Schema::Object
14
- include Scalars
15
- include ActiveRecordExtensions
16
- extend ObjectAssociation
17
-
18
- field_class Field
19
-
20
- def self.authorize_action(action)
21
- self.authorized_action = action
22
- end
23
-
24
- def self.authorized?(object, context)
25
- super && ::HQ::GraphQL.authorized?(authorized_action, object, context)
26
- end
27
-
28
- def self.with_model(model_name, attributes: true, associations: true, auto_nil: true, enums: true)
29
- self.model_name = model_name
30
- self.auto_load_attributes = attributes
31
- self.auto_load_associations = associations
32
- self.auto_load_enums = enums
33
-
34
- lazy_load do
35
- model_columns.each do |column|
36
- field_from_column(column, auto_nil: auto_nil)
37
- end
38
-
39
- model_associations.each do |association|
40
- next if resource_reflections[association.name.to_s]
41
- field_from_association(association, auto_nil: auto_nil)
42
- end
43
-
44
- resource_reflections.values.each do |resource_reflection|
45
- reflection = resource_reflection.reflection(model_klass)
46
- next unless reflection
47
- field_from_association(reflection, auto_nil: auto_nil, internal_association: true, &resource_reflection.block)
48
- end
49
- end
50
- end
51
-
52
- def self.to_graphql
53
- lazy_load!
54
- super
55
- end
56
-
57
- class << self
58
- private
59
- attr_writer :authorized_action
60
-
61
- def authorized_action
62
- @authorized_action ||= :read
63
- end
64
-
65
- def field_from_association(association, auto_nil:, internal_association: false, &block)
66
- association_klass = association.klass
67
- name = association.name.to_s
68
- return if field_exists?(name)
69
-
70
- klass = model_klass
71
- type = Types[association_klass]
72
- case association.macro
73
- when :has_many
74
- field name, [type], null: false, klass: model_name do
75
- if ::HQ::GraphQL.use_experimental_associations?
76
- extension FieldExtension::PaginatedArguments, klass: association_klass
77
- extension FieldExtension::PaginatedLoader, klass: klass, association: name, internal_association: internal_association
78
- else
79
- extension FieldExtension::AssociationLoaderExtension, klass: klass
80
- end
81
- instance_eval(&block) if block
82
- end
83
- when :has_one
84
- field name, type, null: !auto_nil || !has_presence_validation?(association), klass: model_name do
85
- extension FieldExtension::AssociationLoaderExtension, klass: klass
86
- end
87
- else
88
- field name, type, null: !auto_nil || !association_required?(association), klass: model_name do
89
- extension FieldExtension::AssociationLoaderExtension, klass: klass
90
- end
91
- end
92
- rescue Types::Error
93
- nil
94
- end
95
-
96
- def field_from_column(column, auto_nil:)
97
- name = column.name
98
- return if field_exists?(name)
99
-
100
- field name, Types.type_from_column(column), null: !auto_nil || column.null
101
- end
102
-
103
- def field_exists?(name)
104
- !!fields[camelize(name)]
105
- end
106
-
107
- def association_required?(association)
108
- !association.options[:optional] || has_presence_validation?(association)
109
- end
110
-
111
- def has_presence_validation?(association)
112
- model_klass.validators.any? do |validation|
113
- next unless validation.class == ActiveRecord::Validations::PresenceValidator && !(validation.options.include?(:if) || validation.options.include?(:unless))
114
- validation.attributes.any? { |a| a.to_s == association.name.to_s }
115
- end
116
- end
117
- end
118
- end
119
- end
120
- end
@@ -1,22 +0,0 @@
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,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module HQ
4
- module GraphQL
5
- module Types
6
- class Object < ::GraphQL::Schema::Scalar
7
- description "Object"
8
-
9
- def self.coerce_input(value, _context)
10
- validate_and_return_object(value)
11
- end
12
-
13
- def self.coerce_result(value, _context)
14
- validate_and_return_object(value)
15
- end
16
-
17
- class << self
18
- private
19
-
20
- def validate_and_return_object(value)
21
- if validate_object(value)
22
- value
23
- else
24
- raise ::GraphQL::CoercionError, "#{value.inspect} is not a valid Object"
25
- end
26
- end
27
-
28
- def validate_object(value)
29
- value.is_a?(Hash)
30
- end
31
- end
32
- end
33
- end
34
- end
35
- end