graph_weaver 0.5.0 → 0.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 +4 -4
- data/CHANGELOG.md +537 -0
- data/Gemfile.lock +19 -19
- data/README.md +74 -53
- data/docs/cassettes.md +29 -4
- data/docs/editors.md +3 -1
- data/docs/errors.md +75 -16
- data/docs/federation.md +206 -155
- data/docs/generated_modules.md +223 -166
- data/docs/getting_started.md +106 -82
- data/docs/logging.md +35 -5
- data/docs/scalars.md +119 -24
- data/docs/testing.md +196 -155
- data/docs/transports.md +47 -19
- data/docs/upgrading.md +243 -22
- data/graph_weaver.gemspec +16 -2
- data/lib/generators/graph_weaver/install_generator.rb +31 -16
- data/lib/graph_weaver/client.rb +52 -15
- data/lib/graph_weaver/codegen/aliases.rb +15 -8
- data/lib/graph_weaver/codegen/emit.rb +107 -42
- data/lib/graph_weaver/codegen/enum_type.rb +4 -3
- data/lib/graph_weaver/codegen/nodes.rb +42 -21
- data/lib/graph_weaver/codegen/scalar_type.rb +87 -83
- data/lib/graph_weaver/codegen/type_helpers.rb +2 -3
- data/lib/graph_weaver/codegen.rb +382 -105
- data/lib/graph_weaver/coerce.rb +113 -0
- data/lib/graph_weaver/errors.rb +57 -13
- data/lib/graph_weaver/federation.rb +10 -22
- data/lib/graph_weaver/hints.rb +76 -2
- data/lib/graph_weaver/in_process.rb +11 -8
- data/lib/graph_weaver/inflect.rb +2 -0
- data/lib/graph_weaver/input_struct.rb +115 -12
- data/lib/graph_weaver/internal/overrides.rb +101 -0
- data/lib/graph_weaver/internal/planner.rb +868 -0
- data/lib/graph_weaver/internal/schemas.rb +50 -0
- data/lib/graph_weaver/internal/selection.rb +127 -0
- data/lib/graph_weaver/{testing → internal}/subgraphs.rb +45 -43
- data/lib/graph_weaver/internal/values.rb +181 -0
- data/lib/graph_weaver/internal.rb +206 -0
- data/lib/graph_weaver/logging.rb +108 -20
- data/lib/graph_weaver/parsing.rb +6 -13
- data/lib/graph_weaver/query_module.rb +2 -0
- data/lib/graph_weaver/railtie.rb +113 -14
- data/lib/graph_weaver/representation.rb +30 -2
- data/lib/graph_weaver/response.rb +15 -0
- data/lib/graph_weaver/retry.rb +54 -22
- data/lib/graph_weaver/rspec.rb +63 -18
- data/lib/graph_weaver/schema_diff.rb +293 -0
- data/lib/graph_weaver/schema_loader.rb +126 -35
- data/lib/graph_weaver/tasks.rb +88 -36
- data/lib/graph_weaver/testing/cassette.rb +131 -78
- data/lib/graph_weaver/testing/coverage.rb +11 -15
- data/lib/graph_weaver/testing/failure.rb +14 -8
- data/lib/graph_weaver/testing/fake_client.rb +253 -60
- data/lib/graph_weaver/testing/fake_subgraph.rb +19 -8
- data/lib/graph_weaver/testing/router.rb +147 -840
- data/lib/graph_weaver/testing.rb +40 -83
- data/lib/graph_weaver/transport/faraday.rb +1 -1
- data/lib/graph_weaver/transport/http.rb +29 -12
- data/lib/graph_weaver/transport.rb +11 -34
- data/lib/graph_weaver/version.rb +1 -1
- data/lib/graph_weaver.rb +221 -118
- metadata +17 -13
- data/CLAUDE.md +0 -161
- data/DECISIONS.md +0 -309
- data/Makefile +0 -23
- data/NOTES.md +0 -182
- data/PLAN.md +0 -115
- data/REVIEW.md +0 -946
- data/lib/graph_weaver/schemas.rb +0 -46
- data/lib/graph_weaver/selection.rb +0 -120
- data/lib/graph_weaver/testing/values.rb +0 -98
data/PLAN.md
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
# Project Plan — GraphWeaver, typed GraphQL client for Ruby/Sorbet
|
|
2
|
-
|
|
3
|
-
_Resume-from-here notes: where the project stands and what's next. The README
|
|
4
|
-
documents the product, CHANGELOG records what changed, DECISIONS.md records the
|
|
5
|
-
roads not taken, NOTES.md is the research notebook this grew out of. Update on
|
|
6
|
-
change._
|
|
7
|
-
|
|
8
|
-
## Vision
|
|
9
|
-
|
|
10
|
-
A "graphql-codegen for Ruby": `.graphql` queries + a schema (live class,
|
|
11
|
-
introspection JSON, SDL, or an Apollo supergraph) → checked-in `# typed: strict`
|
|
12
|
-
Ruby — nested `T::Struct`s, generated casting, a typed `execute` — so `srb tc`
|
|
13
|
-
sees the exact shape of every query result. Dynamic mode for consoles, a build
|
|
14
|
-
step for CI. Runtime deps: `graphql` + `sorbet-runtime`, nothing else.
|
|
15
|
-
|
|
16
|
-
## State
|
|
17
|
-
|
|
18
|
-
`0.4.6` on RubyGems. `main` carries a large unreleased body of work headed for
|
|
19
|
-
**0.5.0** — see `## Unreleased` in the CHANGELOG, which is long and has a real
|
|
20
|
-
upgrade story to tell.
|
|
21
|
-
|
|
22
|
-
Green gate is in `CLAUDE.md`; `make check` runs the core of it.
|
|
23
|
-
|
|
24
|
-
**What's built**, in brief — the CHANGELOG has the detail:
|
|
25
|
-
|
|
26
|
-
- **Codegen.** Queries and mutations, typed variable kwargs, fragments (inline,
|
|
27
|
-
named, shared across queries), unions and interfaces (a struct per named
|
|
28
|
-
condition plus a forward-compatible `Other`), enums as `T::Enum`, custom
|
|
29
|
-
scalars, `@skip`/`@include` nullability. Generated class names derive from the
|
|
30
|
-
response key, so they're stable under unrelated edits. Shared types live once
|
|
31
|
-
per schema in `GraphQLTypes`.
|
|
32
|
-
- **Sources.** Live schema class, introspection JSON, SDL, Apollo supergraph
|
|
33
|
-
(composition machinery stripped, `@inaccessible` subtracted to the API schema —
|
|
34
|
-
verified identical to Apollo's own `toAPISchema`), and raw subgraph SDL.
|
|
35
|
-
- **Transports.** `Transport::HTTP` (zero-dep, pooled, keep-alive) by default;
|
|
36
|
-
Faraday on explicit opt-in. `InProcess` wraps a live schema class with
|
|
37
|
-
`context:`, logging and branded errors. Composable `Retry` honouring
|
|
38
|
-
`Retry-After`. One instrumentation seam covering both paths.
|
|
39
|
-
- **Errors.** A typed `Response` envelope, an error hierarchy split by failure
|
|
40
|
-
site, field-level reporting with entity ids, `schema_stale?`, `#to_h`
|
|
41
|
-
throughout.
|
|
42
|
-
- **Testing.** Schema-correct fakes, failure simulation, anonymizing cassettes,
|
|
43
|
-
and an in-process federation router that runs real subgraph resolvers —
|
|
44
|
-
verified against a real `@apollo/gateway` (42 identical, 1 refused, 0 wrong),
|
|
45
|
-
refusing at plan time anything it can't answer faithfully. One rspec tag picks
|
|
46
|
-
the mode: `graphql: :fake | :in_process | :router`.
|
|
47
|
-
- **Lifecycle.** `generate` / `verify` / `schema:refresh` / `schema:diff` /
|
|
48
|
-
`queries:check` / `federation:diff`, plus `rails g graph_weaver:install`.
|
|
49
|
-
|
|
50
|
-
## Next
|
|
51
|
-
|
|
52
|
-
1. **Cut 0.5.0.** Needs an upgrade guide rather than a changelog dump — the
|
|
53
|
-
breaking list is long, but most of it is caught mechanically, so the guide is
|
|
54
|
-
largely *"regenerate, then follow `srb tc` and `verify_generated!`"*.
|
|
55
|
-
`gem push` needs an OTP.
|
|
56
|
-
2. **`extend_type`'s mixin forms can't be statically checked.** A mixin's method
|
|
57
|
-
bodies are checked in the module's scope, not the struct's, so the docs have
|
|
58
|
-
to recommend `# typed: false` or `T.unsafe(self)`. In a library whose pitch is
|
|
59
|
-
static checking, that's a seam worth a design pass. Note `alias:` — which
|
|
60
|
-
emits into the struct body — *is* checked, which suggests the mixin forms are
|
|
61
|
-
the ones carrying the cost.
|
|
62
|
-
3. **Nice-to-haves, unclaimed.** `write_timeout` on `Transport::HTTP` (and
|
|
63
|
-
possibly a `net_http:` passthrough rather than more kwargs); a Tapioca DSL
|
|
64
|
-
compiler so dynamic `parse` modules get static types without the build step.
|
|
65
|
-
|
|
66
|
-
## Federation router: what it still refuses
|
|
67
|
-
|
|
68
|
-
Each refuses at plan time with the type, field, subgraphs and next action. The
|
|
69
|
-
cost of moving each boundary, if a real query mix ever demands it:
|
|
70
|
-
|
|
71
|
-
- **`@requires` needing a chain** — the prefetch's own key must come from the
|
|
72
|
-
subgraph in hand; needs a real dependency DAG.
|
|
73
|
-
- **An abstract type the supergraph doesn't break down** — a union or interface
|
|
74
|
-
at a boundary now plans, one branch per concrete type, bucketed on
|
|
75
|
-
`__typename` at execution. What is left is the supergraph that doesn't say
|
|
76
|
-
which concrete types a subgraph answers it with — no
|
|
77
|
-
`@join__unionMember`/`@join__implements`, and the type in more than one
|
|
78
|
-
subgraph. Closing it means reading a join version that predates those
|
|
79
|
-
directives; a modern composition always carries them.
|
|
80
|
-
- **A nested field set no one fetch can build** — a nested field set now
|
|
81
|
-
crosses as the object it is, to any depth. What is left is the one whose
|
|
82
|
-
fields are split across subgraphs (`origin` in one and `origin.lat` in
|
|
83
|
-
another, or a `@key`'s object a `@requires` would half-fill from
|
|
84
|
-
elsewhere): a representation comes from one fetch, so the object would
|
|
85
|
-
arrive in pieces. Closing it means merging the pieces, which
|
|
86
|
-
`DECISIONS.md` argues against — the shapes that produce a split are the
|
|
87
|
-
ones where a real gateway stops being an oracle.
|
|
88
|
-
- **Mutation root fields spanning subgraphs** — root mutation fields run in
|
|
89
|
-
series, so grouping them would run them in plan order.
|
|
90
|
-
- **An alias shadowing an injected `@key`** — Apollo resolves the collision in
|
|
91
|
-
favour of its own key and a spec-conformant server doesn't, so there is no one
|
|
92
|
-
answer to agree with. Unfixable by design.
|
|
93
|
-
|
|
94
|
-
`rake graph_weaver:federation:coverage` reports the refusal rate against a real
|
|
95
|
-
supergraph and query set. That number decides whether any of the above is worth
|
|
96
|
-
building — on the demo corpus it is 17/17.
|
|
97
|
-
|
|
98
|
-
## Stated non-goals
|
|
99
|
-
|
|
100
|
-
Recorded so they read as decisions rather than omissions, with the reasoning in
|
|
101
|
-
`REVIEW.md` §7: subscriptions, `@defer`/`@stream`, file uploads, normalized
|
|
102
|
-
caching, fragment masking, request batching, and a watch mode.
|
|
103
|
-
|
|
104
|
-
## Gotchas worth remembering
|
|
105
|
-
|
|
106
|
-
- graphql-ruby's `to_definition`/`from_introspection` reorder enum values and
|
|
107
|
-
possible types — codegen sorts both; keep any new emission deterministic.
|
|
108
|
-
- Schemas built from introspection or SDL have no scalar coercion or resolvers,
|
|
109
|
-
so codegen stays name-keyed and never calls schema runtime hooks.
|
|
110
|
-
- A `SchemaDefinition` node reprints without its body when the root type names
|
|
111
|
-
are the GraphQL defaults, so directives on `schema` must be stripped before
|
|
112
|
-
reprinting a supergraph.
|
|
113
|
-
- Code the build doesn't exercise rots silently — integration specs excluded from
|
|
114
|
-
the default run, examples the generator skips, doc samples nobody executes.
|
|
115
|
-
Six fabricated doc samples were found in one session by running them.
|