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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +175 -1
- data/README.md +47 -3
- data/docs/authorization.md +116 -57
- data/docs/best-practices.md +16 -3
- data/docs/caching.md +161 -0
- data/docs/configuration.md +83 -4
- data/docs/custom-directives.md +5 -1
- data/docs/directives.md +117 -38
- data/docs/getting-started.md +84 -0
- data/docs/motivation.md +184 -0
- data/docs/mutations.md +260 -0
- data/docs/performance.md +138 -0
- data/docs/relationships.md +80 -33
- data/docs/resolvers.md +189 -0
- data/docs/validation.md +132 -0
- data/lib/generators/lighthouse/builder_generator.rb +30 -0
- data/lib/generators/lighthouse/class_generator.rb +61 -0
- data/lib/generators/lighthouse/install/install_generator.rb +127 -0
- data/lib/generators/lighthouse/install/templates/graphql.config.yml.tt +8 -0
- data/lib/generators/lighthouse/install/templates/graphql_controller.rb.tt +57 -0
- data/lib/generators/lighthouse/install/templates/initializer.rb.tt +67 -0
- data/lib/generators/lighthouse/install/templates/schema.graphql.tt +19 -0
- data/lib/generators/lighthouse/install/templates/schema.rb.tt +10 -0
- data/lib/generators/lighthouse/mutation_generator.rb +30 -0
- data/lib/generators/lighthouse/query_generator.rb +29 -0
- data/lib/generators/lighthouse/validator_generator.rb +36 -0
- data/lib/lighthouse/cache_control.rb +126 -0
- data/lib/lighthouse/caching.rb +68 -0
- data/lib/lighthouse/config.rb +85 -19
- data/lib/lighthouse/contracts/arg_builder.rb +8 -12
- data/lib/lighthouse/contracts/arg_manipulator.rb +8 -12
- data/lib/lighthouse/contracts/directive.rb +10 -14
- data/lib/lighthouse/contracts/field_manipulator.rb +8 -12
- data/lib/lighthouse/contracts/field_middleware.rb +7 -11
- data/lib/lighthouse/contracts/field_resolver.rb +9 -13
- data/lib/lighthouse/dataloader_sources/association_loader.rb +28 -19
- data/lib/lighthouse/dataloader_sources/model_loader.rb +10 -14
- data/lib/lighthouse/dataloader_sources/relation_count_loader.rb +16 -0
- data/lib/lighthouse/dataloader_sources/relation_page_loader.rb +18 -0
- data/lib/lighthouse/directive_resolvers/aggregate_resolver.rb +57 -69
- data/lib/lighthouse/directive_resolvers/all_resolver.rb +26 -57
- data/lib/lighthouse/directive_resolvers/association_resolvers.rb +161 -0
- data/lib/lighthouse/directive_resolvers/auth_resolver.rb +41 -38
- data/lib/lighthouse/directive_resolvers/base.rb +142 -86
- data/lib/lighthouse/directive_resolvers/builder_applier.rb +58 -56
- data/lib/lighthouse/directive_resolvers/cache_resolvers.rb +133 -0
- data/lib/lighthouse/directive_resolvers/can_resolvers.rb +177 -0
- data/lib/lighthouse/directive_resolvers/convention_resolver.rb +70 -0
- data/lib/lighthouse/directive_resolvers/count_resolver.rb +42 -48
- data/lib/lighthouse/directive_resolvers/field_resolver.rb +27 -68
- data/lib/lighthouse/directive_resolvers/find_resolver.rb +42 -52
- data/lib/lighthouse/directive_resolvers/first_resolver.rb +39 -45
- data/lib/lighthouse/directive_resolvers/guard_resolver.rb +16 -22
- data/lib/lighthouse/directive_resolvers/method_resolver.rb +19 -25
- data/lib/lighthouse/directive_resolvers/model_mutation_resolver.rb +219 -0
- data/lib/lighthouse/directive_resolvers/paginate_resolver.rb +70 -128
- data/lib/lighthouse/directive_resolvers/rename_resolver.rb +18 -24
- data/lib/lighthouse/directive_resolvers/resolution.rb +31 -27
- data/lib/lighthouse/directive_resolvers/validator_resolver.rb +193 -0
- data/lib/lighthouse/directive_resolvers/where_conditions_applier.rb +164 -163
- data/lib/lighthouse/directives/arguments/base.rb +23 -31
- data/lib/lighthouse/directives/arguments/filters.rb +113 -93
- data/lib/lighthouse/directives/arguments/order_by.rb +41 -41
- data/lib/lighthouse/directives/pagination_info_types.rb +69 -0
- data/lib/lighthouse/directives/pagination_manipulator.rb +176 -0
- data/lib/lighthouse/directives/registry.rb +210 -141
- data/lib/lighthouse/directives/where_conditions_directive.rb +236 -200
- data/lib/lighthouse/errors.rb +27 -0
- data/lib/lighthouse/federation_directives.rb +53 -0
- data/lib/lighthouse/field_resolver_stack.rb +56 -0
- data/lib/lighthouse/generated_resolvers.rb +82 -0
- data/lib/lighthouse/graphql/version.rb +1 -1
- data/lib/lighthouse/graphql_ruby_patches.rb +18 -0
- data/lib/lighthouse/ide_helper.rb +98 -0
- data/lib/lighthouse/namespaces.rb +21 -0
- data/lib/lighthouse/nested_mutations/belongs_to_operations.rb +50 -0
- data/lib/lighthouse/nested_mutations/executor.rb +149 -0
- data/lib/lighthouse/nested_mutations/has_operations.rb +66 -0
- data/lib/lighthouse/nested_mutations/many_to_many_operations.rb +44 -0
- data/lib/lighthouse/nested_mutations/partitioner.rb +125 -0
- data/lib/lighthouse/nested_mutations.rb +210 -0
- data/lib/lighthouse/pagination.rb +221 -0
- data/lib/lighthouse/persisted_queries.rb +167 -0
- data/lib/lighthouse/railtie.rb +26 -0
- data/lib/lighthouse/rb_lighthouse.rb +50 -29
- data/lib/lighthouse/reference_resolver.rb +13 -15
- data/lib/lighthouse/relation_batch.rb +156 -0
- data/lib/lighthouse/resolver_dispatch.rb +26 -0
- data/lib/lighthouse/schema_cache.rb +120 -0
- data/lib/lighthouse/schema_factory.rb +27 -37
- data/lib/lighthouse/schema_generator.rb +196 -239
- data/lib/lighthouse/schema_implementation.rb +51 -48
- data/lib/lighthouse/sdl_loader.rb +17 -20
- data/lib/lighthouse/support/arguments.rb +119 -0
- data/lib/lighthouse/support/authorization.rb +18 -19
- data/lib/lighthouse/support/batching.rb +16 -0
- data/lib/lighthouse/support/directive_args.rb +26 -24
- data/lib/lighthouse/support/model_resolver.rb +56 -56
- data/lib/lighthouse/support/naming.rb +55 -59
- data/lib/lighthouse/tasks/lighthouse.rake +33 -0
- data/lib/lighthouse/where_conditions/operator_map.rb +25 -29
- data/sig/lighthouse/directives.rbs +158 -0
- data/sig/lighthouse/graphql.rbs +78 -0
- data/sig/lighthouse.rbs +142 -0
- metadata +56 -64
- data/lib/lighthouse/directive_resolvers/belongs_to_many_resolver.rb +0 -56
- data/lib/lighthouse/directive_resolvers/belongs_to_resolver.rb +0 -47
- data/lib/lighthouse/directive_resolvers/can_resolver.rb +0 -86
- data/lib/lighthouse/directive_resolvers/has_many_resolver.rb +0 -109
- data/lib/lighthouse/directive_resolvers/has_one_resolver.rb +0 -43
- 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
|
data/sig/lighthouse.rbs
ADDED
|
@@ -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.
|
|
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/
|
|
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.
|
|
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
|