graphql-persisted_queries 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78784d32983df6d9d75af398dcf87f1239e37dce760eb99b73c3ebcf5856ee8c
4
- data.tar.gz: d2e0a437767dfa2a148654b32ebfe7669167273fcf123de9b9834ac733cc3f03
3
+ metadata.gz: 7a8319ef6ac9b60ce31f69b86163c9c77f700b2d663da6ab10018b76c96ebc2f
4
+ data.tar.gz: b197af199c9699cda0a7c3c5491d2f22b110b77f61a7632a1982ca3acbc49292
5
5
  SHA512:
6
- metadata.gz: b070e30dea650ae02e6164440cd1b7b1a73796b98db7e691c8ff10fce9b5eb9351daebcbf68f2d2d3e7d2ccdf8bb6503f00eae2060a674be66d1229811e3f375
7
- data.tar.gz: cb4f0137249ab7414857af926833de0d8060a8fc77eb7f29fb2853dfcb22f85382ed8341169a7b0015c21fd52429b7e735c67e1923545ba69d44441166c217e6
6
+ metadata.gz: 2f6f9f3d32aad7d89b263f60701c30f06cba0bb43934fa18360e70ef979c1bdf1f28050859b92788040a600e8d803d850f753383d700243dbdea0b59973bcaf5
7
+ data.tar.gz: 5505e5d9b983b8dc2a510dd17fe417eee561bc337da0deb203030b6f0889732ea46b5d76dc9694d5129ddc7538f43467040dcbe907651863b6a26d3c9888a2b3
@@ -20,8 +20,6 @@ jobs:
20
20
  matrix:
21
21
  ruby: [2.6, 2.7, 3.0]
22
22
  gemfile: [
23
- "gemfiles/graphql_1_10.gemfile",
24
- "gemfiles/graphql_1_11.gemfile",
25
23
  "gemfiles/graphql_1_12_0.gemfile",
26
24
  "gemfiles/graphql_1_12_4.gemfile",
27
25
  "gemfiles/graphql_1_13_7.gemfile",
@@ -17,5 +17,5 @@ jobs:
17
17
  ruby-version: 2.7
18
18
  - name: Lint Ruby code with RuboCop
19
19
  run: |
20
- bundle install --gemfile gemfiles/graphql_1_10.gemfile --jobs 4 --retry 3
21
- bundle exec --gemfile gemfiles/graphql_1_10.gemfile rubocop
20
+ bundle install --gemfile gemfiles/graphql_1_12_0.gemfile --jobs 4 --retry 3
21
+ bundle exec --gemfile gemfiles/graphql_1_12_0.gemfile rubocop
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.6.0 (2022-10-10)
6
+
7
+ - [PR#57](https://github.com/DmitryTsepelev/graphql-ruby-persisted_queries/pull/57) Refactor code to use instrumentation instead of a monkey patch, deprecate graphql-ruby 1.10 and 1.11 ([@DmitryTsepelev][])
8
+
5
9
  ## 1.5.1 (2022-09-28)
6
10
 
7
11
  - [PR#56](https://github.com/DmitryTsepelev/graphql-ruby-persisted_queries/pull/56) Support graphql-ruby 2.0.14 ([@DmitryTsepelev][])
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.required_ruby_version = ">= 2.6"
24
24
 
25
- spec.add_dependency "graphql", ">= 1.10"
25
+ spec.add_dependency "graphql", ">= 1.12"
26
26
 
27
27
  spec.add_development_dependency "rspec", "~> 3.9"
28
28
  spec.add_development_dependency "rake", ">= 10.0"
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module PersistedQueries
5
+ module CompiledQueries
6
+ # Instrumentation to support compiled queries
7
+ module Instrumentation
8
+ class << self
9
+ # Actions to perform before the query resolution
10
+ def before_query(query)
11
+ return unless query.context[:extensions]
12
+
13
+ resolver = resolver_for(query)
14
+ if (document = resolver.fetch)
15
+ query.fulfill_document(document)
16
+ else
17
+ query.not_loaded_document!
18
+ end
19
+
20
+ return if document || query.query_string
21
+
22
+ query.persisted_query_not_found!
23
+ query.context.errors << GraphQL::ExecutionError.new(NotFound::MESSAGE)
24
+ end
25
+
26
+ def after_query(*); end
27
+
28
+ private
29
+
30
+ def resolver_for(query)
31
+ CompiledQueries::Resolver.new(query.schema, query.context[:extensions])
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -21,7 +21,7 @@ module GraphQL
21
21
 
22
22
  def add_not_found_error(query)
23
23
  query.context.errors.clear
24
- query.context.errors << GraphQL::ExecutionError.new("PersistedQueryNotFound")
24
+ query.context.errors << GraphQL::ExecutionError.new(NotFound::MESSAGE)
25
25
  GraphQL::Execution::Multiplex::NO_OPERATION
26
26
  end
27
27
  end
@@ -5,6 +5,18 @@ module GraphQL
5
5
  module CompiledQueries
6
6
  # Patches GraphQL::Query to support compiled queries
7
7
  module QueryPatch
8
+ def fulfill_document(document)
9
+ @document = document
10
+ end
11
+
12
+ def not_loaded_document!
13
+ @not_loaded_document = true
14
+ end
15
+
16
+ def persisted_query_not_found!
17
+ @persisted_query_not_found = true
18
+ end
19
+
8
20
  def persisted_query_not_found?
9
21
  @persisted_query_not_found
10
22
  end
@@ -12,13 +24,12 @@ module GraphQL
12
24
  def prepare_ast
13
25
  return super unless @context[:extensions]
14
26
 
15
- @document = resolver.fetch
16
- not_loaded_document = @document.nil?
17
-
18
- @persisted_query_not_found = not_loaded_document && query_string.nil?
19
-
20
27
  super.tap do
21
- resolver.persist(query_string, @document) if not_loaded_document && query_string
28
+ if @context.errors.any?(&method(:not_found_error?))
29
+ @context.errors.select!(&method(:not_found_error?))
30
+ end
31
+
32
+ resolver.persist(query_string, @document) if @not_loaded_document && query_string
22
33
  end
23
34
  end
24
35
 
@@ -27,6 +38,10 @@ module GraphQL
27
38
  def resolver
28
39
  @resolver ||= Resolver.new(@schema, @context[:extensions])
29
40
  end
41
+
42
+ def not_found_error?(error)
43
+ error.message == GraphQL::PersistedQueries::NotFound::MESSAGE
44
+ end
30
45
  end
31
46
  end
32
47
  end
@@ -4,8 +4,10 @@ module GraphQL
4
4
  module PersistedQueries
5
5
  # Raised when persisted query is not found in the storage
6
6
  class NotFound < StandardError
7
+ MESSAGE = "PersistedQueryNotFound"
8
+
7
9
  def message
8
- "PersistedQueryNotFound"
10
+ MESSAGE
9
11
  end
10
12
  end
11
13
 
@@ -3,6 +3,7 @@
3
3
  require "graphql/persisted_queries/hash_generator_builder"
4
4
  require "graphql/persisted_queries/resolver"
5
5
  require "graphql/persisted_queries/multiplex_resolver"
6
+ require "graphql/persisted_queries/compiled_queries/instrumentation"
6
7
  require "graphql/persisted_queries/analyzers/http_method_validator"
7
8
 
8
9
  module GraphQL
@@ -13,10 +14,12 @@ module GraphQL
13
14
  def patch(schema, compiled_queries)
14
15
  schema.singleton_class.prepend(SchemaPatch)
15
16
 
16
- return if compiled_queries
17
-
18
- schema.singleton_class.class_eval { alias_method :multiplex_original, :multiplex }
19
- schema.singleton_class.prepend(MultiplexPatch)
17
+ if compiled_queries
18
+ schema.instrument :query, CompiledQueries::Instrumentation
19
+ else
20
+ schema.singleton_class.class_eval { alias_method :multiplex_original, :multiplex }
21
+ schema.singleton_class.prepend(MultiplexPatch)
22
+ end
20
23
  end
21
24
  end
22
25
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GraphQL
4
4
  module PersistedQueries
5
- VERSION = "1.5.1"
5
+ VERSION = "1.6.0"
6
6
  end
7
7
  end
@@ -10,7 +10,6 @@ require "graphql/persisted_queries/builder_helpers"
10
10
 
11
11
  require "graphql/persisted_queries/compiled_queries/resolver"
12
12
  require "graphql/persisted_queries/compiled_queries/multiplex_patch"
13
- require "graphql/persisted_queries/compiled_queries/interpreter_patch"
14
13
  require "graphql/persisted_queries/compiled_queries/query_patch"
15
14
 
16
15
  module GraphQL
@@ -38,16 +37,12 @@ module GraphQL
38
37
  end
39
38
  # rubocop:enable Metrics/MethodLength
40
39
 
41
- def self.configure_compiled_queries # rubocop:disable Metrics/MethodLength
40
+ def self.configure_compiled_queries
42
41
  if Gem::Dependency.new("graphql", "< 1.12.0").match?("graphql", GraphQL::VERSION)
43
42
  raise ArgumentError, "compiled_queries are not supported for graphql-ruby < 1.12.0"
44
43
  end
45
44
 
46
- if Gem::Dependency.new("graphql", ">= 2.0.14").match?("graphql", GraphQL::VERSION)
47
- GraphQL::Execution::Interpreter.singleton_class.prepend(
48
- GraphQL::PersistedQueries::CompiledQueries::InterpreterPatch
49
- )
50
- else
45
+ if Gem::Dependency.new("graphql", "< 2.0.14").match?("graphql", GraphQL::VERSION)
51
46
  GraphQL::Execution::Multiplex.singleton_class.prepend(
52
47
  GraphQL::PersistedQueries::CompiledQueries::MultiplexPatch
53
48
  )
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-persisted_queries
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.1
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - DmitryTsepelev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-28 00:00:00.000000000 Z
11
+ date: 2022-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.10'
19
+ version: '1.12'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.10'
26
+ version: '1.12'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -136,8 +136,6 @@ files:
136
136
  - docs/hash.md
137
137
  - docs/http_cache.md
138
138
  - docs/tracing.md
139
- - gemfiles/graphql_1_10.gemfile
140
- - gemfiles/graphql_1_11.gemfile
141
139
  - gemfiles/graphql_1_12_0.gemfile
142
140
  - gemfiles/graphql_1_12_4.gemfile
143
141
  - gemfiles/graphql_1_13_7.gemfile
@@ -149,7 +147,7 @@ files:
149
147
  - lib/graphql/persisted_queries/analyzers/http_method_ast_analyzer.rb
150
148
  - lib/graphql/persisted_queries/analyzers/http_method_validator.rb
151
149
  - lib/graphql/persisted_queries/builder_helpers.rb
152
- - lib/graphql/persisted_queries/compiled_queries/interpreter_patch.rb
150
+ - lib/graphql/persisted_queries/compiled_queries/instrumentation.rb
153
151
  - lib/graphql/persisted_queries/compiled_queries/multiplex_patch.rb
154
152
  - lib/graphql/persisted_queries/compiled_queries/query_patch.rb
155
153
  - lib/graphql/persisted_queries/compiled_queries/resolver.rb
@@ -1,5 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gem "graphql", "~> 1.10.0"
4
-
5
- gemspec path: "../"
@@ -1,5 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gem "graphql", "~> 1.11.0"
4
-
5
- gemspec path: "../"
@@ -1,162 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module GraphQL
4
- module PersistedQueries
5
- module CompiledQueries
6
- # Patches GraphQL::Execution::Multiplex to support compiled queries
7
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Layout/IndentationWidth
8
- # rubocop:disable Metrics/PerceivedComplexity, Metrics/ModuleLength, Metrics/LineLength
9
- # rubocop:disable Metrics/BlockLength, Style/BracesAroundHashParameters, Style/CommentAnnotation
10
- # rubocop:disable Naming/RescuedExceptionsVariableName, Layout/SpaceInsideHashLiteralBraces
11
- # rubocop:disable Lint/ShadowingOuterLocalVariable, Style/BlockDelimiters, Metrics/MethodLength
12
- # rubocop:disable Style/Next, Layout/ElseAlignment, Layout/EndAlignment, Lint/RescueException
13
- module InterpreterPatch
14
- # This method is fully copied from the gem because I didn't find a way to patch it. In future we will
15
- # need to keep it in sync and migrate the monkey patch to newer versions of the file.
16
- def run_all(schema, query_options, context: {}, max_complexity: schema.max_complexity)
17
- queries = query_options.map do |opts|
18
- case opts
19
- when Hash
20
- GraphQL::Query.new(schema, nil, **opts)
21
- when GraphQL::Query
22
- opts
23
- else
24
- raise "Expected Hash or GraphQL::Query, not #{opts.class} (#{opts.inspect})"
25
- end
26
- end
27
-
28
- multiplex = Execution::Multiplex.new(schema: schema, queries: queries, context: context, max_complexity: max_complexity)
29
- multiplex.trace("execute_multiplex", { multiplex: multiplex }) do
30
- schema = multiplex.schema
31
- queries = multiplex.queries
32
- query_instrumenters = schema.instrumenters[:query]
33
- multiplex_instrumenters = schema.instrumenters[:multiplex]
34
-
35
- # First, run multiplex instrumentation, then query instrumentation for each query
36
- call_hooks(multiplex_instrumenters, multiplex, :before_multiplex, :after_multiplex) do
37
- each_query_call_hooks(query_instrumenters, queries) do
38
- schema = multiplex.schema
39
- multiplex_analyzers = schema.multiplex_analyzers
40
- queries = multiplex.queries
41
- if multiplex.max_complexity
42
- multiplex_analyzers += [GraphQL::Analysis::AST::MaxQueryComplexity]
43
- end
44
-
45
- schema.analysis_engine.analyze_multiplex(multiplex, multiplex_analyzers)
46
- begin
47
- # Since this is basically the batching context,
48
- # share it for a whole multiplex
49
- multiplex.context[:interpreter_instance] ||= multiplex.schema.query_execution_strategy.new
50
- # Do as much eager evaluation of the query as possible
51
- results = []
52
- queries.each_with_index do |query, idx|
53
- multiplex.dataloader.append_job {
54
- operation = query.selected_operation
55
- result =
56
- # MONKEY PATCH START
57
- if query.persisted_query_not_found?
58
- query.context.errors.clear
59
- query.context.errors << GraphQL::ExecutionError.new("PersistedQueryNotFound")
60
- singleton_class::NO_OPERATION
61
- # MONKEY PATCH END
62
- elsif operation.nil? || !query.valid? || query.context.errors.any?
63
- singleton_class::NO_OPERATION
64
- else
65
- begin
66
- # Although queries in a multiplex _share_ an Interpreter instance,
67
- # they also have another item of state, which is private to that query
68
- # in particular, assign it here:
69
- runtime = GraphQL::Execution::Interpreter::Runtime.new(query: query)
70
- query.context.namespace(:interpreter)[:runtime] = runtime
71
-
72
- query.trace("execute_query", {query: query}) do
73
- runtime.run_eager
74
- end
75
- rescue GraphQL::ExecutionError => err
76
- query.context.errors << err
77
- singleton_class::NO_OPERATION
78
- end
79
- end
80
- results[idx] = result
81
- }
82
- end
83
-
84
- multiplex.dataloader.run
85
-
86
- # Then, work through lazy results in a breadth-first way
87
- multiplex.dataloader.append_job {
88
- tracer = multiplex
89
- query = multiplex.queries.length == 1 ? multiplex.queries[0] : nil
90
- queries = multiplex ? multiplex.queries : [query]
91
- final_values = queries.map do |query|
92
- runtime = query.context.namespace(:interpreter)[:runtime]
93
- # it might not be present if the query has an error
94
- runtime ? runtime.final_result : nil
95
- end
96
- final_values.compact!
97
- tracer.trace("execute_query_lazy", {multiplex: multiplex, query: query}) do
98
- GraphQL::Execution::Interpreter::Resolve.resolve_all(final_values, multiplex.dataloader)
99
- end
100
- queries.each do |query|
101
- runtime = query.context.namespace(:interpreter)[:runtime]
102
- if runtime
103
- runtime.delete_interpreter_context(:current_path)
104
- runtime.delete_interpreter_context(:current_field)
105
- runtime.delete_interpreter_context(:current_object)
106
- runtime.delete_interpreter_context(:current_arguments)
107
- end
108
- end
109
- }
110
- multiplex.dataloader.run
111
-
112
- # Then, find all errors and assign the result to the query object
113
- results.each_with_index do |data_result, idx|
114
- query = queries[idx]
115
- # Assign the result so that it can be accessed in instrumentation
116
- query.result_values = if data_result.equal?(singleton_class::NO_OPERATION)
117
- if !query.valid? || query.context.errors.any?
118
- # A bit weird, but `Query#static_errors` _includes_ `query.context.errors`
119
- { "errors" => query.static_errors.map(&:to_h) }
120
- else
121
- data_result
122
- end
123
- else
124
- result = {
125
- "data" => query.context.namespace(:interpreter)[:runtime].final_result
126
- }
127
-
128
- if query.context.errors.any?
129
- error_result = query.context.errors.map(&:to_h)
130
- result["errors"] = error_result
131
- end
132
-
133
- result
134
- end
135
- if query.context.namespace?(:__query_result_extensions__)
136
- query.result_values["extensions"] = query.context.namespace(:__query_result_extensions__)
137
- end
138
- # Get the Query::Result, not the Hash
139
- results[idx] = query.result
140
- end
141
-
142
- results
143
- rescue Exception
144
- # TODO rescue at a higher level so it will catch errors in analysis, too
145
- # Assign values here so that the query's `@executed` becomes true
146
- queries.map { |q| q.result_values ||= {} }
147
- raise
148
- end
149
- end
150
- end
151
- end
152
- end
153
- end
154
- end
155
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Layout/IndentationWidth
156
- # rubocop:enable Metrics/PerceivedComplexity, Metrics/ModuleLength, Metrics/LineLength
157
- # rubocop:enable Metrics/BlockLength, Style/BracesAroundHashParameters, Style/CommentAnnotation
158
- # rubocop:enable Naming/RescuedExceptionsVariableName, Layout/SpaceInsideHashLiteralBraces
159
- # rubocop:enable Lint/ShadowingOuterLocalVariable, Style/BlockDelimiters, Metrics/MethodLength
160
- # rubocop:enable Style/Next, Layout/ElseAlignment, Layout/EndAlignment, Lint/RescueException
161
- end
162
- end