graphql-modernize 0.1.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 +7 -0
- data/.rubocop.yml +40 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +106 -0
- data/Rakefile +10 -0
- data/docs/migration-guide.md +23 -0
- data/docs/research/changelog-survey.md +68 -0
- data/docs/rules/GQLM101.md +5 -0
- data/docs/rules/GQLM102.md +12 -0
- data/docs/rules/GQLM103.md +5 -0
- data/docs/rules/GQLM104.md +5 -0
- data/docs/rules/GQLM105.md +9 -0
- data/docs/rules/GQLM106.md +7 -0
- data/docs/rules/GQLM107.md +7 -0
- data/docs/rules/GQLM108.md +4 -0
- data/docs/rules/GQLM201.md +5 -0
- data/docs/rules/GQLM202.md +4 -0
- data/docs/rules/GQLM203.md +5 -0
- data/docs/rules/GQLM204.md +5 -0
- data/docs/rules/GQLM205.md +5 -0
- data/docs/rules/GQLM301.md +5 -0
- data/docs/rules/GQLM302.md +5 -0
- data/docs/rules/GQLM303.md +6 -0
- data/docs/rules/GQLM304.md +4 -0
- data/docs/rules/GQLM305.md +8 -0
- data/docs/rules/GQLM306.md +8 -0
- data/docs/rules/GQLM307.md +11 -0
- data/docs/rules/GQLM308.md +5 -0
- data/docs/rules/GQLM309.md +4 -0
- data/docs/rules/GQLM310.md +9 -0
- data/docs/rules/GQLM401.md +6 -0
- data/docs/rules/GQLM402.md +6 -0
- data/docs/rules/GQLM501.md +6 -0
- data/docs/rules/GQLM502.md +5 -0
- data/docs/rules/README.md +35 -0
- data/docs/writing-rules.md +29 -0
- data/exe/graphql-modernize +6 -0
- data/lib/graphql/modernize/application.rb +172 -0
- data/lib/graphql/modernize/class_hierarchy.rb +329 -0
- data/lib/graphql/modernize/cli.rb +175 -0
- data/lib/graphql/modernize/config.rb +163 -0
- data/lib/graphql/modernize/context_builder.rb +78 -0
- data/lib/graphql/modernize/file_finder.rb +45 -0
- data/lib/graphql/modernize/offense.rb +28 -0
- data/lib/graphql/modernize/reporter.rb +103 -0
- data/lib/graphql/modernize/rule_registry.rb +26 -0
- data/lib/graphql/modernize/rules/base.rb +132 -0
- data/lib/graphql/modernize/rules/deprecation.rb +219 -0
- data/lib/graphql/modernize/rules/legacy.rb +301 -0
- data/lib/graphql/modernize/rules/modernize.rb +69 -0
- data/lib/graphql/modernize/rules/relay.rb +74 -0
- data/lib/graphql/modernize/rules/schema_config.rb +38 -0
- data/lib/graphql/modernize/runner.rb +34 -0
- data/lib/graphql/modernize/suppression_index.rb +88 -0
- data/lib/graphql/modernize/version.rb +7 -0
- data/lib/graphql/modernize.rb +30 -0
- metadata +120 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 367624e4b4eb0dcd521cc6d637179eccebeebd2a97d1ec6b4a074496a693d2a7
|
|
4
|
+
data.tar.gz: 1b144aa928b31103102daffa6cfd6de727dee13fdd89ad5fd4b87bc1e52137f5
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 9a0c14c313ab2c390d8aa22794a90246c1c5ed394d75820f83c1f5e2a3e3d784458eac33ee829e25d44e3f5b5223af0ac1535929c9ececb57800306decccf9bb
|
|
7
|
+
data.tar.gz: ec31abe6cae4bf0be75fa509e3c08b4e7f9f4e241541a0734d07e44b50abd2051a220b186ad4edddd0c1908b944ebe2488a783a5a290976c7878a6ae08027a16
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
NewCops: enable
|
|
3
|
+
SuggestExtensions: false
|
|
4
|
+
TargetRubyVersion: 3.3
|
|
5
|
+
UseCache: false
|
|
6
|
+
|
|
7
|
+
Layout/LineLength:
|
|
8
|
+
Max: 120
|
|
9
|
+
|
|
10
|
+
Metrics/AbcSize:
|
|
11
|
+
Max: 100
|
|
12
|
+
|
|
13
|
+
Metrics/BlockLength:
|
|
14
|
+
Exclude:
|
|
15
|
+
- "*.gemspec"
|
|
16
|
+
- "spec/**/*"
|
|
17
|
+
|
|
18
|
+
Metrics/ClassLength:
|
|
19
|
+
Max: 200
|
|
20
|
+
|
|
21
|
+
Metrics/CyclomaticComplexity:
|
|
22
|
+
Max: 30
|
|
23
|
+
|
|
24
|
+
Metrics/MethodLength:
|
|
25
|
+
Max: 50
|
|
26
|
+
|
|
27
|
+
Metrics/ParameterLists:
|
|
28
|
+
Max: 12
|
|
29
|
+
|
|
30
|
+
Metrics/PerceivedComplexity:
|
|
31
|
+
Max: 30
|
|
32
|
+
|
|
33
|
+
Style/Documentation:
|
|
34
|
+
Enabled: false
|
|
35
|
+
|
|
36
|
+
Style/MultilineBlockChain:
|
|
37
|
+
Enabled: false
|
|
38
|
+
|
|
39
|
+
Style/StringLiterals:
|
|
40
|
+
EnforcedStyle: double_quotes
|
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yudai Takada
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# graphql-modernize
|
|
2
|
+
|
|
3
|
+
`graphql-modernize` migrates deprecated graphql-ruby APIs without booting the
|
|
4
|
+
application. It parses Ruby with Prism through [astel](https://github.com/ydah/astel),
|
|
5
|
+
preserves formatting, validates every rewrite, and reports changes before writing.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
bundle add graphql-modernize
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Ruby 3.3 or newer is required. The tool does not depend on the `graphql` gem.
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
Start with a dry run:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
bundle exec graphql-modernize run
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Review the unified diff, then apply safe rules:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
bundle exec graphql-modernize run --write
|
|
27
|
+
git diff
|
|
28
|
+
bundle exec rspec
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Without `--force`, writes require a clean Git working tree and every target
|
|
32
|
+
must be a tracked, non-symlinked path inside that working tree.
|
|
33
|
+
|
|
34
|
+
Unsafe rules require an explicit opt-in and can be run one at a time:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
bundle exec graphql-modernize run --only GQLM307 --unsafe --write
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Useful commands:
|
|
41
|
+
|
|
42
|
+
```text
|
|
43
|
+
graphql-modernize list
|
|
44
|
+
graphql-modernize explain GQLM307
|
|
45
|
+
graphql-modernize doctor
|
|
46
|
+
graphql-modernize run --format json
|
|
47
|
+
graphql-modernize run --format github
|
|
48
|
+
graphql-modernize run --format sarif --out results.sarif
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Exit status is `0` when no unresolved offenses remain, `1` when manual or
|
|
52
|
+
unfixed offenses remain, and `2` for configuration, parse (`--strict`), or
|
|
53
|
+
internal errors.
|
|
54
|
+
|
|
55
|
+
## Configuration
|
|
56
|
+
|
|
57
|
+
Create `.graphql-modernize.yml` in the project root:
|
|
58
|
+
|
|
59
|
+
```yaml
|
|
60
|
+
from_version: "1.13"
|
|
61
|
+
target_version: "2.6"
|
|
62
|
+
ruby_version: "3.3"
|
|
63
|
+
include: ["app/graphql/**/*.rb", "lib/graphql/**/*.rb"]
|
|
64
|
+
exclude: ["app/graphql/legacy/**/*.rb"]
|
|
65
|
+
base_classes:
|
|
66
|
+
object: ["ApplicationObjectType"]
|
|
67
|
+
rules:
|
|
68
|
+
GQLM401:
|
|
69
|
+
enabled: true
|
|
70
|
+
GQLM307:
|
|
71
|
+
migration_errors: true
|
|
72
|
+
apply_unsafe: false
|
|
73
|
+
require_suppression_reason: true
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
CLI options override configuration. GQLM401 and GQLM402 are disabled by
|
|
77
|
+
default because they can create large style-only diffs.
|
|
78
|
+
|
|
79
|
+
## Suppression comments
|
|
80
|
+
|
|
81
|
+
```ruby
|
|
82
|
+
field :name, types.String # graphql-modernize:disable GQLM105 -- staged migration
|
|
83
|
+
|
|
84
|
+
# graphql-modernize:disable GQLM401 -- keep explicit defaults here
|
|
85
|
+
argument :id, ID, required: true
|
|
86
|
+
# graphql-modernize:enable GQLM401
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Use `graphql-modernize:disable-file GQLM101 -- reason` near the top of a file
|
|
90
|
+
for file-wide suppression. Unused suppressions are reported as GQLM000.
|
|
91
|
+
|
|
92
|
+
See [the migration guide](docs/migration-guide.md), [rule index](docs/rules/README.md),
|
|
93
|
+
and [rule authoring guide](docs/writing-rules.md).
|
|
94
|
+
|
|
95
|
+
## Development
|
|
96
|
+
|
|
97
|
+
Run `bundle install`, then `bundle exec rake`. Build the gem with
|
|
98
|
+
`bundle exec rake build`.
|
|
99
|
+
|
|
100
|
+
## Contributing
|
|
101
|
+
|
|
102
|
+
Bug reports and pull requests are welcome at <https://github.com/ydah/graphql-modernize>.
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
The gem is available under the [MIT License](LICENSE.txt).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Migration guide
|
|
2
|
+
|
|
3
|
+
## 1.13 to 2.x
|
|
4
|
+
|
|
5
|
+
1. Run `bundle exec graphql-modernize run` and review the proposed safe changes.
|
|
6
|
+
2. Apply them with `--write`, then run the application's tests.
|
|
7
|
+
3. Run GQLM102 separately with `--unsafe`; resolve its manual fallbacks and
|
|
8
|
+
GQLM101, GQLM104, and GQLM108 before updating.
|
|
9
|
+
4. Apply each unsafe superclass or Relay migration separately with
|
|
10
|
+
`--only RULE --unsafe --write` and test it.
|
|
11
|
+
5. Update graphql-ruby and rerun the tool with the target version.
|
|
12
|
+
|
|
13
|
+
## 2.3 to 2.6
|
|
14
|
+
|
|
15
|
+
1. Remove obsolete execution and pagination settings with the safe rules.
|
|
16
|
+
2. Review type-index consumers reported by GQLM308.
|
|
17
|
+
3. Run GQLM307 by itself. Keep `migration_errors: true` while comparing Warden
|
|
18
|
+
and Visibility, then remove that option after the differences are resolved.
|
|
19
|
+
4. Decide the validation and complexity migration modes reported by GQLM310
|
|
20
|
+
and GQLM501 before accepting the new behavior.
|
|
21
|
+
|
|
22
|
+
Always review `git diff`; the tool deliberately leaves application-specific
|
|
23
|
+
choices as manual offenses.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# graphql-ruby migration survey
|
|
2
|
+
|
|
3
|
+
Surveyed against graphql-ruby's `CHANGELOG.md` through 2.6.10 (2026-08-27),
|
|
4
|
+
the historical official upgrader, rubocop-graphql's cop list, and astel 0.2.0.
|
|
5
|
+
|
|
6
|
+
## Rules selected for the first releases
|
|
7
|
+
|
|
8
|
+
| Rule | Upstream boundary | Static | Correction | Safety |
|
|
9
|
+
|---|---:|---|---|---|
|
|
10
|
+
| GQLM101 `.define` DSL | deprecated 1.10 | yes | guidance only | manual |
|
|
11
|
+
| GQLM102 `resolve:` field option | removed 2.0.1 | yes | simple lambda to method | unsafe/manual fallback |
|
|
12
|
+
| GQLM103 `GraphQL::Function` | removed 2.0 | yes | superclass replacement | unsafe |
|
|
13
|
+
| GQLM104 `to_graphql` / `graphql_definition` | deprecated 1.13 | yes | guidance only | manual |
|
|
14
|
+
| GQLM105 `types.X` | class API migration | yes | remove `types.` | safe |
|
|
15
|
+
| GQLM106 `property:` | class API migration | yes | rename to `method:` | safe |
|
|
16
|
+
| GQLM107 `field:` / `function:` | removed 2.0.1 | yes | remove option | safe |
|
|
17
|
+
| GQLM108 `GraphQL::Query::Arguments` | removed 2.0 | yes | guidance only | manual |
|
|
18
|
+
| GQLM201 Relay mutation | class API migration | yes | superclass replacement | unsafe |
|
|
19
|
+
| GQLM205 load failure error | renamed 1.9.4 | yes | constant replacement | safe |
|
|
20
|
+
| GQLM301 Interpreter plugin | default since 1.12 | yes | remove line | safe |
|
|
21
|
+
| GQLM302 Analysis::AST plugin | default since 1.12 | yes | remove line | safe |
|
|
22
|
+
| GQLM303 Connections plugin | default since 1.12 | yes | remove line | safe |
|
|
23
|
+
| GQLM304 `error_bubbling(true)` | deprecated 2.2.7 | yes | guidance only | manual |
|
|
24
|
+
| GQLM305 bidirectional pagination setting | deprecated 1.13.10 | yes | remove line | safe |
|
|
25
|
+
| GQLM306 default nodes setting | deprecated 1.13.10 | yes | remove line | safe |
|
|
26
|
+
| GQLM307 custom `visible?` without visibility plugin | required since 2.4.0 | project scan | insert plugin | unsafe |
|
|
27
|
+
| GQLM308 possible type/reference keys | changed 2.3.5 | yes | guidance only | manual |
|
|
28
|
+
| GQLM310 empty Union selections | deprecated behavior 2.5.3 | schema scan | guidance only | manual |
|
|
29
|
+
| GQLM401 `required: true` | default since 1.13.0 | yes | remove option | safe, opt-in |
|
|
30
|
+
| GQLM402 `null: true` | default since 1.13.0 | yes | remove option | safe, opt-in |
|
|
31
|
+
| GQLM501 complexity cost mode | migration support 2.5.3 | schema scan | guidance only | manual |
|
|
32
|
+
|
|
33
|
+
The remaining catalog entries need application-specific intent or do not have a
|
|
34
|
+
single generally correct rewrite, so they are reported as manual guidance.
|
|
35
|
+
|
|
36
|
+
GraphQL-Ruby 2.6.3 requires `Schema::Visibility` to be attached after root type
|
|
37
|
+
configuration, so GQLM307 appends the plugin. GraphQL-Ruby 2.5.15 added the
|
|
38
|
+
type-aware `legacy_invalid_empty_selections_on_union_with_type` hook; GQLM310
|
|
39
|
+
recognizes either legacy-selection hook as an explicit policy.
|
|
40
|
+
|
|
41
|
+
## Existing tools
|
|
42
|
+
|
|
43
|
+
The removed official `GraphQL::Upgrader` targeted the `.define` to class API
|
|
44
|
+
migration. Its transforms mixed regular expressions with `parser` AST
|
|
45
|
+
processing and did not cover later 2.x deprecations.
|
|
46
|
+
|
|
47
|
+
rubocop-graphql has `LegacyDSL`, but no equivalents of graphql-ruby's bundled
|
|
48
|
+
`GraphQL/DefaultNullTrue` and `GraphQL/DefaultRequiredTrue` cops. GQLM401 and
|
|
49
|
+
GQLM402 therefore overlap graphql-ruby's bundled cops and remain disabled by
|
|
50
|
+
default. GQLM403 is omitted: graphql-ruby's `GraphQL/FieldTypeInBlock` enforces
|
|
51
|
+
the opposite shape for lazy loading, so an automatic normalization would be a
|
|
52
|
+
style conflict rather than a migration.
|
|
53
|
+
|
|
54
|
+
## astel findings
|
|
55
|
+
|
|
56
|
+
astel 0.2.0 provides every required write primitive: transactions, same-offset
|
|
57
|
+
insertions, parse validation, keyword/list editing, body insertion, comments,
|
|
58
|
+
and unified diff output. `NodePattern` handles the narrow node and field checks
|
|
59
|
+
used here, but its DSL has no list literal syntax for argument-list matching.
|
|
60
|
+
Rules therefore compile a broad call pattern once and use
|
|
61
|
+
`Rewriter#find_keyword_argument` for keyword details.
|
|
62
|
+
|
|
63
|
+
## Sources
|
|
64
|
+
|
|
65
|
+
- <https://github.com/rmosolgo/graphql-ruby/blob/master/CHANGELOG.md>
|
|
66
|
+
- <https://github.com/rmosolgo/graphql-ruby/issues/3056>
|
|
67
|
+
- <https://github.com/DmitryTsepelev/rubocop-graphql/tree/master/lib/rubocop/cop/graphql>
|
|
68
|
+
- <https://github.com/ydah/astel>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# GQLM102 — `resolve:` field option
|
|
2
|
+
|
|
3
|
+
Safety: unsafe. With `--unsafe`, a self-contained three-argument lambda is
|
|
4
|
+
moved to an instance resolver method and legacy `obj` / `ctx` references become
|
|
5
|
+
`object` / `context`. The generated method accepts and ignores extra keyword
|
|
6
|
+
arguments, matching a legacy proc that did not read `args`. Captured locals,
|
|
7
|
+
`args`, nested blocks, bare calls,
|
|
8
|
+
dynamic field names, and method-name collisions are reported as manual because
|
|
9
|
+
an automatic rewrite could change their meaning. Static declarations made with
|
|
10
|
+
`attr`, `alias`, or `define_method` also count as existing methods. Duplicate
|
|
11
|
+
`resolve:` options and calls containing dynamic keyword expansion (`**options`)
|
|
12
|
+
are also left unchanged for manual resolution.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# GQLM105 — `types.X`
|
|
2
|
+
|
|
3
|
+
Safety: safe. Rewrites the five legacy `TypeDefiner` scalars: `String` and
|
|
4
|
+
`Float` keep their Ruby classes, `Int` becomes `Integer`, and `Boolean` / `ID`
|
|
5
|
+
become `GraphQL::Types::Boolean` / `GraphQL::Types::ID`. Other `types.X` calls
|
|
6
|
+
and calls with arguments or blocks are left unchanged. Automatic rewrites are
|
|
7
|
+
limited to GraphQL type DSL arguments; other class-level uses and chained
|
|
8
|
+
wrappers such as `types.String.to_non_null_type` are reported for manual
|
|
9
|
+
class-API migration.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# GQLM106 — `property:`
|
|
2
|
+
|
|
3
|
+
Safety: safe. Renames the removed field option `property:` to its class API
|
|
4
|
+
equivalent `method:` inside GraphQL object and interface definitions.
|
|
5
|
+
Calls with duplicate `property:` or an existing `method:` are reported for
|
|
6
|
+
manual resolution, as are calls containing dynamic keyword expansion
|
|
7
|
+
(`**options`).
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# GQLM107 — removed field options
|
|
2
|
+
|
|
3
|
+
Safety: safe. Removes `field:` and `function:` from field definitions. They
|
|
4
|
+
were already no-ops before GraphQL-Ruby removed them in 2.0.1. Values that may
|
|
5
|
+
have side effects are preserved and reported as manual. String-keyed hashes are
|
|
6
|
+
not treated as legacy keyword options. Calls containing dynamic keyword
|
|
7
|
+
expansion (`**options`) are also left unchanged for manual resolution.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# GQLM301 — Interpreter plugin
|
|
2
|
+
|
|
3
|
+
Safety: safe. Removes `use GraphQL::Execution::Interpreter`; Interpreter has
|
|
4
|
+
been the schema default since 1.12. Conditional, option-bearing, and block-based
|
|
5
|
+
uses, and uses with trailing comments, are preserved and reported as manual.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# GQLM302 — Analysis::AST plugin
|
|
2
|
+
|
|
3
|
+
Safety: safe. Removes `use GraphQL::Analysis::AST`; AST analysis has been the
|
|
4
|
+
schema default since 1.12. Conditional, option-bearing, and block-based uses are
|
|
5
|
+
preserved and reported as manual. Uses with trailing comments are also preserved.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# GQLM303 — Connections plugin
|
|
2
|
+
|
|
3
|
+
Safety: safe. Removes `use GraphQL::Pagination::Connections`; the new
|
|
4
|
+
connection implementation has been the schema default since 1.12. Conditional,
|
|
5
|
+
option-bearing, and block-based uses, and uses with trailing comments, are
|
|
6
|
+
preserved and reported as manual.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# GQLM305 — bidirectional pagination
|
|
2
|
+
|
|
3
|
+
Safety: safe. Removes the obsolete
|
|
4
|
+
`GraphQL::Relay::ConnectionType.bidirectional_pagination` assignment,
|
|
5
|
+
which does not affect the current pagination implementation. Conditional
|
|
6
|
+
assignments and values that may have side effects are reported as manual.
|
|
7
|
+
Assignments nested in methods, blocks, or expressions and assignments with
|
|
8
|
+
trailing comments are also preserved for manual review.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# GQLM306 — default nodes field
|
|
2
|
+
|
|
3
|
+
Safety: safe. Removes the obsolete
|
|
4
|
+
`GraphQL::Relay::ConnectionType.default_nodes_field` assignment, which
|
|
5
|
+
does not affect the current pagination implementation. Conditional assignments
|
|
6
|
+
and values that may have side effects are reported as manual.
|
|
7
|
+
Assignments nested in methods, blocks, or expressions and assignments with
|
|
8
|
+
trailing comments are also preserved for manual review.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# GQLM307 — Visibility plugin
|
|
2
|
+
|
|
3
|
+
Safety: unsafe. When a GraphQL type defines the class method `visible?`, inserts
|
|
4
|
+
`use GraphQL::Schema::Visibility, migration_errors: true` after existing schema
|
|
5
|
+
configuration. Placement after root type configuration is required by
|
|
6
|
+
GraphQL-Ruby 2.6.3 and newer. Resolve migration errors before removing the
|
|
7
|
+
option. Existing one-line Visibility configuration is moved after root types;
|
|
8
|
+
conditional, block-based, or trailing-comment configuration is reported as
|
|
9
|
+
manual so its surrounding behavior and commentary are preserved. Conditional
|
|
10
|
+
plugin calls do not count as guaranteed configuration and prevent automatic
|
|
11
|
+
insertion until they are resolved.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# GQLM310 — empty Union selections
|
|
2
|
+
|
|
3
|
+
Safety: manual. GraphQL-Ruby 2.5.3 began migrating toward rejecting Union
|
|
4
|
+
fields without subselections. Set
|
|
5
|
+
`allow_legacy_invalid_empty_selections_on_union` deliberately while fixing
|
|
6
|
+
affected queries. An override of
|
|
7
|
+
`legacy_invalid_empty_selections_on_union_with_type` also counts as an explicit
|
|
8
|
+
migration policy. Conditional configuration calls do not count as an explicit
|
|
9
|
+
migration policy.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# GQLM401 — redundant `required: true`
|
|
2
|
+
|
|
3
|
+
Safety: safe, disabled by default. Removes `required: true`, the argument
|
|
4
|
+
default since 1.13. Enable this rule explicitly when the style-only diff is
|
|
5
|
+
acceptable. Calls containing dynamic keyword expansion (`**options`) are left
|
|
6
|
+
unchanged for manual resolution, as are duplicate `required:` options.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# GQLM402 — redundant `null: true`
|
|
2
|
+
|
|
3
|
+
Safety: safe, disabled by default. Removes `null: true`, the field default
|
|
4
|
+
since 1.13. Enable this rule explicitly when the style-only diff is acceptable.
|
|
5
|
+
Calls containing dynamic keyword expansion (`**options`) are left unchanged
|
|
6
|
+
for manual resolution, as are duplicate `null:` options.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# GQLM501 — complexity cost mode
|
|
2
|
+
|
|
3
|
+
Safety: manual. GraphQL-Ruby 2.5.3 added migration support for corrected
|
|
4
|
+
complexity merging. Set `complexity_cost_calculation_mode` explicitly, compare
|
|
5
|
+
limits, then adopt the corrected behavior. Conditional configuration calls do
|
|
6
|
+
not count as an explicit migration policy.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Rule index
|
|
2
|
+
|
|
3
|
+
| ID | Safety | Migration |
|
|
4
|
+
|---|---|---|
|
|
5
|
+
| [GQLM101](GQLM101.md) | manual | `.define` DSL |
|
|
6
|
+
| [GQLM102](GQLM102.md) | unsafe/manual fallback | `resolve:` option |
|
|
7
|
+
| [GQLM103](GQLM103.md) | unsafe | `GraphQL::Function` |
|
|
8
|
+
| [GQLM104](GQLM104.md) | manual | legacy definition calls |
|
|
9
|
+
| [GQLM105](GQLM105.md) | safe | `types.X` |
|
|
10
|
+
| [GQLM106](GQLM106.md) | safe | `property:` |
|
|
11
|
+
| [GQLM107](GQLM107.md) | safe | removed field options |
|
|
12
|
+
| [GQLM108](GQLM108.md) | manual | `Query::Arguments` |
|
|
13
|
+
| [GQLM201](GQLM201.md) | unsafe | Relay mutation |
|
|
14
|
+
| [GQLM202](GQLM202.md) | manual | connection type factory |
|
|
15
|
+
| [GQLM203](GQLM203.md) | unsafe | Relay node field |
|
|
16
|
+
| [GQLM204](GQLM204.md) | unsafe | base connection |
|
|
17
|
+
| [GQLM205](GQLM205.md) | safe | load failure error |
|
|
18
|
+
| [GQLM301](GQLM301.md) | safe | Interpreter plugin |
|
|
19
|
+
| [GQLM302](GQLM302.md) | safe | Analysis plugin |
|
|
20
|
+
| [GQLM303](GQLM303.md) | safe | Connections plugin |
|
|
21
|
+
| [GQLM304](GQLM304.md) | manual | error bubbling |
|
|
22
|
+
| [GQLM305](GQLM305.md) | safe | bidirectional pagination |
|
|
23
|
+
| [GQLM306](GQLM306.md) | safe | default nodes field |
|
|
24
|
+
| [GQLM307](GQLM307.md) | unsafe | Visibility plugin |
|
|
25
|
+
| [GQLM308](GQLM308.md) | manual | schema type indexes |
|
|
26
|
+
| [GQLM309](GQLM309.md) | manual | error handlers |
|
|
27
|
+
| [GQLM310](GQLM310.md) | manual | empty Union selections |
|
|
28
|
+
| [GQLM401](GQLM401.md) | safe, opt-in | redundant required |
|
|
29
|
+
| [GQLM402](GQLM402.md) | safe, opt-in | redundant null |
|
|
30
|
+
| [GQLM501](GQLM501.md) | manual | complexity mode |
|
|
31
|
+
| [GQLM502](GQLM502.md) | unsafe | page size settings |
|
|
32
|
+
|
|
33
|
+
GQLM403 is intentionally not provided because graphql-ruby's
|
|
34
|
+
`GraphQL/FieldTypeInBlock` cop owns that style decision. GQLM503 was folded
|
|
35
|
+
into the specific GQLM310 and GQLM501 diagnostics.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Writing rules
|
|
2
|
+
|
|
3
|
+
Rules inherit `GraphQL::Modernize::Rules::Base`, declare metadata once, and
|
|
4
|
+
compile their astel node pattern at class load time.
|
|
5
|
+
|
|
6
|
+
```ruby
|
|
7
|
+
class PropertyOption < Base
|
|
8
|
+
rule id: "GQLM106", safety: :safe, summary: "property to method"
|
|
9
|
+
node_pattern :call_node, "(call_node receiver: nil name: :field)"
|
|
10
|
+
|
|
11
|
+
def on_match(node, _captures)
|
|
12
|
+
return unless inside?(node, :object, :interface)
|
|
13
|
+
|
|
14
|
+
arguments = keyword_arguments(node, :property)
|
|
15
|
+
return unless arguments.one? && !dynamic_keyword_arguments?(node)
|
|
16
|
+
|
|
17
|
+
argument = arguments.first
|
|
18
|
+
|
|
19
|
+
add_offense(argument.location, message: "replace property") do |rw|
|
|
20
|
+
rw.replace_keyword_key(argument, :method)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Use the narrowest NodePattern that astel supports, then inspect GraphQL-specific
|
|
27
|
+
details in Ruby. `add_offense` wraps corrections in an astel transaction.
|
|
28
|
+
Every non-trivial correction needs a test for output, parse validity,
|
|
29
|
+
idempotence, and an unrelated DSL false-positive case.
|