graph_weaver 0.4.0 → 0.4.6

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.
@@ -32,6 +32,13 @@ module GraphWeaver
32
32
  def initialize(url_or_connection, headers: {}, &block)
33
33
  @connection = case url_or_connection
34
34
  when ::Faraday::Connection
35
+ # a prebuilt connection carries its own headers/middleware, so
36
+ # headers:/block would be silently dropped — fail loudly instead
37
+ unless headers.empty? && block.nil?
38
+ raise ArgumentError,
39
+ "headers:/block are ignored when passing a prebuilt Faraday::Connection — configure them on it"
40
+ end
41
+
35
42
  url_or_connection
36
43
  else
37
44
  # Faraday appends the default adapter when the block doesn't set one
@@ -62,15 +62,18 @@ class GraphWeaver::Transport
62
62
  # envelope so QueryError machinery sees the structured errors; only
63
63
  # a body that isn't GraphQL (proxy pages, HTML 500s) is a ServerError.
64
64
  unless (200..299).cover?(status)
65
- return parsed if parsed.is_a?(Hash) && parsed.key?("errors")
65
+ # only a body carrying actual GraphQL errors flows through — a 4xx with
66
+ # `"errors": null` (or []) isn't a structured error response, so the
67
+ # status stays the signal
68
+ return parsed if parsed.is_a?(Hash) && parsed["errors"].is_a?(Array) && parsed["errors"].any?
66
69
 
67
70
  raise GraphWeaver::ServerError.new(status:, body: body.to_s)
68
71
  end
69
72
 
70
- unless parsed
71
- # a 200 that isn't GraphQL — an HTML error page from a proxy, a
72
- # captive portal: the server misbehaved, classify it that way
73
- raise GraphWeaver::ServerError.new(status:, body: "non-JSON response: #{body.to_s[0, 500]}")
73
+ unless parsed.is_a?(Hash)
74
+ # a 200 that isn't a GraphQL object — an HTML error page from a proxy, a
75
+ # captive portal, or a bare JSON array/string: the server misbehaved
76
+ raise GraphWeaver::ServerError.new(status:, body: "non-GraphQL response: #{body.to_s[0, 500]}")
74
77
  end
75
78
 
76
79
  parsed
@@ -1,3 +1,3 @@
1
1
  module GraphWeaver
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.6"
3
3
  end
data/lib/graph_weaver.rb CHANGED
@@ -17,9 +17,6 @@ require_relative "graph_weaver/railtie" if defined?(::Rails::Railtie)
17
17
 
18
18
  # opt-in extras:
19
19
  # require "graph_weaver/transport/faraday" # Faraday transport
20
- # require "graph_weaver/directive_defaults_patch" # fix graphql-ruby
21
- # dropping directive argument defaults when loading SDL (needed for
22
- # Apollo supergraph SDL until rmosolgo/graphql-ruby#5659 ships)
23
20
  module GraphWeaver
24
21
  class << self
25
22
  # A client for one GraphQL server — transport, schema, and scoped
@@ -296,6 +293,15 @@ module GraphWeaver
296
293
  # (`class Module; include T::Sig`) — extracted so it's stubbable in tests.
297
294
  def global_tsig? = Module.include?(T::Sig)
298
295
 
296
+ # The closest entry in `dictionary` to `term` — a "did you mean" suggestion,
297
+ # or nil (also nil when did_you_mean isn't loadable). One home for the guard
298
+ # used by codegen validation, alias resolution, and the runtime prop hints.
299
+ def did_you_mean(dictionary, term)
300
+ return unless defined?(DidYouMean::SpellChecker)
301
+
302
+ DidYouMean::SpellChecker.new(dictionary: dictionary).correct(term).first
303
+ end
304
+
299
305
  # Teach the generator how a GraphQL custom scalar deserializes into a
300
306
  # rich Ruby object (and serializes back onto the wire when used as a
301
307
  # variable):
@@ -348,13 +354,15 @@ module GraphWeaver
348
354
  end
349
355
 
350
356
  # Include app-owned helper modules into every struct generated from a
351
- # GraphQL type — derived values live as methods next to the honest
352
- # wire data, and srb tc checks them against each query's selection:
357
+ # GraphQL type — derived values live as methods next to the honest wire
358
+ # data, on the struct at runtime (fakes/cassettes included):
353
359
  #
354
360
  # GraphWeaver.extend_type("Pet", PetHelpers)
355
361
  #
356
- # Or build the mixin inline with a block (module_eval'd into an
357
- # auto-named module quick, but invisible to srb tc):
362
+ # A helper that reads a wire field is checked by srb tc in the module's
363
+ # own scope, not the struct's, so the field won't resolve — write it
364
+ # # typed: false or reach it via T.unsafe(self). Or build the mixin inline
365
+ # with a block (module_eval'd into an auto-named module — invisible to srb):
358
366
  #
359
367
  # GraphWeaver.extend_type("Pet") do
360
368
  # def display_name = "#{name} the pet"
@@ -362,8 +370,8 @@ module GraphWeaver
362
370
  #
363
371
  # Additive (repeated and client-scoped registrations stack). Global;
364
372
  # client.extend_type scopes to one client.
365
- def extend_type(graphql_name, *mixins, requires: nil, &block)
366
- Codegen.extend_type(graphql_name, *mixins, requires:, &block)
373
+ def extend_type(graphql_name, *mixins, requires: nil, **kw, &block)
374
+ Codegen.extend_type(graphql_name, *mixins, requires:, **kw, &block)
367
375
  end
368
376
 
369
377
  # Restore the built-in scalars, dropping every custom registration —
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graph_weaver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Pepper
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '2'
18
+ version: 2.6.7
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: '2'
25
+ version: 2.6.7
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: sorbet-runtime
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -253,7 +253,6 @@ files:
253
253
  - lib/graph_weaver/codegen/enum_type.rb
254
254
  - lib/graph_weaver/codegen/nodes.rb
255
255
  - lib/graph_weaver/codegen/scalar_type.rb
256
- - lib/graph_weaver/directive_defaults_patch.rb
257
256
  - lib/graph_weaver/errors.rb
258
257
  - lib/graph_weaver/hints.rb
259
258
  - lib/graph_weaver/inflect.rb
@@ -1,32 +0,0 @@
1
- # typed: false — monkeypatch; `self.class` resolves against the prepended host
2
- # frozen_string_literal: true
3
-
4
- require "graphql"
5
-
6
- # graphql-ruby's SDL builder (BuildFromDefinition#prepare_directives)
7
- # passes only the directive arguments present at the usage site, but
8
- # Directive#initialize validates ALL defined arguments — so a defaulted
9
- # non-null argument (`extension: Boolean! = false`) raises
10
- # InvalidArgumentError when omitted, even though the SDL spec makes it
11
- # optional. Real Apollo supergraph SDL (join v0.3) hits this on every
12
- # @join__type usage.
13
- #
14
- # Fill in the declared defaults before validation. This is what upstream
15
- # should do; present in graphql 2.6.3 (latest at time of writing).
16
- #
17
- # TODO: delete this file (and its requires) once
18
- # https://github.com/rmosolgo/graphql-ruby/pull/5659 lands in a released
19
- # graphql version and the Gemfile picks it up.
20
- module DirectiveDefaultsPatch
21
- def initialize(owner, **arguments)
22
- self.class.all_argument_definitions.each do |arg_defn|
23
- if !arguments.key?(arg_defn.keyword) && arg_defn.default_value?
24
- arguments[arg_defn.keyword] = arg_defn.default_value
25
- end
26
- end
27
-
28
- super(owner, **arguments)
29
- end
30
- end
31
-
32
- GraphQL::Schema::Directive.prepend(DirectiveDefaultsPatch)