graphql_cody 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +5 -0
- data/MIT-LICENSE +20 -0
- data/lib/generators/graphql/core.rb +74 -0
- data/lib/generators/graphql/enum_generator.rb +33 -0
- data/lib/generators/graphql/install_generator.rb +190 -0
- data/lib/generators/graphql/interface_generator.rb +27 -0
- data/lib/generators/graphql/loader_generator.rb +21 -0
- data/lib/generators/graphql/mutation_generator.rb +55 -0
- data/lib/generators/graphql/object_generator.rb +79 -0
- data/lib/generators/graphql/relay.rb +63 -0
- data/lib/generators/graphql/relay_generator.rb +21 -0
- data/lib/generators/graphql/scalar_generator.rb +20 -0
- data/lib/generators/graphql/templates/base_argument.erb +6 -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 +6 -0
- data/lib/generators/graphql/templates/base_field.erb +7 -0
- data/lib/generators/graphql/templates/base_input_object.erb +7 -0
- data/lib/generators/graphql/templates/base_interface.erb +9 -0
- data/lib/generators/graphql/templates/base_mutation.erb +10 -0
- data/lib/generators/graphql/templates/base_object.erb +7 -0
- data/lib/generators/graphql/templates/base_scalar.erb +6 -0
- data/lib/generators/graphql/templates/base_union.erb +6 -0
- data/lib/generators/graphql/templates/enum.erb +7 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +52 -0
- data/lib/generators/graphql/templates/interface.erb +8 -0
- data/lib/generators/graphql/templates/loader.erb +19 -0
- data/lib/generators/graphql/templates/mutation.erb +16 -0
- data/lib/generators/graphql/templates/mutation_type.erb +12 -0
- data/lib/generators/graphql/templates/node_type.erb +9 -0
- data/lib/generators/graphql/templates/object.erb +8 -0
- data/lib/generators/graphql/templates/query_type.erb +15 -0
- data/lib/generators/graphql/templates/scalar.erb +15 -0
- data/lib/generators/graphql/templates/schema.erb +27 -0
- data/lib/generators/graphql/templates/union.erb +7 -0
- data/lib/generators/graphql/type_generator.rb +98 -0
- data/lib/generators/graphql/union_generator.rb +33 -0
- data/lib/graphql/analysis/analyze_query.rb +98 -0
- data/lib/graphql/analysis/ast/analyzer.rb +84 -0
- data/lib/graphql/analysis/ast/field_usage.rb +51 -0
- data/lib/graphql/analysis/ast/max_query_complexity.rb +23 -0
- data/lib/graphql/analysis/ast/max_query_depth.rb +22 -0
- data/lib/graphql/analysis/ast/query_complexity.rb +230 -0
- data/lib/graphql/analysis/ast/query_depth.rb +56 -0
- data/lib/graphql/analysis/ast/visitor.rb +268 -0
- data/lib/graphql/analysis/ast.rb +91 -0
- data/lib/graphql/analysis/field_usage.rb +45 -0
- data/lib/graphql/analysis/max_query_complexity.rb +26 -0
- data/lib/graphql/analysis/max_query_depth.rb +26 -0
- data/lib/graphql/analysis/query_complexity.rb +88 -0
- data/lib/graphql/analysis/query_depth.rb +43 -0
- data/lib/graphql/analysis/reducer_state.rb +48 -0
- data/lib/graphql/analysis.rb +9 -0
- data/lib/graphql/analysis_error.rb +5 -0
- data/lib/graphql/argument.rb +131 -0
- data/lib/graphql/authorization.rb +82 -0
- data/lib/graphql/backtrace/inspect_result.rb +50 -0
- data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
- data/lib/graphql/backtrace/table.rb +159 -0
- data/lib/graphql/backtrace/traced_error.rb +54 -0
- data/lib/graphql/backtrace/tracer.rb +81 -0
- data/lib/graphql/backtrace.rb +64 -0
- data/lib/graphql/backwards_compatibility.rb +61 -0
- data/lib/graphql/base_type.rb +230 -0
- data/lib/graphql/boolean_type.rb +2 -0
- data/lib/graphql/coercion_error.rb +13 -0
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +53 -0
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +200 -0
- data/lib/graphql/compatibility/execution_specification.rb +436 -0
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +111 -0
- data/lib/graphql/compatibility/lazy_execution_specification.rb +215 -0
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +87 -0
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +79 -0
- data/lib/graphql/compatibility/query_parser_specification.rb +266 -0
- data/lib/graphql/compatibility/schema_parser_specification.rb +682 -0
- data/lib/graphql/compatibility.rb +5 -0
- data/lib/graphql/dataloader/null_dataloader.rb +22 -0
- data/lib/graphql/dataloader/request.rb +19 -0
- data/lib/graphql/dataloader/request_all.rb +19 -0
- data/lib/graphql/dataloader/source.rb +155 -0
- data/lib/graphql/dataloader.rb +308 -0
- data/lib/graphql/define/assign_argument.rb +12 -0
- data/lib/graphql/define/assign_connection.rb +13 -0
- data/lib/graphql/define/assign_enum_value.rb +18 -0
- data/lib/graphql/define/assign_global_id_field.rb +11 -0
- data/lib/graphql/define/assign_mutation_function.rb +34 -0
- data/lib/graphql/define/assign_object_field.rb +42 -0
- data/lib/graphql/define/defined_object_proxy.rb +53 -0
- data/lib/graphql/define/instance_definable.rb +240 -0
- data/lib/graphql/define/no_definition_error.rb +7 -0
- data/lib/graphql/define/non_null_with_bang.rb +16 -0
- data/lib/graphql/define/type_definer.rb +31 -0
- data/lib/graphql/define.rb +31 -0
- data/lib/graphql/deprecated_dsl.rb +55 -0
- data/lib/graphql/deprecation.rb +9 -0
- data/lib/graphql/dig.rb +19 -0
- data/lib/graphql/directive/deprecated_directive.rb +2 -0
- data/lib/graphql/directive/include_directive.rb +2 -0
- data/lib/graphql/directive/skip_directive.rb +2 -0
- data/lib/graphql/directive.rb +107 -0
- data/lib/graphql/enum_type.rb +133 -0
- data/lib/graphql/execution/directive_checks.rb +37 -0
- data/lib/graphql/execution/errors.rb +163 -0
- data/lib/graphql/execution/execute.rb +333 -0
- data/lib/graphql/execution/flatten.rb +40 -0
- data/lib/graphql/execution/instrumentation.rb +92 -0
- 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 +103 -0
- data/lib/graphql/execution/interpreter/execution_errors.rb +29 -0
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
- data/lib/graphql/execution/interpreter/resolve.rb +70 -0
- data/lib/graphql/execution/interpreter/runtime.rb +949 -0
- data/lib/graphql/execution/interpreter.rb +122 -0
- data/lib/graphql/execution/lazy/lazy_method_map.rb +98 -0
- data/lib/graphql/execution/lazy/resolve.rb +91 -0
- data/lib/graphql/execution/lazy.rb +83 -0
- data/lib/graphql/execution/lookahead.rb +307 -0
- data/lib/graphql/execution/multiplex.rb +214 -0
- data/lib/graphql/execution/typecast.rb +50 -0
- data/lib/graphql/execution.rb +11 -0
- data/lib/graphql/execution_error.rb +58 -0
- data/lib/graphql/field/resolve.rb +59 -0
- data/lib/graphql/field.rb +226 -0
- data/lib/graphql/filter.rb +53 -0
- data/lib/graphql/float_type.rb +2 -0
- data/lib/graphql/function.rb +128 -0
- data/lib/graphql/id_type.rb +2 -0
- data/lib/graphql/input_object_type.rb +138 -0
- data/lib/graphql/int_type.rb +2 -0
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/integer_encoding_error.rb +36 -0
- data/lib/graphql/interface_type.rb +72 -0
- data/lib/graphql/internal_representation/document.rb +27 -0
- data/lib/graphql/internal_representation/node.rb +206 -0
- data/lib/graphql/internal_representation/print.rb +51 -0
- data/lib/graphql/internal_representation/rewrite.rb +184 -0
- data/lib/graphql/internal_representation/scope.rb +88 -0
- data/lib/graphql/internal_representation/visit.rb +36 -0
- data/lib/graphql/internal_representation.rb +7 -0
- data/lib/graphql/introspection/base_object.rb +13 -0
- data/lib/graphql/introspection/directive_location_enum.rb +15 -0
- data/lib/graphql/introspection/directive_type.rb +29 -0
- data/lib/graphql/introspection/dynamic_fields.rb +17 -0
- data/lib/graphql/introspection/entry_points.rb +35 -0
- data/lib/graphql/introspection/enum_value_type.rb +23 -0
- data/lib/graphql/introspection/field_type.rb +28 -0
- data/lib/graphql/introspection/input_value_type.rb +67 -0
- data/lib/graphql/introspection/introspection_query.rb +7 -0
- data/lib/graphql/introspection/schema_type.rb +44 -0
- data/lib/graphql/introspection/type_kind_enum.rb +13 -0
- data/lib/graphql/introspection/type_type.rb +95 -0
- data/lib/graphql/introspection.rb +114 -0
- data/lib/graphql/invalid_name_error.rb +11 -0
- data/lib/graphql/invalid_null_error.rb +50 -0
- data/lib/graphql/language/block_string.rb +99 -0
- data/lib/graphql/language/cache.rb +37 -0
- data/lib/graphql/language/definition_slice.rb +41 -0
- data/lib/graphql/language/document_from_schema_definition.rb +347 -0
- data/lib/graphql/language/generation.rb +24 -0
- data/lib/graphql/language/lexer.rb +1467 -0
- data/lib/graphql/language/lexer.rl +258 -0
- data/lib/graphql/language/nodes.rb +707 -0
- data/lib/graphql/language/parser.rb +1974 -0
- data/lib/graphql/language/parser.y +544 -0
- data/lib/graphql/language/printer.rb +366 -0
- data/lib/graphql/language/sanitized_printer.rb +222 -0
- data/lib/graphql/language/token.rb +34 -0
- data/lib/graphql/language/visitor.rb +242 -0
- data/lib/graphql/language.rb +36 -0
- data/lib/graphql/list_type.rb +80 -0
- data/lib/graphql/load_application_object_failed_error.rb +22 -0
- data/lib/graphql/name_validator.rb +11 -0
- data/lib/graphql/non_null_type.rb +71 -0
- data/lib/graphql/object_type.rb +130 -0
- data/lib/graphql/pagination/active_record_relation_connection.rb +48 -0
- data/lib/graphql/pagination/array_connection.rb +77 -0
- data/lib/graphql/pagination/connection.rb +226 -0
- data/lib/graphql/pagination/connections.rb +160 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
- data/lib/graphql/pagination/relation_connection.rb +196 -0
- data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
- data/lib/graphql/pagination.rb +6 -0
- data/lib/graphql/parse_error.rb +24 -0
- data/lib/graphql/query/arguments.rb +189 -0
- data/lib/graphql/query/arguments_cache.rb +24 -0
- data/lib/graphql/query/context.rb +371 -0
- data/lib/graphql/query/executor.rb +52 -0
- data/lib/graphql/query/fingerprint.rb +26 -0
- data/lib/graphql/query/input_validation_result.rb +43 -0
- data/lib/graphql/query/literal_input.rb +136 -0
- data/lib/graphql/query/null_context.rb +55 -0
- data/lib/graphql/query/result.rb +63 -0
- data/lib/graphql/query/serial_execution/field_resolution.rb +92 -0
- data/lib/graphql/query/serial_execution/operation_resolution.rb +19 -0
- data/lib/graphql/query/serial_execution/selection_resolution.rb +23 -0
- data/lib/graphql/query/serial_execution/value_resolution.rb +87 -0
- data/lib/graphql/query/serial_execution.rb +40 -0
- data/lib/graphql/query/validation_pipeline.rb +139 -0
- data/lib/graphql/query/variable_validation_error.rb +44 -0
- data/lib/graphql/query/variables.rb +78 -0
- data/lib/graphql/query.rb +454 -0
- data/lib/graphql/railtie.rb +117 -0
- data/lib/graphql/rake_task/validate.rb +63 -0
- data/lib/graphql/rake_task.rb +145 -0
- data/lib/graphql/relay/array_connection.rb +83 -0
- data/lib/graphql/relay/base_connection.rb +189 -0
- data/lib/graphql/relay/connection_instrumentation.rb +54 -0
- data/lib/graphql/relay/connection_resolve.rb +43 -0
- data/lib/graphql/relay/connection_type.rb +41 -0
- data/lib/graphql/relay/edge.rb +27 -0
- data/lib/graphql/relay/edge_type.rb +19 -0
- data/lib/graphql/relay/edges_instrumentation.rb +39 -0
- data/lib/graphql/relay/global_id_resolve.rb +18 -0
- data/lib/graphql/relay/mongo_relation_connection.rb +50 -0
- data/lib/graphql/relay/mutation/instrumentation.rb +23 -0
- data/lib/graphql/relay/mutation/resolve.rb +56 -0
- data/lib/graphql/relay/mutation/result.rb +38 -0
- data/lib/graphql/relay/mutation.rb +106 -0
- data/lib/graphql/relay/node.rb +39 -0
- data/lib/graphql/relay/page_info.rb +7 -0
- data/lib/graphql/relay/range_add.rb +59 -0
- data/lib/graphql/relay/relation_connection.rb +188 -0
- data/lib/graphql/relay/type_extensions.rb +32 -0
- data/lib/graphql/relay.rb +18 -0
- data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
- data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
- data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
- data/lib/graphql/rubocop.rb +4 -0
- data/lib/graphql/runtime_type_error.rb +5 -0
- data/lib/graphql/scalar_type.rb +91 -0
- data/lib/graphql/schema/addition.rb +247 -0
- data/lib/graphql/schema/argument.rb +383 -0
- data/lib/graphql/schema/base_64_bp.rb +26 -0
- data/lib/graphql/schema/base_64_encoder.rb +21 -0
- data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +47 -0
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +78 -0
- data/lib/graphql/schema/build_from_definition.rb +477 -0
- data/lib/graphql/schema/built_in_types.rb +12 -0
- data/lib/graphql/schema/catchall_middleware.rb +35 -0
- data/lib/graphql/schema/default_parse_error.rb +10 -0
- data/lib/graphql/schema/default_type_error.rb +17 -0
- data/lib/graphql/schema/directive/deprecated.rb +18 -0
- data/lib/graphql/schema/directive/feature.rb +66 -0
- data/lib/graphql/schema/directive/flagged.rb +57 -0
- data/lib/graphql/schema/directive/include.rb +25 -0
- data/lib/graphql/schema/directive/skip.rb +25 -0
- data/lib/graphql/schema/directive/transform.rb +60 -0
- data/lib/graphql/schema/directive.rb +210 -0
- data/lib/graphql/schema/enum.rb +193 -0
- data/lib/graphql/schema/enum_value.rb +97 -0
- data/lib/graphql/schema/field/connection_extension.rb +76 -0
- data/lib/graphql/schema/field/scope_extension.rb +22 -0
- data/lib/graphql/schema/field.rb +880 -0
- data/lib/graphql/schema/field_extension.rb +69 -0
- data/lib/graphql/schema/find_inherited_value.rb +36 -0
- data/lib/graphql/schema/finder.rb +155 -0
- data/lib/graphql/schema/input_object.rb +253 -0
- data/lib/graphql/schema/interface.rb +136 -0
- data/lib/graphql/schema/introspection_system.rb +169 -0
- data/lib/graphql/schema/invalid_type_error.rb +7 -0
- data/lib/graphql/schema/late_bound_type.rb +33 -0
- data/lib/graphql/schema/list.rb +75 -0
- data/lib/graphql/schema/loader.rb +226 -0
- data/lib/graphql/schema/member/accepts_definition.rb +159 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +129 -0
- data/lib/graphql/schema/member/build_type.rb +180 -0
- data/lib/graphql/schema/member/cached_graphql_definition.rb +31 -0
- data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
- data/lib/graphql/schema/member/has_arguments.rb +332 -0
- 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 +98 -0
- data/lib/graphql/schema/member/has_fields.rb +163 -0
- data/lib/graphql/schema/member/has_interfaces.rb +90 -0
- data/lib/graphql/schema/member/has_path.rb +25 -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/instrumentation.rb +131 -0
- data/lib/graphql/schema/member/relay_shortcuts.rb +47 -0
- data/lib/graphql/schema/member/scoped.rb +21 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +38 -0
- data/lib/graphql/schema/member/validates_input.rb +33 -0
- data/lib/graphql/schema/member.rb +161 -0
- data/lib/graphql/schema/middleware_chain.rb +82 -0
- data/lib/graphql/schema/mutation.rb +94 -0
- data/lib/graphql/schema/non_null.rb +67 -0
- data/lib/graphql/schema/null_mask.rb +11 -0
- data/lib/graphql/schema/object.rb +150 -0
- data/lib/graphql/schema/possible_types.rb +44 -0
- data/lib/graphql/schema/printer.rb +100 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +160 -0
- data/lib/graphql/schema/rescue_middleware.rb +60 -0
- data/lib/graphql/schema/resolver/has_payload_type.rb +96 -0
- data/lib/graphql/schema/resolver.rb +397 -0
- data/lib/graphql/schema/scalar.rb +69 -0
- data/lib/graphql/schema/subscription.rb +155 -0
- data/lib/graphql/schema/timeout.rb +123 -0
- data/lib/graphql/schema/timeout_middleware.rb +88 -0
- data/lib/graphql/schema/traversal.rb +228 -0
- data/lib/graphql/schema/type_expression.rb +43 -0
- data/lib/graphql/schema/type_membership.rb +48 -0
- data/lib/graphql/schema/union.rb +95 -0
- data/lib/graphql/schema/unique_within_type.rb +34 -0
- data/lib/graphql/schema/validation.rb +313 -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 +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 +68 -0
- data/lib/graphql/schema/validator.rb +174 -0
- data/lib/graphql/schema/warden.rb +409 -0
- data/lib/graphql/schema/wrapper.rb +29 -0
- data/lib/graphql/schema.rb +1945 -0
- data/lib/graphql/static_validation/all_rules.rb +40 -0
- data/lib/graphql/static_validation/base_visitor.rb +217 -0
- data/lib/graphql/static_validation/default_visitor.rb +15 -0
- data/lib/graphql/static_validation/definition_dependencies.rb +198 -0
- data/lib/graphql/static_validation/error.rb +46 -0
- data/lib/graphql/static_validation/interpreter_visitor.rb +14 -0
- data/lib/graphql/static_validation/literal_validator.rb +139 -0
- data/lib/graphql/static_validation/no_validate_visitor.rb +10 -0
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +66 -0
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +48 -0
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +31 -0
- data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +30 -0
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +71 -0
- data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +37 -0
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +23 -0
- data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +29 -0
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +65 -0
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +31 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +30 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +32 -0
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +73 -0
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +31 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +418 -0
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +53 -0
- data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +30 -0
- data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +29 -0
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +73 -0
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +35 -0
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +39 -0
- data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +29 -0
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +21 -0
- data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +29 -0
- data/lib/graphql/static_validation/rules/fragments_are_named.rb +16 -0
- data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +26 -0
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +37 -0
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +30 -0
- data/lib/graphql/static_validation/rules/fragments_are_used.rb +32 -0
- data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +29 -0
- 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/mutation_root_exists.rb +17 -0
- data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +41 -0
- data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +25 -0
- data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +36 -0
- data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +28 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +37 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +35 -0
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +59 -0
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +35 -0
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +17 -0
- data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +50 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +29 -0
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +46 -0
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +39 -0
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +24 -0
- data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +29 -0
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +153 -0
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +38 -0
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +39 -0
- data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +32 -0
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +155 -0
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +37 -0
- data/lib/graphql/static_validation/type_stack.rb +216 -0
- data/lib/graphql/static_validation/validation_context.rb +49 -0
- data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
- data/lib/graphql/static_validation/validator.rb +96 -0
- data/lib/graphql/static_validation.rb +19 -0
- data/lib/graphql/string_encoding_error.rb +20 -0
- data/lib/graphql/string_type.rb +2 -0
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +245 -0
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
- data/lib/graphql/subscriptions/event.rb +144 -0
- data/lib/graphql/subscriptions/instrumentation.rb +79 -0
- data/lib/graphql/subscriptions/serialize.rb +138 -0
- data/lib/graphql/subscriptions/subscription_root.rb +76 -0
- data/lib/graphql/subscriptions.rb +299 -0
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +35 -0
- data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +51 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +76 -0
- data/lib/graphql/tracing/new_relic_tracing.rb +51 -0
- data/lib/graphql/tracing/platform_tracing.rb +139 -0
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +32 -0
- data/lib/graphql/tracing/prometheus_tracing.rb +67 -0
- data/lib/graphql/tracing/scout_tracing.rb +54 -0
- data/lib/graphql/tracing/skylight_tracing.rb +70 -0
- data/lib/graphql/tracing/statsd_tracing.rb +42 -0
- data/lib/graphql/tracing.rb +95 -0
- data/lib/graphql/type_kinds.rb +77 -0
- data/lib/graphql/types/big_int.rb +23 -0
- data/lib/graphql/types/boolean.rb +18 -0
- data/lib/graphql/types/float.rb +19 -0
- data/lib/graphql/types/id.rb +24 -0
- data/lib/graphql/types/int.rb +36 -0
- data/lib/graphql/types/iso_8601_date.rb +34 -0
- data/lib/graphql/types/iso_8601_date_time.rb +65 -0
- data/lib/graphql/types/json.rb +25 -0
- data/lib/graphql/types/relay/base_connection.rb +39 -0
- data/lib/graphql/types/relay/base_edge.rb +29 -0
- data/lib/graphql/types/relay/connection_behaviors.rb +156 -0
- data/lib/graphql/types/relay/default_relay.rb +27 -0
- data/lib/graphql/types/relay/edge_behaviors.rb +53 -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 +15 -0
- data/lib/graphql/types/relay/node_behaviors.rb +15 -0
- data/lib/graphql/types/relay/node_field.rb +25 -0
- data/lib/graphql/types/relay/nodes_field.rb +27 -0
- data/lib/graphql/types/relay/page_info.rb +11 -0
- data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
- data/lib/graphql/types/relay.rb +41 -0
- data/lib/graphql/types/string.rb +29 -0
- data/lib/graphql/types.rb +11 -0
- data/lib/graphql/unauthorized_error.rb +29 -0
- data/lib/graphql/unauthorized_field_error.rb +23 -0
- data/lib/graphql/union_type.rb +115 -0
- data/lib/graphql/unresolved_type_error.rb +35 -0
- data/lib/graphql/upgrader/member.rb +937 -0
- data/lib/graphql/upgrader/schema.rb +38 -0
- data/lib/graphql/version.rb +4 -0
- data/lib/graphql.rb +168 -0
- data/readme.md +49 -0
- metadata +714 -0
@@ -0,0 +1,397 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "graphql/schema/resolver/has_payload_type"
|
3
|
+
|
4
|
+
module GraphQL
|
5
|
+
class Schema
|
6
|
+
# A class-based container for field configuration and resolution logic. It supports:
|
7
|
+
#
|
8
|
+
# - Arguments, via `.argument(...)` helper, which will be applied to the field.
|
9
|
+
# - Return type, via `.type(..., null: ...)`, which will be applied to the field.
|
10
|
+
# - Description, via `.description(...)`, which will be applied to the field
|
11
|
+
# - Resolution, via `#resolve(**args)` method, which will be called to resolve the field.
|
12
|
+
# - `#object` and `#context` accessors for use during `#resolve`.
|
13
|
+
#
|
14
|
+
# Resolvers can be attached with the `resolver:` option in a `field(...)` call.
|
15
|
+
#
|
16
|
+
# A resolver's configuration may be overridden with other keywords in the `field(...)` call.
|
17
|
+
#
|
18
|
+
# See the {.field_options} to see how a Resolver becomes a set of field configuration options.
|
19
|
+
#
|
20
|
+
# @see {GraphQL::Schema::Mutation} for a concrete subclass of `Resolver`.
|
21
|
+
# @see {GraphQL::Function} `Resolver` is a replacement for `GraphQL::Function`
|
22
|
+
class Resolver
|
23
|
+
include Schema::Member::GraphQLTypeNames
|
24
|
+
# Really we only need description from here, but:
|
25
|
+
extend Schema::Member::BaseDSLMethods
|
26
|
+
extend GraphQL::Schema::Member::HasArguments
|
27
|
+
extend GraphQL::Schema::Member::HasValidators
|
28
|
+
include Schema::Member::HasPath
|
29
|
+
extend Schema::Member::HasPath
|
30
|
+
|
31
|
+
# @param object [Object] The application object that this field is being resolved on
|
32
|
+
# @param context [GraphQL::Query::Context]
|
33
|
+
# @param field [GraphQL::Schema::Field]
|
34
|
+
def initialize(object:, context:, field:)
|
35
|
+
@object = object
|
36
|
+
@context = context
|
37
|
+
@field = field
|
38
|
+
# Since this hash is constantly rebuilt, cache it for this call
|
39
|
+
@arguments_by_keyword = {}
|
40
|
+
self.class.arguments(context).each do |name, arg|
|
41
|
+
@arguments_by_keyword[arg.keyword] = arg
|
42
|
+
end
|
43
|
+
@prepared_arguments = nil
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [Object] The application object this field is being resolved on
|
47
|
+
attr_reader :object
|
48
|
+
|
49
|
+
# @return [GraphQL::Query::Context]
|
50
|
+
attr_reader :context
|
51
|
+
|
52
|
+
# @return [GraphQL::Dataloader]
|
53
|
+
def dataloader
|
54
|
+
context.dataloader
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [GraphQL::Schema::Field]
|
58
|
+
attr_reader :field
|
59
|
+
|
60
|
+
def arguments
|
61
|
+
@prepared_arguments || raise("Arguments have not been prepared yet, still waiting for #load_arguments to resolve. (Call `.arguments` later in the code.)")
|
62
|
+
end
|
63
|
+
|
64
|
+
# This method is _actually_ called by the runtime,
|
65
|
+
# it does some preparation and then eventually calls
|
66
|
+
# the user-defined `#resolve` method.
|
67
|
+
# @api private
|
68
|
+
def resolve_with_support(**args)
|
69
|
+
# First call the ready? hook which may raise
|
70
|
+
ready_val = if args.any?
|
71
|
+
ready?(**args)
|
72
|
+
else
|
73
|
+
ready?
|
74
|
+
end
|
75
|
+
context.schema.after_lazy(ready_val) do |is_ready, ready_early_return|
|
76
|
+
if ready_early_return
|
77
|
+
if is_ready != false
|
78
|
+
raise "Unexpected result from #ready? (expected `true`, `false` or `[false, {...}]`): [#{authorized_result.inspect}, #{ready_early_return.inspect}]"
|
79
|
+
else
|
80
|
+
ready_early_return
|
81
|
+
end
|
82
|
+
elsif is_ready
|
83
|
+
# Then call each prepare hook, which may return a different value
|
84
|
+
# for that argument, or may return a lazy object
|
85
|
+
load_arguments_val = load_arguments(args)
|
86
|
+
context.schema.after_lazy(load_arguments_val) do |loaded_args|
|
87
|
+
@prepared_arguments = loaded_args
|
88
|
+
Schema::Validator.validate!(self.class.validators, object, context, loaded_args, as: @field)
|
89
|
+
# Then call `authorized?`, which may raise or may return a lazy object
|
90
|
+
authorized_val = if loaded_args.any?
|
91
|
+
authorized?(**loaded_args)
|
92
|
+
else
|
93
|
+
authorized?
|
94
|
+
end
|
95
|
+
context.schema.after_lazy(authorized_val) do |(authorized_result, early_return)|
|
96
|
+
# If the `authorized?` returned two values, `false, early_return`,
|
97
|
+
# then use the early return value instead of continuing
|
98
|
+
if early_return
|
99
|
+
if authorized_result == false
|
100
|
+
early_return
|
101
|
+
else
|
102
|
+
raise "Unexpected result from #authorized? (expected `true`, `false` or `[false, {...}]`): [#{authorized_result.inspect}, #{early_return.inspect}]"
|
103
|
+
end
|
104
|
+
elsif authorized_result
|
105
|
+
# Finally, all the hooks have passed, so resolve it
|
106
|
+
if loaded_args.any?
|
107
|
+
public_send(self.class.resolve_method, **loaded_args)
|
108
|
+
else
|
109
|
+
public_send(self.class.resolve_method)
|
110
|
+
end
|
111
|
+
else
|
112
|
+
raise GraphQL::UnauthorizedFieldError.new(context: context, object: object, type: field.owner, field: field)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Do the work. Everything happens here.
|
121
|
+
# @return [Object] An object corresponding to the return type
|
122
|
+
def resolve(**args)
|
123
|
+
raise GraphQL::RequiredImplementationMissingError, "#{self.class.name}#resolve should execute the field's logic"
|
124
|
+
end
|
125
|
+
|
126
|
+
# Called before arguments are prepared.
|
127
|
+
# Implement this hook to make checks before doing any work.
|
128
|
+
#
|
129
|
+
# If it returns a lazy object (like a promise), it will be synced by GraphQL
|
130
|
+
# (but the resulting value won't be used).
|
131
|
+
#
|
132
|
+
# @param args [Hash] The input arguments, if there are any
|
133
|
+
# @raise [GraphQL::ExecutionError] To add an error to the response
|
134
|
+
# @raise [GraphQL::UnauthorizedError] To signal an authorization failure
|
135
|
+
# @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
|
136
|
+
def ready?(**args)
|
137
|
+
true
|
138
|
+
end
|
139
|
+
|
140
|
+
# Called after arguments are loaded, but before resolving.
|
141
|
+
#
|
142
|
+
# Override it to check everything before calling the mutation.
|
143
|
+
# @param inputs [Hash] The input arguments
|
144
|
+
# @raise [GraphQL::ExecutionError] To add an error to the response
|
145
|
+
# @raise [GraphQL::UnauthorizedError] To signal an authorization failure
|
146
|
+
# @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
|
147
|
+
def authorized?(**inputs)
|
148
|
+
self.class.arguments(context).each_value do |argument|
|
149
|
+
arg_keyword = argument.keyword
|
150
|
+
if inputs.key?(arg_keyword) && !(arg_value = inputs[arg_keyword]).nil? && (arg_value != argument.default_value)
|
151
|
+
arg_auth, err = argument.authorized?(self, arg_value, context)
|
152
|
+
if !arg_auth
|
153
|
+
return arg_auth, err
|
154
|
+
else
|
155
|
+
true
|
156
|
+
end
|
157
|
+
else
|
158
|
+
true
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Called when an object loaded by `loads:` fails the `.authorized?` check for its resolved GraphQL object type.
|
164
|
+
#
|
165
|
+
# By default, the error is re-raised and passed along to {{Schema.unauthorized_object}}.
|
166
|
+
#
|
167
|
+
# Any value returned here will be used _instead of_ of the loaded object.
|
168
|
+
# @param err [GraphQL::UnauthorizedError]
|
169
|
+
def unauthorized_object(err)
|
170
|
+
raise err
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
def load_arguments(args)
|
176
|
+
prepared_args = {}
|
177
|
+
prepare_lazies = []
|
178
|
+
|
179
|
+
args.each do |key, value|
|
180
|
+
arg_defn = @arguments_by_keyword[key]
|
181
|
+
if arg_defn
|
182
|
+
prepped_value = prepared_args[key] = arg_defn.load_and_authorize_value(self, value, context)
|
183
|
+
if context.schema.lazy?(prepped_value)
|
184
|
+
prepare_lazies << context.schema.after_lazy(prepped_value) do |finished_prepped_value|
|
185
|
+
prepared_args[key] = finished_prepped_value
|
186
|
+
end
|
187
|
+
end
|
188
|
+
else
|
189
|
+
# these are `extras:`
|
190
|
+
prepared_args[key] = value
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# Avoid returning a lazy if none are needed
|
195
|
+
if prepare_lazies.any?
|
196
|
+
GraphQL::Execution::Lazy.all(prepare_lazies).then { prepared_args }
|
197
|
+
else
|
198
|
+
prepared_args
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def get_argument(name, context = GraphQL::Query::NullContext)
|
203
|
+
self.class.get_argument(name, context)
|
204
|
+
end
|
205
|
+
|
206
|
+
class << self
|
207
|
+
# Default `:resolve` set below.
|
208
|
+
# @return [Symbol] The method to call on instances of this object to resolve the field
|
209
|
+
def resolve_method(new_method = nil)
|
210
|
+
if new_method
|
211
|
+
@resolve_method = new_method
|
212
|
+
end
|
213
|
+
@resolve_method || (superclass.respond_to?(:resolve_method) ? superclass.resolve_method : :resolve)
|
214
|
+
end
|
215
|
+
|
216
|
+
# Additional info injected into {#resolve}
|
217
|
+
# @see {GraphQL::Schema::Field#extras}
|
218
|
+
def extras(new_extras = nil)
|
219
|
+
if new_extras
|
220
|
+
@own_extras = new_extras
|
221
|
+
end
|
222
|
+
own_extras = @own_extras || []
|
223
|
+
own_extras + (superclass.respond_to?(:extras) ? superclass.extras : [])
|
224
|
+
end
|
225
|
+
|
226
|
+
# If `true` (default), then the return type for this resolver will be nullable.
|
227
|
+
# If `false`, then the return type is non-null.
|
228
|
+
#
|
229
|
+
# @see #type which sets the return type of this field and accepts a `null:` option
|
230
|
+
# @param allow_null [Boolean] Whether or not the response can be null
|
231
|
+
def null(allow_null = nil)
|
232
|
+
if !allow_null.nil?
|
233
|
+
@null = allow_null
|
234
|
+
end
|
235
|
+
|
236
|
+
@null.nil? ? (superclass.respond_to?(:null) ? superclass.null : true) : @null
|
237
|
+
end
|
238
|
+
|
239
|
+
# Call this method to get the return type of the field,
|
240
|
+
# or use it as a configuration method to assign a return type
|
241
|
+
# instead of generating one.
|
242
|
+
# TODO unify with {#null}
|
243
|
+
# @param new_type [Class, Array<Class>, nil] If a type definition class is provided, it will be used as the return type of the field
|
244
|
+
# @param null [true, false] Whether or not the field may return `nil`
|
245
|
+
# @return [Class] The type which this field returns.
|
246
|
+
def type(new_type = nil, null: nil)
|
247
|
+
if new_type
|
248
|
+
if null.nil?
|
249
|
+
raise ArgumentError, "required argument `null:` is missing"
|
250
|
+
end
|
251
|
+
@type_expr = new_type
|
252
|
+
@null = null
|
253
|
+
else
|
254
|
+
if @type_expr
|
255
|
+
GraphQL::Schema::Member::BuildType.parse_type(@type_expr, null: @null)
|
256
|
+
elsif superclass.respond_to?(:type)
|
257
|
+
superclass.type
|
258
|
+
else
|
259
|
+
nil
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# Specifies the complexity of the field. Defaults to `1`
|
265
|
+
# @return [Integer, Proc]
|
266
|
+
def complexity(new_complexity = nil)
|
267
|
+
if new_complexity
|
268
|
+
@complexity = new_complexity
|
269
|
+
end
|
270
|
+
@complexity || (superclass.respond_to?(:complexity) ? superclass.complexity : 1)
|
271
|
+
end
|
272
|
+
|
273
|
+
def broadcastable(new_broadcastable)
|
274
|
+
@broadcastable = new_broadcastable
|
275
|
+
end
|
276
|
+
|
277
|
+
# @return [Boolean, nil]
|
278
|
+
def broadcastable?
|
279
|
+
if defined?(@broadcastable)
|
280
|
+
@broadcastable
|
281
|
+
else
|
282
|
+
(superclass.respond_to?(:broadcastable?) ? superclass.broadcastable? : nil)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
# Get or set the `max_page_size:` which will be configured for fields using this resolver
|
287
|
+
# (`nil` means "unlimited max page size".)
|
288
|
+
# @param max_page_size [Integer, nil] Set a new value
|
289
|
+
# @return [Integer, nil] The `max_page_size` assigned to fields that use this resolver
|
290
|
+
def max_page_size(new_max_page_size = :not_given)
|
291
|
+
if new_max_page_size != :not_given
|
292
|
+
@max_page_size = new_max_page_size
|
293
|
+
elsif defined?(@max_page_size)
|
294
|
+
@max_page_size
|
295
|
+
elsif superclass.respond_to?(:max_page_size)
|
296
|
+
superclass.max_page_size
|
297
|
+
else
|
298
|
+
nil
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
# @return [Boolean] `true` if this resolver or a superclass has an assigned `max_page_size`
|
303
|
+
def has_max_page_size?
|
304
|
+
defined?(@max_page_size) || (superclass.respond_to?(:has_max_page_size?) && superclass.has_max_page_size?)
|
305
|
+
end
|
306
|
+
|
307
|
+
def field_options
|
308
|
+
|
309
|
+
all_args = {}
|
310
|
+
all_argument_definitions.each do |arg|
|
311
|
+
if (prev_entry = all_args[arg.graphql_name])
|
312
|
+
if prev_entry.is_a?(Array)
|
313
|
+
prev_entry << arg
|
314
|
+
else
|
315
|
+
all_args[arg.graphql_name] = [prev_entry, arg]
|
316
|
+
end
|
317
|
+
else
|
318
|
+
all_args[arg.graphql_name] = arg
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
field_opts = {
|
323
|
+
type: type_expr,
|
324
|
+
description: description,
|
325
|
+
extras: extras,
|
326
|
+
resolver_method: :resolve_with_support,
|
327
|
+
resolver_class: self,
|
328
|
+
arguments: all_args,
|
329
|
+
null: null,
|
330
|
+
complexity: complexity,
|
331
|
+
broadcastable: broadcastable?,
|
332
|
+
}
|
333
|
+
|
334
|
+
# If there aren't any, then the returned array is `[].freeze`,
|
335
|
+
# but passing that along breaks some user code.
|
336
|
+
if (exts = extensions).any?
|
337
|
+
field_opts[:extensions] = exts
|
338
|
+
end
|
339
|
+
|
340
|
+
if has_max_page_size?
|
341
|
+
field_opts[:max_page_size] = max_page_size
|
342
|
+
end
|
343
|
+
|
344
|
+
field_opts
|
345
|
+
end
|
346
|
+
|
347
|
+
# A non-normalized type configuration, without `null` applied
|
348
|
+
def type_expr
|
349
|
+
@type_expr || (superclass.respond_to?(:type_expr) ? superclass.type_expr : nil)
|
350
|
+
end
|
351
|
+
|
352
|
+
# Add an argument to this field's signature, but
|
353
|
+
# also add some preparation hook methods which will be used for this argument
|
354
|
+
# @see {GraphQL::Schema::Argument#initialize} for the signature
|
355
|
+
def argument(*args, **kwargs, &block)
|
356
|
+
# Use `from_resolver: true` to short-circuit the InputObject's own `loads:` implementation
|
357
|
+
# so that we can support `#load_{x}` methods below.
|
358
|
+
super(*args, from_resolver: true, **kwargs)
|
359
|
+
end
|
360
|
+
|
361
|
+
# Registers new extension
|
362
|
+
# @param extension [Class] Extension class
|
363
|
+
# @param options [Hash] Optional extension options
|
364
|
+
def extension(extension, **options)
|
365
|
+
@own_extensions ||= []
|
366
|
+
@own_extensions << {extension => options}
|
367
|
+
end
|
368
|
+
|
369
|
+
# @api private
|
370
|
+
def extensions
|
371
|
+
own_exts = @own_extensions
|
372
|
+
# Jump through some hoops to avoid creating arrays when we don't actually need them
|
373
|
+
if superclass.respond_to?(:extensions)
|
374
|
+
s_exts = superclass.extensions
|
375
|
+
if own_exts
|
376
|
+
if s_exts.any?
|
377
|
+
own_exts + s_exts
|
378
|
+
else
|
379
|
+
own_exts
|
380
|
+
end
|
381
|
+
else
|
382
|
+
s_exts
|
383
|
+
end
|
384
|
+
else
|
385
|
+
own_exts || EMPTY_ARRAY
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
private
|
390
|
+
|
391
|
+
def own_extensions
|
392
|
+
@own_extensions
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
396
|
+
end
|
397
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class Schema
|
4
|
+
class Scalar < GraphQL::Schema::Member
|
5
|
+
extend GraphQL::Schema::Member::AcceptsDefinition
|
6
|
+
extend GraphQL::Schema::Member::ValidatesInput
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def coerce_input(val, ctx)
|
10
|
+
val
|
11
|
+
end
|
12
|
+
|
13
|
+
def coerce_result(val, ctx)
|
14
|
+
val
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_graphql
|
18
|
+
type_defn = GraphQL::ScalarType.new
|
19
|
+
type_defn.name = graphql_name
|
20
|
+
type_defn.description = description
|
21
|
+
type_defn.coerce_result = method(:coerce_result)
|
22
|
+
type_defn.coerce_input = method(:coerce_input)
|
23
|
+
type_defn.metadata[:type_class] = self
|
24
|
+
type_defn.default_scalar = default_scalar
|
25
|
+
type_defn.ast_node = ast_node
|
26
|
+
type_defn
|
27
|
+
end
|
28
|
+
|
29
|
+
def kind
|
30
|
+
GraphQL::TypeKinds::SCALAR
|
31
|
+
end
|
32
|
+
|
33
|
+
def default_scalar(is_default = nil)
|
34
|
+
if !is_default.nil?
|
35
|
+
@default_scalar = is_default
|
36
|
+
end
|
37
|
+
@default_scalar
|
38
|
+
end
|
39
|
+
|
40
|
+
def default_scalar?
|
41
|
+
@default_scalar ||= false
|
42
|
+
end
|
43
|
+
|
44
|
+
def validate_non_null_input(value, ctx)
|
45
|
+
result = Query::InputValidationResult.new
|
46
|
+
coerced_result = begin
|
47
|
+
ctx.query.with_error_handling do
|
48
|
+
coerce_input(value, ctx)
|
49
|
+
end
|
50
|
+
rescue GraphQL::CoercionError => err
|
51
|
+
err
|
52
|
+
end
|
53
|
+
|
54
|
+
if coerced_result.nil?
|
55
|
+
str_value = if value == Float::INFINITY
|
56
|
+
""
|
57
|
+
else
|
58
|
+
" #{GraphQL::Language.serialize(value)}"
|
59
|
+
end
|
60
|
+
result.add_problem("Could not coerce value#{str_value} to #{graphql_name}")
|
61
|
+
elsif coerced_result.is_a?(GraphQL::CoercionError)
|
62
|
+
result.add_problem(coerced_result.message, message: coerced_result.message, extensions: coerced_result.extensions)
|
63
|
+
end
|
64
|
+
result
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
# This class can be extended to create fields on your subscription root.
|
6
|
+
#
|
7
|
+
# It provides hooks for the different parts of the subscription lifecycle:
|
8
|
+
#
|
9
|
+
# - `#authorized?`: called before initial subscription and subsequent updates
|
10
|
+
# - `#subscribe`: called for the initial subscription
|
11
|
+
# - `#update`: called for subsequent update
|
12
|
+
#
|
13
|
+
# Also, `#unsubscribe` terminates the subscription.
|
14
|
+
class Subscription < GraphQL::Schema::Resolver
|
15
|
+
extend GraphQL::Schema::Resolver::HasPayloadType
|
16
|
+
extend GraphQL::Schema::Member::HasFields
|
17
|
+
NO_UPDATE = :no_update
|
18
|
+
# The generated payload type is required; If there's no payload,
|
19
|
+
# propagate null.
|
20
|
+
null false
|
21
|
+
|
22
|
+
def initialize(object:, context:, field:)
|
23
|
+
super
|
24
|
+
# Figure out whether this is an update or an initial subscription
|
25
|
+
@mode = context.query.subscription_update? ? :update : :subscribe
|
26
|
+
end
|
27
|
+
|
28
|
+
def resolve_with_support(**args)
|
29
|
+
result = nil
|
30
|
+
unsubscribed = true
|
31
|
+
catch :graphql_subscription_unsubscribed do
|
32
|
+
result = super
|
33
|
+
unsubscribed = false
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
if unsubscribed
|
38
|
+
context.skip
|
39
|
+
else
|
40
|
+
result
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Implement the {Resolve} API
|
45
|
+
def resolve(**args)
|
46
|
+
# Dispatch based on `@mode`, which will raise a `NoMethodError` if we ever
|
47
|
+
# have an unexpected `@mode`
|
48
|
+
public_send("resolve_#{@mode}", **args)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Wrap the user-defined `#subscribe` hook
|
52
|
+
def resolve_subscribe(**args)
|
53
|
+
ret_val = args.any? ? subscribe(**args) : subscribe
|
54
|
+
if ret_val == :no_response
|
55
|
+
context.skip
|
56
|
+
else
|
57
|
+
ret_val
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# The default implementation returns nothing on subscribe.
|
62
|
+
# Override it to return an object or
|
63
|
+
# `:no_response` to (explicitly) return nothing.
|
64
|
+
def subscribe(args = {})
|
65
|
+
:no_response
|
66
|
+
end
|
67
|
+
|
68
|
+
# Wrap the user-provided `#update` hook
|
69
|
+
def resolve_update(**args)
|
70
|
+
ret_val = args.any? ? update(**args) : update
|
71
|
+
if ret_val == NO_UPDATE
|
72
|
+
context.namespace(:subscriptions)[:no_update] = true
|
73
|
+
context.skip
|
74
|
+
else
|
75
|
+
ret_val
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# The default implementation returns the root object.
|
80
|
+
# Override it to return {NO_UPDATE} if you want to
|
81
|
+
# skip updates sometimes. Or override it to return a different object.
|
82
|
+
def update(args = {})
|
83
|
+
object
|
84
|
+
end
|
85
|
+
|
86
|
+
# If an argument is flagged with `loads:` and no object is found for it,
|
87
|
+
# remove this subscription (assuming that the object was deleted in the meantime,
|
88
|
+
# or that it became inaccessible).
|
89
|
+
def load_application_object_failed(err)
|
90
|
+
if @mode == :update
|
91
|
+
unsubscribe
|
92
|
+
end
|
93
|
+
super
|
94
|
+
end
|
95
|
+
|
96
|
+
# Call this to halt execution and remove this subscription from the system
|
97
|
+
def unsubscribe
|
98
|
+
context.namespace(:subscriptions)[:unsubscribed] = true
|
99
|
+
throw :graphql_subscription_unsubscribed
|
100
|
+
end
|
101
|
+
|
102
|
+
READING_SCOPE = ::Object.new
|
103
|
+
# Call this method to provide a new subscription_scope; OR
|
104
|
+
# call it without an argument to get the subscription_scope
|
105
|
+
# @param new_scope [Symbol]
|
106
|
+
# @param optional [Boolean] If true, then don't require `scope:` to be provided to updates to this subscription.
|
107
|
+
# @return [Symbol]
|
108
|
+
def self.subscription_scope(new_scope = READING_SCOPE, optional: false)
|
109
|
+
if new_scope != READING_SCOPE
|
110
|
+
@subscription_scope = new_scope
|
111
|
+
@subscription_scope_optional = optional
|
112
|
+
elsif defined?(@subscription_scope)
|
113
|
+
@subscription_scope
|
114
|
+
else
|
115
|
+
find_inherited_value(:subscription_scope)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.subscription_scope_optional?
|
120
|
+
if defined?(@subscription_scope_optional)
|
121
|
+
@subscription_scope_optional
|
122
|
+
else
|
123
|
+
find_inherited_value(:subscription_scope_optional, false)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# This is called during initial subscription to get a "name" for this subscription.
|
128
|
+
# Later, when `.trigger` is called, this will be called again to build another "name".
|
129
|
+
# Any subscribers with matching topic will begin the update flow.
|
130
|
+
#
|
131
|
+
# The default implementation creates a string using the field name, subscription scope, and argument keys and values.
|
132
|
+
# In that implementation, only `.trigger` calls with _exact matches_ result in updates to subscribers.
|
133
|
+
#
|
134
|
+
# To implement a filtered stream-type subscription flow, override this method to return a string with field name and subscription scope.
|
135
|
+
# Then, implement {#update} to compare its arguments to the current `object` and return {NO_UPDATE} when an
|
136
|
+
# update should be filtered out.
|
137
|
+
#
|
138
|
+
# @see {#update} for how to skip updates when an event comes with a matching topic.
|
139
|
+
# @param arguments [Hash<String => Object>] The arguments for this topic, in GraphQL-style (camelized strings)
|
140
|
+
# @param field [GraphQL::Schema::Field]
|
141
|
+
# @param scope [Object, nil] A value corresponding to `.trigger(... scope:)` (for updates) or the `subscription_scope` found in `context` (for initial subscriptions).
|
142
|
+
# @return [String] An identifier corresponding to a stream of updates
|
143
|
+
def self.topic_for(arguments:, field:, scope:)
|
144
|
+
Subscriptions::Serialize.dump_recursive([scope, field.graphql_name, arguments])
|
145
|
+
end
|
146
|
+
|
147
|
+
# Overriding Resolver#field_options to include subscription_scope
|
148
|
+
def self.field_options
|
149
|
+
super.merge(
|
150
|
+
subscription_scope: subscription_scope
|
151
|
+
)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|