graphql_rails 1.2.4 → 2.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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +18 -0
- data/.hound.yml +1 -1
- data/.rubocop.yml +4 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +21 -0
- data/Gemfile +3 -3
- data/Gemfile.lock +129 -128
- data/docs/README.md +1 -1
- data/docs/components/model.md +107 -13
- data/docs/components/routes.md +4 -3
- data/docs/other_tools/schema_dump.md +8 -8
- data/lib/graphql_rails/attributes/attributable.rb +6 -14
- data/lib/graphql_rails/attributes/attribute.rb +10 -34
- data/lib/graphql_rails/attributes/attribute_configurable.rb +45 -0
- data/lib/graphql_rails/attributes/attribute_name_parser.rb +7 -7
- data/lib/graphql_rails/attributes/input_attribute.rb +20 -14
- data/lib/graphql_rails/attributes/input_type_parser.rb +5 -7
- data/lib/graphql_rails/attributes/type_parseable.rb +49 -19
- data/lib/graphql_rails/attributes/type_parser.rb +4 -9
- data/lib/graphql_rails/concerns/chainable_options.rb +49 -0
- data/lib/graphql_rails/controller/build_controller_action_resolver/controller_action_resolver.rb +3 -0
- data/lib/graphql_rails/controller/log_controller_action.rb +7 -2
- data/lib/graphql_rails/decorator/relation_decorator.rb +2 -2
- data/lib/graphql_rails/input_configurable.rb +11 -9
- data/lib/graphql_rails/model/build_graphql_input_type.rb +4 -2
- data/lib/graphql_rails/model/configurable.rb +30 -8
- data/lib/graphql_rails/model/configuration.rb +8 -12
- data/lib/graphql_rails/model/find_or_build_graphql_type.rb +16 -19
- data/lib/graphql_rails/model/find_or_build_graphql_type_class.rb +2 -1
- data/lib/graphql_rails/model/input.rb +10 -26
- data/lib/graphql_rails/query_runner.rb +9 -3
- data/lib/graphql_rails/router/mutation_route.rb +4 -0
- data/lib/graphql_rails/router/query_route.rb +4 -0
- data/lib/graphql_rails/router/resource_routes_builder.rb +8 -0
- data/lib/graphql_rails/router/route.rb +2 -2
- data/lib/graphql_rails/router/schema_builder.rb +12 -3
- data/lib/graphql_rails/router/subscription_route.rb +22 -0
- data/lib/graphql_rails/router.rb +8 -2
- data/lib/graphql_rails/tasks/dump_graphql_schema.rb +18 -27
- data/lib/graphql_rails/tasks/dump_graphql_schemas.rb +57 -0
- data/lib/graphql_rails/tasks/schema.rake +8 -5
- data/lib/graphql_rails/types/argument_type.rb +12 -0
- data/lib/graphql_rails/types/field_type.rb +14 -0
- data/lib/graphql_rails/types/hidable_by_group.rb +32 -0
- data/lib/graphql_rails/types/object_type.rb +12 -0
- data/lib/graphql_rails/version.rb +1 -1
- metadata +16 -8
- data/.travis.yml +0 -5
@@ -2,25 +2,47 @@
|
|
2
2
|
|
3
3
|
module GraphqlRails
|
4
4
|
module Model
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# Contains methods which are shared between various configurations.
|
6
|
+
#
|
7
|
+
# Expects `default_name` to be defined.
|
8
|
+
# Expects `build_attribute(attr_name)` method to be defined.
|
7
9
|
module Configurable
|
10
|
+
require 'active_support/concern'
|
11
|
+
require 'graphql_rails/concerns/chainable_options'
|
12
|
+
|
13
|
+
extend ActiveSupport::Concern
|
14
|
+
|
15
|
+
included do
|
16
|
+
include GraphqlRails::ChainableOptions
|
17
|
+
|
18
|
+
chainable_option :description
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize_copy(other)
|
22
|
+
super
|
23
|
+
@type_name = nil
|
24
|
+
@attributes = other.attributes.transform_values(&:dup)
|
25
|
+
end
|
26
|
+
|
8
27
|
def attributes
|
9
28
|
@attributes ||= {}
|
10
29
|
end
|
11
30
|
|
12
|
-
def name(
|
13
|
-
|
14
|
-
@name || default_name
|
31
|
+
def name(*args)
|
32
|
+
get_or_set_chainable_option(:name, *args) || default_name
|
15
33
|
end
|
16
34
|
|
17
35
|
def type_name
|
18
36
|
@type_name ||= "#{name.camelize}Type#{SecureRandom.hex}"
|
19
37
|
end
|
20
38
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
39
|
+
def attribute(attribute_name, **attribute_options)
|
40
|
+
key = attribute_name.to_s
|
41
|
+
|
42
|
+
attributes[key] ||= build_attribute(attribute_name).tap do |new_attribute|
|
43
|
+
new_attribute.with(**attribute_options) unless attribute_options.empty?
|
44
|
+
yield(new_attribute) if block_given?
|
45
|
+
end
|
24
46
|
end
|
25
47
|
end
|
26
48
|
end
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require 'graphql_rails/attributes'
|
4
4
|
require 'graphql_rails/model/find_or_build_graphql_type'
|
5
|
-
require 'graphql_rails/model/build_enum_type'
|
6
5
|
require 'graphql_rails/model/input'
|
7
6
|
require 'graphql_rails/model/configurable'
|
8
7
|
require 'graphql_rails/model/build_connection_type'
|
@@ -11,6 +10,7 @@ module GraphqlRails
|
|
11
10
|
module Model
|
12
11
|
# stores information about model specific config, like attributes and types
|
13
12
|
class Configuration
|
13
|
+
include ChainableOptions
|
14
14
|
include Configurable
|
15
15
|
|
16
16
|
def initialize(model_class)
|
@@ -22,22 +22,14 @@ module GraphqlRails
|
|
22
22
|
@connection_type = nil
|
23
23
|
@graphql_type = nil
|
24
24
|
@input = other.instance_variable_get(:@input)&.transform_values(&:dup)
|
25
|
-
@attributes = other.instance_variable_get(:@attributes)&.transform_values(&:dup)
|
26
25
|
end
|
27
26
|
|
28
27
|
def attribute(attribute_name, **attribute_options)
|
29
28
|
key = attribute_name.to_s
|
30
29
|
|
31
|
-
attributes[key] ||=
|
32
|
-
|
33
|
-
|
34
|
-
attribute_options.each do |method_name, args|
|
35
|
-
send_args = [method_name]
|
36
|
-
send_args << args if attribute.method(method_name).parameters.present?
|
37
|
-
attribute.public_send(*send_args)
|
38
|
-
end
|
39
|
-
|
40
|
-
yield(attribute) if block_given?
|
30
|
+
attributes[key] ||= build_attribute(attribute_name).tap do |new_attribute|
|
31
|
+
new_attribute.with(**attribute_options)
|
32
|
+
yield(new_attribute) if block_given?
|
41
33
|
end
|
42
34
|
end
|
43
35
|
|
@@ -80,6 +72,10 @@ module GraphqlRails
|
|
80
72
|
|
81
73
|
attr_reader :model_class
|
82
74
|
|
75
|
+
def build_attribute(attribute_name)
|
76
|
+
Attributes::Attribute.new(attribute_name)
|
77
|
+
end
|
78
|
+
|
83
79
|
def default_name
|
84
80
|
@default_name ||= model_class.name.split('::').last
|
85
81
|
end
|
@@ -37,28 +37,25 @@ module GraphqlRails
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def add_fields_to_graphql_type
|
40
|
-
|
40
|
+
scalar_attributes, dynamic_attributes = attributes.values.partition(&:scalar_type?)
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
name: name, description: description,
|
46
|
-
attributes: attributes, type_name: type_name
|
47
|
-
)
|
48
|
-
end
|
49
|
-
AddFieldsToGraphqlType.call(klass: klass, attributes: dynamic_attributes)
|
50
|
-
end
|
42
|
+
AddFieldsToGraphqlType.call(klass: klass, attributes: scalar_attributes)
|
43
|
+
dynamic_attributes.each { |attribute| find_or_build_dynamic_type(attribute) }
|
44
|
+
AddFieldsToGraphqlType.call(klass: klass, attributes: dynamic_attributes)
|
51
45
|
end
|
52
46
|
|
53
|
-
def
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
47
|
+
def find_or_build_dynamic_type(attribute)
|
48
|
+
graphql_model = attribute.graphql_model
|
49
|
+
find_or_build_graphql_model_type(graphql_model) if graphql_model
|
50
|
+
end
|
51
|
+
|
52
|
+
def find_or_build_graphql_model_type(graphql_model)
|
53
|
+
self.class.call(
|
54
|
+
name: graphql_model.graphql.name,
|
55
|
+
description: graphql_model.graphql.description,
|
56
|
+
attributes: graphql_model.graphql.attributes,
|
57
|
+
type_name: graphql_model.graphql.type_name
|
58
|
+
)
|
62
59
|
end
|
63
60
|
end
|
64
61
|
end
|
@@ -5,6 +5,7 @@ module GraphqlRails
|
|
5
5
|
# Initializes class to define graphql type and fields.
|
6
6
|
class FindOrBuildGraphqlTypeClass
|
7
7
|
require 'graphql_rails/concerns/service'
|
8
|
+
require 'graphql_rails/types/object_type'
|
8
9
|
|
9
10
|
include ::GraphqlRails::Service
|
10
11
|
|
@@ -32,7 +33,7 @@ module GraphqlRails
|
|
32
33
|
graphql_type_name = name
|
33
34
|
graphql_type_description = description
|
34
35
|
|
35
|
-
graphql_type_klass = Class.new(
|
36
|
+
graphql_type_klass = Class.new(GraphqlRails::Types::ObjectType) do
|
36
37
|
graphql_name(graphql_type_name)
|
37
38
|
description(graphql_type_description)
|
38
39
|
end
|
@@ -1,58 +1,42 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'graphql_rails/model/build_graphql_input_type'
|
4
|
-
require 'graphql_rails/model/configurable'
|
5
|
-
|
6
3
|
module GraphqlRails
|
7
4
|
module Model
|
8
5
|
# stores information about model input specific config, like attributes and types
|
9
6
|
class Input
|
7
|
+
require 'graphql_rails/concerns/chainable_options'
|
8
|
+
require 'graphql_rails/model/configurable'
|
9
|
+
require 'graphql_rails/model/build_graphql_input_type'
|
10
|
+
|
10
11
|
include Configurable
|
11
12
|
|
13
|
+
chainable_option :enum
|
14
|
+
|
12
15
|
def initialize(model_class, input_name_suffix)
|
13
16
|
@model_class = model_class
|
14
17
|
@input_name_suffix = input_name_suffix
|
15
18
|
end
|
16
19
|
|
17
|
-
def initialize_copy(other)
|
18
|
-
super
|
19
|
-
@attributes = other.instance_variable_get(:@attributes)&.transform_values(&:dup)
|
20
|
-
end
|
21
|
-
|
22
20
|
def graphql_input_type
|
23
21
|
@graphql_input_type ||= BuildGraphqlInputType.call(
|
24
22
|
name: name, description: description, attributes: attributes
|
25
23
|
)
|
26
24
|
end
|
27
25
|
|
28
|
-
def attribute(attribute_name, type: nil, enum: nil, **attribute_options)
|
29
|
-
input_type = attribute_type(attribute_name, type: type, enum: enum, **attribute_options)
|
30
|
-
|
31
|
-
attributes[attribute_name.to_s] = Attributes::InputAttribute.new(
|
32
|
-
attribute_name, type: input_type, **attribute_options
|
33
|
-
)
|
34
|
-
end
|
35
|
-
|
36
26
|
private
|
37
27
|
|
38
28
|
attr_reader :input_name_suffix, :model_class
|
39
29
|
|
30
|
+
def build_attribute(attribute_name)
|
31
|
+
Attributes::InputAttribute.new(attribute_name, config: self)
|
32
|
+
end
|
33
|
+
|
40
34
|
def default_name
|
41
35
|
@default_name ||= begin
|
42
36
|
suffix = input_name_suffix ? input_name_suffix.to_s.camelize : ''
|
43
37
|
"#{model_class.name.split('::').last}#{suffix}Input"
|
44
38
|
end
|
45
39
|
end
|
46
|
-
|
47
|
-
def attribute_type(attribute_name, type:, enum:, description: nil, **_other)
|
48
|
-
return type unless enum
|
49
|
-
|
50
|
-
BuildEnumType.call(
|
51
|
-
"#{name}_#{attribute_name}_enum",
|
52
|
-
allowed_values: enum,
|
53
|
-
description: description
|
54
|
-
)
|
55
|
-
end
|
56
40
|
end
|
57
41
|
end
|
58
42
|
end
|
@@ -8,12 +8,13 @@ module GraphqlRails
|
|
8
8
|
|
9
9
|
include ::GraphqlRails::Service
|
10
10
|
|
11
|
-
def initialize(
|
11
|
+
def initialize(params:, context: {}, schema: nil, router: nil, group: nil, **schema_options) # rubocop:disable Metrics/ParameterLists
|
12
12
|
@group = group
|
13
13
|
@graphql_schema = schema
|
14
14
|
@params = params
|
15
|
-
@schema_options = schema_options
|
16
15
|
@router = router
|
16
|
+
@initial_context = context
|
17
|
+
@schema_options = schema_options
|
17
18
|
end
|
18
19
|
|
19
20
|
def call
|
@@ -21,13 +22,18 @@ module GraphqlRails
|
|
21
22
|
params[:query],
|
22
23
|
variables: variables,
|
23
24
|
operation_name: params[:operationName],
|
25
|
+
context: context,
|
24
26
|
**schema_options
|
25
27
|
)
|
26
28
|
end
|
27
29
|
|
28
30
|
private
|
29
31
|
|
30
|
-
attr_reader :schema_options, :params, :group
|
32
|
+
attr_reader :schema_options, :params, :group, :initial_context
|
33
|
+
|
34
|
+
def context
|
35
|
+
initial_context.merge(graphql_group: group)
|
36
|
+
end
|
31
37
|
|
32
38
|
def variables
|
33
39
|
ensure_hash(params[:variables])
|
@@ -28,6 +28,10 @@ module GraphqlRails
|
|
28
28
|
routes << build_mutation(*args, **kwargs)
|
29
29
|
end
|
30
30
|
|
31
|
+
def subscription(*args, **kwargs)
|
32
|
+
routes << build_subscription(*args, **kwargs)
|
33
|
+
end
|
34
|
+
|
31
35
|
private
|
32
36
|
|
33
37
|
attr_reader :autogenerated_action_names, :name, :options
|
@@ -62,6 +66,10 @@ module GraphqlRails
|
|
62
66
|
build_route(QueryRoute, *args, **kwargs)
|
63
67
|
end
|
64
68
|
|
69
|
+
def build_subscription(*args, **kwargs)
|
70
|
+
build_route(SubscriptionRoute, *args, **kwargs)
|
71
|
+
end
|
72
|
+
|
65
73
|
# rubocop:disable Metrics/ParameterLists
|
66
74
|
def build_route(builder, action, prefix: action, suffix: false, on: :member, **custom_options)
|
67
75
|
if suffix == true
|
@@ -6,7 +6,7 @@ module GraphqlRails
|
|
6
6
|
class Router
|
7
7
|
# Generic class for any type graphql action. Should not be used directly
|
8
8
|
class Route
|
9
|
-
attr_reader :name, :module_name, :on, :relative_path
|
9
|
+
attr_reader :name, :module_name, :on, :relative_path, :groups
|
10
10
|
|
11
11
|
def initialize(name, to: '', on:, groups: nil, **options)
|
12
12
|
@name = name.to_s.camelize(:lower)
|
@@ -43,7 +43,7 @@ module GraphqlRails
|
|
43
43
|
|
44
44
|
private
|
45
45
|
|
46
|
-
attr_reader :function
|
46
|
+
attr_reader :function
|
47
47
|
|
48
48
|
def resolver
|
49
49
|
@resolver ||= Controller::BuildControllerActionResolver.call(route: self)
|
@@ -6,11 +6,12 @@ module GraphqlRails
|
|
6
6
|
class SchemaBuilder
|
7
7
|
require_relative './plain_cursor_encoder'
|
8
8
|
|
9
|
-
attr_reader :queries, :mutations, :raw_actions
|
9
|
+
attr_reader :queries, :mutations, :subscriptions, :raw_actions
|
10
10
|
|
11
|
-
def initialize(queries:, mutations:, raw_actions:, group: nil)
|
11
|
+
def initialize(queries:, mutations:, subscriptions:, raw_actions:, group: nil)
|
12
12
|
@queries = queries
|
13
13
|
@mutations = mutations
|
14
|
+
@subscriptions = subscriptions
|
14
15
|
@raw_actions = raw_actions
|
15
16
|
@group = group
|
16
17
|
end
|
@@ -18,6 +19,7 @@ module GraphqlRails
|
|
18
19
|
def call
|
19
20
|
query_type = build_group_type('Query', queries)
|
20
21
|
mutation_type = build_group_type('Mutation', mutations)
|
22
|
+
subscription_type = build_group_type('Subscription', subscriptions)
|
21
23
|
raw = raw_actions
|
22
24
|
|
23
25
|
Class.new(GraphQL::Schema) do
|
@@ -30,6 +32,7 @@ module GraphqlRails
|
|
30
32
|
|
31
33
|
query(query_type) if query_type
|
32
34
|
mutation(mutation_type) if mutation_type
|
35
|
+
subscription(subscription_type) if subscription_type
|
33
36
|
end
|
34
37
|
end
|
35
38
|
|
@@ -39,7 +42,13 @@ module GraphqlRails
|
|
39
42
|
|
40
43
|
def build_group_type(type_name, routes)
|
41
44
|
group_name = group
|
42
|
-
group_routes =
|
45
|
+
group_routes =
|
46
|
+
routes
|
47
|
+
.select { |route| route.show_in_group?(group_name) }
|
48
|
+
.reverse
|
49
|
+
.uniq(&:name)
|
50
|
+
.reverse
|
51
|
+
|
43
52
|
return if group_routes.empty?
|
44
53
|
|
45
54
|
build_type(type_name, group_routes)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'route'
|
4
|
+
|
5
|
+
module GraphqlRails
|
6
|
+
class Router
|
7
|
+
# stores subscription type graphql action info
|
8
|
+
class SubscriptionRoute < Route
|
9
|
+
def query?
|
10
|
+
false
|
11
|
+
end
|
12
|
+
|
13
|
+
def mutation?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
def subscription?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/graphql_rails/router.rb
CHANGED
@@ -5,6 +5,7 @@ require 'active_support/core_ext/string/inflections'
|
|
5
5
|
require 'graphql_rails/router/schema_builder'
|
6
6
|
require 'graphql_rails/router/mutation_route'
|
7
7
|
require 'graphql_rails/router/query_route'
|
8
|
+
require 'graphql_rails/router/subscription_route'
|
8
9
|
require 'graphql_rails/router/resource_routes_builder'
|
9
10
|
|
10
11
|
module GraphqlRails
|
@@ -27,6 +28,7 @@ module GraphqlRails
|
|
27
28
|
@group_names = group_names
|
28
29
|
@routes ||= Set.new
|
29
30
|
@raw_graphql_actions ||= []
|
31
|
+
@graphql_schema = {}
|
30
32
|
end
|
31
33
|
|
32
34
|
def group(*group_names, &block)
|
@@ -57,6 +59,10 @@ module GraphqlRails
|
|
57
59
|
routes << build_route(MutationRoute, name, **options)
|
58
60
|
end
|
59
61
|
|
62
|
+
def subscription(name, **options)
|
63
|
+
routes << build_route(SubscriptionRoute, name, **options)
|
64
|
+
end
|
65
|
+
|
60
66
|
RAW_ACTION_NAMES.each do |action_name|
|
61
67
|
define_method(action_name) do |*args, &block|
|
62
68
|
add_raw_action(action_name, *args, &block)
|
@@ -64,17 +70,17 @@ module GraphqlRails
|
|
64
70
|
end
|
65
71
|
|
66
72
|
def graphql_schema(group = nil)
|
67
|
-
@graphql_schema ||= {}
|
68
73
|
@graphql_schema[group&.to_sym] ||= SchemaBuilder.new(
|
69
74
|
queries: routes.select(&:query?),
|
70
75
|
mutations: routes.select(&:mutation?),
|
76
|
+
subscriptions: routes.select(&:subscription?),
|
71
77
|
raw_actions: raw_graphql_actions,
|
72
78
|
group: group
|
73
79
|
).call
|
74
80
|
end
|
75
81
|
|
76
82
|
def reload_schema
|
77
|
-
@graphql_schema
|
83
|
+
@graphql_schema.clear
|
78
84
|
end
|
79
85
|
|
80
86
|
private
|
@@ -7,51 +7,42 @@ module GraphqlRails
|
|
7
7
|
|
8
8
|
class MissingGraphqlRouterError < GraphqlRails::Error; end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
def self.call(*args)
|
13
|
-
new(*args).call
|
10
|
+
def self.call(**args)
|
11
|
+
new(**args).call
|
14
12
|
end
|
15
13
|
|
16
|
-
def initialize(
|
17
|
-
@
|
14
|
+
def initialize(group:, router:, dump_dir: nil)
|
15
|
+
@group = group
|
16
|
+
@router = router
|
17
|
+
@dump_dir = dump_dir
|
18
18
|
end
|
19
19
|
|
20
20
|
def call
|
21
|
-
|
22
|
-
File.write(schema_path, schema.to_definition)
|
21
|
+
File.write(schema_path, schema_dump)
|
23
22
|
end
|
24
23
|
|
25
24
|
private
|
26
25
|
|
27
|
-
|
28
|
-
return if router
|
29
|
-
|
30
|
-
error_message = \
|
31
|
-
'GraphqlRouter is missing. ' \
|
32
|
-
'Run `rails g graphql_rails:install` to build it'
|
33
|
-
raise MissingGraphqlRouterError, error_message
|
34
|
-
end
|
26
|
+
attr_reader :router, :group
|
35
27
|
|
36
|
-
def
|
37
|
-
|
28
|
+
def schema_dump
|
29
|
+
context = { graphql_group: group }
|
30
|
+
schema.to_definition(context: context)
|
38
31
|
end
|
39
32
|
|
40
33
|
def schema
|
41
|
-
@schema ||=
|
34
|
+
@schema ||= router.graphql_schema(group.presence)
|
42
35
|
end
|
43
36
|
|
44
37
|
def schema_path
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
def default_schema_path
|
49
|
-
schema_folder_path = Rails.root.join('spec', 'fixtures')
|
38
|
+
FileUtils.mkdir_p(dump_dir)
|
39
|
+
file_name = group.present? ? "graphql_#{group}_schema.graphql" : 'graphql_schema.graphql'
|
50
40
|
|
51
|
-
|
52
|
-
|
41
|
+
"#{dump_dir}/#{file_name}"
|
42
|
+
end
|
53
43
|
|
54
|
-
|
44
|
+
def dump_dir
|
45
|
+
@dump_dir ||= Rails.root.join('spec/fixtures').to_s
|
55
46
|
end
|
56
47
|
end
|
57
48
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'graphql_rails/tasks/dump_graphql_schema'
|
4
|
+
|
5
|
+
module GraphqlRails
|
6
|
+
# Generates graphql schema dump files
|
7
|
+
class DumpGraphqlSchemas
|
8
|
+
require 'graphql_rails/errors/error'
|
9
|
+
|
10
|
+
class MissingGraphqlRouterError < GraphqlRails::Error; end
|
11
|
+
|
12
|
+
def self.call(**args)
|
13
|
+
new(**args).call
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(dump_dir:, groups: nil)
|
17
|
+
@groups = groups.presence
|
18
|
+
@dump_dir = dump_dir
|
19
|
+
end
|
20
|
+
|
21
|
+
def call
|
22
|
+
validate
|
23
|
+
return dump_default_schema if groups.empty?
|
24
|
+
|
25
|
+
groups.each { |group| dump_graphql_schema(group) }
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :dump_dir
|
31
|
+
|
32
|
+
def dump_default_schema
|
33
|
+
dump_graphql_schema('')
|
34
|
+
end
|
35
|
+
|
36
|
+
def dump_graphql_schema(group)
|
37
|
+
DumpGraphqlSchema.call(group: group, router: router, dump_dir: dump_dir)
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate
|
41
|
+
return if router
|
42
|
+
|
43
|
+
error_message = \
|
44
|
+
'GraphqlRouter is missing. ' \
|
45
|
+
'Run `rails g graphql_rails:install` to build it'
|
46
|
+
raise MissingGraphqlRouterError, error_message
|
47
|
+
end
|
48
|
+
|
49
|
+
def router
|
50
|
+
@router ||= '::GraphqlRouter'.safe_constantize
|
51
|
+
end
|
52
|
+
|
53
|
+
def groups
|
54
|
+
@groups ||= router.routes.flat_map(&:groups).uniq
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -1,14 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'graphql_rails/tasks/
|
3
|
+
require 'graphql_rails/tasks/dump_graphql_schemas'
|
4
4
|
|
5
5
|
namespace :graphql_rails do
|
6
6
|
namespace :schema do
|
7
7
|
desc 'Dump GraphQL schema'
|
8
|
-
task(:
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
task(dump: :environment) do |_, args|
|
9
|
+
groups_from_args = args.extras
|
10
|
+
groups_from_env = ENV['SCHEMA_GROUP_NAME'].to_s.split(',').map(&:strip)
|
11
|
+
groups = groups_from_args + groups_from_env
|
12
|
+
dump_dir = ENV.fetch('GRAPHQL_SCHEMA_DUMP_DIR') { Rails.root.join('spec/fixtures').to_s }
|
13
|
+
|
14
|
+
GraphqlRails::DumpGraphqlSchemas.call(groups: groups, dump_dir: dump_dir)
|
12
15
|
end
|
13
16
|
end
|
14
17
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'graphql_rails/types/hidable_by_group'
|
4
|
+
|
5
|
+
module GraphqlRails
|
6
|
+
module Types
|
7
|
+
# Base argument type for all GraphqlRails inputs
|
8
|
+
class ArgumentType < GraphQL::Schema::Argument
|
9
|
+
include GraphqlRails::Types::HidableByGroup
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'graphql_rails/types/argument_type'
|
4
|
+
require 'graphql_rails/types/hidable_by_group'
|
5
|
+
|
6
|
+
module GraphqlRails
|
7
|
+
module Types
|
8
|
+
# Base field for all GraphqlRails model fields
|
9
|
+
class FieldType < GraphQL::Schema::Field
|
10
|
+
include GraphqlRails::Types::HidableByGroup
|
11
|
+
argument_class(GraphqlRails::Types::ArgumentType)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'graphql_rails/types/argument_type'
|
4
|
+
|
5
|
+
module GraphqlRails
|
6
|
+
module Types
|
7
|
+
# Add visibility option based on groups
|
8
|
+
module HidableByGroup
|
9
|
+
def initialize(*args, groups: [], **kwargs, &block)
|
10
|
+
super(*args, **kwargs, &block)
|
11
|
+
|
12
|
+
@groups = groups.map(&:to_s)
|
13
|
+
end
|
14
|
+
|
15
|
+
def visible?(context)
|
16
|
+
super && visible_in_context_group?(context)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def groups
|
22
|
+
@groups
|
23
|
+
end
|
24
|
+
|
25
|
+
def visible_in_context_group?(context)
|
26
|
+
group = context[:graphql_group] || context['graphql_group']
|
27
|
+
|
28
|
+
group.nil? || groups.empty? || groups.include?(group.to_s)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|