graphql 1.12.12 → 2.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/generators/graphql/core.rb +3 -8
- data/lib/generators/graphql/enum_generator.rb +4 -10
- data/lib/generators/graphql/field_extractor.rb +31 -0
- data/lib/generators/graphql/input_generator.rb +50 -0
- data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
- data/lib/generators/graphql/{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 +60 -4
- data/lib/generators/graphql/interface_generator.rb +7 -7
- 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 +5 -30
- data/lib/generators/graphql/mutation_update_generator.rb +22 -0
- data/lib/generators/graphql/object_generator.rb +10 -38
- data/lib/generators/graphql/orm_mutations_base.rb +40 -0
- data/lib/generators/graphql/relay.rb +23 -12
- 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 +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/enum.erb +5 -1
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
- data/lib/generators/graphql/templates/input.erb +9 -0
- data/lib/generators/graphql/templates/interface.erb +4 -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 +2 -0
- data/lib/generators/graphql/templates/object.erb +4 -2
- data/lib/generators/graphql/templates/query_type.erb +2 -0
- data/lib/generators/graphql/templates/scalar.erb +3 -1
- data/lib/generators/graphql/templates/schema.erb +22 -2
- data/lib/generators/graphql/templates/union.erb +4 -2
- data/lib/generators/graphql/type_generator.rb +46 -10
- data/lib/generators/graphql/union_generator.rb +5 -5
- data/lib/graphql/analysis/analyzer.rb +89 -0
- data/lib/graphql/analysis/field_usage.rb +65 -28
- data/lib/graphql/analysis/max_query_complexity.rb +11 -17
- data/lib/graphql/analysis/max_query_depth.rb +13 -19
- data/lib/graphql/analysis/query_complexity.rb +156 -61
- data/lib/graphql/analysis/query_depth.rb +38 -23
- data/lib/graphql/analysis/visitor.rb +283 -0
- data/lib/graphql/analysis.rb +90 -6
- data/lib/graphql/autoload.rb +38 -0
- data/lib/graphql/backtrace/inspect_result.rb +0 -12
- data/lib/graphql/backtrace/table.rb +4 -22
- data/lib/graphql/backtrace/trace.rb +93 -0
- data/lib/graphql/backtrace/tracer.rb +8 -6
- data/lib/graphql/backtrace.rb +3 -8
- data/lib/graphql/coercion_error.rb +1 -9
- data/lib/graphql/current.rb +52 -0
- data/lib/graphql/dataloader/async_dataloader.rb +89 -0
- data/lib/graphql/dataloader/null_dataloader.rb +4 -2
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +125 -33
- data/lib/graphql/dataloader.rb +193 -143
- data/lib/graphql/date_encoding_error.rb +16 -0
- data/lib/graphql/dig.rb +1 -1
- data/lib/graphql/duration_encoding_error.rb +16 -0
- data/lib/graphql/execution/errors.rb +12 -81
- data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
- data/lib/graphql/execution/interpreter/arguments.rb +2 -2
- data/lib/graphql/execution/interpreter/arguments_cache.rb +33 -36
- data/lib/graphql/execution/interpreter/resolve.rb +38 -4
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +175 -0
- data/lib/graphql/execution/interpreter/runtime.rb +447 -403
- data/lib/graphql/execution/interpreter.rb +126 -80
- data/lib/graphql/execution/lazy.rb +11 -21
- data/lib/graphql/execution/lookahead.rb +133 -55
- data/lib/graphql/execution/multiplex.rb +4 -172
- data/lib/graphql/execution.rb +11 -4
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/introspection/directive_location_enum.rb +2 -2
- data/lib/graphql/introspection/directive_type.rb +6 -4
- data/lib/graphql/introspection/dynamic_fields.rb +3 -8
- data/lib/graphql/introspection/entry_points.rb +11 -18
- data/lib/graphql/introspection/enum_value_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +4 -4
- data/lib/graphql/introspection/input_value_type.rb +10 -4
- data/lib/graphql/introspection/schema_type.rb +17 -15
- data/lib/graphql/introspection/type_type.rb +29 -16
- data/lib/graphql/introspection.rb +6 -2
- data/lib/graphql/invalid_null_error.rb +1 -1
- data/lib/graphql/language/block_string.rb +37 -25
- 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 +122 -81
- data/lib/graphql/language/lexer.rb +364 -1467
- data/lib/graphql/language/nodes.rb +197 -106
- data/lib/graphql/language/parser.rb +799 -1920
- data/lib/graphql/language/printer.rb +372 -160
- data/lib/graphql/language/sanitized_printer.rb +25 -27
- data/lib/graphql/language/static_visitor.rb +167 -0
- data/lib/graphql/language/visitor.rb +188 -141
- data/lib/graphql/language.rb +62 -1
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/name_validator.rb +0 -4
- data/lib/graphql/pagination/active_record_relation_connection.rb +37 -8
- data/lib/graphql/pagination/array_connection.rb +8 -6
- data/lib/graphql/pagination/connection.rb +61 -7
- data/lib/graphql/pagination/connections.rb +22 -23
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
- data/lib/graphql/pagination/relation_connection.rb +60 -28
- data/lib/graphql/query/context/scoped_context.rb +101 -0
- data/lib/graphql/query/context.rb +146 -222
- data/lib/graphql/query/input_validation_result.rb +10 -1
- data/lib/graphql/query/null_context.rb +15 -32
- data/lib/graphql/query/validation_pipeline.rb +15 -39
- data/lib/graphql/query/variable_validation_error.rb +3 -3
- data/lib/graphql/query/variables.rb +35 -17
- data/lib/graphql/query.rb +149 -82
- data/lib/graphql/railtie.rb +15 -109
- data/lib/graphql/rake_task/validate.rb +1 -1
- data/lib/graphql/rake_task.rb +30 -11
- data/lib/graphql/relay/range_add.rb +9 -16
- 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/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 +6 -0
- data/lib/graphql/schema/addition.rb +98 -54
- data/lib/graphql/schema/always_visible.rb +14 -0
- data/lib/graphql/schema/argument.rb +179 -82
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +77 -39
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/directive/flagged.rb +4 -4
- data/lib/graphql/schema/directive/include.rb +1 -1
- data/lib/graphql/schema/directive/one_of.rb +24 -0
- data/lib/graphql/schema/directive/skip.rb +1 -1
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive/transform.rb +2 -2
- data/lib/graphql/schema/directive.rb +36 -22
- data/lib/graphql/schema/enum.rb +158 -63
- data/lib/graphql/schema/enum_value.rb +12 -21
- data/lib/graphql/schema/field/connection_extension.rb +7 -17
- data/lib/graphql/schema/field/scope_extension.rb +8 -1
- data/lib/graphql/schema/field.rb +521 -359
- data/lib/graphql/schema/field_extension.rb +86 -2
- data/lib/graphql/schema/find_inherited_value.rb +3 -7
- data/lib/graphql/schema/finder.rb +5 -5
- data/lib/graphql/schema/has_single_input_argument.rb +160 -0
- data/lib/graphql/schema/input_object.rb +148 -99
- data/lib/graphql/schema/interface.rb +41 -64
- data/lib/graphql/schema/introspection_system.rb +12 -26
- data/lib/graphql/schema/late_bound_type.rb +12 -2
- data/lib/graphql/schema/list.rb +18 -7
- data/lib/graphql/schema/loader.rb +6 -5
- data/lib/graphql/schema/member/base_dsl_methods.rb +32 -18
- data/lib/graphql/schema/member/build_type.rb +16 -13
- data/lib/graphql/schema/member/has_arguments.rb +270 -86
- data/lib/graphql/schema/member/has_ast_node.rb +12 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
- data/lib/graphql/schema/member/has_directives.rb +81 -61
- data/lib/graphql/schema/member/has_fields.rb +169 -31
- data/lib/graphql/schema/member/has_interfaces.rb +143 -0
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- data/lib/graphql/schema/member/has_validators.rb +32 -6
- data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +16 -0
- data/lib/graphql/schema/member/validates_input.rb +6 -6
- data/lib/graphql/schema/member.rb +1 -6
- data/lib/graphql/schema/mutation.rb +7 -9
- data/lib/graphql/schema/non_null.rb +7 -7
- data/lib/graphql/schema/object.rb +38 -119
- data/lib/graphql/schema/printer.rb +24 -25
- data/lib/graphql/schema/relay_classic_mutation.rb +13 -91
- data/lib/graphql/schema/resolver/has_payload_type.rb +46 -11
- data/lib/graphql/schema/resolver.rb +118 -115
- data/lib/graphql/schema/scalar.rb +20 -21
- data/lib/graphql/schema/subscription.rb +95 -21
- data/lib/graphql/schema/timeout.rb +25 -29
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/type_membership.rb +21 -4
- data/lib/graphql/schema/union.rb +16 -16
- 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/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 +3 -1
- data/lib/graphql/schema/validator/format_validator.rb +4 -5
- data/lib/graphql/schema/validator/inclusion_validator.rb +3 -1
- data/lib/graphql/schema/validator/length_validator.rb +5 -3
- data/lib/graphql/schema/validator/numericality_validator.rb +13 -2
- data/lib/graphql/schema/validator/required_validator.rb +56 -18
- data/lib/graphql/schema/validator.rb +38 -28
- data/lib/graphql/schema/visibility/migration.rb +188 -0
- data/lib/graphql/schema/visibility/profile.rb +359 -0
- data/lib/graphql/schema/visibility/visit.rb +190 -0
- data/lib/graphql/schema/visibility.rb +294 -0
- data/lib/graphql/schema/warden.rb +423 -134
- data/lib/graphql/schema/wrapper.rb +0 -5
- data/lib/graphql/schema.rb +1015 -1057
- data/lib/graphql/static_validation/all_rules.rb +3 -1
- data/lib/graphql/static_validation/base_visitor.rb +15 -28
- 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 +24 -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 +4 -3
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +13 -7
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +15 -13
- 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 +13 -5
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +62 -35
- 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/fragment_types_exist.rb +12 -2
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -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/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 +7 -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.rb +1 -1
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +14 -8
- 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 +14 -8
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +11 -2
- data/lib/graphql/static_validation/validation_context.rb +32 -6
- data/lib/graphql/static_validation/validator.rb +11 -27
- data/lib/graphql/static_validation.rb +0 -3
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +49 -11
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +40 -1
- data/lib/graphql/subscriptions/event.rb +87 -38
- data/lib/graphql/subscriptions/serialize.rb +27 -3
- data/lib/graphql/subscriptions.rb +63 -49
- data/lib/graphql/testing/helpers.rb +155 -0
- data/lib/graphql/testing.rb +2 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +6 -20
- data/lib/graphql/tracing/appoptics_trace.rb +253 -0
- data/lib/graphql/tracing/appoptics_tracing.rb +4 -2
- data/lib/graphql/tracing/appsignal_trace.rb +79 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +17 -0
- data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
- data/lib/graphql/tracing/data_dog_trace.rb +185 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +27 -15
- data/lib/graphql/{execution/instrumentation.rb → tracing/legacy_hooks_trace.rb} +11 -28
- data/lib/graphql/tracing/legacy_trace.rb +12 -0
- data/lib/graphql/tracing/new_relic_trace.rb +77 -0
- data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
- data/lib/graphql/tracing/notifications_trace.rb +45 -0
- data/lib/graphql/tracing/notifications_tracing.rb +61 -0
- data/lib/graphql/tracing/null_trace.rb +9 -0
- data/lib/graphql/tracing/platform_trace.rb +118 -0
- data/lib/graphql/tracing/platform_tracing.rb +46 -49
- data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +6 -2
- data/lib/graphql/tracing/prometheus_trace.rb +94 -0
- data/lib/graphql/tracing/prometheus_tracing.rb +5 -3
- data/lib/graphql/tracing/scout_trace.rb +74 -0
- data/lib/graphql/tracing/scout_tracing.rb +2 -0
- data/lib/graphql/tracing/sentry_trace.rb +114 -0
- data/lib/graphql/tracing/statsd_trace.rb +58 -0
- data/lib/graphql/tracing/statsd_tracing.rb +2 -0
- data/lib/graphql/tracing/trace.rb +79 -0
- data/lib/graphql/tracing.rb +29 -52
- data/lib/graphql/type_kinds.rb +7 -4
- data/lib/graphql/types/big_int.rb +5 -1
- data/lib/graphql/types/int.rb +1 -1
- data/lib/graphql/types/iso_8601_date.rb +17 -6
- data/lib/graphql/types/iso_8601_date_time.rb +12 -1
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/base_connection.rb +16 -6
- data/lib/graphql/types/relay/connection_behaviors.rb +92 -32
- data/lib/graphql/types/relay/edge_behaviors.rb +46 -7
- data/lib/graphql/types/relay/has_node_field.rb +2 -2
- data/lib/graphql/types/relay/has_nodes_field.rb +2 -2
- data/lib/graphql/types/relay/node_behaviors.rb +12 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +11 -2
- data/lib/graphql/types/relay.rb +0 -3
- data/lib/graphql/types/string.rb +2 -2
- data/lib/graphql/types.rb +18 -10
- data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
- data/lib/graphql/unauthorized_error.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +82 -137
- data/readme.md +13 -6
- metadata +127 -186
- data/lib/graphql/analysis/analyze_query.rb +0 -98
- data/lib/graphql/analysis/ast/analyzer.rb +0 -84
- data/lib/graphql/analysis/ast/field_usage.rb +0 -28
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -23
- data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
- data/lib/graphql/analysis/ast/query_complexity.rb +0 -234
- data/lib/graphql/analysis/ast/query_depth.rb +0 -56
- data/lib/graphql/analysis/ast/visitor.rb +0 -268
- data/lib/graphql/analysis/ast.rb +0 -91
- data/lib/graphql/analysis/reducer_state.rb +0 -48
- data/lib/graphql/argument.rb +0 -131
- data/lib/graphql/authorization.rb +0 -82
- data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
- data/lib/graphql/backwards_compatibility.rb +0 -61
- data/lib/graphql/base_type.rb +0 -230
- 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 -436
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
- data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
- data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
- data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
- 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 -240
- 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 -47
- data/lib/graphql/deprecation.rb +0 -13
- data/lib/graphql/directive/deprecated_directive.rb +0 -2
- data/lib/graphql/directive/include_directive.rb +0 -2
- data/lib/graphql/directive/skip_directive.rb +0 -2
- data/lib/graphql/directive.rb +0 -111
- data/lib/graphql/enum_type.rb +0 -129
- data/lib/graphql/execution/execute.rb +0 -333
- data/lib/graphql/execution/flatten.rb +0 -40
- 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 -226
- data/lib/graphql/filter.rb +0 -53
- data/lib/graphql/float_type.rb +0 -2
- data/lib/graphql/function.rb +0 -128
- data/lib/graphql/id_type.rb +0 -2
- data/lib/graphql/input_object_type.rb +0 -138
- data/lib/graphql/int_type.rb +0 -2
- data/lib/graphql/interface_type.rb +0 -72
- 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/language/lexer.rl +0 -262
- data/lib/graphql/language/parser.y +0 -543
- data/lib/graphql/language/token.rb +0 -38
- data/lib/graphql/list_type.rb +0 -80
- data/lib/graphql/non_null_type.rb +0 -71
- data/lib/graphql/object_type.rb +0 -130
- data/lib/graphql/query/arguments.rb +0 -189
- data/lib/graphql/query/arguments_cache.rb +0 -24
- data/lib/graphql/query/executor.rb +0 -52
- data/lib/graphql/query/literal_input.rb +0 -136
- 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 -40
- data/lib/graphql/relay/array_connection.rb +0 -83
- data/lib/graphql/relay/base_connection.rb +0 -189
- 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 -41
- data/lib/graphql/relay/edge.rb +0 -27
- data/lib/graphql/relay/edge_type.rb +0 -19
- 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 -106
- data/lib/graphql/relay/node.rb +0 -39
- data/lib/graphql/relay/page_info.rb +0 -7
- data/lib/graphql/relay/relation_connection.rb +0 -188
- data/lib/graphql/relay/type_extensions.rb +0 -32
- data/lib/graphql/scalar_type.rb +0 -91
- data/lib/graphql/schema/base_64_bp.rb +0 -26
- 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 -17
- data/lib/graphql/schema/invalid_type_error.rb +0 -7
- data/lib/graphql/schema/member/accepts_definition.rb +0 -152
- data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -31
- data/lib/graphql/schema/member/instrumentation.rb +0 -131
- data/lib/graphql/schema/middleware_chain.rb +0 -82
- data/lib/graphql/schema/possible_types.rb +0 -44
- data/lib/graphql/schema/rescue_middleware.rb +0 -60
- data/lib/graphql/schema/timeout_middleware.rb +0 -88
- data/lib/graphql/schema/traversal.rb +0 -228
- data/lib/graphql/schema/validation.rb +0 -313
- data/lib/graphql/static_validation/default_visitor.rb +0 -15
- data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
- data/lib/graphql/static_validation/type_stack.rb +0 -216
- data/lib/graphql/string_type.rb +0 -2
- data/lib/graphql/subscriptions/instrumentation.rb +0 -79
- data/lib/graphql/subscriptions/subscription_root.rb +0 -76
- data/lib/graphql/tracing/skylight_tracing.rb +0 -70
- data/lib/graphql/types/relay/default_relay.rb +0 -27
- data/lib/graphql/types/relay/node_field.rb +0 -25
- data/lib/graphql/types/relay/nodes_field.rb +0 -27
- data/lib/graphql/union_type.rb +0 -115
- data/lib/graphql/upgrader/member.rb +0 -937
- data/lib/graphql/upgrader/schema.rb +0 -38
@@ -1,13 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "graphql/static_validation/error"
|
3
3
|
require "graphql/static_validation/definition_dependencies"
|
4
|
-
require "graphql/static_validation/type_stack"
|
5
4
|
require "graphql/static_validation/validator"
|
6
5
|
require "graphql/static_validation/validation_context"
|
7
6
|
require "graphql/static_validation/validation_timeout_error"
|
8
7
|
require "graphql/static_validation/literal_validator"
|
9
8
|
require "graphql/static_validation/base_visitor"
|
10
|
-
require "graphql/static_validation/no_validate_visitor"
|
11
9
|
|
12
10
|
rules_glob = File.expand_path("../static_validation/rules/*.rb", __FILE__)
|
13
11
|
Dir.glob(rules_glob).each do |file|
|
@@ -15,5 +13,4 @@ Dir.glob(rules_glob).each do |file|
|
|
15
13
|
end
|
16
14
|
|
17
15
|
require "graphql/static_validation/all_rules"
|
18
|
-
require "graphql/static_validation/default_visitor"
|
19
16
|
require "graphql/static_validation/interpreter_visitor"
|
@@ -1,10 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module GraphQL
|
3
3
|
class StringEncodingError < GraphQL::RuntimeTypeError
|
4
|
-
attr_reader :string
|
5
|
-
def initialize(str)
|
4
|
+
attr_reader :string, :field, :path
|
5
|
+
def initialize(str, context:)
|
6
6
|
@string = str
|
7
|
-
|
7
|
+
@field = context[:current_field]
|
8
|
+
@path = context[:current_path]
|
9
|
+
message = "String #{str.inspect} was encoded as #{str.encoding}".dup
|
10
|
+
if @path
|
11
|
+
message << " @ #{@path.join(".")}"
|
12
|
+
end
|
13
|
+
if @field
|
14
|
+
message << " (#{@field.path})"
|
15
|
+
end
|
16
|
+
message << ". GraphQL requires an encoding compatible with UTF-8."
|
17
|
+
super(message)
|
8
18
|
end
|
9
19
|
end
|
10
20
|
end
|
@@ -35,7 +35,7 @@ module GraphQL
|
|
35
35
|
# }
|
36
36
|
#
|
37
37
|
# result = MySchema.execute(
|
38
|
-
# query
|
38
|
+
# query,
|
39
39
|
# context: context,
|
40
40
|
# variables: variables,
|
41
41
|
# operation_name: operation_name
|
@@ -91,10 +91,24 @@ module GraphQL
|
|
91
91
|
# A per-process map of subscriptions to deliver.
|
92
92
|
# This is provided by Rails, so let's use it
|
93
93
|
@subscriptions = Concurrent::Map.new
|
94
|
-
@events = Concurrent::Map.new
|
94
|
+
@events = Concurrent::Map.new do |h, k|
|
95
|
+
h.compute_if_absent(k) do
|
96
|
+
Concurrent::Map.new do |h2, k2|
|
97
|
+
h2.compute_if_absent(k2) { Concurrent::Array.new }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
95
101
|
@action_cable = action_cable
|
96
102
|
@action_cable_coder = action_cable_coder
|
97
103
|
@serializer = serializer
|
104
|
+
@serialize_with_context = case @serializer.method(:load).arity
|
105
|
+
when 1
|
106
|
+
false
|
107
|
+
when 2
|
108
|
+
true
|
109
|
+
else
|
110
|
+
raise ArgumentError, "#{@serializer} must respond to `.load` accepting one or two arguments"
|
111
|
+
end
|
98
112
|
@transmit_ns = namespace
|
99
113
|
super
|
100
114
|
end
|
@@ -110,7 +124,8 @@ module GraphQL
|
|
110
124
|
# This subscription was re-evaluated.
|
111
125
|
# Send it to the specific stream where this client was waiting.
|
112
126
|
def deliver(subscription_id, result)
|
113
|
-
|
127
|
+
has_more = !result.context.namespace(:subscriptions)[:final_update]
|
128
|
+
payload = { result: result.to_h, more: has_more }
|
114
129
|
@action_cable.server.broadcast(stream_subscription_name(subscription_id), payload)
|
115
130
|
end
|
116
131
|
|
@@ -119,7 +134,13 @@ module GraphQL
|
|
119
134
|
# It will receive notifications when events come in
|
120
135
|
# and re-evaluate the query locally.
|
121
136
|
def write_subscription(query, events)
|
122
|
-
channel = query.context
|
137
|
+
unless (channel = query.context[:channel])
|
138
|
+
raise GraphQL::Error, "This GraphQL Subscription client does not support the transport protocol expected"\
|
139
|
+
"by the backend Subscription Server implementation (graphql-ruby ActionCableSubscriptions in this case)."\
|
140
|
+
"Some official client implementation including Apollo (https://graphql-ruby.org/javascript_client/apollo_subscriptions.html), "\
|
141
|
+
"Relay Modern (https://graphql-ruby.org/javascript_client/relay_subscriptions.html#actioncable)."\
|
142
|
+
"GraphiQL via `graphiql-rails` may not work out of box (#1051)."
|
143
|
+
end
|
123
144
|
subscription_id = query.context[:subscription_id] ||= build_id
|
124
145
|
stream = stream_subscription_name(subscription_id)
|
125
146
|
channel.stream_from(stream)
|
@@ -145,21 +166,24 @@ module GraphQL
|
|
145
166
|
#
|
146
167
|
def setup_stream(channel, initial_event)
|
147
168
|
topic = initial_event.topic
|
148
|
-
|
169
|
+
event_stream = stream_event_name(initial_event)
|
170
|
+
channel.stream_from(event_stream, coder: @action_cable_coder) do |message|
|
149
171
|
events_by_fingerprint = @events[topic]
|
150
172
|
object = nil
|
151
173
|
events_by_fingerprint.each do |_fingerprint, events|
|
152
|
-
if events.
|
174
|
+
if !events.empty? && events.first == initial_event
|
153
175
|
# The fingerprint has told us that this response should be shared by all subscribers,
|
154
176
|
# so just run it once, then deliver the result to every subscriber
|
155
177
|
first_event = events.first
|
156
178
|
first_subscription_id = first_event.context.fetch(:subscription_id)
|
157
|
-
object ||=
|
179
|
+
object ||= load_action_cable_message(message, first_event.context)
|
158
180
|
result = execute_update(first_subscription_id, first_event, object)
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
181
|
+
if !result.nil?
|
182
|
+
# Having calculated the result _once_, send the same payload to all subscribers
|
183
|
+
events.each do |event|
|
184
|
+
subscription_id = event.context.fetch(:subscription_id)
|
185
|
+
deliver(subscription_id, result)
|
186
|
+
end
|
163
187
|
end
|
164
188
|
end
|
165
189
|
end
|
@@ -167,6 +191,18 @@ module GraphQL
|
|
167
191
|
end
|
168
192
|
end
|
169
193
|
|
194
|
+
# This is called to turn an ActionCable-broadcasted string (JSON)
|
195
|
+
# into a query-ready application object.
|
196
|
+
# @param message [String] n ActionCable-broadcasted string (JSON)
|
197
|
+
# @param context [GraphQL::Query::Context] the context of the first event for a given subscription fingerprint
|
198
|
+
def load_action_cable_message(message, context)
|
199
|
+
if @serialize_with_context
|
200
|
+
@serializer.load(message, context)
|
201
|
+
else
|
202
|
+
@serializer.load(message)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
170
206
|
# Return the query from "storage" (in memory)
|
171
207
|
def read_subscription(subscription_id)
|
172
208
|
query = @subscriptions[subscription_id]
|
@@ -188,6 +224,8 @@ module GraphQL
|
|
188
224
|
# The channel was closed, forget about it.
|
189
225
|
def delete_subscription(subscription_id)
|
190
226
|
query = @subscriptions.delete(subscription_id)
|
227
|
+
# In case this came from the server, tell the client to unsubscribe:
|
228
|
+
@action_cable.server.broadcast(stream_subscription_name(subscription_id), { more: false })
|
191
229
|
# This can be `nil` when `.trigger` happens inside an unsubscribed ActionCable channel,
|
192
230
|
# see https://github.com/rmosolgo/graphql-ruby/issues/2478
|
193
231
|
if query
|
@@ -9,7 +9,7 @@ module GraphQL
|
|
9
9
|
# Assign the result to `context.namespace(:subscriptions)[:subscription_broadcastable]`
|
10
10
|
# @api private
|
11
11
|
# @see Subscriptions#broadcastable? for a public API
|
12
|
-
class BroadcastAnalyzer < GraphQL::Analysis::
|
12
|
+
class BroadcastAnalyzer < GraphQL::Analysis::Analyzer
|
13
13
|
def initialize(subject)
|
14
14
|
super
|
15
15
|
@default_broadcastable = subject.schema.subscriptions.default_broadcastable
|
@@ -28,9 +28,8 @@ module GraphQL
|
|
28
28
|
end
|
29
29
|
|
30
30
|
current_field = visitor.field_definition
|
31
|
-
apply_broadcastable(current_field)
|
32
|
-
|
33
31
|
current_type = visitor.parent_type_definition
|
32
|
+
apply_broadcastable(current_type, current_field)
|
34
33
|
if current_type.kind.interface?
|
35
34
|
pt = @query.possible_types(current_type)
|
36
35
|
pt.each do |object_type|
|
@@ -38,7 +37,7 @@ module GraphQL
|
|
38
37
|
# Inherited fields would be exactly the same object;
|
39
38
|
# only check fields that are overrides of the inherited one
|
40
39
|
if ot_field && ot_field != current_field
|
41
|
-
apply_broadcastable(ot_field)
|
40
|
+
apply_broadcastable(object_type, ot_field)
|
42
41
|
end
|
43
42
|
end
|
44
43
|
end
|
@@ -55,10 +54,16 @@ module GraphQL
|
|
55
54
|
private
|
56
55
|
|
57
56
|
# Modify `@subscription_broadcastable` based on `field_defn`'s configuration (and/or the default value)
|
58
|
-
def apply_broadcastable(field_defn)
|
57
|
+
def apply_broadcastable(owner_type, field_defn)
|
59
58
|
current_field_broadcastable = field_defn.introspection? || field_defn.broadcastable?
|
59
|
+
|
60
|
+
if current_field_broadcastable.nil? && owner_type.respond_to?(:default_broadcastable?)
|
61
|
+
current_field_broadcastable = owner_type.default_broadcastable?
|
62
|
+
end
|
63
|
+
|
60
64
|
case current_field_broadcastable
|
61
65
|
when nil
|
66
|
+
query.logger.debug { "`broadcastable: nil` for field: #{field_defn.path}" }
|
62
67
|
# If the value wasn't set, mix in the default value:
|
63
68
|
# - If the default is false and the current value is true, make it false
|
64
69
|
# - If the default is true and the current value is true, it stays true
|
@@ -66,6 +71,7 @@ module GraphQL
|
|
66
71
|
# - If the default is true and the current value is false, keep it false
|
67
72
|
@subscription_broadcastable = @subscription_broadcastable && @default_broadcastable
|
68
73
|
when false
|
74
|
+
query.logger.debug { "`broadcastable: false` for field: #{field_defn.path}" }
|
69
75
|
# One non-broadcastable field is enough to make the whole subscription non-broadcastable
|
70
76
|
@subscription_broadcastable = false
|
71
77
|
when true
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module GraphQL
|
3
3
|
class Subscriptions
|
4
|
-
class DefaultSubscriptionResolveExtension < GraphQL::
|
4
|
+
class DefaultSubscriptionResolveExtension < GraphQL::Schema::FieldExtension
|
5
5
|
def resolve(context:, object:, arguments:)
|
6
6
|
has_override_implementation = @field.resolver ||
|
7
7
|
object.respond_to?(@field.resolver_method)
|
@@ -16,6 +16,45 @@ module GraphQL
|
|
16
16
|
yield(object, arguments)
|
17
17
|
end
|
18
18
|
end
|
19
|
+
|
20
|
+
def after_resolve(value:, context:, object:, arguments:, **rest)
|
21
|
+
if value.is_a?(GraphQL::ExecutionError)
|
22
|
+
value
|
23
|
+
elsif @field.resolver&.method_defined?(:subscription_written?) &&
|
24
|
+
(subscription_namespace = context.namespace(:subscriptions)) &&
|
25
|
+
(subscriptions_by_path = subscription_namespace[:subscriptions])
|
26
|
+
(subscription_instance = subscriptions_by_path[context.current_path])
|
27
|
+
# If it was already written, don't append this event to be written later
|
28
|
+
if !subscription_instance.subscription_written?
|
29
|
+
events = context.namespace(:subscriptions)[:events]
|
30
|
+
events << subscription_instance.event
|
31
|
+
end
|
32
|
+
value
|
33
|
+
elsif (events = context.namespace(:subscriptions)[:events])
|
34
|
+
# This is the first execution, so gather an Event
|
35
|
+
# for the backend to register:
|
36
|
+
event = Subscriptions::Event.new(
|
37
|
+
name: field.name,
|
38
|
+
arguments: arguments,
|
39
|
+
context: context,
|
40
|
+
field: field,
|
41
|
+
)
|
42
|
+
events << event
|
43
|
+
value
|
44
|
+
elsif context.query.subscription_topic == Subscriptions::Event.serialize(
|
45
|
+
field.name,
|
46
|
+
arguments,
|
47
|
+
field,
|
48
|
+
scope: (field.subscription_scope ? context[field.subscription_scope] : nil),
|
49
|
+
)
|
50
|
+
# This is a subscription update. The resolver returned `skip` if it should be skipped,
|
51
|
+
# or else it returned an object to resolve the update.
|
52
|
+
value
|
53
|
+
else
|
54
|
+
# This is a subscription update, but this event wasn't triggered.
|
55
|
+
context.skip
|
56
|
+
end
|
57
|
+
end
|
19
58
|
end
|
20
59
|
end
|
21
60
|
end
|
@@ -9,7 +9,7 @@ module GraphQL
|
|
9
9
|
# @return [String] Corresponds to the Subscription root field name
|
10
10
|
attr_reader :name
|
11
11
|
|
12
|
-
# @return [GraphQL::
|
12
|
+
# @return [GraphQL::Execution::Interpreter::Arguments]
|
13
13
|
attr_reader :arguments
|
14
14
|
|
15
15
|
# @return [GraphQL::Query::Context]
|
@@ -20,35 +20,28 @@ module GraphQL
|
|
20
20
|
|
21
21
|
def initialize(name:, arguments:, field: nil, context: nil, scope: nil)
|
22
22
|
@name = name
|
23
|
-
@arguments = arguments
|
23
|
+
@arguments = self.class.arguments_without_field_extras(arguments: arguments, field: field)
|
24
24
|
@context = context
|
25
25
|
field ||= context.field
|
26
|
-
|
26
|
+
scope_key = field.subscription_scope
|
27
|
+
scope_val = scope || (context && scope_key && context[scope_key])
|
28
|
+
if scope_key &&
|
29
|
+
(subscription = field.resolver) &&
|
30
|
+
(subscription.respond_to?(:subscription_scope_optional?)) &&
|
31
|
+
!subscription.subscription_scope_optional? &&
|
32
|
+
scope_val.nil?
|
33
|
+
raise Subscriptions::SubscriptionScopeMissingError, "#{field.path} (#{subscription}) requires a `scope:` value to trigger updates (Set `subscription_scope ..., optional: true` to disable this requirement)"
|
34
|
+
end
|
27
35
|
|
28
|
-
@topic = self.class.serialize(name, arguments, field, scope: scope_val)
|
36
|
+
@topic = self.class.serialize(name, arguments, field, scope: scope_val, context: context)
|
29
37
|
end
|
30
38
|
|
31
39
|
# @return [String] an identifier for this unit of subscription
|
32
|
-
def self.serialize(
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
if field.is_a?(GraphQL::Schema::Field)
|
38
|
-
stringify_args(field, arguments)
|
39
|
-
else
|
40
|
-
GraphQL::Query::LiteralInput.from_arguments(
|
41
|
-
arguments,
|
42
|
-
field,
|
43
|
-
nil,
|
44
|
-
)
|
45
|
-
end
|
46
|
-
else
|
47
|
-
raise ArgumentError, "Unexpected arguments: #{arguments}, must be Hash or GraphQL::Arguments"
|
48
|
-
end
|
49
|
-
|
50
|
-
sorted_h = stringify_args(field, normalized_args.to_h)
|
51
|
-
Serialize.dump_recursive([scope, name, sorted_h])
|
40
|
+
def self.serialize(_name, arguments, field, scope:, context: GraphQL::Query::NullContext.instance)
|
41
|
+
subscription = field.resolver || GraphQL::Schema::Subscription
|
42
|
+
arguments = arguments_without_field_extras(field: field, arguments: arguments)
|
43
|
+
normalized_args = stringify_args(field, arguments.to_h, context)
|
44
|
+
subscription.topic_for(arguments: normalized_args, field: field, scope: scope)
|
52
45
|
end
|
53
46
|
|
54
47
|
# @return [String] a logical identifier for this event. (Stable when the query is broadcastable.)
|
@@ -68,38 +61,94 @@ module GraphQL
|
|
68
61
|
end
|
69
62
|
|
70
63
|
class << self
|
64
|
+
def arguments_without_field_extras(arguments:, field:)
|
65
|
+
if !field.extras.empty?
|
66
|
+
arguments = arguments.dup
|
67
|
+
field.extras.each do |extra_key|
|
68
|
+
arguments.delete(extra_key)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
arguments
|
72
|
+
end
|
73
|
+
|
71
74
|
private
|
72
|
-
|
75
|
+
|
76
|
+
# This method does not support cyclic references in the Hash,
|
77
|
+
# nor does it support Hashes whose keys are not sortable
|
78
|
+
# with respect to their peers ( cases where a <=> b might throw an error )
|
79
|
+
def deep_sort_hash_keys(hash_to_sort)
|
80
|
+
raise ArgumentError.new("Argument must be a Hash") unless hash_to_sort.is_a?(Hash)
|
81
|
+
hash_to_sort.keys.sort.map do |k|
|
82
|
+
if hash_to_sort[k].is_a?(Hash)
|
83
|
+
[k, deep_sort_hash_keys(hash_to_sort[k])]
|
84
|
+
elsif hash_to_sort[k].is_a?(Array)
|
85
|
+
[k, deep_sort_array_hashes(hash_to_sort[k])]
|
86
|
+
else
|
87
|
+
[k, hash_to_sort[k]]
|
88
|
+
end
|
89
|
+
end.to_h
|
90
|
+
end
|
91
|
+
|
92
|
+
def deep_sort_array_hashes(array_to_inspect)
|
93
|
+
raise ArgumentError.new("Argument must be an Array") unless array_to_inspect.is_a?(Array)
|
94
|
+
array_to_inspect.map do |v|
|
95
|
+
if v.is_a?(Hash)
|
96
|
+
deep_sort_hash_keys(v)
|
97
|
+
elsif v.is_a?(Array)
|
98
|
+
deep_sort_array_hashes(v)
|
99
|
+
else
|
100
|
+
v
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def stringify_args(arg_owner, args, context)
|
106
|
+
arg_owner = arg_owner.respond_to?(:unwrap) ? arg_owner.unwrap : arg_owner # remove list and non-null wrappers
|
73
107
|
case args
|
74
108
|
when Hash
|
75
109
|
next_args = {}
|
76
110
|
args.each do |k, v|
|
77
111
|
arg_name = k.to_s
|
78
112
|
camelized_arg_name = GraphQL::Schema::Member::BuildType.camelize(arg_name)
|
79
|
-
arg_defn = get_arg_definition(arg_owner, camelized_arg_name)
|
80
|
-
|
81
|
-
|
82
|
-
|
113
|
+
arg_defn = get_arg_definition(arg_owner, camelized_arg_name, context)
|
114
|
+
arg_defn ||= get_arg_definition(arg_owner, arg_name, context)
|
115
|
+
normalized_arg_name = arg_defn.graphql_name
|
116
|
+
arg_base_type = arg_defn.type.unwrap
|
117
|
+
# In the case where the value being emitted is seen as a "JSON"
|
118
|
+
# type, treat the value as one atomic unit of serialization
|
119
|
+
is_json_definition = arg_base_type && arg_base_type <= GraphQL::Types::JSON
|
120
|
+
if is_json_definition
|
121
|
+
sorted_value = if v.is_a?(Hash)
|
122
|
+
deep_sort_hash_keys(v)
|
123
|
+
elsif v.is_a?(Array)
|
124
|
+
deep_sort_array_hashes(v)
|
125
|
+
else
|
126
|
+
v
|
127
|
+
end
|
128
|
+
next_args[normalized_arg_name] = sorted_value.respond_to?(:to_json) ? sorted_value.to_json : sorted_value
|
83
129
|
else
|
84
|
-
normalized_arg_name =
|
85
|
-
arg_defn = get_arg_definition(arg_owner, normalized_arg_name)
|
130
|
+
next_args[normalized_arg_name] = stringify_args(arg_base_type, v, context)
|
86
131
|
end
|
87
|
-
|
88
|
-
next_args[normalized_arg_name] = stringify_args(arg_defn.type, v)
|
89
132
|
end
|
90
133
|
# Make sure they're deeply sorted
|
91
134
|
next_args.sort.to_h
|
92
135
|
when Array
|
93
|
-
args.map { |a| stringify_args(arg_owner, a) }
|
136
|
+
args.map { |a| stringify_args(arg_owner, a, context) }
|
94
137
|
when GraphQL::Schema::InputObject
|
95
|
-
stringify_args(arg_owner, args.to_h)
|
138
|
+
stringify_args(arg_owner, args.to_h, context)
|
96
139
|
else
|
97
|
-
|
140
|
+
if arg_owner.is_a?(Class) && arg_owner < GraphQL::Schema::Enum
|
141
|
+
# `prepare:` may have made the value something other than
|
142
|
+
# a defined value of this enum -- use _that_ in this case.
|
143
|
+
arg_owner.coerce_isolated_input(args) || args
|
144
|
+
else
|
145
|
+
args
|
146
|
+
end
|
98
147
|
end
|
99
148
|
end
|
100
149
|
|
101
|
-
def get_arg_definition(arg_owner, arg_name)
|
102
|
-
arg_owner
|
150
|
+
def get_arg_definition(arg_owner, arg_name, context)
|
151
|
+
context.types.argument(arg_owner, arg_name) || context.types.arguments(arg_owner).find { |v| v.keyword.to_s == arg_name }
|
103
152
|
end
|
104
153
|
end
|
105
154
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "set"
|
3
|
+
require "ostruct"
|
4
|
+
|
3
5
|
module GraphQL
|
4
6
|
class Subscriptions
|
5
7
|
# Serialization helpers for passing subscription data around.
|
@@ -9,7 +11,7 @@ module GraphQL
|
|
9
11
|
SYMBOL_KEY = "__sym__"
|
10
12
|
SYMBOL_KEYS_KEY = "__sym_keys__"
|
11
13
|
TIMESTAMP_KEY = "__timestamp__"
|
12
|
-
TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S.%N%
|
14
|
+
TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S.%N%z" # eg '2020-01-01 23:59:59.123456789+05:00'
|
13
15
|
OPEN_STRUCT_KEY = "__ostruct__"
|
14
16
|
|
15
17
|
module_function
|
@@ -71,9 +73,17 @@ module GraphQL
|
|
71
73
|
when SYMBOL_KEY
|
72
74
|
value[SYMBOL_KEY].to_sym
|
73
75
|
when TIMESTAMP_KEY
|
74
|
-
timestamp_class_name,
|
76
|
+
timestamp_class_name, *timestamp_args = value[TIMESTAMP_KEY]
|
75
77
|
timestamp_class = Object.const_get(timestamp_class_name)
|
76
|
-
|
78
|
+
if defined?(ActiveSupport::TimeWithZone) && timestamp_class <= ActiveSupport::TimeWithZone
|
79
|
+
zone_name, timestamp_s = timestamp_args
|
80
|
+
zone = ActiveSupport::TimeZone[zone_name]
|
81
|
+
raise "Zone #{zone_name} not found, unable to deserialize" unless zone
|
82
|
+
zone.strptime(timestamp_s, TIMESTAMP_FORMAT)
|
83
|
+
else
|
84
|
+
timestamp_s = timestamp_args.first
|
85
|
+
timestamp_class.strptime(timestamp_s, TIMESTAMP_FORMAT)
|
86
|
+
end
|
77
87
|
when OPEN_STRUCT_KEY
|
78
88
|
ostruct_values = load_value(value[OPEN_STRUCT_KEY])
|
79
89
|
OpenStruct.new(ostruct_values)
|
@@ -123,11 +133,25 @@ module GraphQL
|
|
123
133
|
{ SYMBOL_KEY => obj.to_s }
|
124
134
|
elsif obj.respond_to?(:to_gid_param)
|
125
135
|
{GLOBALID_KEY => obj.to_gid_param}
|
136
|
+
elsif defined?(ActiveSupport::TimeWithZone) && obj.is_a?(ActiveSupport::TimeWithZone) && obj.class.name != Time.name
|
137
|
+
# This handles a case where Rails prior to 7 would
|
138
|
+
# make the class ActiveSupport::TimeWithZone return "Time" for
|
139
|
+
# its name. In Rails 7, it will now return "ActiveSupport::TimeWithZone",
|
140
|
+
# which happens to be incompatible with expectations we have
|
141
|
+
# with what a Time class supports ( notably, strptime in `load_value` ).
|
142
|
+
#
|
143
|
+
# This now passes along the name of the zone, such that a future deserialization
|
144
|
+
# of this string will use the correct time zone from the ActiveSupport TimeZone
|
145
|
+
# list to produce the time.
|
146
|
+
#
|
147
|
+
{ TIMESTAMP_KEY => [obj.class.name, obj.time_zone.name, obj.strftime(TIMESTAMP_FORMAT)] }
|
126
148
|
elsif obj.is_a?(Date) || obj.is_a?(Time)
|
127
149
|
# DateTime extends Date; for TimeWithZone, call `.utc` first.
|
128
150
|
{ TIMESTAMP_KEY => [obj.class.name, obj.strftime(TIMESTAMP_FORMAT)] }
|
129
151
|
elsif obj.is_a?(OpenStruct)
|
130
152
|
{ OPEN_STRUCT_KEY => dump_value(obj.to_h) }
|
153
|
+
elsif defined?(ActiveRecord::Relation) && obj.is_a?(ActiveRecord::Relation)
|
154
|
+
dump_value(obj.to_a)
|
131
155
|
else
|
132
156
|
obj
|
133
157
|
end
|