graph_weaver 0.7.5 → 0.7.7
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/Gemfile.lock +43 -43
- data/docs/errors.md +7 -3
- data/docs/generated_modules.md +66 -16
- data/docs/getting_started.md +39 -19
- data/docs/logging.md +79 -35
- data/docs/migrating.md +11 -4
- data/docs/scalars.md +12 -3
- data/docs/testing.md +75 -13
- data/docs/upgrading.md +43 -3
- data/examples/README.md +4 -2
- data/examples/github/generate.rb +22 -8
- data/examples/github/generated/star_mutation.rb +2 -2
- data/examples/github/generated/stargazers_query.rb +2 -2
- data/examples/github/generated/starred_query.rb +2 -2
- data/examples/github/run.rb +1 -0
- data/examples/github/setup.rb +16 -8
- data/graph_weaver.gemspec +15 -6
- data/lib/generators/graph_weaver/install_generator.rb +20 -2
- data/lib/graph_weaver/client.rb +0 -23
- data/lib/graph_weaver/codegen/aliases.rb +15 -3
- data/lib/graph_weaver/codegen/emit.rb +7 -6
- data/lib/graph_weaver/codegen/enum_type.rb +26 -2
- data/lib/graph_weaver/codegen/nodes.rb +21 -2
- data/lib/graph_weaver/codegen.rb +106 -54
- data/lib/graph_weaver/graph.rb +67 -6
- data/lib/graph_weaver/in_process.rb +1 -1
- data/lib/graph_weaver/input_struct.rb +29 -4
- data/lib/graph_weaver/internal/overrides.rb +126 -14
- data/lib/graph_weaver/internal/test_clients.rb +29 -7
- data/lib/graph_weaver/internal/unused.rb +30 -11
- data/lib/graph_weaver/internal/values.rb +17 -5
- data/lib/graph_weaver/internal.rb +23 -6
- data/lib/graph_weaver/log_subscriber.rb +27 -17
- data/lib/graph_weaver/logging.rb +89 -53
- data/lib/graph_weaver/parsing.rb +32 -3
- data/lib/graph_weaver/query_module.rb +48 -8
- data/lib/graph_weaver/railtie.rb +250 -11
- data/lib/graph_weaver/rspec.rb +41 -17
- data/lib/graph_weaver/schema_diff.rb +24 -5
- data/lib/graph_weaver/schema_loader.rb +22 -9
- data/lib/graph_weaver/tasks.rb +71 -44
- data/lib/graph_weaver/testing/fake_client.rb +24 -21
- data/lib/graph_weaver/testing.rb +27 -7
- data/lib/graph_weaver/transport.rb +1 -1
- data/lib/graph_weaver/version.rb +1 -1
- data/lib/graph_weaver.rb +76 -43
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a7b665c1263db52f315217a6298ff638d963b926e44f94c16dc2972de4140320
|
|
4
|
+
data.tar.gz: a9712a11f712adfa8846b180b1e22874f63d57fd00514d311b9cb0e60c9f6ebf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 693fa12dd8117988b35adcf7f88234b382bae9a8d82307a23ce7ffa3f2837c1304a529155dedab414691b13c3d982314cb70c8d5587660f0766988c7defc0f83
|
|
7
|
+
data.tar.gz: 2933a687d3c85faa3d514e6daddd5fe9ea62ee6e48f146e847f492a63e91b6c43c6986964f52f1fa458f1f6a60b92038058357e21062e966c47c8fef0a0235c4
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
graph_weaver (0.7.
|
|
4
|
+
graph_weaver (0.7.7)
|
|
5
5
|
graphql (>= 2.6.7)
|
|
6
6
|
sorbet-runtime
|
|
7
7
|
|
|
@@ -62,7 +62,7 @@ GEM
|
|
|
62
62
|
erubi (1.13.1)
|
|
63
63
|
faker (3.8.0)
|
|
64
64
|
i18n (>= 1.8.11, < 2)
|
|
65
|
-
faraday (2.14.
|
|
65
|
+
faraday (2.14.4)
|
|
66
66
|
faraday-net_http (>= 2.0, < 3.5)
|
|
67
67
|
json
|
|
68
68
|
logger
|
|
@@ -94,7 +94,7 @@ GEM
|
|
|
94
94
|
prism (>= 1.3.0)
|
|
95
95
|
rdoc (>= 4.0.0)
|
|
96
96
|
reline (>= 0.4.2)
|
|
97
|
-
json (
|
|
97
|
+
json (3.0.2)
|
|
98
98
|
logger (1.7.0)
|
|
99
99
|
loofah (2.25.2)
|
|
100
100
|
crass (~> 1.0.2)
|
|
@@ -124,7 +124,7 @@ GEM
|
|
|
124
124
|
racc (~> 1.4)
|
|
125
125
|
nokogiri (1.19.4-x86_64-linux-gnu)
|
|
126
126
|
racc (~> 1.4)
|
|
127
|
-
parallel (2.
|
|
127
|
+
parallel (2.2.0)
|
|
128
128
|
parser (3.3.12.0)
|
|
129
129
|
ast (~> 2.4.1)
|
|
130
130
|
racc
|
|
@@ -159,10 +159,10 @@ GEM
|
|
|
159
159
|
tsort (>= 0.2)
|
|
160
160
|
zeitwerk (~> 2.6)
|
|
161
161
|
rake (13.4.2)
|
|
162
|
-
rbi (0.3
|
|
162
|
+
rbi (0.4.3)
|
|
163
163
|
prism (~> 1.0)
|
|
164
164
|
rbs (>= 4.0.1)
|
|
165
|
-
rbs (4.0
|
|
165
|
+
rbs (4.2.0)
|
|
166
166
|
logger
|
|
167
167
|
prism (>= 1.6.0)
|
|
168
168
|
tsort
|
|
@@ -175,7 +175,7 @@ GEM
|
|
|
175
175
|
regexp_parser (2.12.0)
|
|
176
176
|
reline (0.6.3)
|
|
177
177
|
io-console (~> 0.5)
|
|
178
|
-
require-hooks (0.
|
|
178
|
+
require-hooks (0.5.1)
|
|
179
179
|
rexml (3.4.4)
|
|
180
180
|
rspec (3.13.2)
|
|
181
181
|
rspec-core (~> 3.13.0)
|
|
@@ -190,35 +190,35 @@ GEM
|
|
|
190
190
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
191
191
|
rspec-support (~> 3.13.0)
|
|
192
192
|
rspec-support (3.13.7)
|
|
193
|
-
rubydex (0.
|
|
194
|
-
rubydex (0.
|
|
195
|
-
rubydex (0.
|
|
196
|
-
rubydex (0.
|
|
193
|
+
rubydex (0.4.1-aarch64-linux)
|
|
194
|
+
rubydex (0.4.1-arm64-darwin)
|
|
195
|
+
rubydex (0.4.1-x86_64-darwin)
|
|
196
|
+
rubydex (0.4.1-x86_64-linux)
|
|
197
197
|
securerandom (0.4.1)
|
|
198
198
|
simplecov (1.3.0)
|
|
199
|
-
sorbet (0.6.
|
|
200
|
-
sorbet-static (= 0.6.
|
|
201
|
-
sorbet-runtime (0.6.
|
|
202
|
-
sorbet-static (0.6.
|
|
203
|
-
sorbet-static (0.6.
|
|
204
|
-
sorbet-static (0.6.
|
|
205
|
-
sorbet-static-and-runtime (0.6.
|
|
206
|
-
sorbet (= 0.6.
|
|
207
|
-
sorbet-runtime (= 0.6.
|
|
208
|
-
spoom (1.8.
|
|
199
|
+
sorbet (0.6.13506)
|
|
200
|
+
sorbet-static (= 0.6.13506)
|
|
201
|
+
sorbet-runtime (0.6.13506)
|
|
202
|
+
sorbet-static (0.6.13506-aarch64-linux)
|
|
203
|
+
sorbet-static (0.6.13506-universal-darwin)
|
|
204
|
+
sorbet-static (0.6.13506-x86_64-linux)
|
|
205
|
+
sorbet-static-and-runtime (0.6.13506)
|
|
206
|
+
sorbet (= 0.6.13506)
|
|
207
|
+
sorbet-runtime (= 0.6.13506)
|
|
208
|
+
spoom (1.8.7)
|
|
209
209
|
erubi (>= 1.10.0)
|
|
210
210
|
prism (>= 0.28.0)
|
|
211
|
-
rbi (>= 0.
|
|
211
|
+
rbi (>= 0.4.2)
|
|
212
212
|
rbs (>= 4.0.0.dev.5)
|
|
213
213
|
rexml (>= 3.2.6)
|
|
214
214
|
sorbet-static-and-runtime (>= 0.5.10187)
|
|
215
215
|
thor (>= 0.19.2)
|
|
216
|
-
tapioca (0.
|
|
216
|
+
tapioca (0.20.0)
|
|
217
217
|
benchmark
|
|
218
218
|
bundler (>= 2.2.25)
|
|
219
219
|
netrc (>= 0.11.0)
|
|
220
220
|
parallel (>= 1.21.0)
|
|
221
|
-
rbi (>= 0.
|
|
221
|
+
rbi (>= 0.4.1)
|
|
222
222
|
require-hooks (>= 0.2.2)
|
|
223
223
|
rubydex (>= 0.1.0.beta10)
|
|
224
224
|
sorbet-static-and-runtime (>= 0.6.12698)
|
|
@@ -292,20 +292,20 @@ CHECKSUMS
|
|
|
292
292
|
erb (6.0.4) sha256=38e3803694be357fe2bfe312487c74beaf9fb4e5beb3e22498952fe1645b95d9
|
|
293
293
|
erubi (1.13.1) sha256=a082103b0885dbc5ecf1172fede897f9ebdb745a4b97a5e8dc63953db1ee4ad9
|
|
294
294
|
faker (3.8.0) sha256=c147b308df73a90f27a4fc84f18d4c22ef0ad9c2a64b2b61c86fd0ca71753efc
|
|
295
|
-
faraday (2.14.
|
|
295
|
+
faraday (2.14.4) sha256=9bb4408c44621b0dbaaaa39e5dbfc4dbe58cc6751b6eb94d16ae9e1f2f2fab6e
|
|
296
296
|
faraday-net_http (3.4.4) sha256=0e78af151747ed1b00f33e25973b4bc220d7f16c00c39676817c8b12331eb588
|
|
297
297
|
fiber-storage (1.0.1) sha256=f48e5b6d8b0be96dac486332b55cee82240057065dc761c1ea692b2e719240e1
|
|
298
298
|
google-protobuf (4.35.1-aarch64-linux-gnu) sha256=50ca44d0eeff3f8475e630a1accdd974256f3510694d574e2c9d6119ea8bc9e1
|
|
299
299
|
google-protobuf (4.35.1-arm64-darwin) sha256=d9c957df04fa89c749fa9a72a7b383eb4296efc9b2303dc6fd6fbe39c698ad6b
|
|
300
300
|
google-protobuf (4.35.1-x86_64-darwin) sha256=66b62b4df00931018a692806df66393efa960d6d2b7da69735187249f950d3ee
|
|
301
301
|
google-protobuf (4.35.1-x86_64-linux-gnu) sha256=c786439087512a3fbd199e9897d265b855f951d4027e218ea55e858d45969edd
|
|
302
|
-
graph_weaver (0.7.
|
|
302
|
+
graph_weaver (0.7.7)
|
|
303
303
|
graphql (2.6.10) sha256=9b7c8633767f516ff9d48a8d6305b2a00a2101c82aa871b92e69086944f9f83e
|
|
304
304
|
hashdiff (1.2.1) sha256=9c079dbc513dfc8833ab59c0c2d8f230fa28499cc5efb4b8dd276cf931457cd1
|
|
305
305
|
i18n (1.15.2) sha256=00f9eb62412fe593b2a65a97daa75300d37abb8f7202ec748e94b6d46a9dd1b5
|
|
306
306
|
io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc
|
|
307
307
|
irb (1.18.0) sha256=de9454a0703a54704b9811a5ef31a60c86949fbf4013fcf244fabc7c775248e3
|
|
308
|
-
json (
|
|
308
|
+
json (3.0.2) sha256=8e6d7e7b11384c21230430cef90b71f14849a34a1f4452796670f7c981bd19df
|
|
309
309
|
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
|
|
310
310
|
loofah (2.25.2) sha256=2007f746959ac65552456e04b433e83deb22759ab38c838b4445c70e43425918
|
|
311
311
|
minitest (6.0.6) sha256=153ea36d1d987a62942382b61075745042a2b3123b1cd48f4c3675af9cc7d6f1
|
|
@@ -317,7 +317,7 @@ CHECKSUMS
|
|
|
317
317
|
nokogiri (1.19.4-arm64-darwin) sha256=a46db9853286e6597b36ebc6953817d15acf3a299583eb3f89fdc6f91dd63527
|
|
318
318
|
nokogiri (1.19.4-x86_64-darwin) sha256=7fd17057d3e1f00e9954a74b3cd76595d3d4a5ef233b7ed9599047c204f70551
|
|
319
319
|
nokogiri (1.19.4-x86_64-linux-gnu) sha256=379fae440b28915e3f19d752ce2dcf8465ed2b2fbefd2a7ca0dd497bc981a06a
|
|
320
|
-
parallel (2.
|
|
320
|
+
parallel (2.2.0) sha256=e1059c5fd7b649558a0aec38a769f06a42942bdb40503d005a59c352fe011cd8
|
|
321
321
|
parser (3.3.12.0) sha256=21a6d7f755d5a24dfbdc6e6b772e4e879a52e7631a88bc5a3a134606052c9828
|
|
322
322
|
pp (0.6.4) sha256=dfcb0fce700c41456265922884f9fe195d7fbb0674a3578e6c0f69588e82b570
|
|
323
323
|
prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193
|
|
@@ -332,33 +332,33 @@ CHECKSUMS
|
|
|
332
332
|
rails-html-sanitizer (1.7.1) sha256=e797a7c9b01e567307e317c576b49ab4168017e63eea4dba9ce3cb587e2f22c2
|
|
333
333
|
railties (8.1.3.1) sha256=2388a232579a00cefea4487de66c8553c3408c1300abdc6cf1799d86ffb04487
|
|
334
334
|
rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
|
|
335
|
-
rbi (0.3
|
|
336
|
-
rbs (4.0
|
|
335
|
+
rbi (0.4.3) sha256=cc090ae62c3246412b992954f54077d6046c9b04f1537a4d24bfae8714503eac
|
|
336
|
+
rbs (4.2.0) sha256=51f7b886dcc05bc09e10b901daa6a81829f6adc03101d6ca9ea4aac6103e0674
|
|
337
337
|
rdoc (8.0.0) sha256=03bf8c08a9639658855a0cfd77c0abca8325c227693f7f33f82957811348c469
|
|
338
338
|
redcarpet (3.6.1) sha256=d444910e6aa55480c6bcdc0cdb057626e8a32c054c29e793fa642ba2f155f445
|
|
339
339
|
regexp_parser (2.12.0) sha256=35a916a1d63190ab5c9009457136ae5f3c0c7512d60291d0d1378ba18ce08ebb
|
|
340
340
|
reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835
|
|
341
|
-
require-hooks (0.
|
|
341
|
+
require-hooks (0.5.1) sha256=49a6b14518b91c5b8006d0644ef257af0ca033df23625bd4e314a8c5282191d9
|
|
342
342
|
rexml (3.4.4) sha256=19e0a2c3425dfbf2d4fc1189747bdb2f849b6c5e74180401b15734bc97b5d142
|
|
343
343
|
rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587
|
|
344
344
|
rspec-core (3.13.6) sha256=a8823c6411667b60a8bca135364351dda34cd55e44ff94c4be4633b37d828b2d
|
|
345
345
|
rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836
|
|
346
346
|
rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47
|
|
347
347
|
rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
|
|
348
|
-
rubydex (0.
|
|
349
|
-
rubydex (0.
|
|
350
|
-
rubydex (0.
|
|
351
|
-
rubydex (0.
|
|
348
|
+
rubydex (0.4.1-aarch64-linux) sha256=abc1c9eb22479f60dd015fa81373163c5a71f2700b76bced1282631686bd6271
|
|
349
|
+
rubydex (0.4.1-arm64-darwin) sha256=d23720253876d88fb98954e5d3a1ef9696a269697acf50e3ab53cdfbb2b66b96
|
|
350
|
+
rubydex (0.4.1-x86_64-darwin) sha256=a9681db5bc9be6a62f226d96d6889b6b600d0b09e7576391702aafd29912145b
|
|
351
|
+
rubydex (0.4.1-x86_64-linux) sha256=4e2c8398c9fc585485b54edd28f5ecf76b5a02255e177b6f8402e9d2afffd51b
|
|
352
352
|
securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
|
|
353
353
|
simplecov (1.3.0) sha256=d9886307863c1ead47657dcbed869bfffd82318808b09014d8f0ff77dcfe7492
|
|
354
|
-
sorbet (0.6.
|
|
355
|
-
sorbet-runtime (0.6.
|
|
356
|
-
sorbet-static (0.6.
|
|
357
|
-
sorbet-static (0.6.
|
|
358
|
-
sorbet-static (0.6.
|
|
359
|
-
sorbet-static-and-runtime (0.6.
|
|
360
|
-
spoom (1.8.
|
|
361
|
-
tapioca (0.
|
|
354
|
+
sorbet (0.6.13506) sha256=b6fd9f9ab2563c709b9308437cb40754e190667fddfe841723a7dda430978cd6
|
|
355
|
+
sorbet-runtime (0.6.13506) sha256=94a7ff795cf2a67818a954883c0301de0b7222a9f732b24ab30ea5253e7568f6
|
|
356
|
+
sorbet-static (0.6.13506-aarch64-linux) sha256=04405070206de265a87e6544454092cd4c7b275415dccf76a4ab41649819ae9f
|
|
357
|
+
sorbet-static (0.6.13506-universal-darwin) sha256=744918a125841c84d0804410bfda068a6dc8182285ba50ddb1e8ce5955b24700
|
|
358
|
+
sorbet-static (0.6.13506-x86_64-linux) sha256=b57d36d1db374e10109bbd5af3bec0edf6f94f3e86dbffe69199763909ad2c91
|
|
359
|
+
sorbet-static-and-runtime (0.6.13506) sha256=12c6abbc1d988267452c97e4cff75c563a480e3e8b7a1a633e2f714856e5c313
|
|
360
|
+
spoom (1.8.7) sha256=81960502cdf23aa991f015988aa5dd43325e23ae4318b8e00d541299cbdb70f6
|
|
361
|
+
tapioca (0.20.0) sha256=b375ed7bf51d2c86c09543eafedd0de85513634187c0f7a062615af8bb9347a0
|
|
362
362
|
thor (1.5.0) sha256=e3a9e55fe857e44859ce104a84675ab6e8cd59c650a49106a05f55f136425e73
|
|
363
363
|
tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f
|
|
364
364
|
tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b
|
data/docs/errors.md
CHANGED
|
@@ -106,6 +106,7 @@ subclass says where it failed:
|
|
|
106
106
|
| `InputError` | the variables wouldn't build into the generated input structs — unknown/typo'd key, missing required field, out-of-range enum, wrong-typed field, wrong number of @oneOf fields — `#kind`, `#path`, `#coordinate`, `#value`, `#details`, `#field`, `#struct` |
|
|
107
107
|
| `QueryValidationError` | build time: the query didn't validate against the schema |
|
|
108
108
|
| `Codegen::Aliases::UnknownSegment` | build time: an [`alias:`](generated_modules.md#flat-accessors-with-alias) path names a field no type here has — a typo, so `optional: true` won't skip it |
|
|
109
|
+
| `Codegen::Aliases::HoistedSegment` | build time: an [`alias:`](generated_modules.md#flat-accessors-with-alias) path reads *into* a struct [hoisted](generated_modules.md#a-shared-fragment-is-one-type) from a shared fragment — `optional: true` skips it, but only at the cost of the accessor for every query that spreads the fragment |
|
|
109
110
|
| `ConfigurationError` | setup judged against your schema — which Ruby schema serves which subgraph (`Testing::Router`, `federation:diff`) |
|
|
110
111
|
| `Testing::Unplannable` | the local test router won't plan this operation — `#category`, `#detail` |
|
|
111
112
|
| `Testing::MissingRecording` | a [cassette](cassettes.md) holds no entry for this request — the message prints the variables, and the ones it did record |
|
|
@@ -219,9 +220,12 @@ a form keyed on `e.field` finds the same slot for a refusal raised before the
|
|
|
219
220
|
request left and for one the server sent back.
|
|
220
221
|
|
|
221
222
|
The **prop** (`issued_on`) is what you type in Ruby — `.new`, `.coerce`, the kwargs
|
|
222
|
-
of `execute` — and it is `#message`, the developer's line, that names it
|
|
223
|
-
|
|
224
|
-
the
|
|
223
|
+
of `execute` — and it is `#message`, the developer's line, that names it, with the
|
|
224
|
+
schema's spelling beside it where the two differ (`issued_on (issuedOn): expected
|
|
225
|
+
a String`): the prop is what you fix, and the wire name is what you grep the
|
|
226
|
+
`.graphql` for. In a Rails form the field names are the props, so underscore on
|
|
227
|
+
the way in — and give the nil case a home, because **`#field` is `nil` whenever
|
|
228
|
+
nothing named a slot**:
|
|
225
229
|
|
|
226
230
|
```ruby
|
|
227
231
|
form.errors.add(e.field&.underscore || :base, render_input_error(e))
|
data/docs/generated_modules.md
CHANGED
|
@@ -142,7 +142,9 @@ file, and `verify` fails until you regenerate.
|
|
|
142
142
|
**A graph's `namespace:` nests what it generates**, and is the answer when two
|
|
143
143
|
schemas in one app each have a `person.graphql`: `namespace: "Billing"` makes
|
|
144
144
|
that one `Billing::PersonQuery` in the same `person_query.rb`, and its shared
|
|
145
|
-
types module `Billing::
|
|
145
|
+
types module `Billing::Types` (plain `Types` inside a namespace, where nothing
|
|
146
|
+
collides with graphql-ruby's own `Types::`; `GraphQLTypes` without one). Nothing
|
|
147
|
+
else about the rule changes. See
|
|
146
148
|
[getting started](getting_started.md#more-than-one-schema).
|
|
147
149
|
|
|
148
150
|
Parsing a raw query *string* has no file to name it after, so it uses the
|
|
@@ -461,10 +463,12 @@ off `__typename` when the selection carries one unaliased and unguarded, and off
|
|
|
461
463
|
narrowed fragment, or one whose `__typename` is itself guarded, is refused: a
|
|
462
464
|
match would be indistinguishable from a miss.
|
|
463
465
|
|
|
464
|
-
A whole
|
|
466
|
+
A whole abstract field selected as one named *shared* fragment
|
|
465
467
|
(`{ ...FeedItemFields }`) is [hoisted](#a-shared-fragment-is-one-type) into
|
|
466
|
-
`GraphQLTypes` like any other,
|
|
467
|
-
|
|
468
|
+
`GraphQLTypes` like any other, in whichever of the three shapes above the
|
|
469
|
+
fragment has — a dispatch module, one struct, or a nilable narrowed struct. So
|
|
470
|
+
which shape it is never decides whether consuming queries share a type, and
|
|
471
|
+
adding a second `... on` to a shared fragment doesn't move their constant.
|
|
468
472
|
|
|
469
473
|
### Consuming a union — dispatch on the class, not `__typename`
|
|
470
474
|
|
|
@@ -673,7 +677,7 @@ to replace it; what the *example* says still wins.
|
|
|
673
677
|
generated module). A generated file says nothing about transport — only a private
|
|
674
678
|
`GRAPH` naming its graph, which is also how `graphql: :fake` fabricates each
|
|
675
679
|
module's own schema with two graphs in play, and the
|
|
676
|
-
`:graph` on every [instrumentation event](logging.md#
|
|
680
|
+
`:graph` on every [instrumentation event](logging.md#instrumentation) the module's
|
|
677
681
|
`execute` produces.
|
|
678
682
|
|
|
679
683
|
## Deserializing a response from another client
|
|
@@ -831,10 +835,8 @@ has the other attributes it reads.
|
|
|
831
835
|
|
|
832
836
|
### Loading what it wrote
|
|
833
837
|
|
|
834
|
-
In Rails, loading is automatic — the
|
|
835
|
-
|
|
836
|
-
in a `to_prepare` block, and again after each development reload. Elsewhere it's
|
|
837
|
-
explicit, factory_bot-style:
|
|
838
|
+
In Rails, loading is automatic — [one rule](#the-rule-in-rails) decides whether
|
|
839
|
+
Zeitwerk does it or the Railtie does. Elsewhere it's explicit, factory_bot-style:
|
|
838
840
|
`GraphWeaver.load_generated!` requires every file under `generated_paths`.
|
|
839
841
|
|
|
840
842
|
**Outside Rails, four things have to agree**, and nothing wires them together for
|
|
@@ -848,8 +850,10 @@ you — a script that generates its own modules sets all four:
|
|
|
848
850
|
other [client](#clients) to reach for.
|
|
849
851
|
|
|
850
852
|
Miss (3) and the script gets a `NameError` for its own module; miss (4) and it
|
|
851
|
-
gets `
|
|
852
|
-
|
|
853
|
+
gets `no client configured — set GraphWeaver.client= or pass a client` from a
|
|
854
|
+
module that otherwise looks fine. Set the slot to something that can't execute
|
|
855
|
+
and the module names the contract instead: `PersonQuery: client must respond to
|
|
856
|
+
#execute(query, variables:, operation_name:), got Hash`.
|
|
853
857
|
|
|
854
858
|
Every directory setting is a list — `queries_paths`, `generated_paths`,
|
|
855
859
|
`fragments_paths` — and every entry is read (entries may be globs; the generated
|
|
@@ -861,11 +865,57 @@ list would name a dump nothing ever opens. A relative path resolves against
|
|
|
861
865
|
`GraphWeaver.root` — `Rails.root` in a Rails app, the working directory otherwise
|
|
862
866
|
— so where you started the process doesn't change which files it reads.
|
|
863
867
|
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
868
|
+
#### The rule in Rails
|
|
869
|
+
|
|
870
|
+
**A generated tree Zeitwerk would name correctly is left to Zeitwerk; any other
|
|
871
|
+
is hidden from it and required at boot.**
|
|
872
|
+
|
|
873
|
+
The conventional layout is the second one: `generated/person_query.rb` defines
|
|
874
|
+
`::PersonQuery` where Zeitwerk reads `Generated::PersonQuery` off the path. So
|
|
875
|
+
the Railtie hides that directory from the autoloader and requires every file at
|
|
876
|
+
the end of boot — after your initializers and after any `to_prepare`
|
|
877
|
+
registrations of your own, and again after each development reload.
|
|
878
|
+
|
|
879
|
+
A tree is named correctly when the graph's [`namespace`](getting_started.md#more-than-one-schema)
|
|
880
|
+
is the constant its output path spells:
|
|
881
|
+
|
|
882
|
+
```ruby
|
|
883
|
+
GraphWeaver.graph :reports do
|
|
884
|
+
output "app/graphql/queries/reports/generated"
|
|
885
|
+
namespace "Queries::Reports::Generated"
|
|
886
|
+
end
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
`report_query.rb` then defines `Queries::Reports::Generated::ReportQuery`, which
|
|
890
|
+
is exactly what Zeitwerk expects there — your own `inflect`/`acronym` rules
|
|
891
|
+
included, since graph_weaver asks the loader rather than guessing. Nothing is
|
|
892
|
+
hidden and nothing is required: the modules autoload on first reference and
|
|
893
|
+
reload with the rest of the app, and **no part of the parent namespace chain is
|
|
894
|
+
defined until a query is used**. Leave `types_module` unset for it — the shared
|
|
895
|
+
manifest is `types.rb`, which Zeitwerk reads as `<Namespace>::Types`, and `Types`
|
|
896
|
+
is what a namespaced graph already calls it.
|
|
897
|
+
|
|
898
|
+
The Railtie says which side each graph fell on, one line apiece at debug, naming
|
|
899
|
+
the constant that disagreed:
|
|
900
|
+
|
|
901
|
+
```
|
|
902
|
+
graph :reports's output app/graphql/queries/reports/generated is hidden from
|
|
903
|
+
Zeitwerk and required at boot — types.rb defines …::GraphQLTypes, Zeitwerk
|
|
904
|
+
expects …::Types
|
|
905
|
+
```
|
|
906
|
+
|
|
907
|
+
**The settings have two lifetimes.** `schema`, `queries`, `output` and
|
|
908
|
+
`namespace` matter only when `generate`/`verify` runs. `extend_type`,
|
|
909
|
+
`register_scalar` and `register_enum` are needed wherever generated code *loads*
|
|
910
|
+
— which under autoloading is the first request that uses a query, long after
|
|
911
|
+
boot. So generation settings can live wherever generation happens, and
|
|
912
|
+
registrations belong in `config/initializers` or a `to_prepare` block, where
|
|
913
|
+
every boot runs them.
|
|
914
|
+
|
|
915
|
+
In development a query edit regenerates and reloads before the next request;
|
|
916
|
+
everywhere else generated code changes only on regeneration — restart, like a
|
|
917
|
+
schema migration, or call `GraphWeaver.reload_generated!` after regenerating in
|
|
918
|
+
another terminal.
|
|
869
919
|
|
|
870
920
|
## Dynamic mode
|
|
871
921
|
|
data/docs/getting_started.md
CHANGED
|
@@ -292,9 +292,11 @@ omits it. Any drift exits non-zero — whether a change matters is yours to judg
|
|
|
292
292
|
(`#breaking`, `#compatible`, `#to_h`, `#empty?`).
|
|
293
293
|
|
|
294
294
|
`queries:check` answers the question that matters when the schema *has* moved:
|
|
295
|
-
**which of your queries no longer validate, and why.** It re-introspects
|
|
296
|
-
|
|
297
|
-
|
|
295
|
+
**which of your queries no longer validate, and why.** It re-introspects
|
|
296
|
+
whatever is behind each graph's dump (without rewriting the dump) — the same
|
|
297
|
+
source `schema:refresh` rewrites from and `schema:diff` compares against — and
|
|
298
|
+
validates every `.graphql` file against the schema as it is right now, naming
|
|
299
|
+
each error's line and column:
|
|
298
300
|
|
|
299
301
|
```
|
|
300
302
|
app/graphql/queries/person.graphql
|
|
@@ -355,8 +357,11 @@ named `generated`, plus `vendor`, `node_modules`, `tmp` and `log`, is skipped,
|
|
|
355
357
|
as is any file defining a graphql-ruby **type** — a `field :sku` there is your
|
|
356
358
|
*server* offering a field, not this app reading one back. A module handed whole
|
|
357
359
|
to a serializer (`render json:`, `to_h`, `as_json`, a local and all) counts every
|
|
358
|
-
prop as read, and the report quotes the line it followed
|
|
359
|
-
the
|
|
360
|
+
prop as read, and the report quotes the line it followed — a plain local stands
|
|
361
|
+
for the module only inside the method it was assigned in, so a same-named block
|
|
362
|
+
param in the next method credits nothing, while an `@ivar` crosses that boundary
|
|
363
|
+
the way a `before_action` does. Nothing is edited and the exit is 0;
|
|
364
|
+
`STRICT=1` exits 1 when anything is unread.
|
|
360
365
|
|
|
361
366
|
**It is a lint, not a proof**, and the task's own footer says so. It matches
|
|
362
367
|
names as text, so a prop called `name` counts as read the moment anything says
|
|
@@ -441,18 +446,25 @@ the client the graph names, rewrites the dump, and records the source, so every
|
|
|
441
446
|
later refresh and `schema:diff` re-read the right server. `URL=` names the
|
|
442
447
|
endpoint instead, if you'd rather say it once than configure the client first.
|
|
443
448
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
`
|
|
449
|
+
Until there is something behind the dump to re-read — the url it records, the
|
|
450
|
+
server the graph's client posts to, or the graphql-ruby class that client runs
|
|
451
|
+
in-process — `queries:check` validates against the committed file: a real check,
|
|
452
|
+
but `verify`'s question rather than this one's, and the verdict says which:
|
|
447
453
|
|
|
448
454
|
```
|
|
449
455
|
every query validates against db/schema.graphql as committed — not the server (rake graph_weaver:schema:diff asks whether the server moved)
|
|
450
456
|
```
|
|
451
457
|
|
|
452
|
-
A dump with
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
458
|
+
A dump with none of those behind it *is* the schema — a hand-maintained SDL
|
|
459
|
+
nothing serves. All three tasks say so in one sentence:
|
|
460
|
+
|
|
461
|
+
```
|
|
462
|
+
db/schema.graphql records no source url and the graph names no server behind it — no client posting to one, and no graphql-ruby schema class in this process — so the file is the schema and nothing here can re-read it
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
`schema:refresh` steps over that graph and refreshes the rest; `schema:diff`
|
|
466
|
+
still exits 1, because a gate that passes on having compared nothing is worse
|
|
467
|
+
than one that says so.
|
|
456
468
|
|
|
457
469
|
## More than one schema
|
|
458
470
|
|
|
@@ -484,7 +496,7 @@ plus `register_scalar`, `register_enum` and `extend_type`).
|
|
|
484
496
|
| `output` | one directory — where this graph's generated Ruby is written |
|
|
485
497
|
| `client` | what this graph's modules execute against — a client, or the name of the constant holding one |
|
|
486
498
|
| `namespace` | a constant, or its name — what every constant this graph generates nests under |
|
|
487
|
-
| `types_module` | a constant name for the shared types module (default: `
|
|
499
|
+
| `types_module` | a constant name for the shared types module (default: `Types` under a `namespace`, `GraphQLTypes` without one) |
|
|
488
500
|
|
|
489
501
|
**Declaring graph two means declaring graph one.** A declared graph *replaces*
|
|
490
502
|
the implicit one the top-level settings describe, so the moment any graph is
|
|
@@ -506,15 +518,19 @@ they belong to and nothing about transport, so they read it when they execute.
|
|
|
506
518
|
A graph with no `client` falls back to `GraphWeaver.client`, the app default.
|
|
507
519
|
Name the object (`client GraphWeaver.new(url, auth: …)`) or, when the constant
|
|
508
520
|
holding it is defined later than the graph block, its name (`client "GITHUB"`),
|
|
509
|
-
which is resolved on first use
|
|
510
|
-
|
|
511
|
-
|
|
521
|
+
which is resolved on first use — and not a lambda, which `schema` needs and this
|
|
522
|
+
doesn't, since the name is resolved at call time already. `schema "x"` sets and
|
|
523
|
+
a bare `schema` reads back; there is no `schema = "x"` form, since the block is
|
|
524
|
+
`instance_eval`'d and that would be a local variable that silently does nothing.
|
|
512
525
|
|
|
513
526
|
**`namespace` nests everything that graph generates** — `person.graphql` becomes
|
|
514
527
|
`Billing::PersonQuery` ([naming](generated_modules.md#naming)). Constants are
|
|
515
528
|
global, so two schemas that both have a `person.graphql` would otherwise fight
|
|
516
529
|
over one name; without a namespace the collision is refused at generation,
|
|
517
|
-
naming both files. **
|
|
530
|
+
naming both files. **A namespace that is the constant the output path spells is
|
|
531
|
+
also what makes the tree autoloadable** — graph_weaver then leaves it to Zeitwerk
|
|
532
|
+
instead of hiding it and requiring it at boot
|
|
533
|
+
([loading](generated_modules.md#the-rule-in-rails)). **The block's registrations reach that graph alone**, laid
|
|
518
534
|
over the top-level ones — so `Money` is checked against the schema it was
|
|
519
535
|
registered for, and against no other.
|
|
520
536
|
|
|
@@ -522,8 +538,9 @@ An app that is a pure client of someone else's GraphQL owns no schema class, so
|
|
|
522
538
|
every graph's `schema` is a dump. Give each the file you want and a `client`
|
|
523
539
|
that can fetch it: `rake graph_weaver:schema:refresh` introspects each graph's
|
|
524
540
|
client into its own dump, recording the url so every later `schema:refresh` and
|
|
525
|
-
`schema:diff` re-reads the right server.
|
|
526
|
-
|
|
541
|
+
`schema:diff` re-reads the right server. Every graph is its own job — one with
|
|
542
|
+
no server behind its dump is left as checked in, one whose server is down is
|
|
543
|
+
reported under its own heading, and the rest still refresh. (`URL=` is for the
|
|
527
544
|
app that has one dump and no graphs.)
|
|
528
545
|
|
|
529
546
|
In specs, `graph:` is how an example says which graph a helper stands in for —
|
|
@@ -680,6 +697,9 @@ GraphWeaver.client = GraphWeaver.new(
|
|
|
680
697
|
GraphWeaver.load_generated! # no Railtie to require the generated files
|
|
681
698
|
```
|
|
682
699
|
|
|
700
|
+
**A public API needs no `auth:`** — leave the line out. It is in the example
|
|
701
|
+
because most endpoints want a token, not because the constructor asks for one.
|
|
702
|
+
|
|
683
703
|
**`load_generated!` goes before your own requires** when anything your app loads
|
|
684
704
|
names a generated constant as it loads — a `STATUS_LABELS` table keyed on
|
|
685
705
|
`GraphQLTypes::ShipmentStatus` raises `uninitialized constant` otherwise, and
|