Skip to content

Core: Fix Manifest Resolution For JS Imports Backed By TSX Files#34983

Closed
SSDWGG wants to merge 1 commit into
storybookjs:nextfrom
SSDWGG:codex/resolve-import-tsx-fallback
Closed

Core: Fix Manifest Resolution For JS Imports Backed By TSX Files#34983
SSDWGG wants to merge 1 commit into
storybookjs:nextfrom
SSDWGG:codex/resolve-import-tsx-fallback

Conversation

@SSDWGG
Copy link
Copy Markdown

@SSDWGG SSDWGG commented May 30, 2026

Summary

Fixes #34812.

When resolveImport() falls back from an ESM-style .js import to TypeScript sources, it currently only checks the sibling .ts file. That misses common React component files such as Chip.tsx, so the component manifest can report No component file found even though the story renders correctly through the bundler.

This PR keeps the existing .js -> .ts behavior and adds a second .js -> .tsx fallback when no .ts file resolves. It also adds a regression test using a real temporary fixture directory so the resolver path matches production behavior.

Testing

  • yarn install --immutable
  • yarn vitest run --config code/core/vitest.config.ts code/core/src/common/utils/interpret-files.resolve.test.ts code/core/src/common/utils/__tests__/interpret-files.test.ts

Notes

I attempted the repository lint command locally, but this shallow fork checkout cannot resolve the workspace-built eslint-plugin-storybook package from code/.eslintrc.js. The focused Vitest regression passes locally; CI should run the full workspace pipeline with generated packages available.

Manual testing

Not run locally; this change is covered by the added automated regression test.

Summary by CodeRabbit

  • Tests

    • Added test coverage for import resolution between JavaScript and TypeScript file formats.
  • Bug Fixes

    • Enhanced import resolution error handling to attempt multiple file type conversion fallbacks, improving module resolution reliability in edge cases.

Review Change Stack

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 30, 2026

Fails
🚫

PR is not labeled with one of: ["cleanup","BREAKING CHANGE","feature request","bug","documentation","maintenance","build","dependencies"]

🚫

PR is not labeled with one of: ["ci:normal","ci:merged","ci:daily","ci:docs"]

Generated by 🚫 dangerJS against b123f92

@SSDWGG
Copy link
Copy Markdown
Author

SSDWGG commented May 30, 2026

I updated the title and added the required #### Manual testing section from Danger. I do not have permission to add labels from this fork; could a maintainer please add bug and ci:normal when reviewing?

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 30, 2026

📝 Walkthrough

Walkthrough

resolveImport now attempts multiple TypeScript extension fallbacks sequentially when initial module resolution fails, adding support for mapping .js imports to .tsx files alongside existing .ts and .tsx fallbacks. A test validates the .js.tsx resolution path works correctly.

Changes

Module Resolution Fallback Handling

Layer / File(s) Summary
Fallback resolution logic with test coverage
code/core/src/common/utils/interpret-files.ts, code/core/src/common/utils/interpret-files.resolve.test.ts
resolveImport replaces its single fallback computation with a fallbackIds array, then retries resolveSync for each fallback ID (.js.ts, .js.tsx, .jsx.tsx) in order before rethrowing the original error. Test fixture validates .js specifiers correctly resolve to .tsx files.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • storybookjs/storybook#34393: Updates module-resolution fallback behavior for .js/.cjs imports in docgen resolvers' recovery paths with similar .ts and .tsx fallback ordering.
  • storybookjs/storybook#33698: Changes module-resolution logic to remap TypeScript alternatives for .js-style import specifiers in the loader's resolution flow.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
code/core/src/common/utils/interpret-files.resolve.test.ts (1)

19-27: 💤 Low value

Consider adding test cases for fallback priority and other extension mappings.

The test correctly validates the .js.tsx fallback. For completeness, consider adding tests for:

  • .js.ts when a .ts file exists (priority over .tsx)
  • .mjs.mts and .cjs.cts mappings
  • .jsx.tsx mapping

This would ensure the full fallback chain is covered and prevent regressions.

🧪 Example additional test case for priority
it('resolves a .js import to a .ts file when both .ts and .tsx exist', () => {
  fixtureDir = mkdtempSync(join(tmpdir(), 'storybook-resolve-import-'));
  mkdirSync(join(fixtureDir, 'src'));
  writeFileSync(join(fixtureDir, 'src', 'Chip.ts'), 'export const Chip = () => null;');
  writeFileSync(join(fixtureDir, 'src', 'Chip.tsx'), 'export const Chip = () => null;');

  const resolved = resolveImport('./src/Chip.js', { basedir: fixtureDir });

  expect(resolved).toBe(realpathSync(join(fixtureDir, 'src', 'Chip.ts')));
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@code/core/src/common/utils/interpret-files.resolve.test.ts` around lines 19 -
27, Add additional unit tests in interpret-files.resolve.test.ts covering the
full fallback chain and priority rules for resolveImport: add a test that when
both Chip.ts and Chip.tsx exist resolving './src/Chip.js' returns Chip.ts
(verifies .js→.ts priority over .tsx), and add tests verifying .mjs→.mts,
.cjs→.cts, and .jsx→.tsx mappings by creating appropriate fixture files and
asserting resolveImport('./src/YourModule.<ext>') returns the realpath of the
expected fallback file; use the same fixture setup pattern (mkdtempSync,
mkdirSync, writeFileSync, realpathSync) as existing tests and call resolveImport
with { basedir: fixtureDir } to locate the code under test.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@code/core/src/common/utils/interpret-files.resolve.test.ts`:
- Around line 19-27: Add additional unit tests in
interpret-files.resolve.test.ts covering the full fallback chain and priority
rules for resolveImport: add a test that when both Chip.ts and Chip.tsx exist
resolving './src/Chip.js' returns Chip.ts (verifies .js→.ts priority over .tsx),
and add tests verifying .mjs→.mts, .cjs→.cts, and .jsx→.tsx mappings by creating
appropriate fixture files and asserting resolveImport('./src/YourModule.<ext>')
returns the realpath of the expected fallback file; use the same fixture setup
pattern (mkdtempSync, mkdirSync, writeFileSync, realpathSync) as existing tests
and call resolveImport with { basedir: fixtureDir } to locate the code under
test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d8b8e00f-ae79-44e7-a580-2f367289c25e

📥 Commits

Reviewing files that changed from the base of the PR and between d6ce689 and b123f92.

📒 Files selected for processing (2)
  • code/core/src/common/utils/interpret-files.resolve.test.ts
  • code/core/src/common/utils/interpret-files.ts

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Manifest resolveImport() in interpret-files.ts missing .tsx fallback for .js extensions

2 participants