lighthouse-graphql 0.1.1 → 0.2.1

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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +175 -1
  3. data/README.md +47 -3
  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/motivation.md +184 -0
  12. data/docs/mutations.md +260 -0
  13. data/docs/performance.md +138 -0
  14. data/docs/relationships.md +80 -33
  15. data/docs/resolvers.md +189 -0
  16. data/docs/validation.md +132 -0
  17. data/lib/generators/lighthouse/builder_generator.rb +30 -0
  18. data/lib/generators/lighthouse/class_generator.rb +61 -0
  19. data/lib/generators/lighthouse/install/install_generator.rb +127 -0
  20. data/lib/generators/lighthouse/install/templates/graphql.config.yml.tt +8 -0
  21. data/lib/generators/lighthouse/install/templates/graphql_controller.rb.tt +57 -0
  22. data/lib/generators/lighthouse/install/templates/initializer.rb.tt +67 -0
  23. data/lib/generators/lighthouse/install/templates/schema.graphql.tt +19 -0
  24. data/lib/generators/lighthouse/install/templates/schema.rb.tt +10 -0
  25. data/lib/generators/lighthouse/mutation_generator.rb +30 -0
  26. data/lib/generators/lighthouse/query_generator.rb +29 -0
  27. data/lib/generators/lighthouse/validator_generator.rb +36 -0
  28. data/lib/lighthouse/cache_control.rb +126 -0
  29. data/lib/lighthouse/caching.rb +68 -0
  30. data/lib/lighthouse/config.rb +85 -19
  31. data/lib/lighthouse/contracts/arg_builder.rb +8 -12
  32. data/lib/lighthouse/contracts/arg_manipulator.rb +8 -12
  33. data/lib/lighthouse/contracts/directive.rb +10 -14
  34. data/lib/lighthouse/contracts/field_manipulator.rb +8 -12
  35. data/lib/lighthouse/contracts/field_middleware.rb +7 -11
  36. data/lib/lighthouse/contracts/field_resolver.rb +9 -13
  37. data/lib/lighthouse/dataloader_sources/association_loader.rb +28 -19
  38. data/lib/lighthouse/dataloader_sources/model_loader.rb +10 -14
  39. data/lib/lighthouse/dataloader_sources/relation_count_loader.rb +16 -0
  40. data/lib/lighthouse/dataloader_sources/relation_page_loader.rb +18 -0
  41. data/lib/lighthouse/directive_resolvers/aggregate_resolver.rb +57 -69
  42. data/lib/lighthouse/directive_resolvers/all_resolver.rb +26 -57
  43. data/lib/lighthouse/directive_resolvers/association_resolvers.rb +161 -0
  44. data/lib/lighthouse/directive_resolvers/auth_resolver.rb +41 -38
  45. data/lib/lighthouse/directive_resolvers/base.rb +142 -86
  46. data/lib/lighthouse/directive_resolvers/builder_applier.rb +58 -56
  47. data/lib/lighthouse/directive_resolvers/cache_resolvers.rb +133 -0
  48. data/lib/lighthouse/directive_resolvers/can_resolvers.rb +177 -0
  49. data/lib/lighthouse/directive_resolvers/convention_resolver.rb +70 -0
  50. data/lib/lighthouse/directive_resolvers/count_resolver.rb +42 -48
  51. data/lib/lighthouse/directive_resolvers/field_resolver.rb +27 -68
  52. data/lib/lighthouse/directive_resolvers/find_resolver.rb +42 -52
  53. data/lib/lighthouse/directive_resolvers/first_resolver.rb +39 -45
  54. data/lib/lighthouse/directive_resolvers/guard_resolver.rb +16 -22
  55. data/lib/lighthouse/directive_resolvers/method_resolver.rb +19 -25
  56. data/lib/lighthouse/directive_resolvers/model_mutation_resolver.rb +219 -0
  57. data/lib/lighthouse/directive_resolvers/paginate_resolver.rb +70 -128
  58. data/lib/lighthouse/directive_resolvers/rename_resolver.rb +18 -24
  59. data/lib/lighthouse/directive_resolvers/resolution.rb +31 -27
  60. data/lib/lighthouse/directive_resolvers/validator_resolver.rb +193 -0
  61. data/lib/lighthouse/directive_resolvers/where_conditions_applier.rb +164 -163
  62. data/lib/lighthouse/directives/arguments/base.rb +23 -31
  63. data/lib/lighthouse/directives/arguments/filters.rb +113 -93
  64. data/lib/lighthouse/directives/arguments/order_by.rb +41 -41
  65. data/lib/lighthouse/directives/pagination_info_types.rb +69 -0
  66. data/lib/lighthouse/directives/pagination_manipulator.rb +176 -0
  67. data/lib/lighthouse/directives/registry.rb +210 -141
  68. data/lib/lighthouse/directives/where_conditions_directive.rb +236 -200
  69. data/lib/lighthouse/errors.rb +27 -0
  70. data/lib/lighthouse/federation_directives.rb +53 -0
  71. data/lib/lighthouse/field_resolver_stack.rb +56 -0
  72. data/lib/lighthouse/generated_resolvers.rb +82 -0
  73. data/lib/lighthouse/graphql/version.rb +1 -1
  74. data/lib/lighthouse/graphql_ruby_patches.rb +18 -0
  75. data/lib/lighthouse/ide_helper.rb +98 -0
  76. data/lib/lighthouse/namespaces.rb +21 -0
  77. data/lib/lighthouse/nested_mutations/belongs_to_operations.rb +50 -0
  78. data/lib/lighthouse/nested_mutations/executor.rb +149 -0
  79. data/lib/lighthouse/nested_mutations/has_operations.rb +66 -0
  80. data/lib/lighthouse/nested_mutations/many_to_many_operations.rb +44 -0
  81. data/lib/lighthouse/nested_mutations/partitioner.rb +125 -0
  82. data/lib/lighthouse/nested_mutations.rb +210 -0
  83. data/lib/lighthouse/pagination.rb +221 -0
  84. data/lib/lighthouse/persisted_queries.rb +167 -0
  85. data/lib/lighthouse/railtie.rb +26 -0
  86. data/lib/lighthouse/rb_lighthouse.rb +50 -29
  87. data/lib/lighthouse/reference_resolver.rb +13 -15
  88. data/lib/lighthouse/relation_batch.rb +156 -0
  89. data/lib/lighthouse/resolver_dispatch.rb +26 -0
  90. data/lib/lighthouse/schema_cache.rb +120 -0
  91. data/lib/lighthouse/schema_factory.rb +27 -37
  92. data/lib/lighthouse/schema_generator.rb +196 -239
  93. data/lib/lighthouse/schema_implementation.rb +51 -48
  94. data/lib/lighthouse/sdl_loader.rb +17 -20
  95. data/lib/lighthouse/support/arguments.rb +119 -0
  96. data/lib/lighthouse/support/authorization.rb +18 -19
  97. data/lib/lighthouse/support/batching.rb +16 -0
  98. data/lib/lighthouse/support/directive_args.rb +26 -24
  99. data/lib/lighthouse/support/model_resolver.rb +56 -56
  100. data/lib/lighthouse/support/naming.rb +55 -59
  101. data/lib/lighthouse/tasks/lighthouse.rake +33 -0
  102. data/lib/lighthouse/where_conditions/operator_map.rb +25 -29
  103. data/sig/lighthouse/directives.rbs +158 -0
  104. data/sig/lighthouse/graphql.rbs +78 -0
  105. data/sig/lighthouse.rbs +142 -0
  106. metadata +56 -64
  107. data/lib/lighthouse/directive_resolvers/belongs_to_many_resolver.rb +0 -56
  108. data/lib/lighthouse/directive_resolvers/belongs_to_resolver.rb +0 -47
  109. data/lib/lighthouse/directive_resolvers/can_resolver.rb +0 -86
  110. data/lib/lighthouse/directive_resolvers/has_many_resolver.rb +0 -109
  111. data/lib/lighthouse/directive_resolvers/has_one_resolver.rb +0 -43
  112. data/lib/lighthouse/directives/relation_directive.rb +0 -332
@@ -0,0 +1,158 @@
1
+ # The extension points for custom directives: the contracts a directive class
2
+ # includes, the registry it is registered in, and the base classes it can
3
+ # subclass. See docs/custom-directives.md.
4
+ module Lighthouse
5
+ # What the registry asks a self-describing directive class: its SDL name
6
+ # (without the @) and its `directive @name(...) on ...` definition.
7
+ interface _DirectiveClass
8
+ def directive_name: () -> String
9
+ def definition: () -> String?
10
+ end
11
+
12
+ # Marker modules: the registry detects a class's capabilities by which of
13
+ # them it includes. Only FieldResolver and ArgBuilder change how a class is
14
+ # registered; the others document intent.
15
+ module Contracts
16
+ module Directive
17
+ end
18
+
19
+ # Its instances, built with (field_def, type_def, directive_node, opts),
20
+ # install the field's resolver in `define_resolver(target_type)`.
21
+ module FieldResolver
22
+ include Directive
23
+ end
24
+
25
+ # Its instances, built with (arg_node, directive_node), answer
26
+ # `handle_builder(relation, value)` with the constrained relation.
27
+ module ArgBuilder
28
+ include Directive
29
+ end
30
+
31
+ module FieldMiddleware
32
+ include Directive
33
+ end
34
+
35
+ module FieldManipulator
36
+ include Directive
37
+ end
38
+
39
+ module ArgManipulator
40
+ include Directive
41
+ end
42
+ end
43
+
44
+ class DirectiveRegistry
45
+ RESOLUTION_ORDER: Hash[String, Integer]
46
+ NAMED_RESOLVERS: Hash[String, Symbol]
47
+ SELF_DESCRIBING_RESOLVERS: Array[Symbol]
48
+ ARG_BUILDERS: Array[Symbol]
49
+ PASSIVE_DEFINITIONS: Hash[String, String]
50
+
51
+ def self.default: () -> DirectiveRegistry
52
+
53
+ # register(MyDirective) when the class answers `directive_name`, else
54
+ # register('name', MyDirective).
55
+ def self.register: (Class | String | Symbol name_or_klass, ?Class? klass) -> DirectiveRegistry
56
+
57
+ def initialize: () -> void
58
+ def register: (Class | String | Symbol name_or_klass, ?Class? klass) -> self
59
+ def register_defaults: () -> self
60
+ def register_definition: (String | Symbol name, String definition) -> self
61
+ def register_type_definition: (String | Symbol name, String definition) -> self
62
+ def register_manipulator: (_SdlManipulator manipulator) -> self
63
+
64
+ def resolution_class: (String | Symbol name) -> Class?
65
+ def resolution_order: (String | Symbol name) -> Integer
66
+ def wrapper?: (String | Symbol name) -> bool
67
+ def resolution_names: () -> Array[String]
68
+ def arg_builder_class: (String | Symbol name) -> Class?
69
+ def arg_builder_names: () -> Array[String]
70
+
71
+ # { "name" => "directive @name(...) on ..." }
72
+ def directive_definitions: () -> Hash[String, String]
73
+ # { "Name" => "enum Name { ... }" }
74
+ def type_definitions: () -> Hash[String, String]
75
+
76
+ attr_reader sdl_manipulators: Array[_SdlManipulator]
77
+ def manipulate_sdl: (String sdl) -> String
78
+ end
79
+
80
+ # Writes the SDL an IDE needs next to the app's own: `bin/rails lighthouse:ide_helper`.
81
+ module IdeHelper
82
+ DIRECTIVES_FILE: String
83
+ PROGRAMMATIC_TYPES_FILE: String
84
+
85
+ # Writes both files into `output_dir` and returns their paths.
86
+ def self?.write: (output_dir: path, ?sdl_folder: path?, ?registry: DirectiveRegistry) -> Array[String]
87
+ def self?.directives_sdl: (?String sdl, ?registry: DirectiveRegistry) -> String
88
+ def self?.programmatic_types_sdl: (String sdl, ?registry: DirectiveRegistry) -> String
89
+ end
90
+
91
+ module GraphQL
92
+ module DirectiveResolvers
93
+ # The base of the built-in field directives, and of a custom one:
94
+ # subclass it and implement `define_resolver`.
95
+ class BaseDirectiveResolver
96
+ # graphql-ruby's field and type definitions, and the directive's AST node.
97
+ @field_def: untyped
98
+ @type_def: untyped
99
+ @directive_node: untyped
100
+ @opts: Hash[Symbol, untyped]
101
+
102
+ def initialize: (untyped field_def, untyped type_def, untyped directive_node, ?Hash[Symbol, untyped] opts) -> void
103
+
104
+ # Install the field's resolver on `target_type_class` (a graphql-ruby type class).
105
+ def define_resolver: (untyped target_type_class) -> untyped
106
+
107
+ def apply_where_filters: (relation relation, untyped args) -> relation
108
+ def apply_arg_builders: (relation relation, arguments args_h) -> relation
109
+ def extract_relation_name_from_directive: (untyped arg_node) -> String?
110
+ def constantize_model: (String? name) -> Class?
111
+ def apply_scopes: (relation relation) -> relation
112
+
113
+ # The literal value of an argument of this directive.
114
+ def directive_arg: (String name) -> untyped
115
+ def resolver_method_name: () -> String
116
+ # The field's resolver so far, for a directive that wraps it.
117
+ def capture_inner: (untyped target_type_class) -> untyped
118
+ def install: (untyped target_type_class, untyped callable) -> untyped
119
+ # The model the directive acts on; raises DefinitionError when there is none.
120
+ def model_class: () -> Class
121
+ end
122
+
123
+ # Applies the field's @builder directives, in SDL order, to its relation.
124
+ class BuilderApplier
125
+ DEFINITION: String
126
+
127
+ def self.apply: (relation relation, untyped field_def_ast_node, arguments args, context ctx, untyped resolver_instance) -> relation
128
+ def self.apply_directive: (relation relation, untyped directive_node, arguments args, context ctx, untyped resolver_instance) -> relation
129
+ def self.extract_directive_arg: (untyped directive_node, String name) -> untyped
130
+ end
131
+ end
132
+
133
+ module Directives
134
+ module Arguments
135
+ # The base of the argument filters (@eq, @in, @orderBy, ...), and of a
136
+ # custom one: subclass it and implement `handle_builder`.
137
+ class Base
138
+ include Contracts::ArgBuilder
139
+
140
+ # graphql-ruby's AST nodes for the argument and the directive on it.
141
+ @arg_node: untyped
142
+ @directive_node: untyped
143
+
144
+ def initialize: (untyped arg_node, untyped directive_node) -> void
145
+
146
+ # Constrain the relation by the value the client gave the argument.
147
+ def handle_builder: (relation relation, untyped value) -> relation
148
+
149
+ private
150
+
151
+ # The directive's `key:`, else the argument's name in snake_case.
152
+ def column: () -> String
153
+ def arel_column: (relation relation) -> untyped
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,78 @@
1
+ # The entrypoints: building the schema from SDL and running operations.
2
+ module Lighthouse
3
+ module GraphQL
4
+ VERSION: String
5
+
6
+ Config: singleton(Lighthouse::Config)
7
+
8
+ # A GraphQL::Schema subclass.
9
+ type schema = untyped
10
+
11
+ module RbLightHouse
12
+ # The schema built from the SDL in `sdl_folder` (default: Config.sdl_folder).
13
+ # `options` takes :base_types, :base_schema and the schema's own options.
14
+ def self.get_schema: (?sdl_folder: path?, ?options: Hash[Symbol, untyped]) -> schema
15
+ def self.configure: () ?{ (singleton(Lighthouse::Config) config) -> void } -> void
16
+ end
17
+
18
+ module SchemaFactory
19
+ def self?.build_base_schema: (?sdl_folder: path?, ?sdl: String?, ?base_types: Hash[untyped, untyped],
20
+ ?schema_options: Hash[Symbol, untyped], **untyped extra_options) -> schema
21
+ def self?.load_sdl: (path? sdl_folder) -> String
22
+ end
23
+
24
+ # Apollo's Automatic Persisted Queries, and a manifest of trusted operations.
25
+ module PersistedQueries
26
+ HASH: Regexp
27
+ NOT_FOUND: Array[String]
28
+ NOT_SUPPORTED: Array[String]
29
+ HASH_MISMATCH: Array[String]
30
+ NOT_IN_LIST: Array[String]
31
+
32
+ # A request the protocol rejects, rendered with Apollo's error codes.
33
+ class Error < StandardError
34
+ attr_reader code: String
35
+
36
+ def initialize: (String message, String code) -> void
37
+ def to_h: () -> Hash[String, untyped]
38
+ end
39
+
40
+ # `extensions` as the request carries it: a Hash, a JSON String (GET) or
41
+ # ActionController::Parameters.
42
+ #
43
+ # `schema.execute` with the query the request names: its result, or a
44
+ # protocol error as a ready-to-render { "errors" => [...] } Hash.
45
+ def self?.execute: (schema schema, query: String?, ?extensions: untyped, **untyped options) -> untyped
46
+ # The query text to run for a request's `query` and `extensions`.
47
+ def self?.resolve: (String? query, untyped extensions) -> String?
48
+ def self?.enabled?: () -> bool
49
+ def self?.digest: (String query) -> String
50
+ # Store a query ahead of time (e.g. from a deploy task); returns its hash.
51
+ def self?.register: (String query) -> String
52
+ end
53
+
54
+ # The Cache-Control header the selected fields' @cacheControl hints allow.
55
+ module CacheControl
56
+ DEFINITION: String
57
+ TYPE_DEFINITIONS: Hash[String, String]
58
+ CONTEXT_KEY: Symbol
59
+
60
+ # For an executed query (a GraphQL::Query::Result or GraphQL::Query);
61
+ # nil when the schema does not use @cacheControl.
62
+ def self?.header: (untyped result) -> String?
63
+ # Set the header on a Rails (or Rack) response, and return it.
64
+ def self?.apply: (untyped response, untyped result) -> String?
65
+ end
66
+
67
+ # The opt-in cache of the manipulated schema document, in tmp/cache.
68
+ module SchemaCache
69
+ PREFIX: String
70
+
71
+ def self?.enabled?: () -> bool
72
+ def self?.directory: () -> path
73
+ # Build the schema document now and return the cache file's path.
74
+ def self?.warm!: (?String? sdl) -> String
75
+ def self?.clear!: () -> void
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,142 @@
1
+ # Signatures for the parts of Lighthouse an application implements or calls:
2
+ # the classes a schema names (builders, validators), the configuration, the
3
+ # directive extension points and the entrypoints. Internals are left out.
4
+ #
5
+ # graphql-ruby and Active Record ship no RBS every app has, so the values that
6
+ # come from them are aliases of untyped, named for what they hold.
7
+ module Lighthouse
8
+ # An ActiveRecord::Relation, or anything with its query interface.
9
+ type relation = untyped
10
+
11
+ # A field's arguments, with snake_case Symbol keys as graphql-ruby passes them.
12
+ type arguments = Hash[Symbol, untyped]
13
+
14
+ # The request's GraphQL::Query::Context.
15
+ type context = untyped
16
+
17
+ # A path on disk: a String or a Pathname.
18
+ type path = String | _ToPath
19
+
20
+ # A class `@builder(class: "Name")` names, looked up in Config.namespaces[:builders].
21
+ # It refines the relation of a field resolved by @all, @paginate, @first,
22
+ # @count or @aggregate and returns the relation to use; nil keeps the one it
23
+ # was given. `@builder(method:)` names a method other than `call`, with the
24
+ # same signature. The class answers it, or else an instance built with no
25
+ # arguments does. A GraphQL::ExecutionError it raises reaches the client.
26
+ interface _Builder
27
+ def call: (relation relation, arguments args, context context) -> relation?
28
+ end
29
+
30
+ # A @validator contract other than a Dry::Validation::Contract: it gets the
31
+ # arguments (snake_case Symbol keys) and answers the errors by key,
32
+ # { title: ["is missing"] }, nested for input objects; empty when valid.
33
+ interface _Validator
34
+ def call: (Hash[Symbol, untyped] values) -> Hash[Symbol | String, untyped]
35
+ end
36
+
37
+ # Config.on_error: called with an error a directive or resolver swallowed.
38
+ interface _ErrorHandler
39
+ def call: (StandardError error, context? context) -> void
40
+ end
41
+
42
+ # Config.authenticated_user and Config.policy_user: the user of a request.
43
+ interface _UserReader
44
+ def call: (context? context) -> untyped
45
+ end
46
+
47
+ # Config.authorizer: may `user` perform `ability` on `record` (a model
48
+ # instance, or a model class for @canModel)? `args` are the @can* `args:`,
49
+ # after the field's arguments with `injectArgs: true`.
50
+ interface _Authorizer
51
+ def call: (untyped user, untyped record, String | Symbol ability, ?Array[untyped] args) -> boolish
52
+ end
53
+
54
+ # What DirectiveRegistry#register_manipulator takes: it transforms the SDL
55
+ # before the schema is built.
56
+ interface _SdlManipulator
57
+ def manipulate: (String sdl) -> String
58
+ end
59
+
60
+ def self.configure: () ?{ (singleton(Config) config) -> void } -> void
61
+
62
+ module Config
63
+ DEFAULT_NAMESPACES: Hash[Symbol, Array[String]]
64
+ SETTINGS: Array[Symbol]
65
+
66
+ def self.configure: () ?{ (singleton(Config) config) -> void } -> void
67
+ def self.[]: (Symbol | String key) -> untyped
68
+ def self.reset!: () -> void
69
+
70
+ def self.sdl_folder: () -> path?
71
+ def self.sdl_folder=: (path? folder) -> path?
72
+
73
+ # { queries:, mutations:, builders:, validators: } => [namespace, ...].
74
+ # Assigning a partial hash overrides only the kinds it names.
75
+ def self.namespaces: () -> Hash[Symbol, Array[String]]
76
+ def self.namespaces=: (Hash[Symbol | String, String | Array[String]] overrides) -> Hash[Symbol | String, String | Array[String]]
77
+
78
+ def self.resolver_namespaces: () -> Array[String]
79
+ def self.resolver_namespaces=: (Array[String] namespaces) -> Array[String]
80
+
81
+ def self.directive_map: () -> Hash[untyped, untyped]
82
+
83
+ # An ActiveSupport::Cache::Store; Rails.cache by default.
84
+ def self.cache_store: () -> untyped
85
+ def self.cache_store=: (untyped store) -> untyped
86
+
87
+ def self.transactional_mutations: () -> bool
88
+ def self.transactional_mutations=: (bool? enabled) -> bool?
89
+
90
+ def self.pagination_default_count: () -> Integer?
91
+ def self.pagination_default_count=: (Integer? count) -> Integer?
92
+ def self.pagination_max_count: () -> Integer?
93
+ def self.pagination_max_count=: (Integer? count) -> Integer?
94
+
95
+ def self.schema_cache: () -> bool
96
+ def self.schema_cache=: (bool? enabled) -> bool?
97
+ def self.schema_cache_path: () -> path?
98
+ def self.schema_cache_path=: (path? path) -> path?
99
+ def self.watch_sdl: () -> bool
100
+ def self.watch_sdl=: (bool? enabled) -> bool?
101
+
102
+ def self.persisted_queries: () -> bool
103
+ def self.persisted_queries=: (bool? enabled) -> bool?
104
+ def self.persisted_queries_store: () -> untyped
105
+ def self.persisted_queries_store=: (untyped store) -> untyped
106
+ def self.persisted_queries_ttl: () -> Numeric?
107
+ def self.persisted_queries_ttl=: (Numeric? seconds) -> Numeric?
108
+ def self.persisted_queries_manifest: () -> path?
109
+ def self.persisted_queries_manifest=: (path? path) -> path?
110
+ def self.persisted_queries_only: () -> bool
111
+ def self.persisted_queries_only=: (bool? enabled) -> bool?
112
+
113
+ def self.on_error: () -> _ErrorHandler
114
+ def self.on_error=: (_ErrorHandler? handler) -> _ErrorHandler?
115
+ def self.handle_error: (StandardError error, ?context? context) -> void
116
+
117
+ def self.authenticated_user: () -> _UserReader
118
+ def self.authenticated_user=: (_UserReader? reader) -> _UserReader?
119
+ def self.policy_user: () -> _UserReader
120
+ def self.policy_user=: (_UserReader? reader) -> _UserReader?
121
+ def self.authorizer: () -> _Authorizer
122
+ def self.authorizer=: (_Authorizer? authorizer) -> _Authorizer?
123
+ end
124
+
125
+ # The schema refers to something that does not exist or breaks a contract.
126
+ class DefinitionError < StandardError
127
+ end
128
+
129
+ # A GraphQL::ExecutionError (declared from StandardError, which it descends
130
+ # from, as graphql-ruby ships no RBS): the @can* family denied the ability.
131
+ class AuthorizationError < StandardError
132
+ def initialize: (?String message, **untyped options) -> void
133
+ end
134
+
135
+ # A GraphQL::ExecutionError: invalid arguments, keyed by argument path
136
+ # ({ "input.title" => ["Title can't be blank"] }) under extensions.validation.
137
+ class ValidationError < StandardError
138
+ attr_reader messages: Hash[String, Array[String]]
139
+
140
+ def initialize: (String | Symbol field_name, Hash[String, Array[String]] messages) -> void
141
+ end
142
+ end
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.1
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,33 @@ 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/motivation.md
66
+ - docs/mutations.md
67
+ - docs/performance.md
120
68
  - docs/relationships.md
69
+ - docs/resolvers.md
70
+ - docs/validation.md
71
+ - lib/generators/lighthouse/builder_generator.rb
72
+ - lib/generators/lighthouse/class_generator.rb
73
+ - lib/generators/lighthouse/install/install_generator.rb
74
+ - lib/generators/lighthouse/install/templates/graphql.config.yml.tt
75
+ - lib/generators/lighthouse/install/templates/graphql_controller.rb.tt
76
+ - lib/generators/lighthouse/install/templates/initializer.rb.tt
77
+ - lib/generators/lighthouse/install/templates/schema.graphql.tt
78
+ - lib/generators/lighthouse/install/templates/schema.rb.tt
79
+ - lib/generators/lighthouse/mutation_generator.rb
80
+ - lib/generators/lighthouse/query_generator.rb
81
+ - lib/generators/lighthouse/validator_generator.rb
121
82
  - lib/lighthouse-graphql.rb
83
+ - lib/lighthouse/cache_control.rb
84
+ - lib/lighthouse/caching.rb
122
85
  - lib/lighthouse/config.rb
123
86
  - lib/lighthouse/contracts/arg_builder.rb
124
87
  - lib/lighthouse/contracts/arg_manipulator.rb
@@ -128,52 +91,81 @@ files:
128
91
  - lib/lighthouse/contracts/field_resolver.rb
129
92
  - lib/lighthouse/dataloader_sources/association_loader.rb
130
93
  - lib/lighthouse/dataloader_sources/model_loader.rb
94
+ - lib/lighthouse/dataloader_sources/relation_count_loader.rb
95
+ - lib/lighthouse/dataloader_sources/relation_page_loader.rb
131
96
  - lib/lighthouse/directive_resolvers/aggregate_resolver.rb
132
97
  - lib/lighthouse/directive_resolvers/all_resolver.rb
98
+ - lib/lighthouse/directive_resolvers/association_resolvers.rb
133
99
  - lib/lighthouse/directive_resolvers/auth_resolver.rb
134
100
  - 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
101
  - lib/lighthouse/directive_resolvers/builder_applier.rb
138
- - lib/lighthouse/directive_resolvers/can_resolver.rb
102
+ - lib/lighthouse/directive_resolvers/cache_resolvers.rb
103
+ - lib/lighthouse/directive_resolvers/can_resolvers.rb
104
+ - lib/lighthouse/directive_resolvers/convention_resolver.rb
139
105
  - lib/lighthouse/directive_resolvers/count_resolver.rb
140
106
  - lib/lighthouse/directive_resolvers/field_resolver.rb
141
107
  - lib/lighthouse/directive_resolvers/find_resolver.rb
142
108
  - lib/lighthouse/directive_resolvers/first_resolver.rb
143
109
  - 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
110
  - lib/lighthouse/directive_resolvers/method_resolver.rb
111
+ - lib/lighthouse/directive_resolvers/model_mutation_resolver.rb
147
112
  - lib/lighthouse/directive_resolvers/paginate_resolver.rb
148
113
  - lib/lighthouse/directive_resolvers/rename_resolver.rb
149
114
  - lib/lighthouse/directive_resolvers/resolution.rb
115
+ - lib/lighthouse/directive_resolvers/validator_resolver.rb
150
116
  - lib/lighthouse/directive_resolvers/where_conditions_applier.rb
151
117
  - lib/lighthouse/directives/arguments/base.rb
152
118
  - lib/lighthouse/directives/arguments/filters.rb
153
119
  - lib/lighthouse/directives/arguments/order_by.rb
120
+ - lib/lighthouse/directives/pagination_info_types.rb
121
+ - lib/lighthouse/directives/pagination_manipulator.rb
154
122
  - lib/lighthouse/directives/registry.rb
155
- - lib/lighthouse/directives/relation_directive.rb
156
123
  - lib/lighthouse/directives/where_conditions_directive.rb
124
+ - lib/lighthouse/errors.rb
125
+ - lib/lighthouse/federation_directives.rb
126
+ - lib/lighthouse/field_resolver_stack.rb
127
+ - lib/lighthouse/generated_resolvers.rb
157
128
  - lib/lighthouse/graphql.rb
158
129
  - lib/lighthouse/graphql/version.rb
130
+ - lib/lighthouse/graphql_ruby_patches.rb
131
+ - lib/lighthouse/ide_helper.rb
132
+ - lib/lighthouse/namespaces.rb
133
+ - lib/lighthouse/nested_mutations.rb
134
+ - lib/lighthouse/nested_mutations/belongs_to_operations.rb
135
+ - lib/lighthouse/nested_mutations/executor.rb
136
+ - lib/lighthouse/nested_mutations/has_operations.rb
137
+ - lib/lighthouse/nested_mutations/many_to_many_operations.rb
138
+ - lib/lighthouse/nested_mutations/partitioner.rb
139
+ - lib/lighthouse/pagination.rb
140
+ - lib/lighthouse/persisted_queries.rb
141
+ - lib/lighthouse/railtie.rb
159
142
  - lib/lighthouse/rb_lighthouse.rb
160
143
  - lib/lighthouse/reference_resolver.rb
144
+ - lib/lighthouse/relation_batch.rb
145
+ - lib/lighthouse/resolver_dispatch.rb
146
+ - lib/lighthouse/schema_cache.rb
161
147
  - lib/lighthouse/schema_factory.rb
162
148
  - lib/lighthouse/schema_generator.rb
163
149
  - lib/lighthouse/schema_implementation.rb
164
150
  - lib/lighthouse/sdl_loader.rb
151
+ - lib/lighthouse/support/arguments.rb
165
152
  - lib/lighthouse/support/authorization.rb
153
+ - lib/lighthouse/support/batching.rb
166
154
  - lib/lighthouse/support/directive_args.rb
167
155
  - lib/lighthouse/support/model_resolver.rb
168
156
  - lib/lighthouse/support/naming.rb
157
+ - lib/lighthouse/tasks/lighthouse.rake
169
158
  - lib/lighthouse/where_conditions/operator_map.rb
159
+ - sig/lighthouse.rbs
160
+ - sig/lighthouse/directives.rbs
161
+ - sig/lighthouse/graphql.rbs
170
162
  homepage: https://github.com/Vaz-Innovation/lighthouse-graphql
171
163
  licenses:
172
164
  - MIT
173
165
  metadata:
174
166
  source_code_uri: https://github.com/Vaz-Innovation/lighthouse-graphql
175
167
  changelog_uri: https://github.com/Vaz-Innovation/lighthouse-graphql/blob/main/CHANGELOG.md
176
- documentation_uri: https://github.com/Vaz-Innovation/lighthouse-graphql/tree/main/docs
168
+ documentation_uri: https://vaz-innovation.github.io/lighthouse-graphql/
177
169
  rubygems_mfa_required: 'true'
178
170
  rdoc_options: []
179
171
  require_paths:
@@ -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