graphql 1.9.21 → 2.0.16
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 +21 -10
- 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/{templates → install/templates}/base_mutation.erb +2 -0
- data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +2 -0
- data/lib/generators/graphql/install_generator.rb +45 -8
- 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 +28 -12
- data/lib/generators/graphql/orm_mutations_base.rb +40 -0
- data/lib/generators/graphql/relay.rb +49 -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_argument.erb +2 -0
- 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/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_scalar.erb +2 -0
- data/lib/generators/graphql/templates/base_union.erb +2 -0
- data/lib/generators/graphql/templates/enum.erb +7 -1
- data/lib/generators/graphql/templates/graphql_controller.erb +16 -12
- data/lib/generators/graphql/templates/input.erb +9 -0
- data/lib/generators/graphql/templates/interface.erb +6 -2
- data/lib/generators/graphql/templates/loader.erb +2 -0
- data/lib/generators/graphql/templates/mutation.erb +3 -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 +7 -3
- data/lib/generators/graphql/templates/query_type.erb +3 -3
- data/lib/generators/graphql/templates/scalar.erb +5 -1
- data/lib/generators/graphql/templates/schema.erb +25 -27
- data/lib/generators/graphql/templates/union.erb +6 -2
- data/lib/generators/graphql/type_generator.rb +47 -10
- data/lib/generators/graphql/union_generator.rb +5 -5
- data/lib/graphql/analysis/ast/field_usage.rb +31 -2
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +175 -68
- data/lib/graphql/analysis/ast/query_depth.rb +0 -1
- data/lib/graphql/analysis/ast/visitor.rb +17 -8
- data/lib/graphql/analysis/ast.rb +14 -14
- data/lib/graphql/analysis.rb +0 -7
- data/lib/graphql/backtrace/inspect_result.rb +0 -1
- data/lib/graphql/backtrace/table.rb +37 -16
- data/lib/graphql/backtrace/traced_error.rb +0 -1
- data/lib/graphql/backtrace/tracer.rb +39 -9
- data/lib/graphql/backtrace.rb +20 -17
- data/lib/graphql/dataloader/null_dataloader.rb +24 -0
- data/lib/graphql/dataloader/request.rb +19 -0
- data/lib/graphql/dataloader/request_all.rb +19 -0
- data/lib/graphql/dataloader/source.rb +164 -0
- data/lib/graphql/dataloader.rb +311 -0
- data/lib/graphql/date_encoding_error.rb +16 -0
- data/lib/graphql/deprecation.rb +9 -0
- data/lib/graphql/dig.rb +1 -1
- data/lib/graphql/execution/directive_checks.rb +2 -2
- data/lib/graphql/execution/errors.rb +77 -45
- data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
- data/lib/graphql/execution/interpreter/arguments.rb +88 -0
- data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
- data/lib/graphql/execution/interpreter/resolve.rb +44 -25
- data/lib/graphql/execution/interpreter/runtime.rb +755 -395
- data/lib/graphql/execution/interpreter.rb +201 -74
- data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
- data/lib/graphql/execution/lazy.rb +5 -9
- data/lib/graphql/execution/lookahead.rb +65 -136
- data/lib/graphql/execution/multiplex.rb +5 -152
- data/lib/graphql/execution.rb +11 -4
- data/lib/graphql/filter.rb +1 -1
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/introspection/base_object.rb +2 -5
- data/lib/graphql/introspection/directive_location_enum.rb +2 -2
- data/lib/graphql/introspection/directive_type.rb +11 -5
- data/lib/graphql/introspection/dynamic_fields.rb +3 -8
- data/lib/graphql/introspection/entry_points.rb +5 -18
- data/lib/graphql/introspection/enum_value_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +9 -5
- data/lib/graphql/introspection/input_value_type.rb +41 -11
- data/lib/graphql/introspection/introspection_query.rb +6 -92
- data/lib/graphql/introspection/schema_type.rb +10 -10
- data/lib/graphql/introspection/type_type.rb +34 -17
- data/lib/graphql/introspection.rb +100 -0
- data/lib/graphql/invalid_null_error.rb +18 -0
- data/lib/graphql/language/block_string.rb +20 -5
- data/lib/graphql/language/cache.rb +37 -0
- data/lib/graphql/language/definition_slice.rb +21 -10
- data/lib/graphql/language/document_from_schema_definition.rb +104 -68
- data/lib/graphql/language/lexer.rb +83 -40
- data/lib/graphql/language/lexer.rl +31 -9
- data/lib/graphql/language/nodes.rb +64 -93
- data/lib/graphql/language/parser.rb +940 -896
- data/lib/graphql/language/parser.y +130 -103
- data/lib/graphql/language/printer.rb +48 -23
- data/lib/graphql/language/sanitized_printer.rb +222 -0
- data/lib/graphql/language/token.rb +0 -4
- data/lib/graphql/language/visitor.rb +2 -2
- data/lib/graphql/language.rb +3 -1
- data/lib/graphql/name_validator.rb +2 -7
- data/lib/graphql/pagination/active_record_relation_connection.rb +85 -0
- data/lib/graphql/pagination/array_connection.rb +79 -0
- data/lib/graphql/pagination/connection.rb +253 -0
- data/lib/graphql/pagination/connections.rb +135 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
- data/lib/graphql/pagination/relation_connection.rb +228 -0
- data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
- data/lib/graphql/pagination.rb +6 -0
- data/lib/graphql/parse_error.rb +0 -1
- data/lib/graphql/query/context.rb +172 -198
- data/lib/graphql/query/fingerprint.rb +26 -0
- data/lib/graphql/query/input_validation_result.rb +33 -7
- data/lib/graphql/query/null_context.rb +21 -8
- data/lib/graphql/query/validation_pipeline.rb +16 -38
- data/lib/graphql/query/variable_validation_error.rb +3 -3
- data/lib/graphql/query/variables.rb +39 -12
- data/lib/graphql/query.rb +74 -38
- data/lib/graphql/railtie.rb +6 -102
- data/lib/graphql/rake_task/validate.rb +4 -1
- data/lib/graphql/rake_task.rb +41 -10
- data/lib/graphql/relay/range_add.rb +17 -10
- data/lib/graphql/relay.rb +0 -15
- 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/schema/addition.rb +245 -0
- data/lib/graphql/schema/argument.rb +286 -31
- 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 +334 -220
- data/lib/graphql/schema/built_in_types.rb +5 -5
- data/lib/graphql/schema/directive/deprecated.rb +18 -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 +2 -2
- data/lib/graphql/schema/directive/one_of.rb +12 -0
- data/lib/graphql/schema/directive/skip.rb +2 -2
- data/lib/graphql/schema/directive/transform.rb +14 -2
- data/lib/graphql/schema/directive.rb +117 -14
- data/lib/graphql/schema/enum.rb +113 -22
- data/lib/graphql/schema/enum_value.rb +16 -21
- data/lib/graphql/schema/field/connection_extension.rb +50 -20
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +491 -329
- data/lib/graphql/schema/field_extension.rb +89 -2
- data/lib/graphql/schema/find_inherited_value.rb +17 -1
- data/lib/graphql/schema/finder.rb +16 -14
- data/lib/graphql/schema/input_object.rb +182 -60
- data/lib/graphql/schema/interface.rb +28 -43
- data/lib/graphql/schema/introspection_system.rb +101 -38
- data/lib/graphql/schema/late_bound_type.rb +7 -2
- data/lib/graphql/schema/list.rb +61 -3
- data/lib/graphql/schema/loader.rb +144 -102
- data/lib/graphql/schema/member/base_dsl_methods.rb +33 -32
- data/lib/graphql/schema/member/build_type.rb +24 -15
- data/lib/graphql/schema/member/has_arguments.rb +261 -24
- data/lib/graphql/schema/member/has_ast_node.rb +20 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
- data/lib/graphql/schema/member/has_directives.rb +113 -0
- data/lib/graphql/schema/member/has_fields.rb +99 -34
- data/lib/graphql/schema/member/has_interfaces.rb +88 -0
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
- data/lib/graphql/schema/member/has_validators.rb +31 -0
- data/lib/graphql/schema/member/relay_shortcuts.rb +28 -2
- data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
- data/lib/graphql/schema/member/validates_input.rb +33 -0
- data/lib/graphql/schema/member.rb +11 -6
- data/lib/graphql/schema/mutation.rb +4 -9
- data/lib/graphql/schema/non_null.rb +34 -4
- data/lib/graphql/schema/object.rb +38 -60
- data/lib/graphql/schema/printer.rb +16 -35
- data/lib/graphql/schema/relay_classic_mutation.rb +90 -43
- data/lib/graphql/schema/resolver/has_payload_type.rb +46 -6
- data/lib/graphql/schema/resolver.rb +146 -93
- data/lib/graphql/schema/scalar.rb +40 -15
- data/lib/graphql/schema/subscription.rb +55 -26
- data/lib/graphql/schema/timeout.rb +29 -15
- data/lib/graphql/schema/type_expression.rb +21 -13
- data/lib/graphql/schema/type_membership.rb +22 -5
- data/lib/graphql/schema/union.rb +48 -14
- data/lib/graphql/schema/unique_within_type.rb +1 -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 +187 -33
- data/lib/graphql/schema/wrapper.rb +0 -5
- data/lib/graphql/schema.rb +773 -892
- data/lib/graphql/static_validation/all_rules.rb +3 -0
- data/lib/graphql/static_validation/base_visitor.rb +21 -31
- data/lib/graphql/static_validation/definition_dependencies.rb +7 -2
- data/lib/graphql/static_validation/error.rb +3 -1
- data/lib/graphql/static_validation/literal_validator.rb +55 -26
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +45 -83
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +22 -6
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +35 -26
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +12 -6
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +14 -14
- 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 +94 -51
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- 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/one_of_input_objects_are_valid.rb +66 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -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 +9 -10
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +13 -7
- 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 +19 -14
- 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 +13 -3
- data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
- data/lib/graphql/static_validation/validator.rb +31 -19
- data/lib/graphql/static_validation.rb +1 -2
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +129 -22
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +58 -0
- data/lib/graphql/subscriptions/event.rb +85 -31
- data/lib/graphql/subscriptions/instrumentation.rb +0 -47
- data/lib/graphql/subscriptions/serialize.rb +53 -6
- data/lib/graphql/subscriptions.rb +137 -57
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
- data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +34 -2
- data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
- data/lib/graphql/tracing/notifications_tracing.rb +59 -0
- data/lib/graphql/tracing/platform_tracing.rb +67 -38
- 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/statsd_tracing.rb +42 -0
- data/lib/graphql/tracing.rb +15 -36
- 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 +20 -9
- data/lib/graphql/types/iso_8601_date_time.rb +36 -10
- data/lib/graphql/types/relay/base_connection.rb +18 -90
- data/lib/graphql/types/relay/base_edge.rb +2 -34
- data/lib/graphql/types/relay/connection_behaviors.rb +158 -0
- data/lib/graphql/types/relay/default_relay.rb +27 -0
- data/lib/graphql/types/relay/edge_behaviors.rb +65 -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 +19 -0
- 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 -5
- data/lib/graphql/types/string.rb +8 -2
- data/lib/graphql/unauthorized_error.rb +2 -2
- data/lib/graphql/unresolved_type_error.rb +2 -2
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +41 -58
- data/readme.md +3 -6
- metadata +103 -237
- data/lib/graphql/analysis/analyze_query.rb +0 -91
- data/lib/graphql/analysis/field_usage.rb +0 -45
- data/lib/graphql/analysis/max_query_complexity.rb +0 -26
- data/lib/graphql/analysis/max_query_depth.rb +0 -26
- data/lib/graphql/analysis/query_complexity.rb +0 -88
- data/lib/graphql/analysis/query_depth.rb +0 -43
- data/lib/graphql/analysis/reducer_state.rb +0 -48
- data/lib/graphql/argument.rb +0 -159
- data/lib/graphql/authorization.rb +0 -82
- data/lib/graphql/backwards_compatibility.rb +0 -60
- data/lib/graphql/base_type.rb +0 -226
- data/lib/graphql/boolean_type.rb +0 -2
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
- data/lib/graphql/compatibility/execution_specification.rb +0 -435
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
- data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -213
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -91
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
- data/lib/graphql/compatibility/query_parser_specification.rb +0 -264
- data/lib/graphql/compatibility/schema_parser_specification.rb +0 -680
- data/lib/graphql/compatibility.rb +0 -5
- data/lib/graphql/define/assign_argument.rb +0 -12
- data/lib/graphql/define/assign_connection.rb +0 -13
- data/lib/graphql/define/assign_enum_value.rb +0 -18
- data/lib/graphql/define/assign_global_id_field.rb +0 -11
- data/lib/graphql/define/assign_mutation_function.rb +0 -34
- data/lib/graphql/define/assign_object_field.rb +0 -42
- data/lib/graphql/define/defined_object_proxy.rb +0 -53
- data/lib/graphql/define/instance_definable.rb +0 -311
- data/lib/graphql/define/no_definition_error.rb +0 -7
- data/lib/graphql/define/non_null_with_bang.rb +0 -16
- data/lib/graphql/define/type_definer.rb +0 -31
- data/lib/graphql/define.rb +0 -31
- data/lib/graphql/deprecated_dsl.rb +0 -42
- data/lib/graphql/directive/deprecated_directive.rb +0 -13
- data/lib/graphql/directive/include_directive.rb +0 -2
- data/lib/graphql/directive/skip_directive.rb +0 -2
- data/lib/graphql/directive.rb +0 -104
- data/lib/graphql/enum_type.rb +0 -193
- data/lib/graphql/execution/execute.rb +0 -326
- data/lib/graphql/execution/flatten.rb +0 -40
- data/lib/graphql/execution/instrumentation.rb +0 -92
- data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
- data/lib/graphql/execution/lazy/resolve.rb +0 -91
- data/lib/graphql/execution/typecast.rb +0 -50
- data/lib/graphql/field/resolve.rb +0 -59
- data/lib/graphql/field.rb +0 -330
- data/lib/graphql/float_type.rb +0 -2
- data/lib/graphql/function.rb +0 -153
- data/lib/graphql/id_type.rb +0 -2
- data/lib/graphql/input_object_type.rb +0 -154
- data/lib/graphql/int_type.rb +0 -2
- data/lib/graphql/interface_type.rb +0 -86
- data/lib/graphql/internal_representation/document.rb +0 -27
- data/lib/graphql/internal_representation/node.rb +0 -206
- data/lib/graphql/internal_representation/print.rb +0 -51
- data/lib/graphql/internal_representation/rewrite.rb +0 -184
- data/lib/graphql/internal_representation/scope.rb +0 -88
- data/lib/graphql/internal_representation/visit.rb +0 -36
- data/lib/graphql/internal_representation.rb +0 -7
- data/lib/graphql/list_type.rb +0 -80
- data/lib/graphql/literal_validation_error.rb +0 -6
- data/lib/graphql/non_null_type.rb +0 -81
- data/lib/graphql/object_type.rb +0 -141
- data/lib/graphql/query/arguments.rb +0 -187
- data/lib/graphql/query/arguments_cache.rb +0 -25
- data/lib/graphql/query/executor.rb +0 -53
- data/lib/graphql/query/literal_input.rb +0 -116
- data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
- data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
- data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
- data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
- data/lib/graphql/query/serial_execution.rb +0 -39
- data/lib/graphql/relay/array_connection.rb +0 -85
- data/lib/graphql/relay/base_connection.rb +0 -172
- data/lib/graphql/relay/connection_instrumentation.rb +0 -54
- data/lib/graphql/relay/connection_resolve.rb +0 -43
- data/lib/graphql/relay/connection_type.rb +0 -40
- data/lib/graphql/relay/edge.rb +0 -27
- data/lib/graphql/relay/edge_type.rb +0 -18
- data/lib/graphql/relay/edges_instrumentation.rb +0 -40
- data/lib/graphql/relay/global_id_resolve.rb +0 -18
- data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
- data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
- data/lib/graphql/relay/mutation/resolve.rb +0 -56
- data/lib/graphql/relay/mutation/result.rb +0 -38
- data/lib/graphql/relay/mutation.rb +0 -190
- data/lib/graphql/relay/node.rb +0 -36
- data/lib/graphql/relay/page_info.rb +0 -7
- data/lib/graphql/relay/relation_connection.rb +0 -190
- data/lib/graphql/relay/type_extensions.rb +0 -30
- data/lib/graphql/scalar_type.rb +0 -133
- data/lib/graphql/schema/catchall_middleware.rb +0 -35
- data/lib/graphql/schema/default_parse_error.rb +0 -10
- data/lib/graphql/schema/default_type_error.rb +0 -15
- data/lib/graphql/schema/member/accepts_definition.rb +0 -152
- data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -26
- data/lib/graphql/schema/member/instrumentation.rb +0 -132
- data/lib/graphql/schema/middleware_chain.rb +0 -82
- data/lib/graphql/schema/possible_types.rb +0 -39
- data/lib/graphql/schema/rescue_middleware.rb +0 -60
- data/lib/graphql/schema/timeout_middleware.rb +0 -86
- data/lib/graphql/schema/traversal.rb +0 -228
- data/lib/graphql/schema/validation.rb +0 -303
- data/lib/graphql/static_validation/default_visitor.rb +0 -15
- data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
- data/lib/graphql/string_type.rb +0 -2
- data/lib/graphql/subscriptions/subscription_root.rb +0 -74
- data/lib/graphql/tracing/skylight_tracing.rb +0 -62
- 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/graphql/types/relay/node_field.rb +0 -43
- data/lib/graphql/types/relay/nodes_field.rb +0 -45
- data/lib/graphql/union_type.rb +0 -135
- data/lib/graphql/upgrader/member.rb +0 -936
- data/lib/graphql/upgrader/schema.rb +0 -37
@@ -1,12 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "securerandom"
|
3
|
+
require "graphql/subscriptions/broadcast_analyzer"
|
3
4
|
require "graphql/subscriptions/event"
|
4
5
|
require "graphql/subscriptions/instrumentation"
|
5
6
|
require "graphql/subscriptions/serialize"
|
6
|
-
|
7
|
-
|
8
|
-
end
|
9
|
-
require "graphql/subscriptions/subscription_root"
|
7
|
+
require "graphql/subscriptions/action_cable_subscriptions"
|
8
|
+
require "graphql/subscriptions/default_subscription_resolve_extension"
|
10
9
|
|
11
10
|
module GraphQL
|
12
11
|
class Subscriptions
|
@@ -16,39 +15,64 @@ module GraphQL
|
|
16
15
|
class InvalidTriggerError < GraphQL::Error
|
17
16
|
end
|
18
17
|
|
18
|
+
# Raised when either:
|
19
|
+
# - An initial subscription didn't have a value for `context[subscription_scope]`
|
20
|
+
# - Or, an update didn't pass `.trigger(..., scope:)`
|
21
|
+
# When raised, the initial subscription or update fails completely.
|
22
|
+
class SubscriptionScopeMissingError < GraphQL::Error
|
23
|
+
end
|
24
|
+
|
19
25
|
# @see {Subscriptions#initialize} for options, concrete implementations may add options.
|
20
26
|
def self.use(defn, options = {})
|
21
|
-
schema = defn.target
|
22
|
-
|
23
|
-
schema.subscriptions
|
27
|
+
schema = defn.is_a?(Class) ? defn : defn.target
|
28
|
+
|
29
|
+
if schema.subscriptions(inherited: false)
|
30
|
+
raise ArgumentError, "Can't reinstall subscriptions. #{schema} is using #{schema.subscriptions}, can't also add #{self}"
|
31
|
+
end
|
32
|
+
|
24
33
|
instrumentation = Subscriptions::Instrumentation.new(schema: schema)
|
25
|
-
defn.instrument(:field, instrumentation)
|
26
34
|
defn.instrument(:query, instrumentation)
|
35
|
+
options[:schema] = schema
|
36
|
+
schema.subscriptions = self.new(**options)
|
37
|
+
schema.add_subscription_extension_if_necessary
|
27
38
|
nil
|
28
39
|
end
|
29
40
|
|
30
41
|
# @param schema [Class] the GraphQL schema this manager belongs to
|
31
|
-
|
42
|
+
# @param validate_update [Boolean] If false, then validation is skipped when executing updates
|
43
|
+
def initialize(schema:, validate_update: true, broadcast: false, default_broadcastable: false, **rest)
|
44
|
+
if broadcast
|
45
|
+
schema.query_analyzer(Subscriptions::BroadcastAnalyzer)
|
46
|
+
end
|
47
|
+
@default_broadcastable = default_broadcastable
|
32
48
|
@schema = schema
|
49
|
+
@validate_update = validate_update
|
33
50
|
end
|
34
51
|
|
52
|
+
# @return [Boolean] Used when fields don't have `broadcastable:` explicitly set
|
53
|
+
attr_reader :default_broadcastable
|
54
|
+
|
35
55
|
# Fetch subscriptions matching this field + arguments pair
|
36
56
|
# And pass them off to the queue.
|
37
57
|
# @param event_name [String]
|
38
58
|
# @param args [Hash<String, Symbol => Object]
|
39
59
|
# @param object [Object]
|
40
60
|
# @param scope [Symbol, String]
|
61
|
+
# @param context [Hash]
|
41
62
|
# @return [void]
|
42
|
-
def trigger(event_name, args, object, scope: nil)
|
63
|
+
def trigger(event_name, args, object, scope: nil, context: {})
|
64
|
+
# Make something as context-like as possible, even though there isn't a current query:
|
65
|
+
dummy_query = GraphQL::Query.new(@schema, "", validate: false, context: context)
|
66
|
+
context = dummy_query.context
|
43
67
|
event_name = event_name.to_s
|
44
68
|
|
45
69
|
# Try with the verbatim input first:
|
46
|
-
field = @schema.get_field(@schema.subscription, event_name)
|
70
|
+
field = @schema.get_field(@schema.subscription, event_name, context)
|
47
71
|
|
48
72
|
if field.nil?
|
49
73
|
# And if it wasn't found, normalize it:
|
50
74
|
normalized_event_name = normalize_name(event_name)
|
51
|
-
field = @schema.get_field(@schema.subscription, normalized_event_name)
|
75
|
+
field = @schema.get_field(@schema.subscription, normalized_event_name, context)
|
52
76
|
if field.nil?
|
53
77
|
raise InvalidTriggerError, "No subscription matching trigger: #{event_name} (looked for #{@schema.subscription.graphql_name}.#{normalized_event_name})"
|
54
78
|
end
|
@@ -58,13 +82,15 @@ module GraphQL
|
|
58
82
|
end
|
59
83
|
|
60
84
|
# Normalize symbol-keyed args to strings, try camelizing them
|
61
|
-
|
85
|
+
# Should this accept a real context somehow?
|
86
|
+
normalized_args = normalize_arguments(normalized_event_name, field, args, GraphQL::Query::NullContext)
|
62
87
|
|
63
88
|
event = Subscriptions::Event.new(
|
64
89
|
name: normalized_event_name,
|
65
90
|
arguments: normalized_args,
|
66
91
|
field: field,
|
67
92
|
scope: scope,
|
93
|
+
context: context,
|
68
94
|
)
|
69
95
|
execute_all(event, object)
|
70
96
|
end
|
@@ -72,40 +98,73 @@ module GraphQL
|
|
72
98
|
# `event` was triggered on `object`, and `subscription_id` was subscribed,
|
73
99
|
# so it should be updated.
|
74
100
|
#
|
75
|
-
# Load `subscription_id`'s GraphQL data, re-evaluate the query
|
76
|
-
#
|
77
|
-
# This is where a queue may be inserted to push updates in the background.
|
101
|
+
# Load `subscription_id`'s GraphQL data, re-evaluate the query and return the result.
|
78
102
|
#
|
79
103
|
# @param subscription_id [String]
|
80
104
|
# @param event [GraphQL::Subscriptions::Event] The event which was triggered
|
81
105
|
# @param object [Object] The value for the subscription field
|
82
|
-
# @return [
|
83
|
-
def
|
106
|
+
# @return [GraphQL::Query::Result]
|
107
|
+
def execute_update(subscription_id, event, object)
|
84
108
|
# Lookup the saved data for this subscription
|
85
109
|
query_data = read_subscription(subscription_id)
|
110
|
+
if query_data.nil?
|
111
|
+
delete_subscription(subscription_id)
|
112
|
+
return nil
|
113
|
+
end
|
114
|
+
|
86
115
|
# Fetch the required keys from the saved data
|
87
116
|
query_string = query_data.fetch(:query_string)
|
88
117
|
variables = query_data.fetch(:variables)
|
89
118
|
context = query_data.fetch(:context)
|
90
119
|
operation_name = query_data.fetch(:operation_name)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
)
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
120
|
+
execute_options = {
|
121
|
+
query: query_string,
|
122
|
+
context: context,
|
123
|
+
subscription_topic: event.topic,
|
124
|
+
operation_name: operation_name,
|
125
|
+
variables: variables,
|
126
|
+
root_value: object,
|
127
|
+
}
|
128
|
+
|
129
|
+
# merge event's and query's context together
|
130
|
+
context.merge!(event.context) unless event.context.nil? || context.nil?
|
131
|
+
|
132
|
+
execute_options[:validate] = validate_update?(**execute_options)
|
133
|
+
result = @schema.execute(**execute_options)
|
134
|
+
subscriptions_context = result.context.namespace(:subscriptions)
|
135
|
+
if subscriptions_context[:no_update]
|
136
|
+
result = nil
|
137
|
+
end
|
138
|
+
|
139
|
+
unsubscribed = subscriptions_context[:unsubscribed]
|
140
|
+
|
141
|
+
if unsubscribed
|
142
|
+
# `unsubscribe` was called, clean up on our side
|
143
|
+
# TODO also send `{more: false}` to client?
|
144
|
+
delete_subscription(subscription_id)
|
145
|
+
result = nil
|
146
|
+
end
|
147
|
+
|
148
|
+
result
|
149
|
+
end
|
150
|
+
|
151
|
+
# Define this method to customize whether to validate
|
152
|
+
# this subscription when executing an update.
|
153
|
+
#
|
154
|
+
# @return [Boolean] defaults to `true`, or false if `validate: false` is provided.
|
155
|
+
def validate_update?(query:, context:, root_value:, subscription_topic:, operation_name:, variables:)
|
156
|
+
@validate_update
|
157
|
+
end
|
158
|
+
|
159
|
+
# Run the update query for this subscription and deliver it
|
160
|
+
# @see {#execute_update}
|
161
|
+
# @see {#deliver}
|
162
|
+
# @return [void]
|
163
|
+
def execute(subscription_id, event, object)
|
164
|
+
res = execute_update(subscription_id, event, object)
|
165
|
+
if !res.nil?
|
166
|
+
deliver(subscription_id, res)
|
167
|
+
end
|
109
168
|
end
|
110
169
|
|
111
170
|
# Event `event` occurred on `object`,
|
@@ -114,16 +173,6 @@ module GraphQL
|
|
114
173
|
# @param object [Object]
|
115
174
|
# @return [void]
|
116
175
|
def execute_all(event, object)
|
117
|
-
each_subscription_id(event) do |subscription_id|
|
118
|
-
execute(subscription_id, event, object)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
# Get each `subscription_id` subscribed to `event.topic` and yield them
|
123
|
-
# @param event [GraphQL::Subscriptions::Event]
|
124
|
-
# @yieldparam subscription_id [String]
|
125
|
-
# @return [void]
|
126
|
-
def each_subscription_id(event)
|
127
176
|
raise GraphQL::RequiredImplementationMissingError
|
128
177
|
end
|
129
178
|
|
@@ -178,6 +227,16 @@ module GraphQL
|
|
178
227
|
Schema::Member::BuildType.camelize(event_or_arg_name.to_s)
|
179
228
|
end
|
180
229
|
|
230
|
+
# @return [Boolean] if true, then a query like this one would be broadcasted
|
231
|
+
def broadcastable?(query_str, **query_options)
|
232
|
+
query = GraphQL::Query.new(@schema, query_str, **query_options)
|
233
|
+
if !query.valid?
|
234
|
+
raise "Invalid query: #{query.validation_errors.map(&:to_h).inspect}"
|
235
|
+
end
|
236
|
+
GraphQL::Analysis::AST.analyze_query(query, @schema.query_analyzers)
|
237
|
+
query.context.namespace(:subscriptions)[:subscription_broadcastable]
|
238
|
+
end
|
239
|
+
|
181
240
|
private
|
182
241
|
|
183
242
|
# Recursively normalize `args` as belonging to `arg_owner`:
|
@@ -186,32 +245,53 @@ module GraphQL
|
|
186
245
|
# @param arg_owner [GraphQL::Field, GraphQL::BaseType]
|
187
246
|
# @param args [Hash, Array, Any] some GraphQL input value to coerce as `arg_owner`
|
188
247
|
# @return [Any] normalized arguments value
|
189
|
-
def normalize_arguments(event_name, arg_owner, args)
|
248
|
+
def normalize_arguments(event_name, arg_owner, args, context)
|
190
249
|
case arg_owner
|
191
|
-
when GraphQL::Field,
|
250
|
+
when GraphQL::Schema::Field, Class
|
251
|
+
if arg_owner.is_a?(Class) && !arg_owner.kind.input_object?
|
252
|
+
# it's a type, but not an input object
|
253
|
+
return args
|
254
|
+
end
|
192
255
|
normalized_args = {}
|
193
256
|
missing_arg_names = []
|
194
257
|
args.each do |k, v|
|
195
258
|
arg_name = k.to_s
|
196
|
-
arg_defn = arg_owner.
|
259
|
+
arg_defn = arg_owner.get_argument(arg_name, context)
|
197
260
|
if arg_defn
|
198
261
|
normalized_arg_name = arg_name
|
199
262
|
else
|
200
263
|
normalized_arg_name = normalize_name(arg_name)
|
201
|
-
arg_defn = arg_owner.
|
264
|
+
arg_defn = arg_owner.get_argument(normalized_arg_name, context)
|
202
265
|
end
|
203
266
|
|
204
267
|
if arg_defn
|
205
|
-
|
268
|
+
if arg_defn.loads
|
269
|
+
normalized_arg_name = arg_defn.keyword.to_s
|
270
|
+
end
|
271
|
+
normalized = normalize_arguments(event_name, arg_defn.type, v, context)
|
272
|
+
normalized_args[normalized_arg_name] = normalized
|
206
273
|
else
|
207
274
|
# Couldn't find a matching argument definition
|
208
275
|
missing_arg_names << arg_name
|
209
276
|
end
|
210
277
|
end
|
211
278
|
|
279
|
+
# Backfill default values so that trigger arguments
|
280
|
+
# match query arguments.
|
281
|
+
arg_owner.arguments(context).each do |_name, arg_defn|
|
282
|
+
if arg_defn.default_value? && !normalized_args.key?(arg_defn.name)
|
283
|
+
default_value = arg_defn.default_value
|
284
|
+
# We don't have an underlying "object" here, so it can't call methods.
|
285
|
+
# This is broken.
|
286
|
+
normalized_args[arg_defn.name] = arg_defn.prepare_value(nil, default_value, context: context)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
212
290
|
if missing_arg_names.any?
|
213
|
-
arg_owner_name = if arg_owner.is_a?(GraphQL::Field)
|
214
|
-
|
291
|
+
arg_owner_name = if arg_owner.is_a?(GraphQL::Schema::Field)
|
292
|
+
arg_owner.path
|
293
|
+
elsif arg_owner.is_a?(Class)
|
294
|
+
arg_owner.graphql_name
|
215
295
|
else
|
216
296
|
arg_owner.to_s
|
217
297
|
end
|
@@ -219,10 +299,10 @@ module GraphQL
|
|
219
299
|
end
|
220
300
|
|
221
301
|
normalized_args
|
222
|
-
when GraphQL::
|
223
|
-
args.map { |a| normalize_arguments(event_name, arg_owner.of_type, a) }
|
224
|
-
when GraphQL::
|
225
|
-
normalize_arguments(event_name, arg_owner.of_type, args)
|
302
|
+
when GraphQL::Schema::List
|
303
|
+
args.map { |a| normalize_arguments(event_name, arg_owner.of_type, a, context) }
|
304
|
+
when GraphQL::Schema::NonNull
|
305
|
+
normalize_arguments(event_name, arg_owner.of_type, args, context)
|
226
306
|
else
|
227
307
|
args
|
228
308
|
end
|
@@ -1,29 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'graphql/tracing/notifications_tracing'
|
4
|
+
|
3
5
|
module GraphQL
|
4
6
|
module Tracing
|
5
7
|
# This implementation forwards events to ActiveSupport::Notifications
|
6
|
-
# with a `graphql
|
8
|
+
# with a `graphql` suffix.
|
7
9
|
#
|
10
|
+
# @see KEYS for event names
|
8
11
|
module ActiveSupportNotificationsTracing
|
9
12
|
# A cache of frequently-used keys to avoid needless string allocations
|
10
|
-
KEYS =
|
11
|
-
|
12
|
-
"parse" => "graphql.parse",
|
13
|
-
"validate" => "graphql.validate",
|
14
|
-
"analyze_multiplex" => "graphql.analyze_multiplex",
|
15
|
-
"analyze_query" => "graphql.analyze_query",
|
16
|
-
"execute_query" => "graphql.execute_query",
|
17
|
-
"execute_query_lazy" => "graphql.execute_query_lazy",
|
18
|
-
"execute_field" => "graphql.execute_field",
|
19
|
-
"execute_field_lazy" => "graphql.execute_field_lazy",
|
20
|
-
}
|
13
|
+
KEYS = NotificationsTracing::KEYS
|
14
|
+
NOTIFICATIONS_ENGINE = NotificationsTracing.new(ActiveSupport::Notifications) if defined?(ActiveSupport::Notifications)
|
21
15
|
|
22
|
-
def self.trace(key, metadata)
|
23
|
-
|
24
|
-
ActiveSupport::Notifications.instrument(prefixed_key, metadata) do
|
25
|
-
yield
|
26
|
-
end
|
16
|
+
def self.trace(key, metadata, &blk)
|
17
|
+
NOTIFICATIONS_ENGINE.trace(key, metadata, &blk)
|
27
18
|
end
|
28
19
|
end
|
29
20
|
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Tracing
|
5
|
+
|
6
|
+
# This class uses the AppopticsAPM SDK from the appoptics_apm gem to create
|
7
|
+
# traces for GraphQL.
|
8
|
+
#
|
9
|
+
# There are 4 configurations available. They can be set in the
|
10
|
+
# appoptics_apm config file or in code. Please see:
|
11
|
+
# {https://docs.appoptics.com/kb/apm_tracing/ruby/configure}
|
12
|
+
#
|
13
|
+
# AppOpticsAPM::Config[:graphql][:enabled] = true|false
|
14
|
+
# AppOpticsAPM::Config[:graphql][:transaction_name] = true|false
|
15
|
+
# AppOpticsAPM::Config[:graphql][:sanitize_query] = true|false
|
16
|
+
# AppOpticsAPM::Config[:graphql][:remove_comments] = true|false
|
17
|
+
class AppOpticsTracing < GraphQL::Tracing::PlatformTracing
|
18
|
+
# These GraphQL events will show up as 'graphql.prep' spans
|
19
|
+
PREP_KEYS = ['lex', 'parse', 'validate', 'analyze_query', 'analyze_multiplex'].freeze
|
20
|
+
# These GraphQL events will show up as 'graphql.execute' spans
|
21
|
+
EXEC_KEYS = ['execute_multiplex', 'execute_query', 'execute_query_lazy'].freeze
|
22
|
+
|
23
|
+
# During auto-instrumentation this version of AppOpticsTracing is compared
|
24
|
+
# with the version provided in the appoptics_apm gem, so that the newer
|
25
|
+
# version of the class can be used
|
26
|
+
|
27
|
+
def self.version
|
28
|
+
Gem::Version.new('1.0.0')
|
29
|
+
end
|
30
|
+
|
31
|
+
self.platform_keys = {
|
32
|
+
'lex' => 'lex',
|
33
|
+
'parse' => 'parse',
|
34
|
+
'validate' => 'validate',
|
35
|
+
'analyze_query' => 'analyze_query',
|
36
|
+
'analyze_multiplex' => 'analyze_multiplex',
|
37
|
+
'execute_multiplex' => 'execute_multiplex',
|
38
|
+
'execute_query' => 'execute_query',
|
39
|
+
'execute_query_lazy' => 'execute_query_lazy'
|
40
|
+
}
|
41
|
+
|
42
|
+
def platform_trace(platform_key, _key, data)
|
43
|
+
return yield if !defined?(AppOpticsAPM) || gql_config[:enabled] == false
|
44
|
+
|
45
|
+
layer = span_name(platform_key)
|
46
|
+
kvs = metadata(data, layer)
|
47
|
+
kvs[:Key] = platform_key if (PREP_KEYS + EXEC_KEYS).include?(platform_key)
|
48
|
+
|
49
|
+
transaction_name(kvs[:InboundQuery]) if kvs[:InboundQuery] && layer == 'graphql.execute'
|
50
|
+
|
51
|
+
::AppOpticsAPM::SDK.trace(layer, kvs) do
|
52
|
+
kvs.clear # we don't have to send them twice
|
53
|
+
yield
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def platform_field_key(type, field)
|
58
|
+
"graphql.#{type.graphql_name}.#{field.graphql_name}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def platform_authorized_key(type)
|
62
|
+
"graphql.authorized.#{type.graphql_name}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def platform_resolve_type_key(type)
|
66
|
+
"graphql.resolve_type.#{type.graphql_name}"
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def gql_config
|
72
|
+
::AppOpticsAPM::Config[:graphql] ||= {}
|
73
|
+
end
|
74
|
+
|
75
|
+
def transaction_name(query)
|
76
|
+
return if gql_config[:transaction_name] == false ||
|
77
|
+
::AppOpticsAPM::SDK.get_transaction_name
|
78
|
+
|
79
|
+
split_query = query.strip.split(/\W+/, 3)
|
80
|
+
split_query[0] = 'query' if split_query[0].empty?
|
81
|
+
name = "graphql.#{split_query[0..1].join('.')}"
|
82
|
+
|
83
|
+
::AppOpticsAPM::SDK.set_transaction_name(name)
|
84
|
+
end
|
85
|
+
|
86
|
+
def multiplex_transaction_name(names)
|
87
|
+
return if gql_config[:transaction_name] == false ||
|
88
|
+
::AppOpticsAPM::SDK.get_transaction_name
|
89
|
+
|
90
|
+
name = "graphql.multiplex.#{names.join('.')}"
|
91
|
+
name = "#{name[0..251]}..." if name.length > 254
|
92
|
+
|
93
|
+
::AppOpticsAPM::SDK.set_transaction_name(name)
|
94
|
+
end
|
95
|
+
|
96
|
+
def span_name(key)
|
97
|
+
return 'graphql.prep' if PREP_KEYS.include?(key)
|
98
|
+
return 'graphql.execute' if EXEC_KEYS.include?(key)
|
99
|
+
|
100
|
+
key[/^graphql\./] ? key : "graphql.#{key}"
|
101
|
+
end
|
102
|
+
|
103
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
104
|
+
def metadata(data, layer)
|
105
|
+
data.keys.map do |key|
|
106
|
+
case key
|
107
|
+
when :context
|
108
|
+
graphql_context(data[key], layer)
|
109
|
+
when :query
|
110
|
+
graphql_query(data[key])
|
111
|
+
when :query_string
|
112
|
+
graphql_query_string(data[key])
|
113
|
+
when :multiplex
|
114
|
+
graphql_multiplex(data[key])
|
115
|
+
when :path
|
116
|
+
[key, data[key].join(".")]
|
117
|
+
else
|
118
|
+
[key, data[key]]
|
119
|
+
end
|
120
|
+
end.flatten(2).each_slice(2).to_h.merge(Spec: 'graphql')
|
121
|
+
end
|
122
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
123
|
+
|
124
|
+
def graphql_context(context, layer)
|
125
|
+
context.errors && context.errors.each do |err|
|
126
|
+
AppOpticsAPM::API.log_exception(layer, err)
|
127
|
+
end
|
128
|
+
|
129
|
+
[[:Path, context.path.join('.')]]
|
130
|
+
end
|
131
|
+
|
132
|
+
def graphql_query(query)
|
133
|
+
return [] unless query
|
134
|
+
|
135
|
+
query_string = query.query_string
|
136
|
+
query_string = remove_comments(query_string) if gql_config[:remove_comments] != false
|
137
|
+
query_string = sanitize(query_string) if gql_config[:sanitize_query] != false
|
138
|
+
|
139
|
+
[[:InboundQuery, query_string],
|
140
|
+
[:Operation, query.selected_operation_name]]
|
141
|
+
end
|
142
|
+
|
143
|
+
def graphql_query_string(query_string)
|
144
|
+
query_string = remove_comments(query_string) if gql_config[:remove_comments] != false
|
145
|
+
query_string = sanitize(query_string) if gql_config[:sanitize_query] != false
|
146
|
+
|
147
|
+
[:InboundQuery, query_string]
|
148
|
+
end
|
149
|
+
|
150
|
+
def graphql_multiplex(data)
|
151
|
+
names = data.queries.map(&:operations).map(&:keys).flatten.compact
|
152
|
+
multiplex_transaction_name(names) if names.size > 1
|
153
|
+
|
154
|
+
[:Operations, names.join(', ')]
|
155
|
+
end
|
156
|
+
|
157
|
+
def sanitize(query)
|
158
|
+
return unless query
|
159
|
+
|
160
|
+
# remove arguments
|
161
|
+
query.gsub(/"[^"]*"/, '"?"') # strings
|
162
|
+
.gsub(/-?[0-9]*\.?[0-9]+e?[0-9]*/, '?') # ints + floats
|
163
|
+
.gsub(/\[[^\]]*\]/, '[?]') # arrays
|
164
|
+
end
|
165
|
+
|
166
|
+
def remove_comments(query)
|
167
|
+
return unless query
|
168
|
+
|
169
|
+
query.gsub(/#[^\n\r]*/, '')
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -14,7 +14,22 @@ module GraphQL
|
|
14
14
|
"execute_query_lazy" => "execute.graphql",
|
15
15
|
}
|
16
16
|
|
17
|
+
# @param set_action_name [Boolean] If true, the GraphQL operation name will be used as the transaction name.
|
18
|
+
# This is not advised if you run more than one query per HTTP request, for example, with `graphql-client` or multiplexing.
|
19
|
+
# It can also be specified per-query with `context[:set_appsignal_action_name]`.
|
20
|
+
def initialize(options = {})
|
21
|
+
@set_action_name = options.fetch(:set_action_name, false)
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
17
25
|
def platform_trace(platform_key, key, data)
|
26
|
+
if key == "execute_query"
|
27
|
+
set_this_txn_name = data[:query].context[:set_appsignal_action_name]
|
28
|
+
if set_this_txn_name == true || (set_this_txn_name.nil? && @set_action_name)
|
29
|
+
Appsignal::Transaction.current.set_action(transaction_name(data[:query]))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
18
33
|
Appsignal.instrument(platform_key) do
|
19
34
|
yield
|
20
35
|
end
|
@@ -23,6 +38,14 @@ module GraphQL
|
|
23
38
|
def platform_field_key(type, field)
|
24
39
|
"#{type.graphql_name}.#{field.graphql_name}.graphql"
|
25
40
|
end
|
41
|
+
|
42
|
+
def platform_authorized_key(type)
|
43
|
+
"#{type.graphql_name}.authorized.graphql"
|
44
|
+
end
|
45
|
+
|
46
|
+
def platform_resolve_type_key(type)
|
47
|
+
"#{type.graphql_name}.resolve_type.graphql"
|
48
|
+
end
|
26
49
|
end
|
27
50
|
end
|
28
51
|
end
|
@@ -17,10 +17,21 @@ module GraphQL
|
|
17
17
|
def platform_trace(platform_key, key, data)
|
18
18
|
tracer.trace(platform_key, service: service_name) do |span|
|
19
19
|
span.span_type = 'custom'
|
20
|
+
if defined?(Datadog::Tracing::Metadata::Ext) # Introduced in ddtrace 1.0
|
21
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT, 'graphql')
|
22
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION, key)
|
23
|
+
end
|
20
24
|
|
21
25
|
if key == 'execute_multiplex'
|
22
26
|
operations = data[:multiplex].queries.map(&:selected_operation_name).join(', ')
|
23
|
-
|
27
|
+
|
28
|
+
resource = if operations.empty?
|
29
|
+
first_query = data[:multiplex].queries.first
|
30
|
+
fallback_transaction_name(first_query && first_query.context)
|
31
|
+
else
|
32
|
+
operations
|
33
|
+
end
|
34
|
+
span.resource = resource if resource
|
24
35
|
|
25
36
|
# For top span of query, set the analytics sample rate tag, if available.
|
26
37
|
if analytics_enabled?
|
@@ -34,6 +45,8 @@ module GraphQL
|
|
34
45
|
span.set_tag(:query_string, data[:query].query_string)
|
35
46
|
end
|
36
47
|
|
48
|
+
prepare_span(key, data, span)
|
49
|
+
|
37
50
|
yield
|
38
51
|
end
|
39
52
|
end
|
@@ -42,8 +55,17 @@ module GraphQL
|
|
42
55
|
options.fetch(:service, 'ruby-graphql')
|
43
56
|
end
|
44
57
|
|
58
|
+
# Implement this method in a subclass to apply custom tags to datadog spans
|
59
|
+
# @param key [String] The event being traced
|
60
|
+
# @param data [Hash] The runtime data for this event (@see GraphQL::Tracing for keys for each event)
|
61
|
+
# @param span [Datadog::Tracing::SpanOperation] The datadog span for this event
|
62
|
+
def prepare_span(key, data, span)
|
63
|
+
end
|
64
|
+
|
45
65
|
def tracer
|
46
|
-
|
66
|
+
default_tracer = defined?(Datadog::Tracing) ? Datadog::Tracing : Datadog.tracer
|
67
|
+
|
68
|
+
options.fetch(:tracer, default_tracer)
|
47
69
|
end
|
48
70
|
|
49
71
|
def analytics_available?
|
@@ -53,16 +75,26 @@ module GraphQL
|
|
53
75
|
end
|
54
76
|
|
55
77
|
def analytics_enabled?
|
78
|
+
# [Deprecated] options[:analytics_enabled] will be removed in the future
|
56
79
|
analytics_available? && Datadog::Contrib::Analytics.enabled?(options.fetch(:analytics_enabled, false))
|
57
80
|
end
|
58
81
|
|
59
82
|
def analytics_sample_rate
|
83
|
+
# [Deprecated] options[:analytics_sample_rate] will be removed in the future
|
60
84
|
options.fetch(:analytics_sample_rate, 1.0)
|
61
85
|
end
|
62
86
|
|
63
87
|
def platform_field_key(type, field)
|
64
88
|
"#{type.graphql_name}.#{field.graphql_name}"
|
65
89
|
end
|
90
|
+
|
91
|
+
def platform_authorized_key(type)
|
92
|
+
"#{type.graphql_name}.authorized"
|
93
|
+
end
|
94
|
+
|
95
|
+
def platform_resolve_type_key(type)
|
96
|
+
"#{type.graphql_name}.resolve_type"
|
97
|
+
end
|
66
98
|
end
|
67
99
|
end
|
68
100
|
end
|
@@ -26,18 +26,7 @@ module GraphQL
|
|
26
26
|
if key == "execute_query"
|
27
27
|
set_this_txn_name = data[:query].context[:set_new_relic_transaction_name]
|
28
28
|
if set_this_txn_name == true || (set_this_txn_name.nil? && @set_transaction_name)
|
29
|
-
|
30
|
-
# Set the transaction name based on the operation type and name
|
31
|
-
selected_op = query.selected_operation
|
32
|
-
if selected_op
|
33
|
-
op_type = selected_op.operation_type
|
34
|
-
op_name = selected_op.name || "anonymous"
|
35
|
-
else
|
36
|
-
op_type = "query"
|
37
|
-
op_name = "anonymous"
|
38
|
-
end
|
39
|
-
|
40
|
-
NewRelic::Agent.set_transaction_name("GraphQL/#{op_type}.#{op_name}")
|
29
|
+
NewRelic::Agent.set_transaction_name(transaction_name(data[:query]))
|
41
30
|
end
|
42
31
|
end
|
43
32
|
|
@@ -49,6 +38,14 @@ module GraphQL
|
|
49
38
|
def platform_field_key(type, field)
|
50
39
|
"GraphQL/#{type.graphql_name}/#{field.graphql_name}"
|
51
40
|
end
|
41
|
+
|
42
|
+
def platform_authorized_key(type)
|
43
|
+
"GraphQL/Authorize/#{type.graphql_name}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def platform_resolve_type_key(type)
|
47
|
+
"GraphQL/ResolveType/#{type.graphql_name}"
|
48
|
+
end
|
52
49
|
end
|
53
50
|
end
|
54
51
|
end
|