Skip to content

React: respect tsconfigPath in react-docgen-typescript#34406

Closed
bae080311 wants to merge 17 commits into
storybookjs:nextfrom
bae080311:fix/typescript-tsconfig-path
Closed

React: respect tsconfigPath in react-docgen-typescript#34406
bae080311 wants to merge 17 commits into
storybookjs:nextfrom
bae080311:fix/typescript-tsconfig-path

Conversation

@bae080311
Copy link
Copy Markdown

@bae080311 bae080311 commented Mar 31, 2026

Closes #34388

What I did

getParser() in reactDocgenTypescript.ts always called
findTsconfigPath(process.cwd()), completely ignoring the
tsconfigPath value users pass through
reactDocgenTypescriptOptions. This broke monorepo setups where
the root tsconfig.json uses project references with empty
include/files arrays — react-docgen-typescript found no files
and extracted no component documentation.

Changes:

  • Core fix: getParser() now prefers
    userOptions.tsconfigPath (resolved relative to process.cwd())
    and falls back to auto-detection when not set
  • Error handling: guard readConfigFile error before applying
    parsed compiler options, so an invalid path doesn't crash
  • Type stripping: tsconfigPath is removed from options
    before forwarding to react-docgen-typescript since it's not part
    of their ParserOptions type
  • Official types: add tsconfigPath?: string to
    reactDocgenTypescriptOptions in getComponentImports.ts,
    react-vite types, and react-webpack preset types
  • Docs: document the option in main-config-typescript.mdx
    with a monorepo example
  • Remove stray console.log from reactDocgen/utils.ts

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated

tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

No automated tests added — the change is a small conditional
branch in config resolution. Best verified manually with a
monorepo as described below.

Manual testing

  1. Set up a monorepo with a solution-style root tsconfig.json
    (empty include/files, only references)
  2. Create tsconfig.storybook.json that explicitly includes
    component source files:
    {                                                              
      "extends": "./tsconfig.base.json",                           
      "include": ["packages/*/src/**/*.ts",

"packages//src/**/.tsx"]
}
3. Configure .storybook/main.ts:
typescript: {
reactDocgen: 'react-docgen-typescript',
reactDocgenTypescriptOptions: {
tsconfigPath: './tsconfig.storybook.json',
},
},
4. Run Storybook — component props should now be extracted
correctly in the Controls/Docs panel

Documentation

  • Add or update documentation reflecting your changes

Summary by CodeRabbit

  • New Features

    • Added a tsconfigPath option to TypeScript react-docgen configuration so you can point to a custom tsconfig resolved from the project root.
  • Bug Fixes / Reliability

    • Improved tsconfig loading and error handling; clearer warnings when a provided custom tsconfig cannot be read and reduced silent failures.
  • Documentation

    • Added examples and guidance for using tsconfigPath in monorepo/project-reference setups.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 31, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds an optional tsconfigPath to react-docgen TypeScript option types and threads it through parser initialization: resolves/reads the specified tsconfig (relative to process.cwd()), strips tsconfigPath from options passed to react-docgen-typescript, conditions parsing on successful read, and removes a debug log.

Changes

Cohort / File(s) Summary
Type Definitions — Framework / Preset
code/frameworks/react-vite/src/types.ts, code/presets/react-webpack/src/types.ts
Extended reactDocgenTypescriptOptions type to include tsconfigPath?: string.
Type Definitions — Renderer
code/renderers/react/src/componentManifest/getComponentImports.ts
Added optional tsconfigPath to renderer TypescriptOptions.
Implementation — React docgen/typescript parser
code/renderers/react/src/componentManifest/reactDocgenTypescript.ts
Accepts tsconfigPath on user options, removes it before passing options to react-docgen-typescript, resolves explicit path via resolve(process.cwd(), ...), falls back to discovery, only derives compiler options/fileNames when readConfigFile returns no error, resets cached fileNames when reinitializing, and logs a warning if an explicit tsconfig fails to load.
Utils Cleanup
code/renderers/react/src/componentManifest/reactDocgen/utils.ts
Removed stray debug console.log({ tsconfigPath }) from getTsConfig.
Documentation
docs/api/main-config/main-config-typescript.mdx
Documented typescript.reactDocgenTypescriptOptions.tsconfigPath with examples and resolution semantics (relative to process.cwd()).

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant ParserModule as getParser / parseWithReactDocgenTypescript
  participant FS as Resolver
  participant TS as TypeScript API
  participant Docgen as react-docgen-typescript Parser

  Caller->>ParserModule: parseWithReactDocgenTypescript(filePath, userOptions)
  ParserModule->>ParserModule: extract tsconfigPath and restUserOptions
  alt tsconfigPath provided
    ParserModule->>FS: resolve(process.cwd(), tsconfigPath)
    FS-->>ParserModule: resolvedConfigPath
    ParserModule->>TS: readConfigFile(resolvedConfigPath)
    TS-->>ParserModule: { config, error }
    alt no error
      ParserModule->>TS: parseJsonConfigFileContent(config, resolvedConfigPath)
      TS-->>ParserModule: { compilerOptions, fileNames }
      ParserModule->>ParserModule: set cachedCompilerOptions / cachedFileNames
    else error
      ParserModule-->>Caller: log warning (resolvedConfigPath, error.messageText)
    end
  else no tsconfigPath
    ParserModule->>TS: findTsconfigPath(process.cwd())
    TS-->>ParserModule: detectedConfigPath
    ParserModule->>TS: readConfigFile(detectedConfigPath)
    TS-->>ParserModule: { config, error }
    ParserModule->>TS: parseJsonConfigFileContent(config, detectedConfigPath)
    TS-->>ParserModule: { compilerOptions, fileNames }
    ParserModule->>ParserModule: set cachedCompilerOptions / cachedFileNames
  end
  ParserModule->>Docgen: create/return Parser(restUserOptions, cachedCompilerOptions)
  Docgen-->>Caller: extracted docgen info
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs


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/renderers/react/src/componentManifest/reactDocgenTypescript.ts (1)

195-211: Consider logging a warning when the user-provided tsconfigPath fails to load.

When typescript.readConfigFile returns an error, the code silently falls back to default compiler options. If a user explicitly provides a tsconfigPath that cannot be read (e.g., typo, missing file), they receive no feedback about why their configuration isn't being applied.

💡 Proposed improvement to add a warning
 import { dirname, resolve } from 'node:path';
+import { logger } from 'storybook/internal/node-logger';
 
 // ... in getParser function:
 
     if (configPath) {
       const { config, error } = typescript.readConfigFile(configPath, typescript.sys.readFile);
       if (!error) {
         const parsed = typescript.parseJsonConfigFileContent(
           config,
           typescript.sys,
           dirname(configPath)
         );
         cachedCompilerOptions = { ...parsed.options, noErrorTruncation: true };
         cachedFileNames = parsed.fileNames;
+      } else if (userTsconfigPath) {
+        // Only warn if user explicitly provided a path that failed to load
+        logger.warn(`Failed to load tsconfig at "${configPath}": ${error.messageText}`);
       }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/renderers/react/src/componentManifest/reactDocgenTypescript.ts` around
lines 195 - 211, When typescript.readConfigFile fails for a user-provided path
(userTsconfigPath) the code silently falls back; add a warning that includes the
failing path and the error details. Inside the existing if (configPath) block,
handle the case where typescript.readConfigFile(configPath,
typescript.sys.readFile) returns an error by calling console.warn (or the
project's logger if available) with a clear message referencing
userTsconfigPath/configPath and the error.message/object, then continue falling
back to cachedCompilerOptions as before. This ensures failures to load user
tsconfig are visible while preserving current behavior in the code around
userOptions, configPath, and typescript.readConfigFile.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@code/renderers/react/src/componentManifest/reactDocgenTypescript.ts`:
- Around line 195-211: When typescript.readConfigFile fails for a user-provided
path (userTsconfigPath) the code silently falls back; add a warning that
includes the failing path and the error details. Inside the existing if
(configPath) block, handle the case where typescript.readConfigFile(configPath,
typescript.sys.readFile) returns an error by calling console.warn (or the
project's logger if available) with a clear message referencing
userTsconfigPath/configPath and the error.message/object, then continue falling
back to cachedCompilerOptions as before. This ensures failures to load user
tsconfig are visible while preserving current behavior in the code around
userOptions, configPath, and typescript.readConfigFile.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6a5f878e-9477-4056-919d-f4cc4a037286

📥 Commits

Reviewing files that changed from the base of the PR and between 5eeadf7 and 936d25e.

📒 Files selected for processing (6)
  • code/frameworks/react-vite/src/types.ts
  • code/presets/react-webpack/src/types.ts
  • code/renderers/react/src/componentManifest/getComponentImports.ts
  • code/renderers/react/src/componentManifest/reactDocgen/utils.ts
  • code/renderers/react/src/componentManifest/reactDocgenTypescript.ts
  • docs/api/main-config/main-config-typescript.mdx
💤 Files with no reviewable changes (1)
  • code/renderers/react/src/componentManifest/reactDocgen/utils.ts

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@code/renderers/react/src/componentManifest/reactDocgenTypescript.ts`:
- Around line 213-215: Replace direct usage of error.messageText in the
logger.warn call with TypeScript's flattenDiagnosticMessageText to handle
DiagnosticMessageChain cases; in the branch that checks userTsconfigPath (the
else-if around logger.warn), call
typescript.flattenDiagnosticMessageText(error.messageText, '\n') (or
ts.flattenDiagnosticMessageText if `ts` is the imported alias) and pass that
result into the warning message so the log prints a readable string for both
string and DiagnosticMessageChain types.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 16c9e28b-352c-42d8-a497-1c915045bd86

📥 Commits

Reviewing files that changed from the base of the PR and between 936d25e and baf0eb6.

📒 Files selected for processing (1)
  • code/renderers/react/src/componentManifest/reactDocgenTypescript.ts

Comment thread code/renderers/react/src/componentManifest/reactDocgenTypescript.ts
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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@code/renderers/react/src/componentManifest/reactDocgenTypescript.ts`:
- Around line 197-214: Reset cachedFileNames whenever you rebuild the parser
options so a stale file list isn't reused: when setting cachedCompilerOptions
(e.g., in the block around cachedCompilerOptions = { noErrorTruncation: true,
strict: true } and before calling
typescript.readConfigFile/parseJsonConfigFileContent), also set cachedFileNames
= undefined; additionally ensure that if typescript.readConfigFile returns an
error or configPath is falsy (including when userTsconfigPath is provided but
failing), cachedFileNames remains cleared so downstream createProgram cannot
consume a previous run’s fileNames; reference variables/functions:
cachedCompilerOptions, cachedFileNames, configPath, userTsconfigPath,
typescript.readConfigFile, typescript.parseJsonConfigFileContent, and
createProgram.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fd4c6d60-2877-4a11-a00d-f567b9a09c9c

📥 Commits

Reviewing files that changed from the base of the PR and between 188c7c6 and 659db06.

📒 Files selected for processing (1)
  • code/renderers/react/src/componentManifest/reactDocgenTypescript.ts

Comment thread code/renderers/react/src/componentManifest/reactDocgenTypescript.ts
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/renderers/react/src/componentManifest/reactDocgenTypescript.ts (1)

185-241: Add regression tests for tsconfigPath behavior branches.

Please add automated coverage for: (1) explicit tsconfigPath precedence, and (2) invalid tsconfigPath warning path without throw. This path is easy to regress and currently relies on manual verification.

Also applies to: 303-306

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/renderers/react/src/componentManifest/reactDocgenTypescript.ts` around
lines 185 - 241, Add automated tests that cover getParser's tsconfigPath
branches: (1) a test asserting that when calling getParser with a user-provided
tsconfigPath (userTsconfigPath) the code uses that file (precedence over
findTsconfigPath) by mocking/resolving process.cwd and
typescript.readConfigFile/parseJsonConfigFileContent to return expected
parsed.options and parsed.fileNames and then asserting the created
parser.program reflects those compiler options/fileNames; (2) a test for an
invalid userTsconfigPath where typescript.readConfigFile returns an error—mock
typescript.flattenDiagnosticMessageText and ensure logger.warn is called with
the expected message and that getParser does not throw (it falls back to
cachedCompilerOptions and returns a parser), using mocks for
reactDocgenTypescript.withCompilerOptions to verify parser.fileParser is
constructed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@code/renderers/react/src/componentManifest/reactDocgenTypescript.ts`:
- Around line 185-241: Add automated tests that cover getParser's tsconfigPath
branches: (1) a test asserting that when calling getParser with a user-provided
tsconfigPath (userTsconfigPath) the code uses that file (precedence over
findTsconfigPath) by mocking/resolving process.cwd and
typescript.readConfigFile/parseJsonConfigFileContent to return expected
parsed.options and parsed.fileNames and then asserting the created
parser.program reflects those compiler options/fileNames; (2) a test for an
invalid userTsconfigPath where typescript.readConfigFile returns an error—mock
typescript.flattenDiagnosticMessageText and ensure logger.warn is called with
the expected message and that getParser does not throw (it falls back to
cachedCompilerOptions and returns a parser), using mocks for
reactDocgenTypescript.withCompilerOptions to verify parser.fileParser is
constructed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5b942f41-25f3-4dfe-8fc1-4f6d456beea5

📥 Commits

Reviewing files that changed from the base of the PR and between 659db06 and b641009.

📒 Files selected for processing (1)
  • code/renderers/react/src/componentManifest/reactDocgenTypescript.ts

@bae080311 bae080311 closed this Apr 17, 2026
@github-project-automation github-project-automation Bot moved this from Empathy Queue (prioritized) to Done in Core Team Projects Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Documentation]: TypeScript parseJsonConfigFileContent() Doesn't Follow References

2 participants