elasticgraph-graphql 0.19.2.0 → 0.19.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c406c0dd4109d2b92b834f989f5819fc6342696b9c0b231f38b0bb4fc0d8f858
4
- data.tar.gz: 95b206f183b6ccfc644ffab571e43232be92123d8c0998bd4add03b4d8571404
3
+ metadata.gz: 48f8d7c9aefb1e034cae73f0476b2a5c8a7fa3d653e2c2f0354650a7e18e17b4
4
+ data.tar.gz: 0eef52c59c0842516168951888b3b2d995f93cc5a5716297e8e9f2b4f5d15db6
5
5
  SHA512:
6
- metadata.gz: 5a1474ca90d5ec6a4c65996491e3570d3b4fef1bd40c9550b0b850bb663018dd9cd690e262af080212019ab12c05651aeca3f79f22ba1007a676422578e8787e
7
- data.tar.gz: 8d7f2aff08c7ea4f6038943682f1231d4371c67003acf2f78321b749d4838550eef4b53df7a37b02ee134a10075e0f382251c06d9d18ce7f8bada9838579f201
6
+ metadata.gz: 597c2a1678dab99f0425fdec407493e8706c154df056979affaa097253b51084576d500b55a70c3d84ad66915b63476c6c0083cc1f01796ac04d9d82027591bc
7
+ data.tar.gz: b764415cb4898528a7b1fc54b10fc3a77cb81f92c51a903e9c304ffce0bb0effeeae67c7dd9db57bb8c36952dc93a0c72810c213081dedb6a20b7898b513e2b8
@@ -6,16 +6,11 @@
6
6
  #
7
7
  # frozen_string_literal: true
8
8
 
9
- require "elastic_graph/graphql/client"
10
- require "elastic_graph/support/hash_util"
11
- require "graphql"
12
-
13
9
  module ElasticGraph
14
10
  class GraphQL
15
11
  # Class used to track details of what happens during a single GraphQL query for the purposes of logging.
16
12
  # Here we use `Struct` instead of `Data` specifically because it is designed to be mutable.
17
13
  class QueryDetailsTracker < Struct.new(
18
- :hidden_types,
19
14
  :shard_routing_values,
20
15
  :search_index_expressions,
21
16
  :query_counts_per_datastore_request,
@@ -26,7 +21,6 @@ module ElasticGraph
26
21
  )
27
22
  def self.empty
28
23
  new(
29
- hidden_types: ::Set.new,
30
24
  shard_routing_values: ::Set.new,
31
25
  search_index_expressions: ::Set.new,
32
26
  query_counts_per_datastore_request: [],
@@ -45,12 +39,6 @@ module ElasticGraph
45
39
  end
46
40
  end
47
41
 
48
- def record_hidden_type(type)
49
- mutex.synchronize do
50
- hidden_types << type
51
- end
52
- end
53
-
54
42
  def record_datastore_query_metrics(client_duration_ms:, server_duration_ms:, queried_shard_count:)
55
43
  mutex.synchronize do
56
44
  self.datastore_query_client_duration_ms += client_duration_ms
@@ -9,7 +9,6 @@
9
9
  require "elastic_graph/graphql/client"
10
10
  require "elastic_graph/graphql/query_details_tracker"
11
11
  require "elastic_graph/support/hash_util"
12
- require "graphql"
13
12
 
14
13
  module ElasticGraph
15
14
  class GraphQL
@@ -18,13 +17,11 @@ module ElasticGraph
18
17
  # @dynamic schema
19
18
  attr_reader :schema
20
19
 
21
- def initialize(schema:, monotonic_clock:, logger:, slow_query_threshold_ms:, datastore_search_router:, config:)
20
+ def initialize(schema:, monotonic_clock:, logger:, slow_query_threshold_ms:)
22
21
  @schema = schema
23
22
  @monotonic_clock = monotonic_clock
24
23
  @logger = logger
25
24
  @slow_query_threshold_ms = slow_query_threshold_ms
26
- @datastore_search_router = datastore_search_router
27
- @config = config
28
25
  end
29
26
 
30
27
  # Executes the given `query_string` using the provided `variables`.
@@ -61,13 +58,8 @@ module ElasticGraph
61
58
  operation_name: operation_name,
62
59
  client: client,
63
60
  context: context.merge({
64
- logger: @logger,
65
61
  monotonic_clock_deadline: timeout_in_ms&.+(start_time_in_ms),
66
- elastic_graph_schema: @schema,
67
- schema_element_names: @schema.element_names,
68
- elastic_graph_query_tracker: query_tracker,
69
- datastore_search_router: @datastore_search_router,
70
- nested_relationship_resolver_mode: @config.nested_relationship_resolver_mode
62
+ elastic_graph_query_tracker: query_tracker
71
63
  }.compact)
72
64
  )
73
65
 
@@ -81,10 +73,6 @@ module ElasticGraph
81
73
  EOS
82
74
  end
83
75
 
84
- unless query_tracker.hidden_types.empty?
85
- @logger.warn "#{query_tracker.hidden_types.size} GraphQL types were hidden from the schema due to their backing indices being inaccessible: #{query_tracker.hidden_types.sort.join(", ")}"
86
- end
87
-
88
76
  duration = @monotonic_clock.now_in_ms - start_time_in_ms
89
77
 
90
78
  # Note: I also wanted to log the sanitized query if `result` has `errors`, but `GraphQL::Query#sanitized_query`
@@ -140,8 +128,7 @@ module ElasticGraph
140
128
  # Note: this is designed so that `elasticgraph-query_registry` can hook into this method. It needs to be able
141
129
  # to override how the query is built and executed.
142
130
  def build_and_execute_query(query_string:, variables:, operation_name:, context:, client:)
143
- query = ::GraphQL::Query.new(
144
- @schema.graphql_schema,
131
+ query = @schema.new_graphql_query(
145
132
  query_string,
146
133
  variables: variables,
147
134
  operation_name: operation_name,
@@ -109,7 +109,10 @@ module ElasticGraph
109
109
  # If `__typename` is available, use that to resolve. It should be available on any embedded abstract types...
110
110
  # (See `Inventor` in `config/schema.graphql` for an example of this kind of type union.)
111
111
  if (typename = object["__typename"])
112
- schema.graphql_schema.possible_types(supertype).find { |t| t.graphql_name == typename }
112
+ schema
113
+ .graphql_schema
114
+ .possible_types(supertype, visibility_profile: VISIBILITY_PROFILE)
115
+ .find { |t| t.graphql_name == typename }
113
116
  else
114
117
  # ...otherwise infer the type based on what index the object came from. This is the case
115
118
  # with unions/interfaces of individually indexed types.
@@ -65,8 +65,9 @@ module ElasticGraph
65
65
  @join = join
66
66
  @filter_id_field_name_path = @join.filter_id_field_name.split(".")
67
67
  @context = context
68
- @schema_element_names = @context.fetch(:schema_element_names)
69
- @logger = context.fetch(:logger)
68
+ elastic_graph_schema = context.fetch(:elastic_graph_schema)
69
+ @schema_element_names = elastic_graph_schema.element_names
70
+ @logger = elastic_graph_schema.logger
70
71
  @monotonic_clock = monotonic_clock
71
72
  @mode = mode
72
73
  end
@@ -20,7 +20,7 @@ module ElasticGraph
20
20
  def self.maybe_wrap(search_response, field:, context:, lookahead:, query:)
21
21
  return search_response unless field.type.relay_connection?
22
22
 
23
- schema_element_names = context.fetch(:schema_element_names)
23
+ schema_element_names = context.fetch(:elastic_graph_schema).element_names
24
24
 
25
25
  unless field.type.unwrap_fully.indexed_aggregation?
26
26
  return SearchResponseAdapterBuilder.build_from(
@@ -112,7 +112,10 @@ module ElasticGraph
112
112
  # Returns the subtypes of this type, if it has any. This is like `#possible_types` provided by the
113
113
  # GraphQL gem, but that includes a type itself when you ask for the possible types of a non-abstract type.
114
114
  def subtypes
115
- @subtypes ||= @schema.graphql_schema.possible_types(graphql_type).map { |t| @schema.type_from(t) } - [self]
115
+ @subtypes ||= @schema
116
+ .graphql_schema
117
+ .possible_types(graphql_type, visibility_profile: :boot)
118
+ .map { |t| @schema.type_from(t) } - [self]
116
119
  end
117
120
 
118
121
  def field_named(field_name)
@@ -6,13 +6,11 @@
6
6
  #
7
7
  # frozen_string_literal: true
8
8
 
9
+ require "graphql"
9
10
  require "elastic_graph/constants"
10
11
  require "elastic_graph/errors"
11
- require "elastic_graph/graphql/monkey_patches/schema_field"
12
- require "elastic_graph/graphql/monkey_patches/schema_object"
13
12
  require "elastic_graph/graphql/schema/field"
14
13
  require "elastic_graph/graphql/schema/type"
15
- require "graphql"
16
14
 
17
15
  module ElasticGraph
18
16
  # Wraps a GraphQL::Schema object in order to provide higher-level, more convenient APIs
@@ -26,19 +24,24 @@ module ElasticGraph
26
24
  scalar_types.to_set.union(introspection_types)
27
25
  )
28
26
 
29
- attr_reader :element_names, :config, :graphql_schema, :runtime_metadata
27
+ attr_reader :element_names, :config, :logger, :graphql_schema, :runtime_metadata
30
28
 
31
29
  def initialize(
32
30
  graphql_schema_string:,
33
31
  config:,
32
+ logger:,
34
33
  runtime_metadata:,
34
+ datastore_search_router:,
35
35
  index_definitions_by_graphql_type:,
36
36
  graphql_gem_plugins:,
37
37
  graphql_adapter:
38
38
  )
39
39
  @element_names = runtime_metadata.schema_element_names
40
40
  @config = config
41
+ @logger = logger
41
42
  @runtime_metadata = runtime_metadata
43
+ @datastore_search_router = datastore_search_router
44
+
42
45
  resolvers_needing_lookahead = runtime_metadata.graphql_resolvers_by_name.filter_map do |name, resolver|
43
46
  name if resolver.needs_lookahead
44
47
  end.to_set
@@ -60,6 +63,7 @@ module ElasticGraph
60
63
  # variables above we'll get `NoMethodError` on `nil`.
61
64
  @graphql_schema = ::GraphQL::Schema.from_definition(
62
65
  graphql_schema_string,
66
+ base_types: {object: build_base_object_class},
63
67
  default_resolve: graphql_adapter,
64
68
  using: graphql_gem_plugins
65
69
  )
@@ -67,6 +71,36 @@ module ElasticGraph
67
71
  # Pre-load all defined types so that all field extras can get configured as part
68
72
  # of loading the schema, before we execute the first query.
69
73
  @types_by_name = build_types_by_name
74
+ @graphql_schema.visibility.preload
75
+
76
+ log_hidden_types
77
+ end
78
+
79
+ def new_graphql_query(
80
+ query_string,
81
+ operation_name: nil,
82
+ variables: {},
83
+ context: {},
84
+ document: nil,
85
+ validate: true
86
+ )
87
+ ::GraphQL::Query.new(
88
+ graphql_schema,
89
+ query_string,
90
+ variables: variables,
91
+ operation_name: operation_name,
92
+ document: document,
93
+ validate: validate,
94
+ context: context.merge({
95
+ datastore_search_router: @datastore_search_router,
96
+ elastic_graph_schema: self,
97
+ visibility_profile: VISIBILITY_PROFILE
98
+ })
99
+ )
100
+ end
101
+
102
+ def graphql_query_context
103
+ @graphql_query_context ||= new_graphql_query(nil).context
70
104
  end
71
105
 
72
106
  def type_from(graphql_type)
@@ -119,8 +153,38 @@ module ElasticGraph
119
153
 
120
154
  private
121
155
 
156
+ def build_base_object_class
157
+ schema = self
158
+
159
+ base_field_class = ::Class.new(::GraphQL::Schema::Field) do
160
+ define_method :visible? do |context|
161
+ return super(context) if context[:visibility_profile] == :boot
162
+
163
+ if schema.field_named(owner.graphql_name, graphql_name).hidden_from_queries?
164
+ return false
165
+ end
166
+
167
+ super(context)
168
+ end
169
+ end
170
+
171
+ ::Class.new(::GraphQL::Schema::Object) do
172
+ field_class base_field_class
173
+
174
+ define_singleton_method :visible? do |context|
175
+ return super(context) if context[:visibility_profile] == :boot
176
+
177
+ if schema.type_named(graphql_name).hidden_from_queries?
178
+ return false
179
+ end
180
+
181
+ super(context)
182
+ end
183
+ end
184
+ end
185
+
122
186
  def build_types_by_name
123
- graphql_schema.types.transform_values do |graphql_type|
187
+ graphql_schema.types(visibility_profile: :boot).transform_values do |graphql_type|
124
188
  @types_by_graphql_type[graphql_type]
125
189
  end
126
190
  end
@@ -136,6 +200,16 @@ module ElasticGraph
136
200
  end
137
201
  end.freeze
138
202
  end
203
+
204
+ def log_hidden_types
205
+ hidden_types = @types_by_name.values.select(&:hidden_from_queries?)
206
+ return if hidden_types.empty?
207
+
208
+ logger.warn(
209
+ "#{hidden_types.size} GraphQL types were hidden from the schema due to their backing indices being " \
210
+ "inaccessible: #{hidden_types.map(&:name).sort.join(", ")}"
211
+ )
212
+ end
139
213
  end
140
214
  end
141
215
  end
@@ -8,6 +8,7 @@
8
8
 
9
9
  require "elastic_graph/datastore_core"
10
10
  require "elastic_graph/graphql/config"
11
+ require "elastic_graph/constants"
11
12
  require "elastic_graph/support/from_yaml_file"
12
13
 
13
14
  module ElasticGraph
@@ -26,7 +27,7 @@ module ElasticGraph
26
27
  def self.from_parsed_yaml(parsed_yaml, &datastore_client_customization_block)
27
28
  new(
28
29
  config: GraphQL::Config.from_parsed_yaml(parsed_yaml),
29
- datastore_core: DatastoreCore.from_parsed_yaml(parsed_yaml, for_context: :graphql, &datastore_client_customization_block)
30
+ datastore_core: DatastoreCore.from_parsed_yaml(parsed_yaml, &datastore_client_customization_block)
30
31
  )
31
32
  end
32
33
 
@@ -55,7 +56,7 @@ module ElasticGraph
55
56
 
56
57
  # Apply any extension modules that have been configured.
57
58
  @config.extension_modules.each { |mod| extend mod }
58
- @runtime_metadata.graphql_extension_modules.each { |ext_mod| extend ext_mod.extension_class }
59
+ @runtime_metadata.graphql_extension_modules.each { |ext_mod| extend ext_mod.load_extension.extension_class }
59
60
  end
60
61
 
61
62
  # @private
@@ -78,9 +79,7 @@ module ElasticGraph
78
79
  schema: schema,
79
80
  monotonic_clock: monotonic_clock,
80
81
  logger: logger,
81
- slow_query_threshold_ms: @config.slow_query_latency_warning_threshold_in_ms,
82
- datastore_search_router: datastore_search_router,
83
- config: config
82
+ slow_query_threshold_ms: @config.slow_query_latency_warning_threshold_in_ms
84
83
  )
85
84
  end
86
85
  end
@@ -92,7 +91,9 @@ module ElasticGraph
92
91
  Schema.new(
93
92
  graphql_schema_string: graphql_schema_string,
94
93
  config: config,
94
+ logger: logger,
95
95
  runtime_metadata: runtime_metadata,
96
+ datastore_search_router: datastore_search_router,
96
97
  index_definitions_by_graphql_type: @datastore_core.index_definitions_by_graphql_type,
97
98
  graphql_gem_plugins: graphql_gem_plugins,
98
99
  graphql_adapter: graphql_adapter
@@ -132,15 +133,27 @@ module ElasticGraph
132
133
  def graphql_gem_plugins
133
134
  @graphql_gem_plugins ||= begin
134
135
  require "graphql"
136
+ # As per https://graphql-ruby.org/language_tools/c_parser.html, loading the
137
+ # C parser causes the faster parser to be assigned as the `::GraphQL.default_parser`,
138
+ # providing greater efficiency.
139
+ #
140
+ # We load it here since this is where we load the GraphQL gem.
141
+ require "graphql/c_parser"
142
+
135
143
  {
136
144
  # We depend on this to avoid N+1 calls to the datastore.
137
145
  ::GraphQL::Dataloader => {},
138
- # Here we opt-in to the old `GraphQL::Schema::Warden` visibility plugin.
139
- # The new plugin, `GraphQL::Schema::Visibility`, causes a performance regression
140
- # in ElasticGraph projects, and until that's fixed we want to stick with the old plugin.
141
- #
142
- # TODO: switch back to `::GraphQL::Schema::Visibility => {preload: true}` once the perf issue has been fixed.
143
- ::GraphQL::Schema::Warden => {}
146
+ # https://graphql-ruby.org/authorization/visibility.html
147
+ ::GraphQL::Schema::Visibility => {
148
+ # The GraphQL gem internally cache the visibility per profile. Ideally, we'd have only a single profile,
149
+ # but that makes for a chicken-and-egg problem: our visibility logic depends on the schema being fully
150
+ # loaded, but the `visibility?` methods are called while loading the schema. To deal with that, we're
151
+ # using tw profiles:
152
+ #
153
+ # - `boot` is used while loading, and skips our normal visibility logic.
154
+ # - `main` is used after that and uses our normal visibility logic.
155
+ profiles: {:boot => {}, VISIBILITY_PROFILE => {}} # : ::Hash[::Symbol, ::Hash[::Symbol, untyped]]
156
+ }
144
157
  }
145
158
  end
146
159
  end
@@ -250,6 +263,8 @@ module ElasticGraph
250
263
  # it's nice to load dependencies when needed.
251
264
  def load_dependencies_eagerly
252
265
  require "graphql"
266
+ require "graphql/c_parser"
267
+
253
268
  ::GraphQL.eager_load!
254
269
 
255
270
  # run a simple GraphQL query to force load any dependencies needed to handle GraphQL queries
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elasticgraph-graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.2.0
4
+ version: 0.19.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Myron Marston
@@ -9,120 +9,154 @@ authors:
9
9
  - Block Engineering
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-04-09 00:00:00.000000000 Z
12
+ date: 2025-04-24 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: base64
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '0.2'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '0.2'
14
28
  - !ruby/object:Gem::Dependency
15
29
  name: elasticgraph-datastore_core
16
30
  requirement: !ruby/object:Gem::Requirement
17
31
  requirements:
18
32
  - - '='
19
33
  - !ruby/object:Gem::Version
20
- version: 0.19.2.0
34
+ version: 0.19.2.1
21
35
  type: :runtime
22
36
  prerelease: false
23
37
  version_requirements: !ruby/object:Gem::Requirement
24
38
  requirements:
25
39
  - - '='
26
40
  - !ruby/object:Gem::Version
27
- version: 0.19.2.0
41
+ version: 0.19.2.1
28
42
  - !ruby/object:Gem::Dependency
29
43
  name: elasticgraph-schema_artifacts
30
44
  requirement: !ruby/object:Gem::Requirement
31
45
  requirements:
32
46
  - - '='
33
47
  - !ruby/object:Gem::Version
34
- version: 0.19.2.0
48
+ version: 0.19.2.1
35
49
  type: :runtime
36
50
  prerelease: false
37
51
  version_requirements: !ruby/object:Gem::Requirement
38
52
  requirements:
39
53
  - - '='
40
54
  - !ruby/object:Gem::Version
41
- version: 0.19.2.0
55
+ version: 0.19.2.1
42
56
  - !ruby/object:Gem::Dependency
43
57
  name: graphql
44
58
  requirement: !ruby/object:Gem::Requirement
45
59
  requirements:
46
60
  - - "~>"
47
61
  - !ruby/object:Gem::Version
48
- version: 2.5.1
62
+ version: 2.5.4
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: 2.5.4
70
+ - !ruby/object:Gem::Dependency
71
+ name: graphql-c_parser
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '1.1'
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: 1.1.2
49
80
  type: :runtime
50
81
  prerelease: false
51
82
  version_requirements: !ruby/object:Gem::Requirement
52
83
  requirements:
53
84
  - - "~>"
54
85
  - !ruby/object:Gem::Version
55
- version: 2.5.1
86
+ version: '1.1'
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 1.1.2
56
90
  - !ruby/object:Gem::Dependency
57
91
  name: elasticgraph-admin
58
92
  requirement: !ruby/object:Gem::Requirement
59
93
  requirements:
60
94
  - - '='
61
95
  - !ruby/object:Gem::Version
62
- version: 0.19.2.0
96
+ version: 0.19.2.1
63
97
  type: :development
64
98
  prerelease: false
65
99
  version_requirements: !ruby/object:Gem::Requirement
66
100
  requirements:
67
101
  - - '='
68
102
  - !ruby/object:Gem::Version
69
- version: 0.19.2.0
103
+ version: 0.19.2.1
70
104
  - !ruby/object:Gem::Dependency
71
105
  name: elasticgraph-elasticsearch
72
106
  requirement: !ruby/object:Gem::Requirement
73
107
  requirements:
74
108
  - - '='
75
109
  - !ruby/object:Gem::Version
76
- version: 0.19.2.0
110
+ version: 0.19.2.1
77
111
  type: :development
78
112
  prerelease: false
79
113
  version_requirements: !ruby/object:Gem::Requirement
80
114
  requirements:
81
115
  - - '='
82
116
  - !ruby/object:Gem::Version
83
- version: 0.19.2.0
117
+ version: 0.19.2.1
84
118
  - !ruby/object:Gem::Dependency
85
119
  name: elasticgraph-opensearch
86
120
  requirement: !ruby/object:Gem::Requirement
87
121
  requirements:
88
122
  - - '='
89
123
  - !ruby/object:Gem::Version
90
- version: 0.19.2.0
124
+ version: 0.19.2.1
91
125
  type: :development
92
126
  prerelease: false
93
127
  version_requirements: !ruby/object:Gem::Requirement
94
128
  requirements:
95
129
  - - '='
96
130
  - !ruby/object:Gem::Version
97
- version: 0.19.2.0
131
+ version: 0.19.2.1
98
132
  - !ruby/object:Gem::Dependency
99
133
  name: elasticgraph-indexer
100
134
  requirement: !ruby/object:Gem::Requirement
101
135
  requirements:
102
136
  - - '='
103
137
  - !ruby/object:Gem::Version
104
- version: 0.19.2.0
138
+ version: 0.19.2.1
105
139
  type: :development
106
140
  prerelease: false
107
141
  version_requirements: !ruby/object:Gem::Requirement
108
142
  requirements:
109
143
  - - '='
110
144
  - !ruby/object:Gem::Version
111
- version: 0.19.2.0
145
+ version: 0.19.2.1
112
146
  - !ruby/object:Gem::Dependency
113
147
  name: elasticgraph-schema_definition
114
148
  requirement: !ruby/object:Gem::Requirement
115
149
  requirements:
116
150
  - - '='
117
151
  - !ruby/object:Gem::Version
118
- version: 0.19.2.0
152
+ version: 0.19.2.1
119
153
  type: :development
120
154
  prerelease: false
121
155
  version_requirements: !ruby/object:Gem::Requirement
122
156
  requirements:
123
157
  - - '='
124
158
  - !ruby/object:Gem::Version
125
- version: 0.19.2.0
159
+ version: 0.19.2.1
126
160
  email:
127
161
  - myron@squareup.com
128
162
  executables: []
@@ -171,8 +205,6 @@ files:
171
205
  - lib/elastic_graph/graphql/filtering/filter_value_set_extractor.rb
172
206
  - lib/elastic_graph/graphql/filtering/range_query.rb
173
207
  - lib/elastic_graph/graphql/http_endpoint.rb
174
- - lib/elastic_graph/graphql/monkey_patches/schema_field.rb
175
- - lib/elastic_graph/graphql/monkey_patches/schema_object.rb
176
208
  - lib/elastic_graph/graphql/query_adapter/filters.rb
177
209
  - lib/elastic_graph/graphql/query_adapter/pagination.rb
178
210
  - lib/elastic_graph/graphql/query_adapter/requested_fields.rb
@@ -215,10 +247,10 @@ licenses:
215
247
  - MIT
216
248
  metadata:
217
249
  bug_tracker_uri: https://github.com/block/elasticgraph/issues
218
- changelog_uri: https://github.com/block/elasticgraph/releases/tag/v0.19.2.0
219
- documentation_uri: https://block.github.io/elasticgraph/api-docs/v0.19.2.0/
250
+ changelog_uri: https://github.com/block/elasticgraph/releases/tag/v0.19.2.1
251
+ documentation_uri: https://block.github.io/elasticgraph/api-docs/v0.19.2.1/
220
252
  homepage_uri: https://block.github.io/elasticgraph/
221
- source_code_uri: https://github.com/block/elasticgraph/tree/v0.19.2.0/elasticgraph-graphql
253
+ source_code_uri: https://github.com/block/elasticgraph/tree/v0.19.2.1/elasticgraph-graphql
222
254
  gem_category: core
223
255
  rdoc_options: []
224
256
  require_paths:
@@ -1,56 +0,0 @@
1
- # Copyright 2024 - 2025 Block, Inc.
2
- #
3
- # Use of this source code is governed by an MIT-style
4
- # license that can be found in the LICENSE file or at
5
- # https://opensource.org/licenses/MIT.
6
- #
7
- # frozen_string_literal: true
8
-
9
- require "graphql"
10
-
11
- module ElasticGraph
12
- class GraphQL
13
- module MonkeyPatches
14
- # This module is designed to monkey patch `GraphQL::Schema::Field`, but to do so in a
15
- # conservative, safe way:
16
- #
17
- # - It defines no new methods.
18
- # - It delegates to the original implementation with `super` unless we are sure that a type should be hidden.
19
- # - It only changes the behavior for ElasticGraph schemas (as indicated by `:elastic_graph_schema` in the `context`).
20
- module SchemaFieldVisibilityDecorator
21
- def visible?(context)
22
- # `DynamicFields` and `EntryPoints` are built-in introspection types that `field_named` below doesn't support:
23
- # https://github.com/rmosolgo/graphql-ruby/blob/0df187995c971b399ed7cc1fbdcbd958af6c4ade/lib/graphql/introspection/entry_points.rb
24
- # https://github.com/rmosolgo/graphql-ruby/blob/0df187995c971b399ed7cc1fbdcbd958af6c4ade/lib/graphql/introspection/dynamic_fields.rb
25
- #
26
- # ...so if the owner is one of those we just return `super` here.
27
- return super if %w[DynamicFields EntryPoints].include?(owner.graphql_name)
28
-
29
- if context[:elastic_graph_schema]&.field_named(owner.graphql_name, graphql_name)&.hidden_from_queries?
30
- return false
31
- end
32
-
33
- super
34
- end
35
- end
36
- end
37
- end
38
- end
39
-
40
- # As per https://graphql-ruby.org/authorization/visibility.html, the public API
41
- # provided by the GraphQL gem to control visibility of object types is to define
42
- # a `visible?` instance method on a custom subclass of `GraphQL::Schema::Field`.
43
- # However, because we load our schema from an SDL definition rather than defining
44
- # classes for each schema type, we don't have a way to register a custom subclass
45
- # to be used for fields.
46
- #
47
- # So, here we solve this a slightly different way: we prepend a module onto
48
- # the `GraphQL::Schema::Field class. This allows our module to act like a
49
- # decorator and intercept calls to `visible?` so that it can hide types as needed.
50
- module GraphQL
51
- class Schema
52
- class Field
53
- prepend ::ElasticGraph::GraphQL::MonkeyPatches::SchemaFieldVisibilityDecorator
54
- end
55
- end
56
- end
@@ -1,48 +0,0 @@
1
- # Copyright 2024 - 2025 Block, Inc.
2
- #
3
- # Use of this source code is governed by an MIT-style
4
- # license that can be found in the LICENSE file or at
5
- # https://opensource.org/licenses/MIT.
6
- #
7
- # frozen_string_literal: true
8
-
9
- require "graphql"
10
-
11
- module ElasticGraph
12
- class GraphQL
13
- module MonkeyPatches
14
- # This module is designed to monkey patch `GraphQL::Schema::Object`, but to do so in a
15
- # conservative, safe way:
16
- #
17
- # - It defines no new methods.
18
- # - It delegates to the original implementation with `super` unless we are sure that a type should be hidden.
19
- # - It only changes the behavior for ElasticGraph schemas (as indicated by `:elastic_graph_schema` in the `context`).
20
- module SchemaObjectVisibilityDecorator
21
- def visible?(context)
22
- if context[:elastic_graph_schema]&.type_named(graphql_name)&.hidden_from_queries?
23
- context[:elastic_graph_query_tracker].record_hidden_type(graphql_name)
24
- return false
25
- end
26
-
27
- super
28
- end
29
- end
30
- end
31
- end
32
- end
33
-
34
- # As per https://graphql-ruby.org/authorization/visibility.html, the public API
35
- # provided by the GraphQL gem to control visibility of object types is to define
36
- # a `visible?` class method on each of your type classes. However, because we load
37
- # our schema from an SDL definition rather than defining classes for each schema
38
- # type, we don't have a way to define the `visible?` on each of our type classes.
39
- #
40
- # So, here we solve this a slightly different way: we prepend a module onto
41
- # the `GraphQL::Schema::Object` singleton class. This allows our module to
42
- # act like a decorator and intercept calls to `visible?` so that it can hide
43
- # types as needed. This works because all types must be defined as subclasses
44
- # of `GraphQL::Schema::Object`, and in fact the GraphQL gem defined anonymous
45
- # subclasses for each type in our SDL schema, as you can see here:
46
- #
47
- # https://github.com/rmosolgo/graphql-ruby/blob/v1.12.16/lib/graphql/schema/build_from_definition.rb#L312
48
- GraphQL::Schema::Object.singleton_class.prepend ElasticGraph::GraphQL::MonkeyPatches::SchemaObjectVisibilityDecorator