graphql 2.0.31 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/generators/graphql/detailed_trace_generator.rb +77 -0
- data/lib/generators/graphql/install/mutation_root_generator.rb +2 -2
- data/lib/generators/graphql/install/templates/base_mutation.erb +2 -0
- data/lib/generators/graphql/install/templates/mutation_type.erb +2 -0
- data/lib/generators/graphql/install_generator.rb +49 -0
- data/lib/generators/graphql/orm_mutations_base.rb +1 -1
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_connection.erb +2 -0
- data/lib/generators/graphql/templates/base_edge.erb +2 -0
- data/lib/generators/graphql/templates/base_enum.erb +2 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +2 -0
- data/lib/generators/graphql/templates/base_interface.erb +2 -0
- data/lib/generators/graphql/templates/base_object.erb +2 -0
- data/lib/generators/graphql/templates/base_resolver.erb +8 -0
- data/lib/generators/graphql/templates/base_scalar.erb +2 -0
- data/lib/generators/graphql/templates/base_union.erb +2 -0
- data/lib/generators/graphql/templates/create_graphql_detailed_traces.erb +10 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
- data/lib/generators/graphql/templates/loader.erb +2 -0
- data/lib/generators/graphql/templates/mutation.erb +2 -0
- data/lib/generators/graphql/templates/node_type.erb +2 -0
- data/lib/generators/graphql/templates/query_type.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +5 -0
- data/lib/generators/graphql/type_generator.rb +1 -1
- data/lib/graphql/analysis/analyzer.rb +90 -0
- data/lib/graphql/analysis/field_usage.rb +82 -0
- data/lib/graphql/analysis/max_query_complexity.rb +20 -0
- data/lib/graphql/analysis/max_query_depth.rb +20 -0
- data/lib/graphql/analysis/query_complexity.rb +263 -0
- data/lib/graphql/analysis/query_depth.rb +58 -0
- data/lib/graphql/analysis/visitor.rb +280 -0
- data/lib/graphql/analysis.rb +102 -1
- data/lib/graphql/autoload.rb +38 -0
- data/lib/graphql/backtrace/table.rb +118 -55
- data/lib/graphql/backtrace.rb +1 -19
- data/lib/graphql/coercion_error.rb +1 -9
- data/lib/graphql/current.rb +57 -0
- data/lib/graphql/dashboard/application_controller.rb +41 -0
- data/lib/graphql/dashboard/detailed_traces.rb +47 -0
- data/lib/graphql/dashboard/installable.rb +22 -0
- data/lib/graphql/dashboard/landings_controller.rb +9 -0
- data/lib/graphql/dashboard/limiters.rb +93 -0
- data/lib/graphql/dashboard/operation_store.rb +199 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.css +6 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.js +7 -0
- data/lib/graphql/dashboard/statics/charts.min.css +1 -0
- data/lib/graphql/dashboard/statics/dashboard.css +30 -0
- data/lib/graphql/dashboard/statics/dashboard.js +143 -0
- data/lib/graphql/dashboard/statics/header-icon.png +0 -0
- data/lib/graphql/dashboard/statics/icon.png +0 -0
- data/lib/graphql/dashboard/statics_controller.rb +31 -0
- data/lib/graphql/dashboard/subscriptions.rb +97 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/detailed_traces/traces/index.html.erb +45 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/landings/show.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/limiters/limiters/show.html.erb +62 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/not_installed.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/_form.html.erb +24 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/edit.html.erb +21 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/index.html.erb +69 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/new.html.erb +7 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/index.html.erb +39 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/show.html.erb +32 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/index.html.erb +81 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/show.html.erb +71 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/subscriptions/show.html.erb +41 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/index.html.erb +55 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/show.html.erb +40 -0
- data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +108 -0
- data/lib/graphql/dashboard.rb +96 -0
- data/lib/graphql/dataloader/active_record_association_source.rb +84 -0
- data/lib/graphql/dataloader/active_record_source.rb +47 -0
- data/lib/graphql/dataloader/async_dataloader.rb +112 -0
- data/lib/graphql/dataloader/null_dataloader.rb +55 -10
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +35 -12
- data/lib/graphql/dataloader.rb +224 -149
- data/lib/graphql/date_encoding_error.rb +1 -1
- data/lib/graphql/dig.rb +2 -1
- data/lib/graphql/duration_encoding_error.rb +16 -0
- data/lib/graphql/execution/field_resolve_step.rb +631 -0
- data/lib/graphql/execution/finalize.rb +217 -0
- data/lib/graphql/execution/input_values.rb +261 -0
- data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -10
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +6 -0
- data/lib/graphql/execution/interpreter/resolve.rb +23 -25
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +228 -0
- data/lib/graphql/execution/interpreter/runtime.rb +365 -435
- data/lib/graphql/execution/interpreter.rb +87 -163
- data/lib/graphql/execution/lazy.rb +1 -1
- data/lib/graphql/execution/load_argument_step.rb +64 -0
- data/lib/graphql/execution/lookahead.rb +105 -31
- data/lib/graphql/execution/multiplex.rb +7 -6
- data/lib/graphql/execution/next.rb +90 -0
- data/lib/graphql/execution/prepare_object_step.rb +128 -0
- data/lib/graphql/execution/runner.rb +410 -0
- data/lib/graphql/execution/selections_step.rb +91 -0
- data/lib/graphql/execution.rb +8 -4
- data/lib/graphql/execution_error.rb +17 -10
- data/lib/graphql/introspection/directive_location_enum.rb +1 -1
- data/lib/graphql/introspection/directive_type.rb +7 -3
- data/lib/graphql/introspection/dynamic_fields.rb +5 -1
- data/lib/graphql/introspection/entry_points.rb +20 -6
- data/lib/graphql/introspection/enum_value_type.rb +5 -5
- data/lib/graphql/introspection/field_type.rb +13 -5
- data/lib/graphql/introspection/input_value_type.rb +21 -13
- data/lib/graphql/introspection/schema_type.rb +8 -11
- data/lib/graphql/introspection/type_type.rb +64 -28
- data/lib/graphql/invalid_name_error.rb +1 -1
- data/lib/graphql/invalid_null_error.rb +26 -17
- data/lib/graphql/language/block_string.rb +34 -18
- data/lib/graphql/language/cache.rb +13 -0
- data/lib/graphql/language/comment.rb +18 -0
- data/lib/graphql/language/definition_slice.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +90 -61
- data/lib/graphql/language/lexer.rb +323 -193
- data/lib/graphql/language/nodes.rb +139 -77
- data/lib/graphql/language/parser.rb +807 -1985
- data/lib/graphql/language/printer.rb +324 -151
- data/lib/graphql/language/sanitized_printer.rb +21 -23
- data/lib/graphql/language/static_visitor.rb +171 -0
- data/lib/graphql/language/visitor.rb +62 -119
- data/lib/graphql/language.rb +71 -1
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/pagination/array_connection.rb +6 -6
- data/lib/graphql/pagination/connection.rb +30 -1
- data/lib/graphql/pagination/connections.rb +32 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
- data/lib/graphql/query/context/scoped_context.rb +101 -0
- data/lib/graphql/query/context.rb +88 -144
- data/lib/graphql/query/null_context.rb +15 -18
- data/lib/graphql/query/partial.rb +194 -0
- data/lib/graphql/query/validation_pipeline.rb +4 -4
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query/variables.rb +3 -3
- data/lib/graphql/query.rb +135 -81
- data/lib/graphql/railtie.rb +16 -6
- data/lib/graphql/rake_task.rb +3 -12
- data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
- data/lib/graphql/rubocop/graphql/field_type_in_block.rb +144 -0
- data/lib/graphql/rubocop/graphql/root_types_in_block.rb +38 -0
- data/lib/graphql/rubocop.rb +2 -0
- data/lib/graphql/runtime_error.rb +6 -0
- data/lib/graphql/schema/addition.rb +26 -13
- data/lib/graphql/schema/always_visible.rb +7 -2
- data/lib/graphql/schema/argument.rb +78 -14
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +140 -66
- data/lib/graphql/schema/directive/flagged.rb +4 -2
- data/lib/graphql/schema/directive/one_of.rb +12 -0
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive.rb +78 -12
- data/lib/graphql/schema/enum.rb +110 -27
- data/lib/graphql/schema/enum_value.rb +11 -3
- data/lib/graphql/schema/field/connection_extension.rb +4 -51
- data/lib/graphql/schema/field/scope_extension.rb +19 -7
- data/lib/graphql/schema/field.rb +245 -119
- data/lib/graphql/schema/field_extension.rb +12 -9
- data/lib/graphql/schema/has_single_input_argument.rb +160 -0
- data/lib/graphql/schema/input_object.rb +123 -65
- data/lib/graphql/schema/interface.rb +60 -16
- data/lib/graphql/schema/introspection_system.rb +8 -17
- data/lib/graphql/schema/late_bound_type.rb +4 -0
- data/lib/graphql/schema/list.rb +8 -4
- data/lib/graphql/schema/loader.rb +3 -4
- data/lib/graphql/schema/member/base_dsl_methods.rb +18 -12
- data/lib/graphql/schema/member/has_arguments.rb +132 -100
- data/lib/graphql/schema/member/has_authorization.rb +35 -0
- data/lib/graphql/schema/member/has_dataloader.rb +99 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +15 -0
- data/lib/graphql/schema/member/has_directives.rb +5 -5
- data/lib/graphql/schema/member/has_fields.rb +121 -17
- data/lib/graphql/schema/member/has_interfaces.rb +27 -13
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- data/lib/graphql/schema/member/has_validators.rb +1 -1
- data/lib/graphql/schema/member/relay_shortcuts.rb +1 -1
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +18 -5
- data/lib/graphql/schema/member/validates_input.rb +3 -3
- data/lib/graphql/schema/member.rb +6 -0
- data/lib/graphql/schema/mutation.rb +7 -0
- data/lib/graphql/schema/non_null.rb +1 -1
- data/lib/graphql/schema/object.rb +34 -8
- data/lib/graphql/schema/printer.rb +9 -7
- data/lib/graphql/schema/ractor_shareable.rb +79 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +6 -129
- data/lib/graphql/schema/resolver.rb +128 -32
- data/lib/graphql/schema/scalar.rb +4 -9
- data/lib/graphql/schema/subscription.rb +63 -12
- data/lib/graphql/schema/timeout.rb +19 -2
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/union.rb +2 -2
- data/lib/graphql/schema/unique_within_type.rb +1 -1
- data/lib/graphql/schema/validator/all_validator.rb +62 -0
- data/lib/graphql/schema/validator/required_validator.rb +92 -11
- data/lib/graphql/schema/validator.rb +3 -1
- data/lib/graphql/schema/visibility/migration.rb +188 -0
- data/lib/graphql/schema/visibility/profile.rb +464 -0
- data/lib/graphql/schema/visibility/visit.rb +190 -0
- data/lib/graphql/schema/visibility.rb +311 -0
- data/lib/graphql/schema/warden.rb +275 -103
- data/lib/graphql/schema/wrapper.rb +7 -1
- data/lib/graphql/schema.rb +954 -212
- data/lib/graphql/static_validation/all_rules.rb +3 -3
- data/lib/graphql/static_validation/base_visitor.rb +96 -71
- data/lib/graphql/static_validation/literal_validator.rb +6 -7
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +2 -2
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +18 -6
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +6 -2
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +6 -3
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +14 -3
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +59 -15
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +391 -262
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +10 -2
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +6 -6
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +15 -2
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +1 -1
- data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +25 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +28 -8
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
- data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +26 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +7 -3
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +14 -2
- data/lib/graphql/static_validation/validation_context.rb +22 -6
- data/lib/graphql/static_validation/validator.rb +9 -1
- data/lib/graphql/static_validation.rb +0 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +8 -5
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +45 -19
- data/lib/graphql/subscriptions/event.rb +22 -4
- data/lib/graphql/subscriptions/serialize.rb +3 -1
- data/lib/graphql/subscriptions.rb +56 -17
- data/lib/graphql/testing/helpers.rb +161 -0
- data/lib/graphql/testing/mock_action_cable.rb +111 -0
- data/lib/graphql/testing.rb +3 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +14 -3
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +1 -1
- data/lib/graphql/tracing/appoptics_trace.rb +11 -3
- data/lib/graphql/tracing/appoptics_tracing.rb +9 -2
- data/lib/graphql/tracing/appsignal_trace.rb +32 -55
- data/lib/graphql/tracing/appsignal_tracing.rb +2 -0
- data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
- data/lib/graphql/tracing/data_dog_trace.rb +46 -158
- data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
- data/lib/graphql/tracing/detailed_trace/active_record_backend.rb +74 -0
- data/lib/graphql/tracing/detailed_trace/memory_backend.rb +60 -0
- data/lib/graphql/tracing/detailed_trace/redis_backend.rb +72 -0
- data/lib/graphql/tracing/detailed_trace.rb +156 -0
- data/lib/graphql/tracing/legacy_hooks_trace.rb +75 -0
- data/lib/graphql/tracing/legacy_trace.rb +4 -61
- data/lib/graphql/tracing/monitor_trace.rb +283 -0
- data/lib/graphql/tracing/new_relic_trace.rb +47 -54
- data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
- data/lib/graphql/tracing/notifications_trace.rb +184 -34
- data/lib/graphql/tracing/notifications_tracing.rb +2 -0
- data/lib/graphql/tracing/null_trace.rb +9 -0
- data/lib/graphql/tracing/perfetto_trace/trace.proto +141 -0
- data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +33 -0
- data/lib/graphql/tracing/perfetto_trace.rb +864 -0
- data/lib/graphql/tracing/platform_trace.rb +5 -0
- data/lib/graphql/tracing/platform_tracing.rb +3 -1
- data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +5 -1
- data/lib/graphql/tracing/prometheus_trace.rb +72 -68
- data/lib/graphql/tracing/prometheus_tracing.rb +2 -0
- data/lib/graphql/tracing/scout_trace.rb +32 -55
- data/lib/graphql/tracing/scout_tracing.rb +2 -0
- data/lib/graphql/tracing/sentry_trace.rb +82 -0
- data/lib/graphql/tracing/statsd_trace.rb +33 -41
- data/lib/graphql/tracing/statsd_tracing.rb +2 -0
- data/lib/graphql/tracing/trace.rb +118 -1
- data/lib/graphql/tracing.rb +31 -28
- data/lib/graphql/type_kinds.rb +2 -1
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/connection_behaviors.rb +45 -3
- data/lib/graphql/types/relay/edge_behaviors.rb +19 -1
- data/lib/graphql/types/relay/has_node_field.rb +13 -8
- data/lib/graphql/types/relay/has_nodes_field.rb +13 -8
- data/lib/graphql/types/relay/node_behaviors.rb +13 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
- data/lib/graphql/types.rb +18 -10
- data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
- data/lib/graphql/unauthorized_error.rb +9 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +69 -54
- data/readme.md +12 -2
- metadata +236 -40
- data/lib/graphql/analysis/ast/analyzer.rb +0 -84
- data/lib/graphql/analysis/ast/field_usage.rb +0 -57
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -22
- data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
- data/lib/graphql/analysis/ast/query_complexity.rb +0 -230
- data/lib/graphql/analysis/ast/query_depth.rb +0 -55
- data/lib/graphql/analysis/ast/visitor.rb +0 -276
- data/lib/graphql/analysis/ast.rb +0 -81
- data/lib/graphql/backtrace/inspect_result.rb +0 -50
- data/lib/graphql/backtrace/trace.rb +0 -96
- data/lib/graphql/backtrace/tracer.rb +0 -80
- data/lib/graphql/deprecation.rb +0 -9
- data/lib/graphql/filter.rb +0 -59
- data/lib/graphql/language/parser.y +0 -560
- data/lib/graphql/language/token.rb +0 -34
- data/lib/graphql/schema/base_64_bp.rb +0 -26
- data/lib/graphql/schema/invalid_type_error.rb +0 -7
- data/lib/graphql/schema/null_mask.rb +0 -11
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +0 -17
- data/lib/graphql/static_validation/type_stack.rb +0 -216
- data/lib/graphql/subscriptions/instrumentation.rb +0 -28
|
@@ -40,7 +40,7 @@ module GraphQL
|
|
|
40
40
|
case node
|
|
41
41
|
when FalseClass, Float, Integer, String, TrueClass
|
|
42
42
|
if @current_argument && redact_argument_value?(@current_argument, node)
|
|
43
|
-
redacted_argument_value(@current_argument)
|
|
43
|
+
print_string(redacted_argument_value(@current_argument))
|
|
44
44
|
else
|
|
45
45
|
super
|
|
46
46
|
end
|
|
@@ -51,9 +51,8 @@ module GraphQL
|
|
|
51
51
|
@current_input_type = @current_input_type.of_type if @current_input_type.non_null?
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
super
|
|
55
55
|
@current_input_type = old_input_type
|
|
56
|
-
res
|
|
57
56
|
else
|
|
58
57
|
super
|
|
59
58
|
end
|
|
@@ -89,11 +88,12 @@ module GraphQL
|
|
|
89
88
|
else
|
|
90
89
|
argument.value
|
|
91
90
|
end
|
|
92
|
-
|
|
91
|
+
|
|
92
|
+
print_string("#{argument.name}: ")
|
|
93
|
+
print_node(argument_value)
|
|
93
94
|
|
|
94
95
|
@current_input_type = old_input_type
|
|
95
96
|
@current_argument = old_current_argument
|
|
96
|
-
res
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
def coerce_argument_value_to_list?(type, value)
|
|
@@ -113,12 +113,11 @@ module GraphQL
|
|
|
113
113
|
end
|
|
114
114
|
|
|
115
115
|
def print_field(field, indent: "")
|
|
116
|
-
@current_field = query.
|
|
116
|
+
@current_field = query.types.field(@current_type, field.name)
|
|
117
117
|
old_type = @current_type
|
|
118
118
|
@current_type = @current_field.type.unwrap
|
|
119
|
-
|
|
119
|
+
super
|
|
120
120
|
@current_type = old_type
|
|
121
|
-
res
|
|
122
121
|
end
|
|
123
122
|
|
|
124
123
|
def print_inline_fragment(inline_fragment, indent: "")
|
|
@@ -128,31 +127,26 @@ module GraphQL
|
|
|
128
127
|
@current_type = query.get_type(inline_fragment.type.name)
|
|
129
128
|
end
|
|
130
129
|
|
|
131
|
-
|
|
130
|
+
super
|
|
132
131
|
|
|
133
132
|
@current_type = old_type
|
|
134
|
-
|
|
135
|
-
res
|
|
136
133
|
end
|
|
137
134
|
|
|
138
135
|
def print_fragment_definition(fragment_def, indent: "")
|
|
139
136
|
old_type = @current_type
|
|
140
137
|
@current_type = query.get_type(fragment_def.type.name)
|
|
141
138
|
|
|
142
|
-
|
|
139
|
+
super
|
|
143
140
|
|
|
144
141
|
@current_type = old_type
|
|
145
|
-
|
|
146
|
-
res
|
|
147
142
|
end
|
|
148
143
|
|
|
149
144
|
def print_directive(directive)
|
|
150
145
|
@current_directive = query.schema.directives[directive.name]
|
|
151
146
|
|
|
152
|
-
|
|
147
|
+
super
|
|
153
148
|
|
|
154
149
|
@current_directive = nil
|
|
155
|
-
res
|
|
156
150
|
end
|
|
157
151
|
|
|
158
152
|
# Print the operation definition but do not include the variable
|
|
@@ -162,16 +156,15 @@ module GraphQL
|
|
|
162
156
|
@current_type = query.schema.public_send(operation_definition.operation_type)
|
|
163
157
|
|
|
164
158
|
if @inline_variables
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
159
|
+
print_string("#{indent}#{operation_definition.operation_type}")
|
|
160
|
+
print_string(" #{operation_definition.name}") if operation_definition.name
|
|
161
|
+
print_directives(operation_definition.directives)
|
|
162
|
+
print_selections(operation_definition.selections, indent: indent)
|
|
169
163
|
else
|
|
170
|
-
|
|
164
|
+
super
|
|
171
165
|
end
|
|
172
166
|
|
|
173
167
|
@current_type = old_type
|
|
174
|
-
out
|
|
175
168
|
end
|
|
176
169
|
|
|
177
170
|
private
|
|
@@ -210,7 +203,12 @@ module GraphQL
|
|
|
210
203
|
[value].map { |v| value_to_ast(v, type.of_type) }
|
|
211
204
|
end
|
|
212
205
|
when "ENUM"
|
|
213
|
-
GraphQL::Language::Nodes::Enum
|
|
206
|
+
if value.is_a?(GraphQL::Language::Nodes::Enum)
|
|
207
|
+
# if it was a default value, it's already wrapped
|
|
208
|
+
value
|
|
209
|
+
else
|
|
210
|
+
GraphQL::Language::Nodes::Enum.new(name: value)
|
|
211
|
+
end
|
|
214
212
|
else
|
|
215
213
|
value
|
|
216
214
|
end
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module GraphQL
|
|
3
|
+
module Language
|
|
4
|
+
# Like `GraphQL::Language::Visitor` except it doesn't support
|
|
5
|
+
# making changes to the document -- only visiting it as-is.
|
|
6
|
+
class StaticVisitor
|
|
7
|
+
def initialize(document)
|
|
8
|
+
@document = document
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Visit `document` and all children
|
|
12
|
+
# @return [void]
|
|
13
|
+
def visit
|
|
14
|
+
# `@document` may be any kind of node:
|
|
15
|
+
visit_method = @document.visit_method
|
|
16
|
+
result = public_send(visit_method, @document, nil)
|
|
17
|
+
@result = if result.is_a?(Array)
|
|
18
|
+
result.first
|
|
19
|
+
else
|
|
20
|
+
# The node wasn't modified
|
|
21
|
+
@document
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def on_document_children(document_node)
|
|
26
|
+
document_node.children.each do |child_node|
|
|
27
|
+
visit_method = child_node.visit_method
|
|
28
|
+
public_send(visit_method, child_node, document_node)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def on_field_children(new_node)
|
|
33
|
+
new_node.arguments.each do |arg_node| # rubocop:disable Development/ContextIsPassedCop
|
|
34
|
+
on_argument(arg_node, new_node)
|
|
35
|
+
end
|
|
36
|
+
visit_directives(new_node)
|
|
37
|
+
visit_selections(new_node)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def visit_directives(new_node)
|
|
41
|
+
new_node.directives.each do |dir_node|
|
|
42
|
+
on_directive(dir_node, new_node)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def visit_selections(new_node)
|
|
47
|
+
new_node.selections.each do |selection|
|
|
48
|
+
case selection
|
|
49
|
+
when GraphQL::Language::Nodes::Field
|
|
50
|
+
on_field(selection, new_node)
|
|
51
|
+
when GraphQL::Language::Nodes::InlineFragment
|
|
52
|
+
on_inline_fragment(selection, new_node)
|
|
53
|
+
when GraphQL::Language::Nodes::FragmentSpread
|
|
54
|
+
on_fragment_spread(selection, new_node)
|
|
55
|
+
else
|
|
56
|
+
raise ArgumentError, "Invariant: unexpected field selection #{selection.class} (#{selection.inspect})"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def on_fragment_definition_children(new_node)
|
|
62
|
+
visit_directives(new_node)
|
|
63
|
+
visit_selections(new_node)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
alias :on_inline_fragment_children :on_fragment_definition_children
|
|
67
|
+
|
|
68
|
+
def on_operation_definition_children(new_node)
|
|
69
|
+
new_node.variables.each do |arg_node|
|
|
70
|
+
on_variable_definition(arg_node, new_node)
|
|
71
|
+
end
|
|
72
|
+
visit_directives(new_node)
|
|
73
|
+
visit_selections(new_node)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def on_argument_children(new_node)
|
|
77
|
+
new_node.children.each do |value_node|
|
|
78
|
+
case value_node
|
|
79
|
+
when Language::Nodes::VariableIdentifier
|
|
80
|
+
on_variable_identifier(value_node, new_node)
|
|
81
|
+
when Language::Nodes::InputObject
|
|
82
|
+
on_input_object(value_node, new_node)
|
|
83
|
+
when Language::Nodes::Enum
|
|
84
|
+
on_enum(value_node, new_node)
|
|
85
|
+
when Language::Nodes::NullValue
|
|
86
|
+
on_null_value(value_node, new_node)
|
|
87
|
+
else
|
|
88
|
+
raise ArgumentError, "Invariant: unexpected argument value node #{value_node.class} (#{value_node.inspect})"
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
|
94
|
+
|
|
95
|
+
# We don't use `alias` here because it breaks `super`
|
|
96
|
+
def self.make_visit_methods(ast_node_class)
|
|
97
|
+
node_method = ast_node_class.visit_method
|
|
98
|
+
children_of_type = ast_node_class.children_of_type
|
|
99
|
+
child_visit_method = :"#{node_method}_children"
|
|
100
|
+
|
|
101
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
102
|
+
# The default implementation for visiting an AST node.
|
|
103
|
+
# It doesn't _do_ anything, but it continues to visiting the node's children.
|
|
104
|
+
# To customize this hook, override one of its make_visit_methods (or the base method?)
|
|
105
|
+
# in your subclasses.
|
|
106
|
+
#
|
|
107
|
+
# @param node [GraphQL::Language::Nodes::AbstractNode] the node being visited
|
|
108
|
+
# @param parent [GraphQL::Language::Nodes::AbstractNode, nil] the previously-visited node, or `nil` if this is the root node.
|
|
109
|
+
# @return [void]
|
|
110
|
+
def #{node_method}(node, parent)
|
|
111
|
+
#{
|
|
112
|
+
if method_defined?(child_visit_method)
|
|
113
|
+
"#{child_visit_method}(node)"
|
|
114
|
+
elsif children_of_type
|
|
115
|
+
children_of_type.map do |child_accessor, child_class|
|
|
116
|
+
"node.#{child_accessor}.each do |child_node|
|
|
117
|
+
#{child_class.visit_method}(child_node, node)
|
|
118
|
+
end"
|
|
119
|
+
end.join("\n")
|
|
120
|
+
else
|
|
121
|
+
""
|
|
122
|
+
end
|
|
123
|
+
}
|
|
124
|
+
end
|
|
125
|
+
RUBY
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
[
|
|
129
|
+
Language::Nodes::Argument,
|
|
130
|
+
Language::Nodes::Directive,
|
|
131
|
+
Language::Nodes::DirectiveDefinition,
|
|
132
|
+
Language::Nodes::DirectiveLocation,
|
|
133
|
+
Language::Nodes::Document,
|
|
134
|
+
Language::Nodes::Enum,
|
|
135
|
+
Language::Nodes::EnumTypeDefinition,
|
|
136
|
+
Language::Nodes::EnumTypeExtension,
|
|
137
|
+
Language::Nodes::EnumValueDefinition,
|
|
138
|
+
Language::Nodes::Field,
|
|
139
|
+
Language::Nodes::FieldDefinition,
|
|
140
|
+
Language::Nodes::FragmentDefinition,
|
|
141
|
+
Language::Nodes::FragmentSpread,
|
|
142
|
+
Language::Nodes::InlineFragment,
|
|
143
|
+
Language::Nodes::InputObject,
|
|
144
|
+
Language::Nodes::InputObjectTypeDefinition,
|
|
145
|
+
Language::Nodes::InputObjectTypeExtension,
|
|
146
|
+
Language::Nodes::InputValueDefinition,
|
|
147
|
+
Language::Nodes::InterfaceTypeDefinition,
|
|
148
|
+
Language::Nodes::InterfaceTypeExtension,
|
|
149
|
+
Language::Nodes::ListType,
|
|
150
|
+
Language::Nodes::NonNullType,
|
|
151
|
+
Language::Nodes::NullValue,
|
|
152
|
+
Language::Nodes::ObjectTypeDefinition,
|
|
153
|
+
Language::Nodes::ObjectTypeExtension,
|
|
154
|
+
Language::Nodes::OperationDefinition,
|
|
155
|
+
Language::Nodes::ScalarTypeDefinition,
|
|
156
|
+
Language::Nodes::ScalarTypeExtension,
|
|
157
|
+
Language::Nodes::SchemaDefinition,
|
|
158
|
+
Language::Nodes::SchemaExtension,
|
|
159
|
+
Language::Nodes::TypeName,
|
|
160
|
+
Language::Nodes::UnionTypeDefinition,
|
|
161
|
+
Language::Nodes::UnionTypeExtension,
|
|
162
|
+
Language::Nodes::VariableDefinition,
|
|
163
|
+
Language::Nodes::VariableIdentifier,
|
|
164
|
+
].each do |ast_node_class|
|
|
165
|
+
make_visit_methods(ast_node_class)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# rubocop:disable Development/NoEvalCop
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
@@ -30,12 +30,9 @@ module GraphQL
|
|
|
30
30
|
# # Check the result
|
|
31
31
|
# visitor.count
|
|
32
32
|
# # => 3
|
|
33
|
+
#
|
|
34
|
+
# @see GraphQL::Language::StaticVisitor for a faster visitor that doesn't support modifying the document
|
|
33
35
|
class Visitor
|
|
34
|
-
# If any hook returns this value, the {Visitor} stops visiting this
|
|
35
|
-
# node right away
|
|
36
|
-
# @deprecated Use `super` to continue the visit; or don't call it to halt.
|
|
37
|
-
SKIP = :_skip
|
|
38
|
-
|
|
39
36
|
class DeleteNode; end
|
|
40
37
|
|
|
41
38
|
# When this is returned from a visitor method,
|
|
@@ -44,25 +41,13 @@ module GraphQL
|
|
|
44
41
|
|
|
45
42
|
def initialize(document)
|
|
46
43
|
@document = document
|
|
47
|
-
@visitors = {}
|
|
48
44
|
@result = nil
|
|
49
45
|
end
|
|
50
46
|
|
|
51
47
|
# @return [GraphQL::Language::Nodes::Document] The document with any modifications applied
|
|
52
48
|
attr_reader :result
|
|
53
49
|
|
|
54
|
-
#
|
|
55
|
-
# @param node_class [Class] The node class that you want to listen to
|
|
56
|
-
# @return [NodeVisitor]
|
|
57
|
-
#
|
|
58
|
-
# @example Run a hook whenever you enter a new Field
|
|
59
|
-
# visitor[GraphQL::Language::Nodes::Field] << ->(node, parent) { p "Here's a field" }
|
|
60
|
-
# @deprecated see `on_` methods, like {#on_field}
|
|
61
|
-
def [](node_class)
|
|
62
|
-
@visitors[node_class] ||= NodeVisitor.new
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# Visit `document` and all children, applying hooks as you go
|
|
50
|
+
# Visit `document` and all children
|
|
66
51
|
# @return [void]
|
|
67
52
|
def visit
|
|
68
53
|
# `@document` may be any kind of node:
|
|
@@ -76,67 +61,6 @@ module GraphQL
|
|
|
76
61
|
end
|
|
77
62
|
end
|
|
78
63
|
|
|
79
|
-
# We don't use `alias` here because it breaks `super`
|
|
80
|
-
def self.make_visit_methods(ast_node_class)
|
|
81
|
-
node_method = ast_node_class.visit_method
|
|
82
|
-
children_of_type = ast_node_class.children_of_type
|
|
83
|
-
child_visit_method = :"#{node_method}_children"
|
|
84
|
-
|
|
85
|
-
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
86
|
-
# The default implementation for visiting an AST node.
|
|
87
|
-
# It doesn't _do_ anything, but it continues to visiting the node's children.
|
|
88
|
-
# To customize this hook, override one of its make_visit_methods (or the base method?)
|
|
89
|
-
# in your subclasses.
|
|
90
|
-
#
|
|
91
|
-
# For compatibility, it calls hook procs, too.
|
|
92
|
-
# @param node [GraphQL::Language::Nodes::AbstractNode] the node being visited
|
|
93
|
-
# @param parent [GraphQL::Language::Nodes::AbstractNode, nil] the previously-visited node, or `nil` if this is the root node.
|
|
94
|
-
# @return [Array, nil] If there were modifications, it returns an array of new nodes, otherwise, it returns `nil`.
|
|
95
|
-
def #{node_method}(node, parent)
|
|
96
|
-
if node.equal?(DELETE_NODE)
|
|
97
|
-
# This might be passed to `super(DELETE_NODE, ...)`
|
|
98
|
-
# by a user hook, don't want to keep visiting in that case.
|
|
99
|
-
[node, parent]
|
|
100
|
-
else
|
|
101
|
-
# Run hooks if there are any
|
|
102
|
-
new_node = node
|
|
103
|
-
no_hooks = !@visitors.key?(node.class)
|
|
104
|
-
if no_hooks || begin_visit(new_node, parent)
|
|
105
|
-
#{
|
|
106
|
-
if method_defined?(child_visit_method)
|
|
107
|
-
"new_node = #{child_visit_method}(new_node)"
|
|
108
|
-
elsif children_of_type
|
|
109
|
-
children_of_type.map do |child_accessor, child_class|
|
|
110
|
-
"node.#{child_accessor}.each do |child_node|
|
|
111
|
-
new_child_and_node = #{child_class.visit_method}_with_modifications(child_node, new_node)
|
|
112
|
-
# Reassign `node` in case the child hook makes a modification
|
|
113
|
-
if new_child_and_node.is_a?(Array)
|
|
114
|
-
new_node = new_child_and_node[1]
|
|
115
|
-
end
|
|
116
|
-
end"
|
|
117
|
-
end.join("\n")
|
|
118
|
-
else
|
|
119
|
-
""
|
|
120
|
-
end
|
|
121
|
-
}
|
|
122
|
-
end
|
|
123
|
-
end_visit(new_node, parent) unless no_hooks
|
|
124
|
-
|
|
125
|
-
if new_node.equal?(node)
|
|
126
|
-
[node, parent]
|
|
127
|
-
else
|
|
128
|
-
[new_node, parent]
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
def #{node_method}_with_modifications(node, parent)
|
|
134
|
-
new_node_and_new_parent = #{node_method}(node, parent)
|
|
135
|
-
apply_modifications(node, parent, new_node_and_new_parent)
|
|
136
|
-
end
|
|
137
|
-
RUBY
|
|
138
|
-
end
|
|
139
|
-
|
|
140
64
|
def on_document_children(document_node)
|
|
141
65
|
new_node = document_node
|
|
142
66
|
document_node.children.each do |child_node|
|
|
@@ -237,6 +161,63 @@ module GraphQL
|
|
|
237
161
|
new_node
|
|
238
162
|
end
|
|
239
163
|
|
|
164
|
+
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
|
165
|
+
|
|
166
|
+
# We don't use `alias` here because it breaks `super`
|
|
167
|
+
def self.make_visit_methods(ast_node_class)
|
|
168
|
+
node_method = ast_node_class.visit_method
|
|
169
|
+
children_of_type = ast_node_class.children_of_type
|
|
170
|
+
child_visit_method = :"#{node_method}_children"
|
|
171
|
+
|
|
172
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
173
|
+
# The default implementation for visiting an AST node.
|
|
174
|
+
# It doesn't _do_ anything, but it continues to visiting the node's children.
|
|
175
|
+
# To customize this hook, override one of its make_visit_methods (or the base method?)
|
|
176
|
+
# in your subclasses.
|
|
177
|
+
#
|
|
178
|
+
# @param node [GraphQL::Language::Nodes::AbstractNode] the node being visited
|
|
179
|
+
# @param parent [GraphQL::Language::Nodes::AbstractNode, nil] the previously-visited node, or `nil` if this is the root node.
|
|
180
|
+
# @return [Array, nil] If there were modifications, it returns an array of new nodes, otherwise, it returns `nil`.
|
|
181
|
+
def #{node_method}(node, parent)
|
|
182
|
+
if node.equal?(DELETE_NODE)
|
|
183
|
+
# This might be passed to `super(DELETE_NODE, ...)`
|
|
184
|
+
# by a user hook, don't want to keep visiting in that case.
|
|
185
|
+
[node, parent]
|
|
186
|
+
else
|
|
187
|
+
new_node = node
|
|
188
|
+
#{
|
|
189
|
+
if method_defined?(child_visit_method)
|
|
190
|
+
"new_node = #{child_visit_method}(new_node)"
|
|
191
|
+
elsif children_of_type
|
|
192
|
+
children_of_type.map do |child_accessor, child_class|
|
|
193
|
+
"node.#{child_accessor}.each do |child_node|
|
|
194
|
+
new_child_and_node = #{child_class.visit_method}_with_modifications(child_node, new_node)
|
|
195
|
+
# Reassign `node` in case the child hook makes a modification
|
|
196
|
+
if new_child_and_node.is_a?(Array)
|
|
197
|
+
new_node = new_child_and_node[1]
|
|
198
|
+
end
|
|
199
|
+
end"
|
|
200
|
+
end.join("\n")
|
|
201
|
+
else
|
|
202
|
+
""
|
|
203
|
+
end
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if new_node.equal?(node)
|
|
207
|
+
[node, parent]
|
|
208
|
+
else
|
|
209
|
+
[new_node, parent]
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def #{node_method}_with_modifications(node, parent)
|
|
215
|
+
new_node_and_new_parent = #{node_method}(node, parent)
|
|
216
|
+
apply_modifications(node, parent, new_node_and_new_parent)
|
|
217
|
+
end
|
|
218
|
+
RUBY
|
|
219
|
+
end
|
|
220
|
+
|
|
240
221
|
[
|
|
241
222
|
Language::Nodes::Argument,
|
|
242
223
|
Language::Nodes::Directive,
|
|
@@ -277,6 +258,8 @@ module GraphQL
|
|
|
277
258
|
make_visit_methods(ast_node_class)
|
|
278
259
|
end
|
|
279
260
|
|
|
261
|
+
# rubocop:enable Development/NoEvalCop
|
|
262
|
+
|
|
280
263
|
private
|
|
281
264
|
|
|
282
265
|
def apply_modifications(node, parent, new_node_and_new_parent)
|
|
@@ -305,46 +288,6 @@ module GraphQL
|
|
|
305
288
|
new_node_and_new_parent
|
|
306
289
|
end
|
|
307
290
|
end
|
|
308
|
-
|
|
309
|
-
def begin_visit(node, parent)
|
|
310
|
-
node_visitor = self[node.class]
|
|
311
|
-
self.class.apply_hooks(node_visitor.enter, node, parent)
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
# Should global `leave` visitors come first or last?
|
|
315
|
-
def end_visit(node, parent)
|
|
316
|
-
node_visitor = self[node.class]
|
|
317
|
-
self.class.apply_hooks(node_visitor.leave, node, parent)
|
|
318
|
-
end
|
|
319
|
-
|
|
320
|
-
# If one of the visitors returns SKIP, stop visiting this node
|
|
321
|
-
def self.apply_hooks(hooks, node, parent)
|
|
322
|
-
hooks.each do |proc|
|
|
323
|
-
return false if proc.call(node, parent) == SKIP
|
|
324
|
-
end
|
|
325
|
-
true
|
|
326
|
-
end
|
|
327
|
-
|
|
328
|
-
# Collect `enter` and `leave` hooks for classes in {GraphQL::Language::Nodes}
|
|
329
|
-
#
|
|
330
|
-
# Access {NodeVisitor}s via {GraphQL::Language::Visitor#[]}
|
|
331
|
-
class NodeVisitor
|
|
332
|
-
# @return [Array<Proc>] Hooks to call when entering a node of this type
|
|
333
|
-
attr_reader :enter
|
|
334
|
-
# @return [Array<Proc>] Hooks to call when leaving a node of this type
|
|
335
|
-
attr_reader :leave
|
|
336
|
-
|
|
337
|
-
def initialize
|
|
338
|
-
@enter = []
|
|
339
|
-
@leave = []
|
|
340
|
-
end
|
|
341
|
-
|
|
342
|
-
# Shorthand to add a hook to the {#enter} array
|
|
343
|
-
# @param hook [Proc] A hook to add
|
|
344
|
-
def <<(hook)
|
|
345
|
-
enter << hook
|
|
346
|
-
end
|
|
347
|
-
end
|
|
348
291
|
end
|
|
349
292
|
end
|
|
350
293
|
end
|
data/lib/graphql/language.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require "graphql/language/block_string"
|
|
3
|
+
require "graphql/language/comment"
|
|
3
4
|
require "graphql/language/printer"
|
|
4
5
|
require "graphql/language/sanitized_printer"
|
|
5
6
|
require "graphql/language/document_from_schema_definition"
|
|
@@ -8,9 +9,10 @@ require "graphql/language/lexer"
|
|
|
8
9
|
require "graphql/language/nodes"
|
|
9
10
|
require "graphql/language/cache"
|
|
10
11
|
require "graphql/language/parser"
|
|
11
|
-
require "graphql/language/
|
|
12
|
+
require "graphql/language/static_visitor"
|
|
12
13
|
require "graphql/language/visitor"
|
|
13
14
|
require "graphql/language/definition_slice"
|
|
15
|
+
require "strscan"
|
|
14
16
|
|
|
15
17
|
module GraphQL
|
|
16
18
|
module Language
|
|
@@ -31,6 +33,74 @@ module GraphQL
|
|
|
31
33
|
else
|
|
32
34
|
JSON.generate(value, quirks_mode: true)
|
|
33
35
|
end
|
|
36
|
+
rescue JSON::GeneratorError
|
|
37
|
+
if Float::INFINITY == value
|
|
38
|
+
"Infinity"
|
|
39
|
+
else
|
|
40
|
+
raise
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Returns a new string if any single-quoted newlines were escaped.
|
|
45
|
+
# Otherwise, returns `query_str` unchanged.
|
|
46
|
+
# @return [String]
|
|
47
|
+
def self.escape_single_quoted_newlines(query_str)
|
|
48
|
+
scanner = StringScanner.new(query_str)
|
|
49
|
+
inside_single_quoted_string = false
|
|
50
|
+
new_query_str = nil
|
|
51
|
+
while !scanner.eos?
|
|
52
|
+
if scanner.skip(/(?:\\"|[^"\n\r]|""")+/m)
|
|
53
|
+
new_query_str && (new_query_str << scanner.matched)
|
|
54
|
+
elsif scanner.skip('"')
|
|
55
|
+
new_query_str && (new_query_str << '"')
|
|
56
|
+
inside_single_quoted_string = !inside_single_quoted_string
|
|
57
|
+
elsif scanner.skip("\n")
|
|
58
|
+
if inside_single_quoted_string
|
|
59
|
+
new_query_str ||= query_str[0, scanner.pos - 1]
|
|
60
|
+
new_query_str << '\\n'
|
|
61
|
+
else
|
|
62
|
+
new_query_str && (new_query_str << "\n")
|
|
63
|
+
end
|
|
64
|
+
elsif scanner.skip("\r")
|
|
65
|
+
if inside_single_quoted_string
|
|
66
|
+
new_query_str ||= query_str[0, scanner.pos - 1]
|
|
67
|
+
new_query_str << '\\r'
|
|
68
|
+
else
|
|
69
|
+
new_query_str && (new_query_str << "\r")
|
|
70
|
+
end
|
|
71
|
+
elsif scanner.eos?
|
|
72
|
+
break
|
|
73
|
+
else
|
|
74
|
+
raise ArgumentError, "Unmatchable string scanner segment: #{scanner.rest.inspect}"
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
new_query_str || query_str
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
LEADING_REGEX = Regexp.union(" ", *Lexer::Punctuation.constants.map { |const| Lexer::Punctuation.const_get(const) })
|
|
81
|
+
|
|
82
|
+
# Optimized pattern using:
|
|
83
|
+
# - Possessive quantifiers (*+, ++) to prevent backtracking in number patterns
|
|
84
|
+
# - Atomic group (?>...) for IGNORE to prevent backtracking
|
|
85
|
+
# - Single unified number pattern instead of three alternatives
|
|
86
|
+
EFFICIENT_NUMBER_REGEXP = /-?(?:0|[1-9][0-9]*+)(?:\.[0-9]++)?(?:[eE][+-]?[0-9]++)?/
|
|
87
|
+
EFFICIENT_IGNORE_REGEXP = /(?>[, \r\n\t]+|\#[^\n]*$)*/
|
|
88
|
+
|
|
89
|
+
MAYBE_INVALID_NUMBER = /\d[_a-zA-Z]/
|
|
90
|
+
|
|
91
|
+
INVALID_NUMBER_FOLLOWED_BY_NAME_REGEXP = %r{
|
|
92
|
+
(?<leading>#{LEADING_REGEX})
|
|
93
|
+
(?<num>#{EFFICIENT_NUMBER_REGEXP})
|
|
94
|
+
(?<name>#{Lexer::IDENTIFIER_REGEXP})
|
|
95
|
+
#{EFFICIENT_IGNORE_REGEXP}
|
|
96
|
+
:
|
|
97
|
+
}x
|
|
98
|
+
|
|
99
|
+
def self.add_space_between_numbers_and_names(query_str)
|
|
100
|
+
# Fast check for digit followed by identifier char. If this doesn't match, skip the more expensive regexp entirely.
|
|
101
|
+
return query_str unless query_str.match?(MAYBE_INVALID_NUMBER)
|
|
102
|
+
return query_str unless query_str.match?(INVALID_NUMBER_FOLLOWED_BY_NAME_REGEXP)
|
|
103
|
+
query_str.gsub(INVALID_NUMBER_FOLLOWED_BY_NAME_REGEXP, "\\k<leading>\\k<num> \\k<name>:")
|
|
34
104
|
end
|
|
35
105
|
end
|
|
36
106
|
end
|
|
@@ -12,10 +12,14 @@ module GraphQL
|
|
|
12
12
|
attr_reader :id
|
|
13
13
|
# @return [Object] The value found with this ID
|
|
14
14
|
attr_reader :object
|
|
15
|
-
|
|
15
|
+
# @return [GraphQL::Query::Context]
|
|
16
|
+
attr_reader :context
|
|
17
|
+
|
|
18
|
+
def initialize(argument:, id:, object:, context:)
|
|
16
19
|
@id = id
|
|
17
20
|
@argument = argument
|
|
18
21
|
@object = object
|
|
22
|
+
@context = context
|
|
19
23
|
super("No object found for `#{argument.graphql_name}: #{id.inspect}`")
|
|
20
24
|
end
|
|
21
25
|
end
|
|
@@ -35,10 +35,10 @@ module GraphQL
|
|
|
35
35
|
def load_nodes
|
|
36
36
|
@nodes ||= begin
|
|
37
37
|
sliced_nodes = if before && after
|
|
38
|
-
end_idx = index_from_cursor(before)-
|
|
38
|
+
end_idx = index_from_cursor(before) - 2
|
|
39
39
|
end_idx < 0 ? [] : items[index_from_cursor(after)..end_idx] || []
|
|
40
40
|
elsif before
|
|
41
|
-
end_idx = index_from_cursor(before)-2
|
|
41
|
+
end_idx = index_from_cursor(before) - 2
|
|
42
42
|
end_idx < 0 ? [] : items[0..end_idx] || []
|
|
43
43
|
elsif after
|
|
44
44
|
items[index_from_cursor(after)..-1] || []
|
|
@@ -56,12 +56,12 @@ module GraphQL
|
|
|
56
56
|
false
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
-
@has_next_page = if
|
|
60
|
-
# There are more items after these items
|
|
61
|
-
sliced_nodes.count > first
|
|
62
|
-
elsif before
|
|
59
|
+
@has_next_page = if before
|
|
63
60
|
# The original array is longer than the `before` index
|
|
64
61
|
index_from_cursor(before) < items.length + 1
|
|
62
|
+
elsif first
|
|
63
|
+
# There are more items after these items
|
|
64
|
+
sliced_nodes.count > first
|
|
65
65
|
else
|
|
66
66
|
false
|
|
67
67
|
end
|