Repository navigation
Conversation
🦋 Changeset detectedLatest commit: 78b4918 The changes in this PR will be included in the next version bump. This PR includes changesets to release 6 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 |
| ) { | ||
| for (const mappingName of Object.keys(mapping)) { | ||
| // values that are not refs are schema names, the same way the bundler treats them | ||
| if (!isMappingRef(mapping[mappingName])) continue; |
There was a problem hiding this comment.
What about turning this around instead of skipping non-ref values? spec-discriminator-defaultMapping already does it for defaultMapping: a value is either a ref or a schema name, so a bare value gets checked against components.schemas. Otherwise a typo like dog: Doge passes silently after this change.
Something like:
let componentsSchemaNames: string[] = [];
return {
Root: {
enter(root) {
componentsSchemaNames = Object.keys(root.components?.schemas || {});
},
},
ref: { /* unchanged */ },
DiscriminatorMapping(mapping: Record<string, string>, { report, location }: UserContext) {
for (const mappingName of Object.keys(mapping)) {
const mappingValue = mapping[mappingName];
if (isMappingRef(mappingValue) || componentsSchemaNames.includes(mappingValue)) continue;
report({
message: `Discriminator mapping value '${mappingValue}' does not point to an existing schema component.`,
location: location.child(mappingName),
reference: 'https://redocly.com/docs/cli/rules/oas/no-unresolved-refs',
});
}
},
};There was a problem hiding this comment.
good call, turned it around like your sketch. bare values are now checked against components.schemas the same way spec-discriminator-defaultMapping does, so dog: Doge gets reported again.
refs are skipped in the mapping visitor like in your snippet. the walker already turns mapping refs into $ref (directResolveAs), so the ref visitor reports broken ones. the old resolve() there only added a duplicate report, and its return stopped after the first good entry anyway.
added a test with a good ref, a typo name and a broken ref, and it gets exactly one report for each bad one. updated the changeset too.
Performance Benchmark (Lower is Faster)
|
|
Could you update the PR description? It still says that the rule skips the mapping values that are not refs, and that the new test reports nothing. Also, please tick the required checklist items, so |
|
updated the description, it now describes the schema name check and both tests. ticked the required boxes. also added a short note about the mapping checks to the rule docs. |
What/Why/How?
The
no-unresolved-refsrule resolved every discriminator mapping value as a$ref. A mapping value can also be a schema name (dog: Dog), and the OpenAPI spec recommends treating such a value as a schema name. The rule tried to resolveDogas a relative file, failed, and reportedCan't resolve $reffor each name.The
DiscriminatorMappingvisitor now works the same way asspec-discriminator-defaultMappingdoes fordefaultMapping:isMappingRef()is left to therefvisitor. The walker already turns mapping refs into$ref(directResolveAs), so therefvisitor reports the unresolvable ones. The visitor's ownresolve()only added a duplicate report for a broken ref, and itsreturnstopped checking after the first entry that resolved.components.schemas. Otherwise the rule reportsDiscriminator mapping value 'Doge' does not point to an existing schema component., so a typo is still caught.The rule docs now mention the mapping checks.
Reference
Fixes #1877. Thanks @tobiaspatton-s4 for the report, and @jeremyfiel for narrowing it down to this rule.
Testing
Two tests in
packages/core/src/rules/common/__tests__/no-unresolved-refs.test.ts:mappingof existing schema names (cat: Cat,dog: Dog) reports nothing. Without the fix it reports twoCan't resolve $referrors.mappingwith a good ref, a typo name (dog: Doge) and a broken ref (bird: '#/components/schemas/Bird') reports exactly one problem for each bad entry. Without the fix only the broken ref is reported (by therefvisitor). The typo name is missed because the visitor stopped at the first entry that resolved.npm run typecheckandnpm run lintpass. Thepackages/coreunit tests pass (149 files, 1187 tests). No fixture underpackages,resources,testsorcookbookhas a bare mapping name that the new check would report.Screenshots (optional)
Check yourself
Security
Note
Low Risk
Narrow lint-rule change aligned with existing ref-utils behavior; only reduces false positives for valid discriminator mappings.
Overview
Fixes false positives from
no-unresolved-refswhen OpenAPI discriminatormappingvalues are schema names (e.g.dog: Dog) instead of$refstrings.The
DiscriminatorMappingvisitor now usesisMappingRef()before resolving mapping values—the same rule the bundler already applies—so bare names are not treated as unresolved references. Actual ref values are still validated and reported when they cannot be resolved.A regression test covers a
Petschema withmapping: { cat: Cat, dog: Dog }and expects zero lint errors.Reviewed by Cursor Bugbot for commit 7f95b5c. Configure here.