rails-graphql 1.0.0 → 1.0.2
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 +4 -4
- data/ext/shared.c +6 -8
- data/ext/shared.h +5 -1
- data/lib/generators/graphql/templates/config.rb +5 -0
- data/lib/gql_parser.so +0 -0
- data/lib/rails/graphql/alternative/field_set.rb +3 -3
- data/lib/rails/graphql/alternative/query.rb +1 -1
- data/lib/rails/graphql/alternative.rb +1 -0
- data/lib/rails/graphql/helpers/with_fields.rb +4 -4
- data/lib/rails/graphql/request/component/operation.rb +2 -0
- data/lib/rails/graphql/version.rb +1 -1
- data/test/assets/alternative.gql +323 -0
- data/test/graphql/request/component/operation_test.rb +21 -0
- data/test/integration/alternative_test.rb +145 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e7d0465d49d0e8eef8d0672cc60cbf8f15e5ee8cb11bf765a2a944b4d5aab33
|
4
|
+
data.tar.gz: 6ada22cc356373aa92a4986029092fb63b16532e8a5df16798b15f17c4d8221a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a62b2abf73592f82b4b5b2b290dde535b32054903d6a330808c03137369df0d1962576eaf4658ef42e08803ba82fed36963d75dd72101d0ec1e3362ae2d9ceb1
|
7
|
+
data.tar.gz: d5f8e3b75c6458623e9af9a493113ac230855fadd7bdb93b4bc2f3165a3bf0ed6a7cd6697a05199749a69c3b55412cd849fbc92cd25edbbc331493f5c5989df5
|
data/ext/gql_parser.c
CHANGED
@@ -83,7 +83,7 @@ VALUE gql_parse_execution(VALUE self, VALUE document)
|
|
83
83
|
{
|
84
84
|
// Try to upgrade if the token is a name
|
85
85
|
if (scanner.lexeme == gql_i_name)
|
86
|
-
scanner.lexeme =
|
86
|
+
scanner.lexeme = GQL_SAFE_NAME_TO_KEYWORD(&scanner, GQL_EXECUTION_KEYWORDS);
|
87
87
|
|
88
88
|
// It can contain either operations or fragments, anything else is unknown and an error
|
89
89
|
if (QGL_I_OPERATION(scanner.lexeme) || scanner.lexeme == gql_is_op_curly)
|
@@ -157,14 +157,14 @@ VALUE gql_parse_fragment(struct gql_scanner *scanner)
|
|
157
157
|
gql_next_lexeme_no_comments(scanner);
|
158
158
|
if (scanner->lexeme != gql_i_name)
|
159
159
|
return gql_nil_and_unknown(scanner);
|
160
|
-
else if (
|
160
|
+
else if (GQL_SAFE_NAME_TO_KEYWORD(scanner, GQL_EXECUTION_KEYWORDS) == gql_ie_on)
|
161
161
|
return gql_nil_and_unknown(scanner);
|
162
162
|
|
163
163
|
// Save the name of the fragment
|
164
164
|
GQL_ASSIGN_TOKEN_AND_NEXT(pieces[0], scanner);
|
165
165
|
|
166
166
|
// If we don't have an "on" next, we have a problem
|
167
|
-
if (
|
167
|
+
if (GQL_SAFE_NAME_TO_KEYWORD(scanner, GQL_EXECUTION_KEYWORDS) != gql_ie_on)
|
168
168
|
return gql_nil_and_unknown(scanner);
|
169
169
|
|
170
170
|
// Skip the on and ensure that next is a name
|
@@ -481,7 +481,7 @@ VALUE gql_parse_spread(struct gql_scanner *scanner)
|
|
481
481
|
if (scanner->lexeme == gql_i_name)
|
482
482
|
{
|
483
483
|
// Upgrade the name because it will decide if it is an inline spread or not
|
484
|
-
scanner->lexeme =
|
484
|
+
scanner->lexeme = GQL_SAFE_NAME_TO_KEYWORD(scanner, GQL_EXECUTION_KEYWORDS);
|
485
485
|
|
486
486
|
// If we are at "on" then we have an inline spread, otherwise a fragment referenced by name
|
487
487
|
if (scanner->lexeme == gql_ie_on)
|
data/ext/shared.c
CHANGED
@@ -65,16 +65,17 @@ enum gql_lexeme gql_upgrade_basis(const char *upgrade_from[])
|
|
65
65
|
}
|
66
66
|
|
67
67
|
// This checks if the identifier in the scanner should be upgraded to a keyword
|
68
|
-
enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *
|
68
|
+
enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *keywords[], unsigned int size)
|
69
69
|
{
|
70
70
|
unsigned long pos, len = GQL_SCAN_SIZE(scanner);
|
71
|
-
unsigned int valid = 0
|
71
|
+
unsigned int valid = 0;
|
72
72
|
const char *keyword;
|
73
73
|
|
74
74
|
// Check until it finds the end of the array
|
75
|
-
|
75
|
+
for (size_t i = 0; i < size; ++i)
|
76
76
|
{
|
77
77
|
// Move ot the next item and check the current for different size
|
78
|
+
keyword = keywords[i];
|
78
79
|
if(strlen(keyword) == len)
|
79
80
|
{
|
80
81
|
// We cannot use the normal strcomp because we are comparing a mid part of the string
|
@@ -85,11 +86,8 @@ enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *upg
|
|
85
86
|
}
|
86
87
|
|
87
88
|
// Only return if valid was kept as true
|
88
|
-
if (valid == 1) return gql_upgrade_basis(
|
89
|
+
if (valid == 1) return gql_upgrade_basis(keywords) + i;
|
89
90
|
}
|
90
|
-
|
91
|
-
// Move to the next index
|
92
|
-
i++;
|
93
91
|
}
|
94
92
|
|
95
93
|
// Return name if was not able to upgrade to a keyword
|
@@ -438,7 +436,7 @@ VALUE gql_value_to_rb(struct gql_scanner *scanner, int accept_var)
|
|
438
436
|
// If it's a name, then it can be a keyword or a enum value
|
439
437
|
if (scanner->lexeme == gql_i_name)
|
440
438
|
{
|
441
|
-
scanner->lexeme =
|
439
|
+
scanner->lexeme = GQL_SAFE_NAME_TO_KEYWORD(scanner, GQL_VALUE_KEYWORDS);
|
442
440
|
if (scanner->lexeme == gql_iv_true)
|
443
441
|
return Qtrue;
|
444
442
|
else if (scanner->lexeme == gql_iv_false)
|
data/ext/shared.h
CHANGED
@@ -70,6 +70,10 @@
|
|
70
70
|
rb_ary_push(source, value); \
|
71
71
|
})
|
72
72
|
|
73
|
+
#define GQL_SAFE_NAME_TO_KEYWORD(scanner, source) ({ \
|
74
|
+
gql_name_to_keyword(scanner, source, (sizeof(source) / sizeof(char *))); \
|
75
|
+
})
|
76
|
+
|
73
77
|
enum gql_lexeme
|
74
78
|
{
|
75
79
|
// Basic identifiers
|
@@ -153,7 +157,7 @@ void gql_debug_print(const char *message);
|
|
153
157
|
struct gql_scanner gql_new_scanner(VALUE source);
|
154
158
|
|
155
159
|
enum gql_lexeme gql_upgrade_basis(const char *upgrade_from[]);
|
156
|
-
enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *
|
160
|
+
enum gql_lexeme gql_name_to_keyword(struct gql_scanner *scanner, const char *keywords[], unsigned int size);
|
157
161
|
|
158
162
|
enum gql_lexeme gql_read_name(struct gql_scanner *scanner);
|
159
163
|
enum gql_lexeme gql_read_comment(struct gql_scanner *scanner);
|
@@ -37,6 +37,11 @@ Rails::GraphQL.configure do |config|
|
|
37
37
|
# different suffix, change this value to it.
|
38
38
|
# config.auto_suffix_input_objects = 'Input'
|
39
39
|
|
40
|
+
# Set if the server should allow strings be used as input for ENUM inputs.
|
41
|
+
# It means that operations will support quotes for ENUM values embedded in
|
42
|
+
# the documents (heredoc won't be accepted).
|
43
|
+
# config.allow_string_as_enum_input = false
|
44
|
+
|
40
45
|
# Introspection is enabled by default. It is recommended to only use
|
41
46
|
# introspection during development and tests, never in production.
|
42
47
|
# This can also be set per schema level.
|
data/lib/gql_parser.so
CHANGED
Binary file
|
@@ -12,7 +12,7 @@ module Rails
|
|
12
12
|
|
13
13
|
include Helpers::Instantiable
|
14
14
|
|
15
|
-
self.field_type = Field::OutputField
|
15
|
+
self.field_type = GraphQL::Field::OutputField
|
16
16
|
self.valid_field_types = Type::Object.valid_field_types
|
17
17
|
|
18
18
|
def self.i18n_scope
|
@@ -33,7 +33,7 @@ module Rails
|
|
33
33
|
#
|
34
34
|
# Same as a +FieldSet+ but for mutation fields
|
35
35
|
MutationSet = Class.new(FieldSet)
|
36
|
-
MutationSet.field_type = Field::MutationField
|
36
|
+
MutationSet.field_type = GraphQL::Field::MutationField
|
37
37
|
MutationSet.redefine_singleton_method(:i18n_scope) { :mutation }
|
38
38
|
|
39
39
|
|
@@ -41,7 +41,7 @@ module Rails
|
|
41
41
|
#
|
42
42
|
# Same as a +FieldSet+ but for subscription fields
|
43
43
|
SubscriptionSet = Class.new(FieldSet)
|
44
|
-
SubscriptionSet.field_type = Field::SubscriptionField
|
44
|
+
SubscriptionSet.field_type = GraphQL::Field::SubscriptionField
|
45
45
|
SubscriptionSet.redefine_singleton_method(:i18n_scope) { :subscription }
|
46
46
|
end
|
47
47
|
end
|
@@ -52,7 +52,7 @@ module Rails
|
|
52
52
|
def define_field(field_name = nil, type = :any, **xargs, &block)
|
53
53
|
field_name ||= anonymous? ? '_anonymous' : begin
|
54
54
|
type_module = type_field_class.to_s.classify.pluralize
|
55
|
-
user_name = name.split(+"#{type_module}::")
|
55
|
+
user_name = name.split(+"#{type_module}::")&.at(1)
|
56
56
|
user_name ||= name.delete_prefix('GraphQL::')
|
57
57
|
user_name.tr(':', '')
|
58
58
|
end
|
@@ -137,19 +137,19 @@ module Rails
|
|
137
137
|
def import(source)
|
138
138
|
# Import an alternative declaration of a field
|
139
139
|
if source.is_a?(Module) && source <= Alternative::Query
|
140
|
-
return proxy_field(
|
140
|
+
return proxy_field(source.field)
|
141
141
|
end
|
142
142
|
|
143
143
|
case source
|
144
144
|
when Array
|
145
145
|
# Import a list of fields
|
146
|
-
source.each { |field| proxy_field(
|
146
|
+
source.each { |field| proxy_field(field) }
|
147
147
|
when Hash, Concurrent::Map
|
148
148
|
# Import a keyed list of fields
|
149
|
-
source.each_value { |field| proxy_field(
|
149
|
+
source.each_value { |field| proxy_field(field) }
|
150
150
|
when Helpers::WithFields
|
151
151
|
# Import a set of fields
|
152
|
-
source.fields.each_value { |field| proxy_field(
|
152
|
+
source.fields.each_value { |field| proxy_field(field) }
|
153
153
|
else
|
154
154
|
return if GraphQL.config.silence_import_warnings
|
155
155
|
GraphQL.logger.warn(+"Unable to import #{source.inspect} into #{self.name}.")
|
@@ -19,6 +19,8 @@ module Rails
|
|
19
19
|
# Helper method to initialize an operation given the node
|
20
20
|
def build(request, node)
|
21
21
|
request.build(const_get(node.type.to_s.classify, false), request, node)
|
22
|
+
rescue ::NameError
|
23
|
+
raise NameError, +%[Unable to initialize "#{node.type}" operation.]
|
22
24
|
end
|
23
25
|
|
24
26
|
# Rewrite the kind to always return +:operation+
|
@@ -0,0 +1,323 @@
|
|
1
|
+
schema {
|
2
|
+
query: _Query
|
3
|
+
mutation: _Mutation
|
4
|
+
}
|
5
|
+
|
6
|
+
"The Boolean scalar type represents true or false."
|
7
|
+
scalar Boolean
|
8
|
+
|
9
|
+
"The Float scalar type represents signed double-precision fractional values."
|
10
|
+
scalar Float
|
11
|
+
|
12
|
+
"""
|
13
|
+
The ID scalar type represents a unique identifier and it is serialized in the same
|
14
|
+
way as a String but it accepts both numeric and string based values as input.
|
15
|
+
"""
|
16
|
+
scalar ID
|
17
|
+
|
18
|
+
"The Int scalar type represents a signed 32-bit numeric non-fractional value."
|
19
|
+
scalar Int
|
20
|
+
|
21
|
+
"""
|
22
|
+
The String scalar type represents textual data, represented as UTF-8 character
|
23
|
+
sequences.
|
24
|
+
"""
|
25
|
+
scalar String
|
26
|
+
|
27
|
+
"The valid locations that a directive may be placed."
|
28
|
+
enum __DirectiveLocation {
|
29
|
+
"Mark as a executable directive usable on query objects."
|
30
|
+
QUERY
|
31
|
+
|
32
|
+
"Mark as a executable directive usable on mutation objects."
|
33
|
+
MUTATION
|
34
|
+
|
35
|
+
"Mark as a executable directive usable on subscription objects."
|
36
|
+
SUBSCRIPTION
|
37
|
+
|
38
|
+
"Mark as a executable directive usable on field objects."
|
39
|
+
FIELD
|
40
|
+
|
41
|
+
"Mark as a executable directive usable on fragment definition objects."
|
42
|
+
FRAGMENT_DEFINITION
|
43
|
+
|
44
|
+
"Mark as a executable directive usable on fragment spread objects."
|
45
|
+
FRAGMENT_SPREAD
|
46
|
+
|
47
|
+
"Mark as a executable directive usable on inline fragment objects."
|
48
|
+
INLINE_FRAGMENT
|
49
|
+
|
50
|
+
"Mark as a type system directive usable on schema definitions."
|
51
|
+
SCHEMA
|
52
|
+
|
53
|
+
"Mark as a type system directive usable on scalar definitions."
|
54
|
+
SCALAR
|
55
|
+
|
56
|
+
"Mark as a type system directive usable on object definitions."
|
57
|
+
OBJECT
|
58
|
+
|
59
|
+
"Mark as a type system directive usable on field definitions."
|
60
|
+
FIELD_DEFINITION
|
61
|
+
|
62
|
+
"Mark as a type system directive usable on argument definitions."
|
63
|
+
ARGUMENT_DEFINITION
|
64
|
+
|
65
|
+
"Mark as a type system directive usable on interface definitions."
|
66
|
+
INTERFACE
|
67
|
+
|
68
|
+
"Mark as a type system directive usable on union definitions."
|
69
|
+
UNION
|
70
|
+
|
71
|
+
"Mark as a type system directive usable on enum definitions."
|
72
|
+
ENUM
|
73
|
+
|
74
|
+
"Mark as a type system directive usable on enum value definitions."
|
75
|
+
ENUM_VALUE
|
76
|
+
|
77
|
+
"Mark as a type system directive usable on input object definitions."
|
78
|
+
INPUT_OBJECT
|
79
|
+
|
80
|
+
"Mark as a type system directive usable on input field definitions."
|
81
|
+
INPUT_FIELD_DEFINITION
|
82
|
+
}
|
83
|
+
|
84
|
+
"""
|
85
|
+
The fundamental unit of any GraphQL Schema is the type.
|
86
|
+
This enum enlist all the valid base types.
|
87
|
+
"""
|
88
|
+
enum __TypeKind {
|
89
|
+
"Scalar types represent primitive leaf values in a GraphQL type system.\n"
|
90
|
+
SCALAR
|
91
|
+
|
92
|
+
"Objects represent a list of named fields, each of which yield a value of a\nspecific type.\n"
|
93
|
+
OBJECT
|
94
|
+
|
95
|
+
"Interfaces represent a list of named fields and their types.\n"
|
96
|
+
INTERFACE
|
97
|
+
|
98
|
+
"Unions represent an object that could be one of a list of GraphQL Object types.\n"
|
99
|
+
UNION
|
100
|
+
|
101
|
+
"Enum types, like scalar types, also represent leaf values in a GraphQL\ntype system. However Enum types describe the set of possible values.\n"
|
102
|
+
ENUM
|
103
|
+
|
104
|
+
"Objects represent a list of named fields, each of which yield a value of\na specific type.\n"
|
105
|
+
INPUT_OBJECT
|
106
|
+
|
107
|
+
"A GraphQL list is a special collection type which declares the type of\neach item in the List (referred to as the item type of the list).\n"
|
108
|
+
LIST
|
109
|
+
|
110
|
+
"This type wraps an underlying type, and this type acts identically to that wrapped\ntype, with the exception that null is not a valid response for the wrapping type.\n"
|
111
|
+
NON_NULL
|
112
|
+
}
|
113
|
+
|
114
|
+
type Sample {
|
115
|
+
sample: String
|
116
|
+
}
|
117
|
+
|
118
|
+
type _Mutation {
|
119
|
+
sampleMutation: String
|
120
|
+
|
121
|
+
sampleMutationA: String
|
122
|
+
|
123
|
+
sampleMutationB: String
|
124
|
+
}
|
125
|
+
|
126
|
+
type _Query {
|
127
|
+
__schema: __Schema!
|
128
|
+
|
129
|
+
__type(name: String!): __Type
|
130
|
+
|
131
|
+
sampleObject: Sample
|
132
|
+
|
133
|
+
sampleQuery: String
|
134
|
+
|
135
|
+
sampleQueryA: String
|
136
|
+
|
137
|
+
sampleQueryB: String
|
138
|
+
}
|
139
|
+
|
140
|
+
"""
|
141
|
+
Directives provide a way to describe alternate runtime execution
|
142
|
+
and type validation behavior in a GraphQL document.
|
143
|
+
|
144
|
+
In some cases, you need to provide options to alter GraphQL's execution
|
145
|
+
behavior in ways field arguments will not suffice, such as conditionally
|
146
|
+
including or skipping a field. Directives provide this by describing
|
147
|
+
additional information to the executor.
|
148
|
+
"""
|
149
|
+
# Assigned to Rails::GraphQL::Directive class
|
150
|
+
type __Directive {
|
151
|
+
args: [__InputValue!]!
|
152
|
+
|
153
|
+
description: String
|
154
|
+
|
155
|
+
isRepeatable: Boolean!
|
156
|
+
|
157
|
+
locations: [__DirectiveLocation!]!
|
158
|
+
|
159
|
+
name: String!
|
160
|
+
}
|
161
|
+
|
162
|
+
"""
|
163
|
+
One of the values of an Enum object. It is unique within the Enum set
|
164
|
+
of values. It's a string representation, not a numeric representation,
|
165
|
+
of a value kept as all caps (ie. ONE_VALUE).
|
166
|
+
"""
|
167
|
+
type __EnumValue {
|
168
|
+
deprecationReason: String
|
169
|
+
|
170
|
+
description: String
|
171
|
+
|
172
|
+
isDeprecated: Boolean!
|
173
|
+
|
174
|
+
name: String!
|
175
|
+
}
|
176
|
+
|
177
|
+
"""
|
178
|
+
Fields are the elements that compose both Objects and Interfaces. Each
|
179
|
+
field in these other objects may contain arguments and always yields
|
180
|
+
a value of a specific type.
|
181
|
+
"""
|
182
|
+
# Assigned to Rails::GraphQL::Field class
|
183
|
+
type __Field {
|
184
|
+
args: [__InputValue!]!
|
185
|
+
|
186
|
+
deprecationReason: String
|
187
|
+
|
188
|
+
description: String
|
189
|
+
|
190
|
+
isDeprecated: Boolean!
|
191
|
+
|
192
|
+
name: String!
|
193
|
+
|
194
|
+
type: __Type!
|
195
|
+
}
|
196
|
+
|
197
|
+
"""
|
198
|
+
Arguments provided to Fields or Directives and the input fields of an
|
199
|
+
InputObject are represented as Input Values which describe their type
|
200
|
+
and optionally a default value.
|
201
|
+
"""
|
202
|
+
# Assigned to Rails::GraphQL::Field::InputField class
|
203
|
+
type __InputValue {
|
204
|
+
defaultValue: String
|
205
|
+
|
206
|
+
description: String
|
207
|
+
|
208
|
+
name: String!
|
209
|
+
|
210
|
+
type: __Type!
|
211
|
+
}
|
212
|
+
|
213
|
+
"""
|
214
|
+
A GraphQL service's collective type system capabilities are referred
|
215
|
+
to as that service's "schema". A schema is defined in terms of the
|
216
|
+
types and directives it supports as well as the root operation types
|
217
|
+
for each kind of operation: query, mutation, and subscription; this
|
218
|
+
determines the place in the type system where those operations begin.
|
219
|
+
"""
|
220
|
+
# Assigned to Rails::GraphQL::Schema class
|
221
|
+
type __Schema {
|
222
|
+
directives: [__Directive!]!
|
223
|
+
|
224
|
+
mutationType: __Type
|
225
|
+
|
226
|
+
queryType: __Type!
|
227
|
+
|
228
|
+
subscriptionType: __Type
|
229
|
+
|
230
|
+
types: [__Type!]!
|
231
|
+
}
|
232
|
+
|
233
|
+
"""
|
234
|
+
The fundamental unit of any GraphQL Schema is the type. There are six
|
235
|
+
kinds of named type definitions in GraphQL, and two wrapping types.
|
236
|
+
|
237
|
+
The most basic type is a +Scalar+. A scalar represents a primitive value,
|
238
|
+
like a string or an integer.
|
239
|
+
|
240
|
+
+Scalars+ and +Enums+ form the leaves in response trees; the intermediate
|
241
|
+
levels are +Object+ types, which define a set of fields.
|
242
|
+
|
243
|
+
An +Interface+ defines a list of fields; +Object+ types that implement
|
244
|
+
that interface are guaranteed to implement those fields.
|
245
|
+
|
246
|
+
A +Union+ defines a list of possible types; similar to interfaces,
|
247
|
+
whenever the type system claims a union will be returned, one of the
|
248
|
+
possible types will be returned.
|
249
|
+
|
250
|
+
Finally, oftentimes it is useful to provide complex structs as inputs
|
251
|
+
to GraphQL field arguments or variables; the +Input Object+ type allows
|
252
|
+
the schema to define exactly what data is expected.
|
253
|
+
"""
|
254
|
+
# Assigned to Rails::GraphQL::Type class
|
255
|
+
type __Type {
|
256
|
+
description: String
|
257
|
+
|
258
|
+
"ENUM only"
|
259
|
+
enumValues(includeDeprecated: Boolean = false): [__EnumValue!]
|
260
|
+
|
261
|
+
"OBJECT and INTERFACE only"
|
262
|
+
fields(includeDeprecated: Boolean = false): [__Field!]
|
263
|
+
|
264
|
+
"INPUT_OBJECT only"
|
265
|
+
inputFields: [__InputValue!]
|
266
|
+
|
267
|
+
"OBJECT only"
|
268
|
+
interfaces: [__Type!]
|
269
|
+
|
270
|
+
kind: __TypeKind!
|
271
|
+
|
272
|
+
name: String
|
273
|
+
|
274
|
+
"NON_NULL and LIST only"
|
275
|
+
ofType: __Type
|
276
|
+
|
277
|
+
"INTERFACE and UNION only"
|
278
|
+
possibleTypes: [__Type!]
|
279
|
+
|
280
|
+
specifiedByURL: String
|
281
|
+
}
|
282
|
+
|
283
|
+
"""
|
284
|
+
Indicate deprecated portions of a GraphQL service's schema, such as deprecated
|
285
|
+
fields on a type or deprecated enum values.
|
286
|
+
"""
|
287
|
+
directive @deprecated(
|
288
|
+
|
289
|
+
"""
|
290
|
+
Explain why the underlying element was marked as deprecated. If possible,
|
291
|
+
indicate what element should be used instead. This description is formatted
|
292
|
+
using Markdown syntax (as specified by [CommonMark](http://commonmark.org/)).
|
293
|
+
"""
|
294
|
+
reason: String
|
295
|
+
|
296
|
+
) on FIELD_DEFINITION | ENUM_VALUE
|
297
|
+
|
298
|
+
"Allows for conditional inclusion during execution as described by the if argument."
|
299
|
+
directive @include(
|
300
|
+
|
301
|
+
"When false, the underlying element will be automatically marked as null."
|
302
|
+
if: Boolean!
|
303
|
+
|
304
|
+
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
|
305
|
+
|
306
|
+
"Allows for conditional exclusion during execution as described by the if argument."
|
307
|
+
directive @skip(
|
308
|
+
|
309
|
+
"When true, the underlying element will be automatically marked as null."
|
310
|
+
if: Boolean!
|
311
|
+
|
312
|
+
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
|
313
|
+
|
314
|
+
"""
|
315
|
+
A built-in directive used within the type system definition language to provide
|
316
|
+
a scalar specification URL for specifying the behavior of custom scalar types.
|
317
|
+
"""
|
318
|
+
directive @specifiedBy(
|
319
|
+
|
320
|
+
"Point to a human-readable specification of the data format."
|
321
|
+
url: String!
|
322
|
+
|
323
|
+
) on SCALAR
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'config'
|
2
|
+
|
3
|
+
class GraphQL_Request_Component_OperationTest < GraphQL::TestCase
|
4
|
+
def test_build
|
5
|
+
request = Object.new
|
6
|
+
request.define_singleton_method(:build) { |klass, *| klass }
|
7
|
+
|
8
|
+
assert_equal(klass::Query, klass.build(request, new_token('', :query)))
|
9
|
+
assert_equal(klass::Mutation, klass.build(request, new_token('', :mutation)))
|
10
|
+
assert_equal(klass::Subscription, klass.build(request, new_token('', :subscription)))
|
11
|
+
|
12
|
+
assert_raises(Rails::GraphQL::NameError) { klass.build(request, new_token('', '')) }
|
13
|
+
assert_raises(Rails::GraphQL::NameError) { klass.build(request, new_token('', :field)) }
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def klass
|
19
|
+
Rails::GraphQL::Request::Component::Operation
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'integration/config'
|
2
|
+
|
3
|
+
class Integration_AlternativeTest < GraphQL::IntegrationTestCase
|
4
|
+
module Alternatives
|
5
|
+
# A regular field that is imported into an object
|
6
|
+
class SampleField < GraphQL::Field
|
7
|
+
define_field :sample, :string
|
8
|
+
|
9
|
+
def resolve
|
10
|
+
"#{current[:sample]} Resolved"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# A simple query field that can called directly
|
15
|
+
class SampleQuery < GraphQL::Query
|
16
|
+
define_field :sample_query, :string
|
17
|
+
|
18
|
+
def resolve
|
19
|
+
'Sample Query'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# A simple mutation field that can called directly
|
24
|
+
class SampleMutation < GraphQL::Mutation
|
25
|
+
define_field :sample_mutation, :string
|
26
|
+
|
27
|
+
def perform
|
28
|
+
request.extensions['mutation'] = 'Ok!'
|
29
|
+
end
|
30
|
+
|
31
|
+
def resolve
|
32
|
+
'Sample Mutation'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# A set of query fields
|
37
|
+
class SampleQuerySet < GraphQL::QuerySet
|
38
|
+
field :sample_query_a, :string
|
39
|
+
field :sample_query_b, :string
|
40
|
+
|
41
|
+
def sample_query_a
|
42
|
+
'Sample Query A'
|
43
|
+
end
|
44
|
+
|
45
|
+
def sample_query_b
|
46
|
+
'Sample Query B'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# A set of mutation fields
|
51
|
+
class SampleMutationSet < GraphQL::MutationSet
|
52
|
+
field :sample_mutation_a, :string
|
53
|
+
field :sample_mutation_b, :string
|
54
|
+
|
55
|
+
def sample_mutation_a!
|
56
|
+
request.extensions['mutationA'] = 'Ok!'
|
57
|
+
end
|
58
|
+
|
59
|
+
def sample_mutation_a
|
60
|
+
'Sample Mutation A'
|
61
|
+
end
|
62
|
+
|
63
|
+
def sample_mutation_b!
|
64
|
+
request.extensions['mutationB'] = 'Ok!'
|
65
|
+
end
|
66
|
+
|
67
|
+
def sample_mutation_b
|
68
|
+
'Sample Mutation B'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class SCHEMA < GraphQL::Schema
|
74
|
+
namespace :authorization
|
75
|
+
|
76
|
+
configure do |config|
|
77
|
+
config.enable_string_collector = false
|
78
|
+
config.default_response_format = :json
|
79
|
+
end
|
80
|
+
|
81
|
+
object 'Sample' do
|
82
|
+
import Alternatives::SampleField
|
83
|
+
end
|
84
|
+
|
85
|
+
query_fields do
|
86
|
+
import Alternatives::SampleQuery
|
87
|
+
import Alternatives::SampleQuerySet
|
88
|
+
field :sample_object, 'Sample'
|
89
|
+
end
|
90
|
+
|
91
|
+
mutation_fields do
|
92
|
+
import Alternatives::SampleMutation
|
93
|
+
import Alternatives::SampleMutationSet
|
94
|
+
end
|
95
|
+
|
96
|
+
def sample_object
|
97
|
+
{ sample: 'Sample Field' }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_query_object
|
102
|
+
result = { data: { sampleObject: { sample: 'Sample Field Resolved' } } }
|
103
|
+
assert_result(result, '{ sampleObject { sample } }')
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_query_field
|
107
|
+
assert_result({ data: { sampleQuery: 'Sample Query' } }, '{ sampleQuery }')
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_query_field_set
|
111
|
+
assert_result({ data: { sampleQueryA: 'Sample Query A' } }, '{ sampleQueryA }')
|
112
|
+
assert_result({ data: { sampleQueryB: 'Sample Query B' } }, '{ sampleQueryB }')
|
113
|
+
|
114
|
+
result = { data: { sampleQueryA: 'Sample Query A', sampleQueryB: 'Sample Query B' } }
|
115
|
+
assert_result(result, '{ sampleQueryA sampleQueryB }')
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_mutation_field
|
119
|
+
result = { data: { sampleMutation: 'Sample Mutation' }, extensions: { mutation: 'Ok!' } }
|
120
|
+
assert_result(result, 'mutation { sampleMutation }')
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_mutation_field_set
|
124
|
+
result = { data: { sampleMutationA: 'Sample Mutation A' }, extensions: { mutationA: 'Ok!' } }
|
125
|
+
assert_result(result, 'mutation { sampleMutationA }')
|
126
|
+
|
127
|
+
result = { data: { sampleMutationB: 'Sample Mutation B' }, extensions: { mutationB: 'Ok!' } }
|
128
|
+
assert_result(result, 'mutation { sampleMutationB }')
|
129
|
+
|
130
|
+
result = {
|
131
|
+
data: { sampleMutationA: 'Sample Mutation A', sampleMutationB: 'Sample Mutation B' },
|
132
|
+
extensions: { mutationA: 'Ok!', mutationB: 'Ok!' },
|
133
|
+
}
|
134
|
+
|
135
|
+
assert_result(result, 'mutation { sampleMutationA sampleMutationB }')
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_gql_introspection
|
139
|
+
result = SCHEMA.to_gql
|
140
|
+
expected = gql_file('alternative').split('').sort.join.squish
|
141
|
+
|
142
|
+
# File.write('test/assets/alternative.gql', result)
|
143
|
+
assert_equal(expected, result.split('').sort.join.squish)
|
144
|
+
end
|
145
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carlos Silva
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -339,6 +339,7 @@ files:
|
|
339
339
|
- lib/rails/graphql/type_map.rb
|
340
340
|
- lib/rails/graphql/uri.rb
|
341
341
|
- lib/rails/graphql/version.rb
|
342
|
+
- test/assets/alternative.gql
|
342
343
|
- test/assets/en.yml
|
343
344
|
- test/assets/introspection-db.json
|
344
345
|
- test/assets/introspection-mem.txt
|
@@ -349,6 +350,7 @@ files:
|
|
349
350
|
- test/assets/sqlite.gql
|
350
351
|
- test/assets/translate.gql
|
351
352
|
- test/config.rb
|
353
|
+
- test/graphql/request/component/operation_test.rb
|
352
354
|
- test/graphql/request/context_test.rb
|
353
355
|
- test/graphql/schema_test.rb
|
354
356
|
- test/graphql/source_test.rb
|
@@ -374,6 +376,7 @@ files:
|
|
374
376
|
- test/graphql/type_map_test.rb
|
375
377
|
- test/graphql/type_test.rb
|
376
378
|
- test/graphql_test.rb
|
379
|
+
- test/integration/alternative_test.rb
|
377
380
|
- test/integration/authorization_test.rb
|
378
381
|
- test/integration/config.rb
|
379
382
|
- test/integration/customization_test.rb
|
@@ -423,6 +426,7 @@ signing_key:
|
|
423
426
|
specification_version: 4
|
424
427
|
summary: GraphQL meets RoR with the most Ruby-like DSL
|
425
428
|
test_files:
|
429
|
+
- test/assets/alternative.gql
|
426
430
|
- test/assets/en.yml
|
427
431
|
- test/assets/introspection-db.json
|
428
432
|
- test/assets/introspection-mem.txt
|
@@ -433,6 +437,7 @@ test_files:
|
|
433
437
|
- test/assets/sqlite.gql
|
434
438
|
- test/assets/translate.gql
|
435
439
|
- test/config.rb
|
440
|
+
- test/graphql/request/component/operation_test.rb
|
436
441
|
- test/graphql/request/context_test.rb
|
437
442
|
- test/graphql/schema_test.rb
|
438
443
|
- test/graphql/source_test.rb
|
@@ -458,6 +463,7 @@ test_files:
|
|
458
463
|
- test/graphql/type_map_test.rb
|
459
464
|
- test/graphql/type_test.rb
|
460
465
|
- test/graphql_test.rb
|
466
|
+
- test/integration/alternative_test.rb
|
461
467
|
- test/integration/authorization_test.rb
|
462
468
|
- test/integration/config.rb
|
463
469
|
- test/integration/customization_test.rb
|