graphql 1.9.17 → 1.11.7
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.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/generators/graphql/core.rb +18 -2
- data/lib/generators/graphql/install_generator.rb +27 -0
- data/lib/generators/graphql/object_generator.rb +52 -8
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_enum.erb +2 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +2 -0
- data/lib/generators/graphql/templates/base_interface.erb +2 -0
- data/lib/generators/graphql/templates/base_mutation.erb +2 -0
- data/lib/generators/graphql/templates/base_object.erb +2 -0
- data/lib/generators/graphql/templates/base_scalar.erb +2 -0
- data/lib/generators/graphql/templates/base_union.erb +2 -0
- data/lib/generators/graphql/templates/enum.erb +2 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +14 -10
- data/lib/generators/graphql/templates/interface.erb +2 -0
- data/lib/generators/graphql/templates/loader.erb +2 -0
- data/lib/generators/graphql/templates/mutation.erb +2 -0
- data/lib/generators/graphql/templates/mutation_type.erb +2 -0
- data/lib/generators/graphql/templates/object.erb +2 -0
- data/lib/generators/graphql/templates/query_type.erb +2 -0
- data/lib/generators/graphql/templates/scalar.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +10 -0
- data/lib/generators/graphql/templates/union.erb +3 -1
- data/lib/graphql/analysis/ast/field_usage.rb +1 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +178 -67
- data/lib/graphql/analysis/ast/visitor.rb +3 -3
- data/lib/graphql/analysis/ast.rb +12 -11
- data/lib/graphql/argument.rb +10 -38
- data/lib/graphql/backtrace/table.rb +10 -2
- data/lib/graphql/backtrace/tracer.rb +2 -1
- data/lib/graphql/base_type.rb +4 -0
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +2 -2
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +5 -9
- data/lib/graphql/define/assign_enum_value.rb +1 -1
- data/lib/graphql/define/assign_global_id_field.rb +2 -2
- data/lib/graphql/define/assign_object_field.rb +3 -3
- data/lib/graphql/define/defined_object_proxy.rb +3 -0
- data/lib/graphql/define/instance_definable.rb +18 -108
- data/lib/graphql/directive/deprecated_directive.rb +1 -12
- data/lib/graphql/directive.rb +8 -1
- data/lib/graphql/enum_type.rb +5 -71
- data/lib/graphql/execution/directive_checks.rb +2 -2
- data/lib/graphql/execution/errors.rb +2 -3
- data/lib/graphql/execution/execute.rb +1 -1
- data/lib/graphql/execution/instrumentation.rb +1 -1
- data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
- data/lib/graphql/execution/interpreter/arguments.rb +51 -0
- data/lib/graphql/execution/interpreter/arguments_cache.rb +79 -0
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +25 -0
- data/lib/graphql/execution/interpreter/runtime.rb +227 -254
- data/lib/graphql/execution/interpreter.rb +34 -11
- data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
- data/lib/graphql/execution/lookahead.rb +39 -114
- data/lib/graphql/execution/multiplex.rb +14 -5
- data/lib/graphql/field.rb +14 -118
- data/lib/graphql/filter.rb +1 -1
- data/lib/graphql/function.rb +1 -30
- data/lib/graphql/input_object_type.rb +6 -24
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/interface_type.rb +7 -23
- data/lib/graphql/internal_representation/scope.rb +2 -2
- data/lib/graphql/internal_representation/visit.rb +2 -2
- data/lib/graphql/introspection/base_object.rb +2 -5
- data/lib/graphql/introspection/directive_type.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +7 -7
- data/lib/graphql/introspection/field_type.rb +7 -3
- data/lib/graphql/introspection/input_value_type.rb +33 -9
- data/lib/graphql/introspection/introspection_query.rb +6 -92
- data/lib/graphql/introspection/schema_type.rb +4 -9
- data/lib/graphql/introspection/type_type.rb +11 -7
- data/lib/graphql/introspection.rb +96 -0
- data/lib/graphql/invalid_null_error.rb +18 -0
- data/lib/graphql/language/block_string.rb +24 -5
- data/lib/graphql/language/definition_slice.rb +21 -10
- data/lib/graphql/language/document_from_schema_definition.rb +89 -64
- data/lib/graphql/language/lexer.rb +7 -3
- data/lib/graphql/language/lexer.rl +7 -3
- data/lib/graphql/language/nodes.rb +52 -91
- data/lib/graphql/language/parser.rb +719 -717
- data/lib/graphql/language/parser.y +104 -98
- data/lib/graphql/language/printer.rb +1 -1
- data/lib/graphql/language/sanitized_printer.rb +222 -0
- data/lib/graphql/language/visitor.rb +2 -2
- data/lib/graphql/language.rb +2 -1
- data/lib/graphql/name_validator.rb +6 -7
- data/lib/graphql/non_null_type.rb +0 -10
- data/lib/graphql/object_type.rb +45 -56
- data/lib/graphql/pagination/active_record_relation_connection.rb +41 -0
- data/lib/graphql/pagination/array_connection.rb +77 -0
- data/lib/graphql/pagination/connection.rb +208 -0
- data/lib/graphql/pagination/connections.rb +145 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
- data/lib/graphql/pagination/relation_connection.rb +185 -0
- data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
- data/lib/graphql/pagination.rb +6 -0
- data/lib/graphql/query/arguments.rb +4 -2
- data/lib/graphql/query/context.rb +36 -9
- data/lib/graphql/query/fingerprint.rb +26 -0
- data/lib/graphql/query/input_validation_result.rb +23 -6
- data/lib/graphql/query/literal_input.rb +30 -10
- data/lib/graphql/query/null_context.rb +5 -1
- data/lib/graphql/query/validation_pipeline.rb +4 -1
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query/variables.rb +16 -7
- data/lib/graphql/query.rb +64 -15
- data/lib/graphql/rake_task/validate.rb +3 -0
- data/lib/graphql/rake_task.rb +9 -9
- data/lib/graphql/relay/array_connection.rb +10 -12
- data/lib/graphql/relay/base_connection.rb +23 -13
- data/lib/graphql/relay/connection_type.rb +2 -1
- data/lib/graphql/relay/edge_type.rb +1 -0
- data/lib/graphql/relay/edges_instrumentation.rb +1 -1
- data/lib/graphql/relay/mutation.rb +1 -86
- data/lib/graphql/relay/node.rb +2 -2
- data/lib/graphql/relay/range_add.rb +14 -5
- data/lib/graphql/relay/relation_connection.rb +8 -10
- data/lib/graphql/scalar_type.rb +15 -59
- data/lib/graphql/schema/argument.rb +113 -11
- data/lib/graphql/schema/base_64_encoder.rb +2 -0
- data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
- data/lib/graphql/schema/build_from_definition.rb +212 -190
- data/lib/graphql/schema/built_in_types.rb +5 -5
- data/lib/graphql/schema/default_type_error.rb +2 -0
- data/lib/graphql/schema/directive/deprecated.rb +18 -0
- data/lib/graphql/schema/directive/include.rb +1 -1
- data/lib/graphql/schema/directive/skip.rb +1 -1
- data/lib/graphql/schema/directive.rb +34 -3
- data/lib/graphql/schema/enum.rb +52 -4
- data/lib/graphql/schema/enum_value.rb +6 -1
- data/lib/graphql/schema/field/connection_extension.rb +44 -20
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +200 -129
- data/lib/graphql/schema/find_inherited_value.rb +13 -0
- data/lib/graphql/schema/finder.rb +13 -11
- data/lib/graphql/schema/input_object.rb +131 -22
- data/lib/graphql/schema/interface.rb +26 -8
- data/lib/graphql/schema/introspection_system.rb +108 -37
- data/lib/graphql/schema/late_bound_type.rb +3 -2
- data/lib/graphql/schema/list.rb +47 -0
- data/lib/graphql/schema/loader.rb +134 -96
- data/lib/graphql/schema/member/base_dsl_methods.rb +29 -12
- data/lib/graphql/schema/member/build_type.rb +19 -5
- data/lib/graphql/schema/member/cached_graphql_definition.rb +5 -0
- data/lib/graphql/schema/member/has_arguments.rb +105 -5
- data/lib/graphql/schema/member/has_ast_node.rb +20 -0
- data/lib/graphql/schema/member/has_fields.rb +20 -10
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +2 -2
- data/lib/graphql/schema/member/validates_input.rb +33 -0
- data/lib/graphql/schema/member.rb +6 -0
- data/lib/graphql/schema/mutation.rb +5 -1
- data/lib/graphql/schema/non_null.rb +30 -0
- data/lib/graphql/schema/object.rb +65 -12
- data/lib/graphql/schema/possible_types.rb +9 -4
- data/lib/graphql/schema/printer.rb +0 -15
- data/lib/graphql/schema/relay_classic_mutation.rb +5 -3
- data/lib/graphql/schema/resolver/has_payload_type.rb +5 -2
- data/lib/graphql/schema/resolver.rb +26 -18
- data/lib/graphql/schema/scalar.rb +27 -3
- data/lib/graphql/schema/subscription.rb +8 -18
- data/lib/graphql/schema/timeout.rb +29 -15
- data/lib/graphql/schema/traversal.rb +1 -1
- data/lib/graphql/schema/type_expression.rb +21 -13
- data/lib/graphql/schema/type_membership.rb +2 -2
- data/lib/graphql/schema/union.rb +37 -3
- data/lib/graphql/schema/unique_within_type.rb +1 -2
- data/lib/graphql/schema/validation.rb +10 -2
- data/lib/graphql/schema/warden.rb +115 -29
- data/lib/graphql/schema.rb +903 -195
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/base_visitor.rb +10 -6
- data/lib/graphql/static_validation/literal_validator.rb +52 -27
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +43 -83
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +17 -5
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +33 -25
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +29 -21
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
- data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +2 -2
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +4 -5
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +5 -6
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
- data/lib/graphql/static_validation/type_stack.rb +2 -2
- data/lib/graphql/static_validation/validation_context.rb +1 -1
- data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
- data/lib/graphql/static_validation/validator.rb +30 -8
- data/lib/graphql/static_validation.rb +1 -0
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +89 -19
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +84 -0
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
- data/lib/graphql/subscriptions/event.rb +23 -5
- data/lib/graphql/subscriptions/instrumentation.rb +10 -5
- data/lib/graphql/subscriptions/serialize.rb +22 -4
- data/lib/graphql/subscriptions/subscription_root.rb +15 -5
- data/lib/graphql/subscriptions.rb +108 -35
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +14 -10
- data/lib/graphql/tracing/appoptics_tracing.rb +171 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +8 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +8 -0
- data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
- data/lib/graphql/tracing/platform_tracing.rb +53 -9
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
- data/lib/graphql/tracing/prometheus_tracing.rb +8 -0
- data/lib/graphql/tracing/scout_tracing.rb +19 -0
- data/lib/graphql/tracing/skylight_tracing.rb +8 -0
- data/lib/graphql/tracing/statsd_tracing.rb +42 -0
- data/lib/graphql/tracing.rb +14 -34
- data/lib/graphql/types/big_int.rb +1 -1
- data/lib/graphql/types/int.rb +9 -2
- data/lib/graphql/types/iso_8601_date.rb +3 -3
- data/lib/graphql/types/iso_8601_date_time.rb +25 -10
- data/lib/graphql/types/relay/base_connection.rb +11 -7
- data/lib/graphql/types/relay/base_edge.rb +2 -1
- data/lib/graphql/types/string.rb +7 -1
- data/lib/graphql/unauthorized_error.rb +1 -1
- data/lib/graphql/union_type.rb +13 -28
- data/lib/graphql/unresolved_type_error.rb +2 -2
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +31 -6
- data/readme.md +1 -1
- metadata +34 -9
- data/lib/graphql/literal_validation_error.rb +0 -6
@@ -5,37 +5,49 @@ module GraphQL
|
|
5
5
|
# to make a schema. This schema is missing some important details like
|
6
6
|
# `resolve` functions, but it does include the full type system,
|
7
7
|
# so you can use it to validate queries.
|
8
|
+
#
|
9
|
+
# @see GraphQL::Schema.from_introspection for a public API
|
8
10
|
module Loader
|
9
11
|
extend self
|
10
12
|
|
11
13
|
# Create schema with the result of an introspection query.
|
12
14
|
# @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
|
13
|
-
# @return [
|
14
|
-
# @deprecated Use {GraphQL::Schema.from_introspection} instead
|
15
|
+
# @return [Class] the schema described by `input`
|
15
16
|
def load(introspection_result)
|
16
17
|
schema = introspection_result.fetch("data").fetch("__schema")
|
17
18
|
|
18
19
|
types = {}
|
19
|
-
type_resolver = ->(type) {
|
20
|
+
type_resolver = ->(type) { resolve_type(types, type) }
|
20
21
|
|
21
22
|
schema.fetch("types").each do |type|
|
22
23
|
next if type.fetch("name").start_with?("__")
|
23
24
|
type_object = define_type(type, type_resolver)
|
24
|
-
types[
|
25
|
+
types[type["name"]] = type_object
|
25
26
|
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
directives = []
|
29
|
+
schema.fetch("directives", []).each do |directive|
|
30
|
+
next if GraphQL::Schema.default_directives.include?(directive.fetch("name"))
|
31
|
+
directives << define_directive(directive, type_resolver)
|
31
32
|
end
|
32
33
|
|
33
|
-
|
34
|
-
|
34
|
+
Class.new(GraphQL::Schema) do
|
35
|
+
orphan_types(types.values)
|
36
|
+
directives(directives)
|
37
|
+
|
38
|
+
def self.resolve_type(*)
|
39
|
+
raise(GraphQL::RequiredImplementationMissingError, "This schema was loaded from string, so it can't resolve types for objects")
|
40
|
+
end
|
35
41
|
|
36
|
-
|
37
|
-
|
38
|
-
|
42
|
+
[:query, :mutation, :subscription].each do |root|
|
43
|
+
type = schema["#{root}Type"]
|
44
|
+
if type
|
45
|
+
type_defn = types.fetch(type.fetch("name"))
|
46
|
+
self.public_send(root, type_defn)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
39
51
|
|
40
52
|
NullScalarCoerce = ->(val, _ctx) { val }
|
41
53
|
|
@@ -45,11 +57,17 @@ module GraphQL
|
|
45
57
|
def resolve_type(types, type)
|
46
58
|
case kind = type.fetch("kind")
|
47
59
|
when "ENUM", "INTERFACE", "INPUT_OBJECT", "OBJECT", "SCALAR", "UNION"
|
48
|
-
|
60
|
+
type_name = type.fetch("name")
|
61
|
+
type = types[type_name] || Schema::BUILT_IN_TYPES[type_name]
|
62
|
+
if type.nil?
|
63
|
+
GraphQL::Schema::LateBoundType.new(type_name)
|
64
|
+
else
|
65
|
+
type
|
66
|
+
end
|
49
67
|
when "LIST"
|
50
|
-
|
68
|
+
Schema::List.new(resolve_type(types, type.fetch("ofType")))
|
51
69
|
when "NON_NULL"
|
52
|
-
|
70
|
+
Schema::NonNull.new(resolve_type(types, type.fetch("ofType")))
|
53
71
|
else
|
54
72
|
fail GraphQL::RequiredImplementationMissingError, "#{kind} not implemented"
|
55
73
|
end
|
@@ -77,103 +95,123 @@ module GraphQL
|
|
77
95
|
end
|
78
96
|
|
79
97
|
def define_type(type, type_resolver)
|
98
|
+
loader = self
|
80
99
|
case type.fetch("kind")
|
81
100
|
when "ENUM"
|
82
|
-
|
83
|
-
|
84
|
-
description
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
description:
|
89
|
-
deprecation_reason:
|
90
|
-
value: enum["name"]
|
101
|
+
Class.new(GraphQL::Schema::Enum) do
|
102
|
+
graphql_name(type["name"])
|
103
|
+
description(type["description"])
|
104
|
+
type["enumValues"].each do |enum_value|
|
105
|
+
value(
|
106
|
+
enum_value["name"],
|
107
|
+
description: enum_value["description"],
|
108
|
+
deprecation_reason: enum_value["deprecationReason"],
|
91
109
|
)
|
92
|
-
|
110
|
+
end
|
111
|
+
end
|
93
112
|
when "INTERFACE"
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
)
|
113
|
+
Module.new do
|
114
|
+
include GraphQL::Schema::Interface
|
115
|
+
graphql_name(type["name"])
|
116
|
+
description(type["description"])
|
117
|
+
loader.build_fields(self, type["fields"] || [], type_resolver)
|
118
|
+
end
|
101
119
|
when "INPUT_OBJECT"
|
102
|
-
|
103
|
-
|
104
|
-
description
|
105
|
-
|
106
|
-
|
107
|
-
}]
|
108
|
-
)
|
120
|
+
Class.new(GraphQL::Schema::InputObject) do
|
121
|
+
graphql_name(type["name"])
|
122
|
+
description(type["description"])
|
123
|
+
loader.build_arguments(self, type["inputFields"], type_resolver)
|
124
|
+
end
|
109
125
|
when "OBJECT"
|
110
|
-
|
111
|
-
|
112
|
-
description
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
[field["name"], define_type(field.merge("kind" => "FIELD"), type_resolver)]
|
118
|
-
}]
|
119
|
-
)
|
120
|
-
when "FIELD"
|
121
|
-
GraphQL::Field.define(
|
122
|
-
name: type["name"],
|
123
|
-
type: type_resolver.call(type["type"]),
|
124
|
-
description: type["description"],
|
125
|
-
arguments: Hash[type["args"].map { |arg|
|
126
|
-
[arg["name"], define_type(arg.merge("kind" => "ARGUMENT"), type_resolver)]
|
127
|
-
}]
|
128
|
-
)
|
129
|
-
when "ARGUMENT"
|
130
|
-
kwargs = {}
|
131
|
-
if type["defaultValue"]
|
132
|
-
kwargs[:default_value] = begin
|
133
|
-
default_value_str = type["defaultValue"]
|
134
|
-
|
135
|
-
dummy_query_str = "query getStuff($var: InputObj = #{default_value_str}) { __typename }"
|
136
|
-
|
137
|
-
# Returns a `GraphQL::Language::Nodes::Document`:
|
138
|
-
dummy_query_ast = GraphQL.parse(dummy_query_str)
|
139
|
-
|
140
|
-
# Reach into the AST for the default value:
|
141
|
-
input_value_ast = dummy_query_ast.definitions.first.variables.first.default_value
|
142
|
-
|
143
|
-
extract_default_value(default_value_str, input_value_ast)
|
126
|
+
Class.new(GraphQL::Schema::Object) do
|
127
|
+
graphql_name(type["name"])
|
128
|
+
description(type["description"])
|
129
|
+
if type["interfaces"]
|
130
|
+
type["interfaces"].each do |interface_type|
|
131
|
+
implements(type_resolver.call(interface_type))
|
132
|
+
end
|
144
133
|
end
|
134
|
+
loader.build_fields(self, type["fields"], type_resolver)
|
145
135
|
end
|
146
|
-
|
147
|
-
GraphQL::Argument.define(
|
148
|
-
name: type["name"],
|
149
|
-
type: type_resolver.call(type["type"]),
|
150
|
-
description: type["description"],
|
151
|
-
method_access: false,
|
152
|
-
**kwargs
|
153
|
-
)
|
154
136
|
when "SCALAR"
|
155
137
|
type_name = type.fetch("name")
|
156
|
-
if GraphQL::Schema::BUILT_IN_TYPES[type_name]
|
157
|
-
|
138
|
+
if (builtin = GraphQL::Schema::BUILT_IN_TYPES[type_name])
|
139
|
+
builtin
|
158
140
|
else
|
159
|
-
|
160
|
-
|
161
|
-
description
|
162
|
-
|
163
|
-
)
|
141
|
+
Class.new(GraphQL::Schema::Scalar) do
|
142
|
+
graphql_name(type["name"])
|
143
|
+
description(type["description"])
|
144
|
+
end
|
164
145
|
end
|
165
146
|
when "UNION"
|
166
|
-
|
167
|
-
|
168
|
-
description
|
169
|
-
possible_types
|
170
|
-
|
171
|
-
}
|
172
|
-
)
|
147
|
+
Class.new(GraphQL::Schema::Union) do
|
148
|
+
graphql_name(type["name"])
|
149
|
+
description(type["description"])
|
150
|
+
possible_types(*(type["possibleTypes"].map { |pt| type_resolver.call(pt) }))
|
151
|
+
end
|
173
152
|
else
|
174
153
|
fail GraphQL::RequiredImplementationMissingError, "#{type["kind"]} not implemented"
|
175
154
|
end
|
176
155
|
end
|
156
|
+
|
157
|
+
def define_directive(directive, type_resolver)
|
158
|
+
loader = self
|
159
|
+
Class.new(GraphQL::Schema::Directive) do
|
160
|
+
graphql_name(directive["name"])
|
161
|
+
description(directive["description"])
|
162
|
+
locations(*directive["locations"].map(&:to_sym))
|
163
|
+
loader.build_arguments(self, directive["args"], type_resolver)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
public
|
168
|
+
|
169
|
+
def build_fields(type_defn, fields, type_resolver)
|
170
|
+
loader = self
|
171
|
+
fields.each do |field_hash|
|
172
|
+
type_defn.field(
|
173
|
+
field_hash["name"],
|
174
|
+
type: type_resolver.call(field_hash["type"]),
|
175
|
+
description: field_hash["description"],
|
176
|
+
deprecation_reason: field_hash["deprecationReason"],
|
177
|
+
null: true,
|
178
|
+
camelize: false,
|
179
|
+
) do
|
180
|
+
if field_hash["args"].any?
|
181
|
+
loader.build_arguments(self, field_hash["args"], type_resolver)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def build_arguments(arg_owner, args, type_resolver)
|
188
|
+
args.each do |arg|
|
189
|
+
kwargs = {
|
190
|
+
type: type_resolver.call(arg["type"]),
|
191
|
+
description: arg["description"],
|
192
|
+
deprecation_reason: arg["deprecationReason"],
|
193
|
+
required: false,
|
194
|
+
method_access: false,
|
195
|
+
camelize: false,
|
196
|
+
}
|
197
|
+
|
198
|
+
if arg["defaultValue"]
|
199
|
+
default_value_str = arg["defaultValue"]
|
200
|
+
|
201
|
+
dummy_query_str = "query getStuff($var: InputObj = #{default_value_str}) { __typename }"
|
202
|
+
|
203
|
+
# Returns a `GraphQL::Language::Nodes::Document`:
|
204
|
+
dummy_query_ast = GraphQL.parse(dummy_query_str)
|
205
|
+
|
206
|
+
# Reach into the AST for the default value:
|
207
|
+
input_value_ast = dummy_query_ast.definitions.first.variables.first.default_value
|
208
|
+
|
209
|
+
kwargs[:default_value] = extract_default_value(default_value_str, input_value_ast)
|
210
|
+
end
|
211
|
+
|
212
|
+
arg_owner.argument(arg["name"], **kwargs)
|
213
|
+
end
|
214
|
+
end
|
177
215
|
end
|
178
216
|
end
|
179
217
|
end
|
@@ -18,16 +18,17 @@ module GraphQL
|
|
18
18
|
# @param new_name [String]
|
19
19
|
# @return [String]
|
20
20
|
def graphql_name(new_name = nil)
|
21
|
-
|
22
|
-
when new_name
|
21
|
+
if new_name
|
23
22
|
@graphql_name = new_name
|
24
|
-
when overridden = overridden_graphql_name
|
25
|
-
overridden
|
26
23
|
else
|
27
|
-
default_graphql_name
|
24
|
+
overridden_graphql_name || default_graphql_name
|
28
25
|
end
|
29
26
|
end
|
30
27
|
|
28
|
+
def overridden_graphql_name
|
29
|
+
defined?(@graphql_name) ? @graphql_name : nil
|
30
|
+
end
|
31
|
+
|
31
32
|
# Just a convenience method to point out that people should use graphql_name instead
|
32
33
|
def name(new_name = nil)
|
33
34
|
return super() if new_name.nil?
|
@@ -45,8 +46,23 @@ module GraphQL
|
|
45
46
|
def description(new_description = nil)
|
46
47
|
if new_description
|
47
48
|
@description = new_description
|
49
|
+
elsif defined?(@description)
|
50
|
+
@description
|
48
51
|
else
|
49
|
-
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# This pushes some configurations _down_ the inheritance tree,
|
57
|
+
# in order to prevent repetitive lookups at runtime.
|
58
|
+
module ConfigurationExtension
|
59
|
+
def inherited(child_class)
|
60
|
+
child_class.introspection(introspection)
|
61
|
+
child_class.description(description)
|
62
|
+
if overridden_graphql_name
|
63
|
+
child_class.graphql_name(overridden_graphql_name)
|
64
|
+
end
|
65
|
+
super
|
50
66
|
end
|
51
67
|
end
|
52
68
|
|
@@ -54,8 +70,10 @@ module GraphQL
|
|
54
70
|
def introspection(new_introspection = nil)
|
55
71
|
if !new_introspection.nil?
|
56
72
|
@introspection = new_introspection
|
73
|
+
elsif defined?(@introspection)
|
74
|
+
@introspection
|
57
75
|
else
|
58
|
-
|
76
|
+
false
|
59
77
|
end
|
60
78
|
end
|
61
79
|
|
@@ -68,8 +86,11 @@ module GraphQL
|
|
68
86
|
def mutation(mutation_class = nil)
|
69
87
|
if mutation_class
|
70
88
|
@mutation = mutation_class
|
89
|
+
elsif defined?(@mutation)
|
90
|
+
@mutation
|
91
|
+
else
|
92
|
+
nil
|
71
93
|
end
|
72
|
-
@mutation
|
73
94
|
end
|
74
95
|
|
75
96
|
# @return [GraphQL::BaseType] Convert this type to a legacy-style object.
|
@@ -79,10 +100,6 @@ module GraphQL
|
|
79
100
|
|
80
101
|
alias :unwrap :itself
|
81
102
|
|
82
|
-
def overridden_graphql_name
|
83
|
-
@graphql_name || find_inherited_value(:overridden_graphql_name)
|
84
|
-
end
|
85
|
-
|
86
103
|
# Creates the default name for a schema member.
|
87
104
|
# The default name is the Ruby constant name,
|
88
105
|
# without any namespaces and with any `-Type` suffix removed
|
@@ -4,6 +4,10 @@ module GraphQL
|
|
4
4
|
class Member
|
5
5
|
# @api private
|
6
6
|
module BuildType
|
7
|
+
if !String.method_defined?(:match?)
|
8
|
+
using GraphQL::StringMatchBackport
|
9
|
+
end
|
10
|
+
|
7
11
|
LIST_TYPE_ERROR = "Use an array of [T] or [T, null: true] for list types; other arrays are not supported"
|
8
12
|
|
9
13
|
module_function
|
@@ -64,6 +68,8 @@ module GraphQL
|
|
64
68
|
else
|
65
69
|
raise ArgumentError, LIST_TYPE_ERROR
|
66
70
|
end
|
71
|
+
when GraphQL::Schema::NonNull, GraphQL::Schema::List
|
72
|
+
type_expr
|
67
73
|
when Module
|
68
74
|
# This is a way to check that it's the right kind of module:
|
69
75
|
if type_expr.respond_to?(:graphql_definition)
|
@@ -72,12 +78,14 @@ module GraphQL
|
|
72
78
|
# Eg `String` => GraphQL::STRING_TYPE
|
73
79
|
parse_type(type_expr.name, null: true)
|
74
80
|
end
|
81
|
+
when Proc
|
82
|
+
parse_type(type_expr.call, null: true)
|
75
83
|
when false
|
76
84
|
raise ArgumentError, "Received `false` instead of a type, maybe a `!` should be replaced with `null: true` (for fields) or `required: true` (for arguments)"
|
77
85
|
end
|
78
86
|
|
79
87
|
if return_type.nil?
|
80
|
-
raise "Unexpected type input: #{type_expr} (#{type_expr.class})"
|
88
|
+
raise "Unexpected type input: #{type_expr.inspect} (#{type_expr.class})"
|
81
89
|
end
|
82
90
|
|
83
91
|
# Apply list_type first, that way the
|
@@ -158,10 +166,16 @@ module GraphQL
|
|
158
166
|
end
|
159
167
|
|
160
168
|
def underscore(string)
|
161
|
-
string
|
162
|
-
|
163
|
-
|
164
|
-
|
169
|
+
if string.match?(/\A[a-z_]+\Z/)
|
170
|
+
return string
|
171
|
+
end
|
172
|
+
string2 = string.dup
|
173
|
+
|
174
|
+
string2.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2') # URLDecoder -> URL_Decoder
|
175
|
+
string2.gsub!(/([a-z\d])([A-Z])/,'\1_\2') # someThing -> some_Thing
|
176
|
+
string2.downcase!
|
177
|
+
|
178
|
+
string2
|
165
179
|
end
|
166
180
|
end
|
167
181
|
end
|
@@ -15,6 +15,11 @@ module GraphQL
|
|
15
15
|
@graphql_definition ||= to_graphql
|
16
16
|
end
|
17
17
|
|
18
|
+
# This is for a common interface with .define-based types
|
19
|
+
def type_class
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
18
23
|
# Wipe out the cached graphql_definition so that `.to_graphql` will be called again.
|
19
24
|
def initialize_copy(original)
|
20
25
|
super
|
@@ -43,6 +43,7 @@ module GraphQL
|
|
43
43
|
# @param arg_defn [GraphQL::Schema::Argument]
|
44
44
|
# @return [GraphQL::Schema::Argument]
|
45
45
|
def add_argument(arg_defn)
|
46
|
+
@own_arguments ||= {}
|
46
47
|
own_arguments[arg_defn.name] = arg_defn
|
47
48
|
arg_defn
|
48
49
|
end
|
@@ -58,17 +59,112 @@ module GraphQL
|
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
62
|
+
# @return [GraphQL::Schema::Argument, nil] Argument defined on this thing, fetched by name.
|
63
|
+
def get_argument(argument_name)
|
64
|
+
a = own_arguments[argument_name]
|
65
|
+
|
66
|
+
if a || !self.is_a?(Class)
|
67
|
+
a
|
68
|
+
else
|
69
|
+
for ancestor in ancestors
|
70
|
+
if ancestor.respond_to?(:own_arguments) && a = ancestor.own_arguments[argument_name]
|
71
|
+
return a
|
72
|
+
end
|
73
|
+
end
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
61
78
|
# @param new_arg_class [Class] A class to use for building argument definitions
|
62
79
|
def argument_class(new_arg_class = nil)
|
63
80
|
self.class.argument_class(new_arg_class)
|
64
81
|
end
|
65
82
|
|
83
|
+
# @api private
|
84
|
+
# @param values [Hash<String, Object>]
|
85
|
+
# @param context [GraphQL::Query::Context]
|
86
|
+
# @return [Hash<Symbol, Object>, Execution::Lazy<Hash>]
|
87
|
+
def coerce_arguments(parent_object, values, context)
|
88
|
+
# Cache this hash to avoid re-merging it
|
89
|
+
arg_defns = self.arguments
|
90
|
+
|
91
|
+
if arg_defns.empty?
|
92
|
+
GraphQL::Execution::Interpreter::Arguments.new(argument_values: nil)
|
93
|
+
else
|
94
|
+
argument_values = {}
|
95
|
+
arg_lazies = arg_defns.map do |arg_name, arg_defn|
|
96
|
+
arg_key = arg_defn.keyword
|
97
|
+
has_value = false
|
98
|
+
default_used = false
|
99
|
+
if values.key?(arg_name)
|
100
|
+
has_value = true
|
101
|
+
value = values[arg_name]
|
102
|
+
elsif values.key?(arg_key)
|
103
|
+
has_value = true
|
104
|
+
value = values[arg_key]
|
105
|
+
elsif arg_defn.default_value?
|
106
|
+
has_value = true
|
107
|
+
value = arg_defn.default_value
|
108
|
+
default_used = true
|
109
|
+
end
|
110
|
+
|
111
|
+
if has_value
|
112
|
+
loads = arg_defn.loads
|
113
|
+
loaded_value = nil
|
114
|
+
if loads && !arg_defn.from_resolver?
|
115
|
+
loaded_value = if arg_defn.type.list?
|
116
|
+
loaded_values = value.map { |val| load_application_object(arg_defn, loads, val, context) }
|
117
|
+
context.schema.after_any_lazies(loaded_values) { |result| result }
|
118
|
+
else
|
119
|
+
load_application_object(arg_defn, loads, value, context)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
coerced_value = if loaded_value
|
124
|
+
loaded_value
|
125
|
+
else
|
126
|
+
context.schema.error_handler.with_error_handling(context) do
|
127
|
+
arg_defn.type.coerce_input(value, context)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context.schema.after_lazy(coerced_value) do |coerced_value|
|
132
|
+
prepared_value = context.schema.error_handler.with_error_handling(context) do
|
133
|
+
arg_defn.prepare_value(parent_object, coerced_value, context: context)
|
134
|
+
end
|
135
|
+
|
136
|
+
# TODO code smell to access such a deeply-nested constant in a distant module
|
137
|
+
argument_values[arg_key] = GraphQL::Execution::Interpreter::ArgumentValue.new(
|
138
|
+
value: prepared_value,
|
139
|
+
definition: arg_defn,
|
140
|
+
default_used: default_used,
|
141
|
+
)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context.schema.after_any_lazies(arg_lazies) do
|
147
|
+
GraphQL::Execution::Interpreter::Arguments.new(
|
148
|
+
argument_values: argument_values,
|
149
|
+
)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def arguments_statically_coercible?
|
155
|
+
return @arguments_statically_coercible if defined?(@arguments_statically_coercible)
|
156
|
+
|
157
|
+
@arguments_statically_coercible = arguments.each_value.all?(&:statically_coercible?)
|
158
|
+
end
|
159
|
+
|
66
160
|
module ArgumentClassAccessor
|
67
161
|
def argument_class(new_arg_class = nil)
|
68
162
|
if new_arg_class
|
69
163
|
@argument_class = new_arg_class
|
164
|
+
elsif defined?(@argument_class) && @argument_class
|
165
|
+
@argument_class
|
70
166
|
else
|
71
|
-
|
167
|
+
superclass.respond_to?(:argument_class) ? superclass.argument_class : GraphQL::Schema::Argument
|
72
168
|
end
|
73
169
|
end
|
74
170
|
end
|
@@ -85,8 +181,11 @@ module GraphQL
|
|
85
181
|
context.schema.object_from_id(id, context)
|
86
182
|
end
|
87
183
|
|
88
|
-
def load_application_object(argument, lookup_as_type, id)
|
184
|
+
def load_application_object(argument, lookup_as_type, id, context)
|
89
185
|
# See if any object can be found for this ID
|
186
|
+
if id.nil?
|
187
|
+
return nil
|
188
|
+
end
|
90
189
|
loaded_application_object = object_from_id(lookup_as_type, id, context)
|
91
190
|
context.schema.after_lazy(loaded_application_object) do |application_object|
|
92
191
|
if application_object.nil?
|
@@ -97,7 +196,7 @@ module GraphQL
|
|
97
196
|
# (Don't want to allow arbitrary access to objects this way)
|
98
197
|
resolved_application_object_type = context.schema.resolve_type(lookup_as_type, application_object, context)
|
99
198
|
context.schema.after_lazy(resolved_application_object_type) do |application_object_type|
|
100
|
-
possible_object_types = context.
|
199
|
+
possible_object_types = context.warden.possible_types(lookup_as_type)
|
101
200
|
if !possible_object_types.include?(application_object_type)
|
102
201
|
err = GraphQL::LoadApplicationObjectFailedError.new(argument: argument, id: id, object: application_object)
|
103
202
|
load_application_object_failed(err)
|
@@ -105,7 +204,7 @@ module GraphQL
|
|
105
204
|
# This object was loaded successfully
|
106
205
|
# and resolved to the right type,
|
107
206
|
# now apply the `.authorized?` class method if there is one
|
108
|
-
if (class_based_type = application_object_type.
|
207
|
+
if (class_based_type = application_object_type.type_class)
|
109
208
|
context.schema.after_lazy(class_based_type.authorized?(application_object, context)) do |authed|
|
110
209
|
if authed
|
111
210
|
application_object
|
@@ -130,8 +229,9 @@ module GraphQL
|
|
130
229
|
end
|
131
230
|
end
|
132
231
|
|
232
|
+
NO_ARGUMENTS = {}.freeze
|
133
233
|
def own_arguments
|
134
|
-
@own_arguments
|
234
|
+
@own_arguments || NO_ARGUMENTS
|
135
235
|
end
|
136
236
|
end
|
137
237
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class Schema
|
4
|
+
class Member
|
5
|
+
module HasAstNode
|
6
|
+
# If this schema was parsed from a `.graphql` file (or other SDL),
|
7
|
+
# this is the AST node that defined this part of the schema.
|
8
|
+
def ast_node(new_ast_node = nil)
|
9
|
+
if new_ast_node
|
10
|
+
@ast_node = new_ast_node
|
11
|
+
elsif defined?(@ast_node)
|
12
|
+
@ast_node
|
13
|
+
else
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|