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,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
class Validator
|
6
|
+
# Use this validator to require _one_ of the named arguments to be present.
|
7
|
+
# Or, use Arrays of symbols to name a valid _set_ of arguments.
|
8
|
+
#
|
9
|
+
# (This is for specifying mutually exclusive sets of arguments.)
|
10
|
+
#
|
11
|
+
# @example Require exactly one of these arguments
|
12
|
+
#
|
13
|
+
# field :update_amount, IngredientAmount, null: false do
|
14
|
+
# argument :ingredient_id, ID, required: true
|
15
|
+
# argument :cups, Integer, required: false
|
16
|
+
# argument :tablespoons, Integer, required: false
|
17
|
+
# argument :teaspoons, Integer, required: true
|
18
|
+
# validates required: { one_of: [:cups, :tablespoons, :teaspoons] }
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# @example Require one of these _sets_ of arguments
|
22
|
+
#
|
23
|
+
# field :find_object, Node, null: true do
|
24
|
+
# argument :node_id, ID, required: false
|
25
|
+
# argument :object_type, String, required: false
|
26
|
+
# argument :object_id, Integer, required: false
|
27
|
+
# # either a global `node_id` or an `object_type`/`object_id` pair is required:
|
28
|
+
# validates required: { one_of: [:node_id, [:object_type, :object_id]] }
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
class RequiredValidator < Validator
|
32
|
+
# @param one_of [Symbol, Array<Symbol>] An argument, or a list of arguments, that represents a valid set of inputs for this field
|
33
|
+
# @param message [String]
|
34
|
+
def initialize(one_of:, message: "%{validated} has the wrong arguments", **default_options)
|
35
|
+
@one_of = one_of
|
36
|
+
@message = message
|
37
|
+
super(**default_options)
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate(_object, _context, value)
|
41
|
+
matched_conditions = 0
|
42
|
+
|
43
|
+
@one_of.each do |one_of_condition|
|
44
|
+
case one_of_condition
|
45
|
+
when Symbol
|
46
|
+
if value.key?(one_of_condition)
|
47
|
+
matched_conditions += 1
|
48
|
+
end
|
49
|
+
when Array
|
50
|
+
if one_of_condition.all? { |k| value.key?(k) }
|
51
|
+
matched_conditions += 1
|
52
|
+
break
|
53
|
+
end
|
54
|
+
else
|
55
|
+
raise ArgumentError, "Unknown one_of condition: #{one_of_condition.inspect}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if matched_conditions == 1
|
60
|
+
nil # OK
|
61
|
+
else
|
62
|
+
@message
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
class Validator
|
6
|
+
# The thing being validated
|
7
|
+
# @return [GraphQL::Schema::Argument, GraphQL::Schema::Field, GraphQL::Schema::Resolver, Class<GraphQL::Schema::InputObject>]
|
8
|
+
attr_reader :validated
|
9
|
+
|
10
|
+
# @param validated [GraphQL::Schema::Argument, GraphQL::Schema::Field, GraphQL::Schema::Resolver, Class<GraphQL::Schema::InputObject>] The argument or argument owner this validator is attached to
|
11
|
+
# @param allow_blank [Boolean] if `true`, then objects that respond to `.blank?` and return true for `.blank?` will skip this validation
|
12
|
+
# @param allow_null [Boolean] if `true`, then incoming `null`s will skip this validation
|
13
|
+
def initialize(validated:, allow_blank: false, allow_null: false)
|
14
|
+
@validated = validated
|
15
|
+
@allow_blank = allow_blank
|
16
|
+
@allow_null = allow_null
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param object [Object] The application object that this argument's field is being resolved for
|
20
|
+
# @param context [GraphQL::Query::Context]
|
21
|
+
# @param value [Object] The client-provided value for this argument (after parsing and coercing by the input type)
|
22
|
+
# @return [nil, Array<String>, String] Error message or messages to add
|
23
|
+
def validate(object, context, value)
|
24
|
+
raise GraphQL::RequiredImplementationMissingError, "Validator classes should implement #validate"
|
25
|
+
end
|
26
|
+
|
27
|
+
# This is like `String#%`, but it supports the case that only some of `string`'s
|
28
|
+
# values are present in `substitutions`
|
29
|
+
def partial_format(string, substitutions)
|
30
|
+
substitutions.each do |key, value|
|
31
|
+
sub_v = value.is_a?(String) ? value : value.to_s
|
32
|
+
string = string.gsub("%{#{key}}", sub_v)
|
33
|
+
end
|
34
|
+
string
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [Boolean] `true` if `value` is `nil` and this validator has `allow_null: true` or if value is `.blank?` and this validator has `allow_blank: true`
|
38
|
+
def permitted_empty_value?(value)
|
39
|
+
(value.nil? && @allow_null) ||
|
40
|
+
(@allow_blank && value.respond_to?(:blank?) && value.blank?)
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param schema_member [GraphQL::Schema::Field, GraphQL::Schema::Argument, Class<GraphQL::Schema::InputObject>]
|
44
|
+
# @param validates_hash [Hash{Symbol => Hash}, Hash{Class => Hash} nil] A configuration passed as `validates:`
|
45
|
+
# @return [Array<Validator>]
|
46
|
+
def self.from_config(schema_member, validates_hash)
|
47
|
+
if validates_hash.nil? || validates_hash.empty?
|
48
|
+
EMPTY_ARRAY
|
49
|
+
else
|
50
|
+
validates_hash = validates_hash.dup
|
51
|
+
allow_null = validates_hash.delete(:allow_null)
|
52
|
+
allow_blank = validates_hash.delete(:allow_blank)
|
53
|
+
|
54
|
+
# This could be {...}.compact on Ruby 2.4+
|
55
|
+
default_options = {}
|
56
|
+
if !allow_null.nil?
|
57
|
+
default_options[:allow_null] = allow_null
|
58
|
+
end
|
59
|
+
if !allow_blank.nil?
|
60
|
+
default_options[:allow_blank] = allow_blank
|
61
|
+
end
|
62
|
+
|
63
|
+
# allow_nil or allow_blank are the _only_ validations:
|
64
|
+
if validates_hash.empty?
|
65
|
+
validates_hash = default_options
|
66
|
+
end
|
67
|
+
|
68
|
+
validates_hash.map do |validator_name, options|
|
69
|
+
validator_class = case validator_name
|
70
|
+
when Class
|
71
|
+
validator_name
|
72
|
+
else
|
73
|
+
all_validators[validator_name] || raise(ArgumentError, "unknown validation: #{validator_name.inspect}")
|
74
|
+
end
|
75
|
+
if options.is_a?(Hash)
|
76
|
+
validator_class.new(validated: schema_member, **(default_options.merge(options)))
|
77
|
+
else
|
78
|
+
validator_class.new(options, validated: schema_member, **default_options)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Add `validator_class` to be initialized when `validates:` is given `name`.
|
85
|
+
# (It's initialized with whatever options are given by the key `name`).
|
86
|
+
# @param name [Symbol]
|
87
|
+
# @param validator_class [Class]
|
88
|
+
# @return [void]
|
89
|
+
def self.install(name, validator_class)
|
90
|
+
all_validators[name] = validator_class
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
|
94
|
+
# Remove whatever validator class is {.install}ed at `name`, if there is one
|
95
|
+
# @param name [Symbol]
|
96
|
+
# @return [void]
|
97
|
+
def self.uninstall(name)
|
98
|
+
all_validators.delete(name)
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
|
102
|
+
class << self
|
103
|
+
attr_accessor :all_validators
|
104
|
+
end
|
105
|
+
|
106
|
+
self.all_validators = {}
|
107
|
+
|
108
|
+
include Schema::FindInheritedValue::EmptyObjects
|
109
|
+
|
110
|
+
class ValidationFailedError < GraphQL::ExecutionError
|
111
|
+
attr_reader :errors
|
112
|
+
|
113
|
+
def initialize(errors:)
|
114
|
+
@errors = errors
|
115
|
+
super(errors.join(", "))
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# @param validators [Array<Validator>]
|
120
|
+
# @param object [Object]
|
121
|
+
# @param context [Query::Context]
|
122
|
+
# @param value [Object]
|
123
|
+
# @return [void]
|
124
|
+
# @raises [ValidationFailedError]
|
125
|
+
def self.validate!(validators, object, context, value, as: nil)
|
126
|
+
# Assuming the default case is no errors, reduce allocations in that case.
|
127
|
+
# This will be replaced with a mutable array if we actually get any errors.
|
128
|
+
all_errors = EMPTY_ARRAY
|
129
|
+
|
130
|
+
validators.each do |validator|
|
131
|
+
validated = as || validator.validated
|
132
|
+
errors = validator.validate(object, context, value)
|
133
|
+
if errors &&
|
134
|
+
(errors.is_a?(Array) && errors != EMPTY_ARRAY) ||
|
135
|
+
(errors.is_a?(String))
|
136
|
+
if all_errors.frozen? # It's empty
|
137
|
+
all_errors = []
|
138
|
+
end
|
139
|
+
interpolation_vars = { validated: validated.graphql_name }
|
140
|
+
if errors.is_a?(String)
|
141
|
+
all_errors << (errors % interpolation_vars)
|
142
|
+
else
|
143
|
+
errors = errors.map { |e| e % interpolation_vars }
|
144
|
+
all_errors.concat(errors)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
if all_errors.any?
|
150
|
+
raise ValidationFailedError.new(errors: all_errors)
|
151
|
+
end
|
152
|
+
nil
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
require "graphql/schema/validator/length_validator"
|
160
|
+
GraphQL::Schema::Validator.install(:length, GraphQL::Schema::Validator::LengthValidator)
|
161
|
+
require "graphql/schema/validator/numericality_validator"
|
162
|
+
GraphQL::Schema::Validator.install(:numericality, GraphQL::Schema::Validator::NumericalityValidator)
|
163
|
+
require "graphql/schema/validator/format_validator"
|
164
|
+
GraphQL::Schema::Validator.install(:format, GraphQL::Schema::Validator::FormatValidator)
|
165
|
+
require "graphql/schema/validator/inclusion_validator"
|
166
|
+
GraphQL::Schema::Validator.install(:inclusion, GraphQL::Schema::Validator::InclusionValidator)
|
167
|
+
require "graphql/schema/validator/exclusion_validator"
|
168
|
+
GraphQL::Schema::Validator.install(:exclusion, GraphQL::Schema::Validator::ExclusionValidator)
|
169
|
+
require "graphql/schema/validator/required_validator"
|
170
|
+
GraphQL::Schema::Validator.install(:required, GraphQL::Schema::Validator::RequiredValidator)
|
171
|
+
require "graphql/schema/validator/allow_null_validator"
|
172
|
+
GraphQL::Schema::Validator.install(:allow_null, GraphQL::Schema::Validator::AllowNullValidator)
|
173
|
+
require "graphql/schema/validator/allow_blank_validator"
|
174
|
+
GraphQL::Schema::Validator.install(:allow_blank, GraphQL::Schema::Validator::AllowBlankValidator)
|
@@ -0,0 +1,409 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module GraphQL
|
6
|
+
class Schema
|
7
|
+
# Restrict access to a {GraphQL::Schema} with a user-defined filter.
|
8
|
+
#
|
9
|
+
# When validating and executing a query, all access to schema members
|
10
|
+
# should go through a warden. If you access the schema directly,
|
11
|
+
# you may show a client something that it shouldn't be allowed to see.
|
12
|
+
#
|
13
|
+
# @example Hidding private fields
|
14
|
+
# private_members = -> (member, ctx) { member.metadata[:private] }
|
15
|
+
# result = Schema.execute(query_string, except: private_members)
|
16
|
+
#
|
17
|
+
# @example Custom filter implementation
|
18
|
+
# # It must respond to `#call(member)`.
|
19
|
+
# class MissingRequiredFlags
|
20
|
+
# def initialize(user)
|
21
|
+
# @user = user
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # Return `false` if any required flags are missing
|
25
|
+
# def call(member, ctx)
|
26
|
+
# member.metadata[:required_flags].any? do |flag|
|
27
|
+
# !@user.has_flag?(flag)
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# # Then, use the custom filter in query:
|
33
|
+
# missing_required_flags = MissingRequiredFlags.new(current_user)
|
34
|
+
#
|
35
|
+
# # This query can only access members which match the user's flags
|
36
|
+
# result = Schema.execute(query_string, except: missing_required_flags)
|
37
|
+
#
|
38
|
+
# @api private
|
39
|
+
class Warden
|
40
|
+
def self.from_context(context)
|
41
|
+
(context.respond_to?(:warden) && context.warden) || PassThruWarden
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param visibility_method [Symbol] a Warden method to call for this entry
|
45
|
+
# @param entry [Object, Array<Object>] One or more definitions for a given name in a GraphQL Schema
|
46
|
+
# @param context [GraphQL::Query::Context]
|
47
|
+
# @param warden [Warden]
|
48
|
+
# @return [Object] `entry` or one of `entry`'s items if exactly one of them is visible for this context
|
49
|
+
# @return [nil] If neither `entry` nor any of `entry`'s items are visible for this context
|
50
|
+
def self.visible_entry?(visibility_method, entry, context, warden = Warden.from_context(context))
|
51
|
+
if entry.is_a?(Array)
|
52
|
+
visible_item = nil
|
53
|
+
entry.each do |item|
|
54
|
+
if warden.public_send(visibility_method, item, context)
|
55
|
+
if visible_item.nil?
|
56
|
+
visible_item = item
|
57
|
+
else
|
58
|
+
raise Schema::DuplicateNamesError, "Found two visible definitions for `#{item.path}`: #{visible_item.inspect}, #{item.inspect}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
visible_item
|
63
|
+
elsif warden.public_send(visibility_method, entry, context)
|
64
|
+
entry
|
65
|
+
else
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# This is used when a caller provides a Hash for context.
|
71
|
+
# We want to call the schema's hooks, but we don't have a full-blown warden.
|
72
|
+
# The `context` arguments to these methods exist purely to simplify the code that
|
73
|
+
# calls methods on this object, so it will have everything it needs.
|
74
|
+
class PassThruWarden
|
75
|
+
class << self
|
76
|
+
def visible_field?(field, ctx); field.visible?(ctx); end
|
77
|
+
def visible_argument?(arg, ctx); arg.visible?(ctx); end
|
78
|
+
def visible_type?(type, ctx); type.visible?(ctx); end
|
79
|
+
def visible_enum_value?(ev, ctx); ev.visible?(ctx); end
|
80
|
+
def visible_type_membership?(tm, ctx); tm.visible?(ctx); end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# @param filter [<#call(member)>] Objects are hidden when `.call(member, ctx)` returns true
|
85
|
+
# @param context [GraphQL::Query::Context]
|
86
|
+
# @param schema [GraphQL::Schema]
|
87
|
+
def initialize(filter, context:, schema:)
|
88
|
+
@schema = schema.interpreter? ? schema : schema.graphql_definition
|
89
|
+
# Cache these to avoid repeated hits to the inheritance chain when one isn't present
|
90
|
+
@query = @schema.query
|
91
|
+
@mutation = @schema.mutation
|
92
|
+
@subscription = @schema.subscription
|
93
|
+
@context = context
|
94
|
+
@visibility_cache = read_through { |m| filter.call(m, context) }
|
95
|
+
end
|
96
|
+
|
97
|
+
# @return [Hash<String, GraphQL::BaseType>] Visible types in the schema
|
98
|
+
def types
|
99
|
+
@types ||= begin
|
100
|
+
vis_types = {}
|
101
|
+
@schema.types(@context).each do |n, t|
|
102
|
+
if visible_and_reachable_type?(t)
|
103
|
+
vis_types[n] = t
|
104
|
+
end
|
105
|
+
end
|
106
|
+
vis_types
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# @return [GraphQL::BaseType, nil] The type named `type_name`, if it exists (else `nil`)
|
111
|
+
def get_type(type_name)
|
112
|
+
@visible_types ||= read_through do |name|
|
113
|
+
type_defn = @schema.get_type(name, @context)
|
114
|
+
if type_defn && visible_and_reachable_type?(type_defn)
|
115
|
+
type_defn
|
116
|
+
else
|
117
|
+
nil
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
@visible_types[type_name]
|
122
|
+
end
|
123
|
+
|
124
|
+
# @return [Array<GraphQL::BaseType>] Visible and reachable types in the schema
|
125
|
+
def reachable_types
|
126
|
+
@reachable_types ||= reachable_type_set.to_a
|
127
|
+
end
|
128
|
+
|
129
|
+
# @return Boolean True if the type is visible and reachable in the schema
|
130
|
+
def reachable_type?(type_name)
|
131
|
+
type = get_type(type_name) # rubocop:disable Development/ContextIsPassedCop -- `self` is query-aware
|
132
|
+
type && reachable_type_set.include?(type)
|
133
|
+
end
|
134
|
+
|
135
|
+
# @return [GraphQL::Field, nil] The field named `field_name` on `parent_type`, if it exists
|
136
|
+
def get_field(parent_type, field_name)
|
137
|
+
@visible_parent_fields ||= read_through do |type|
|
138
|
+
read_through do |f_name|
|
139
|
+
field_defn = @schema.get_field(type, f_name, @context)
|
140
|
+
if field_defn && visible_field?(field_defn, nil, type)
|
141
|
+
field_defn
|
142
|
+
else
|
143
|
+
nil
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
@visible_parent_fields[parent_type][field_name]
|
149
|
+
end
|
150
|
+
|
151
|
+
# @return [GraphQL::Argument, nil] The argument named `argument_name` on `parent_type`, if it exists and is visible
|
152
|
+
def get_argument(parent_type, argument_name)
|
153
|
+
argument = parent_type.get_argument(argument_name, @context)
|
154
|
+
return argument if argument && visible_argument?(argument, @context)
|
155
|
+
end
|
156
|
+
|
157
|
+
# @return [Array<GraphQL::BaseType>] The types which may be member of `type_defn`
|
158
|
+
def possible_types(type_defn)
|
159
|
+
@visible_possible_types ||= read_through { |type_defn|
|
160
|
+
pt = @schema.possible_types(type_defn, @context)
|
161
|
+
pt.select { |t| visible_and_reachable_type?(t) }
|
162
|
+
}
|
163
|
+
@visible_possible_types[type_defn]
|
164
|
+
end
|
165
|
+
|
166
|
+
# @param type_defn [GraphQL::ObjectType, GraphQL::InterfaceType]
|
167
|
+
# @return [Array<GraphQL::Field>] Fields on `type_defn`
|
168
|
+
def fields(type_defn)
|
169
|
+
@visible_fields ||= read_through { |t| @schema.get_fields(t, @context).values }
|
170
|
+
@visible_fields[type_defn]
|
171
|
+
end
|
172
|
+
|
173
|
+
# @param argument_owner [GraphQL::Field, GraphQL::InputObjectType]
|
174
|
+
# @return [Array<GraphQL::Argument>] Visible arguments on `argument_owner`
|
175
|
+
def arguments(argument_owner)
|
176
|
+
@visible_arguments ||= read_through { |o| o.arguments(@context).each_value.select { |a| visible_argument?(a) } }
|
177
|
+
@visible_arguments[argument_owner]
|
178
|
+
end
|
179
|
+
|
180
|
+
# @return [Array<GraphQL::EnumType::EnumValue>] Visible members of `enum_defn`
|
181
|
+
def enum_values(enum_defn)
|
182
|
+
@visible_enum_arrays ||= read_through { |e| e.enum_values(@context) }
|
183
|
+
@visible_enum_arrays[enum_defn]
|
184
|
+
end
|
185
|
+
|
186
|
+
def visible_enum_value?(enum_value, _ctx = nil)
|
187
|
+
@visible_enum_values ||= read_through { |ev| visible?(ev) }
|
188
|
+
@visible_enum_values[enum_value]
|
189
|
+
end
|
190
|
+
|
191
|
+
# @return [Array<GraphQL::InterfaceType>] Visible interfaces implemented by `obj_type`
|
192
|
+
def interfaces(obj_type)
|
193
|
+
@visible_interfaces ||= read_through { |t| t.interfaces(@context).select { |i| visible_type?(i) } }
|
194
|
+
@visible_interfaces[obj_type]
|
195
|
+
end
|
196
|
+
|
197
|
+
def directives
|
198
|
+
@schema.directives.each_value.select { |d| visible?(d) }
|
199
|
+
end
|
200
|
+
|
201
|
+
def root_type_for_operation(op_name)
|
202
|
+
root_type = @schema.root_type_for_operation(op_name)
|
203
|
+
if root_type && visible?(root_type)
|
204
|
+
root_type
|
205
|
+
else
|
206
|
+
nil
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
# @param owner [Class, Module] If provided, confirm that field has the given owner.
|
211
|
+
def visible_field?(field_defn, _ctx = nil, owner = field_defn.owner)
|
212
|
+
# This field is visible in its own right
|
213
|
+
visible?(field_defn) &&
|
214
|
+
# This field's return type is visible
|
215
|
+
visible_and_reachable_type?(field_defn.type.unwrap) &&
|
216
|
+
# This field is either defined on this object type,
|
217
|
+
# or the interface it's inherited from is also visible
|
218
|
+
((field_defn.respond_to?(:owner) && field_defn.owner == owner) || field_on_visible_interface?(field_defn, owner))
|
219
|
+
end
|
220
|
+
|
221
|
+
def visible_argument?(arg_defn, _ctx = nil)
|
222
|
+
visible?(arg_defn) && visible_and_reachable_type?(arg_defn.type.unwrap)
|
223
|
+
end
|
224
|
+
|
225
|
+
def visible_type?(type_defn, _ctx = nil)
|
226
|
+
@type_visibility ||= read_through { |type_defn| visible?(type_defn) }
|
227
|
+
@type_visibility[type_defn]
|
228
|
+
end
|
229
|
+
|
230
|
+
def visible_type_membership?(type_membership, _ctx = nil)
|
231
|
+
visible?(type_membership)
|
232
|
+
end
|
233
|
+
|
234
|
+
private
|
235
|
+
|
236
|
+
def visible_and_reachable_type?(type_defn)
|
237
|
+
@visible_and_reachable_type ||= read_through do |type_defn|
|
238
|
+
next false unless visible_type?(type_defn)
|
239
|
+
next true if root_type?(type_defn) || type_defn.introspection?
|
240
|
+
|
241
|
+
if type_defn.kind.union?
|
242
|
+
visible_possible_types?(type_defn) && (referenced?(type_defn) || orphan_type?(type_defn))
|
243
|
+
elsif type_defn.kind.interface?
|
244
|
+
visible_possible_types?(type_defn)
|
245
|
+
else
|
246
|
+
referenced?(type_defn) || visible_abstract_type?(type_defn)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
@visible_and_reachable_type[type_defn]
|
251
|
+
end
|
252
|
+
|
253
|
+
def union_memberships(obj_type)
|
254
|
+
@unions ||= read_through { |obj_type| @schema.union_memberships(obj_type).select { |u| visible?(u) } }
|
255
|
+
@unions[obj_type]
|
256
|
+
end
|
257
|
+
|
258
|
+
# We need this to tell whether a field was inherited by an interface
|
259
|
+
# even when that interface is hidden from `#interfaces`
|
260
|
+
def unfiltered_interfaces(type_defn)
|
261
|
+
@unfiltered_interfaces ||= read_through(&:interfaces)
|
262
|
+
@unfiltered_interfaces[type_defn]
|
263
|
+
end
|
264
|
+
|
265
|
+
# If this field was inherited from an interface, and the field on that interface is _hidden_,
|
266
|
+
# then treat this inherited field as hidden.
|
267
|
+
# (If it _wasn't_ inherited, then don't hide it for this reason.)
|
268
|
+
def field_on_visible_interface?(field_defn, type_defn)
|
269
|
+
if type_defn.kind.object?
|
270
|
+
any_interface_has_field = false
|
271
|
+
any_interface_has_visible_field = false
|
272
|
+
ints = unfiltered_interfaces(type_defn)
|
273
|
+
ints.each do |interface_type|
|
274
|
+
if (iface_field_defn = interface_type.get_field(field_defn.graphql_name, @context))
|
275
|
+
any_interface_has_field = true
|
276
|
+
|
277
|
+
if interfaces(type_defn).include?(interface_type) && visible_field?(iface_field_defn, nil, interface_type)
|
278
|
+
any_interface_has_visible_field = true
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
if any_interface_has_field
|
284
|
+
any_interface_has_visible_field
|
285
|
+
else
|
286
|
+
# it's the object's own field
|
287
|
+
true
|
288
|
+
end
|
289
|
+
else
|
290
|
+
true
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def root_type?(type_defn)
|
295
|
+
@query == type_defn ||
|
296
|
+
@mutation == type_defn ||
|
297
|
+
@subscription == type_defn
|
298
|
+
end
|
299
|
+
|
300
|
+
def referenced?(type_defn)
|
301
|
+
@references_to ||= @schema.references_to
|
302
|
+
graphql_name = type_defn.unwrap.graphql_name
|
303
|
+
members = @references_to[graphql_name] || NO_REFERENCES
|
304
|
+
members.any? { |m| visible?(m) }
|
305
|
+
end
|
306
|
+
|
307
|
+
NO_REFERENCES = [].freeze
|
308
|
+
|
309
|
+
def orphan_type?(type_defn)
|
310
|
+
@schema.orphan_types.include?(type_defn)
|
311
|
+
end
|
312
|
+
|
313
|
+
def visible_abstract_type?(type_defn)
|
314
|
+
type_defn.kind.object? && (
|
315
|
+
interfaces(type_defn).any? ||
|
316
|
+
union_memberships(type_defn).any?
|
317
|
+
)
|
318
|
+
end
|
319
|
+
|
320
|
+
def visible_possible_types?(type_defn)
|
321
|
+
possible_types(type_defn).any? { |t| visible_and_reachable_type?(t) }
|
322
|
+
end
|
323
|
+
|
324
|
+
def visible?(member)
|
325
|
+
@visibility_cache[member]
|
326
|
+
end
|
327
|
+
|
328
|
+
def read_through
|
329
|
+
Hash.new { |h, k| h[k] = yield(k) }
|
330
|
+
end
|
331
|
+
|
332
|
+
def reachable_type_set
|
333
|
+
return @reachable_type_set if defined?(@reachable_type_set)
|
334
|
+
|
335
|
+
@reachable_type_set = Set.new
|
336
|
+
rt_hash = {}
|
337
|
+
|
338
|
+
unvisited_types = []
|
339
|
+
['query', 'mutation', 'subscription'].each do |op_name|
|
340
|
+
root_type = root_type_for_operation(op_name)
|
341
|
+
unvisited_types << root_type if root_type
|
342
|
+
end
|
343
|
+
unvisited_types.concat(@schema.introspection_system.types.values)
|
344
|
+
|
345
|
+
directives.each do |dir_class|
|
346
|
+
arguments(dir_class).each do |arg_defn|
|
347
|
+
arg_t = arg_defn.type.unwrap
|
348
|
+
if get_type(arg_t.graphql_name) # rubocop:disable Development/ContextIsPassedCop -- `self` is query-aware
|
349
|
+
unvisited_types << arg_t
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
@schema.orphan_types.each do |orphan_type|
|
355
|
+
if get_type(orphan_type.graphql_name) == orphan_type # rubocop:disable Development/ContextIsPassedCop -- `self` is query-aware
|
356
|
+
unvisited_types << orphan_type
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
until unvisited_types.empty?
|
361
|
+
type = unvisited_types.pop
|
362
|
+
if @reachable_type_set.add?(type)
|
363
|
+
type_by_name = rt_hash[type.graphql_name] ||= type
|
364
|
+
if type_by_name != type
|
365
|
+
raise DuplicateNamesError, "Found two visible type definitions for `#{type.graphql_name}`: #{type.inspect}, #{type_by_name.inspect}"
|
366
|
+
end
|
367
|
+
if type.kind.input_object?
|
368
|
+
# recurse into visible arguments
|
369
|
+
arguments(type).each do |argument|
|
370
|
+
argument_type = argument.type.unwrap
|
371
|
+
unvisited_types << argument_type
|
372
|
+
end
|
373
|
+
elsif type.kind.union?
|
374
|
+
# recurse into visible possible types
|
375
|
+
possible_types(type).each do |possible_type|
|
376
|
+
unvisited_types << possible_type
|
377
|
+
end
|
378
|
+
elsif type.kind.fields?
|
379
|
+
if type.kind.interface?
|
380
|
+
# recurse into visible possible types
|
381
|
+
possible_types(type).each do |possible_type|
|
382
|
+
unvisited_types << possible_type
|
383
|
+
end
|
384
|
+
elsif type.kind.object?
|
385
|
+
# recurse into visible implemented interfaces
|
386
|
+
interfaces(type).each do |interface|
|
387
|
+
unvisited_types << interface
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
# recurse into visible fields
|
392
|
+
fields(type).each do |field|
|
393
|
+
field_type = field.type.unwrap
|
394
|
+
unvisited_types << field_type
|
395
|
+
# recurse into visible arguments
|
396
|
+
arguments(field).each do |argument|
|
397
|
+
argument_type = argument.type.unwrap
|
398
|
+
unvisited_types << argument_type
|
399
|
+
end
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
@reachable_type_set
|
406
|
+
end
|
407
|
+
end
|
408
|
+
end
|
409
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
class Wrapper
|
6
|
+
include GraphQL::Schema::Member::CachedGraphQLDefinition
|
7
|
+
include GraphQL::Schema::Member::TypeSystemHelpers
|
8
|
+
|
9
|
+
# @return [Class, Module] The inner type of this wrapping type, the type of which one or more objects may be present.
|
10
|
+
attr_reader :of_type
|
11
|
+
|
12
|
+
def initialize(of_type)
|
13
|
+
@of_type = of_type
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_graphql
|
17
|
+
raise GraphQL::RequiredImplementationMissingError
|
18
|
+
end
|
19
|
+
|
20
|
+
def unwrap
|
21
|
+
@of_type.unwrap
|
22
|
+
end
|
23
|
+
|
24
|
+
def ==(other)
|
25
|
+
self.class == other.class && of_type == other.of_type
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|