graphql 2.0.32 → 2.5.22
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/lib/generators/graphql/detailed_trace_generator.rb +77 -0
- data/lib/generators/graphql/install/mutation_root_generator.rb +2 -2
- data/lib/generators/graphql/install/templates/base_mutation.erb +2 -0
- data/lib/generators/graphql/install/templates/mutation_type.erb +2 -0
- data/lib/generators/graphql/install_generator.rb +49 -0
- data/lib/generators/graphql/orm_mutations_base.rb +1 -1
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_connection.erb +2 -0
- data/lib/generators/graphql/templates/base_edge.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_object.erb +2 -0
- data/lib/generators/graphql/templates/base_resolver.erb +8 -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/create_graphql_detailed_traces.erb +10 -0
- data/lib/generators/graphql/templates/graphql_controller.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/node_type.erb +2 -0
- data/lib/generators/graphql/templates/query_type.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +5 -0
- data/lib/generators/graphql/type_generator.rb +1 -1
- data/lib/graphql/analysis/analyzer.rb +90 -0
- data/lib/graphql/analysis/field_usage.rb +82 -0
- data/lib/graphql/analysis/max_query_complexity.rb +20 -0
- data/lib/graphql/analysis/max_query_depth.rb +20 -0
- data/lib/graphql/analysis/query_complexity.rb +263 -0
- data/lib/graphql/analysis/query_depth.rb +58 -0
- data/lib/graphql/analysis/visitor.rb +280 -0
- data/lib/graphql/analysis.rb +95 -1
- data/lib/graphql/autoload.rb +38 -0
- data/lib/graphql/backtrace/table.rb +118 -55
- data/lib/graphql/backtrace.rb +1 -19
- data/lib/graphql/coercion_error.rb +1 -9
- data/lib/graphql/current.rb +57 -0
- data/lib/graphql/dashboard/application_controller.rb +41 -0
- data/lib/graphql/dashboard/detailed_traces.rb +47 -0
- data/lib/graphql/dashboard/installable.rb +22 -0
- data/lib/graphql/dashboard/landings_controller.rb +9 -0
- data/lib/graphql/dashboard/limiters.rb +93 -0
- data/lib/graphql/dashboard/operation_store.rb +199 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.css +6 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.js +7 -0
- data/lib/graphql/dashboard/statics/charts.min.css +1 -0
- data/lib/graphql/dashboard/statics/dashboard.css +30 -0
- data/lib/graphql/dashboard/statics/dashboard.js +143 -0
- data/lib/graphql/dashboard/statics/header-icon.png +0 -0
- data/lib/graphql/dashboard/statics/icon.png +0 -0
- data/lib/graphql/dashboard/statics_controller.rb +31 -0
- data/lib/graphql/dashboard/subscriptions.rb +97 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/detailed_traces/traces/index.html.erb +45 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/landings/show.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/limiters/limiters/show.html.erb +62 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/not_installed.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/_form.html.erb +24 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/edit.html.erb +21 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/index.html.erb +69 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/new.html.erb +7 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/index.html.erb +39 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/show.html.erb +32 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/index.html.erb +81 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/show.html.erb +71 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/subscriptions/show.html.erb +41 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/index.html.erb +55 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/show.html.erb +40 -0
- data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +108 -0
- data/lib/graphql/dashboard.rb +96 -0
- data/lib/graphql/dataloader/active_record_association_source.rb +84 -0
- data/lib/graphql/dataloader/active_record_source.rb +47 -0
- data/lib/graphql/dataloader/async_dataloader.rb +112 -0
- data/lib/graphql/dataloader/null_dataloader.rb +55 -10
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +35 -12
- data/lib/graphql/dataloader.rb +224 -149
- data/lib/graphql/date_encoding_error.rb +1 -1
- data/lib/graphql/dig.rb +2 -1
- data/lib/graphql/duration_encoding_error.rb +16 -0
- data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -10
- data/lib/graphql/execution/interpreter/resolve.rb +23 -25
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +228 -0
- data/lib/graphql/execution/interpreter/runtime.rb +363 -434
- data/lib/graphql/execution/interpreter.rb +91 -164
- data/lib/graphql/execution/lookahead.rb +105 -31
- data/lib/graphql/execution/multiplex.rb +7 -6
- data/lib/graphql/execution/next/field_resolve_step.rb +711 -0
- data/lib/graphql/execution/next/load_argument_step.rb +60 -0
- data/lib/graphql/execution/next/prepare_object_step.rb +129 -0
- data/lib/graphql/execution/next/runner.rb +389 -0
- data/lib/graphql/execution/next/selections_step.rb +37 -0
- data/lib/graphql/execution/next.rb +70 -0
- data/lib/graphql/execution.rb +1 -0
- data/lib/graphql/execution_error.rb +13 -10
- data/lib/graphql/introspection/directive_location_enum.rb +1 -1
- data/lib/graphql/introspection/directive_type.rb +7 -3
- data/lib/graphql/introspection/dynamic_fields.rb +5 -1
- data/lib/graphql/introspection/entry_points.rb +20 -6
- data/lib/graphql/introspection/enum_value_type.rb +5 -5
- data/lib/graphql/introspection/field_type.rb +13 -5
- data/lib/graphql/introspection/input_value_type.rb +21 -13
- data/lib/graphql/introspection/schema_type.rb +8 -11
- data/lib/graphql/introspection/type_type.rb +64 -28
- data/lib/graphql/invalid_name_error.rb +1 -1
- data/lib/graphql/invalid_null_error.rb +26 -17
- data/lib/graphql/language/block_string.rb +34 -18
- data/lib/graphql/language/cache.rb +13 -0
- data/lib/graphql/language/comment.rb +18 -0
- data/lib/graphql/language/definition_slice.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +90 -61
- data/lib/graphql/language/lexer.rb +319 -193
- data/lib/graphql/language/nodes.rb +136 -77
- data/lib/graphql/language/parser.rb +807 -1985
- data/lib/graphql/language/printer.rb +324 -151
- data/lib/graphql/language/sanitized_printer.rb +21 -23
- data/lib/graphql/language/static_visitor.rb +171 -0
- data/lib/graphql/language/visitor.rb +23 -83
- data/lib/graphql/language.rb +71 -1
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/pagination/array_connection.rb +6 -6
- data/lib/graphql/pagination/connection.rb +30 -1
- data/lib/graphql/pagination/connections.rb +32 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
- data/lib/graphql/query/context/scoped_context.rb +101 -0
- data/lib/graphql/query/context.rb +82 -144
- data/lib/graphql/query/null_context.rb +15 -18
- data/lib/graphql/query/partial.rb +179 -0
- data/lib/graphql/query/validation_pipeline.rb +4 -4
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query/variables.rb +3 -3
- data/lib/graphql/query.rb +126 -81
- data/lib/graphql/railtie.rb +16 -6
- data/lib/graphql/rake_task.rb +3 -12
- data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
- data/lib/graphql/rubocop/graphql/field_type_in_block.rb +144 -0
- data/lib/graphql/rubocop/graphql/root_types_in_block.rb +38 -0
- data/lib/graphql/rubocop.rb +2 -0
- data/lib/graphql/schema/addition.rb +26 -13
- data/lib/graphql/schema/always_visible.rb +7 -2
- data/lib/graphql/schema/argument.rb +75 -9
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +123 -60
- data/lib/graphql/schema/directive/flagged.rb +4 -2
- data/lib/graphql/schema/directive/one_of.rb +12 -0
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive.rb +54 -2
- data/lib/graphql/schema/enum.rb +110 -27
- data/lib/graphql/schema/enum_value.rb +10 -2
- data/lib/graphql/schema/field/connection_extension.rb +15 -49
- data/lib/graphql/schema/field/scope_extension.rb +23 -7
- data/lib/graphql/schema/field.rb +245 -118
- data/lib/graphql/schema/field_extension.rb +34 -1
- data/lib/graphql/schema/has_single_input_argument.rb +160 -0
- data/lib/graphql/schema/input_object.rb +116 -60
- data/lib/graphql/schema/interface.rb +34 -16
- data/lib/graphql/schema/introspection_system.rb +8 -17
- data/lib/graphql/schema/late_bound_type.rb +4 -0
- data/lib/graphql/schema/list.rb +3 -3
- data/lib/graphql/schema/loader.rb +3 -4
- data/lib/graphql/schema/member/base_dsl_methods.rb +18 -2
- data/lib/graphql/schema/member/has_arguments.rb +132 -100
- data/lib/graphql/schema/member/has_authorization.rb +35 -0
- data/lib/graphql/schema/member/has_dataloader.rb +99 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +15 -0
- data/lib/graphql/schema/member/has_directives.rb +4 -4
- data/lib/graphql/schema/member/has_fields.rb +115 -15
- data/lib/graphql/schema/member/has_interfaces.rb +26 -12
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- data/lib/graphql/schema/member/has_validators.rb +1 -1
- data/lib/graphql/schema/member/relay_shortcuts.rb +1 -1
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -4
- data/lib/graphql/schema/member/validates_input.rb +3 -3
- data/lib/graphql/schema/member.rb +6 -0
- data/lib/graphql/schema/mutation.rb +7 -0
- data/lib/graphql/schema/object.rb +34 -8
- data/lib/graphql/schema/printer.rb +9 -7
- data/lib/graphql/schema/ractor_shareable.rb +79 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +6 -129
- data/lib/graphql/schema/resolver.rb +90 -32
- data/lib/graphql/schema/scalar.rb +4 -9
- data/lib/graphql/schema/subscription.rb +63 -10
- data/lib/graphql/schema/timeout.rb +19 -2
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/union.rb +2 -2
- data/lib/graphql/schema/unique_within_type.rb +1 -1
- data/lib/graphql/schema/validator/all_validator.rb +62 -0
- data/lib/graphql/schema/validator/required_validator.rb +92 -11
- data/lib/graphql/schema/validator.rb +3 -1
- data/lib/graphql/schema/visibility/migration.rb +188 -0
- data/lib/graphql/schema/visibility/profile.rb +445 -0
- data/lib/graphql/schema/visibility/visit.rb +190 -0
- data/lib/graphql/schema/visibility.rb +311 -0
- data/lib/graphql/schema/warden.rb +275 -103
- data/lib/graphql/schema.rb +950 -210
- data/lib/graphql/static_validation/all_rules.rb +3 -3
- data/lib/graphql/static_validation/base_visitor.rb +7 -6
- data/lib/graphql/static_validation/literal_validator.rb +6 -7
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +3 -3
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +12 -2
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +47 -13
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +88 -25
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +10 -2
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +12 -2
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +1 -1
- data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +25 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +5 -5
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
- data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +26 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +7 -3
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +11 -2
- data/lib/graphql/static_validation/validation_context.rb +21 -5
- data/lib/graphql/static_validation/validator.rb +9 -1
- data/lib/graphql/static_validation.rb +0 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +8 -5
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +12 -10
- data/lib/graphql/subscriptions/event.rb +21 -4
- data/lib/graphql/subscriptions/serialize.rb +3 -1
- data/lib/graphql/subscriptions.rb +21 -17
- data/lib/graphql/testing/helpers.rb +161 -0
- data/lib/graphql/testing/mock_action_cable.rb +111 -0
- data/lib/graphql/testing.rb +3 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +14 -3
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +1 -1
- data/lib/graphql/tracing/appoptics_trace.rb +7 -3
- data/lib/graphql/tracing/appoptics_tracing.rb +9 -2
- data/lib/graphql/tracing/appsignal_trace.rb +32 -59
- data/lib/graphql/tracing/appsignal_tracing.rb +2 -0
- data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
- data/lib/graphql/tracing/data_dog_trace.rb +46 -162
- data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
- data/lib/graphql/tracing/detailed_trace/active_record_backend.rb +74 -0
- data/lib/graphql/tracing/detailed_trace/memory_backend.rb +60 -0
- data/lib/graphql/tracing/detailed_trace/redis_backend.rb +72 -0
- data/lib/graphql/tracing/detailed_trace.rb +156 -0
- data/lib/graphql/tracing/legacy_hooks_trace.rb +75 -0
- data/lib/graphql/tracing/legacy_trace.rb +4 -61
- data/lib/graphql/tracing/monitor_trace.rb +283 -0
- data/lib/graphql/tracing/new_relic_trace.rb +47 -54
- data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
- data/lib/graphql/tracing/notifications_trace.rb +183 -37
- data/lib/graphql/tracing/notifications_tracing.rb +2 -0
- data/lib/graphql/tracing/null_trace.rb +9 -0
- data/lib/graphql/tracing/perfetto_trace/trace.proto +141 -0
- data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +33 -0
- data/lib/graphql/tracing/perfetto_trace.rb +864 -0
- data/lib/graphql/tracing/platform_tracing.rb +3 -1
- data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +5 -1
- data/lib/graphql/tracing/prometheus_trace.rb +73 -73
- data/lib/graphql/tracing/prometheus_tracing.rb +2 -0
- data/lib/graphql/tracing/scout_trace.rb +32 -58
- data/lib/graphql/tracing/scout_tracing.rb +2 -0
- data/lib/graphql/tracing/sentry_trace.rb +82 -0
- data/lib/graphql/tracing/statsd_trace.rb +33 -45
- data/lib/graphql/tracing/statsd_tracing.rb +2 -0
- data/lib/graphql/tracing/trace.rb +112 -1
- data/lib/graphql/tracing.rb +31 -28
- data/lib/graphql/type_kinds.rb +2 -1
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/connection_behaviors.rb +44 -2
- data/lib/graphql/types/relay/edge_behaviors.rb +18 -0
- data/lib/graphql/types/relay/has_node_field.rb +13 -8
- data/lib/graphql/types/relay/has_nodes_field.rb +13 -8
- data/lib/graphql/types/relay/node_behaviors.rb +13 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
- data/lib/graphql/types.rb +18 -10
- data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
- data/lib/graphql/unauthorized_error.rb +5 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +71 -54
- data/readme.md +12 -2
- metadata +233 -37
- data/lib/graphql/analysis/ast/analyzer.rb +0 -84
- data/lib/graphql/analysis/ast/field_usage.rb +0 -57
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -22
- data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
- data/lib/graphql/analysis/ast/query_complexity.rb +0 -230
- data/lib/graphql/analysis/ast/query_depth.rb +0 -55
- data/lib/graphql/analysis/ast/visitor.rb +0 -276
- data/lib/graphql/analysis/ast.rb +0 -81
- data/lib/graphql/backtrace/inspect_result.rb +0 -50
- data/lib/graphql/backtrace/trace.rb +0 -96
- data/lib/graphql/backtrace/tracer.rb +0 -80
- data/lib/graphql/deprecation.rb +0 -9
- data/lib/graphql/filter.rb +0 -59
- data/lib/graphql/language/parser.y +0 -560
- data/lib/graphql/language/token.rb +0 -34
- data/lib/graphql/schema/base_64_bp.rb +0 -26
- data/lib/graphql/schema/invalid_type_error.rb +0 -7
- data/lib/graphql/schema/null_mask.rb +0 -11
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +0 -17
- data/lib/graphql/static_validation/type_stack.rb +0 -216
- data/lib/graphql/subscriptions/instrumentation.rb +0 -28
|
@@ -5,11 +5,88 @@ module GraphQL
|
|
|
5
5
|
class Member
|
|
6
6
|
# Shared code for Objects, Interfaces, Mutations, Subscriptions
|
|
7
7
|
module HasFields
|
|
8
|
+
include EmptyObjects
|
|
8
9
|
# Add a field to this object or interface with the given definition
|
|
9
|
-
# @
|
|
10
|
+
# @param name_positional [Symbol] The underscore-cased version of this field name (will be camelized for the GraphQL API); `name:` keyword is also accepted
|
|
11
|
+
# @param type_positional [Class, GraphQL::BaseType, Array] The return type of this field; `type:` keyword is also accepted
|
|
12
|
+
# @param desc_positional [String] Field description; `description:` keyword is also accepted
|
|
13
|
+
# @option kwargs [Symbol] :name The underscore-cased version of this field name (will be camelized for the GraphQL API); positional argument also accepted
|
|
14
|
+
# @option kwargs [Class, GraphQL::BaseType, Array] :type The return type of this field; positional argument is also accepted
|
|
15
|
+
# @option kwargs [Boolean] :null (defaults to `true`) `true` if this field may return `null`, `false` if it is never `null`
|
|
16
|
+
# @option kwargs [String] :description Field description; positional argument also accepted
|
|
17
|
+
# @option kwargs [String] :comment Field comment
|
|
18
|
+
# @option kwargs [String] :deprecation_reason If present, the field is marked "deprecated" with this message
|
|
19
|
+
# @option kwargs [Symbol] :method The method to call on the underlying object to resolve this field (defaults to `name`)
|
|
20
|
+
# @option kwargs [String, Symbol] :hash_key The hash key to lookup on the underlying object (if its a Hash) to resolve this field (defaults to `name` or `name.to_s`)
|
|
21
|
+
# @option kwargs [Array<String, Symbol>] :dig The nested hash keys to lookup on the underlying hash to resolve this field using dig
|
|
22
|
+
# @option kwargs [Symbol, true] :resolver_method The method on the type to call to resolve this field (defaults to `name`)
|
|
23
|
+
# @option kwargs [Symbol, true] :resolve_static Used by {Schema.execute_next} to produce a single value, shared by all objects which resolve this field. Called on the owner type class with `context, **arguments`
|
|
24
|
+
# @option kwargs [Symbol, true] :resolve_batch Used by {Schema.execute_next} map `objects` to a same-sized Array of results. Called on the owner type class with `objects, context, **arguments`.
|
|
25
|
+
# @option kwargs [Symbol, true] :resolve_each Used by {Schema.execute_next} to get a value value for each item. Called on the owner type class with `object, context, **arguments`.
|
|
26
|
+
# @option kwargs [Symbol, true] :resolve_legacy_instance_method Used by {Schema.execute_next} to get a value value for each item. Calls an instance method on the object type class.
|
|
27
|
+
# @option kwargs [Boolean] :connection `true` if this field should get automagic connection behavior; default is to infer by `*Connection` in the return type name
|
|
28
|
+
# @option kwargs [Class] :connection_extension The extension to add, to implement connections. If `nil`, no extension is added.
|
|
29
|
+
# @option kwargs [Integer, nil] :max_page_size For connections, the maximum number of items to return from this field, or `nil` to allow unlimited results.
|
|
30
|
+
# @option kwargs [Integer, nil] :default_page_size For connections, the default number of items to return from this field, or `nil` to return unlimited results.
|
|
31
|
+
# @option kwargs [Boolean] :introspection If true, this field will be marked as `#introspection?` and the name may begin with `__`
|
|
32
|
+
# @option kwargs [{String=>GraphQL::Schema::Argument, Hash}] :arguments Arguments for this field (may be added in the block, also)
|
|
33
|
+
# @option kwargs [Boolean] :camelize If true, the field name will be camelized when building the schema
|
|
34
|
+
# @option kwargs [Numeric] :complexity When provided, set the complexity for this field
|
|
35
|
+
# @option kwargs [Boolean] :scope If true, the return type's `.scope_items` method will be called on the return value
|
|
36
|
+
# @option kwargs [Symbol, String] :subscription_scope A key in `context` which will be used to scope subscription payloads
|
|
37
|
+
# @option kwargs [Array<Class, Hash<Class => Object>>] :extensions Named extensions to apply to this field (see also {#extension})
|
|
38
|
+
# @option kwargs [Hash{Class => Hash}] :directives Directives to apply to this field
|
|
39
|
+
# @option kwargs [Boolean] :trace If true, a {GraphQL::Tracing} tracer will measure this scalar field
|
|
40
|
+
# @option kwargs [Boolean] :broadcastable Whether or not this field can be distributed in subscription broadcasts
|
|
41
|
+
# @option kwargs [Language::Nodes::FieldDefinition, nil] :ast_node If this schema was parsed from definition, this AST node defined the field
|
|
42
|
+
# @option kwargs [Boolean] :method_conflict_warning If false, skip the warning if this field's method conflicts with a built-in method
|
|
43
|
+
# @option kwargs [Array<Hash>] :validates Configurations for validating this field
|
|
44
|
+
# @option kwargs [Object] :fallback_value A fallback value if the method is not defined
|
|
45
|
+
# @option kwargs [Class<GraphQL::Schema::Mutation>] :mutation
|
|
46
|
+
# @option kwargs [Class<GraphQL::Schema::Resolver>] :resolver
|
|
47
|
+
# @option kwargs [Class<GraphQL::Schema::Subscription>] :subscription
|
|
48
|
+
# @option kwargs [Boolean] :dynamic_introspection (Private, used by GraphQL-Ruby)
|
|
49
|
+
# @option kwargs [Boolean] :relay_node_field (Private, used by GraphQL-Ruby)
|
|
50
|
+
# @option kwargs [Boolean] :relay_nodes_field (Private, used by GraphQL-Ruby)
|
|
51
|
+
# @option kwargs [Class, Hash] :dataload Shorthand for dataloader lookups
|
|
52
|
+
# @option kwargs [Array<:ast_node, :parent, :lookahead, :owner, :execution_errors, :graphql_name, :argument_details, Symbol>] :extras Extra arguments to be injected into the resolver for this field
|
|
53
|
+
# @param kwargs [Hash] Keywords for defining the field. Any not documented here will be passed to your base field class where they must be handled.
|
|
54
|
+
# @param definition_block [Proc] an additional block for configuring the field. Receive the field as a block param, or, if no block params are defined, then the block is `instance_eval`'d on the new {Field}.
|
|
55
|
+
# @yieldparam field [GraphQL::Schema::Field] The newly-created field instance
|
|
56
|
+
# @yieldreturn [void]
|
|
10
57
|
# @return [GraphQL::Schema::Field]
|
|
11
|
-
def field(
|
|
12
|
-
|
|
58
|
+
def field(name_positional = nil, type_positional = nil, desc_positional = nil, **kwargs, &definition_block)
|
|
59
|
+
resolver = kwargs.delete(:resolver)
|
|
60
|
+
mutation = kwargs.delete(:mutation)
|
|
61
|
+
subscription = kwargs.delete(:subscription)
|
|
62
|
+
if (resolver_class = resolver || mutation || subscription)
|
|
63
|
+
# Add a reference to that parent class
|
|
64
|
+
kwargs[:resolver_class] = resolver_class
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
kwargs[:name] ||= name_positional
|
|
68
|
+
if !type_positional.nil?
|
|
69
|
+
if desc_positional
|
|
70
|
+
if kwargs[:description]
|
|
71
|
+
raise ArgumentError, "Provide description as a positional argument or `description:` keyword, but not both (#{desc_positional.inspect}, #{kwargs[:description].inspect})"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
kwargs[:description] = desc_positional
|
|
75
|
+
kwargs[:type] = type_positional
|
|
76
|
+
elsif (resolver || mutation) && type_positional.is_a?(String)
|
|
77
|
+
# The return type should be copied from the resolver, and the second positional argument is the description
|
|
78
|
+
kwargs[:description] = type_positional
|
|
79
|
+
else
|
|
80
|
+
kwargs[:type] = type_positional
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
if type_positional.is_a?(Class) && type_positional < GraphQL::Schema::Mutation
|
|
84
|
+
raise ArgumentError, "Use `field #{name_positional.inspect}, mutation: Mutation, ...` to provide a mutation to this field instead"
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
kwargs[:owner] = self
|
|
89
|
+
field_defn = field_class.new(**kwargs, &definition_block)
|
|
13
90
|
add_field(field_defn)
|
|
14
91
|
field_defn
|
|
15
92
|
end
|
|
@@ -79,6 +156,18 @@ module GraphQL
|
|
|
79
156
|
end
|
|
80
157
|
end
|
|
81
158
|
|
|
159
|
+
# @param new_has_no_fields [Boolean] Call with `true` to make this Object type ignore the requirement to have any defined fields.
|
|
160
|
+
# @return [void]
|
|
161
|
+
def has_no_fields(new_has_no_fields)
|
|
162
|
+
@has_no_fields = new_has_no_fields
|
|
163
|
+
nil
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# @return [Boolean] `true` if `has_no_fields(true)` was configued
|
|
167
|
+
def has_no_fields?
|
|
168
|
+
@has_no_fields
|
|
169
|
+
end
|
|
170
|
+
|
|
82
171
|
# @return [Hash<String => GraphQL::Schema::Field, Array<GraphQL::Schema::Field>>] Fields defined on this class _specifically_, not parent classes
|
|
83
172
|
def own_fields
|
|
84
173
|
@own_fields ||= {}
|
|
@@ -97,20 +186,21 @@ module GraphQL
|
|
|
97
186
|
end
|
|
98
187
|
|
|
99
188
|
module InterfaceMethods
|
|
100
|
-
def get_field(field_name, context = GraphQL::Query::NullContext)
|
|
189
|
+
def get_field(field_name, context = GraphQL::Query::NullContext.instance)
|
|
101
190
|
warden = Warden.from_context(context)
|
|
191
|
+
skip_visible = context.respond_to?(:types) && context.types.is_a?(GraphQL::Schema::Visibility::Profile)
|
|
102
192
|
for ancestor in ancestors
|
|
103
193
|
if ancestor.respond_to?(:own_fields) &&
|
|
104
194
|
(f_entry = ancestor.own_fields[field_name]) &&
|
|
105
|
-
(
|
|
106
|
-
return
|
|
195
|
+
(skip_visible || (f_entry = Warden.visible_entry?(:visible_field?, f_entry, context, warden)))
|
|
196
|
+
return f_entry
|
|
107
197
|
end
|
|
108
198
|
end
|
|
109
199
|
nil
|
|
110
200
|
end
|
|
111
201
|
|
|
112
202
|
# @return [Hash<String => GraphQL::Schema::Field>] Fields on this object, keyed by name, including inherited fields
|
|
113
|
-
def fields(context = GraphQL::Query::NullContext)
|
|
203
|
+
def fields(context = GraphQL::Query::NullContext.instance)
|
|
114
204
|
warden = Warden.from_context(context)
|
|
115
205
|
# Local overrides take precedence over inherited fields
|
|
116
206
|
visible_fields = {}
|
|
@@ -120,7 +210,7 @@ module GraphQL
|
|
|
120
210
|
# Choose the most local definition that passes `.visible?` --
|
|
121
211
|
# stop checking for fields by name once one has been found.
|
|
122
212
|
if !visible_fields.key?(field_name) && (f = Warden.visible_entry?(:visible_field?, fields_entry, context, warden))
|
|
123
|
-
visible_fields[field_name] = f
|
|
213
|
+
visible_fields[field_name] = f.ensure_loaded
|
|
124
214
|
end
|
|
125
215
|
end
|
|
126
216
|
end
|
|
@@ -130,37 +220,46 @@ module GraphQL
|
|
|
130
220
|
end
|
|
131
221
|
|
|
132
222
|
module ObjectMethods
|
|
133
|
-
def get_field(field_name, context = GraphQL::Query::NullContext)
|
|
223
|
+
def get_field(field_name, context = GraphQL::Query::NullContext.instance)
|
|
134
224
|
# Objects need to check that the interface implementation is visible, too
|
|
135
225
|
warden = Warden.from_context(context)
|
|
136
|
-
|
|
226
|
+
ancs = ancestors
|
|
227
|
+
skip_visible = context.respond_to?(:types) && context.types.is_a?(GraphQL::Schema::Visibility::Profile)
|
|
228
|
+
i = 0
|
|
229
|
+
while (ancestor = ancs[i])
|
|
137
230
|
if ancestor.respond_to?(:own_fields) &&
|
|
138
231
|
visible_interface_implementation?(ancestor, context, warden) &&
|
|
139
232
|
(f_entry = ancestor.own_fields[field_name]) &&
|
|
140
|
-
(
|
|
141
|
-
return
|
|
233
|
+
(skip_visible || (f_entry = Warden.visible_entry?(:visible_field?, f_entry, context, warden)))
|
|
234
|
+
return (skip_visible ? f_entry : f_entry.ensure_loaded)
|
|
142
235
|
end
|
|
236
|
+
i += 1
|
|
143
237
|
end
|
|
144
238
|
nil
|
|
145
239
|
end
|
|
146
240
|
|
|
147
241
|
# @return [Hash<String => GraphQL::Schema::Field>] Fields on this object, keyed by name, including inherited fields
|
|
148
|
-
def fields(context = GraphQL::Query::NullContext)
|
|
242
|
+
def fields(context = GraphQL::Query::NullContext.instance)
|
|
149
243
|
# Objects need to check that the interface implementation is visible, too
|
|
150
244
|
warden = Warden.from_context(context)
|
|
151
245
|
# Local overrides take precedence over inherited fields
|
|
152
246
|
visible_fields = {}
|
|
247
|
+
had_any_fields_at_all = false
|
|
153
248
|
for ancestor in ancestors
|
|
154
249
|
if ancestor.respond_to?(:own_fields) && visible_interface_implementation?(ancestor, context, warden)
|
|
155
250
|
ancestor.own_fields.each do |field_name, fields_entry|
|
|
251
|
+
had_any_fields_at_all = true
|
|
156
252
|
# Choose the most local definition that passes `.visible?` --
|
|
157
253
|
# stop checking for fields by name once one has been found.
|
|
158
254
|
if !visible_fields.key?(field_name) && (f = Warden.visible_entry?(:visible_field?, fields_entry, context, warden))
|
|
159
|
-
visible_fields[field_name] = f
|
|
255
|
+
visible_fields[field_name] = f.ensure_loaded
|
|
160
256
|
end
|
|
161
257
|
end
|
|
162
258
|
end
|
|
163
259
|
end
|
|
260
|
+
if !had_any_fields_at_all && !has_no_fields?
|
|
261
|
+
warn(GraphQL::Schema::Object::FieldsAreRequiredError.new(self).message + "\n\nThis will raise an error in a future GraphQL-Ruby version.")
|
|
262
|
+
end
|
|
164
263
|
visible_fields
|
|
165
264
|
end
|
|
166
265
|
end
|
|
@@ -183,6 +282,7 @@ module GraphQL
|
|
|
183
282
|
subclass.class_exec do
|
|
184
283
|
@own_fields ||= nil
|
|
185
284
|
@field_class ||= nil
|
|
285
|
+
@has_no_fields ||= false
|
|
186
286
|
end
|
|
187
287
|
end
|
|
188
288
|
|
|
@@ -209,7 +309,7 @@ module GraphQL
|
|
|
209
309
|
end
|
|
210
310
|
end
|
|
211
311
|
|
|
212
|
-
# @param [GraphQL::Schema::Field]
|
|
312
|
+
# @param field_defn [GraphQL::Schema::Field]
|
|
213
313
|
# @return [String] A warning to give when this field definition might conflict with a built-in method
|
|
214
314
|
def conflict_field_name_warning(field_defn)
|
|
215
315
|
"#{self.graphql_name}'s `field :#{field_defn.original_name}` conflicts with a built-in method, use `resolver_method:` to pick a different resolver method for this field (for example, `resolver_method: :resolve_#{field_defn.resolver_method}` and `def resolve_#{field_defn.resolver_method}`). Or use `method_conflict_warning: false` to suppress this warning."
|
|
@@ -8,8 +8,8 @@ module GraphQL
|
|
|
8
8
|
new_memberships = []
|
|
9
9
|
new_interfaces.each do |int|
|
|
10
10
|
if int.is_a?(Module)
|
|
11
|
-
unless int.include?(GraphQL::Schema::Interface)
|
|
12
|
-
raise "#{int} cannot be implemented since it's not a GraphQL Interface. Use `include` for plain Ruby modules."
|
|
11
|
+
unless int.include?(GraphQL::Schema::Interface) && !int.is_a?(Class)
|
|
12
|
+
raise "#{int.respond_to?(:graphql_name) ? "#{int.graphql_name} (#{int})" : int.inspect} cannot be implemented since it's not a GraphQL Interface. Use `include` for plain Ruby modules."
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
new_memberships << int.type_membership_class.new(int, self, **options)
|
|
@@ -24,7 +24,7 @@ module GraphQL
|
|
|
24
24
|
implements(next_interface)
|
|
25
25
|
end
|
|
26
26
|
elsif int.is_a?(String) || int.is_a?(GraphQL::Schema::LateBoundType)
|
|
27
|
-
if options.
|
|
27
|
+
if !options.empty?
|
|
28
28
|
raise ArgumentError, "`implements(...)` doesn't support options with late-loaded types yet. Remove #{options} and open an issue to request this feature."
|
|
29
29
|
end
|
|
30
30
|
new_memberships << int
|
|
@@ -70,11 +70,20 @@ module GraphQL
|
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
module InheritedInterfaces
|
|
73
|
-
def interfaces(context = GraphQL::Query::NullContext)
|
|
73
|
+
def interfaces(context = GraphQL::Query::NullContext.instance)
|
|
74
74
|
visible_interfaces = super
|
|
75
|
-
|
|
76
|
-
visible_interfaces.
|
|
77
|
-
|
|
75
|
+
inherited_interfaces = superclass.interfaces(context)
|
|
76
|
+
if !visible_interfaces.empty?
|
|
77
|
+
if !inherited_interfaces.empty?
|
|
78
|
+
visible_interfaces.concat(inherited_interfaces)
|
|
79
|
+
visible_interfaces.uniq!
|
|
80
|
+
end
|
|
81
|
+
visible_interfaces
|
|
82
|
+
elsif !inherited_interfaces.empty?
|
|
83
|
+
inherited_interfaces
|
|
84
|
+
else
|
|
85
|
+
EmptyObjects::EMPTY_ARRAY
|
|
86
|
+
end
|
|
78
87
|
end
|
|
79
88
|
|
|
80
89
|
def interface_type_memberships
|
|
@@ -90,25 +99,30 @@ module GraphQL
|
|
|
90
99
|
end
|
|
91
100
|
|
|
92
101
|
# param context [Query::Context] If omitted, skip filtering.
|
|
93
|
-
def interfaces(context = GraphQL::Query::NullContext)
|
|
102
|
+
def interfaces(context = GraphQL::Query::NullContext.instance)
|
|
94
103
|
warden = Warden.from_context(context)
|
|
95
|
-
visible_interfaces =
|
|
104
|
+
visible_interfaces = nil
|
|
96
105
|
own_interface_type_memberships.each do |type_membership|
|
|
97
106
|
case type_membership
|
|
98
107
|
when Schema::TypeMembership
|
|
99
108
|
if warden.visible_type_membership?(type_membership, context)
|
|
109
|
+
visible_interfaces ||= []
|
|
100
110
|
visible_interfaces << type_membership.abstract_type
|
|
101
111
|
end
|
|
102
112
|
when String, Schema::LateBoundType
|
|
103
113
|
# During initialization, `type_memberships` can hold late-bound types
|
|
114
|
+
visible_interfaces ||= []
|
|
104
115
|
visible_interfaces << type_membership
|
|
105
116
|
else
|
|
106
117
|
raise "Invariant: Unexpected type_membership #{type_membership.class}: #{type_membership.inspect}"
|
|
107
118
|
end
|
|
108
119
|
end
|
|
109
|
-
visible_interfaces
|
|
110
|
-
|
|
111
|
-
|
|
120
|
+
if visible_interfaces
|
|
121
|
+
visible_interfaces.uniq!
|
|
122
|
+
visible_interfaces
|
|
123
|
+
else
|
|
124
|
+
EmptyObjects::EMPTY_ARRAY
|
|
125
|
+
end
|
|
112
126
|
end
|
|
113
127
|
|
|
114
128
|
private
|
|
@@ -7,7 +7,11 @@ module GraphQL
|
|
|
7
7
|
module HasUnresolvedTypeError
|
|
8
8
|
private
|
|
9
9
|
def add_unresolved_type_error(child_class)
|
|
10
|
-
child_class.
|
|
10
|
+
if child_class.name # Don't set this for anonymous classes
|
|
11
|
+
child_class.const_set(:UnresolvedTypeError, Class.new(GraphQL::UnresolvedTypeError))
|
|
12
|
+
else
|
|
13
|
+
child_class.const_set(:UnresolvedTypeError, UnresolvedTypeError)
|
|
14
|
+
end
|
|
11
15
|
end
|
|
12
16
|
end
|
|
13
17
|
end
|
|
@@ -76,7 +76,7 @@ module GraphQL
|
|
|
76
76
|
|
|
77
77
|
private
|
|
78
78
|
|
|
79
|
-
# If one of
|
|
79
|
+
# If one of these values is accessed, initialize all the instance variables to retain
|
|
80
80
|
# a consistent object shape.
|
|
81
81
|
def initialize_relay_metadata
|
|
82
82
|
if !defined?(@connection_type)
|
|
@@ -15,6 +15,25 @@ module GraphQL
|
|
|
15
15
|
def scope_items(items, context)
|
|
16
16
|
items
|
|
17
17
|
end
|
|
18
|
+
|
|
19
|
+
def reauthorize_scoped_objects(new_value = nil)
|
|
20
|
+
if new_value.nil?
|
|
21
|
+
if @reauthorize_scoped_objects != nil
|
|
22
|
+
@reauthorize_scoped_objects
|
|
23
|
+
else
|
|
24
|
+
find_inherited_value(:reauthorize_scoped_objects, true)
|
|
25
|
+
end
|
|
26
|
+
else
|
|
27
|
+
@reauthorize_scoped_objects = new_value
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def inherited(subclass)
|
|
32
|
+
super
|
|
33
|
+
subclass.class_exec do
|
|
34
|
+
@reauthorize_scoped_objects = nil
|
|
35
|
+
end
|
|
36
|
+
end
|
|
18
37
|
end
|
|
19
38
|
end
|
|
20
39
|
end
|
|
@@ -4,21 +4,34 @@ module GraphQL
|
|
|
4
4
|
class Schema
|
|
5
5
|
class Member
|
|
6
6
|
module TypeSystemHelpers
|
|
7
|
-
def initialize(
|
|
7
|
+
def initialize(...)
|
|
8
8
|
super
|
|
9
9
|
@to_non_null_type ||= nil
|
|
10
10
|
@to_list_type ||= nil
|
|
11
11
|
end
|
|
12
|
-
ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true)
|
|
13
12
|
|
|
14
13
|
# @return [Schema::NonNull] Make a non-null-type representation of this type
|
|
15
14
|
def to_non_null_type
|
|
16
|
-
@to_non_null_type
|
|
15
|
+
@to_non_null_type || begin
|
|
16
|
+
t = GraphQL::Schema::NonNull.new(self)
|
|
17
|
+
if frozen?
|
|
18
|
+
t
|
|
19
|
+
else
|
|
20
|
+
@to_non_null_type = t
|
|
21
|
+
end
|
|
22
|
+
end
|
|
17
23
|
end
|
|
18
24
|
|
|
19
25
|
# @return [Schema::List] Make a list-type representation of this type
|
|
20
26
|
def to_list_type
|
|
21
|
-
@to_list_type
|
|
27
|
+
@to_list_type || begin
|
|
28
|
+
t = GraphQL::Schema::List.new(self)
|
|
29
|
+
if frozen?
|
|
30
|
+
t
|
|
31
|
+
else
|
|
32
|
+
@to_list_type = t
|
|
33
|
+
end
|
|
34
|
+
end
|
|
22
35
|
end
|
|
23
36
|
|
|
24
37
|
# @return [Boolean] true if this is a non-nullable type. A nullable list of non-nullables is considered nullable.
|
|
@@ -17,15 +17,15 @@ module GraphQL
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def valid_isolated_input?(v)
|
|
20
|
-
valid_input?(v, GraphQL::Query::NullContext)
|
|
20
|
+
valid_input?(v, GraphQL::Query::NullContext.instance)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def coerce_isolated_input(v)
|
|
24
|
-
coerce_input(v, GraphQL::Query::NullContext)
|
|
24
|
+
coerce_input(v, GraphQL::Query::NullContext.instance)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def coerce_isolated_result(v)
|
|
28
|
-
coerce_result(v, GraphQL::Query::NullContext)
|
|
28
|
+
coerce_result(v, GraphQL::Query::NullContext.instance)
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
end
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
require 'graphql/schema/member/base_dsl_methods'
|
|
3
3
|
require 'graphql/schema/member/graphql_type_names'
|
|
4
4
|
require 'graphql/schema/member/has_ast_node'
|
|
5
|
+
require 'graphql/schema/member/has_authorization'
|
|
6
|
+
require 'graphql/schema/member/has_dataloader'
|
|
5
7
|
require 'graphql/schema/member/has_directives'
|
|
6
8
|
require 'graphql/schema/member/has_deprecation_reason'
|
|
7
9
|
require 'graphql/schema/member/has_interfaces'
|
|
@@ -30,6 +32,10 @@ module GraphQL
|
|
|
30
32
|
extend HasPath
|
|
31
33
|
extend HasAstNode
|
|
32
34
|
extend HasDirectives
|
|
35
|
+
|
|
36
|
+
def self.authorizes?(_ctx)
|
|
37
|
+
false
|
|
38
|
+
end
|
|
33
39
|
end
|
|
34
40
|
end
|
|
35
41
|
end
|
|
@@ -62,6 +62,13 @@ module GraphQL
|
|
|
62
62
|
extend GraphQL::Schema::Member::HasFields
|
|
63
63
|
extend GraphQL::Schema::Resolver::HasPayloadType
|
|
64
64
|
|
|
65
|
+
# @api private
|
|
66
|
+
def call_resolve(_args_hash)
|
|
67
|
+
# Clear any cached values from `loads` or authorization:
|
|
68
|
+
dataloader.clear_cache
|
|
69
|
+
super
|
|
70
|
+
end
|
|
71
|
+
|
|
65
72
|
class << self
|
|
66
73
|
def visible?(context)
|
|
67
74
|
true
|
|
@@ -5,8 +5,18 @@ require "graphql/query/null_context"
|
|
|
5
5
|
module GraphQL
|
|
6
6
|
class Schema
|
|
7
7
|
class Object < GraphQL::Schema::Member
|
|
8
|
+
extend GraphQL::Schema::Member::HasAuthorization
|
|
8
9
|
extend GraphQL::Schema::Member::HasFields
|
|
9
10
|
extend GraphQL::Schema::Member::HasInterfaces
|
|
11
|
+
include Member::HasDataloader
|
|
12
|
+
|
|
13
|
+
# Raised when an Object doesn't have any field defined and hasn't explicitly opted out of this requirement
|
|
14
|
+
class FieldsAreRequiredError < GraphQL::Error
|
|
15
|
+
def initialize(object_type)
|
|
16
|
+
message = "Object types must have fields, but #{object_type.graphql_name} doesn't have any. Define a field for this type, remove it from your schema, or add `has_no_fields(true)` to its definition."
|
|
17
|
+
super(message)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
10
20
|
|
|
11
21
|
# @return [Object] the application object this type is wrapping
|
|
12
22
|
attr_reader :object
|
|
@@ -30,6 +40,10 @@ module GraphQL
|
|
|
30
40
|
# @see authorized_new to make instances
|
|
31
41
|
protected :new
|
|
32
42
|
|
|
43
|
+
def wrap_scoped(object, context)
|
|
44
|
+
scoped_new(object, context)
|
|
45
|
+
end
|
|
46
|
+
|
|
33
47
|
# This is called by the runtime to return an object to call methods on.
|
|
34
48
|
def wrap(object, context)
|
|
35
49
|
authorized_new(object, context)
|
|
@@ -53,20 +67,28 @@ module GraphQL
|
|
|
53
67
|
# @return [GraphQL::Schema::Object, GraphQL::Execution::Lazy]
|
|
54
68
|
# @raise [GraphQL::UnauthorizedError] if the user-provided hook returns `false`
|
|
55
69
|
def authorized_new(object, context)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
70
|
+
context.query.current_trace.begin_authorized(self, object, context)
|
|
71
|
+
begin
|
|
72
|
+
maybe_lazy_auth_val = context.query.current_trace.authorized(query: context.query, type: self, object: object) do
|
|
73
|
+
begin
|
|
74
|
+
authorized?(object, context)
|
|
75
|
+
rescue GraphQL::UnauthorizedError => err
|
|
76
|
+
context.schema.unauthorized_object(err)
|
|
77
|
+
rescue StandardError => err
|
|
78
|
+
context.query.handle_or_reraise(err)
|
|
79
|
+
end
|
|
63
80
|
end
|
|
81
|
+
ensure
|
|
82
|
+
context.query.current_trace.end_authorized(self, object, context, maybe_lazy_auth_val)
|
|
64
83
|
end
|
|
65
84
|
|
|
66
85
|
auth_val = if context.schema.lazy?(maybe_lazy_auth_val)
|
|
67
86
|
GraphQL::Execution::Lazy.new do
|
|
87
|
+
context.query.current_trace.begin_authorized(self, object, context)
|
|
68
88
|
context.query.current_trace.authorized_lazy(query: context.query, type: self, object: object) do
|
|
69
|
-
context.schema.sync_lazy(maybe_lazy_auth_val)
|
|
89
|
+
res = context.schema.sync_lazy(maybe_lazy_auth_val)
|
|
90
|
+
context.query.current_trace.end_authorized(self, object, context, res)
|
|
91
|
+
res
|
|
70
92
|
end
|
|
71
93
|
end
|
|
72
94
|
else
|
|
@@ -91,6 +113,10 @@ module GraphQL
|
|
|
91
113
|
end
|
|
92
114
|
end
|
|
93
115
|
end
|
|
116
|
+
|
|
117
|
+
def scoped_new(object, context)
|
|
118
|
+
self.new(object, context)
|
|
119
|
+
end
|
|
94
120
|
end
|
|
95
121
|
|
|
96
122
|
def initialize(object, context)
|
|
@@ -36,15 +36,11 @@ module GraphQL
|
|
|
36
36
|
|
|
37
37
|
# @param schema [GraphQL::Schema]
|
|
38
38
|
# @param context [Hash]
|
|
39
|
-
# @param only [<#call(member, ctx)>]
|
|
40
|
-
# @param except [<#call(member, ctx)>]
|
|
41
39
|
# @param introspection [Boolean] Should include the introspection types in the string?
|
|
42
|
-
def initialize(schema, context: nil,
|
|
40
|
+
def initialize(schema, context: nil, introspection: false)
|
|
43
41
|
@document_from_schema = GraphQL::Language::DocumentFromSchemaDefinition.new(
|
|
44
42
|
schema,
|
|
45
43
|
context: context,
|
|
46
|
-
only: only,
|
|
47
|
-
except: except,
|
|
48
44
|
include_introspection_types: introspection,
|
|
49
45
|
)
|
|
50
46
|
|
|
@@ -61,7 +57,13 @@ module GraphQL
|
|
|
61
57
|
false
|
|
62
58
|
end
|
|
63
59
|
end
|
|
64
|
-
schema = Class.new(GraphQL::Schema) {
|
|
60
|
+
schema = Class.new(GraphQL::Schema) {
|
|
61
|
+
use GraphQL::Schema::Visibility
|
|
62
|
+
query(query_root)
|
|
63
|
+
def self.visible?(member, _ctx)
|
|
64
|
+
member.graphql_name != "Root"
|
|
65
|
+
end
|
|
66
|
+
}
|
|
65
67
|
|
|
66
68
|
introspection_schema_ast = GraphQL::Language::DocumentFromSchemaDefinition.new(
|
|
67
69
|
schema,
|
|
@@ -94,7 +96,7 @@ module GraphQL
|
|
|
94
96
|
|
|
95
97
|
class IntrospectionPrinter < GraphQL::Language::Printer
|
|
96
98
|
def print_schema_definition(schema)
|
|
97
|
-
"schema {\n query: Root\n}"
|
|
99
|
+
print_string("schema {\n query: Root\n}")
|
|
98
100
|
end
|
|
99
101
|
end
|
|
100
102
|
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module GraphQL
|
|
3
|
+
class Schema
|
|
4
|
+
module RactorShareable
|
|
5
|
+
def self.extended(schema_class)
|
|
6
|
+
schema_class.extend(SchemaExtension)
|
|
7
|
+
schema_class.freeze_schema
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module SchemaExtension
|
|
11
|
+
|
|
12
|
+
def freeze_error_handlers(handlers)
|
|
13
|
+
handlers[:subclass_handlers].default_proc = nil
|
|
14
|
+
handlers[:subclass_handlers].each do |_class, subclass_handlers|
|
|
15
|
+
freeze_error_handlers(subclass_handlers)
|
|
16
|
+
end
|
|
17
|
+
Ractor.make_shareable(handlers)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def freeze_schema
|
|
21
|
+
# warm some ivars:
|
|
22
|
+
default_analysis_engine
|
|
23
|
+
default_execution_strategy
|
|
24
|
+
GraphQL.default_parser
|
|
25
|
+
default_logger
|
|
26
|
+
freeze_error_handlers(error_handlers)
|
|
27
|
+
# TODO: this freezes errors of parent classes which could cause trouble
|
|
28
|
+
parent_class = superclass
|
|
29
|
+
while parent_class.respond_to?(:error_handlers)
|
|
30
|
+
freeze_error_handlers(parent_class.error_handlers)
|
|
31
|
+
parent_class = parent_class.superclass
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
own_tracers.freeze
|
|
35
|
+
@frozen_tracers = tracers.freeze
|
|
36
|
+
own_trace_modes.each do |m|
|
|
37
|
+
trace_options_for(m)
|
|
38
|
+
build_trace_mode(m)
|
|
39
|
+
end
|
|
40
|
+
build_trace_mode(:default)
|
|
41
|
+
Ractor.make_shareable(@trace_options_for_mode)
|
|
42
|
+
Ractor.make_shareable(own_trace_modes)
|
|
43
|
+
Ractor.make_shareable(own_multiplex_analyzers)
|
|
44
|
+
@frozen_multiplex_analyzers = Ractor.make_shareable(multiplex_analyzers)
|
|
45
|
+
Ractor.make_shareable(own_query_analyzers)
|
|
46
|
+
@frozen_query_analyzers = Ractor.make_shareable(query_analyzers)
|
|
47
|
+
Ractor.make_shareable(own_plugins)
|
|
48
|
+
own_plugins.each do |(plugin, options)|
|
|
49
|
+
Ractor.make_shareable(plugin)
|
|
50
|
+
Ractor.make_shareable(options)
|
|
51
|
+
end
|
|
52
|
+
@frozen_plugins = Ractor.make_shareable(plugins)
|
|
53
|
+
Ractor.make_shareable(own_references_to)
|
|
54
|
+
@frozen_directives = Ractor.make_shareable(directives)
|
|
55
|
+
|
|
56
|
+
Ractor.make_shareable(visibility)
|
|
57
|
+
Ractor.make_shareable(introspection_system)
|
|
58
|
+
extend(FrozenMethods)
|
|
59
|
+
|
|
60
|
+
Ractor.make_shareable(self)
|
|
61
|
+
superclass.respond_to?(:freeze_schema) && superclass.freeze_schema
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
module FrozenMethods
|
|
65
|
+
def tracers; @frozen_tracers; end
|
|
66
|
+
def multiplex_analyzers; @frozen_multiplex_analyzers; end
|
|
67
|
+
def query_analyzers; @frozen_query_analyzers; end
|
|
68
|
+
def plugins; @frozen_plugins; end
|
|
69
|
+
def directives; @frozen_directives; end
|
|
70
|
+
|
|
71
|
+
# This actually accumulates info during execution...
|
|
72
|
+
# How to support it?
|
|
73
|
+
def lazy?(_obj); false; end
|
|
74
|
+
def sync_lazy(obj); obj; end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|