graphql 1.11.6 → 1.13.19
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 +3 -8
- data/lib/generators/graphql/enum_generator.rb +4 -10
- data/lib/generators/graphql/field_extractor.rb +31 -0
- data/lib/generators/graphql/input_generator.rb +50 -0
- data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
- data/lib/generators/graphql/install_generator.rb +17 -7
- data/lib/generators/graphql/interface_generator.rb +7 -7
- data/lib/generators/graphql/loader_generator.rb +1 -0
- data/lib/generators/graphql/mutation_create_generator.rb +22 -0
- data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
- data/lib/generators/graphql/mutation_generator.rb +6 -30
- data/lib/generators/graphql/mutation_update_generator.rb +22 -0
- data/lib/generators/graphql/object_generator.rb +12 -38
- data/lib/generators/graphql/orm_mutations_base.rb +40 -0
- data/lib/generators/graphql/relay.rb +63 -0
- data/lib/generators/graphql/relay_generator.rb +21 -0
- data/lib/generators/graphql/scalar_generator.rb +4 -2
- data/lib/generators/graphql/templates/base_connection.erb +8 -0
- data/lib/generators/graphql/templates/base_edge.erb +8 -0
- data/lib/generators/graphql/templates/enum.erb +5 -1
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -2
- data/lib/generators/graphql/templates/input.erb +9 -0
- data/lib/generators/graphql/templates/interface.erb +4 -2
- data/lib/generators/graphql/templates/mutation.erb +1 -1
- data/lib/generators/graphql/templates/mutation_create.erb +20 -0
- data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
- data/lib/generators/graphql/templates/mutation_update.erb +21 -0
- data/lib/generators/graphql/templates/node_type.erb +9 -0
- data/lib/generators/graphql/templates/object.erb +5 -3
- data/lib/generators/graphql/templates/query_type.erb +1 -3
- data/lib/generators/graphql/templates/scalar.erb +3 -1
- data/lib/generators/graphql/templates/schema.erb +19 -34
- data/lib/generators/graphql/templates/union.erb +4 -2
- data/lib/generators/graphql/type_generator.rb +47 -10
- data/lib/generators/graphql/union_generator.rb +5 -5
- data/lib/graphql/analysis/analyze_query.rb +7 -0
- data/lib/graphql/analysis/ast/field_usage.rb +28 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +10 -14
- data/lib/graphql/analysis/ast/visitor.rb +14 -5
- data/lib/graphql/analysis/ast.rb +11 -2
- data/lib/graphql/argument.rb +1 -1
- data/lib/graphql/backtrace/inspect_result.rb +0 -1
- data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
- data/lib/graphql/backtrace/table.rb +34 -3
- data/lib/graphql/backtrace/traced_error.rb +0 -1
- data/lib/graphql/backtrace/tracer.rb +40 -10
- data/lib/graphql/backtrace.rb +28 -19
- data/lib/graphql/backwards_compatibility.rb +2 -1
- data/lib/graphql/base_type.rb +6 -4
- data/lib/graphql/boolean_type.rb +1 -1
- data/lib/graphql/compatibility/execution_specification.rb +1 -0
- data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
- data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
- data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
- data/lib/graphql/dataloader/null_dataloader.rb +22 -0
- data/lib/graphql/dataloader/request.rb +19 -0
- data/lib/graphql/dataloader/request_all.rb +19 -0
- data/lib/graphql/dataloader/source.rb +155 -0
- data/lib/graphql/dataloader.rb +308 -0
- data/lib/graphql/date_encoding_error.rb +16 -0
- data/lib/graphql/define/assign_global_id_field.rb +1 -1
- data/lib/graphql/define/instance_definable.rb +48 -3
- data/lib/graphql/define/type_definer.rb +5 -5
- data/lib/graphql/deprecated_dsl.rb +18 -5
- data/lib/graphql/deprecation.rb +9 -0
- data/lib/graphql/directive/deprecated_directive.rb +1 -1
- data/lib/graphql/directive/include_directive.rb +1 -1
- data/lib/graphql/directive/skip_directive.rb +1 -1
- data/lib/graphql/directive.rb +1 -5
- data/lib/graphql/enum_type.rb +9 -3
- data/lib/graphql/execution/errors.rb +110 -7
- data/lib/graphql/execution/execute.rb +8 -1
- data/lib/graphql/execution/interpreter/arguments.rb +57 -5
- data/lib/graphql/execution/interpreter/arguments_cache.rb +49 -15
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +0 -7
- data/lib/graphql/execution/interpreter/resolve.rb +37 -25
- data/lib/graphql/execution/interpreter/runtime.rb +670 -294
- data/lib/graphql/execution/interpreter.rb +16 -16
- data/lib/graphql/execution/lazy.rb +5 -1
- data/lib/graphql/execution/lookahead.rb +2 -2
- data/lib/graphql/execution/multiplex.rb +39 -23
- data/lib/graphql/field.rb +1 -1
- data/lib/graphql/float_type.rb +1 -1
- data/lib/graphql/function.rb +4 -0
- data/lib/graphql/id_type.rb +1 -1
- data/lib/graphql/input_object_type.rb +3 -1
- data/lib/graphql/int_type.rb +1 -1
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/interface_type.rb +4 -2
- data/lib/graphql/internal_representation/document.rb +2 -2
- data/lib/graphql/internal_representation/rewrite.rb +1 -1
- data/lib/graphql/introspection/directive_location_enum.rb +2 -2
- data/lib/graphql/introspection/directive_type.rb +11 -5
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/introspection/enum_value_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +3 -3
- data/lib/graphql/introspection/input_value_type.rb +10 -4
- data/lib/graphql/introspection/schema_type.rb +10 -5
- data/lib/graphql/introspection/type_type.rb +18 -12
- data/lib/graphql/introspection.rb +5 -2
- data/lib/graphql/invalid_null_error.rb +1 -1
- data/lib/graphql/language/block_string.rb +2 -6
- data/lib/graphql/language/cache.rb +37 -0
- data/lib/graphql/language/document_from_schema_definition.rb +60 -26
- data/lib/graphql/language/lexer.rb +50 -28
- data/lib/graphql/language/lexer.rl +2 -4
- data/lib/graphql/language/nodes.rb +14 -4
- data/lib/graphql/language/parser.rb +856 -825
- data/lib/graphql/language/parser.y +28 -11
- data/lib/graphql/language/printer.rb +10 -1
- data/lib/graphql/language/sanitized_printer.rb +5 -5
- data/lib/graphql/language/token.rb +0 -4
- data/lib/graphql/language.rb +1 -0
- data/lib/graphql/name_validator.rb +0 -4
- data/lib/graphql/object_type.rb +4 -4
- data/lib/graphql/pagination/active_record_relation_connection.rb +47 -3
- data/lib/graphql/pagination/connection.rb +19 -1
- data/lib/graphql/pagination/connections.rb +45 -30
- data/lib/graphql/pagination/relation_connection.rb +69 -28
- data/lib/graphql/parse_error.rb +0 -1
- data/lib/graphql/query/arguments.rb +2 -2
- data/lib/graphql/query/arguments_cache.rb +1 -2
- data/lib/graphql/query/context.rb +22 -4
- data/lib/graphql/query/executor.rb +0 -1
- data/lib/graphql/query/input_validation_result.rb +9 -0
- data/lib/graphql/query/literal_input.rb +1 -1
- data/lib/graphql/query/null_context.rb +21 -9
- data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
- data/lib/graphql/query/serial_execution.rb +1 -0
- data/lib/graphql/query/validation_pipeline.rb +3 -4
- data/lib/graphql/query/variable_validation_error.rb +3 -3
- data/lib/graphql/query/variables.rb +35 -4
- data/lib/graphql/query.rb +20 -8
- data/lib/graphql/railtie.rb +9 -1
- data/lib/graphql/rake_task.rb +3 -0
- data/lib/graphql/relay/array_connection.rb +2 -2
- data/lib/graphql/relay/base_connection.rb +7 -0
- data/lib/graphql/relay/connection_instrumentation.rb +4 -4
- data/lib/graphql/relay/connection_type.rb +16 -3
- data/lib/graphql/relay/edges_instrumentation.rb +0 -1
- data/lib/graphql/relay/global_id_resolve.rb +1 -2
- data/lib/graphql/relay/mutation.rb +2 -1
- data/lib/graphql/relay/node.rb +3 -0
- data/lib/graphql/relay/page_info.rb +1 -1
- data/lib/graphql/relay/range_add.rb +14 -5
- data/lib/graphql/relay/type_extensions.rb +2 -0
- data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
- data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
- data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
- data/lib/graphql/rubocop.rb +4 -0
- data/lib/graphql/scalar_type.rb +3 -1
- data/lib/graphql/schema/addition.rb +247 -0
- data/lib/graphql/schema/argument.rb +177 -21
- data/lib/graphql/schema/build_from_definition.rb +150 -55
- data/lib/graphql/schema/default_type_error.rb +2 -0
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/directive/flagged.rb +57 -0
- data/lib/graphql/schema/directive/include.rb +1 -1
- data/lib/graphql/schema/directive/skip.rb +1 -1
- data/lib/graphql/schema/directive/transform.rb +14 -2
- data/lib/graphql/schema/directive.rb +103 -4
- data/lib/graphql/schema/enum.rb +72 -11
- data/lib/graphql/schema/enum_value.rb +18 -6
- data/lib/graphql/schema/field/connection_extension.rb +4 -2
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +332 -111
- data/lib/graphql/schema/field_extension.rb +89 -2
- data/lib/graphql/schema/find_inherited_value.rb +4 -1
- data/lib/graphql/schema/finder.rb +5 -5
- data/lib/graphql/schema/input_object.rb +79 -55
- data/lib/graphql/schema/interface.rb +12 -20
- data/lib/graphql/schema/introspection_system.rb +1 -1
- data/lib/graphql/schema/list.rb +21 -4
- data/lib/graphql/schema/loader.rb +11 -0
- data/lib/graphql/schema/member/accepts_definition.rb +15 -3
- data/lib/graphql/schema/member/base_dsl_methods.rb +5 -16
- data/lib/graphql/schema/member/build_type.rb +4 -7
- data/lib/graphql/schema/member/cached_graphql_definition.rb +29 -2
- data/lib/graphql/schema/member/has_arguments.rb +166 -74
- data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
- data/lib/graphql/schema/member/has_directives.rb +98 -0
- data/lib/graphql/schema/member/has_fields.rb +77 -22
- data/lib/graphql/schema/member/has_interfaces.rb +100 -0
- data/lib/graphql/schema/member/has_validators.rb +31 -0
- data/lib/graphql/schema/member/instrumentation.rb +0 -1
- data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
- data/lib/graphql/schema/member/validates_input.rb +2 -2
- data/lib/graphql/schema/member.rb +5 -0
- data/lib/graphql/schema/middleware_chain.rb +1 -1
- data/lib/graphql/schema/non_null.rb +9 -3
- data/lib/graphql/schema/object.rb +40 -80
- data/lib/graphql/schema/printer.rb +16 -20
- data/lib/graphql/schema/relay_classic_mutation.rb +38 -4
- data/lib/graphql/schema/resolver/has_payload_type.rb +29 -2
- data/lib/graphql/schema/resolver.rb +110 -64
- data/lib/graphql/schema/scalar.rb +18 -2
- data/lib/graphql/schema/subscription.rb +55 -9
- data/lib/graphql/schema/timeout_middleware.rb +3 -1
- data/lib/graphql/schema/traversal.rb +1 -1
- data/lib/graphql/schema/type_expression.rb +1 -1
- data/lib/graphql/schema/type_membership.rb +18 -4
- data/lib/graphql/schema/union.rb +8 -1
- data/lib/graphql/schema/validation.rb +4 -2
- data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
- data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
- data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
- data/lib/graphql/schema/validator/format_validator.rb +48 -0
- data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
- data/lib/graphql/schema/validator/length_validator.rb +59 -0
- data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
- data/lib/graphql/schema/validator/required_validator.rb +82 -0
- data/lib/graphql/schema/validator.rb +171 -0
- data/lib/graphql/schema/warden.rb +126 -53
- data/lib/graphql/schema.rb +262 -281
- data/lib/graphql/static_validation/all_rules.rb +2 -0
- data/lib/graphql/static_validation/base_visitor.rb +9 -6
- data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
- data/lib/graphql/static_validation/error.rb +3 -1
- data/lib/graphql/static_validation/literal_validator.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +4 -2
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +6 -2
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +90 -47
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- 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/query_root_exists.rb +17 -0
- data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -2
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +14 -8
- data/lib/graphql/static_validation/validation_context.rb +12 -2
- data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
- data/lib/graphql/static_validation/validator.rb +41 -10
- data/lib/graphql/static_validation.rb +1 -0
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/string_type.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +39 -8
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +0 -3
- data/lib/graphql/subscriptions/event.rb +68 -32
- data/lib/graphql/subscriptions/instrumentation.rb +0 -1
- data/lib/graphql/subscriptions/serialize.rb +34 -5
- data/lib/graphql/subscriptions/subscription_root.rb +1 -1
- data/lib/graphql/subscriptions.rb +34 -39
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -21
- data/lib/graphql/tracing/appoptics_tracing.rb +3 -1
- data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +24 -2
- data/lib/graphql/tracing/notifications_tracing.rb +59 -0
- data/lib/graphql/tracing/platform_tracing.rb +24 -12
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
- data/lib/graphql/tracing/skylight_tracing.rb +1 -1
- data/lib/graphql/tracing.rb +2 -2
- data/lib/graphql/types/big_int.rb +5 -1
- data/lib/graphql/types/int.rb +10 -3
- data/lib/graphql/types/iso_8601_date.rb +13 -5
- data/lib/graphql/types/iso_8601_date_time.rb +8 -1
- data/lib/graphql/types/relay/base_connection.rb +6 -91
- data/lib/graphql/types/relay/base_edge.rb +2 -34
- data/lib/graphql/types/relay/connection_behaviors.rb +174 -0
- data/lib/graphql/types/relay/default_relay.rb +31 -0
- data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
- data/lib/graphql/types/relay/has_node_field.rb +41 -0
- data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
- data/lib/graphql/types/relay/node.rb +2 -4
- data/lib/graphql/types/relay/node_behaviors.rb +15 -0
- data/lib/graphql/types/relay/node_field.rb +3 -22
- data/lib/graphql/types/relay/nodes_field.rb +16 -18
- data/lib/graphql/types/relay/page_info.rb +2 -14
- data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
- data/lib/graphql/types/relay.rb +11 -3
- data/lib/graphql/types/string.rb +8 -2
- data/lib/graphql/unauthorized_error.rb +1 -1
- data/lib/graphql/union_type.rb +3 -1
- data/lib/graphql/upgrader/member.rb +1 -0
- data/lib/graphql/upgrader/schema.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +68 -37
- data/readme.md +3 -6
- metadata +83 -113
- data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
- data/lib/graphql/types/relay/base_field.rb +0 -22
- data/lib/graphql/types/relay/base_interface.rb +0 -29
- data/lib/graphql/types/relay/base_object.rb +0 -26
- /data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +0 -0
- /data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +0 -0
@@ -24,100 +24,15 @@ module GraphQL
|
|
24
24
|
# end
|
25
25
|
# class Types::PostConnection < Types::BaseConnection
|
26
26
|
# edge_type(Types::PostEdge)
|
27
|
+
# edges_nullable(true)
|
28
|
+
# edge_nullable(true)
|
29
|
+
# node_nullable(true)
|
30
|
+
# has_nodes_field(true)
|
27
31
|
# end
|
28
32
|
#
|
29
33
|
# @see Relay::BaseEdge for edge types
|
30
|
-
class BaseConnection <
|
31
|
-
|
32
|
-
def_delegators :@object, :cursor_from_node, :parent
|
33
|
-
|
34
|
-
class << self
|
35
|
-
# @return [Class]
|
36
|
-
attr_reader :node_type
|
37
|
-
|
38
|
-
# @return [Class]
|
39
|
-
attr_reader :edge_class
|
40
|
-
|
41
|
-
# Configure this connection to return `edges` and `nodes` based on `edge_type_class`.
|
42
|
-
#
|
43
|
-
# This method will use the inputs to create:
|
44
|
-
# - `edges` field
|
45
|
-
# - `nodes` field
|
46
|
-
# - description
|
47
|
-
#
|
48
|
-
# It's called when you subclass this base connection, trying to use the
|
49
|
-
# class name to set defaults. You can call it again in the class definition
|
50
|
-
# to override the default (or provide a value, if the default lookup failed).
|
51
|
-
def edge_type(edge_type_class, edge_class: GraphQL::Relay::Edge, node_type: edge_type_class.node_type, nodes_field: true, node_nullable: true)
|
52
|
-
# Set this connection's graphql name
|
53
|
-
node_type_name = node_type.graphql_name
|
54
|
-
|
55
|
-
@node_type = node_type
|
56
|
-
@edge_type = edge_type_class
|
57
|
-
@edge_class = edge_class
|
58
|
-
|
59
|
-
field :edges, [edge_type_class, null: true],
|
60
|
-
null: true,
|
61
|
-
description: "A list of edges.",
|
62
|
-
edge_class: edge_class
|
63
|
-
|
64
|
-
define_nodes_field(node_nullable) if nodes_field
|
65
|
-
|
66
|
-
description("The connection type for #{node_type_name}.")
|
67
|
-
end
|
68
|
-
|
69
|
-
# Filter this list according to the way its node type would scope them
|
70
|
-
def scope_items(items, context)
|
71
|
-
node_type.scope_items(items, context)
|
72
|
-
end
|
73
|
-
|
74
|
-
# Add the shortcut `nodes` field to this connection and its subclasses
|
75
|
-
def nodes_field
|
76
|
-
define_nodes_field
|
77
|
-
end
|
78
|
-
|
79
|
-
def authorized?(obj, ctx)
|
80
|
-
true # Let nodes be filtered out
|
81
|
-
end
|
82
|
-
|
83
|
-
def accessible?(ctx)
|
84
|
-
node_type.accessible?(ctx)
|
85
|
-
end
|
86
|
-
|
87
|
-
def visible?(ctx)
|
88
|
-
node_type.visible?(ctx)
|
89
|
-
end
|
90
|
-
|
91
|
-
private
|
92
|
-
|
93
|
-
def define_nodes_field(nullable = true)
|
94
|
-
type = nullable ? [@node_type, null: true] : [@node_type]
|
95
|
-
field :nodes, type,
|
96
|
-
null: nullable,
|
97
|
-
description: "A list of nodes."
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
field :page_info, GraphQL::Types::Relay::PageInfo, null: false, description: "Information to aid in pagination."
|
102
|
-
|
103
|
-
# By default this calls through to the ConnectionWrapper's edge nodes method,
|
104
|
-
# but sometimes you need to override it to support the `nodes` field
|
105
|
-
def nodes
|
106
|
-
@object.edge_nodes
|
107
|
-
end
|
108
|
-
|
109
|
-
def edges
|
110
|
-
if @object.is_a?(GraphQL::Pagination::Connection)
|
111
|
-
@object.edges
|
112
|
-
elsif context.interpreter?
|
113
|
-
context.schema.after_lazy(object.edge_nodes) do |nodes|
|
114
|
-
nodes.map { |n| self.class.edge_class.new(n, object) }
|
115
|
-
end
|
116
|
-
else
|
117
|
-
# This is done by edges_instrumentation
|
118
|
-
@object.edge_nodes
|
119
|
-
end
|
120
|
-
end
|
34
|
+
class BaseConnection < Schema::Object
|
35
|
+
include ConnectionBehaviors
|
121
36
|
end
|
122
37
|
end
|
123
38
|
end
|
@@ -21,40 +21,8 @@ module GraphQL
|
|
21
21
|
# end
|
22
22
|
#
|
23
23
|
# @see {Relay::BaseConnection} for connection types
|
24
|
-
class BaseEdge <
|
25
|
-
|
26
|
-
|
27
|
-
class << self
|
28
|
-
# Get or set the Object type that this edge wraps.
|
29
|
-
#
|
30
|
-
# @param node_type [Class] A `Schema::Object` subclass
|
31
|
-
# @param null [Boolean]
|
32
|
-
def node_type(node_type = nil, null: true)
|
33
|
-
if node_type
|
34
|
-
@node_type = node_type
|
35
|
-
# Add a default `node` field
|
36
|
-
field :node, node_type, null: null, description: "The item at the end of the edge."
|
37
|
-
end
|
38
|
-
@node_type
|
39
|
-
end
|
40
|
-
|
41
|
-
def authorized?(obj, ctx)
|
42
|
-
true
|
43
|
-
end
|
44
|
-
|
45
|
-
def accessible?(ctx)
|
46
|
-
node_type.accessible?(ctx)
|
47
|
-
end
|
48
|
-
|
49
|
-
def visible?(ctx)
|
50
|
-
node_type.visible?(ctx)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
field :cursor, String,
|
56
|
-
null: false,
|
57
|
-
description: "A cursor for use in pagination."
|
24
|
+
class BaseEdge < GraphQL::Schema::Object
|
25
|
+
include Types::Relay::EdgeBehaviors
|
58
26
|
end
|
59
27
|
end
|
60
28
|
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Types
|
5
|
+
module Relay
|
6
|
+
module ConnectionBehaviors
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators :@object, :cursor_from_node, :parent
|
9
|
+
|
10
|
+
def self.included(child_class)
|
11
|
+
child_class.extend(ClassMethods)
|
12
|
+
child_class.extend(Relay::DefaultRelay)
|
13
|
+
child_class.default_relay(true)
|
14
|
+
child_class.has_nodes_field(true)
|
15
|
+
child_class.node_nullable(true)
|
16
|
+
child_class.edges_nullable(true)
|
17
|
+
child_class.edge_nullable(true)
|
18
|
+
add_page_info_field(child_class)
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
# @return [Class]
|
23
|
+
attr_reader :node_type
|
24
|
+
|
25
|
+
# @return [Class]
|
26
|
+
attr_reader :edge_class
|
27
|
+
|
28
|
+
# Configure this connection to return `edges` and `nodes` based on `edge_type_class`.
|
29
|
+
#
|
30
|
+
# This method will use the inputs to create:
|
31
|
+
# - `edges` field
|
32
|
+
# - `nodes` field
|
33
|
+
# - description
|
34
|
+
#
|
35
|
+
# It's called when you subclass this base connection, trying to use the
|
36
|
+
# class name to set defaults. You can call it again in the class definition
|
37
|
+
# to override the default (or provide a value, if the default lookup failed).
|
38
|
+
# @param field_options [Hash] Any extra keyword arguments to pass to the `field :edges, ...` and `field :nodes, ...` configurations
|
39
|
+
def edge_type(edge_type_class, edge_class: GraphQL::Relay::Edge, node_type: edge_type_class.node_type, nodes_field: self.has_nodes_field, node_nullable: self.node_nullable, edges_nullable: self.edges_nullable, edge_nullable: self.edge_nullable, field_options: nil)
|
40
|
+
# Set this connection's graphql name
|
41
|
+
node_type_name = node_type.graphql_name
|
42
|
+
|
43
|
+
@node_type = node_type
|
44
|
+
@edge_type = edge_type_class
|
45
|
+
@edge_class = edge_class
|
46
|
+
|
47
|
+
base_field_options = {
|
48
|
+
name: :edges,
|
49
|
+
type: [edge_type_class, null: edge_nullable],
|
50
|
+
null: edges_nullable,
|
51
|
+
description: "A list of edges.",
|
52
|
+
legacy_edge_class: edge_class, # This is used by the old runtime only, for EdgesInstrumentation
|
53
|
+
connection: false,
|
54
|
+
}
|
55
|
+
|
56
|
+
if field_options
|
57
|
+
base_field_options.merge!(field_options)
|
58
|
+
end
|
59
|
+
|
60
|
+
field(**base_field_options)
|
61
|
+
|
62
|
+
define_nodes_field(node_nullable, field_options: field_options) if nodes_field
|
63
|
+
|
64
|
+
description("The connection type for #{node_type_name}.")
|
65
|
+
end
|
66
|
+
|
67
|
+
# Filter this list according to the way its node type would scope them
|
68
|
+
def scope_items(items, context)
|
69
|
+
node_type.scope_items(items, context)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Add the shortcut `nodes` field to this connection and its subclasses
|
73
|
+
def nodes_field(node_nullable: self.node_nullable, field_options: nil)
|
74
|
+
define_nodes_field(node_nullable, field_options: field_options)
|
75
|
+
end
|
76
|
+
|
77
|
+
def authorized?(obj, ctx)
|
78
|
+
true # Let nodes be filtered out
|
79
|
+
end
|
80
|
+
|
81
|
+
def accessible?(ctx)
|
82
|
+
node_type.accessible?(ctx)
|
83
|
+
end
|
84
|
+
|
85
|
+
def visible?(ctx)
|
86
|
+
# if this is an abstract base class, there may be no `node_type`
|
87
|
+
node_type ? node_type.visible?(ctx) : super
|
88
|
+
end
|
89
|
+
|
90
|
+
# Set the default `node_nullable` for this class and its child classes. (Defaults to `true`.)
|
91
|
+
# Use `node_nullable(false)` in your base class to make non-null `node` and `nodes` fields.
|
92
|
+
def node_nullable(new_value = nil)
|
93
|
+
if new_value.nil?
|
94
|
+
defined?(@node_nullable) ? @node_nullable : superclass.node_nullable
|
95
|
+
else
|
96
|
+
@node_nullable = new_value
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Set the default `edges_nullable` for this class and its child classes. (Defaults to `true`.)
|
101
|
+
# Use `edges_nullable(false)` in your base class to make non-null `edges` fields.
|
102
|
+
def edges_nullable(new_value = nil)
|
103
|
+
if new_value.nil?
|
104
|
+
defined?(@edges_nullable) ? @edges_nullable : superclass.edges_nullable
|
105
|
+
else
|
106
|
+
@edges_nullable = new_value
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Set the default `edge_nullable` for this class and its child classes. (Defaults to `true`.)
|
111
|
+
# Use `edge_nullable(false)` in your base class to make non-null `edge` fields.
|
112
|
+
def edge_nullable(new_value = nil)
|
113
|
+
if new_value.nil?
|
114
|
+
defined?(@edge_nullable) ? @edge_nullable : superclass.edge_nullable
|
115
|
+
else
|
116
|
+
@edge_nullable = new_value
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Set the default `nodes_field` for this class and its child classes. (Defaults to `true`.)
|
121
|
+
# Use `nodes_field(false)` in your base class to prevent adding of a nodes field.
|
122
|
+
def has_nodes_field(new_value = nil)
|
123
|
+
if new_value.nil?
|
124
|
+
defined?(@nodes_field) ? @nodes_field : superclass.has_nodes_field
|
125
|
+
else
|
126
|
+
@nodes_field = new_value
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def define_nodes_field(nullable, field_options: nil)
|
133
|
+
base_field_options = {
|
134
|
+
name: :nodes,
|
135
|
+
type: [@node_type, null: nullable],
|
136
|
+
null: nullable,
|
137
|
+
description: "A list of nodes.",
|
138
|
+
connection: false,
|
139
|
+
}
|
140
|
+
if field_options
|
141
|
+
base_field_options.merge!(field_options)
|
142
|
+
end
|
143
|
+
field(**base_field_options)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
class << self
|
148
|
+
def add_page_info_field(obj_type)
|
149
|
+
obj_type.field :page_info, GraphQL::Types::Relay::PageInfo, null: false, description: "Information to aid in pagination."
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# By default this calls through to the ConnectionWrapper's edge nodes method,
|
154
|
+
# but sometimes you need to override it to support the `nodes` field
|
155
|
+
def nodes
|
156
|
+
@object.edge_nodes
|
157
|
+
end
|
158
|
+
|
159
|
+
def edges
|
160
|
+
if @object.is_a?(GraphQL::Pagination::Connection)
|
161
|
+
@object.edges
|
162
|
+
elsif context.interpreter?
|
163
|
+
context.schema.after_lazy(object.edge_nodes) do |nodes|
|
164
|
+
nodes.map { |n| self.class.edge_class.new(n, object) }
|
165
|
+
end
|
166
|
+
else
|
167
|
+
# This is done by edges_instrumentation
|
168
|
+
@object.edge_nodes
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Types
|
5
|
+
module Relay
|
6
|
+
module DefaultRelay
|
7
|
+
def self.extended(child_class)
|
8
|
+
child_class.default_relay(true)
|
9
|
+
end
|
10
|
+
|
11
|
+
def default_relay(new_value)
|
12
|
+
@default_relay = new_value
|
13
|
+
end
|
14
|
+
|
15
|
+
def default_relay?
|
16
|
+
!!@default_relay
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_graphql
|
20
|
+
type_defn = if method(:to_graphql).super_method.arity
|
21
|
+
super(silence_deprecation_warning: true)
|
22
|
+
else
|
23
|
+
super
|
24
|
+
end
|
25
|
+
type_defn.default_relay = default_relay?
|
26
|
+
type_defn
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Types
|
5
|
+
module Relay
|
6
|
+
module EdgeBehaviors
|
7
|
+
def self.included(child_class)
|
8
|
+
child_class.description("An edge in a connection.")
|
9
|
+
child_class.field(:cursor, String, null: false, description: "A cursor for use in pagination.")
|
10
|
+
child_class.extend(ClassMethods)
|
11
|
+
child_class.node_nullable(true)
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
# Get or set the Object type that this edge wraps.
|
16
|
+
#
|
17
|
+
# @param node_type [Class] A `Schema::Object` subclass
|
18
|
+
# @param null [Boolean]
|
19
|
+
# @param field_options [Hash] Any extra arguments to pass to the `field :node` configuration
|
20
|
+
def node_type(node_type = nil, null: self.node_nullable, field_options: nil)
|
21
|
+
if node_type
|
22
|
+
@node_type = node_type
|
23
|
+
# Add a default `node` field
|
24
|
+
base_field_options = {
|
25
|
+
name: :node,
|
26
|
+
type: node_type,
|
27
|
+
null: null,
|
28
|
+
description: "The item at the end of the edge.",
|
29
|
+
connection: false,
|
30
|
+
}
|
31
|
+
if field_options
|
32
|
+
base_field_options.merge!(field_options)
|
33
|
+
end
|
34
|
+
field(**base_field_options)
|
35
|
+
end
|
36
|
+
@node_type
|
37
|
+
end
|
38
|
+
|
39
|
+
def authorized?(obj, ctx)
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
def accessible?(ctx)
|
44
|
+
node_type.accessible?(ctx)
|
45
|
+
end
|
46
|
+
|
47
|
+
def visible?(ctx)
|
48
|
+
node_type.visible?(ctx)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Set the default `node_nullable` for this class and its child classes. (Defaults to `true`.)
|
52
|
+
# Use `node_nullable(false)` in your base class to make non-null `node` field.
|
53
|
+
def node_nullable(new_value = nil)
|
54
|
+
if new_value.nil?
|
55
|
+
defined?(@node_nullable) ? @node_nullable : superclass.node_nullable
|
56
|
+
else
|
57
|
+
@node_nullable = new_value
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Types
|
5
|
+
module Relay
|
6
|
+
# Include this module to your root Query type to get a Relay-compliant `node(id: ID!): Node` field that uses the schema's `object_from_id` hook.
|
7
|
+
module HasNodeField
|
8
|
+
def self.included(child_class)
|
9
|
+
child_class.field(**field_options, &field_block)
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def field_options
|
14
|
+
{
|
15
|
+
name: "node",
|
16
|
+
type: GraphQL::Types::Relay::Node,
|
17
|
+
null: true,
|
18
|
+
description: "Fetches an object given its ID.",
|
19
|
+
relay_node_field: true,
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def field_block
|
24
|
+
Proc.new {
|
25
|
+
argument :id, "ID!",
|
26
|
+
description: "ID of the object."
|
27
|
+
|
28
|
+
def resolve(obj, args, ctx)
|
29
|
+
ctx.schema.object_from_id(args[:id], ctx)
|
30
|
+
end
|
31
|
+
|
32
|
+
def resolve_field(obj, args, ctx)
|
33
|
+
resolve(obj, args, ctx)
|
34
|
+
end
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Types
|
5
|
+
module Relay
|
6
|
+
# Include this module to your root Query type to get a Relay-style `nodes(id: ID!): [Node]` field that uses the schema's `object_from_id` hook.
|
7
|
+
module HasNodesField
|
8
|
+
def self.included(child_class)
|
9
|
+
child_class.field(**field_options, &field_block)
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def field_options
|
14
|
+
{
|
15
|
+
name: "nodes",
|
16
|
+
type: [GraphQL::Types::Relay::Node, null: true],
|
17
|
+
null: false,
|
18
|
+
description: "Fetches a list of objects given a list of IDs.",
|
19
|
+
relay_nodes_field: true,
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def field_block
|
24
|
+
Proc.new {
|
25
|
+
argument :ids, "[ID!]!",
|
26
|
+
description: "IDs of the objects."
|
27
|
+
|
28
|
+
def resolve(obj, args, ctx)
|
29
|
+
args[:ids].map { |id| ctx.schema.object_from_id(id, ctx) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def resolve_field(obj, args, ctx)
|
33
|
+
resolve(obj, args, ctx)
|
34
|
+
end
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -7,10 +7,8 @@ module GraphQL
|
|
7
7
|
# or you can take it as inspiration for your own implementation
|
8
8
|
# of the `Node` interface.
|
9
9
|
module Node
|
10
|
-
include
|
11
|
-
|
12
|
-
description "An object with an ID."
|
13
|
-
field(:id, ID, null: false, description: "ID of the object.")
|
10
|
+
include GraphQL::Schema::Interface
|
11
|
+
include Types::Relay::NodeBehaviors
|
14
12
|
end
|
15
13
|
end
|
16
14
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Types
|
5
|
+
module Relay
|
6
|
+
module NodeBehaviors
|
7
|
+
def self.included(child_module)
|
8
|
+
child_module.extend(DefaultRelay)
|
9
|
+
child_module.description("An object with an ID.")
|
10
|
+
child_module.field(:id, ID, null: false, description: "ID of the object.")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -2,11 +2,10 @@
|
|
2
2
|
module GraphQL
|
3
3
|
module Types
|
4
4
|
module Relay
|
5
|
-
#
|
6
|
-
# or use it for inspiration for your own field definition.
|
5
|
+
# Don't use this field directly, instead, use one of these approaches:
|
7
6
|
#
|
8
7
|
# @example Adding this field directly
|
9
|
-
#
|
8
|
+
# include GraphQL::Types::Relay::HasNodeField
|
10
9
|
#
|
11
10
|
# @example Implementing a similar field in your own Query root
|
12
11
|
#
|
@@ -19,25 +18,7 @@ module GraphQL
|
|
19
18
|
# context.schema.object_from_id(id, context)
|
20
19
|
# end
|
21
20
|
#
|
22
|
-
|
23
|
-
name: "node",
|
24
|
-
owner: nil,
|
25
|
-
type: GraphQL::Types::Relay::Node,
|
26
|
-
null: true,
|
27
|
-
description: "Fetches an object given its ID.",
|
28
|
-
relay_node_field: true,
|
29
|
-
) do
|
30
|
-
argument :id, "ID!", required: true,
|
31
|
-
description: "ID of the object."
|
32
|
-
|
33
|
-
def resolve(obj, args, ctx)
|
34
|
-
ctx.schema.object_from_id(args[:id], ctx)
|
35
|
-
end
|
36
|
-
|
37
|
-
def resolve_field(obj, args, ctx)
|
38
|
-
resolve(obj, args, ctx)
|
39
|
-
end
|
40
|
-
end
|
21
|
+
DeprecatedNodeField = GraphQL::Schema::Field.new(owner: nil, **HasNodeField.field_options, &HasNodeField.field_block)
|
41
22
|
end
|
42
23
|
end
|
43
24
|
end
|
@@ -2,11 +2,10 @@
|
|
2
2
|
module GraphQL
|
3
3
|
module Types
|
4
4
|
module Relay
|
5
|
-
#
|
6
|
-
# or use it for inspiration for your own field definition.
|
5
|
+
# Don't use this directly, instead, use one of these:
|
7
6
|
#
|
8
7
|
# @example Adding this field directly
|
9
|
-
#
|
8
|
+
# include GraphQL::Types::Relay::HasNodesField
|
10
9
|
#
|
11
10
|
# @example Implementing a similar field in your own Query root
|
12
11
|
#
|
@@ -21,25 +20,24 @@ module GraphQL
|
|
21
20
|
# end
|
22
21
|
# end
|
23
22
|
#
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
description: "Fetches a list of objects given a list of IDs.",
|
30
|
-
relay_nodes_field: true,
|
31
|
-
) do
|
32
|
-
argument :ids, "[ID!]!", required: true,
|
33
|
-
description: "IDs of the objects."
|
23
|
+
def self.const_missing(const_name)
|
24
|
+
if const_name == :NodesField
|
25
|
+
message = "NodesField is deprecated, use `include GraphQL::Types::Relay::HasNodesField` instead."
|
26
|
+
message += "\n(referenced from #{caller(1, 1).first})"
|
27
|
+
GraphQL::Deprecation.warn(message)
|
34
28
|
|
35
|
-
|
36
|
-
|
37
|
-
|
29
|
+
DeprecatedNodesField
|
30
|
+
elsif const_name == :NodeField
|
31
|
+
message = "NodeField is deprecated, use `include GraphQL::Types::Relay::HasNodeField` instead."
|
32
|
+
message += "\n(referenced from #{caller(1, 1).first})"
|
33
|
+
GraphQL::Deprecation.warn(message)
|
38
34
|
|
39
|
-
|
40
|
-
|
35
|
+
DeprecatedNodeField
|
36
|
+
else
|
37
|
+
super
|
41
38
|
end
|
42
39
|
end
|
40
|
+
DeprecatedNodesField = GraphQL::Schema::Field.new(owner: nil, **HasNodesField.field_options, &HasNodesField.field_block)
|
43
41
|
end
|
44
42
|
end
|
45
43
|
end
|
@@ -3,20 +3,8 @@ module GraphQL
|
|
3
3
|
module Types
|
4
4
|
module Relay
|
5
5
|
# The return type of a connection's `pageInfo` field
|
6
|
-
class PageInfo <
|
7
|
-
|
8
|
-
description "Information about pagination in a connection."
|
9
|
-
field :has_next_page, Boolean, null: false,
|
10
|
-
description: "When paginating forwards, are there more items?"
|
11
|
-
|
12
|
-
field :has_previous_page, Boolean, null: false,
|
13
|
-
description: "When paginating backwards, are there more items?"
|
14
|
-
|
15
|
-
field :start_cursor, String, null: true,
|
16
|
-
description: "When paginating backwards, the cursor to continue."
|
17
|
-
|
18
|
-
field :end_cursor, String, null: true,
|
19
|
-
description: "When paginating forwards, the cursor to continue."
|
6
|
+
class PageInfo < GraphQL::Schema::Object
|
7
|
+
include PageInfoBehaviors
|
20
8
|
end
|
21
9
|
end
|
22
10
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Types
|
4
|
+
module Relay
|
5
|
+
module PageInfoBehaviors
|
6
|
+
def self.included(child_class)
|
7
|
+
child_class.extend GraphQL::Types::Relay::DefaultRelay
|
8
|
+
|
9
|
+
child_class.description "Information about pagination in a connection."
|
10
|
+
child_class.field :has_next_page, Boolean, null: false,
|
11
|
+
description: "When paginating forwards, are there more items?"
|
12
|
+
|
13
|
+
child_class.field :has_previous_page, Boolean, null: false,
|
14
|
+
description: "When paginating backwards, are there more items?"
|
15
|
+
|
16
|
+
child_class.field :start_cursor, String, null: true,
|
17
|
+
description: "When paginating backwards, the cursor to continue."
|
18
|
+
|
19
|
+
child_class.field :end_cursor, String, null: true,
|
20
|
+
description: "When paginating forwards, the cursor to continue."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|