rails-graphql 1.0.0.beta → 1.0.0.rc2
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/ext/gql_parser.c +1 -16
- data/ext/gql_parser.h +21 -0
- data/ext/shared.c +0 -5
- data/ext/shared.h +6 -6
- data/lib/generators/graphql/channel_generator.rb +27 -0
- data/lib/generators/graphql/controller_generator.rb +9 -4
- data/lib/generators/graphql/install_generator.rb +49 -0
- data/lib/generators/graphql/schema_generator.rb +9 -4
- data/lib/generators/graphql/templates/channel.erb +7 -0
- data/lib/generators/graphql/templates/config.rb +97 -0
- data/lib/generators/graphql/templates/controller.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +5 -3
- data/lib/gql_parser.so +0 -0
- data/lib/rails/graphql/alternative/field_set.rb +12 -0
- data/lib/rails/graphql/alternative/query.rb +13 -8
- data/lib/rails/graphql/alternative/subscription.rb +2 -1
- data/lib/rails/graphql/alternative.rb +4 -0
- data/lib/rails/graphql/argument.rb +5 -3
- data/lib/rails/graphql/callback.rb +10 -8
- data/lib/rails/graphql/collectors/hash_collector.rb +12 -1
- data/lib/rails/graphql/collectors/json_collector.rb +21 -0
- data/lib/rails/graphql/config.rb +86 -59
- data/lib/rails/graphql/directive/include_directive.rb +0 -1
- data/lib/rails/graphql/directive/skip_directive.rb +0 -1
- data/lib/rails/graphql/directive/specified_by_directive.rb +24 -0
- data/lib/rails/graphql/directive.rb +31 -25
- data/lib/rails/graphql/event.rb +7 -6
- data/lib/rails/graphql/field/authorized_field.rb +0 -5
- data/lib/rails/graphql/field/input_field.rb +0 -5
- data/lib/rails/graphql/field/mutation_field.rb +5 -6
- data/lib/rails/graphql/field/output_field.rb +13 -2
- data/lib/rails/graphql/field/proxied_field.rb +6 -6
- data/lib/rails/graphql/field/resolved_field.rb +1 -1
- data/lib/rails/graphql/field/subscription_field.rb +35 -52
- data/lib/rails/graphql/field/typed_field.rb +26 -2
- data/lib/rails/graphql/field.rb +20 -19
- data/lib/rails/graphql/global_id.rb +5 -1
- data/lib/rails/graphql/helpers/inherited_collection/array.rb +1 -0
- data/lib/rails/graphql/helpers/inherited_collection/base.rb +3 -1
- data/lib/rails/graphql/helpers/inherited_collection/hash.rb +2 -1
- data/lib/rails/graphql/helpers/registerable.rb +1 -1
- data/lib/rails/graphql/helpers/with_arguments.rb +3 -2
- data/lib/rails/graphql/helpers/with_assignment.rb +5 -5
- data/lib/rails/graphql/helpers/with_callbacks.rb +3 -3
- data/lib/rails/graphql/helpers/with_description.rb +10 -8
- data/lib/rails/graphql/helpers/with_directives.rb +5 -1
- data/lib/rails/graphql/helpers/with_events.rb +1 -0
- data/lib/rails/graphql/helpers/with_fields.rb +30 -24
- data/lib/rails/graphql/helpers/with_name.rb +3 -2
- data/lib/rails/graphql/helpers/with_schema_fields.rb +75 -51
- data/lib/rails/graphql/introspection.rb +1 -1
- data/lib/rails/graphql/railtie.rb +3 -2
- data/lib/rails/graphql/railties/app/base_channel.rb +10 -0
- data/lib/rails/graphql/railties/app/base_controller.rb +12 -0
- data/lib/rails/graphql/railties/app/views/_cable.js.erb +56 -0
- data/lib/rails/graphql/railties/app/views/_fetch.js.erb +20 -0
- data/lib/rails/graphql/railties/app/views/graphiql.html.erb +101 -0
- data/lib/rails/graphql/railties/base_generator.rb +3 -9
- data/lib/rails/graphql/railties/channel.rb +8 -8
- data/lib/rails/graphql/railties/controller.rb +51 -26
- data/lib/rails/graphql/request/arguments.rb +2 -1
- data/lib/rails/graphql/request/backtrace.rb +31 -10
- data/lib/rails/graphql/request/component/field.rb +15 -8
- data/lib/rails/graphql/request/component/fragment.rb +13 -7
- data/lib/rails/graphql/request/component/operation/subscription.rb +4 -6
- data/lib/rails/graphql/request/component/operation.rb +12 -5
- data/lib/rails/graphql/request/component/spread.rb +13 -4
- data/lib/rails/graphql/request/component/typename.rb +1 -1
- data/lib/rails/graphql/request/component.rb +2 -0
- data/lib/rails/graphql/request/context.rb +1 -1
- data/lib/rails/graphql/request/event.rb +6 -2
- data/lib/rails/graphql/request/helpers/directives.rb +1 -0
- data/lib/rails/graphql/request/helpers/selection_set.rb +10 -4
- data/lib/rails/graphql/request/helpers/value_writers.rb +8 -5
- data/lib/rails/graphql/request/prepared_data.rb +3 -1
- data/lib/rails/graphql/request/steps/organizable.rb +1 -1
- data/lib/rails/graphql/request/steps/preparable.rb +1 -1
- data/lib/rails/graphql/request/steps/resolvable.rb +1 -1
- data/lib/rails/graphql/request/strategy/sequenced_strategy.rb +3 -3
- data/lib/rails/graphql/request/strategy.rb +18 -4
- data/lib/rails/graphql/request/subscription.rb +18 -16
- data/lib/rails/graphql/request.rb +71 -41
- data/lib/rails/graphql/schema.rb +39 -86
- data/lib/rails/graphql/shortcuts.rb +11 -5
- data/lib/rails/graphql/source/active_record/builders.rb +22 -24
- data/lib/rails/graphql/source/active_record_source.rb +96 -34
- data/lib/rails/graphql/source/base.rb +13 -40
- data/lib/rails/graphql/source/builder.rb +14 -22
- data/lib/rails/graphql/source/scoped_arguments.rb +10 -4
- data/lib/rails/graphql/source.rb +31 -38
- data/lib/rails/graphql/subscription/provider/action_cable.rb +10 -9
- data/lib/rails/graphql/subscription/provider/base.rb +6 -5
- data/lib/rails/graphql/subscription/store/base.rb +5 -9
- data/lib/rails/graphql/subscription/store/memory.rb +18 -9
- data/lib/rails/graphql/type/creator.rb +198 -0
- data/lib/rails/graphql/type/enum.rb +17 -9
- data/lib/rails/graphql/type/input.rb +30 -7
- data/lib/rails/graphql/type/interface.rb +15 -4
- data/lib/rails/graphql/type/object/directive_object.rb +6 -5
- data/lib/rails/graphql/type/object/input_value_object.rb +3 -4
- data/lib/rails/graphql/type/object/type_object.rb +40 -13
- data/lib/rails/graphql/type/object.rb +11 -6
- data/lib/rails/graphql/type/scalar/binary_scalar.rb +2 -0
- data/lib/rails/graphql/type/scalar/date_scalar.rb +2 -0
- data/lib/rails/graphql/type/scalar/date_time_scalar.rb +2 -0
- data/lib/rails/graphql/type/scalar/decimal_scalar.rb +2 -0
- data/lib/rails/graphql/type/scalar/json_scalar.rb +3 -1
- data/lib/rails/graphql/type/scalar/time_scalar.rb +3 -1
- data/lib/rails/graphql/type/scalar.rb +2 -2
- data/lib/rails/graphql/type/union.rb +7 -2
- data/lib/rails/graphql/type.rb +10 -2
- data/lib/rails/graphql/type_map.rb +20 -7
- data/lib/rails/graphql/uri.rb +5 -4
- data/lib/rails/graphql/version.rb +6 -2
- data/lib/rails/graphql.rb +11 -8
- data/test/assets/introspection-mem.txt +1 -1
- data/test/assets/introspection.gql +2 -0
- data/test/assets/mem.gql +74 -60
- data/test/assets/mysql.gql +69 -55
- data/test/assets/sqlite.gql +78 -64
- data/test/assets/translate.gql +50 -39
- data/test/config.rb +2 -1
- data/test/graphql/schema_test.rb +2 -31
- data/test/graphql/source_test.rb +1 -11
- data/test/graphql/type/interface_test.rb +8 -5
- data/test/graphql/type/object_test.rb +8 -2
- data/test/graphql/type_map_test.rb +13 -16
- data/test/integration/global_id_test.rb +4 -4
- data/test/integration/memory/star_wars_validation_test.rb +2 -2
- data/test/integration/mysql/star_wars_introspection_test.rb +1 -1
- data/test/integration/resolver_precedence_test.rb +1 -1
- data/test/integration/schemas/memory.rb +3 -4
- data/test/integration/sqlite/star_wars_global_id_test.rb +27 -21
- data/test/integration/sqlite/star_wars_introspection_test.rb +1 -1
- data/test/integration/translate_test.rb +26 -14
- metadata +22 -9
data/lib/rails/graphql/config.rb
CHANGED
@@ -3,20 +3,22 @@
|
|
3
3
|
module Rails
|
4
4
|
module GraphQL
|
5
5
|
configure do |config|
|
6
|
-
# This helps to keep track of when things were cached and registered.
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
6
|
+
# This helps to keep track of when things were cached and registered. Cached
|
7
|
+
# objects with mismatching versions need to be upgraded or simply reloaded.
|
8
|
+
# An excellent way to use this is to set it to the commit hash. TypePap will
|
9
|
+
# always use only the first 8 characters for simplicity.
|
10
10
|
config.version = nil
|
11
11
|
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
12
|
+
# The instance responsible for caching all the information generated by
|
13
|
+
# requests and all the other components. Manually setting this property
|
14
|
+
# means that the object in it complies with `ActiveSupport::Cache::Store`.
|
15
|
+
# This will map automatically to `Rails.cache` if kept as `nil`. This can
|
16
|
+
# also be set per Schema.
|
15
17
|
config.cache = nil
|
16
18
|
|
17
|
-
# If Rails cache is not properly defined
|
18
|
-
#
|
19
|
-
#
|
19
|
+
# If Rails cache is not properly defined or just set to use a NullStore,
|
20
|
+
# this fallback will set itself up with a memory store because cache is
|
21
|
+
# crucial, especially for subscriptions.
|
20
22
|
config.cache_fallback = -> do
|
21
23
|
::ActiveSupport::Cache::MemoryStore.new(max_prune_time: nil)
|
22
24
|
end
|
@@ -27,42 +29,47 @@ module Rails
|
|
27
29
|
|
28
30
|
# The list of nested paths inside of the graphql folder that does not
|
29
31
|
# require to be in their own namespace.
|
30
|
-
config.paths = %w[directives fields sources enums inputs interfaces
|
31
|
-
scalars unions].to_set
|
32
|
+
config.paths = %w[directives fields sources enums inputs interfaces objects
|
33
|
+
scalars unions concerns].to_set
|
32
34
|
|
33
|
-
# This
|
35
|
+
# This is very similar to `ActiveRecord` verbose logs, which simply show the
|
36
|
+
# path of the file that started a GraphQL request.
|
34
37
|
config.verbose_logs = true
|
35
38
|
|
36
|
-
# The list of parameters to omit from logger when running a GraphQL
|
37
|
-
# request. Those values
|
38
|
-
#
|
39
|
+
# The list of parameters to omit from the logger when running a GraphQL
|
40
|
+
# request. Those values are displayed better in the internal runtime logger
|
41
|
+
# controller.
|
39
42
|
config.omit_parameters = %w[query operationName operation_name variables graphql]
|
40
43
|
|
41
|
-
#
|
42
|
-
#
|
44
|
+
# Identical to the one available on a Rails application, but exclusive for
|
45
|
+
# GraphQL operations. The list of parameters to display as filtered in the
|
46
|
+
# logs. When it is nil, it will use the same as the Rails application.
|
43
47
|
config.filter_parameters = nil
|
44
48
|
|
45
|
-
# A list of ActiveRecord adapters
|
46
|
-
#
|
49
|
+
# A list of all `ActiveRecord` adapters supported. When an adapter is
|
50
|
+
# supported, it will map the database types into GraphQL types using proper
|
51
|
+
# aliases. Plus, it will have the method to map models attributes to their
|
52
|
+
# equivalent fields.
|
47
53
|
config.ar_adapters = {
|
48
54
|
'Mysql2' => { key: :mysql, path: "#{__dir__}/adapters/mysql_adapter" },
|
49
55
|
'PostgreSQL' => { key: :pg, path: "#{__dir__}/adapters/pg_adapter" },
|
50
56
|
'SQLite' => { key: :sqlite, path: "#{__dir__}/adapters/sqlite_adapter" },
|
51
57
|
}
|
52
58
|
|
53
|
-
#
|
54
|
-
#
|
59
|
+
# The suffix that is added automatically to all the Input type objects. This
|
60
|
+
# prevents situations like `PointInputInput`. If your inputs have a
|
61
|
+
# different suffix, change this value to it.
|
55
62
|
config.auto_suffix_input_objects = 'Input'
|
56
63
|
|
57
|
-
# Introspection is enabled by default.
|
58
|
-
#
|
59
|
-
# set
|
60
|
-
config.enable_introspection =
|
64
|
+
# Introspection is enabled by default. It is recommended to only use
|
65
|
+
# introspection during development and tests, never in production.
|
66
|
+
# This can also be set per schema level.
|
67
|
+
config.enable_introspection = false
|
61
68
|
|
62
69
|
# Define the names of the schema/operations types. The single "_" is a
|
63
|
-
# suggestion
|
64
|
-
#
|
65
|
-
#
|
70
|
+
# suggestion. In an application that has a Subscription object, it will
|
71
|
+
# prevent the conflict. Plus, it is easy to spot that it is something
|
72
|
+
# internal. This can also be set per Schema.
|
66
73
|
config.schema_type_names = {
|
67
74
|
query: '_Query',
|
68
75
|
mutation: '_Mutation',
|
@@ -71,13 +78,15 @@ module Rails
|
|
71
78
|
|
72
79
|
# For performance purposes, this gem implements a
|
73
80
|
# {JsonCollector}[rdoc-ref:Rails::GraphQL::Collectors::JsonCollector].
|
74
|
-
#
|
75
|
-
#
|
81
|
+
# You can disable this option if you prefer to use the standard
|
82
|
+
# hash-to-string serialization provided by `ActiveSupport`.
|
83
|
+
# This can also be set per Schema.
|
76
84
|
config.enable_string_collector = true
|
77
85
|
|
78
86
|
# Set what is de default expected output type of GraphQL requests. String
|
79
|
-
# combined with the previous setting has the best performance. On
|
80
|
-
# it will automatically shift to
|
87
|
+
# combined with the previous setting has the best performance. On the
|
88
|
+
# console, it will automatically shift to Hash. This can also be set per
|
89
|
+
# Schema.
|
81
90
|
config.default_response_format = :string
|
82
91
|
|
83
92
|
# Specifies if the results of operations should be encoded with
|
@@ -85,60 +94,63 @@ module Rails
|
|
85
94
|
# See also https://github.com/rails/rails/blob/master/activesupport/lib/active_support/json/encoding.rb
|
86
95
|
config.encode_with_active_support = false
|
87
96
|
|
88
|
-
# Enable the ability of a callback to
|
97
|
+
# Enable the ability of a callback to inject arguments dynamically into the
|
89
98
|
# calling method.
|
90
99
|
config.callback_inject_arguments = true
|
91
100
|
|
92
|
-
# Enable the ability of a callback to
|
93
|
-
#
|
101
|
+
# Enable the ability of a callback to inject named arguments dynamically
|
102
|
+
# into the calling method.
|
94
103
|
config.callback_inject_named_arguments = true
|
95
104
|
|
96
|
-
# When importing fields
|
97
|
-
#
|
98
|
-
#
|
105
|
+
# When importing fields from modules or other objects, a warning is
|
106
|
+
# displayed for any given element that was not able to be correctly
|
107
|
+
# imported. You can silence such warnings by changing this option.
|
99
108
|
config.silence_import_warnings = false
|
100
109
|
|
101
|
-
# Enable the ability to
|
102
|
-
|
110
|
+
# Enable the ability to define the description of any object, field, or
|
111
|
+
# argument using I18n. It is recommended for multi-language documentation.
|
112
|
+
config.enable_i18n_descriptions = false
|
103
113
|
|
104
|
-
#
|
114
|
+
# The list of scopes that will be used to locate the descriptions.
|
105
115
|
config.i18n_scopes = [
|
106
116
|
'graphql.%{namespace}.%{kind}.%{parent}.%{name}',
|
107
117
|
'graphql.%{namespace}.%{kind}.%{name}',
|
108
118
|
'graphql.%{namespace}.%{name}',
|
109
119
|
'graphql.%{kind}.%{parent}.%{name}',
|
110
120
|
'graphql.%{kind}.%{name}',
|
111
|
-
'graphql.%{name}'
|
121
|
+
'graphql.%{name}',
|
112
122
|
]
|
113
123
|
|
114
|
-
# A list of execution strategies. Each application can add
|
115
|
-
#
|
124
|
+
# A list of execution strategies. Each application can add its own by
|
125
|
+
# appending a class, preferably as a string, in this list. This can also be
|
126
|
+
# set per Schema.
|
116
127
|
config.request_strategies = [
|
117
128
|
'Rails::GraphQL::Request::Strategy::MultiQueryStrategy',
|
118
129
|
'Rails::GraphQL::Request::Strategy::SequencedStrategy',
|
119
130
|
# 'Rails::GraphQL::Request::Strategy::CachedStrategy',
|
120
131
|
]
|
121
132
|
|
122
|
-
# A list of all possible
|
133
|
+
# A list of all possible ruby-to-graphql compatible sources.
|
123
134
|
config.sources = [
|
124
135
|
'Rails::GraphQL::Source::ActiveRecordSource',
|
125
136
|
]
|
126
137
|
|
127
|
-
# A list of all available subscription providers
|
128
|
-
# Rails::GraphQL::SubscriptionProvider::Base
|
138
|
+
# A list of all available subscription providers.
|
129
139
|
config.subscription_providers = [
|
130
140
|
'Rails::GraphQL::Subscription::Provider::ActionCable',
|
131
141
|
]
|
132
142
|
|
133
|
-
# The default subscription provider for all
|
143
|
+
# The default subscription provider for all schemas. This can also be set
|
144
|
+
# per Schema.
|
134
145
|
config.default_subscription_provider = config.subscription_providers.first
|
135
146
|
|
136
|
-
# The default value for fields about their ability
|
147
|
+
# The default value for fields about their ability to be broadcasted. This
|
148
|
+
# can also be set per Schema.
|
137
149
|
config.default_subscription_broadcastable = nil
|
138
150
|
|
139
151
|
# A list of known dependencies that can be requested and included in any
|
140
|
-
#
|
141
|
-
#
|
152
|
+
# Schema. This is the best place for other gems to add their own resources
|
153
|
+
# and allow users to enable them.
|
142
154
|
config.known_dependencies = {
|
143
155
|
scalar: {
|
144
156
|
any: "#{__dir__}/type/scalar/any_scalar",
|
@@ -150,20 +162,35 @@ module Rails
|
|
150
162
|
time: "#{__dir__}/type/scalar/time_scalar",
|
151
163
|
json: "#{__dir__}/type/scalar/json_scalar",
|
152
164
|
},
|
165
|
+
enum: {},
|
166
|
+
input: {},
|
167
|
+
interface: {},
|
168
|
+
object: {},
|
169
|
+
union: {},
|
153
170
|
directive: {
|
154
171
|
# cached: "#{__dir__}/directive/cached_directive",
|
155
172
|
},
|
156
173
|
}
|
157
174
|
|
158
|
-
# The method that should be used to parse literal input values when they
|
159
|
-
#
|
160
|
-
# to support keys without quotes,
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
# +->(value) { anything }+
|
175
|
+
# The method that should be used to parse literal input values when they are
|
176
|
+
# provided as Hash. `JSON.parse` only supports keys wrapped in quotes. You
|
177
|
+
# can use `Psych.method(:safe_load)` to support keys without quotes, which
|
178
|
+
# behaves closer to YAML. The received value is ensured to be wrapped in
|
179
|
+
# "{}". If that produces unexpected results, you can assign a proc and then
|
180
|
+
# parse the value in any other way.
|
165
181
|
config.literal_input_parser = JSON.method(:parse)
|
166
182
|
|
183
|
+
# A mapping for the internal parameters and where they should be taken
|
184
|
+
# from. You can point to nested values using dot notation.
|
185
|
+
# TODO: Needs implementation
|
186
|
+
config.params_mapping = {
|
187
|
+
query: 'query',
|
188
|
+
variables: 'variables',
|
189
|
+
operation_name: 'operation_name',
|
190
|
+
query_cache_key: 'extensions.persistedQuery.sha256Hash',
|
191
|
+
query_cache_version: 'extensions.persistedQuery.version',
|
192
|
+
}
|
193
|
+
|
167
194
|
# TODO: To be implemented
|
168
195
|
# allow_query_serialization
|
169
196
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rails
|
4
|
+
module GraphQL
|
5
|
+
# = GraphQL Spec Specified By Directive
|
6
|
+
#
|
7
|
+
# Provides a scalar specification URL for specifying the behavior of
|
8
|
+
# custom scalar types.
|
9
|
+
class Directive::SpecifiedByDirective < Directive
|
10
|
+
self.spec_object = true
|
11
|
+
|
12
|
+
placed_on :scalar
|
13
|
+
|
14
|
+
desc <<~DESC
|
15
|
+
A built-in directive used within the type system definition language to provide
|
16
|
+
a scalar specification URL for specifying the behavior of custom scalar types.
|
17
|
+
DESC
|
18
|
+
|
19
|
+
argument :url, :string, null: false, desc: <<~DESC
|
20
|
+
Point to a human-readable specification of the data format.
|
21
|
+
DESC
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -44,6 +44,13 @@ module Rails
|
|
44
44
|
:directive
|
45
45
|
end
|
46
46
|
|
47
|
+
# Ensure to return the directive class
|
48
|
+
def base_type
|
49
|
+
GraphQL::Directive
|
50
|
+
end
|
51
|
+
|
52
|
+
alias gid_base_class base_type
|
53
|
+
|
47
54
|
# Return the name of the object as a GraphQL name, ensure to use the
|
48
55
|
# first letter as lower case when being auto generated
|
49
56
|
def gql_name
|
@@ -71,11 +78,6 @@ module Rails
|
|
71
78
|
@locations = list.to_set
|
72
79
|
end
|
73
80
|
|
74
|
-
# Ensure to return the directive class
|
75
|
-
def gid_base_class
|
76
|
-
GraphQL::Directive
|
77
|
-
end
|
78
|
-
|
79
81
|
# A helper method that allows directives to be initialized while
|
80
82
|
# correctly parsing the arguments
|
81
83
|
def build(**xargs)
|
@@ -97,10 +99,11 @@ module Rails
|
|
97
99
|
def inspect
|
98
100
|
return super if eql?(GraphQL::Directive)
|
99
101
|
|
102
|
+
repeatable = ' [repeatable]' if repeatable?
|
100
103
|
args = all_arguments&.each_value&.map(&:inspect)
|
101
104
|
args = args.force if args.respond_to?(:force)
|
102
105
|
args = args.presence && "(#{args.join(', ')})"
|
103
|
-
+"#<GraphQL::Directive @#{gql_name}#{args}>"
|
106
|
+
+"#<GraphQL::Directive @#{gql_name}#{repeatable}#{args}>"
|
104
107
|
end
|
105
108
|
|
106
109
|
private
|
@@ -126,7 +129,7 @@ module Rails
|
|
126
129
|
GraphQL.enumerate(setting).map do |item|
|
127
130
|
next item unless item.is_a?(String) || item.is_a?(Symbol)
|
128
131
|
GraphQL.type_map.fetch(item, namespaces: namespaces) ||
|
129
|
-
::GraphQL.const_get(item)
|
132
|
+
::GraphQL.const_get(item, false)
|
130
133
|
end
|
131
134
|
end
|
132
135
|
|
@@ -141,30 +144,23 @@ module Rails
|
|
141
144
|
Invalid locations for @#{gql_name}: #{invalid.force.to_sentence}.
|
142
145
|
MSG
|
143
146
|
end
|
144
|
-
|
145
|
-
# Allows checking value existence
|
146
|
-
def respond_to_missing?(method_name, *)
|
147
|
-
(const_defined?(method_name) rescue nil) || autoload?(method_name) || super
|
148
|
-
end
|
149
|
-
|
150
|
-
# Allow fast creation of values
|
151
|
-
def method_missing(method_name, *args, **xargs, &block)
|
152
|
-
const_get(method_name)&.new(*args, **xargs, &block) || super
|
153
|
-
rescue ::NameError
|
154
|
-
super
|
155
|
-
end
|
156
147
|
end
|
157
148
|
|
149
|
+
# Marks if the directive may be used repeatedly at a single location
|
150
|
+
class_attribute :repeatable, instance_accessor: false, default: false
|
151
|
+
|
158
152
|
self.abstract = true
|
159
153
|
|
160
154
|
autoload :DeprecatedDirective
|
161
155
|
autoload :IncludeDirective
|
162
156
|
autoload :SkipDirective
|
157
|
+
autoload :SpecifiedByDirective
|
163
158
|
|
164
159
|
autoload :CachedDirective
|
165
160
|
|
166
|
-
delegate :locations, :gql_name, :gid_base_class, to: :class
|
161
|
+
delegate :locations, :gql_name, :gid_base_class, :repeatable?, to: :class
|
167
162
|
|
163
|
+
# TODO: This filters are a bit confusing now, but `for` is working for @deprecated
|
168
164
|
event_filter(:for) do |options, event|
|
169
165
|
sanitize_objects(options).any?(&event.source.method(:of_type?))
|
170
166
|
end
|
@@ -177,7 +173,7 @@ module Rails
|
|
177
173
|
event.key?(:phase) && GraphQL.enumerate(options).include?(event[:phase])
|
178
174
|
end
|
179
175
|
|
180
|
-
attr_reader :args
|
176
|
+
attr_reader :args, :event
|
181
177
|
|
182
178
|
def initialize(args = nil, **xargs)
|
183
179
|
@args = args || OpenStruct.new(xargs.transform_keys { |key| key.to_s.underscore })
|
@@ -211,10 +207,11 @@ module Rails
|
|
211
207
|
|
212
208
|
# When fetching all the events, embed the actual instance as the context
|
213
209
|
# of the callback
|
210
|
+
# TODO: Maybe add a soft cached, based on the total number of events
|
214
211
|
def all_events
|
215
212
|
return unless self.class.events?
|
216
213
|
|
217
|
-
|
214
|
+
self.class.all_events.transform_values do |events|
|
218
215
|
events.map { |item| Callback.set_context(item, self) }
|
219
216
|
end
|
220
217
|
end
|
@@ -237,18 +234,27 @@ module Rails
|
|
237
234
|
MSG
|
238
235
|
end
|
239
236
|
|
237
|
+
# This allows combining directives
|
238
|
+
def +(other)
|
239
|
+
[self, other].flatten
|
240
|
+
end
|
241
|
+
|
242
|
+
alias_method :&, :+
|
243
|
+
|
240
244
|
def inspect
|
241
|
-
args = all_arguments&.
|
245
|
+
args = all_arguments&.filter_map do |name, arg|
|
242
246
|
+"#{arg.gql_name}: #{@args[name].inspect}" unless @args[name].nil?
|
243
|
-
end
|
247
|
+
end
|
244
248
|
|
245
249
|
args = args.presence && +"(#{args.join(', ')})"
|
250
|
+
repeatable = ' [repeatable]' if repeatable?
|
246
251
|
unbound = ' # unbound' unless defined?(@owner)
|
247
|
-
+"@#{gql_name}#{args}#{unbound}"
|
252
|
+
+"@#{gql_name}#{repeatable}#{args}#{unbound}"
|
248
253
|
end
|
249
254
|
|
250
255
|
%i[to_global_id to_gid to_gid_param].each do |method_name|
|
251
256
|
define_method(method_name) do
|
257
|
+
# TODO: The option is kind of broken, because they should always be a Hash
|
252
258
|
self.class.public_send(method_name, args_as_json&.compact || '')
|
253
259
|
end
|
254
260
|
end
|
data/lib/rails/graphql/event.rb
CHANGED
@@ -7,7 +7,7 @@ module Rails
|
|
7
7
|
# This class is responsible for triggering events. It also contains the
|
8
8
|
# +data+ that can be used on the event handlers.
|
9
9
|
class Event
|
10
|
-
attr_reader :source, :data, :
|
10
|
+
attr_reader :source, :data, :event_name, :object, :last_result
|
11
11
|
|
12
12
|
alias event itself
|
13
13
|
|
@@ -34,7 +34,7 @@ module Rails
|
|
34
34
|
@collect = data.delete(:collect?)
|
35
35
|
@reverse = data.delete(:reverse?)
|
36
36
|
|
37
|
-
@
|
37
|
+
@event_name = name
|
38
38
|
@data = data
|
39
39
|
@source = source
|
40
40
|
@layers = []
|
@@ -42,9 +42,10 @@ module Rails
|
|
42
42
|
|
43
43
|
# Check if the provided +other+ is equal to the source of the event. If
|
44
44
|
# other is a directive, then check if the source is using that directive
|
45
|
+
# TODO: Other cannot be an instance
|
45
46
|
def same_source?(other)
|
46
47
|
if other.is_a?(Directive) || (other.is_a?(Module) && other < Directive)
|
47
|
-
source.using?(other)
|
48
|
+
event_name == :attach || source.using?(other)
|
48
49
|
else
|
49
50
|
source == other
|
50
51
|
end
|
@@ -81,6 +82,8 @@ module Rails
|
|
81
82
|
end
|
82
83
|
end
|
83
84
|
|
85
|
+
alias on_instance set_on
|
86
|
+
|
84
87
|
# From the list of all given objects, run the +trigger_object+
|
85
88
|
def trigger_all(*objects)
|
86
89
|
catchable(:stack) do
|
@@ -102,7 +105,7 @@ module Rails
|
|
102
105
|
old_items, old_object, old_result, @object = @items, @object, @last_result, object
|
103
106
|
|
104
107
|
catchable(:object) do
|
105
|
-
events ||= object.all_events.try(:[],
|
108
|
+
events ||= object.all_events.try(:[], event_name)
|
106
109
|
stop if events.blank?
|
107
110
|
|
108
111
|
@items = @reverse ? events.reverse_each : events.each
|
@@ -136,8 +139,6 @@ module Rails
|
|
136
139
|
# Do not do anything when missing next/super
|
137
140
|
end
|
138
141
|
|
139
|
-
alias call_super call_next
|
140
|
-
|
141
142
|
protected
|
142
143
|
|
143
144
|
alias args_source itself
|
@@ -16,11 +16,6 @@ module Rails
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
# Just add the callbacks setup to the field
|
20
|
-
def self.included(other)
|
21
|
-
other.event_types(:authorize, append: true)
|
22
|
-
end
|
23
|
-
|
24
19
|
# Add either settings for authorization or a block to be executed. It
|
25
20
|
# returns +self+ for chain purposes
|
26
21
|
def authorize(*args, **xargs, &block)
|
@@ -28,11 +28,6 @@ module Rails
|
|
28
28
|
@default = deserialize(@default) if @default.is_a?(::GQLParser::Token)
|
29
29
|
end
|
30
30
|
|
31
|
-
# Prevent input fields from being further configured using a block
|
32
|
-
def configure
|
33
|
-
raise ArgumentError, +'Input fields can\'t be further configured using blocks'
|
34
|
-
end
|
35
|
-
|
36
31
|
# Allow change the default value for the input
|
37
32
|
def apply_changes(**xargs, &block)
|
38
33
|
@default = xargs[:default] if xargs.key?(:default)
|
@@ -5,7 +5,7 @@ module Rails
|
|
5
5
|
# = GraphQL Mutation Field
|
6
6
|
#
|
7
7
|
# This is an extension of a normal output field, which just add extra
|
8
|
-
# validation and
|
8
|
+
# validation and insurance that the +perform+ step can be executed
|
9
9
|
#
|
10
10
|
# ==== Options
|
11
11
|
#
|
@@ -58,17 +58,16 @@ module Rails
|
|
58
58
|
# Get the performer that can be already defined or used through the
|
59
59
|
# +method_name+ if that is callable
|
60
60
|
def performer
|
61
|
-
@performer
|
62
|
-
|
63
|
-
|
61
|
+
return @performer if defined?(@performer)
|
62
|
+
|
63
|
+
@performer = callable?(perform_method_name)
|
64
|
+
@performer = Callback.new(self, :perform, perform_method_name) if @performer
|
64
65
|
end
|
65
66
|
|
66
67
|
# Ensures that the performer is defined
|
67
68
|
def validate!(*)
|
68
69
|
super if defined? super
|
69
70
|
|
70
|
-
binding.pry unless performer.present?
|
71
|
-
|
72
71
|
raise ValidationError, (+<<~MSG).squish unless performer.present?
|
73
72
|
The "#{gql_name}" mutation field must have a perform action through a given
|
74
73
|
block or a method named #{method_name} on #{owner.class.name}.
|
@@ -29,10 +29,12 @@ module Rails
|
|
29
29
|
include Field::TypedField
|
30
30
|
|
31
31
|
module Proxied # :nodoc: all
|
32
|
+
Field.proxyable_methods %w[broadcastable?], klass: self
|
33
|
+
|
32
34
|
def all_arguments
|
33
35
|
inherited = field.all_arguments
|
34
36
|
return inherited unless defined?(@arguments)
|
35
|
-
inherited.blank? ? super : inherited
|
37
|
+
inherited.blank? ? super : inherited.merge(super)
|
36
38
|
end
|
37
39
|
|
38
40
|
def has_argument?(name)
|
@@ -43,12 +45,17 @@ module Rails
|
|
43
45
|
super || field.arguments?
|
44
46
|
end
|
45
47
|
|
48
|
+
# TODO: Break events into directive/type/local
|
49
|
+
# because type events should only be added
|
50
|
+
# from the proxy
|
46
51
|
def all_events
|
47
52
|
if (inherited = super).nil?
|
48
53
|
field.all_events
|
49
54
|
elsif (proxied = field.all_events).nil?
|
50
55
|
inherited
|
51
56
|
else
|
57
|
+
# The order is reversed because events from
|
58
|
+
# the proxy must come first
|
52
59
|
Helpers.merge_hash_array(proxied, inherited)
|
53
60
|
end
|
54
61
|
end
|
@@ -163,6 +170,10 @@ module Rails
|
|
163
170
|
defined?(@broadcastable) && @broadcastable
|
164
171
|
end
|
165
172
|
|
173
|
+
def entry_point?
|
174
|
+
owner.is_a?(Helpers::WithSchemaFields)
|
175
|
+
end
|
176
|
+
|
166
177
|
protected
|
167
178
|
|
168
179
|
# Check if the given +value+ is a valid array as output
|
@@ -177,7 +188,7 @@ module Rails
|
|
177
188
|
|
178
189
|
# Properly display the owner section when the field is owned by a Schema
|
179
190
|
def inspect_owner
|
180
|
-
|
191
|
+
entry_point? ? +"#{owner.name}[:#{schema_type}]" : super
|
181
192
|
end
|
182
193
|
|
183
194
|
def proxied
|
@@ -25,10 +25,9 @@ module Rails
|
|
25
25
|
# * <tt>:alias</tt> - Same as the +:as+ key (defaults to nil).
|
26
26
|
module Field::ProxiedField
|
27
27
|
delegate_missing_to :field
|
28
|
-
delegate :leaf_type?, :array?, :internal?, :
|
29
|
-
:to_json, :as_json, :deserialize, :valid?, :proxied_owner, to: :field
|
28
|
+
delegate :leaf_type?, :array?, :internal?, :proxied_owner, to: :field
|
30
29
|
|
31
|
-
Field.proxyable_methods %w[name gql_name method_name
|
30
|
+
Field.proxyable_methods %w[name gql_name method_name description
|
32
31
|
null? nullable? enabled?], klass: self
|
33
32
|
|
34
33
|
def initialize(field, owner:, **xargs, &block)
|
@@ -49,7 +48,7 @@ module Rails
|
|
49
48
|
super || field == other
|
50
49
|
end
|
51
50
|
|
52
|
-
# Allow
|
51
|
+
# Allow changing most of the general kind-independent initialize settings
|
53
52
|
def apply_changes(**xargs, &block)
|
54
53
|
if (deprecated = xargs[:deprecated])
|
55
54
|
xargs[:directives] = ::Array.wrap(xargs[:directives])
|
@@ -62,7 +61,8 @@ module Rails
|
|
62
61
|
@directives = GraphQL.directives_to_set(xargs[:directives], source: self) \
|
63
62
|
if xargs.key?(:directives)
|
64
63
|
|
65
|
-
|
64
|
+
self.description = xargs[:desc] if xargs.key?(:desc)
|
65
|
+
self.description = xargs[:description] if xargs.key?(:description)
|
66
66
|
@enabled = xargs.fetch(:enabled, !xargs.fetch(:disabled, false)) \
|
67
67
|
if xargs.key?(:enabled) || xargs.key?(:disabled)
|
68
68
|
|
@@ -72,7 +72,7 @@ module Rails
|
|
72
72
|
|
73
73
|
# Override this to include proxied owners
|
74
74
|
def all_owners
|
75
|
-
super +
|
75
|
+
super + @field.all_owners
|
76
76
|
end
|
77
77
|
|
78
78
|
# Return the proxied field
|
@@ -18,7 +18,7 @@ module Rails
|
|
18
18
|
|
19
19
|
# Just add the callbacks setup to the field
|
20
20
|
def self.included(other)
|
21
|
-
other.
|
21
|
+
other.send(:expose_events!, :organized, :finalize, :prepared, :prepare)
|
22
22
|
other.alias_method(:before_resolve, :prepare)
|
23
23
|
other.alias_method(:after_resolve, :finalize)
|
24
24
|
end
|