lighthouse-graphql 0.7.0 → 0.7.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eec6f789caae61cc196024238623ebc042783884cf8ebb53b19bb0e3f6d2cf3f
4
- data.tar.gz: 61bdd5cef3df0d2c4ac9701501576c96a9c207d81b5f2f976d22e5fee14df9ba
3
+ metadata.gz: 504295e8c73043df4b45703bb304b02205a40298e5bc686eb7d3b93dd678478e
4
+ data.tar.gz: f5e1bc31e13856b2f636978eaed1c8d00c5fe6246bba46f4fad513d8ee247dfc
5
5
  SHA512:
6
- metadata.gz: 11c76fea28a691e29eea4910674585891907cefbeef72e9efc7519b8f812cd26f39d6895c90a46c91259b53c0dc64e3a0437add651d9eed07e5cd74807f245f2
7
- data.tar.gz: 530507331c8736355448b67e1cf6ac354a0745351038fc9e7f8535df47f30299e2cf4ea203bee15482bc3fbcf3b8f9d0e5d7e72c61f263f0d9759016ae210a10
6
+ metadata.gz: 5aa2a3bcb218dc305b68cbb0d2ac1b437fdcd801a0965bc0e9c69de994b8028febb7c6a46fe2edff8e4b39d386b94369a63d603f6899fe1b9065d1a7196fd750
7
+ data.tar.gz: 1dd8ef4b1426c9c4555a087da98aaee17cdbbf3133bd375ee6e2d83e738a4911d5e091545b7b65a3262bf823a8bd7f5e034943cf2124077a9d54c42930ee0b7a
data/CHANGELOG.md CHANGED
@@ -6,6 +6,17 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.7.1] - 2026-10-18
10
+
11
+ ### Added
12
+
13
+ - **`lighthouse:install` on graphql-ruby's Relay** (`--relay`, its default) writes `node(id:)`
14
+ and `nodes(ids:)` in the starter `graphql/schema.graphql`, with `interface Node` and a
15
+ `User @node` whose ids are global (`id: ID! @globalId`, `user(id: ID! @globalId(decode: ID) @eq)`).
16
+ Graphql-ruby's `field :node` / `field :nodes` move out of `Types::QueryType`, whose
17
+ `#node` / `#nodes` methods resolve the SDL's fields. This happens only when the schema file
18
+ does not exist yet. An install without Relay writes the starter schema as before.
19
+
9
20
  ## [0.7.0] - 2026-10-18
10
21
 
11
22
  The schema is written by PHP Lighthouse's rules now: one entrypoint that imports
@@ -670,7 +681,8 @@ had been running inside a private monorepo as a path gem before being extracted.
670
681
  - Config-driven extension seams: `Lighthouse.configure`, `resolver_namespaces`,
671
682
  `on_error`, and `DirectiveRegistry.register` for app-defined directives.
672
683
 
673
- [Unreleased]: https://github.com/Vaz-Innovation/lighthouse-graphql/compare/v0.7.0...HEAD
684
+ [Unreleased]: https://github.com/Vaz-Innovation/lighthouse-graphql/compare/v0.7.1...HEAD
685
+ [0.7.1]: https://github.com/Vaz-Innovation/lighthouse-graphql/compare/v0.7.0...v0.7.1
674
686
  [0.7.0]: https://github.com/Vaz-Innovation/lighthouse-graphql/compare/v0.6.0...v0.7.0
675
687
  [0.6.0]: https://github.com/Vaz-Innovation/lighthouse-graphql/compare/v0.5.0...v0.6.0
676
688
  [0.5.0]: https://github.com/Vaz-Innovation/lighthouse-graphql/compare/v0.4.0...v0.5.0
data/docs/generators.md CHANGED
@@ -32,7 +32,7 @@ And it adds Lighthouse's own:
32
32
  | File | What it is |
33
33
  | --- | --- |
34
34
  | `config/initializers/lighthouse.rb` | Every [configuration](configuration.md) option, commented out |
35
- | `graphql/schema.graphql` | A starter schema, unless the folder holds `.graphql` files already |
35
+ | `graphql/schema.graphql` | A starter schema, unless the file exists. With graphql-ruby's Relay (`--relay`, its default), it declares `Query.node` and `nodes`, `interface Node`, and a `User @node` with global ids, and `Types::QueryType`'s `field :node` / `:nodes` go: its `#node` / `#nodes` resolve the SDL's |
36
36
  | `graphql.config.yml` | IDE configuration, and `.gitignore` entries for the [IDE helper](getting-started.md#ide-support) files |
37
37
  | `app/graphql/subscriptions/base_subscription.rb` | With `--subscriptions` only: graphql-ruby has no subscription base. It includes `Lighthouse::GraphQL::Subscription` |
38
38
  | `config/routes.rb` | `post "/graphql", to: "graphql#execute"`, when missing |
@@ -37,7 +37,7 @@ graphql-ruby wrote, and adds Lighthouse's own:
37
37
  | `app/graphql/types/base_*.rb`, `resolvers/base_resolver.rb`, `mutations/base_mutation.rb` | graphql-ruby's base classes. `BaseObject`, `BaseInterface`, `BaseUnion` and `BaseScalar` include `Lighthouse::GraphQL::Type` |
38
38
  | `app/controllers/graphql_controller.rb` | graphql-ruby's controller, replaced by one including `Lighthouse::GraphQL::Controller` |
39
39
  | `config/initializers/lighthouse.rb` | Every [configuration](configuration.md) option, commented out at its default |
40
- | `graphql/schema.graphql` | The schema's entrypoint: a starter schema (`user` via `@find`, `users` via `@paginate`) that assumes a `User` model. Skipped when the file exists |
40
+ | `graphql/schema.graphql` | The schema's entrypoint: a starter schema (`user` via `@find`, `users` via `@paginate`) that assumes a `User` model. With graphql-ruby's Relay, also `node(id:)` and `nodes(ids:)` (see [relay.md](relay.md#relay-through-graphql-ruby)). Skipped when the file exists |
41
41
  | `graphql.config.yml` | IDE configuration — see [IDE support](#ide-support) |
42
42
 
43
43
  `--schema=ApiSchema`, `--schema-path=app/schema/schema.graphql`, `--subscriptions`,
data/docs/relay.md CHANGED
@@ -160,9 +160,58 @@ directives then work on them. The schema has one kind of global id and one `Node
160
160
  `ID` gives its id, and `ARRAY` / `TYPE` its class name (`["Tag", 1]`, `"Tag"`).
161
161
  - `node:` is the SDL's `Node` interface: `interface Node`, which `@node` adds, and
162
162
  `implements Node` refer to `Types::NodeType`. A `@node` type implements it.
163
- - `Query.node` and `nodes` are graphql-ruby's code-first fields of
164
- `Types::QueryType`, which find objects with `object_from_id`. The `node` field
165
- `@node` would add to `Query` gives way to them.
163
+ - `Query.node` and `nodes` find objects with `object_from_id`, through the
164
+ `#node` and `#nodes` methods of `Types::QueryType`. `lighthouse:install`
165
+ declares both fields in the starter `graphql/schema.graphql`, and removes the
166
+ `field :node` / `field :nodes` that graphql-ruby wrote in `Types::QueryType`,
167
+ so the SDL is where they are declared. An SDL field without a resolving
168
+ directive resolves with the root type class's method of its name. If the
169
+ fields stay in `Types::QueryType` instead, they are part of the schema too, and
170
+ the `node` field `@node` would add to `Query` gives way to them.
171
+
172
+ The starter schema `lighthouse:install` writes on graphql-ruby's Relay:
173
+
174
+ ```graphql
175
+ type Query {
176
+ "Fetches an object given its ID. Resolved by Types::QueryType#node, with AppSchema.object_from_id."
177
+ node("ID of the object." id: ID!): Node
178
+
179
+ "Fetches a list of objects given a list of IDs. Resolved by Types::QueryType#nodes."
180
+ nodes("IDs of the objects." ids: [ID!]!): [Node]
181
+
182
+ user(id: ID! @globalId(decode: ID) @eq): User @find
183
+ users: [User!]! @paginate(defaultCount: 10)
184
+ }
185
+
186
+ interface Node {
187
+ "ID of the object."
188
+ id: ID!
189
+ }
190
+
191
+ type User @node {
192
+ id: ID! @globalId
193
+ name: String
194
+ email: String
195
+ }
196
+ ```
197
+
198
+ ```ruby
199
+ module Types
200
+ class QueryType < Types::BaseObject
201
+ # Query.node and nodes are declared in graphql/schema.graphql; these methods resolve them.
202
+ def node(id:)
203
+ context.schema.object_from_id(id, context)
204
+ end
205
+
206
+ def nodes(ids:)
207
+ ids.map { |id| context.schema.object_from_id(id, context) }
208
+ end
209
+ end
210
+ end
211
+ ```
212
+
213
+ `lighthouse:install` writes this only when the app has no schema file yet, and
214
+ only on the `node` / `nodes` fields as graphql-ruby writes them.
166
215
 
167
216
  ```graphql
168
217
  type Tag @node {
@@ -26,6 +26,10 @@ module Lighthouse::Generators::GraphqlRubyInstall
26
26
  # The example field graphql-ruby's install puts in each root type.
27
27
  TEST_FIELD = /\n+[ \t]*# TODO: remove me\n[ \t]*field :test_field,.*?\n[ \t]*def test_field\n.*?\n[ \t]*end\n/m
28
28
 
29
+ # The `node` and `nodes` fields graphql-ruby's install (--relay, its default)
30
+ # puts in Types::QueryType, without the methods that resolve them.
31
+ RELAY_FIELDS = /^[ \t]*field :nodes?, \[?Types::NodeType\b.*? do\n(?:[ \t]*argument .*\n)*[ \t]*end\n\n?/
32
+
29
33
  # The `resolve_type` stub graphql-ruby's install puts in the schema class.
30
34
  RESOLVE_TYPE_STUB = /
31
35
  \n+[ \t]*\#\ Union\ and\ Interface\ Resolution\n
@@ -98,6 +102,16 @@ module Lighthouse::Generators::GraphqlRubyInstall
98
102
  options[:subscriptions] || exist?(File.join(directory, 'subscriptions', 'base_subscription.rb'))
99
103
  end
100
104
 
105
+ # Did graphql-ruby's install write Relay's side (--relay, its default):
106
+ # Types::NodeType, and Types::QueryType's node and nodes, as it writes them?
107
+ def relay?
108
+ query_type = types_path('query_type.rb')
109
+ return false unless exist?(types_path('node_type.rb')) && exist?(query_type)
110
+
111
+ source = read(query_type)
112
+ source.scan(RELAY_FIELDS).size == 2 && source.include?('def node(id:)') && source.include?('def nodes(ids:)')
113
+ end
114
+
101
115
  def graphql_ruby_controller?(source)
102
116
  source.include?('def prepare_variables(variables_param)') && source.include?('def handle_error_in_development(e)') &&
103
117
  source.include?("#{schema_name}.execute(query, variables: variables, context: context, operation_name: operation_name)")
@@ -21,6 +21,9 @@ require_relative 'graphql_ruby_install'
21
21
  # graphql-ruby's and stays, but the `resolve_type` stub (Lighthouse resolves
22
22
  # types) and the root types it is built on;
23
23
  # - the example `test_field` goes from the root types;
24
+ # - with Relay, the starter SDL declares Query.node and nodes (and a User
25
+ # @node with global ids), so their `field`s go from Types::QueryType, whose
26
+ # #node / #nodes methods resolve the SDL's fields;
24
27
  # - graphql-ruby's base object, interface, union and scalar include
25
28
  # Lighthouse::GraphQL::Type, so every type class (Types::QueryType,
26
29
  # Types::NodeType, what `graphql:object` writes) is Lighthouse's;
@@ -76,6 +79,7 @@ class Lighthouse::Generators::InstallGenerator < Rails::Generators::Base
76
79
  return
77
80
  end
78
81
 
82
+ @relay_starter = relay?
79
83
  template 'schema.graphql.tt', sdl_schema_path
80
84
  end
81
85
 
@@ -101,12 +105,15 @@ class Lighthouse::Generators::InstallGenerator < Rails::Generators::Base
101
105
  add_dataloader if source.include?('use GraphQL::Batch') && source.exclude?('use GraphQL::Dataloader')
102
106
  end
103
107
 
104
- # The example field goes; the root types' own fields stay.
108
+ # The example field goes; the root types' own fields stay. With Relay, the
109
+ # starter SDL declares Query.node and nodes, so their `field`s go too, and
110
+ # the methods graphql-ruby wrote resolve the SDL's fields.
105
111
  def adapt_root_types
106
112
  %w[query_type mutation_type subscription_type].each do |name|
107
113
  path = types_path("#{name}.rb")
108
114
  gsub_file path, TEST_FIELD, "\n" if exist?(path) && read(path).match?(TEST_FIELD)
109
115
  end
116
+ move_relay_fields_to_sdl if @relay_starter
110
117
  end
111
118
 
112
119
  # Every type class is Lighthouse's: graphql-ruby's base object, interface,
@@ -223,6 +230,13 @@ class Lighthouse::Generators::InstallGenerator < Rails::Generators::Base
223
230
  sdl_schema_path == 'graphql/schema.graphql'
224
231
  end
225
232
 
233
+ def move_relay_fields_to_sdl
234
+ path = types_path('query_type.rb')
235
+ gsub_file path, RELAY_FIELDS, ''
236
+ gsub_file path, /^([ \t]*)def node\(id:\)\n/,
237
+ "\\1# Query.node and nodes are declared in #{sdl_schema_path}; these methods resolve them.\n\\1def node(id:)\n"
238
+ end
239
+
226
240
  def ide_helper_files
227
241
  [Lighthouse::IdeHelper::DIRECTIVES_FILE, Lighthouse::IdeHelper::PROGRAMMATIC_TYPES_FILE]
228
242
  end
@@ -1,15 +1,44 @@
1
1
  # Starter schema generated by `rails generate lighthouse:install`. It assumes a
2
2
  # User model with `name` and `email` columns — replace it with your own types.
3
+ # This file is the schema's entrypoint: split the schema into files it imports
4
+ # (#import user.graphql), which add their fields with `extend type Query`.
3
5
  # Directives reference: https://github.com/Vaz-Innovation/lighthouse-graphql/blob/main/docs/directives.md
4
6
 
5
7
  "Indicates what fields are available at the top level of a query operation."
6
8
  type Query {
9
+ <% if relay? -%>
10
+ "Fetches an object given its ID. Resolved by Types::QueryType#node, with <%= schema_name %>.object_from_id."
11
+ node("ID of the object." id: ID!): Node
12
+
13
+ "Fetches a list of objects given a list of IDs. Resolved by Types::QueryType#nodes."
14
+ nodes("IDs of the objects." ids: [ID!]!): [Node]
15
+
16
+ "Find a single user by its global id."
17
+ user(id: ID! @globalId(decode: ID) @eq): User @find
18
+ <% else -%>
7
19
  "Find a single user by id."
8
20
  user(id: ID! @eq): User @find
21
+ <% end -%>
9
22
 
10
23
  "List users, a page at a time (10 by default; pass first: and page:)."
11
24
  users: [User!]! @paginate(defaultCount: 10)
12
25
  }
26
+ <% if relay? -%>
27
+
28
+ "An object with an ID: graphql-ruby's Types::NodeType."
29
+ interface Node {
30
+ "ID of the object."
31
+ id: ID!
32
+ }
33
+
34
+ "Account of a person who uses this application. @node makes it a Node, which Query.node finds."
35
+ type User @node {
36
+ "Its global id, from <%= schema_name %>.id_from_object (Rails' GlobalID)."
37
+ id: ID! @globalId
38
+ name: String
39
+ email: String
40
+ }
41
+ <% else -%>
13
42
 
14
43
  "Account of a person who uses this application."
15
44
  type User {
@@ -17,3 +46,4 @@ type User {
17
46
  name: String
18
47
  email: String
19
48
  }
49
+ <% end -%>
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lighthouse
4
4
  module GraphQL
5
- VERSION = '0.7.0'
5
+ VERSION = '0.7.1'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lighthouse-graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vaz Innovation