feat: add support for the strategy parameter in component-name-unique rule - #3011
feat: add support for the strategy parameter in component-name-unique rule#3011harshit078 wants to merge 14 commits into
Conversation
🦋 Changeset detectedLatest commit: ff9deed The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Performance Benchmark (Lower is Faster)
|
|
Interesting idea! |
kanoru3101
left a comment
There was a problem hiding this comment.
Thank you for your contribution.
Three descriptions now behave differently under lint and bundle: two in my comments, plus the Bugbot one above — that one is correct, I reproduced it.
Left to do:
- make the rule agree with the bundler in all three cases;
- mirror the bundler's tests — none of the three cases is covered today.
The rest is in the inline comments.
| if ( | ||
| !useTitleStrategy || | ||
| typeName !== TYPE_NAME_SCHEMA || | ||
| resolved.location.source.absoluteRef === rootSourceRef |
There was a problem hiding this comment.
The rule skips the title strategy for every schema in the root file. The bundle command does not skip those schemas. It renames a root schema if an external file refers to it. So two schemas end up wanting the same name and the rule stays quiet.
Example
# openapi.yaml
components:
schemas:
Foo:
title: Bar thing
type: object
# ...a response in this file refers to ./Other.yaml
# Other.yaml
title: Bar thing
type: object
properties:
inner:
$ref: './openapi.yaml#/components/schemas/Foo'
The bundle is still written, but Other.yaml gets Other, not the name from its title. The rule sees no problem here, the bundler does both and should see the same. Please check where the $ref comes from, not only where it points.
|
|
||
| const { node } = resolved; | ||
| const title = isPlainObject(node) && isString(node.title) ? node.title.trim() : ''; | ||
| return title === '' ? null : componentNameFromTitle(title); |
There was a problem hiding this comment.
If a schema has no title, the rule uses the file name and says nothing. The bundler doesn't stop.
# openapi.yaml
openapi: 3.0.0
info:
title: Referenced schema without a title
version: 1.0.0
paths:
/carts:
get:
responses:
'200':
description: ok
content:
application/json:
schema:
$ref: './Cart.yaml'
# Cart.yaml - no title here
type: object
properties:
total:
type: number
Lint says the description is fine, and then there is no bundle at all. The two commands disagree again, and this is the most common way the title strategy breaks, so the rule should report it:
| } | ||
|
|
||
| const { node } = resolved; | ||
| const title = isPlainObject(node) && isString(node.title) ? node.title.trim() : ''; |
There was a problem hiding this comment.
This duplicates code that already exists; you should consider reusing the existing logic
| addComponentFromAbsoluteLocation(typeName, resolvedRef.location); | ||
| const titleName = getTitleComponentName(typeName, resolvedRef); | ||
| if (titleName) { | ||
| addFoundComponent(typeName, titleName, resolvedRef.location); |
There was a problem hiding this comment.
The report points at the start of the file, but the line to change is the title. Pass resolvedRef.location.child('title') here, in the same place the bundler reports at bundle-visitor.ts.
Co-authored-by: Viktor Sydor <31951646+kanoru3101@users.noreply.github.com>
|
Hey @harshit078 ! |
|
Hey @kanoru3101 , I completely forgot to push my fixes for this PR and left it stale. I'll push the solution for it. Thanks ! |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ff9deed. Configure here.

What/Why/How?
#2898
Reference
Testing
Screenshots (optional)
Check yourself
Security
Note
Low Risk
Default behavior stays
basename; changes apply only whenstrategy: titleis configured, with broad test coverage and shared naming logic with bundle.Overview
Adds a
strategyoption (basename|title, defaultbasename) to thecomponent-name-uniquelint rule so uniqueness checks mirror whatbundlewill produce for--component-names-strategy.With
strategy: title, externally referenced schemas (cross-file$ref) are keyed by the sanitized PascalCase name derived fromtitleinstead of file/fragment basename—so same filenames with different titles no longer collide, while identical titles across files do. The rule also errors on referenced schemas missingtitle(matching bundle failure), and still uses basename for the uniqueness check whentitleis absent.Title-to-name logic is extracted to shared
componentNameFromTitleand wired intobundle-visitor(renamed resolver). Docs and a changeset describe configuration and link bundle to the rule; tests cover the newtitlebehavior.Reviewed by Cursor Bugbot for commit ff9deed. Bugbot is set up for automated code reviews on this repo. Configure here.