Skip to content

Maintenance: Extract shared React docgen resolver to internal/common#34620

Open
BrenoSI03 wants to merge 5 commits into
storybookjs:nextfrom
BrenoSI03:refactor-docgen-resolver-34442
Open

Maintenance: Extract shared React docgen resolver to internal/common#34620
BrenoSI03 wants to merge 5 commits into
storybookjs:nextfrom
BrenoSI03:refactor-docgen-resolver-34442

Conversation

@BrenoSI03
Copy link
Copy Markdown

@BrenoSI03 BrenoSI03 commented Apr 24, 2026

Closes #34442

What I did

Extracted the duplicated docgen-resolver.ts implementation shared by react-vite and react-webpack into a common utility.

This PR:

  • Adds code/core/src/common/utils/docgen-resolver.ts
  • Exports the shared resolver utilities from storybook/internal/common
  • Updates both react-vite and react-webpack to re-export ReactDocgenResolveError, RESOLVE_EXTENSIONS, and defaultLookupModule from the shared location
  • Removes the duplicated implementation and the previous cross-file “watch out” comments

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

Manual testing

  1. Installed dependencies with yarn.
  2. Ran focused type checks:
    • yarn nx check react-vite
    • yarn nx check react-webpack
  3. Ran focused unit tests:
    • yarn test code/frameworks/react-vite/src/plugins/react-docgen.test.ts
    • yarn exec vitest run --config code/frameworks/react-vite/vitest.config.ts code/presets/react-webpack/src/loaders/react-docgen-loader.test.ts
  4. Validated the React Vite sandbox flow:
    • yarn task e2e-tests-dev --template react-vite/default-ts --start-from auto

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

🦋 Canary release

This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the @storybookjs/core team here.

core team members can create a canary release here or locally with gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER>

Summary by CodeRabbit

  • Extracted the duplicated React docgen resolver implementation into code/core/src/common/utils/docgen-resolver.ts.
  • Re-exported ReactDocgenResolveError, RESOLVE_EXTENSIONS, and defaultLookupModule through storybook/internal/common.
  • Updated the react-vite and react-webpack docgen resolver files to use the shared implementation.
  • Removed duplicated resolver logic and obsolete cross-file maintenance comments.
  • Verified the change with focused type checks, unit tests, and the React Vite sandbox E2E dev flow.

Summary by CodeRabbit

  • New Features

    • Exposes a shared docgen resolver and related utilities from the core common package for broader consumption.
  • Refactor

    • Centralized docgen module resolution into a single internal implementation; framework and preset packages now re-export it, unifying resolution behavior across environments while preserving the public API.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 24, 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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 19fcced3-cfce-4ab2-a36a-af169e1f7164

📥 Commits

Reviewing files that changed from the base of the PR and between aa17d1c and aae6d0f.

📒 Files selected for processing (1)
  • code/core/src/common/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • code/core/src/common/index.ts

📝 Walkthrough

Walkthrough

Consolidates react-docgen resolver into code/core/src/common/utils/docgen-resolver.ts and exposes it via code/core/src/common/index.ts; framework and preset files now re-export ReactDocgenResolveError, RESOLVE_EXTENSIONS, and defaultLookupModule from the shared common module.

Changes

Docgen resolver consolidation

Layer / File(s) Summary
Core docgen resolver implementation
code/core/src/common/utils/docgen-resolver.ts
Adds ReactDocgenResolveError (class), RESOLVE_EXTENSIONS (string[]), two ResolverFactory instances, resolveSync helper, and defaultLookupModule(filename, basedir) which resolves synchronously and falls back by rewriting .js/.mjs/.cjs → try .ts then .tsx, .jsx.tsx.
Expose via common index
code/core/src/common/index.ts
Adds export * from './utils/docgen-resolver.ts'; to surface the new resolver utilities through the common public API.
Framework / Preset re-exports
code/frameworks/react-vite/src/plugins/docgen-resolver.ts, code/presets/react-webpack/src/loaders/docgen-resolver.ts
Removed local resolver implementations and replaced them with re-exports of ReactDocgenResolveError, RESOLVE_EXTENSIONS, and defaultLookupModule from storybook/internal/common.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
code/core/src/common/utils/docgen-resolver.ts (2)

36-81: Consolidate the React renderer's defaultLookupModule function to use the shared implementation.

A third copy of defaultLookupModule still exists at code/renderers/react/src/componentManifest/reactDocgen/docgenResolver.ts and uses supportedExtensions instead of the new RESOLVE_EXTENSIONS constant. While the react-vite and react-webpack copies have been successfully deduplicated, leaving this implementation behind re-introduces the divergence risk that #34442 addresses. Consider importing from code/core/src/common/utils/docgen-resolver.ts in this PR, or file a follow-up to prevent future drift.

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

In `@code/core/src/common/utils/docgen-resolver.ts` around lines 36 - 81, The
React renderer still has a duplicate defaultLookupModule that uses
supportedExtensions instead of the shared RESOLVE_EXTENSIONS; remove the local
implementation in the React docgen resolver and import the canonical
defaultLookupModule (which already uses RESOLVE_EXTENSIONS) from the common
utils, updating any callers to use that import instead of the local function so
both the React renderer and core share the same implementation.

25-26: Remove .ctsx and .mtsx from the resolver—these are not valid TypeScript extensions.

TypeScript officially supports .ts, .tsx, .mts, and .cts (TS 4.5+), but not .ctsx or .mtsx. These extensions have no standard recognition in the TypeScript compiler and are effectively dead entries that will never match real files on disk. Remove them to keep the resolver surface accurate.

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

In `@code/core/src/common/utils/docgen-resolver.ts` around lines 25 - 26, Remove
the invalid TypeScript extensions '.ctsx' and '.mtsx' from the resolver's
extensions list in code/core/src/common/utils/docgen-resolver.ts; locate the
array of file extension strings (the extensions list used by the resolver) and
delete the '.ctsx' and '.mtsx' entries so only valid extensions like '.ts',
'.tsx', '.mts', and '.cts' remain.
🤖 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/core/src/common/utils/docgen-resolver.ts`:
- Around line 21-34: RESOLVE_EXTENSIONS contains duplicated entries
(specifically '.cts' and '.mts'); update the RESOLVE_EXTENSIONS constant to
remove duplicate extensions so each file extension appears only once (preserve
the intended order of extensions), e.g., edit the RESOLVE_EXTENSIONS array
declaration to deduplicate entries and ensure the final list includes each of
'.js', '.cts', '.mts', '.ctsx', '.mtsx', '.ts', '.tsx', '.mjs', '.cjs', '.jsx'
exactly once.

---

Nitpick comments:
In `@code/core/src/common/utils/docgen-resolver.ts`:
- Around line 36-81: The React renderer still has a duplicate
defaultLookupModule that uses supportedExtensions instead of the shared
RESOLVE_EXTENSIONS; remove the local implementation in the React docgen resolver
and import the canonical defaultLookupModule (which already uses
RESOLVE_EXTENSIONS) from the common utils, updating any callers to use that
import instead of the local function so both the React renderer and core share
the same implementation.
- Around line 25-26: Remove the invalid TypeScript extensions '.ctsx' and
'.mtsx' from the resolver's extensions list in
code/core/src/common/utils/docgen-resolver.ts; locate the array of file
extension strings (the extensions list used by the resolver) and delete the
'.ctsx' and '.mtsx' entries so only valid extensions like '.ts', '.tsx', '.mts',
and '.cts' remain.
🪄 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: a425371d-b755-4086-ac52-6be3e6a9780b

📥 Commits

Reviewing files that changed from the base of the PR and between b9549a6 and 1cc761c.

📒 Files selected for processing (4)
  • code/core/src/common/index.ts
  • code/core/src/common/utils/docgen-resolver.ts
  • code/frameworks/react-vite/src/plugins/docgen-resolver.ts
  • code/presets/react-webpack/src/loaders/docgen-resolver.ts

Comment thread code/core/src/common/utils/docgen-resolver.ts Outdated
@BrenoSI03 BrenoSI03 marked this pull request as draft April 24, 2026 11:43
@BrenoSI03 BrenoSI03 marked this pull request as ready for review April 24, 2026 22:54
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/docgen-resolver.ts (1)

56-64: Optional: restore the explanatory inline comment for slice(0, -2).

The renderer's parallel implementation carries a helpful note on this line ("removes js keeping the dot, e.g. Chip. or Chip.m") that didn't survive the extraction. Since this slice is the only non-obvious bit of the switch arm (it relies on .js/.mjs/.cjs all ending in js), preserving the comment here would help future maintainers.

📝 Suggested tweak
-        // Try .ts first, then fall back to .tsx (for React components using ESM-style .js imports)
-        const base = filename.slice(0, -2);
+        // Try .ts first, then fall back to .tsx (for React components using ESM-style .js imports)
+        const base = filename.slice(0, -2); // removes "js" keeping the dot, e.g. "Chip." or "Chip.m"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/core/src/common/utils/docgen-resolver.ts` around lines 56 - 64, Restore
an inline explanatory comment next to the slice operation where `base` is
computed (the line using `filename.slice(0, -2)` in docgen-resolver.ts)
clarifying that it removes the trailing "js" while keeping the dot (e.g., turns
"Chip.js" or "Chip.mjs" into "Chip." or "Chip.m") so future maintainers
understand why we strip exactly two characters before trying `${base}ts` and
`${base}tsx` in the `resolve.sync`/`newFilename` switch arm.
🤖 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/core/src/common/utils/docgen-resolver.ts`:
- Around line 56-64: Restore an inline explanatory comment next to the slice
operation where `base` is computed (the line using `filename.slice(0, -2)` in
docgen-resolver.ts) clarifying that it removes the trailing "js" while keeping
the dot (e.g., turns "Chip.js" or "Chip.mjs" into "Chip." or "Chip.m") so future
maintainers understand why we strip exactly two characters before trying
`${base}ts` and `${base}tsx` in the `resolve.sync`/`newFilename` switch arm.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b95a1de2-6f45-45a6-be8d-317b8e4a4d94

📥 Commits

Reviewing files that changed from the base of the PR and between 1cc761c and 2d3b701.

📒 Files selected for processing (1)
  • code/core/src/common/utils/docgen-resolver.ts

@@ -0,0 +1,79 @@
import { extname } from 'node:path';

import resolve from 'resolve';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

resolve was recently replaced by oxc-resolver. Could you rebase on next and do the necessary adjustments?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Sure, I'll rebase on next and update the necessary adjustments. Thanks for the feedback!

@valentinpalkovic valentinpalkovic self-assigned this May 21, 2026
@valentinpalkovic valentinpalkovic moved this from Empathy Queue (prioritized) to Blocked in Core Team Projects May 21, 2026
@valentinpalkovic valentinpalkovic moved this from Blocked to On Hold in Core Team Projects May 21, 2026
@BrenoSI03 BrenoSI03 force-pushed the refactor-docgen-resolver-34442 branch from e35b435 to b39e187 Compare May 21, 2026 11:05
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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@code/core/src/common/utils/docgen-resolver.ts`:
- Around line 34-40: The ResolverFactory instances docgenResolver and
docgenResolverExact are missing conditionNames which causes conditional
"exports" resolution failures; update both new ResolverFactory({ ... }) calls to
include a conditionNames array appropriate for the runtime (for Storybook/ESM
use ["node","import"], for CJS callers use ["node","require"]) so that
ResolverFactory({ extensions: [...RESOLVE_EXTENSIONS], conditionNames:
["node","import"] }) and ResolverFactory({ extensions: [], conditionNames:
["node","require"] }) (or the inverse depending on the caller context) are used
to ensure proper conditional exports resolution.
🪄 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: 607491aa-2779-47a3-952d-38137602915b

📥 Commits

Reviewing files that changed from the base of the PR and between 2d3b701 and b39e187.

📒 Files selected for processing (3)
  • code/core/src/common/index.ts
  • code/core/src/common/utils/docgen-resolver.ts
  • code/frameworks/react-vite/src/plugins/docgen-resolver.ts
💤 Files with no reviewable changes (1)
  • code/frameworks/react-vite/src/plugins/docgen-resolver.ts

Comment on lines +34 to +40
const docgenResolver = new ResolverFactory({
extensions: [...RESOLVE_EXTENSIONS],
});

const docgenResolverExact = new ResolverFactory({
extensions: [],
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="code/core/src/common/utils/docgen-resolver.ts"
echo "== File: $FILE =="
if [ ! -f "$FILE" ]; then
  echo "Missing file: $FILE" >&2
  exit 1
fi

# Show a focused window around the reported lines
nl -ba "$FILE" | sed -n '1,120p'

# Also search within the file for ResolverFactory usage and conditionNames
echo "== ResolverFactory occurrences =="
rg -n "new ResolverFactory|conditionNames|RESOLVE_EXTENSIONS|docgenResolverExact|docgenResolver" "$FILE" || true

Repository: storybookjs/storybook

Length of output: 185


🌐 Web query:

oxc-resolver ResolverFactory conditionNames default [] recommended ["node","import"] ["node","require"]

💡 Result:

In the oxc-resolver, the default value for the conditionNames configuration option is an empty array: []. While the default is empty, the library documentation and standard practice recommend configuring conditionNames based on the target module environment to correctly resolve the "exports" field in package.json files [1][2][3]. Common recommended configurations include: ["node", "import"] when the caller is an ESM (ECMAScript Module) import [1][4][3]. ["node", "require"] when the caller is a CJS (CommonJS) require [1][4][3]. Because condition matching is order-dependent, earlier entries in the array take higher priority [5][6][7]. For projects requiring both CJS and ESM support, it is common to initialize a base resolver and then use cloneWithOptions to generate separate resolvers for each environment [1][4][3]. Failing to provide appropriate conditionNames can lead to resolution errors, such as "Package subpath '.' is not defined by 'exports'" [2][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="code/core/src/common/utils/docgen-resolver.ts"

echo "== Showing docgen-resolver.ts (lines 1-140) =="
sed -n '1,140p' "$FILE" | cat -n

echo "== Focus (lines 20-100) =="
sed -n '20,100p' "$FILE" | cat -n

echo "== ResolverFactory usage in this file =="
rg -n "new ResolverFactory|conditionNames|RESOLVE_EXTENSIONS|docgenResolverExact|docgenResolver" "$FILE" || true

echo "== ResolverFactory usage across core utils =="
rg -n "new ResolverFactory" code/core/src/common/utils || true

Repository: storybookjs/storybook

Length of output: 6102


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the other ResolverFactory usage
FILE="code/core/src/common/utils/interpret-files.ts"
echo "== File: $FILE =="
sed -n '1,120p' "$FILE" | cat -n

# Global search for conditionNames usage with oxc-resolver/ResolverFactory
echo "== Search for conditionNames in core =="
rg -n "conditionNames" code/core/src/common || true

echo "== Search for ResolverFactory options containing conditionNames across repo =="
rg -n "new ResolverFactory\\([\\s\\S]*conditionNames" code || true

echo "== Search for ResolverFactory constructor usage across repo (short) =="
rg -n "new ResolverFactory\\(" code/core/src/common/utils code/core/src/common || true

Repository: storybookjs/storybook

Length of output: 3037


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find all call sites of defaultLookupModule
rg -n "defaultLookupModule\\(" code/core/src | head -n 50

# Find where react-docgen uses the lookup module
rg -n "docgen-resolver|resolveSync\\(|ReactDocgenResolveError" code/core/src | head -n 80

# Search for .ctsx/.mtsx usage in repo
rg -n "\\.ctsx|\\.mtsx" code/core/src | head -n 80

Repository: storybookjs/storybook

Length of output: 1859


🌐 Web query:

TypeScript support for .ctsx and .mtsx file extensions

💡 Result:

Answer: TypeScript supports the.cts and.mts file extensions, including JSX variants named.ctsx and.mtsx. In particular, TypeScript’s ESM-in-Node documentation states that TypeScript emits.mts to.mjs and.cts to.cjs [1]. For JSX-typed variants, TypeScript’s TypeScript/JXS ecosystem documentation describes.tsx for JSX, and TypeScript’s internal design discussions explicitly mention wanting TS to recognize “.mtsx” & “.ctsx” [2]. However, separate runtime support (Node.js native TypeScript execution) explicitly lists.tsx as unsupported (and does not mention.ctsx/.mtsx), so even if TypeScript can typecheck/emit, Node’s “full” native TS runtime support won’t run them directly without a transform tool/bundler [3]. What you should take away (practical): 1) If your goal is TypeScript compilation (typecheck + emit) with NodeNext-style ESM/CJS behavior, use.mts/.cts (and.mtsx/.ctsx as JSX-containing variants). TypeScript’s ESM-in-Node docs say it will emit.mts →.mjs and.cts →.cjs [1]. 2) For JSX, TypeScript requires JSX processing settings (the canonical approach is.tsx with the jsx compiler option) [4]. 3) If you’re relying on Node.js to execute TypeScript files directly (no bundler/transform), Node’s TypeScript runtime support says “.tsx files are unsupported” [3]. That implies you cannot rely on Node-native execution for JSX-capable TSX variants (including any hypothetical.ctsx/.mtsx usage) without a tool that compiles/transforms them. Caveat: The sources above confirm intent/recognition for.mtsx/.ctsx and the general emit mapping for.mts/.cts, but the Node.js docs only explicitly cover the unsupported status of.tsx for native execution, not the native execution status of.ctsx/.mtsx specifically [3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "defaultLookupModule\\b" . || true
rg -n "docgen-resolver\\.ts|docgen-resolver|defaultLookupModule\\(" . || true
rg -n "RESOLVE_EXTENSIONS|docgenResolverExact|docgenResolver\\.sync" . || true

Repository: storybookjs/storybook

Length of output: 4336


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILES=(
  "code/renderers/react/src/componentManifest/reactDocgen/docgenResolver.ts"
  "code/frameworks/react-vite/src/plugins/docgen-resolver.ts"
  "code/frameworks/react-vite/src/plugins/react-docgen.ts"
  "code/presets/react-webpack/src/loaders/docgen-resolver.ts"
)

for f in "${FILES[@]}"; do
  echo "== $f =="
  if [ -f "$f" ]; then
    sed -n '1,160p' "$f" | cat -n
  else
    echo "Missing: $f" >&2
  fi
  echo
done

echo "== Search conditionNames in these files =="
rg -n "conditionNames" code/renderers/react/src/componentManifest/reactDocgen/docgenResolver.ts code/frameworks/react-vite/src/plugins/docgen-resolver.ts code/frameworks/react-vite/src/plugins/react-docgen.ts code/presets/react-webpack/src/loaders/docgen-resolver.ts || true

Repository: storybookjs/storybook

Length of output: 8463


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect package.json type fields near the code being executed.
# Prefer top-level package.json and code/ (workspace) packages.
find . -maxdepth 4 -name package.json | sed 's|^\./||' | head -n 50

echo "== top-level package.json type =="
cat package.json | rg -n "\"type\"\\s*:" || true

echo "== code/core package.json type (if exists) =="
if [ -f code/core/package.json ]; then
  cat code/core/package.json | rg -n "\"type\"\\s*:" || true
fi

echo "== code/package.json type (if exists) =="
if [ -f code/package.json ]; then
  cat code/package.json | rg -n "\"type\"\\s*:" || true
fi

Repository: storybookjs/storybook

Length of output: 2189


🌐 Web query:

oxc-resolver conditionNames empty default behavior exports resolution implicit conditions

💡 Result:

In the oxc-resolver, the default value for conditionNames is an empty list (empty array) [1][2][3]. The behavior regarding exports resolution when conditionNames is empty is as follows: 1. Strict Requirement: If a package uses the exports field in its package.json, the resolver requires explicit conditionNames to resolve subpaths correctly [1][4]. If you attempt to resolve a package with an exports field while conditionNames is empty, the resolver will typically fail with an error such as Package subpath '.' is not defined by "exports" [1][5]. 2. No Implicit Defaults: Unlike some other resolution algorithms that may apply implicit or platform-specific default conditions (like "node" or "import") automatically, the oxc-resolver expects the user to explicitly configure the appropriate conditions for their target environment (e.g., ["node", "import"] for ESM or ["node", "require"] for CJS) [1][5]. 3. Resolution Logic: When conditionNames is provided, the resolver uses those conditions to match entries within the exports field. The order of these conditions is significant, with earlier entries having higher priority [2][3]. In summary, the empty default for conditionNames acts as an opt-in mechanism for exports resolution. Users must configure these conditions based on the expected runtime environment (ESM vs. CJS) to successfully traverse and resolve entries defined within a package's exports field [5][6].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect package.json type fields near the code being executed.
# Prefer top-level package.json and code/ (workspace) packages.
find . -maxdepth 4 -name package.json | sed 's|^\./||' | head -n 50

echo "== top-level package.json type =="
cat package.json | rg -n "\"type\"\\s*:" || true

echo "== code/core package.json type (if exists) =="
if [ -f code/core/package.json ]; then
  cat code/core/package.json | rg -n "\"type\"\\s*:" || true
fi

echo "== code/package.json type (if exists) =="
if [ -f code/package.json ]; then
  cat code/package.json | rg -n "\"type\"\\s*:" || true
fi

Repository: storybookjs/storybook

Length of output: 2189


🌐 Web query:

oxc-resolver conditionNames empty default behavior exports resolution implicit conditions

💡 Result:

Answer (grounded in sources): In oxc-resolver, the “conditions” used to match a package.json “exports” field come from ResolveOptions.condition_names (the JS/TS option name is typically conditionNames). The ResolveOptions docs show condition_names defaults to an empty list (condition_names: <>) [1][2]. When conditionNames is empty (or otherwise not set), oxc-resolver can fail to match conditional exports; in particular, the repo docs/examples mention the error “Package subpath '.' is not defined by "exports" in …” occurring when resolving without conditionNames [3][4]. What “default behavior” is otherwise depends on the caller type: - oxc-resolver documentation describes the conditional environment names expected for ESM vs CJS: ESM imports should use conditionNames ["node","import"], while CJS requires should use ["node","require"] [5][6]. - Downstream tooling (example: Rspack) documents that its default conditionNames are mode/target/module-type dependent, and that you can override them via resolve.conditionNames [7]. Key point for your query terms: - “conditionNames empty default behavior exports resolution implicit conditions” → In oxc-resolver, conditionNames corresponds to condition_names, and when it’s empty you do not get any default conditional environment; matching can therefore fail for conditional exports (and you may see the “subpath '.' is not defined by exports” error) [1][2][3][4]. - If you want correct conditional exports resolution, you must provide the appropriate implicit condition set for the module kind (typically ["node","import"] for ESM or ["node","require"] for CJS as described in the project docs) [5][6].

Citations:


Set conditionNames on these ResolverFactory instances to avoid conditional exports resolution failures.

code/core/src/common/utils/docgen-resolver.ts constructs both docgenResolver and docgenResolverExact via new ResolverFactory({ extensions: ... }) without conditionNames. oxc-resolver defaults conditionNames to [], which can trigger errors like Package subpath ... is not defined by "exports" when resolving packages using conditional exports. Configure conditionNames for the runtime module kind (storybook runs as ESM: ["node","import"]; CJS callers: ["node","require"]) on both resolver instances. https://github.com/oxc-project/oxc-resolver

🤖 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/docgen-resolver.ts` around lines 34 - 40, The
ResolverFactory instances docgenResolver and docgenResolverExact are missing
conditionNames which causes conditional "exports" resolution failures; update
both new ResolverFactory({ ... }) calls to include a conditionNames array
appropriate for the runtime (for Storybook/ESM use ["node","import"], for CJS
callers use ["node","require"]) so that ResolverFactory({ extensions:
[...RESOLVE_EXTENSIONS], conditionNames: ["node","import"] }) and
ResolverFactory({ extensions: [], conditionNames: ["node","require"] }) (or the
inverse depending on the caller context) are used to ensure proper conditional
exports resolution.

BrenoSI03 added 3 commits May 21, 2026 08:17
…ng the same pattern used in interpret-files.ts — module-level ResolverFactory instances (one with the full extension list, one with extensions: [] for exact-match fallbacks). The JS → TS fallback logic is preserved.
@BrenoSI03 BrenoSI03 force-pushed the refactor-docgen-resolver-34442 branch from b39e187 to aa17d1c Compare May 21, 2026 11:18
@valentinpalkovic valentinpalkovic moved this from On Hold to In Progress in Core Team Projects May 22, 2026
@storybook-app-bot
Copy link
Copy Markdown

storybook-app-bot Bot commented May 22, 2026

Package Benchmarks

Commit: aae6d0f, ran on 28 May 2026 at 08:17:48 UTC

No significant changes detected, all good. 👏

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

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

Duplicate Code: docgen-resolver.ts Identical in react-vite and react-webpack

2 participants