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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +82 -0
- data/CLAUDE.md +1 -2
- data/Gemfile.lock +3 -3
- data/docs/federation.md +36 -58
- data/docs/generated_modules.md +33 -0
- data/docs/scalars.md +70 -9
- data/graph_weaver.gemspec +3 -1
- data/lib/graph_weaver/client.rb +5 -4
- data/lib/graph_weaver/codegen/emit.rb +17 -1
- data/lib/graph_weaver/codegen/enum_type.rb +63 -5
- data/lib/graph_weaver/codegen/nodes.rb +7 -3
- data/lib/graph_weaver/codegen/scalar_type.rb +4 -1
- data/lib/graph_weaver/codegen.rb +175 -18
- data/lib/graph_weaver/hints.rb +3 -5
- data/lib/graph_weaver/input_struct.rb +7 -0
- data/lib/graph_weaver/response.rb +8 -1
- data/lib/graph_weaver/schema_loader.rb +162 -2
- data/lib/graph_weaver/selection.rb +20 -3
- data/lib/graph_weaver/testing/cassette.rb +28 -3
- data/lib/graph_weaver/testing/fake_client.rb +18 -12
- data/lib/graph_weaver/transport/faraday.rb +7 -0
- data/lib/graph_weaver/transport.rb +8 -5
- data/lib/graph_weaver/version.rb +1 -1
- data/lib/graph_weaver.rb +17 -9
- metadata +3 -4
- data/lib/graph_weaver/directive_defaults_patch.rb +0 -32
|
@@ -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
|
-
|
|
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
|
|
73
|
-
raise GraphWeaver::ServerError.new(status:, body: "non-
|
|
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
|
data/lib/graph_weaver/version.rb
CHANGED
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
|
-
#
|
|
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
|
-
#
|
|
357
|
-
#
|
|
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.
|
|
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:
|
|
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:
|
|
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)
|