graph_weaver 0.6.0 → 0.7.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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1470 -1
  3. data/Gemfile +8 -0
  4. data/Gemfile.lock +151 -2
  5. data/README.md +21 -7
  6. data/docs/alternatives.md +201 -0
  7. data/docs/cassettes.md +17 -1
  8. data/docs/errors.md +382 -17
  9. data/docs/federation.md +469 -63
  10. data/docs/generated_modules.md +231 -15
  11. data/docs/getting_started.md +498 -105
  12. data/docs/i18n.md +234 -0
  13. data/docs/logging.md +160 -24
  14. data/docs/real_world.md +32 -4
  15. data/docs/scalars.md +286 -57
  16. data/docs/testing.md +458 -59
  17. data/docs/transports.md +164 -19
  18. data/docs/upgrading.md +330 -5
  19. data/graph_weaver.gemspec +7 -0
  20. data/lib/generators/graph_weaver/install_generator.rb +138 -4
  21. data/lib/graph_weaver/client.rb +47 -10
  22. data/lib/graph_weaver/codegen/aliases.rb +7 -5
  23. data/lib/graph_weaver/codegen/emit.rb +98 -29
  24. data/lib/graph_weaver/codegen/enum_type.rb +2 -1
  25. data/lib/graph_weaver/codegen/nodes.rb +39 -6
  26. data/lib/graph_weaver/codegen/registry.rb +175 -0
  27. data/lib/graph_weaver/codegen/scalar_type.rb +218 -59
  28. data/lib/graph_weaver/codegen/type_helpers.rb +56 -11
  29. data/lib/graph_weaver/codegen.rb +408 -206
  30. data/lib/graph_weaver/coerce.rb +155 -26
  31. data/lib/graph_weaver/errors.rb +264 -34
  32. data/lib/graph_weaver/federation.rb +119 -26
  33. data/lib/graph_weaver/graph.rb +315 -0
  34. data/lib/graph_weaver/hints.rb +100 -24
  35. data/lib/graph_weaver/in_process.rb +17 -11
  36. data/lib/graph_weaver/input_struct.rb +119 -32
  37. data/lib/graph_weaver/internal/endpoint.rb +78 -0
  38. data/lib/graph_weaver/internal/headers.rb +51 -0
  39. data/lib/graph_weaver/internal/overrides.rb +67 -5
  40. data/lib/graph_weaver/internal/planner.rb +45 -15
  41. data/lib/graph_weaver/internal/refusal.rb +49 -0
  42. data/lib/graph_weaver/internal/schemas.rb +23 -9
  43. data/lib/graph_weaver/internal/selection.rb +34 -0
  44. data/lib/graph_weaver/internal/server_input.rb +251 -0
  45. data/lib/graph_weaver/internal/test_clients.rb +276 -0
  46. data/lib/graph_weaver/internal/unused.rb +287 -0
  47. data/lib/graph_weaver/internal/values.rb +43 -4
  48. data/lib/graph_weaver/internal.rb +183 -1
  49. data/lib/graph_weaver/log_subscriber.rb +66 -0
  50. data/lib/graph_weaver/logging.rb +136 -12
  51. data/lib/graph_weaver/query_module.rb +36 -3
  52. data/lib/graph_weaver/railtie.rb +237 -17
  53. data/lib/graph_weaver/representation.rb +55 -17
  54. data/lib/graph_weaver/result_struct.rb +90 -0
  55. data/lib/graph_weaver/retry.rb +33 -5
  56. data/lib/graph_weaver/rspec.rb +404 -93
  57. data/lib/graph_weaver/schema_loader.rb +221 -49
  58. data/lib/graph_weaver/tasks.rb +380 -89
  59. data/lib/graph_weaver/testing/cassette.rb +6 -5
  60. data/lib/graph_weaver/testing/endpoint.rb +106 -0
  61. data/lib/graph_weaver/testing/failure.rb +69 -12
  62. data/lib/graph_weaver/testing/fake_client.rb +133 -44
  63. data/lib/graph_weaver/testing/router.rb +58 -11
  64. data/lib/graph_weaver/testing.rb +200 -58
  65. data/lib/graph_weaver/transport/faraday.rb +41 -8
  66. data/lib/graph_weaver/transport/http.rb +46 -4
  67. data/lib/graph_weaver/transport.rb +109 -26
  68. data/lib/graph_weaver/version.rb +1 -1
  69. data/lib/graph_weaver.rb +490 -116
  70. metadata +56 -1
@@ -11,16 +11,18 @@
11
11
  # path is resolved against an actual selection).
12
12
 
13
13
  class GraphWeaver::Codegen
14
- class << self
14
+ # The extend_type half of one graph's registrations — see Codegen::Registry.
15
+ class Registry
15
16
  # Attach app-owned helper modules to every struct generated from a
16
17
  # GraphQL type — the logic stays in your code, generation wires it in:
17
18
  #
18
19
  # GraphWeaver.extend_type("Pet", PetHelpers)
19
20
  #
20
21
  # Or build the mixin inline — the block is module_eval'd into a fresh
21
- # module auto-named GraphWeaver::TypeHelpers::<Type>. Handy for quick
22
- # decoration; srb tc can't see into block-defined methods, so prefer
23
- # a named module where static checking matters:
22
+ # module named for where it is written and what it extends:
23
+ # GraphWeaver::TypeHelpers::Pet, or ::Billing::Pet in graph :billing.
24
+ # Handy for quick decoration; srb tc can't see into block-defined methods,
25
+ # so prefer a named module where static checking matters:
24
26
  #
25
27
  # GraphWeaver.extend_type("Pet") do
26
28
  # def display_name = "#{name} the pet"
@@ -118,19 +120,62 @@ class GraphWeaver::Codegen
118
120
  # generated files may still name them.
119
121
  def reset_type_helpers!
120
122
  type_registry.clear
123
+ helper_counts.clear
121
124
  self
122
125
  end
123
126
 
124
- # a block-built mixin needs a name generated files can reference:
125
- # GraphWeaver::TypeHelpers::Pet (suffixed on re-registration)
127
+ # Which graph's registrations this registry holds nil for the top-level
128
+ # one. Block-built helpers are named for it, so two graphs extending the
129
+ # same type get two constants (see helper_module).
130
+ attr_accessor :graph_name
131
+
132
+ # A block-built mixin needs a name generated files can reference:
133
+ # GraphWeaver::TypeHelpers::Pet, or ::Billing::Pet in graph :billing (V2,
134
+ # V3… for a second and third block on the same type in the same place).
135
+ #
136
+ # The name is a function of the source and nothing else — where the block
137
+ # is written and what it extends. It gets baked into generated code, so
138
+ # naming it after whichever constants happened to exist made it a function
139
+ # of how many times THIS process had read the registry, and `generate`
140
+ # wrote a name a plain boot never creates.
126
141
  def helper_module(graphql_name, block)
127
- base = GraphWeaver::Inflect.camelize(graphql_name.to_s)
128
- name = base
129
- count = 1
130
- name = "#{base}V#{count += 1}" while GraphWeaver::TypeHelpers.const_defined?(name, false)
131
- GraphWeaver::TypeHelpers.const_set(name, Module.new(&block))
142
+ namespace = helper_namespace
143
+ type = GraphWeaver::Inflect.camelize(graphql_name.to_s)
144
+ index = (helper_counts[[namespace.name, type]] += 1)
145
+ name = index == 1 ? type : "#{type}V#{index}"
146
+ # reused rather than replaced, so re-declaring the same source (a Rails
147
+ # to_prepare reload) keeps the module already-loaded structs include
148
+ mod = const_under(namespace, name) { Module.new }
149
+ mod.module_eval(&block)
150
+ mod
132
151
  end
133
152
  private :helper_module
153
+
154
+ # Where this registry's block-built helpers live: under a module named for
155
+ # the graph, so two graphs extending the same type get two constants and
156
+ # neither has to know the other exists.
157
+ def helper_namespace
158
+ return GraphWeaver::TypeHelpers unless graph_name
159
+
160
+ const_under(GraphWeaver::TypeHelpers, GraphWeaver::Inflect.camelize(graph_name.to_s)) { Module.new }
161
+ end
162
+ private :helper_namespace
163
+
164
+ def const_under(namespace, name)
165
+ return namespace.const_get(name, false) if namespace.const_defined?(name, false)
166
+
167
+ namespace.const_set(name, yield)
168
+ end
169
+ private :const_under
170
+
171
+ # How many block-built helpers this registry has already named for a type.
172
+ # Per registry, not per process: a graph's registrations are replayed over
173
+ # a fresh copy of the top-level registry on every read, so the same source
174
+ # counts the same way every time.
175
+ def helper_counts
176
+ @helper_counts ||= Hash.new(0)
177
+ end
178
+ private :helper_counts
134
179
  end
135
180
  end
136
181