lighthouse-graphql 0.1.1 → 0.2.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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +154 -1
  3. data/README.md +42 -2
  4. data/docs/authorization.md +116 -57
  5. data/docs/best-practices.md +16 -3
  6. data/docs/caching.md +161 -0
  7. data/docs/configuration.md +83 -4
  8. data/docs/custom-directives.md +5 -1
  9. data/docs/directives.md +117 -38
  10. data/docs/getting-started.md +84 -0
  11. data/docs/mutations.md +260 -0
  12. data/docs/performance.md +138 -0
  13. data/docs/relationships.md +80 -33
  14. data/docs/resolvers.md +179 -0
  15. data/docs/validation.md +132 -0
  16. data/lib/generators/lighthouse/builder_generator.rb +30 -0
  17. data/lib/generators/lighthouse/class_generator.rb +61 -0
  18. data/lib/generators/lighthouse/install/install_generator.rb +127 -0
  19. data/lib/generators/lighthouse/install/templates/graphql.config.yml.tt +8 -0
  20. data/lib/generators/lighthouse/install/templates/graphql_controller.rb.tt +57 -0
  21. data/lib/generators/lighthouse/install/templates/initializer.rb.tt +67 -0
  22. data/lib/generators/lighthouse/install/templates/schema.graphql.tt +19 -0
  23. data/lib/generators/lighthouse/install/templates/schema.rb.tt +10 -0
  24. data/lib/generators/lighthouse/mutation_generator.rb +30 -0
  25. data/lib/generators/lighthouse/query_generator.rb +29 -0
  26. data/lib/generators/lighthouse/validator_generator.rb +36 -0
  27. data/lib/lighthouse/cache_control.rb +126 -0
  28. data/lib/lighthouse/caching.rb +68 -0
  29. data/lib/lighthouse/config.rb +85 -19
  30. data/lib/lighthouse/contracts/arg_builder.rb +8 -12
  31. data/lib/lighthouse/contracts/arg_manipulator.rb +8 -12
  32. data/lib/lighthouse/contracts/directive.rb +10 -14
  33. data/lib/lighthouse/contracts/field_manipulator.rb +8 -12
  34. data/lib/lighthouse/contracts/field_middleware.rb +7 -11
  35. data/lib/lighthouse/contracts/field_resolver.rb +9 -13
  36. data/lib/lighthouse/dataloader_sources/association_loader.rb +28 -19
  37. data/lib/lighthouse/dataloader_sources/model_loader.rb +10 -14
  38. data/lib/lighthouse/dataloader_sources/relation_count_loader.rb +16 -0
  39. data/lib/lighthouse/dataloader_sources/relation_page_loader.rb +18 -0
  40. data/lib/lighthouse/directive_resolvers/aggregate_resolver.rb +57 -69
  41. data/lib/lighthouse/directive_resolvers/all_resolver.rb +26 -57
  42. data/lib/lighthouse/directive_resolvers/association_resolvers.rb +161 -0
  43. data/lib/lighthouse/directive_resolvers/auth_resolver.rb +41 -38
  44. data/lib/lighthouse/directive_resolvers/base.rb +142 -86
  45. data/lib/lighthouse/directive_resolvers/builder_applier.rb +58 -56
  46. data/lib/lighthouse/directive_resolvers/cache_resolvers.rb +133 -0
  47. data/lib/lighthouse/directive_resolvers/can_resolvers.rb +177 -0
  48. data/lib/lighthouse/directive_resolvers/convention_resolver.rb +70 -0
  49. data/lib/lighthouse/directive_resolvers/count_resolver.rb +42 -48
  50. data/lib/lighthouse/directive_resolvers/field_resolver.rb +27 -68
  51. data/lib/lighthouse/directive_resolvers/find_resolver.rb +42 -52
  52. data/lib/lighthouse/directive_resolvers/first_resolver.rb +39 -45
  53. data/lib/lighthouse/directive_resolvers/guard_resolver.rb +16 -22
  54. data/lib/lighthouse/directive_resolvers/method_resolver.rb +19 -25
  55. data/lib/lighthouse/directive_resolvers/model_mutation_resolver.rb +219 -0
  56. data/lib/lighthouse/directive_resolvers/paginate_resolver.rb +70 -128
  57. data/lib/lighthouse/directive_resolvers/rename_resolver.rb +18 -24
  58. data/lib/lighthouse/directive_resolvers/resolution.rb +31 -27
  59. data/lib/lighthouse/directive_resolvers/validator_resolver.rb +193 -0
  60. data/lib/lighthouse/directive_resolvers/where_conditions_applier.rb +164 -163
  61. data/lib/lighthouse/directives/arguments/base.rb +23 -31
  62. data/lib/lighthouse/directives/arguments/filters.rb +113 -93
  63. data/lib/lighthouse/directives/arguments/order_by.rb +41 -41
  64. data/lib/lighthouse/directives/pagination_info_types.rb +69 -0
  65. data/lib/lighthouse/directives/pagination_manipulator.rb +176 -0
  66. data/lib/lighthouse/directives/registry.rb +210 -141
  67. data/lib/lighthouse/directives/where_conditions_directive.rb +236 -200
  68. data/lib/lighthouse/errors.rb +27 -0
  69. data/lib/lighthouse/federation_directives.rb +53 -0
  70. data/lib/lighthouse/field_resolver_stack.rb +56 -0
  71. data/lib/lighthouse/generated_resolvers.rb +82 -0
  72. data/lib/lighthouse/graphql/version.rb +1 -1
  73. data/lib/lighthouse/graphql_ruby_patches.rb +18 -0
  74. data/lib/lighthouse/ide_helper.rb +98 -0
  75. data/lib/lighthouse/namespaces.rb +21 -0
  76. data/lib/lighthouse/nested_mutations/belongs_to_operations.rb +50 -0
  77. data/lib/lighthouse/nested_mutations/executor.rb +149 -0
  78. data/lib/lighthouse/nested_mutations/has_operations.rb +66 -0
  79. data/lib/lighthouse/nested_mutations/many_to_many_operations.rb +44 -0
  80. data/lib/lighthouse/nested_mutations/partitioner.rb +125 -0
  81. data/lib/lighthouse/nested_mutations.rb +210 -0
  82. data/lib/lighthouse/pagination.rb +221 -0
  83. data/lib/lighthouse/persisted_queries.rb +167 -0
  84. data/lib/lighthouse/railtie.rb +26 -0
  85. data/lib/lighthouse/rb_lighthouse.rb +50 -29
  86. data/lib/lighthouse/reference_resolver.rb +13 -15
  87. data/lib/lighthouse/relation_batch.rb +156 -0
  88. data/lib/lighthouse/resolver_dispatch.rb +26 -0
  89. data/lib/lighthouse/schema_cache.rb +120 -0
  90. data/lib/lighthouse/schema_factory.rb +27 -37
  91. data/lib/lighthouse/schema_generator.rb +196 -239
  92. data/lib/lighthouse/schema_implementation.rb +51 -48
  93. data/lib/lighthouse/sdl_loader.rb +17 -20
  94. data/lib/lighthouse/support/arguments.rb +119 -0
  95. data/lib/lighthouse/support/authorization.rb +18 -19
  96. data/lib/lighthouse/support/batching.rb +16 -0
  97. data/lib/lighthouse/support/directive_args.rb +26 -24
  98. data/lib/lighthouse/support/model_resolver.rb +56 -56
  99. data/lib/lighthouse/support/naming.rb +55 -59
  100. data/lib/lighthouse/tasks/lighthouse.rake +33 -0
  101. data/lib/lighthouse/where_conditions/operator_map.rb +25 -29
  102. metadata +51 -63
  103. data/lib/lighthouse/directive_resolvers/belongs_to_many_resolver.rb +0 -56
  104. data/lib/lighthouse/directive_resolvers/belongs_to_resolver.rb +0 -47
  105. data/lib/lighthouse/directive_resolvers/can_resolver.rb +0 -86
  106. data/lib/lighthouse/directive_resolvers/has_many_resolver.rb +0 -109
  107. data/lib/lighthouse/directive_resolvers/has_one_resolver.rb +0 -43
  108. data/lib/lighthouse/directives/relation_directive.rb +0 -332
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lighthouse-graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vaz Innovation
@@ -37,62 +37,6 @@ dependencies:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
39
  version: '2.5'
40
- - !ruby/object:Gem::Dependency
41
- name: rspec
42
- requirement: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - "~>"
45
- - !ruby/object:Gem::Version
46
- version: '3.0'
47
- type: :development
48
- prerelease: false
49
- version_requirements: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '3.0'
54
- - !ruby/object:Gem::Dependency
55
- name: activerecord
56
- requirement: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: '6.0'
61
- type: :development
62
- prerelease: false
63
- version_requirements: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - ">="
66
- - !ruby/object:Gem::Version
67
- version: '6.0'
68
- - !ruby/object:Gem::Dependency
69
- name: sqlite3
70
- requirement: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- version: '1.4'
75
- type: :development
76
- prerelease: false
77
- version_requirements: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- version: '1.4'
82
- - !ruby/object:Gem::Dependency
83
- name: apollo-federation
84
- requirement: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '3.0'
89
- type: :development
90
- prerelease: false
91
- version_requirements: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "~>"
94
- - !ruby/object:Gem::Version
95
- version: '3.0'
96
40
  description: |
97
41
  Lighthouse lets you build a GraphQL API for your Rails app primarily through
98
42
  schema (SDL) and server-side directives — @all, @find, @paginate, @hasMany,
@@ -111,14 +55,32 @@ files:
111
55
  - README.md
112
56
  - docs/authorization.md
113
57
  - docs/best-practices.md
58
+ - docs/caching.md
114
59
  - docs/configuration.md
115
60
  - docs/custom-directives.md
116
61
  - docs/directives.md
117
62
  - docs/federation.md
118
63
  - docs/filtering-and-ordering.md
119
64
  - docs/getting-started.md
65
+ - docs/mutations.md
66
+ - docs/performance.md
120
67
  - docs/relationships.md
68
+ - docs/resolvers.md
69
+ - docs/validation.md
70
+ - lib/generators/lighthouse/builder_generator.rb
71
+ - lib/generators/lighthouse/class_generator.rb
72
+ - lib/generators/lighthouse/install/install_generator.rb
73
+ - lib/generators/lighthouse/install/templates/graphql.config.yml.tt
74
+ - lib/generators/lighthouse/install/templates/graphql_controller.rb.tt
75
+ - lib/generators/lighthouse/install/templates/initializer.rb.tt
76
+ - lib/generators/lighthouse/install/templates/schema.graphql.tt
77
+ - lib/generators/lighthouse/install/templates/schema.rb.tt
78
+ - lib/generators/lighthouse/mutation_generator.rb
79
+ - lib/generators/lighthouse/query_generator.rb
80
+ - lib/generators/lighthouse/validator_generator.rb
121
81
  - lib/lighthouse-graphql.rb
82
+ - lib/lighthouse/cache_control.rb
83
+ - lib/lighthouse/caching.rb
122
84
  - lib/lighthouse/config.rb
123
85
  - lib/lighthouse/contracts/arg_builder.rb
124
86
  - lib/lighthouse/contracts/arg_manipulator.rb
@@ -128,44 +90,70 @@ files:
128
90
  - lib/lighthouse/contracts/field_resolver.rb
129
91
  - lib/lighthouse/dataloader_sources/association_loader.rb
130
92
  - lib/lighthouse/dataloader_sources/model_loader.rb
93
+ - lib/lighthouse/dataloader_sources/relation_count_loader.rb
94
+ - lib/lighthouse/dataloader_sources/relation_page_loader.rb
131
95
  - lib/lighthouse/directive_resolvers/aggregate_resolver.rb
132
96
  - lib/lighthouse/directive_resolvers/all_resolver.rb
97
+ - lib/lighthouse/directive_resolvers/association_resolvers.rb
133
98
  - lib/lighthouse/directive_resolvers/auth_resolver.rb
134
99
  - lib/lighthouse/directive_resolvers/base.rb
135
- - lib/lighthouse/directive_resolvers/belongs_to_many_resolver.rb
136
- - lib/lighthouse/directive_resolvers/belongs_to_resolver.rb
137
100
  - lib/lighthouse/directive_resolvers/builder_applier.rb
138
- - lib/lighthouse/directive_resolvers/can_resolver.rb
101
+ - lib/lighthouse/directive_resolvers/cache_resolvers.rb
102
+ - lib/lighthouse/directive_resolvers/can_resolvers.rb
103
+ - lib/lighthouse/directive_resolvers/convention_resolver.rb
139
104
  - lib/lighthouse/directive_resolvers/count_resolver.rb
140
105
  - lib/lighthouse/directive_resolvers/field_resolver.rb
141
106
  - lib/lighthouse/directive_resolvers/find_resolver.rb
142
107
  - lib/lighthouse/directive_resolvers/first_resolver.rb
143
108
  - lib/lighthouse/directive_resolvers/guard_resolver.rb
144
- - lib/lighthouse/directive_resolvers/has_many_resolver.rb
145
- - lib/lighthouse/directive_resolvers/has_one_resolver.rb
146
109
  - lib/lighthouse/directive_resolvers/method_resolver.rb
110
+ - lib/lighthouse/directive_resolvers/model_mutation_resolver.rb
147
111
  - lib/lighthouse/directive_resolvers/paginate_resolver.rb
148
112
  - lib/lighthouse/directive_resolvers/rename_resolver.rb
149
113
  - lib/lighthouse/directive_resolvers/resolution.rb
114
+ - lib/lighthouse/directive_resolvers/validator_resolver.rb
150
115
  - lib/lighthouse/directive_resolvers/where_conditions_applier.rb
151
116
  - lib/lighthouse/directives/arguments/base.rb
152
117
  - lib/lighthouse/directives/arguments/filters.rb
153
118
  - lib/lighthouse/directives/arguments/order_by.rb
119
+ - lib/lighthouse/directives/pagination_info_types.rb
120
+ - lib/lighthouse/directives/pagination_manipulator.rb
154
121
  - lib/lighthouse/directives/registry.rb
155
- - lib/lighthouse/directives/relation_directive.rb
156
122
  - lib/lighthouse/directives/where_conditions_directive.rb
123
+ - lib/lighthouse/errors.rb
124
+ - lib/lighthouse/federation_directives.rb
125
+ - lib/lighthouse/field_resolver_stack.rb
126
+ - lib/lighthouse/generated_resolvers.rb
157
127
  - lib/lighthouse/graphql.rb
158
128
  - lib/lighthouse/graphql/version.rb
129
+ - lib/lighthouse/graphql_ruby_patches.rb
130
+ - lib/lighthouse/ide_helper.rb
131
+ - lib/lighthouse/namespaces.rb
132
+ - lib/lighthouse/nested_mutations.rb
133
+ - lib/lighthouse/nested_mutations/belongs_to_operations.rb
134
+ - lib/lighthouse/nested_mutations/executor.rb
135
+ - lib/lighthouse/nested_mutations/has_operations.rb
136
+ - lib/lighthouse/nested_mutations/many_to_many_operations.rb
137
+ - lib/lighthouse/nested_mutations/partitioner.rb
138
+ - lib/lighthouse/pagination.rb
139
+ - lib/lighthouse/persisted_queries.rb
140
+ - lib/lighthouse/railtie.rb
159
141
  - lib/lighthouse/rb_lighthouse.rb
160
142
  - lib/lighthouse/reference_resolver.rb
143
+ - lib/lighthouse/relation_batch.rb
144
+ - lib/lighthouse/resolver_dispatch.rb
145
+ - lib/lighthouse/schema_cache.rb
161
146
  - lib/lighthouse/schema_factory.rb
162
147
  - lib/lighthouse/schema_generator.rb
163
148
  - lib/lighthouse/schema_implementation.rb
164
149
  - lib/lighthouse/sdl_loader.rb
150
+ - lib/lighthouse/support/arguments.rb
165
151
  - lib/lighthouse/support/authorization.rb
152
+ - lib/lighthouse/support/batching.rb
166
153
  - lib/lighthouse/support/directive_args.rb
167
154
  - lib/lighthouse/support/model_resolver.rb
168
155
  - lib/lighthouse/support/naming.rb
156
+ - lib/lighthouse/tasks/lighthouse.rake
169
157
  - lib/lighthouse/where_conditions/operator_map.rb
170
158
  homepage: https://github.com/Vaz-Innovation/lighthouse-graphql
171
159
  licenses:
@@ -1,56 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module Lighthouse
6
- module GraphQL
7
- module DirectiveResolvers
8
- class BelongsToManyDirectiveResolver < BaseDirectiveResolver
9
- def define_resolver(target_type_class)
10
- field_name = @field_def.name
11
- assoc_name = extract_relation_name || field_name
12
-
13
- method_name = "resolve_field_#{field_name}"
14
-
15
- target_type_class.define_singleton_method(method_name) do |obj, arguments, ctx|
16
- # Use dataloader when available
17
- if ctx && ctx.respond_to?(:dataloader) && ctx.dataloader
18
- loader = ctx.dataloader.with(Lighthouse::GraphQL::DataloaderSources::AssociationLoader, obj.class, assoc_name)
19
- return loader.load(obj)
20
- end
21
-
22
- # Fallback: call the association directly
23
- if obj.respond_to?(assoc_name)
24
- args = arguments.respond_to?(:to_h) ? arguments.to_h : {}
25
- return obj.public_send(assoc_name)
26
- end
27
-
28
- nil
29
- end
30
-
31
- if @field_def.respond_to?(:resolve_proc=)
32
- @field_def.resolve_proc = ->(obj, arguments, ctx) do
33
- if ctx && ctx.respond_to?(:dataloader) && ctx.dataloader
34
- loader = ctx.dataloader.with(Lighthouse::GraphQL::DataloaderSources::AssociationLoader, obj.class, assoc_name)
35
- loader.load(obj)
36
- elsif obj.respond_to?(assoc_name)
37
- args = arguments.respond_to?(:to_h) ? arguments.to_h : {}
38
- obj.public_send(assoc_name)
39
- else
40
- nil
41
- end
42
- end
43
- end
44
- end
45
-
46
- private
47
-
48
- def extract_relation_name
49
- arg = @directive_node.arguments&.find { |a| a.name == 'relation' }
50
- return nil unless arg
51
- arg.value.respond_to?(:value) ? arg.value.value : arg.value
52
- end
53
- end
54
- end
55
- end
56
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module Lighthouse
6
- module GraphQL
7
- module DirectiveResolvers
8
- class BelongsToDirectiveResolver < BaseDirectiveResolver
9
- def define_resolver(target_type_class)
10
- field_name = @field_def.name
11
- assoc_name = extract_relation_name || field_name
12
- method_name = "resolve_field_#{field_name}"
13
-
14
- target_type_class.define_singleton_method(method_name) do |obj, _arguments, ctx|
15
- if ctx && ctx.respond_to?(:dataloader) && ctx.dataloader
16
- loader = ctx.dataloader.with(Lighthouse::GraphQL::DataloaderSources::AssociationLoader, obj.class, assoc_name)
17
- return loader.load(obj)
18
- end
19
-
20
- obj.public_send(assoc_name) if obj.respond_to?(assoc_name)
21
- end
22
-
23
- if @field_def.respond_to?(:resolve_proc=)
24
- @field_def.resolve_proc = ->(obj, _arguments, ctx) do
25
- if ctx && ctx.respond_to?(:dataloader) && ctx.dataloader
26
- loader = ctx.dataloader.with(Lighthouse::GraphQL::DataloaderSources::AssociationLoader, obj.class, assoc_name)
27
- loader.load(obj)
28
- elsif obj.respond_to?(assoc_name)
29
- obj.public_send(assoc_name)
30
- else
31
- nil
32
- end
33
- end
34
- end
35
- end
36
-
37
- private
38
-
39
- def extract_relation_name
40
- arg = @directive_node.arguments&.find { |a| a.name == 'relation' }
41
- return nil unless arg
42
- arg.value.respond_to?(:value) ? arg.value.value : arg.value
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -1,86 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module Lighthouse
6
- module GraphQL
7
- module DirectiveResolvers
8
- # @can — authorize access to a field using a policy ability (Pundit by
9
- # default; configurable via Config.authorizer). Mirrors PHP Lighthouse's
10
- # @can* family. Repeatable.
11
- #
12
- # contact(id: ID!): Contact @field(resolver: "...") @can(ability: "show")
13
- #
14
- # Modes:
15
- # * default — resolve the field, then authorize the resolved
16
- # record (skips nil; passes collections through —
17
- # use scoping for lists).
18
- # * root: true — authorize the parent object before resolving.
19
- # * find / model — look the model up by an argument and authorize it
20
- # before resolving.
21
- class CanDirectiveResolver < BaseDirectiveResolver
22
- def self.directive_name = 'can'
23
- def self.definition
24
- 'directive @can(ability: String!, find: String, model: String, root: Boolean) repeatable on FIELD_DEFINITION'
25
- end
26
-
27
- def define_resolver(target_type_class)
28
- field_name = @field_def.name
29
- method_name = "resolve_field_#{field_name}"
30
- ability = directive_arg('ability')
31
- return if ability.nil?
32
-
33
- find_arg = directive_arg('find')
34
- model_name = directive_arg('model')
35
- root = directive_arg('root')
36
- inner = Resolution.capture(target_type_class, method_name, @field_def, field_name)
37
- resolver_instance = self
38
-
39
- wrapper = lambda do |obj, arguments, ctx|
40
- if root
41
- resolver_instance.send(:authorize_or_raise, ctx, obj, ability)
42
- next inner.call(obj, arguments, ctx)
43
- end
44
-
45
- if find_arg && model_name
46
- args_h = arguments.respond_to?(:to_h) ? arguments.to_h : {}
47
- id = Lighthouse::Support::Naming.fetch_arg(args_h, find_arg)
48
- model_class = resolver_instance.send(:constantize_model, model_name)
49
- record = model_class&.find_by(id: id)
50
- resolver_instance.send(:authorize_or_raise, ctx, record, ability)
51
- next inner.call(obj, arguments, ctx)
52
- end
53
-
54
- result = inner.call(obj, arguments, ctx)
55
- resolver_instance.send(:authorize_resolved, ctx, result, ability)
56
- end
57
-
58
- target_type_class.define_singleton_method(method_name, &wrapper)
59
- @field_def.resolve_proc = wrapper if @field_def.respond_to?(:resolve_proc=)
60
- end
61
-
62
- private
63
-
64
- def directive_arg(name)
65
- Lighthouse::Support::DirectiveArgs.literal(@directive_node, name)
66
- end
67
-
68
- def authorize_resolved(ctx, result, ability)
69
- return result if result.nil?
70
- # Collections are filtered with scoping, not item-by-item authorization.
71
- return result if result.respond_to?(:each) && !result.respond_to?(:id)
72
-
73
- authorize_or_raise(ctx, result, ability)
74
- result
75
- end
76
-
77
- def authorize_or_raise(ctx, record, ability)
78
- return if record.nil?
79
-
80
- authorized = Lighthouse::Support::Authorization.authorized?(ctx, record, ability)
81
- raise(::GraphQL::ExecutionError, 'You are not authorized to perform this action.') unless authorized
82
- end
83
- end
84
- end
85
- end
86
- end
@@ -1,109 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module Lighthouse
6
- module GraphQL
7
- module DirectiveResolvers
8
- class HasManyDirectiveResolver < BaseDirectiveResolver
9
- def define_resolver(target_type_class)
10
- field_name = @field_def.name
11
- assoc_name = extract_relation_name || field_name
12
- is_connection = @field_def.respond_to?(:connection?) ? @field_def.connection? : false
13
-
14
- resolver_instance = self
15
-
16
- # Keep compatibility with SchemaImplementation-based resolution by
17
- # defining a singleton method on the owner type (e.g. Inbox.resolve_field_conversations).
18
- method_name = "resolve_field_#{field_name}"
19
-
20
- target_type_class.define_singleton_method(method_name) do |*args|
21
- # Support both batch and single resolution modes.
22
- # Batch mode signature: (objects_array, ctx)
23
- # Single mode signature: (obj, arguments, ctx)
24
- if args.length == 2 && args[0].is_a?(Array)
25
- parents, ctx = args
26
-
27
- if ctx && ctx.respond_to?(:dataloader) && ctx.dataloader
28
- loader = ctx.dataloader.with(Lighthouse::GraphQL::DataloaderSources::AssociationLoader, parents.first.class, assoc_name)
29
- parents.map do |p|
30
- promise = loader.load(p)
31
- if is_connection
32
- promise.then { |value| ::GraphQL::Pagination::ArrayConnection.new(value, context: ctx, parent: nil, field: nil, arguments: {}) }
33
- else
34
- promise
35
- end
36
- end
37
- else
38
- parents.map do |p|
39
- value = p.respond_to?(assoc_name) ? p.public_send(assoc_name) : nil
40
- is_connection && value ? ::GraphQL::Pagination::ArrayConnection.new(value, context: ctx, parent: nil, field: nil, arguments: {}) : value
41
- end
42
- end
43
- else
44
- obj, arguments, ctx = args
45
-
46
- # Use dataloader when available
47
- if ctx && ctx.respond_to?(:dataloader) && ctx.dataloader
48
- args_h = arguments.respond_to?(:to_h) ? arguments.to_h : {}
49
- loader = ctx.dataloader.with(Lighthouse::GraphQL::DataloaderSources::AssociationLoader, obj.class, assoc_name)
50
- value = loader.load(obj)
51
- if is_connection
52
- value.then do |v|
53
- filtered = resolver_instance.apply_where_filters(v, args_h)
54
- ::GraphQL::Pagination::ArrayConnection.new(filtered, context: ctx, parent: nil, field: nil, arguments: {})
55
- end
56
- else
57
- value.then { |v| resolver_instance.apply_where_filters(v, args_h) }
58
- end
59
- elsif obj.respond_to?(assoc_name)
60
- args_h = arguments.respond_to?(:to_h) ? arguments.to_h : {}
61
- value = obj.public_send(assoc_name)
62
- value = resolver_instance.apply_where_filters(value, args_h)
63
- is_connection && value ? ::GraphQL::Pagination::ArrayConnection.new(value, context: ctx, parent: nil, field: nil, arguments: {}) : value
64
- else
65
- nil
66
- end
67
- end
68
- end
69
-
70
- # Also attach a resolve proc where supported by the GraphQL runtime.
71
- if @field_def.respond_to?(:resolve_proc=)
72
- @field_def.resolve_proc = ->(obj, arguments, ctx) do
73
- if ctx && ctx.respond_to?(:dataloader) && ctx.dataloader
74
- args_h = arguments.respond_to?(:to_h) ? arguments.to_h : {}
75
- loader = ctx.dataloader.with(Lighthouse::GraphQL::DataloaderSources::AssociationLoader, obj.class, assoc_name)
76
- result = loader.load(obj)
77
- if is_connection
78
- result.then do |value|
79
- filtered = resolver_instance.apply_where_filters(value, args_h)
80
- ::GraphQL::Pagination::ArrayConnection.new(filtered, context: ctx, parent: nil, field: nil, arguments: {})
81
- end
82
- else
83
- result.then { |value| resolver_instance.apply_where_filters(value, args_h) }
84
- end
85
- elsif obj.respond_to?(assoc_name)
86
- args = arguments.respond_to?(:to_h) ? arguments.to_h : {}
87
- value = obj.public_send(assoc_name)
88
- value = resolver_instance.apply_where_filters(value, args)
89
- is_connection && value ? ::GraphQL::Pagination::ArrayConnection.new(value, context: ctx, parent: nil, field: nil, arguments: {}) : value
90
- else
91
- nil
92
- end
93
- end
94
- end
95
- end
96
-
97
- private
98
-
99
- def extract_relation_name
100
- # directive syntax: @hasMany(relation: "name")
101
- arg = @directive_node.arguments&.find { |a| a.name == 'relation' }
102
- return nil unless arg
103
- # value is AST literal node; use its value method if present
104
- arg.value.respond_to?(:value) ? arg.value.value : arg.value
105
- end
106
- end
107
- end
108
- end
109
- end
@@ -1,43 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module Lighthouse
6
- module GraphQL
7
- module DirectiveResolvers
8
- # @hasOne(relation: "name") — resolve a one-to-one association on the parent
9
- # object. Mirrors @belongsTo (single record) and batch-loads through the
10
- # AssociationLoader when a dataloader is available.
11
- class HasOneDirectiveResolver < BaseDirectiveResolver
12
- def self.directive_name = 'hasOne'
13
- def self.definition = 'directive @hasOne(relation: String, scopes: [String!]) on FIELD_DEFINITION'
14
-
15
- def define_resolver(target_type_class)
16
- field_name = @field_def.name
17
- assoc_name = directive_arg('relation') || field_name
18
- method_name = "resolve_field_#{field_name}"
19
-
20
- resolver = lambda do |obj, _arguments, ctx|
21
- next nil if obj.nil?
22
-
23
- if ctx && ctx.respond_to?(:dataloader) && ctx.dataloader
24
- loader = ctx.dataloader.with(Lighthouse::GraphQL::DataloaderSources::AssociationLoader, obj.class, assoc_name)
25
- loader.load(obj)
26
- elsif obj.respond_to?(assoc_name)
27
- obj.public_send(assoc_name)
28
- end
29
- end
30
-
31
- target_type_class.define_singleton_method(method_name, &resolver)
32
- @field_def.resolve_proc = resolver if @field_def.respond_to?(:resolve_proc=)
33
- end
34
-
35
- private
36
-
37
- def directive_arg(name)
38
- Lighthouse::Support::DirectiveArgs.literal(@directive_node, name)
39
- end
40
- end
41
- end
42
- end
43
- end