lighthouse-graphql 0.6.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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +107 -1
  3. data/README.md +15 -7
  4. data/docs/best-practices.md +6 -4
  5. data/docs/configuration.md +19 -5
  6. data/docs/custom-directives.md +2 -1
  7. data/docs/directives.md +65 -7
  8. data/docs/federation.md +1 -1
  9. data/docs/filtering-and-ordering.md +330 -30
  10. data/docs/generators.md +2 -2
  11. data/docs/getting-started.md +43 -10
  12. data/docs/motivation.md +3 -2
  13. data/docs/performance.md +4 -3
  14. data/docs/relationships.md +2 -1
  15. data/docs/relay.md +52 -3
  16. data/docs/resolvers.md +2 -2
  17. data/docs/schema-organisation.md +177 -0
  18. data/lib/generators/lighthouse/install/graphql_ruby_install.rb +14 -0
  19. data/lib/generators/lighthouse/install/install_generator.rb +31 -12
  20. data/lib/generators/lighthouse/install/templates/graphql.config.yml.tt +2 -1
  21. data/lib/generators/lighthouse/install/templates/initializer.rb.tt +11 -4
  22. data/lib/generators/lighthouse/install/templates/schema.graphql.tt +30 -0
  23. data/lib/lighthouse/ast_builder.rb +124 -0
  24. data/lib/lighthouse/config.rb +23 -4
  25. data/lib/lighthouse/contracts/arg_manipulator.rb +9 -5
  26. data/lib/lighthouse/contracts/field_builder.rb +13 -0
  27. data/lib/lighthouse/directive_resolvers/aggregate_resolver.rb +1 -2
  28. data/lib/lighthouse/directive_resolvers/all_resolver.rb +0 -2
  29. data/lib/lighthouse/directive_resolvers/association_resolvers.rb +9 -6
  30. data/lib/lighthouse/directive_resolvers/base.rb +6 -37
  31. data/lib/lighthouse/directive_resolvers/builder_applier.rb +21 -6
  32. data/lib/lighthouse/directive_resolvers/count_resolver.rb +0 -1
  33. data/lib/lighthouse/directive_resolvers/first_resolver.rb +0 -2
  34. data/lib/lighthouse/directive_resolvers/paginate_resolver.rb +2 -3
  35. data/lib/lighthouse/directives/arguments/order_by.rb +190 -26
  36. data/lib/lighthouse/directives/arguments/where_conditions.rb +25 -0
  37. data/lib/lighthouse/directives/arguments/where_conditions_base.rb +84 -0
  38. data/lib/lighthouse/directives/arguments/where_has_conditions.rb +56 -0
  39. data/lib/lighthouse/directives/definitions.rb +0 -1
  40. data/lib/lighthouse/directives/generated_types.rb +103 -0
  41. data/lib/lighthouse/directives/registry.rb +39 -10
  42. data/lib/lighthouse/document_ast.rb +111 -0
  43. data/lib/lighthouse/graphql/version.rb +1 -1
  44. data/lib/lighthouse/ide_helper.rb +80 -23
  45. data/lib/lighthouse/namespaces.rb +1 -0
  46. data/lib/lighthouse/order_by/types.rb +137 -0
  47. data/lib/lighthouse/railtie.rb +9 -2
  48. data/lib/lighthouse/rb_lighthouse.rb +15 -5
  49. data/lib/lighthouse/resolve_info.rb +5 -5
  50. data/lib/lighthouse/schema_cache.rb +8 -4
  51. data/lib/lighthouse/schema_factory.rb +6 -9
  52. data/lib/lighthouse/schema_generator.rb +4 -15
  53. data/lib/lighthouse/schema_stitcher.rb +64 -0
  54. data/lib/lighthouse/support/naming.rb +0 -12
  55. data/lib/lighthouse/where_conditions/columns.rb +36 -0
  56. data/lib/lighthouse/where_conditions/handler.rb +152 -0
  57. data/lib/lighthouse/where_conditions/json_column.rb +99 -0
  58. data/lib/lighthouse/where_conditions/operator_map.rb +1 -4
  59. data/lib/lighthouse/where_conditions/types.rb +110 -0
  60. data/sig/lighthouse/directives.rbs +16 -3
  61. data/sig/lighthouse/graphql.rbs +48 -4
  62. data/sig/lighthouse.rbs +8 -2
  63. metadata +15 -4
  64. data/lib/lighthouse/directive_resolvers/where_conditions_applier.rb +0 -170
  65. data/lib/lighthouse/directives/where_conditions_directive.rb +0 -244
  66. data/lib/lighthouse/sdl_loader.rb +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da632a31f353bc75d798a228769150a76f8cd3a0e8dce13e8bc19c363641f850
4
- data.tar.gz: 6d0e92dc7818bccd89d4d9d1bc2e4905421cedd84190a0d0ae09c8ad31cb546f
3
+ metadata.gz: 504295e8c73043df4b45703bb304b02205a40298e5bc686eb7d3b93dd678478e
4
+ data.tar.gz: f5e1bc31e13856b2f636978eaed1c8d00c5fe6246bba46f4fad513d8ee247dfc
5
5
  SHA512:
6
- metadata.gz: 30c076b60a32754472f1360eedc72c46b2ee518230d8ce686658f6a436f9a7d74cbcb13c24bf6a1d7dc8c05f29fba8f6ddd0d53e5614ea00ab498753340429c3
7
- data.tar.gz: d558ad506a5bfebda1486cf8b62450113d0a1022f0ff458a8b040924aca458189a176cf9dbdcab95f877b571bfc18b1408109b5db36bfc128a6754df55b1bc11
6
+ metadata.gz: 5aa2a3bcb218dc305b68cbb0d2ac1b437fdcd801a0965bc0e9c69de994b8028febb7c6a46fe2edff8e4b39d386b94369a63d603f6899fe1b9065d1a7196fd750
7
+ data.tar.gz: 1dd8ef4b1426c9c4555a087da98aaee17cdbbf3133bd375ee6e2d83e738a4911d5e091545b7b65a3262bf823a8bd7f5e034943cf2124077a9d54c42930ee0b7a
data/CHANGELOG.md CHANGED
@@ -6,6 +6,110 @@ 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
+
20
+ ## [0.7.0] - 2026-10-18
21
+
22
+ The schema is written by PHP Lighthouse's rules now: one entrypoint that imports
23
+ the other files, every type defined once, and `extend type` to add to it.
24
+ `@orderBy`, `@whereConditions` and `@whereHasConditions` generate and apply what
25
+ PHP Lighthouse's do. In development, the IDE helper files are rewritten
26
+ automatically.
27
+
28
+ **Upgrading from 0.6:**
29
+
30
+ 1. Replace `config.sdl_folder = ...` with `config.schema_path = Rails.root.join('graphql/schema.graphql').to_s`
31
+ (that is the default), and `get_schema(sdl_folder:)` with `get_schema(schema_path:)`.
32
+ 2. Import every other file from `graphql/schema.graphql`. `#import **/*.graphql` imports
33
+ every file below its folder, which matches what was loaded before.
34
+ 3. Turn a second `type Query { ... }` (or `type Mutation`, or any type defined in two files)
35
+ into `extend type Query { ... }`. A type defined twice now fails the build.
36
+ 4. Write `orderBy:` arguments as `orderBy: _ @orderBy(columns: [...])`, and drop the
37
+ `OrderByClause` inputs and the `SortOrder` enum you declared. `order` is required in a
38
+ clause, and `{ field:, direction: }` clauses are no longer accepted.
39
+ 5. `SQLOperator` has PHP Lighthouse's values. Replace `NIN` with `NOT_IN`, and
40
+ `CONTAINS` / `STARTS_WITH` / `ENDS_WITH` with `LIKE` and a `%` pattern
41
+ (`value: "%Rails%"`, `"Rails%"`, `"%Rails"`). `@where(operator:)` keeps its operators.
42
+ 6. A `HAS` condition is on the related records' columns (`…HasCondition`, a `String`
43
+ column), as in PHP Lighthouse, no longer on the parent's column enum.
44
+
45
+ ### Added
46
+
47
+ - **`#import`.** The schema's entrypoint, `config.schema_path`, imports other files by a
48
+ path relative to the importing file. Globs (`#import blog/*.graphql`) work too. An
49
+ imported file can import more files, and each file is read once.
50
+ - **Type extensions merged as PHP Lighthouse merges them.** `extend type`, `input`,
51
+ `interface`, `enum`, `union` and `scalar` add to their definition, and the
52
+ directives on their fields work as on the type's own. `extend type Query` alone
53
+ defines `Query`.
54
+ - **`@orderBy` generates its types.** `orderBy: _ @orderBy(columns: [...])` gets
55
+ `[<Type><Field><Arg>OrderByClause!]`, a column enum (`@enum(value:)` per column)
56
+ and `SortOrder`. `columnsEnum:` reuses an enum, and without columns the shared
57
+ `OrderByClause` takes any column.
58
+ - **`@orderBy(relations:)`.** Clients order by `COUNT` of a relation, or by
59
+ `AVG`/`MIN`/`MAX`/`SUM` of one of its columns
60
+ (`{ posts: { aggregate: COUNT }, order: DESC }`). Records without related ones
61
+ are ordered too, and this works on batched relationship pages.
62
+ - **`@orderBy(column:, direction:)` on a field.** It always orders the result, after
63
+ the client's clauses.
64
+ - **`@whereConditions` and `@whereHasConditions`, as in PHP Lighthouse.** They have
65
+ PHP Lighthouse's `SQLOperator` (`LIKE`, `NOT_LIKE`, `NOT_IN`, `BETWEEN`,
66
+ `NOT_BETWEEN`, ...), and `HAS` with `operator:` / `amount:`
67
+ (`{ relation: "posts", operator: LT, amount: 1 }`: the records with none). The
68
+ `…Relation` / `…HasCondition` inputs filter on the related table, and
69
+ `handler:` names a class that applies the conditions instead.
70
+ - **JSON columns.** `@whereConditions`, `@whereHasConditions` and `@orderBy` take a path into a
71
+ JSON column, `meta->author->name` or `meta->tags->0`, on PostgreSQL, MySQL and SQLite.
72
+ Numbers compare and sort as numbers, booleans compare as booleans, and `IS_NULL` holds
73
+ for a JSON `null` too.
74
+ - **`config.ide_helper`.** `schema-directives.graphql` and
75
+ `programmatic-types.graphql` are rewritten on boot and on every reload. By
76
+ default this happens in development when the app has a `graphql.config.yml`.
77
+ - `Contracts::FieldBuilder`, and `Contracts::ArgManipulator` as `ASTBuilder` calls
78
+ it, for custom directives.
79
+ - The guide [docs/schema-organisation.md](docs/schema-organisation.md).
80
+
81
+ ### Changed
82
+
83
+ - **Breaking:** The schema is read from `config.schema_path` and its imports, not from every
84
+ file in `config.sdl_folder`, which is removed. `lighthouse:install` takes `--schema-path`
85
+ instead of `--sdl-folder`.
86
+ - **Breaking:** A type defined twice fails the build: "Duplicate definition X found when parsing
87
+ the schema", pointing at `extend`. PHP Lighthouse keeps the last definition.
88
+ - **Breaking:** An argument typed `_` that no directive replaces fails the build. It used to
89
+ become a scalar.
90
+ - **Breaking:** `@orderBy` clauses need `order`, take only `{ column:, order: }`, and a
91
+ column outside an enum must be an identifier.
92
+ - **Breaking:** `SQLOperator`'s values are PHP Lighthouse's (see above).
93
+ - **Breaking:** `@builder` and `@whereAuth` on a field apply after the argument directives,
94
+ as PHP Lighthouse's field builder directives do. An `order` a builder adds now breaks the
95
+ ties of the client's `orderBy` instead of preceding it. They also apply on relationship
96
+ fields (`@hasMany`, ...), where they used to be ignored, and on `@aggregate`, which now
97
+ gets the argument directives too.
98
+
99
+ ### Fixed
100
+
101
+ - A schema that stops building while you edit it keeps its `programmatic-types.graphql`.
102
+ If there is none yet, the file declares the `_` placeholder alone, so the IDE never
103
+ reports `Unknown type "_"`. When an import is missing, the IDE helper reads every
104
+ `.graphql` file in the folder, as the IDE does.
105
+ - `programmatic-types.graphql` no longer repeats the types `schema-directives.graphql`
106
+ defines (`Mixed`, `CanAction`, `PaginateType`, ...). graphql-js, which the VS Code
107
+ and JetBrains GraphQL plugins use, rejected the schema.
108
+ - `@whereConditions` applied only to an argument named `where`. It and `@whereHasConditions`
109
+ are argument directives like the others now: any name, in SDL order.
110
+ - An error in a `@whereConditions` value (an unknown relation or operator) is the client's
111
+ error. It used to be swallowed and leave the query unfiltered.
112
+
9
113
  ## [0.6.0] - 2026-10-18
10
114
 
11
115
  Lighthouse now uses what the Rails app and graphql-ruby already have instead of settings and
@@ -577,7 +681,9 @@ had been running inside a private monorepo as a path gem before being extracted.
577
681
  - Config-driven extension seams: `Lighthouse.configure`, `resolver_namespaces`,
578
682
  `on_error`, and `DirectiveRegistry.register` for app-defined directives.
579
683
 
580
- [Unreleased]: https://github.com/Vaz-Innovation/lighthouse-graphql/compare/v0.6.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
686
+ [0.7.0]: https://github.com/Vaz-Innovation/lighthouse-graphql/compare/v0.6.0...v0.7.0
581
687
  [0.6.0]: https://github.com/Vaz-Innovation/lighthouse-graphql/compare/v0.5.0...v0.6.0
582
688
  [0.5.0]: https://github.com/Vaz-Innovation/lighthouse-graphql/compare/v0.4.0...v0.5.0
583
689
  [0.4.0]: https://github.com/Vaz-Innovation/lighthouse-graphql/compare/v0.3.0...v0.4.0
data/README.md CHANGED
@@ -87,23 +87,31 @@ and scalar include `Lighthouse::GraphQL::Type`; the controller serves the schema
87
87
  through `Lighthouse::GraphQL::Controller`. It adds the initializer, a starter schema
88
88
  in `graphql/schema.graphql` and a `graphql.config.yml` for your IDE. Run
89
89
  `bin/rails generate lighthouse:install --help` for its options (`--schema`,
90
- `--sdl-folder`, `--subscriptions`, `--skip-controller`, `--skip-ide`), and see
90
+ `--schema-path`, `--subscriptions`, `--skip-controller`, `--skip-ide`), and see
91
91
  [docs/generators.md](docs/generators.md) for every generator, graphql-ruby's included.
92
92
 
93
+ ### Schema files
94
+
95
+ As in PHP Lighthouse, the schema is read from one entrypoint,
96
+ `graphql/schema.graphql`, which `#import`s the other files
97
+ (`#import user.graphql`, `#import blog/*.graphql`). A type is defined once, and the
98
+ other files add to it with `extend type Query`. See
99
+ [docs/schema-organisation.md](docs/schema-organisation.md).
100
+
93
101
  ### IDE support
94
102
 
95
103
  Lighthouse's directives and the types it generates (Paginator/Connection types,
96
- `whereConditions` inputs, …) are defined in Ruby, so your IDE can't see them in
97
- your `.graphql` files. Write them out for it:
104
+ `@whereConditions` and `@orderBy` inputs, the `_` placeholder, …) are defined in
105
+ Ruby, so your IDE can't see them in your `.graphql` files. Lighthouse writes them
106
+ to `schema-directives.graphql` and `programmatic-types.graphql` in the app root:
107
+ in development on every boot and reload, or with:
98
108
 
99
109
  ```shell
100
110
  bin/rails lighthouse:ide_helper
101
111
  ```
102
112
 
103
- This writes `schema-directives.graphql` and `programmatic-types.graphql` to the app
104
- root; the generated `graphql.config.yml` already points the GraphQL plugins for
105
- JetBrains IDEs and VS Code at them. Rerun it after changing your schema or
106
- registering a directive. See [docs/getting-started.md](docs/getting-started.md#ide-support).
113
+ The generated `graphql.config.yml` already points the GraphQL plugins for
114
+ JetBrains IDEs and VS Code at them. See [docs/getting-started.md](docs/getting-started.md#ide-support).
107
115
 
108
116
  ## Quick start
109
117
 
@@ -92,7 +92,9 @@ app's GraphQL setup easy to find.
92
92
 
93
93
  ## Split your SDL
94
94
 
95
- Lighthouse concatenates every `*.graphql` file under your `sdl_folder`. Organize
96
- by domain (`users.graphql`, `orders.graphql`, …) and keep a small
97
- `_directives.graphql` only for directives you declare yourself (built-ins are
98
- injected automatically).
95
+ Lighthouse reads `graphql/schema.graphql` and the files it `#import`s
96
+ ([schema-organisation.md](schema-organisation.md)). Organize
97
+ by domain (`users.graphql`, `orders.graphql`, …), each with its types and the
98
+ fields it adds with `extend type Query` / `extend type Mutation`. Keep a small
99
+ `directives.graphql`, imported too, only for directives you declare yourself
100
+ (built-ins are injected automatically).
@@ -9,7 +9,7 @@ reusable and publishable.
9
9
  require 'lighthouse-graphql'
10
10
 
11
11
  Lighthouse.configure do |config|
12
- config.sdl_folder = Rails.root.join('graphql').to_s
12
+ config.schema_path = Rails.root.join('graphql/schema.graphql').to_s
13
13
  config.namespaces = { queries: ['Resolvers'], mutations: ['Mutations'] }
14
14
  config.resolver_namespaces = ['App::Graphql']
15
15
  config.on_error = ->(error, _context) { Rails.error.report(error) }
@@ -18,11 +18,25 @@ end
18
18
 
19
19
  ## Options
20
20
 
21
- ### `sdl_folder`
21
+ ### `schema_path`
22
22
 
23
- Where Lighthouse loads `*.graphql` files from. Defaults to `RAILS_ROOT/graphql`
24
- in a Rails app, `nil` otherwise (pass SDL explicitly via `SchemaFactory` when not
25
- on Rails).
23
+ The schema's entrypoint, as PHP Lighthouse's `schema_path`. Lighthouse reads
24
+ this file and the files it imports (`#import user.graphql`, `#import blog/*.graphql`).
25
+ A type is defined once, and other files add to it with `extend type`. See
26
+ [schema-organisation.md](schema-organisation.md). Defaults to
27
+ `RAILS_ROOT/graphql/schema.graphql` in a Rails app, and `nil` otherwise. Outside
28
+ Rails, pass the path, or the SDL itself (`SchemaFactory.build_base_schema(sdl:)`).
29
+
30
+ `get_schema(schema_path: ...)` overrides it for one schema.
31
+
32
+ ### `ide_helper`
33
+
34
+ Rewrite `schema-directives.graphql` and `programmatic-types.graphql` in the
35
+ app's root on boot and on every reload, for the IDE
36
+ ([schema-organisation.md](schema-organisation.md#ide-support)). A file whose
37
+ content is unchanged is left alone. `nil` (the default) turns it on in
38
+ development when the app has a `graphql.config.yml`, which `lighthouse:install`
39
+ writes. Set `true` or `false` to decide yourself.
26
40
 
27
41
  ### `namespaces`
28
42
 
@@ -29,7 +29,8 @@ Include the marker module(s) your directive fulfils:
29
29
  | `Contracts::FieldResolver` | provide a field's resolver | `#define_resolver(type)` (or `#resolve_field`) |
30
30
  | `Contracts::FieldMiddleware` | wrap an existing resolver (e.g. `@auth`) | `#wrap_resolver(next)` |
31
31
  | `Contracts::FieldManipulator` | reshape the schema for a field | `manipulate_field_definition(...)` |
32
- | `Contracts::ArgManipulator` | reshape the schema for an argument | `manipulate_argument_definition(...)` |
32
+ | `Contracts::ArgManipulator` | reshape the schema for an argument, as `@orderBy` and `@whereConditions` generate their types | `#manipulate_arg_definition(document_ast, field_node, type_node)` returning the argument node |
33
+ | `Contracts::FieldBuilder` | constrain a field's query, whatever the client sends | `#handle_field_builder(relation)` |
33
34
  | `Contracts::ArgBuilder` | compose a query constraint from an argument | `#handle_builder(relation, value)` |
34
35
 
35
36
  A directive class also answers two class-level questions: its name and its SDL
data/docs/directives.md CHANGED
@@ -78,7 +78,7 @@ type Query {
78
78
  ```
79
79
 
80
80
  - **The query.** It is the model's (`model:`, else the return type), narrowed by
81
- `scopes:`, [`@builder`](#builder) and the field's argument filters. On a nested
81
+ `scopes:`, the field's argument filters and [`@builder`](#builder). On a nested
82
82
  field it pages the parent's association of the same name: `User.posts @paginate`
83
83
  pages the user's posts.
84
84
  - **`first`.** It defaults to `defaultCount`, else
@@ -456,7 +456,12 @@ Builders are looked up in their own namespace, `Builders::` (app/graphql/builder
456
456
  `class:` with `method:` (default `call`), or PHP Lighthouse's `method: "Class@method"`.
457
457
 
458
458
  On a field, the method gets `(relation, args, context)`, or the directive's
459
- `value:` in place of the arguments. On an argument or an input field, it gets
459
+ `value:` in place of the arguments. As in PHP Lighthouse, a field's `@builder`
460
+ (with `@whereAuth` and `@orderBy(column:)`) applies after the argument
461
+ directives, in SDL order. An `order` it adds therefore breaks the ties of the
462
+ client's `orderBy`. It applies on every field that queries records: `@all`,
463
+ `@paginate`, `@find`, `@first`, `@count`, `@aggregate`, the relationship
464
+ directives and `resolve_info.enhance_builder`. On an argument or an input field, it gets
460
465
  `(relation, value, context)` whenever the client sends that argument, an explicit
461
466
  `null` included, and not when it is left out:
462
467
 
@@ -518,7 +523,7 @@ Full guide: [filtering-and-ordering.md](filtering-and-ordering.md).
518
523
  | `@whereBetween` / `@whereNotBetween` | `column BETWEEN` / `NOT BETWEEN` the input's two fields, in order |
519
524
  | `@whereJsonContains` | a JSON column contains the value (every value of a list); `key: "meta->tags"` points into it |
520
525
  | `@scope(name:)` | calls the model scope with the value (`name:` defaults to the argument's) |
521
- | `@orderBy` | sort by one or more columns |
526
+ | `@orderBy` | sort by the client's clauses (columns, relations' aggregates); on a field, a fixed order |
522
527
 
523
528
  ```graphql
524
529
  type Query {
@@ -526,7 +531,7 @@ type Query {
526
531
  status: String @eq
527
532
  nameSearch: String @like
528
533
  minAge: Int @where(operator: "GTE", key: "age")
529
- orderBy: [OrderByClause!] @orderBy
534
+ orderBy: _ @orderBy(columns: ["name", "created_at"])
530
535
  ): [User!]! @all
531
536
  }
532
537
  ```
@@ -568,18 +573,71 @@ parents it would cut them all together, as PHP Lighthouse warns. PHP Lighthouse
568
573
  also allows `@limit` on the field itself, where it only marks the field the argument
569
574
  limits; it is accepted there and changes nothing.
570
575
 
576
+ ### `@orderBy`
577
+
578
+ ```graphql
579
+ directive @orderBy(
580
+ columns: [String!] # argument: the columns the client may order by
581
+ columnsEnum: String # argument: an enum of them instead (one of the two)
582
+ relations: [OrderByRelation!] # argument: { relation:, columns:, columnsEnum: } to order by an aggregate
583
+ column: String # field: the column to order by
584
+ direction: OrderByDirection = ASC
585
+ ) on ARGUMENT_DEFINITION | FIELD_DEFINITION
586
+ ```
587
+
588
+ On an argument written as `_`, Lighthouse generates the clause input
589
+ (`<Type><Field><Arg>OrderByClause`, or `…RelationOrderByClause` with
590
+ `relations:`) and the column enum. Without `columns:`, `columnsEnum:` or
591
+ `relations:`, the argument takes the shared `OrderByClause`, which allows any
592
+ column. A column can be a JSON path, `meta->rank`, in `@orderBy` and in
593
+ `@whereConditions` ([JSON columns](filtering-and-ordering.md#json-columns)). On a field, `@orderBy(column:, direction:)` orders the result after
594
+ the client's clauses.
595
+
596
+ ```graphql
597
+ type Query {
598
+ posts(orderBy: _ @orderBy(columns: ["posted_at", "title"])): [Post!]! @all
599
+ users(orderBy: _ @orderBy(relations: [{ relation: "posts" }])): [User!]! @all
600
+ latestPosts: [Post!]! @all @orderBy(column: "posted_at", direction: DESC)
601
+ }
602
+
603
+ # { posts(orderBy: [{ column: POSTED_AT, order: DESC }]) { title } }
604
+ # { users(orderBy: [{ posts: { aggregate: COUNT }, order: DESC }]) { name } }
605
+ ```
606
+
607
+ Guide: [filtering-and-ordering.md](filtering-and-ordering.md#ordering).
608
+
571
609
  ### `@whereConditions` / `@whereHasConditions`
572
610
 
573
- Give clients a structured, dynamic `WHERE` builder (AND/OR/operators, and HAS for
574
- related records). Lighthouse generates the input and enum types for you. See
575
- [filtering-and-ordering.md](filtering-and-ordering.md#complex-where-conditions).
611
+ ```graphql
612
+ directive @whereConditions(columns: [String!], columnsEnum: String, handler: String) on ARGUMENT_DEFINITION
613
+ directive @whereHasConditions(relation: String, columns: [String!], columnsEnum: String, handler: String) on ARGUMENT_DEFINITION
614
+ ```
615
+
616
+ These give clients a dynamic `WHERE` builder, with conditions joined by `AND`
617
+ and `OR`, PHP Lighthouse's `SQLOperator` operators, and `HAS` checks on
618
+ relations. On an argument written as `_`, Lighthouse generates the input
619
+ (`<Type><Field><Arg>WhereConditions` / `…WhereHasConditions`), its `…Relation`
620
+ and `…HasCondition` inputs, and the column enum. Without `columns:` or
621
+ `columnsEnum:`, the argument takes the shared `WhereConditions`, which allows
622
+ any column.
623
+
624
+ `@whereHasConditions` keeps the records with a related record matching the
625
+ conditions. The relation is `relation:`, or the argument's name without `has`.
626
+ `handler:` names a `Builders::` class whose `call(relation, conditions)` applies
627
+ the conditions instead.
576
628
 
577
629
  ```graphql
578
630
  type Query {
579
631
  people(where: _ @whereConditions(columns: ["age", "type"])): [Person!]! @all
632
+ users(hasPosts: _ @whereHasConditions(columns: ["title"])): [User!]! @all
580
633
  }
634
+
635
+ # { people(where: { AND: [{ column: AGE, operator: GT, value: 37 }, { column: TYPE, value: "Actor" }] }) { name } }
636
+ # { users(hasPosts: { column: TITLE, operator: LIKE, value: "%Rails%" }) { name } }
581
637
  ```
582
638
 
639
+ Guide: [filtering-and-ordering.md](filtering-and-ordering.md#complex-where-conditions).
640
+
583
641
  ### `@trim`, `@hash`, `@drop`, `@bind` and `@upload`
584
642
 
585
643
  Rewrite an argument's or input field's value before the field resolves, in the
data/docs/federation.md CHANGED
@@ -29,7 +29,7 @@ class Types::BaseObject < GraphQL::Schema::Object
29
29
  end
30
30
 
31
31
  BaseAppSchema = Lighthouse::GraphQL::RbLightHouse.get_schema(
32
- sdl_folder: Rails.root.join('graphql').to_s,
32
+ schema_path: Rails.root.join('graphql/schema.graphql').to_s,
33
33
  options: { federation: true, base_types: { object: Types::BaseObject, resolver: Resolvers::BaseResolver } }
34
34
  )
35
35