graphql 2.2.17 → 2.5.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/generators/graphql/install/mutation_root_generator.rb +2 -2
- data/lib/generators/graphql/install_generator.rb +46 -0
- data/lib/generators/graphql/orm_mutations_base.rb +1 -1
- data/lib/generators/graphql/templates/base_resolver.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +3 -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/{ast/query_depth.rb → query_depth.rb} +23 -25
- data/lib/graphql/analysis/visitor.rb +280 -0
- data/lib/graphql/analysis.rb +95 -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/current.rb +57 -0
- data/lib/graphql/dashboard/detailed_traces.rb +47 -0
- data/lib/graphql/dashboard/installable.rb +22 -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/subscriptions.rb +96 -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 +23 -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 +158 -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 +46 -19
- data/lib/graphql/dataloader/null_dataloader.rb +51 -10
- data/lib/graphql/dataloader/source.rb +20 -9
- data/lib/graphql/dataloader.rb +153 -45
- data/lib/graphql/date_encoding_error.rb +1 -1
- data/lib/graphql/dig.rb +2 -1
- 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/resolve.rb +23 -25
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +63 -5
- data/lib/graphql/execution/interpreter/runtime.rb +321 -222
- data/lib/graphql/execution/interpreter.rb +23 -30
- data/lib/graphql/execution/lookahead.rb +18 -11
- data/lib/graphql/execution/multiplex.rb +6 -5
- data/lib/graphql/introspection/directive_location_enum.rb +1 -1
- data/lib/graphql/introspection/directive_type.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +6 -11
- data/lib/graphql/introspection/type_type.rb +5 -5
- data/lib/graphql/invalid_name_error.rb +1 -1
- data/lib/graphql/invalid_null_error.rb +20 -17
- data/lib/graphql/language/cache.rb +13 -0
- data/lib/graphql/language/comment.rb +18 -0
- data/lib/graphql/language/document_from_schema_definition.rb +64 -35
- data/lib/graphql/language/lexer.rb +72 -42
- data/lib/graphql/language/nodes.rb +93 -52
- data/lib/graphql/language/parser.rb +168 -61
- data/lib/graphql/language/printer.rb +31 -15
- data/lib/graphql/language/sanitized_printer.rb +1 -1
- data/lib/graphql/language.rb +61 -1
- data/lib/graphql/pagination/connection.rb +1 -1
- data/lib/graphql/query/context/scoped_context.rb +1 -1
- data/lib/graphql/query/context.rb +46 -47
- data/lib/graphql/query/null_context.rb +3 -5
- data/lib/graphql/query/partial.rb +179 -0
- data/lib/graphql/query/validation_pipeline.rb +2 -2
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query.rb +123 -69
- data/lib/graphql/railtie.rb +7 -0
- 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/schema/addition.rb +26 -13
- data/lib/graphql/schema/always_visible.rb +7 -2
- data/lib/graphql/schema/argument.rb +57 -8
- data/lib/graphql/schema/build_from_definition.rb +116 -49
- data/lib/graphql/schema/directive/flagged.rb +4 -2
- data/lib/graphql/schema/directive.rb +54 -2
- data/lib/graphql/schema/enum.rb +107 -24
- data/lib/graphql/schema/enum_value.rb +10 -2
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +134 -45
- data/lib/graphql/schema/field_extension.rb +1 -1
- data/lib/graphql/schema/has_single_input_argument.rb +6 -2
- data/lib/graphql/schema/input_object.rb +122 -64
- data/lib/graphql/schema/interface.rb +23 -5
- data/lib/graphql/schema/introspection_system.rb +6 -17
- data/lib/graphql/schema/late_bound_type.rb +4 -0
- data/lib/graphql/schema/list.rb +3 -3
- data/lib/graphql/schema/loader.rb +3 -2
- data/lib/graphql/schema/member/base_dsl_methods.rb +15 -0
- data/lib/graphql/schema/member/has_arguments.rb +44 -58
- data/lib/graphql/schema/member/has_dataloader.rb +62 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +15 -0
- data/lib/graphql/schema/member/has_directives.rb +4 -4
- data/lib/graphql/schema/member/has_fields.rb +26 -6
- data/lib/graphql/schema/member/has_interfaces.rb +6 -6
- 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/type_system_helpers.rb +17 -4
- data/lib/graphql/schema/member.rb +1 -0
- data/lib/graphql/schema/mutation.rb +7 -0
- data/lib/graphql/schema/object.rb +25 -8
- data/lib/graphql/schema/printer.rb +1 -0
- data/lib/graphql/schema/ractor_shareable.rb +79 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +0 -1
- data/lib/graphql/schema/resolver.rb +29 -23
- data/lib/graphql/schema/scalar.rb +1 -6
- data/lib/graphql/schema/subscription.rb +52 -6
- data/lib/graphql/schema/timeout.rb +19 -2
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/union.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 +445 -0
- data/lib/graphql/schema/visibility/visit.rb +190 -0
- data/lib/graphql/schema/visibility.rb +311 -0
- data/lib/graphql/schema/warden.rb +190 -20
- data/lib/graphql/schema.rb +695 -167
- data/lib/graphql/static_validation/all_rules.rb +2 -2
- data/lib/graphql/static_validation/base_visitor.rb +6 -5
- data/lib/graphql/static_validation/literal_validator.rb +4 -4
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +3 -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 +12 -2
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +47 -13
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +88 -25
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +10 -2
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +12 -2
- data/lib/graphql/static_validation/rules/fragments_are_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 +4 -4
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +3 -3
- 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 +11 -2
- data/lib/graphql/static_validation/validation_context.rb +18 -2
- data/lib/graphql/static_validation/validator.rb +6 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +5 -3
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +12 -10
- data/lib/graphql/subscriptions/event.rb +13 -2
- data/lib/graphql/subscriptions/serialize.rb +1 -1
- data/lib/graphql/subscriptions.rb +7 -5
- data/lib/graphql/testing/helpers.rb +48 -16
- data/lib/graphql/testing/mock_action_cable.rb +111 -0
- data/lib/graphql/testing.rb +1 -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 +5 -1
- data/lib/graphql/tracing/appoptics_tracing.rb +7 -0
- data/lib/graphql/tracing/appsignal_trace.rb +32 -59
- 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 -162
- data/lib/graphql/tracing/data_dog_tracing.rb +2 -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 +141 -0
- data/lib/graphql/tracing/legacy_hooks_trace.rb +1 -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 +183 -37
- 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 +818 -0
- data/lib/graphql/tracing/platform_tracing.rb +1 -1
- data/lib/graphql/tracing/prometheus_trace/graphql_collector.rb +2 -0
- data/lib/graphql/tracing/prometheus_trace.rb +73 -73
- data/lib/graphql/tracing/prometheus_tracing.rb +2 -0
- data/lib/graphql/tracing/scout_trace.rb +32 -58
- data/lib/graphql/tracing/scout_tracing.rb +2 -0
- data/lib/graphql/tracing/sentry_trace.rb +64 -98
- data/lib/graphql/tracing/statsd_trace.rb +33 -45
- data/lib/graphql/tracing/statsd_tracing.rb +2 -0
- data/lib/graphql/tracing/trace.rb +111 -1
- data/lib/graphql/tracing.rb +31 -30
- data/lib/graphql/type_kinds.rb +2 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +12 -2
- data/lib/graphql/types/relay/edge_behaviors.rb +11 -1
- data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
- data/lib/graphql/types.rb +18 -11
- data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +64 -54
- metadata +197 -22
- data/lib/graphql/analysis/ast/analyzer.rb +0 -91
- data/lib/graphql/analysis/ast/field_usage.rb +0 -82
- 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 -182
- data/lib/graphql/analysis/ast/visitor.rb +0 -276
- data/lib/graphql/analysis/ast.rb +0 -94
- data/lib/graphql/backtrace/inspect_result.rb +0 -50
- data/lib/graphql/backtrace/trace.rb +0 -93
- data/lib/graphql/backtrace/tracer.rb +0 -80
- data/lib/graphql/language/token.rb +0 -34
- 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
|
@@ -18,21 +18,15 @@ module GraphQL
|
|
|
18
18
|
include_built_in_directives: false, include_built_in_scalars: false, always_include_schema: false
|
|
19
19
|
)
|
|
20
20
|
@schema = schema
|
|
21
|
+
@context = context
|
|
21
22
|
@always_include_schema = always_include_schema
|
|
22
23
|
@include_introspection_types = include_introspection_types
|
|
23
24
|
@include_built_in_scalars = include_built_in_scalars
|
|
24
25
|
@include_built_in_directives = include_built_in_directives
|
|
25
26
|
@include_one_of = false
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@warden = @schema.warden_class.new(
|
|
31
|
-
schema: @schema,
|
|
32
|
-
context: schema_context,
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
schema_context.warden = @warden
|
|
28
|
+
dummy_query = @schema.query_class.new(@schema, "{ __typename }", validate: false, context: context)
|
|
29
|
+
@types = dummy_query.types # rubocop:disable Development/ContextIsPassedCop
|
|
36
30
|
end
|
|
37
31
|
|
|
38
32
|
def document
|
|
@@ -44,9 +38,9 @@ module GraphQL
|
|
|
44
38
|
def build_schema_node
|
|
45
39
|
if !schema_respects_root_name_conventions?(@schema)
|
|
46
40
|
GraphQL::Language::Nodes::SchemaDefinition.new(
|
|
47
|
-
query:
|
|
48
|
-
mutation:
|
|
49
|
-
subscription:
|
|
41
|
+
query: @types.query_root&.graphql_name,
|
|
42
|
+
mutation: @types.mutation_root&.graphql_name,
|
|
43
|
+
subscription: @types.subscription_root&.graphql_name,
|
|
50
44
|
directives: definition_directives(@schema, :schema_directives)
|
|
51
45
|
)
|
|
52
46
|
else
|
|
@@ -57,16 +51,18 @@ module GraphQL
|
|
|
57
51
|
end
|
|
58
52
|
|
|
59
53
|
def build_object_type_node(object_type)
|
|
60
|
-
ints =
|
|
61
|
-
|
|
62
|
-
|
|
54
|
+
ints = @types.interfaces(object_type)
|
|
55
|
+
|
|
56
|
+
if !ints.empty?
|
|
57
|
+
ints = ints.sort_by(&:graphql_name)
|
|
63
58
|
ints.map! { |iface| build_type_name_node(iface) }
|
|
64
59
|
end
|
|
65
60
|
|
|
66
61
|
GraphQL::Language::Nodes::ObjectTypeDefinition.new(
|
|
67
62
|
name: object_type.graphql_name,
|
|
63
|
+
comment: object_type.comment,
|
|
68
64
|
interfaces: ints,
|
|
69
|
-
fields: build_field_nodes(
|
|
65
|
+
fields: build_field_nodes(@types.fields(object_type)),
|
|
70
66
|
description: object_type.description,
|
|
71
67
|
directives: directives(object_type),
|
|
72
68
|
)
|
|
@@ -75,7 +71,8 @@ module GraphQL
|
|
|
75
71
|
def build_field_node(field)
|
|
76
72
|
GraphQL::Language::Nodes::FieldDefinition.new(
|
|
77
73
|
name: field.graphql_name,
|
|
78
|
-
|
|
74
|
+
comment: field.comment,
|
|
75
|
+
arguments: build_argument_nodes(@types.arguments(field)),
|
|
79
76
|
type: build_type_name_node(field.type),
|
|
80
77
|
description: field.description,
|
|
81
78
|
directives: directives(field),
|
|
@@ -85,8 +82,9 @@ module GraphQL
|
|
|
85
82
|
def build_union_type_node(union_type)
|
|
86
83
|
GraphQL::Language::Nodes::UnionTypeDefinition.new(
|
|
87
84
|
name: union_type.graphql_name,
|
|
85
|
+
comment: union_type.comment,
|
|
88
86
|
description: union_type.description,
|
|
89
|
-
types:
|
|
87
|
+
types: @types.possible_types(union_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
|
|
90
88
|
directives: directives(union_type),
|
|
91
89
|
)
|
|
92
90
|
end
|
|
@@ -94,9 +92,10 @@ module GraphQL
|
|
|
94
92
|
def build_interface_type_node(interface_type)
|
|
95
93
|
GraphQL::Language::Nodes::InterfaceTypeDefinition.new(
|
|
96
94
|
name: interface_type.graphql_name,
|
|
97
|
-
|
|
95
|
+
comment: interface_type.comment,
|
|
96
|
+
interfaces: @types.interfaces(interface_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
|
|
98
97
|
description: interface_type.description,
|
|
99
|
-
fields: build_field_nodes(
|
|
98
|
+
fields: build_field_nodes(@types.fields(interface_type)),
|
|
100
99
|
directives: directives(interface_type),
|
|
101
100
|
)
|
|
102
101
|
end
|
|
@@ -104,7 +103,8 @@ module GraphQL
|
|
|
104
103
|
def build_enum_type_node(enum_type)
|
|
105
104
|
GraphQL::Language::Nodes::EnumTypeDefinition.new(
|
|
106
105
|
name: enum_type.graphql_name,
|
|
107
|
-
|
|
106
|
+
comment: enum_type.comment,
|
|
107
|
+
values: @types.enum_values(enum_type).sort_by(&:graphql_name).map do |enum_value|
|
|
108
108
|
build_enum_value_node(enum_value)
|
|
109
109
|
end,
|
|
110
110
|
description: enum_type.description,
|
|
@@ -115,6 +115,7 @@ module GraphQL
|
|
|
115
115
|
def build_enum_value_node(enum_value)
|
|
116
116
|
GraphQL::Language::Nodes::EnumValueDefinition.new(
|
|
117
117
|
name: enum_value.graphql_name,
|
|
118
|
+
comment: enum_value.comment,
|
|
118
119
|
description: enum_value.description,
|
|
119
120
|
directives: directives(enum_value),
|
|
120
121
|
)
|
|
@@ -123,6 +124,7 @@ module GraphQL
|
|
|
123
124
|
def build_scalar_type_node(scalar_type)
|
|
124
125
|
GraphQL::Language::Nodes::ScalarTypeDefinition.new(
|
|
125
126
|
name: scalar_type.graphql_name,
|
|
127
|
+
comment: scalar_type.comment,
|
|
126
128
|
description: scalar_type.description,
|
|
127
129
|
directives: directives(scalar_type),
|
|
128
130
|
)
|
|
@@ -137,6 +139,7 @@ module GraphQL
|
|
|
137
139
|
|
|
138
140
|
argument_node = GraphQL::Language::Nodes::InputValueDefinition.new(
|
|
139
141
|
name: argument.graphql_name,
|
|
142
|
+
comment: argument.comment,
|
|
140
143
|
description: argument.description,
|
|
141
144
|
type: build_type_name_node(argument.type),
|
|
142
145
|
default_value: default_value,
|
|
@@ -149,7 +152,8 @@ module GraphQL
|
|
|
149
152
|
def build_input_object_node(input_object)
|
|
150
153
|
GraphQL::Language::Nodes::InputObjectTypeDefinition.new(
|
|
151
154
|
name: input_object.graphql_name,
|
|
152
|
-
|
|
155
|
+
comment: input_object.comment,
|
|
156
|
+
fields: build_argument_nodes(@types.arguments(input_object)),
|
|
153
157
|
description: input_object.description,
|
|
154
158
|
directives: directives(input_object),
|
|
155
159
|
)
|
|
@@ -159,7 +163,7 @@ module GraphQL
|
|
|
159
163
|
GraphQL::Language::Nodes::DirectiveDefinition.new(
|
|
160
164
|
name: directive.graphql_name,
|
|
161
165
|
repeatable: directive.repeatable?,
|
|
162
|
-
arguments: build_argument_nodes(
|
|
166
|
+
arguments: build_argument_nodes(@types.arguments(directive)),
|
|
163
167
|
locations: build_directive_location_nodes(directive.locations),
|
|
164
168
|
description: directive.description,
|
|
165
169
|
)
|
|
@@ -204,7 +208,7 @@ module GraphQL
|
|
|
204
208
|
when "INPUT_OBJECT"
|
|
205
209
|
GraphQL::Language::Nodes::InputObject.new(
|
|
206
210
|
arguments: default_value.to_h.map do |arg_name, arg_value|
|
|
207
|
-
args = @
|
|
211
|
+
args = @types.arguments(type)
|
|
208
212
|
arg = args.find { |a| a.keyword.to_s == arg_name.to_s }
|
|
209
213
|
if arg.nil?
|
|
210
214
|
raise ArgumentError, "No argument definition on #{type.graphql_name} for argument: #{arg_name.inspect} (expected one of: #{args.map(&:keyword)})"
|
|
@@ -244,7 +248,7 @@ module GraphQL
|
|
|
244
248
|
end
|
|
245
249
|
|
|
246
250
|
def build_argument_nodes(arguments)
|
|
247
|
-
if arguments.
|
|
251
|
+
if !arguments.empty?
|
|
248
252
|
nodes = arguments.map { |arg| build_argument_node(arg) }
|
|
249
253
|
nodes.sort_by!(&:name)
|
|
250
254
|
nodes
|
|
@@ -260,13 +264,39 @@ module GraphQL
|
|
|
260
264
|
end
|
|
261
265
|
|
|
262
266
|
def build_definition_nodes
|
|
263
|
-
dirs_to_build =
|
|
267
|
+
dirs_to_build = @types.directives
|
|
264
268
|
if !include_built_in_directives
|
|
265
269
|
dirs_to_build = dirs_to_build.reject { |directive| directive.default_directive? }
|
|
266
270
|
end
|
|
267
271
|
definitions = build_directive_nodes(dirs_to_build)
|
|
272
|
+
all_types = @types.all_types
|
|
273
|
+
type_nodes = build_type_definition_nodes(all_types)
|
|
274
|
+
|
|
275
|
+
if !(ex_t = schema.extra_types).empty?
|
|
276
|
+
dummy_query = Class.new(GraphQL::Schema::Object) do
|
|
277
|
+
graphql_name "DummyQuery"
|
|
278
|
+
(all_types + ex_t).each_with_index do |type, idx|
|
|
279
|
+
if !type.kind.input_object? && !type.introspection?
|
|
280
|
+
field "f#{idx}", type
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
extra_types_schema = Class.new(GraphQL::Schema) do
|
|
286
|
+
query(dummy_query)
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
extra_types_types = GraphQL::Query.new(extra_types_schema, "{ __typename }", context: @context).types # rubocop:disable Development/ContextIsPassedCop
|
|
290
|
+
# Temporarily replace `@types` with something from this example schema.
|
|
291
|
+
# It'd be much nicer to pass this in, but that would be a big refactor :S
|
|
292
|
+
prev_types = @types
|
|
293
|
+
@types = extra_types_types
|
|
294
|
+
type_nodes += build_type_definition_nodes(ex_t)
|
|
295
|
+
@types = prev_types
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
type_nodes.sort_by!(&:name)
|
|
268
299
|
|
|
269
|
-
type_nodes = build_type_definition_nodes(warden.reachable_types + schema.extra_types)
|
|
270
300
|
if @include_one_of
|
|
271
301
|
# This may have been set to true when iterating over all types
|
|
272
302
|
definitions.concat(build_directive_nodes([GraphQL::Schema::Directive::OneOf]))
|
|
@@ -289,9 +319,7 @@ module GraphQL
|
|
|
289
319
|
types = types.reject { |type| type.kind.scalar? && type.default_scalar? }
|
|
290
320
|
end
|
|
291
321
|
|
|
292
|
-
types
|
|
293
|
-
.map { |type| build_type_definition_node(type) }
|
|
294
|
-
.sort_by(&:name)
|
|
322
|
+
types.map { |type| build_type_definition_node(type) }
|
|
295
323
|
end
|
|
296
324
|
|
|
297
325
|
def build_field_nodes(fields)
|
|
@@ -319,10 +347,11 @@ module GraphQL
|
|
|
319
347
|
end
|
|
320
348
|
|
|
321
349
|
def definition_directives(member, directives_method)
|
|
322
|
-
|
|
350
|
+
if !member.respond_to?(directives_method) || member.directives.empty?
|
|
323
351
|
EmptyObjects::EMPTY_ARRAY
|
|
324
352
|
else
|
|
325
|
-
member.public_send(directives_method).
|
|
353
|
+
visible_directives = member.public_send(directives_method).select { |dir| @types.directive_exists?(dir.graphql_name) }
|
|
354
|
+
visible_directives.map! do |dir|
|
|
326
355
|
args = []
|
|
327
356
|
dir.arguments.argument_values.each_value do |arg_value| # rubocop:disable Development/ContextIsPassedCop -- directive instance method
|
|
328
357
|
arg_defn = arg_value.definition
|
|
@@ -346,12 +375,12 @@ module GraphQL
|
|
|
346
375
|
arguments: args
|
|
347
376
|
)
|
|
348
377
|
end
|
|
349
|
-
end
|
|
350
378
|
|
|
351
|
-
|
|
379
|
+
visible_directives
|
|
380
|
+
end
|
|
352
381
|
end
|
|
353
382
|
|
|
354
|
-
attr_reader :schema, :
|
|
383
|
+
attr_reader :schema, :always_include_schema,
|
|
355
384
|
:include_introspection_types, :include_built_in_directives, :include_built_in_scalars
|
|
356
385
|
end
|
|
357
386
|
end
|
|
@@ -3,7 +3,7 @@ module GraphQL
|
|
|
3
3
|
module Language
|
|
4
4
|
|
|
5
5
|
class Lexer
|
|
6
|
-
def initialize(graphql_str, filename: nil)
|
|
6
|
+
def initialize(graphql_str, filename: nil, max_tokens: nil)
|
|
7
7
|
if !(graphql_str.encoding == Encoding::UTF_8 || graphql_str.ascii_only?)
|
|
8
8
|
graphql_str = graphql_str.dup.force_encoding(Encoding::UTF_8)
|
|
9
9
|
end
|
|
@@ -11,17 +11,32 @@ module GraphQL
|
|
|
11
11
|
@filename = filename
|
|
12
12
|
@scanner = StringScanner.new(graphql_str)
|
|
13
13
|
@pos = nil
|
|
14
|
+
@max_tokens = max_tokens || Float::INFINITY
|
|
15
|
+
@tokens_count = 0
|
|
16
|
+
@finished = false
|
|
14
17
|
end
|
|
15
18
|
|
|
16
|
-
def
|
|
17
|
-
@
|
|
19
|
+
def finished?
|
|
20
|
+
@finished
|
|
18
21
|
end
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
def freeze
|
|
24
|
+
@scanner = nil
|
|
25
|
+
super
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
attr_reader :pos, :tokens_count
|
|
21
29
|
|
|
22
30
|
def advance
|
|
23
31
|
@scanner.skip(IGNORE_REGEXP)
|
|
24
|
-
|
|
32
|
+
if @scanner.eos?
|
|
33
|
+
@finished = true
|
|
34
|
+
return false
|
|
35
|
+
end
|
|
36
|
+
@tokens_count += 1
|
|
37
|
+
if @tokens_count > @max_tokens
|
|
38
|
+
raise_parse_error("This query is too large to execute.")
|
|
39
|
+
end
|
|
25
40
|
@pos = @scanner.pos
|
|
26
41
|
next_byte = @string.getbyte(@pos)
|
|
27
42
|
next_byte_is_for = FIRST_BYTES[next_byte]
|
|
@@ -51,9 +66,26 @@ module GraphQL
|
|
|
51
66
|
@scanner.skip(IDENTIFIER_REGEXP)
|
|
52
67
|
:IDENTIFIER
|
|
53
68
|
when ByteFor::NUMBER
|
|
54
|
-
@scanner.skip(NUMERIC_REGEXP)
|
|
55
|
-
|
|
56
|
-
|
|
69
|
+
if len = @scanner.skip(NUMERIC_REGEXP)
|
|
70
|
+
|
|
71
|
+
if GraphQL.reject_numbers_followed_by_names
|
|
72
|
+
new_pos = @scanner.pos
|
|
73
|
+
peek_byte = @string.getbyte(new_pos)
|
|
74
|
+
next_first_byte = FIRST_BYTES[peek_byte]
|
|
75
|
+
if next_first_byte == ByteFor::NAME || next_first_byte == ByteFor::IDENTIFIER
|
|
76
|
+
number_part = token_value
|
|
77
|
+
name_part = @scanner.scan(IDENTIFIER_REGEXP)
|
|
78
|
+
raise_parse_error("Name after number is not allowed (in `#{number_part}#{name_part}`)")
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
# Check for a matched decimal:
|
|
82
|
+
@scanner[1] ? :FLOAT : :INT
|
|
83
|
+
else
|
|
84
|
+
# Attempt to find the part after the `-`
|
|
85
|
+
value = @scanner.scan(/-\s?[a-z0-9]*/i)
|
|
86
|
+
invalid_byte_for_number_error_message = "Expected type 'number', but it was malformed#{value.nil? ? "" : ": #{value.inspect}"}."
|
|
87
|
+
raise_parse_error(invalid_byte_for_number_error_message)
|
|
88
|
+
end
|
|
57
89
|
when ByteFor::ELLIPSIS
|
|
58
90
|
if @string.getbyte(@pos + 1) != 46 || @string.getbyte(@pos + 2) != 46
|
|
59
91
|
raise_parse_error("Expected `...`, actual: #{@string[@pos..@pos + 2].inspect}")
|
|
@@ -109,29 +141,27 @@ module GraphQL
|
|
|
109
141
|
}
|
|
110
142
|
UTF_8 = /\\u(?:([\dAa-f]{4})|\{([\da-f]{4,})\})(?:\\u([\dAa-f]{4}))?/i
|
|
111
143
|
VALID_STRING = /\A(?:[^\\]|#{ESCAPES}|#{UTF_8})*\z/o
|
|
144
|
+
ESCAPED = /(?:#{ESCAPES}|#{UTF_8})/o
|
|
112
145
|
|
|
113
146
|
def string_value
|
|
114
147
|
str = token_value
|
|
115
148
|
is_block = str.start_with?('"""')
|
|
116
149
|
if is_block
|
|
117
150
|
str.gsub!(/\A"""|"""\z/, '')
|
|
151
|
+
return Language::BlockString.trim_whitespace(str)
|
|
118
152
|
else
|
|
119
153
|
str.gsub!(/\A"|"\z/, '')
|
|
120
|
-
end
|
|
121
154
|
|
|
122
|
-
|
|
123
|
-
str = Language::BlockString.trim_whitespace(str)
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
if !str.valid_encoding? || !str.match?(VALID_STRING)
|
|
127
|
-
raise_parse_error("Bad unicode escape in #{str.inspect}")
|
|
128
|
-
else
|
|
129
|
-
Lexer.replace_escaped_characters_in_place(str)
|
|
130
|
-
|
|
131
|
-
if !str.valid_encoding?
|
|
155
|
+
if !str.valid_encoding? || !str.match?(VALID_STRING)
|
|
132
156
|
raise_parse_error("Bad unicode escape in #{str.inspect}")
|
|
133
157
|
else
|
|
134
|
-
str
|
|
158
|
+
Lexer.replace_escaped_characters_in_place(str)
|
|
159
|
+
|
|
160
|
+
if !str.valid_encoding?
|
|
161
|
+
raise_parse_error("Bad unicode escape in #{str.inspect}")
|
|
162
|
+
else
|
|
163
|
+
str
|
|
164
|
+
end
|
|
135
165
|
end
|
|
136
166
|
end
|
|
137
167
|
end
|
|
@@ -158,6 +188,7 @@ module GraphQL
|
|
|
158
188
|
INT_REGEXP = /-?(?:[0]|[1-9][0-9]*)/
|
|
159
189
|
FLOAT_DECIMAL_REGEXP = /[.][0-9]+/
|
|
160
190
|
FLOAT_EXP_REGEXP = /[eE][+-]?[0-9]+/
|
|
191
|
+
# TODO: FLOAT_EXP_REGEXP should not be allowed to follow INT_REGEXP, integers are not allowed to have exponent parts.
|
|
161
192
|
NUMERIC_REGEXP = /#{INT_REGEXP}(#{FLOAT_DECIMAL_REGEXP}#{FLOAT_EXP_REGEXP}|#{FLOAT_DECIMAL_REGEXP}|#{FLOAT_EXP_REGEXP})?/
|
|
162
193
|
|
|
163
194
|
KEYWORDS = [
|
|
@@ -216,7 +247,7 @@ module GraphQL
|
|
|
216
247
|
:SCALAR,
|
|
217
248
|
nil,
|
|
218
249
|
:FRAGMENT
|
|
219
|
-
]
|
|
250
|
+
].freeze
|
|
220
251
|
|
|
221
252
|
# This produces a unique integer for bytes 2 and 3 of each keyword string
|
|
222
253
|
# See https://tenderlovemaking.com/2023/09/02/fast-tokenizers-with-stringscanner.html
|
|
@@ -245,18 +276,18 @@ module GraphQL
|
|
|
245
276
|
PUNCTUATION_NAME_FOR_BYTE = Punctuation.constants.each_with_object([]) { |name, arr|
|
|
246
277
|
punct = Punctuation.const_get(name)
|
|
247
278
|
arr[punct.ord] = name
|
|
248
|
-
}
|
|
279
|
+
}.freeze
|
|
280
|
+
|
|
249
281
|
|
|
250
282
|
QUOTE = '"'
|
|
251
283
|
UNICODE_DIGIT = /[0-9A-Za-z]/
|
|
252
284
|
FOUR_DIGIT_UNICODE = /#{UNICODE_DIGIT}{4}/
|
|
253
285
|
N_DIGIT_UNICODE = %r{#{Punctuation::LCURLY}#{UNICODE_DIGIT}{4,}#{Punctuation::RCURLY}}x
|
|
254
286
|
UNICODE_ESCAPE = %r{\\u(?:#{FOUR_DIGIT_UNICODE}|#{N_DIGIT_UNICODE})}
|
|
255
|
-
# # https://graphql.github.io/graphql-spec/June2018/#sec-String-Value
|
|
256
287
|
STRING_ESCAPE = %r{[\\][\\/bfnrt]}
|
|
257
288
|
BLOCK_QUOTE = '"""'
|
|
258
289
|
ESCAPED_QUOTE = /\\"/;
|
|
259
|
-
STRING_CHAR = /#{ESCAPED_QUOTE}|[^"
|
|
290
|
+
STRING_CHAR = /#{ESCAPED_QUOTE}|[^"\\\n\r]|#{UNICODE_ESCAPE}|#{STRING_ESCAPE}/
|
|
260
291
|
QUOTED_STRING_REGEXP = %r{#{QUOTE} (?:#{STRING_CHAR})* #{QUOTE}}x
|
|
261
292
|
BLOCK_STRING_REGEXP = %r{
|
|
262
293
|
#{BLOCK_QUOTE}
|
|
@@ -296,29 +327,31 @@ module GraphQL
|
|
|
296
327
|
punct = Punctuation.const_get(punct_name)
|
|
297
328
|
FIRST_BYTES[punct.ord] = ByteFor::PUNCTUATION
|
|
298
329
|
end
|
|
330
|
+
FIRST_BYTES.freeze
|
|
299
331
|
|
|
300
332
|
|
|
301
333
|
# Replace any escaped unicode or whitespace with the _actual_ characters
|
|
302
334
|
# To avoid allocating more strings, this modifies the string passed into it
|
|
303
335
|
def self.replace_escaped_characters_in_place(raw_string)
|
|
304
|
-
raw_string.gsub!(
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
(
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
336
|
+
raw_string.gsub!(ESCAPED) do |matched_str|
|
|
337
|
+
if (point_str_1 = $1 || $2)
|
|
338
|
+
codepoint_1 = point_str_1.to_i(16)
|
|
339
|
+
if (codepoint_2 = $3)
|
|
340
|
+
codepoint_2 = codepoint_2.to_i(16)
|
|
341
|
+
if (codepoint_1 >= 0xD800 && codepoint_1 <= 0xDBFF) && # leading surrogate
|
|
342
|
+
(codepoint_2 >= 0xDC00 && codepoint_2 <= 0xDFFF) # trailing surrogate
|
|
343
|
+
# A surrogate pair
|
|
344
|
+
combined = ((codepoint_1 - 0xD800) * 0x400) + (codepoint_2 - 0xDC00) + 0x10000
|
|
345
|
+
[combined].pack('U'.freeze)
|
|
346
|
+
else
|
|
347
|
+
# Two separate code points
|
|
348
|
+
[codepoint_1].pack('U'.freeze) + [codepoint_2].pack('U'.freeze)
|
|
349
|
+
end
|
|
316
350
|
else
|
|
317
|
-
|
|
318
|
-
[codepoint_1].pack('U'.freeze) + [codepoint_2].pack('U'.freeze)
|
|
351
|
+
[codepoint_1].pack('U'.freeze)
|
|
319
352
|
end
|
|
320
353
|
else
|
|
321
|
-
[
|
|
354
|
+
ESCAPES_REPLACE[matched_str]
|
|
322
355
|
end
|
|
323
356
|
end
|
|
324
357
|
nil
|
|
@@ -329,17 +362,14 @@ module GraphQL
|
|
|
329
362
|
def self.tokenize(string)
|
|
330
363
|
lexer = GraphQL::Language::Lexer.new(string)
|
|
331
364
|
tokens = []
|
|
332
|
-
prev_token = nil
|
|
333
365
|
while (token_name = lexer.advance)
|
|
334
366
|
new_token = [
|
|
335
367
|
token_name,
|
|
336
368
|
lexer.line_number,
|
|
337
369
|
lexer.column_number,
|
|
338
370
|
lexer.debug_token_value(token_name),
|
|
339
|
-
prev_token,
|
|
340
371
|
]
|
|
341
372
|
tokens << new_token
|
|
342
|
-
prev_token = new_token
|
|
343
373
|
end
|
|
344
374
|
tokens
|
|
345
375
|
end
|