Skip to content

fix: resolve discriminator defaultMapping into components schemas when bundling#2736

Open
tatomyr wants to merge 5 commits intomainfrom
fix/resolve-defaultMapping-when-bundling
Open

fix: resolve discriminator defaultMapping into components schemas when bundling#2736
tatomyr wants to merge 5 commits intomainfrom
fix/resolve-defaultMapping-when-bundling

Conversation

@tatomyr
Copy link
Copy Markdown
Collaborator

@tatomyr tatomyr commented Apr 10, 2026

What/Why/How?

Fixed an issue where discriminator defaultMapping was not resolved when bundling.

Reference

Testing

Screenshots (optional)

Check yourself

  • This PR follows the contributing guide
  • All new/updated code is covered by tests
  • Core code changed? - Tested with other Redocly products (internal contributions only)
  • New package installed? - Tested in different environments (browser/node)
  • Documentation update has been considered

Security

  • The security impact of the change has been considered
  • Code follows company security practices and guidelines

Note

Low Risk
Low risk: change is scoped to OAS3 bundling behavior for discriminator.defaultMapping and is covered by new unit and e2e tests, with minimal surface area outside bundling.

Overview
Fixes bundling so OAS3 discriminator.defaultMapping is treated like discriminator.mapping: mapping-like values are now resolved and saved into #/components/schemas/... instead of being left as an unresolved string.

Adds regression coverage via a new unit test for component-name mappings and a new OAS 3.2 e2e fixture/snapshot verifying defaultMapping to an external schema is rewritten to an internal component ref.

Reviewed by Cursor Bugbot for commit daa0ca6. Bugbot is set up for automated code reviews on this repo. Configure here.

@tatomyr tatomyr self-assigned this Apr 10, 2026
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 10, 2026

🦋 Changeset detected

Latest commit: daa0ca6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@redocly/openapi-core Patch
@redocly/cli Patch
@redocly/respect-core Patch

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 10, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 79.93% (🎯 79%) 6727 / 8416
🔵 Statements 79.36% (🎯 79%) 6965 / 8776
🔵 Functions 83.1% (🎯 82%) 1367 / 1645
🔵 Branches 71.55% (🎯 71%) 4566 / 6381
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/core/src/bundle/bundle-visitor.ts 64.75% 61.06% 100% 64.75% 30, 34-42, 49-57, 64, 73, 81, 86-107, 172-184, 201-202, 219-225, 236-237, 274
Generated in workflow #9444 for commit daa0ca6 by the Vitest Coverage Report Action

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 10, 2026

CLI Version Mean Time ± Std Dev (s) Relative Performance (Lower is Faster)
cli-latest 3.253s ± 0.047s ▓ 1.01x
cli-next 3.228s ± 0.008s ▓ 1.00x (Fastest)

@tatomyr tatomyr marked this pull request as ready for review April 14, 2026 07:50
@tatomyr tatomyr requested review from a team as code owners April 14, 2026 07:50
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Missing isMappingRef check for defaultMapping resolution
    • Added an isMappingRef guard before resolving defaultMapping and covered the plain schema-name case with a unit test so valid OAS 3.2 documents no longer report unresolved refs.

Create PR

Or push these changes by commenting:

@cursor push 49f3370f76
Preview (49f3370f76)
diff --git a/packages/core/src/__tests__/bundle.test.ts b/packages/core/src/__tests__/bundle.test.ts
--- a/packages/core/src/__tests__/bundle.test.ts
+++ b/packages/core/src/__tests__/bundle.test.ts
@@ -302,6 +302,36 @@
     expect(problems).toHaveLength(0);
   });
 
+  it('should not resolve discriminator defaultMapping schema names (OAS 3.2)', async () => {
+    const document = outdent`
+      openapi: 3.2.0
+      paths: {}
+      components:
+        schemas:
+          Pet:
+            type: object
+            discriminator:
+              propertyName: kind
+              defaultMapping: Cat
+          Cat:
+            type: object
+            properties:
+              kind:
+                type: string
+    `;
+
+    const {
+      bundle: { parsed },
+      problems,
+    } = await bundleFromString({
+      source: document,
+      config: await createConfig({}),
+    });
+
+    expect(problems).toHaveLength(0);
+    expect((parsed as any).components.schemas.Pet.discriminator.defaultMapping).toBe('Cat');
+  });
+
   it('should pull hosted schema', async () => {
     const { bundle: res, problems } = await bundle({
       config: await createConfig({}),

diff --git a/packages/core/src/bundle/bundle-visitor.ts b/packages/core/src/bundle/bundle-visitor.ts
--- a/packages/core/src/bundle/bundle-visitor.ts
+++ b/packages/core/src/bundle/bundle-visitor.ts
@@ -2,6 +2,7 @@
 import { type SpecMajorVersion } from '../oas-types.js';
 import {
   isAbsoluteUrl,
+  isMappingRef,
   replaceRef,
   isExternalValue,
   isRef,
@@ -208,7 +209,12 @@
     const componentType = mapTypeToComponent('Schema', version)!;
     visitor.Discriminator = {
       leave(discriminator: Oas3Discriminator, ctx: UserContext) {
-        if (typeof discriminator.defaultMapping !== 'string') return;
+        if (
+          typeof discriminator.defaultMapping !== 'string' ||
+          !isMappingRef(discriminator.defaultMapping)
+        ) {
+          return;
+        }
 
         const resolved = ctx.resolve({ $ref: discriminator.defaultMapping });
         if (!resolved.location || resolved.node === undefined) {

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a94bfe2. Configure here.

@tatomyr tatomyr force-pushed the fix/resolve-defaultMapping-when-bundling branch from 4e61b1d to daa0ca6 Compare April 14, 2026 14:23
@tatomyr tatomyr requested a review from DmitryAnansky April 14, 2026 14:35
@tatomyr tatomyr added the snapshot Create experimental release PR label Apr 14, 2026
@github-actions
Copy link
Copy Markdown
Contributor

📦 A new experimental 🧪 version v0.0.0-snapshot.1776177415 of Redocly CLI has been published for testing.

Install with NPM:

npm install @redocly/cli@0.0.0-snapshot.1776177415
# or
npm install @redocly/openapi-core@0.0.0-snapshot.1776177415
# or
npm install @redocly/respect-core@0.0.0-snapshot.1776177415

⚠️ Note: This is a development build and may contain unstable features.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

snapshot Create experimental release PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants