Skip to content

Conversation

@kasperpeulen
Copy link
Contributor

@kasperpeulen kasperpeulen commented Oct 31, 2025

Closes #

What I did

image

The idea is:

  • If it is a relative import, override the import with the package name instead
  • Allow the package name to be overridden in main.ts.
    This might not be enough in various scenarios:
  • If there are subpath exports used.
  • If there are even multiple packages used in a monorepo.
  • If you want to use the MCP server for local development.
    For all those scenarios, I think we should recommend:
  • import the component in your stories file using an absolute import (package/alias/sub path import)
  • users can easily make this work using tsconfig paths

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

This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!

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 pull request has been released as version 0.0.0-pr-32912-sha-d9cc661f. Try it out in a new sandbox by running npx [email protected] sandbox or in an existing project with npx [email protected] upgrade.

More information
Published version 0.0.0-pr-32912-sha-d9cc661f
Triggered by @kasperpeulen
Repository storybookjs/storybook
Branch kasper/manifest-auto-import
Commit d9cc661f
Datetime Mon Nov 3 21:55:23 UTC 2025 (1762206923)
Workflow run 19050536283

To request a new release of this pull request, mention the @storybookjs/core team.

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

Summary by CodeRabbit

  • New Features

    • Added an Imports block on component pages for resolved import statements.
    • Stories can show optional Summary and Description beneath each story.
  • Improvements

    • Error groups now sorted to highlight larger groups first.
    • Increased vertical spacing around visible panels and improved code-block styling (wrapping, monospace, size limits).
    • Faster, more reliable component/import resolution with caching and path handling.
  • Tests

    • Expanded tests for import extraction, manifest generation, docgen, and utilities.
  • Chores

    • Added a new development dependency.

@nx-cloud
Copy link

nx-cloud bot commented Oct 31, 2025

View your CI Pipeline Execution ↗ for commit d9cc661

Command Status Duration Result
nx run-many -t build --parallel=3 ✅ Succeeded 44s View ↗

☁️ Nx Cloud last updated this comment at 2025-11-03 22:09:55 UTC

Base automatically changed from kasper/change-examples-to-stories to next October 31, 2025 22:44
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 1, 2025

📝 Walkthrough

Walkthrough

Adds AST-driven import extraction and merged import strings to the React component manifest, enriches per-story metadata (summary/description), integrates cached react-docgen with tsconfig path mapping, updates manifest UI to render an Imports block and panel CSS, and adds memoization utilities plus extensive tests and fixtures.

Changes

Cohort / File(s) Summary
UI Manifest Rendering
code/core/src/core-server/manifest.ts
Sorts errorGroups by descending length; adds CSS for panel margins and wrapped code blocks; renders an "Imports" pre/code block when manifest.import exists; renders optional per-story Summary and Description blocks.
Component Manifest Generator
code/renderers/react/src/componentManifest/generator.ts, code/renderers/react/src/componentManifest/generator.test.ts
Converts generator signature to PresetPropertyFn<'experimental_componentManifestGenerator'>; adds cache invalidation and cached I/O; finds nearest package.json and packageName; calls getComponentImports; integrates getReactDocgen results; improves error handling and per-story metadata; tests updated to use fs mocks and adjusted snapshots.
Import Extraction Utility & Tests
code/renderers/react/src/componentManifest/getComponentImports.ts, .../getComponentImports.test.ts
New module that extracts component refs from CSF AST and synthesizes merged, dependency-aware import declarations (handles default/named/namespace/alias, relative→package rewrites, importOverride); extensive test coverage added.
React Docgen & Tests
code/renderers/react/src/componentManifest/reactDocgen.ts, .../reactDocgen.test.ts
Reworks docgen flow: adds path mapping (matchPath/getTsConfig), cached parsing and importer, recursive gathering of docgens, discriminated union return `{type:'success'
Memoization Utilities & Tests
code/renderers/react/src/componentManifest/utils.ts, .../utils.test.ts
Adds module-level cached (sync/async-aware), invalidateCache, cachedReadFileSync, cachedFindUp, cachedResolveImport; adjusts groupBy initialization; tests for caching and invalidation added.
Test Fixtures
code/renderers/react/src/componentManifest/test-utils.ts
Adds exported fsMocks mapping virtual file paths to contents used by tests (package.json, stories, components).
Core Types
code/core/src/types/modules/core-common.ts
Extends ComponentManifest per-story entries to include optional description?: string and summary?: string.
Build / Dev Server Typing & Errors
code/core/src/core-server/build-static.ts, code/core/src/core-server/dev-server.ts
Removes explicit local TypeScript annotations for componentManifestGenerator; dev-server error handlers assert Error type and include error stacks in HTML responses.
Renderer Dependency
code/renderers/react/package.json
Adds devDependency empathic -> ^2.0.0.
Test Setup / Misc
code/renderers/react/vitest.setup.ts, code/vitest-setup.ts, code/addons/vitest/tsconfig.json
Calls invalidateCache() after each test teardown, adds a verbose mock logger method, and removes a trailing comma in tsconfig.json.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Presets as Presets.apply
    participant Generator as componentManifestGenerator
    participant FindUp as cachedFindUp
    participant FS as cachedReadFileSync
    participant CSF as CSF parser
    participant Imports as getComponentImports
    participant Docgen as getReactDocgen
    Note over Generator,FindUp: resolve nearest package.json & tsconfig (cached)
    Presets->>Generator: invoke experimental_componentManifestGenerator
    Generator->>FindUp: find nearest package.json / tsconfig
    FindUp-->>Generator: path(s)
    Generator->>FS: read package.json -> packageName
    Generator->>CSF: read & parse story file (CSF AST)
    CSF-->>Generator: csf AST
    Generator->>Imports: getComponentImports(csf, packageName, storyFilePath)
    Imports-->>Generator: { components[], imports[] }
    Generator->>Docgen: getReactDocgen(componentPath, componentRef)
    Docgen-->>Generator: { success | error }
    Generator->>Generator: assemble manifest entry (imports, reactDocgen, jsDocTags, stories...)
    Generator-->>Presets: return component manifest map
Loading
sequenceDiagram
    autonumber
    participant UI as Manifest UI
    participant Card as renderComponentCard
    UI->>Card: render component card with manifest
    Card->>Card: check manifest.import and per-story metadata
    alt manifest.import present
        Card->>UI: render "Imports" pre/code block under component/story section
    end
    alt story has summary/description
        Card->>UI: render Summary and Description blocks under the story
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Pay extra attention to:
    • getComponentImports.ts — AST traversal, import binding, namespace/default merging, relative→package rewrites.
    • generator.ts — package resolution, caching interactions, manifest shape and error cases.
    • reactDocgen.ts — path mapping, cached parsing/importer, and discriminated union error shapes.
    • Tests & fixtures — fsMocks, empathic/find mocks, and snapshot updates.

Possibly related PRs

✨ Finishing touches
  • 📝 Generate docstrings

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

Copy link
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: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
code/core/src/core-server/manifest.ts (1)

610-614: Update warning message to reflect automatic import derivation.

The warning message references the @import JSDoc tag, but the new implementation automatically derives imports from the package name. This guidance may confuse users who expect automatic import handling.

Consider updating the message to:

-    warns.push(
-      `Specify an @import jsdoc tag on your component or your stories meta such as @import import { ${c.name} } from 'my-design-system';`
-    );
+    warns.push(
+      `Import could not be automatically determined. Ensure your component is imported from a package, or manually specify an @import JSDoc tag: @import import { ${c.name} } from 'my-design-system';`
+    );
🧹 Nitpick comments (2)
code/renderers/react/src/componentManifest/getComponentImports.ts (2)

59-86: Add comment explaining the Bucket data structure.

The Bucket type and its purpose in organizing imports per source could benefit from a comment to improve maintainability.

+  // Bucket: groups import specifiers by source, tracking defaults, namespaces, named imports, and encounter order
   type Bucket = {
     source: t.StringLiteral;
     defaults: t.Identifier[];
     namespaces: t.Identifier[];
     named: t.ImportSpecifier[];
     order: number;
   };

120-136: Document the default import conversion logic.

The logic for converting default imports to named imports when rewriting relative paths is non-obvious and would benefit from a brief comment explaining the rationale.

       if (t.isImportDefaultSpecifier(s)) {
         if (isRelToPkg) {
-          // Convert default to named when rewriting relative -> package
+          // Convert default to named when rewriting relative -> package
+          // This ensures consistent import style: import { Button } from 'package' instead of import Button from 'package'
           const id = s.local;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d0ff07 and 2b072ba.

⛔ Files ignored due to path filters (1)
  • code/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (6)
  • code/core/src/core-server/manifest.ts (3 hunks)
  • code/renderers/react/package.json (1 hunks)
  • code/renderers/react/src/componentManifest/generator.test.ts (11 hunks)
  • code/renderers/react/src/componentManifest/generator.ts (4 hunks)
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts (1 hunks)
  • code/renderers/react/src/componentManifest/getComponentImports.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
code/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

code/**/*.{test,spec}.{ts,tsx}: Place all test files under the code/ directory
Name test files as *.test.ts, *.test.tsx, *.spec.ts, or *.spec.tsx

Files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/spy-mocking.mdc)

**/*.test.{ts,tsx,js,jsx}: Use vi.mock() with the spy: true option for all package and file mocks in Vitest tests
Place all mocks at the top of the test file before any test cases
Use vi.mocked() to type and access mocked functions
Implement mock behaviors in beforeEach blocks
Mock all required dependencies that the test subject uses
Mock implementations should be placed in beforeEach blocks
Each mock implementation should return a Promise for async functions
Mock implementations should match the expected return type of the original function
Use vi.mocked() to access and implement mock behaviors
Mock all required properties and methods that the test subject uses
Avoid direct function mocking without vi.mocked()
Avoid mock implementations outside of beforeEach blocks
Avoid mocking without the spy: true option
Avoid inline mock implementations within test cases
Avoid mocking only a subset of required dependencies
Mock at the highest level of abstraction needed
Keep mock implementations simple and focused
Use type-safe mocking with vi.mocked()
Document complex mock behaviors
Group related mocks together

Files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/getComponentImports.ts
  • code/renderers/react/package.json
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/core-server/manifest.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
**/*.@(test|spec).{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.@(test|spec).{ts,tsx,js,jsx}: Unit tests should import and execute the functions under test rather than only asserting on syntax patterns
Mock external dependencies in tests using vi.mock() (e.g., filesystem, loggers)

Files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Export functions from modules when they need to be unit-tested

Files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/getComponentImports.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/core-server/manifest.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
code/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/getComponentImports.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/core-server/manifest.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/getComponentImports.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/core-server/manifest.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
🧠 Learnings (21)
📓 Common learnings
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Document complex mock behaviors

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking only a subset of required dependencies

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock all required dependencies that the test subject uses

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Group related mocks together

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock all required properties and methods that the test subject uses

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Keep mock implementations simple and focused

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid inline mock implementations within test cases

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to test-storybooks/** : Maintain test Storybook configurations under `test-storybooks/` for E2E and visual testing scenarios

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.@(test|spec).{ts,tsx,js,jsx} : Mock external dependencies in tests using `vi.mock()` (e.g., filesystem, loggers)

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock at the highest level of abstraction needed

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use vi.mocked() to access and implement mock behaviors

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use vi.mocked() to type and access mocked functions

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use vi.mock() with the spy: true option for all package and file mocks in Vitest tests

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use type-safe mocking with vi.mocked()

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid direct function mocking without vi.mocked()

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to code/.storybook/** : Place internal UI Storybook configuration in `code/.storybook/` and maintain it there

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-10-01T15:24:01.060Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.

Applied to files:

  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/README.md : Update package or feature README files when making significant changes

Applied to files:

  • code/core/src/core-server/manifest.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.@(test|spec).{ts,tsx,js,jsx} : Unit tests should import and execute the functions under test rather than only asserting on syntax patterns

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.{ts,tsx,js,jsx,mjs} : Export functions from modules when they need to be unit-tested

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
🧬 Code graph analysis (4)
code/renderers/react/src/componentManifest/generator.test.ts (2)
code/renderers/react/src/componentManifest/generator.ts (1)
  • componentManifestGenerator (22-170)
code/core/src/core-server/utils/StoryIndexGenerator.ts (1)
  • StoryIndexGenerator (104-874)
code/renderers/react/src/componentManifest/getComponentImports.ts (1)
code/core/src/csf-tools/CsfFile.ts (1)
  • CsfFile (281-1042)
code/renderers/react/src/componentManifest/generator.ts (2)
code/core/src/types/modules/core-common.ts (1)
  • PresetPropertyFn (650-655)
code/renderers/react/src/componentManifest/getComponentImports.ts (1)
  • getComponentImports (11-238)
code/renderers/react/src/componentManifest/getComponentImports.test.ts (2)
code/renderers/react/src/componentManifest/getComponentImports.ts (1)
  • getComponentImports (11-238)
code/core/src/csf-tools/CsfFile.ts (1)
  • loadCsf (1060-1064)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Danger JS
  • GitHub Check: normal
🔇 Additional comments (14)
code/renderers/react/package.json (1)

70-70: LGTM!

The empathic devDependency is appropriately added to support the new package.json path resolution functionality used in tests.

code/core/src/core-server/manifest.ts (2)

529-535: LGTM!

The vertical spacing logic correctly applies margin only when panels are visible, improving the layout consistency.


548-565: LGTM!

The code block styling improvements provide better wrapping behavior for long lines and consistent typography. The inline-size: min(100%, 120ch) constraint is a good choice for readability.

code/renderers/react/src/componentManifest/generator.test.ts (2)

10-23: LGTM!

The mock for storybook/internal/common properly uses importOriginal to preserve existing exports while adding the JsPackageManagerFactory mock for testing package name resolution.


227-230: LGTM!

The generator invocation correctly passes the configDir option and uses optional chaining to handle potentially undefined return values, aligning with the updated generator signature.

code/renderers/react/src/componentManifest/generator.ts (2)

22-24: LGTM!

The function signature correctly uses PresetPropertyFn to provide proper typing and parameter structure, aligning with Storybook's preset system conventions.


79-79: LGTM!

The import field correctly uses the calculated imports, integrating the automatic import derivation into the manifest structure.

code/renderers/react/src/componentManifest/getComponentImports.test.ts (4)

9-13: LGTM!

The helper function getImports provides a clean abstraction for test setup, making the test cases more readable and maintainable.


15-44: LGTM!

The test correctly verifies component extraction from JSX and import reconstruction, covering both meta.component and JSX element usage.


337-357: LGTM!

The test properly validates the conversion of relative default imports to named imports when a packageName is provided, which is a key feature of the automatic import handling.


427-459: LGTM!

Excellent test coverage for import merging behavior, verifying that multiple imports from the same package are correctly consolidated while preserving default/named import distinctions.

code/renderers/react/src/componentManifest/getComponentImports.ts (3)

4-9: LGTM!

The helper functions provide clean abstractions for JSX name handling and base identifier extraction, improving code readability.


11-44: LGTM!

The component collection logic correctly identifies React components by:

  • Scanning JSX opening elements for uppercase-starting identifiers
  • Handling JSX member expressions (e.g., UI.Button)
  • Including meta.component when present

173-235: LGTM!

The import declaration merging logic correctly handles the complex rules for combining default, namespace, and named imports:

  • Namespaces cannot be combined with named imports
  • Defaults can be combined with named imports
  • Multiple defaults/namespaces require separate statements

The implementation preserves encounter order and properly deduplicates imports.

Comment on lines +520 to 527
.card > .tg-warn:checked ~ .panels .panel-warn {
display: grid;
}
.card > .tg-stories:checked ~ .panels .panel-stories {
display: grid;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove or complete empty CSS rule blocks.

These CSS rule blocks appear to be incomplete or placeholder code. They should either be removed or completed with the intended styles.

-      
-      .card > .tg-warn:checked ~ .panels .panel-warn {
-          display: grid;
-      }
-      
-      .card > .tg-stories:checked ~ .panels .panel-stories {
-          display: grid;
-      }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.card > .tg-warn:checked ~ .panels .panel-warn {
display: grid;
}
.card > .tg-stories:checked ~ .panels .panel-stories {
display: grid;
}
🤖 Prompt for AI Agents
In code/core/src/core-server/manifest.ts around lines 520 to 527, there are two
CSS rule blocks that look like incomplete placeholders (.card > .tg-warn:checked
~ .panels .panel-warn and .card > .tg-stories:checked ~ .panels .panel-stories);
either remove these rules entirely if they are not needed, or complete them with
the intended panel styles (for example set grid-template-columns/rows, gap,
align-items, padding, and any show/hide behavior) so they’re not empty
placeholders — choose one of those two options and update the file accordingly.

Comment on lines +782 to +793
${
c.import
? `<div class="note ok">
<div class="row">
<span class="ex-name">Imports</span>
</div>
<pre><code>${c.import}</code></pre>
</div>`
: ''
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Escape import content to prevent XSS.

The import string c.import is rendered without escaping, which could lead to XSS vulnerabilities if the import content contains malicious HTML/script tags.

Apply the esc() function:

           ${
             c.import
               ? `<div class="note ok">
                 <div class="row">
                   <span class="ex-name">Imports</span>
                 </div>
-                <pre><code>${c.import}</code></pre>
+                <pre><code>${esc(c.import)}</code></pre>
               </div>`
               : ''
           }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In code/core/src/core-server/manifest.ts around lines 782 to 793, the template
renders c.import unescaped which can lead to XSS; replace the raw interpolation
with an escaped value (e.g., use esc(c.import) or esc(String(c.import))) when
inserting into the <pre><code> block, and ensure the esc function is
imported/available in this module; keep the conditional logic the same but wrap
the displayed content in esc(...) to prevent HTML/script injection.

Comment on lines +27 to +29
vi.mock('empathic/find', async () => ({
up: (path: string) => '/app/package.json',
}));
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Mock empathic/find without spy: true option.

According to the coding guidelines, all package and file mocks in Vitest tests should use vi.mock() with the spy: true option.

As per coding guidelines

Apply this diff:

-vi.mock('empathic/find', async () => ({
+vi.mock('empathic/find', { spy: true }, async () => ({
   up: (path: string) => '/app/package.json',
 }));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
vi.mock('empathic/find', async () => ({
up: (path: string) => '/app/package.json',
}));
vi.mock('empathic/find', async () => ({
up: (path: string) => '/app/package.json',
}), { spy: true });
🤖 Prompt for AI Agents
In code/renderers/react/src/componentManifest/generator.test.ts around lines
27-29, the Vitest mock for 'empathic/find' is missing the required spy option;
update the vi.mock call to pass the options object with { spy: true } as the
third argument while keeping the async factory intact (i.e.,
vi.mock('empathic/find', async () => ({ up: (path: string) =>
'/app/package.json' }), { spy: true })).

Comment on lines 63 to 69
const nearestPkg = find.up('package.json', {
cwd: path.dirname(storyAbsPath),
last: process.cwd(),
});
const packageName = nearestPkg
? JSON.parse(await readFile(nearestPkg, 'utf-8')).name
: undefined;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add error handling for package.json parsing.

The JSON.parse call on Line 68 could throw if the package.json file is malformed. Consider wrapping it in a try-catch block to prevent uncaught exceptions.

         const nearestPkg = find.up('package.json', {
           cwd: path.dirname(storyAbsPath),
           last: process.cwd(),
         });
-        const packageName = nearestPkg
-          ? JSON.parse(await readFile(nearestPkg, 'utf-8')).name
-          : undefined;
+        let packageName: string | undefined;
+        if (nearestPkg) {
+          try {
+            packageName = JSON.parse(await readFile(nearestPkg, 'utf-8')).name;
+          } catch (e) {
+            // Skip if package.json is malformed
+            packageName = undefined;
+          }
+        }
🤖 Prompt for AI Agents
In code/renderers/react/src/componentManifest/generator.ts around lines 63–69,
the direct JSON.parse of the nearest package.json can throw on malformed JSON;
wrap the parse in a try/catch so a bad package.json does not crash the process —
read the file as before, then attempt JSON.parse inside a try block, on success
set packageName to the parsed.name, on error catch and set packageName =
undefined (and optionally log a warning with the file path and error) so
execution continues safely.

Copy link
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: 7

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 835417c and 8ba3b0b.

📒 Files selected for processing (1)
  • code/renderers/react/src/componentManifest/getComponentImports.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.ts
**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Export functions from modules when they need to be unit-tested

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.ts
code/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.ts
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.
🧬 Code graph analysis (1)
code/renderers/react/src/componentManifest/getComponentImports.ts (1)
code/core/src/csf-tools/CsfFile.ts (1)
  • CsfFile (281-1042)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (7)
code/renderers/react/src/componentManifest/getComponentImports.ts (7)

4-18: LGTM! Clean and focused helper functions.

The helper functions are well-structured and handle their specific tasks correctly. The use of optional chaining in baseIdentifier and the generic addUniqueBy pattern are good practices.


27-60: LGTM! Correct component detection logic.

The traversal correctly identifies React components by uppercase naming convention and properly handles both simple identifiers and member expressions (e.g., UI.Button). The inclusion of meta.component ensures comprehensive component detection.


117-159: LGTM! Correct filtering and namespace handling.

The logic correctly distinguishes between locally-defined and imported components, preventing local components from appearing in the import list. The namespace member extraction properly handles dotted notation like UI.Button.


207-240: LGTM! Intelligent import rewriting and namespace expansion.

The code correctly handles the conversion of relative imports to package imports:

  • Default imports are converted to named imports (lines 207-214)
  • Namespace imports are expanded to only the members actually used (lines 222-240)
  • Both conversions only occur for relative imports being rewritten to package imports

This selective expansion preserves the original import style for non-relative imports while enabling cleaner package imports.


254-325: LGTM! Correct ES module import generation.

The import declaration generation correctly handles all valid ES module import combinations:

  • Properly combines default with namespace in a single statement
  • Separates named imports from namespace imports (per ES module spec)
  • Correctly handles multiple defaults/namespaces with separate statements
  • Respects encounter order for deterministic output

327-347: LGTM! Clean component metadata generation.

The component object building correctly handles both simple identifiers and member expressions, properly extracting import metadata for each component. The final sort ensures deterministic output.


104-107: I need to examine the test case and the implementation more closely to understand how this conversion is handled and whether errors are accounted for.<!-- [scratchpad_start]
[task review_file_1/1 review_segment_3/9 verify_default_import_assumption]
Gather direct evidence from test and implementation

[observations]

  • Web search results don't provide specific storybook component manifest information
  • Test file at line 409 is named "Converts default relative import to named when packageName provided"
  • Need to directly inspect test and implementation to verify behavior
  • Original review comment concerns about name assumptions need direct code evidence

[analysis]

  • Test exists but haven't seen what it expects
  • May need to look directly at test case to understand expected behavior
  • The concern is real per JS module semantics, but may be handled or documented

[pending]

  • Get test case details
  • Check implementation for error handling
  • Verify if this is by design or a limitation

[actions]
Query the test file directly to see test expectations and implementation logic
[scratchpad_start] -->

Based on my investigation, I need to examine the actual test and implementation code to verify whether the assumption mentioned in the review comment is handled appropriately. The test from line 409 explicitly names this behavior "Converts default relative import to named when packageName provided," which indicates this is intentional. However, I need to confirm whether this is documented, tested, and whether error cases are handled.

Verify the assumptions about named export availability when converting default imports to package imports.

When converting a relative default import to a package import, the generated code assumes the package exports a named export matching the local name. This is indeed intentional (confirmed by the test case naming at line 409), but verify whether:

  1. This limitation is documented in comments or PR description
  2. Error handling exists for cases where the named export doesn't match
  3. Tests cover both success and failure scenarios

If this is a known limitation intended for initial release, document it clearly in code comments. If runtime failures are possible, consider adding validation or fallback logic.

Comment on lines 290 to 294
// Remaining defaults: each in its own statement

// Remaining defaults: each in its own statement

// Remaining defaults: each in its own statement
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove duplicate comments.

The comment "// Remaining defaults: each in its own statement" appears three times on consecutive lines (290-294).

Apply this diff:

       }
 
       // Remaining defaults: each in its own statement
-
-      // Remaining defaults: each in its own statement
-
-      // Remaining defaults: each in its own statement
       for (const d of defaults.slice(1)) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Remaining defaults: each in its own statement
// Remaining defaults: each in its own statement
// Remaining defaults: each in its own statement
}
// Remaining defaults: each in its own statement
for (const d of defaults.slice(1)) {
🤖 Prompt for AI Agents
In code/renderers/react/src/componentManifest/getComponentImports.ts around
lines 290 to 294, there are three duplicate consecutive comments "// Remaining
defaults: each in its own statement"; remove the redundant duplicates so the
comment appears only once (keep a single instance on the most appropriate line)
to eliminate repetition and clutter.

Comment on lines 299 to 303
// Remaining namespaces: each in its own statement

// Remaining namespaces: each in its own statement

// Remaining namespaces: each in its own statement
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove duplicate comments.

The comment "// Remaining namespaces: each in its own statement" appears three times on consecutive lines (299-303).

Apply this diff:

       }
 
       // Remaining namespaces: each in its own statement
-
-      // Remaining namespaces: each in its own statement
-
-      // Remaining namespaces: each in its own statement
       for (const ns of namespaces.slice(1)) {
🤖 Prompt for AI Agents
In code/renderers/react/src/componentManifest/getComponentImports.ts around
lines 299 to 303, there are three identical consecutive comments "// Remaining
namespaces: each in its own statement"; remove the duplicate comments leaving a
single instance of that comment (or remove all if redundant) so the code has no
repeated comment lines and retains one clear comment where needed.

Copy link
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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ba3b0b and ce25a2f.

📒 Files selected for processing (2)
  • code/core/src/core-server/build-static.ts (1 hunks)
  • code/core/src/core-server/dev-server.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/core/src/core-server/build-static.ts
  • code/core/src/core-server/dev-server.ts
**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Export functions from modules when they need to be unit-tested

Files:

  • code/core/src/core-server/build-static.ts
  • code/core/src/core-server/dev-server.ts
code/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/core/src/core-server/build-static.ts
  • code/core/src/core-server/dev-server.ts
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/core/src/core-server/build-static.ts
  • code/core/src/core-server/dev-server.ts
🧬 Code graph analysis (2)
code/core/src/core-server/build-static.ts (2)
code/renderers/react/src/componentManifest/generator.ts (1)
  • componentManifestGenerator (25-206)
code/renderers/react/src/preset.ts (1)
  • componentManifestGenerator (11-11)
code/core/src/core-server/dev-server.ts (3)
code/renderers/react/src/componentManifest/generator.ts (1)
  • componentManifestGenerator (25-206)
code/renderers/react/src/preset.ts (1)
  • componentManifestGenerator (11-11)
code/core/src/types/modules/core-common.ts (1)
  • ComponentManifestGenerator (365-367)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: normal
  • GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (1)
code/core/src/core-server/build-static.ts (1)

170-172: LGTM! Type inference from preset system.

The removal of the explicit ComponentManifestGenerator type annotation allows TypeScript to infer the correct type from presets.apply(). This aligns with the updated generator signature that now uses PresetPropertyFn<'experimental_componentManifestGenerator'>.

@shilman shilman added manifest Component manifest generation react labels Nov 2, 2025
@storybook-app-bot
Copy link

storybook-app-bot bot commented Nov 2, 2025

Package Benchmarks

Commit: d9cc661, ran on 3 November 2025 at 21:59:04 UTC

The following packages have significant changes to their size or dependencies:

@storybook/nextjs

Before After Difference
Dependency count 533 533 0
Self size 749 KB 749 KB 0 B
Dependency size 58.93 MB 58.95 MB 🚨 +18 KB 🚨
Bundle Size Analyzer Link Link

@storybook/nextjs-vite

Before After Difference
Dependency count 124 124 0
Self size 3.83 MB 3.83 MB 🚨 +72 B 🚨
Dependency size 21.76 MB 21.78 MB 🚨 +17 KB 🚨
Bundle Size Analyzer Link Link

@storybook/react-native-web-vite

Before After Difference
Dependency count 157 157 0
Self size 31 KB 31 KB 0 B
Dependency size 23.11 MB 23.13 MB 🚨 +17 KB 🚨
Bundle Size Analyzer Link Link

@storybook/react-vite

Before After Difference
Dependency count 114 114 0
Self size 37 KB 37 KB 🎉 -24 B 🎉
Dependency size 19.67 MB 19.69 MB 🚨 +17 KB 🚨
Bundle Size Analyzer Link Link

@storybook/react-webpack5

Before After Difference
Dependency count 273 273 0
Self size 25 KB 25 KB 🎉 -36 B 🎉
Dependency size 43.89 MB 43.91 MB 🚨 +18 KB 🚨
Bundle Size Analyzer Link Link

@storybook/react

Before After Difference
Dependency count 57 57 0
Self size 812 KB 830 KB 🚨 +17 KB 🚨
Dependency size 12.94 MB 12.94 MB 🚨 +12 B 🚨
Bundle Size Analyzer Link Link

Copy link
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: 2

♻️ Duplicate comments (2)
code/renderers/react/src/componentManifest/generator.ts (2)

58-59: Guard JSON.parse on package.json (duplicate of prior feedback).

JSON.parse will throw on malformed package.json, crashing manifest generation. Please wrap the parse in try/catch (as previously requested) so a bad file doesn’t break the process.


65-66: Use || so the fallback import triggers (duplicate of prior feedback).

.trim() returns '' for empty imports, and ?? treats that as a valid value. Use || fallbackImport so we actually fall back when no imports were discovered.

-        const calculatedImports = componentImports.imports.join('\n').trim() ?? fallbackImport;
+        const calculatedImports = componentImports.imports.join('\n').trim() || fallbackImport;
🧹 Nitpick comments (1)
code/renderers/react/src/componentManifest/reactDocgen.ts (1)

60-75: Caches are never populated.

getReactDocgenCache and getTsConfigCache are cleared and read, but no code ever stores results into them. This leaves cache hits impossible and makes invalidateCache() meaningless. Please assign the freshly computed values to the respective maps before returning so repeated lookups can benefit from the cache.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between acf5925 and 2a05fc4.

📒 Files selected for processing (2)
  • code/renderers/react/src/componentManifest/generator.ts (5 hunks)
  • code/renderers/react/src/componentManifest/reactDocgen.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Export functions from modules when they need to be unit-tested

Files:

  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
code/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.
📚 Learning: 2025-10-01T15:24:01.060Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.

Applied to files:

  • code/renderers/react/src/componentManifest/generator.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.{ts,tsx,js,jsx,mjs} : Export functions from modules when they need to be unit-tested

Applied to files:

  • code/renderers/react/src/componentManifest/reactDocgen.ts
🧬 Code graph analysis (2)
code/renderers/react/src/componentManifest/generator.ts (6)
code/core/src/types/modules/core-common.ts (2)
  • ComponentManifest (348-358)
  • PresetPropertyFn (650-655)
code/renderers/react/src/componentManifest/reactDocgen.ts (4)
  • DocObj (22-26)
  • invalidateCache (62-65)
  • matchPath (46-58)
  • getReactDocgen (78-137)
code/core/src/csf-tools/CsfFile.ts (2)
  • loadCsf (1060-1064)
  • stories (968-970)
code/renderers/react/src/componentManifest/getComponentImports.ts (1)
  • getComponentImports (20-348)
code/core/src/common/utils/interpret-files.ts (1)
  • resolveImport (25-58)
code/renderers/react/src/componentManifest/generateCodeSnippet.ts (1)
  • getCodeSnippet (6-227)
code/renderers/react/src/componentManifest/reactDocgen.ts (3)
code/core/src/common/utils/interpret-files.ts (1)
  • supportedExtensions (6-17)
code/core/src/common/utils/paths.ts (1)
  • getProjectRoot (11-57)
code/renderers/react/src/componentManifest/jsdocTags.ts (1)
  • extractJSDocInfo (5-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: normal
  • GitHub Check: Core Unit Tests, windows-latest

Comment on lines 83 to 87
resolved = resolveImport(matchedPath, { basedir: dirname(storyAbsPath) });
componentPath = resolved;
} catch (e) {
console.error(e);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Use Storybook’s logger instead of console.error.

Per repository guidelines for code/** modules, use storybook/internal/client-logger or storybook/internal/node-logger rather than the raw console. Please swap this call to the appropriate logger.

🤖 Prompt for AI Agents
In code/renderers/react/src/componentManifest/generator.ts around lines 83 to
87, replace the console.error usage with Storybook's node logger: import the
logger from "storybook/internal/node-logger" at the top of the file (e.g.,
import { logger } from 'storybook/internal/node-logger') and change
console.error(e) to logger.error with the error (and brief context message).
Ensure the import is added only once and use logger.error(...) in the catch so
the error is reported via Storybook's logging system.

Copy link
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

♻️ Duplicate comments (3)
code/renderers/react/src/componentManifest/generator.ts (3)

53-59: Add error handling for package.json parsing.

The JSON.parse call could throw if the package.json file is malformed. Consider wrapping it in a try-catch block to prevent uncaught exceptions.

Apply this diff to add error handling:

 const nearestPkg = find.up('package.json', {
   cwd: path.dirname(storyAbsPath),
   last: process.cwd(),
 });
-const packageName = nearestPkg
-  ? JSON.parse(await readFile(nearestPkg, 'utf-8')).name
-  : undefined;
+let packageName: string | undefined;
+if (nearestPkg) {
+  try {
+    packageName = JSON.parse(await readFile(nearestPkg, 'utf-8')).name;
+  } catch (e) {
+    // Skip if package.json is malformed
+    packageName = undefined;
+  }
+}

61-65: Fix logical operator for empty string fallback.

The ?? (nullish coalescing) operator only checks for null or undefined, but .trim() on an empty string returns '' (which is falsy but not nullish). Use || instead to properly fallback when the trimmed result is an empty string.

Apply this diff:

-const calculatedImports = componentImports.imports.join('\n').trim() ?? fallbackImport;
+const calculatedImports = componentImports.imports.join('\n').trim() || fallbackImport;

75-88: Use Storybook's logger instead of console.error.

Per repository guidelines for code/** modules, use storybook/internal/node-logger rather than the raw console.

Based on coding guidelines.

Apply this diff:

+import { logger } from 'storybook/internal/node-logger';
+
 // ... in the component path resolution block:
         try {
           resolved = resolveImport(matchedPath, { basedir: dirname(storyAbsPath) });
           componentPath = resolved;
         } catch (e) {
-          console.error(e);
+          logger.error('Failed to resolve component path:', e);
         }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2a05fc4 and 3de6fad.

📒 Files selected for processing (2)
  • code/renderers/react/src/componentManifest/generator.ts (5 hunks)
  • code/renderers/react/src/componentManifest/reactDocgen.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Export functions from modules when they need to be unit-tested

Files:

  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
code/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
🧠 Learnings (6)
📓 Common learnings
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to code/**/*.{ts,tsx,js,jsx,mjs} : In application code, use Storybook loggers instead of `console.*` (client code: `storybook/internal/client-logger`; server code: `storybook/internal/node-logger`)

Applied to files:

  • code/renderers/react/src/componentManifest/generator.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to scripts/**/*.{ts,js,mjs} : In Node.js scripts, use `storybook/internal/node-logger` instead of `console.*`

Applied to files:

  • code/renderers/react/src/componentManifest/generator.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to {code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs} : Do not use `console.log`, `console.warn`, or `console.error` directly unless in isolated files where importing loggers would significantly increase bundle size

Applied to files:

  • code/renderers/react/src/componentManifest/generator.ts
📚 Learning: 2025-10-01T15:24:01.060Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.

Applied to files:

  • code/renderers/react/src/componentManifest/generator.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.{ts,tsx,js,jsx,mjs} : Export functions from modules when they need to be unit-tested

Applied to files:

  • code/renderers/react/src/componentManifest/reactDocgen.ts
🧬 Code graph analysis (2)
code/renderers/react/src/componentManifest/generator.ts (4)
code/core/src/types/modules/core-common.ts (2)
  • ComponentManifest (348-358)
  • PresetPropertyFn (650-655)
code/renderers/react/src/componentManifest/reactDocgen.ts (4)
  • DocObj (23-27)
  • invalidateCache (63-66)
  • matchPath (47-59)
  • getReactDocgen (79-143)
code/renderers/react/src/componentManifest/getComponentImports.ts (1)
  • getComponentImports (20-348)
code/core/src/common/utils/interpret-files.ts (1)
  • resolveImport (25-58)
code/renderers/react/src/componentManifest/reactDocgen.ts (4)
code/core/src/common/utils/interpret-files.ts (1)
  • supportedExtensions (6-17)
code/core/src/common/utils/paths.ts (1)
  • getProjectRoot (11-57)
code/frameworks/react-vite/src/plugins/react-docgen.ts (1)
  • getReactDocgenImporter (100-130)
code/renderers/react/src/componentManifest/jsdocTags.ts (1)
  • extractJSDocInfo (5-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: normal
  • GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (15)
code/renderers/react/src/componentManifest/reactDocgen.ts (6)

34-45: LGTM - Enhanced matching logic with importName parameter.

The updated getMatchingDocgen function correctly prioritizes exportName match when importName is provided, falling back to displayName or actualName. The logic is sound and handles the single-docgen case efficiently.


47-59: LGTM - Path matching with tsconfig support.

The matchPath function correctly uses tsconfig-paths to resolve module paths according to the project's path mappings. The fallback to the original id when tsconfig resolution fails is appropriate.


61-66: LGTM - Cache invalidation for both caches.

The invalidateCache function correctly clears both the docgen cache and tsconfig cache.


79-143: LGTM - Robust getReactDocgen with comprehensive error handling.

The function correctly:

  • Caches results by path and importName
  • Handles file read failures with clear error messages
  • Distinguishes between missing definitions and parsing errors
  • Returns a discriminated union for type-safe error handling
  • Provides helpful debugging guidance for missing component definitions

Note: There's a minor race condition where simultaneous calls before caching could execute the expensive parse operation multiple times. This is unlikely to cause issues in practice but could be mitigated with async locking if needed.


145-170: LGTM - Simplified importer using internal matchPath.

The refactored getReactDocgenImporter correctly uses the internal matchPath function, simplifying the API while maintaining the react-native to react-native-web mapping.


172-176: LGTM - Import tag extraction.

The getImportTag function correctly extracts the import tag from JSDoc comments using extractJSDocInfo.

code/renderers/react/src/componentManifest/generator.ts (9)

2-2: LGTM - Imports support enhanced manifest generation.

The new and updated imports (dirname, resolveImport, component types, find, getComponentImports, docgen utilities) are all properly used in the updated manifest generation flow.

Also applies to: 5-11, 13-13, 17-17, 19-19


26-28: LGTM - Correct type annotation for preset property.

The function is properly typed as PresetPropertyFn<'experimental_componentManifestGenerator'>, which ensures type safety for the preset configuration.


30-30: LGTM - Cache invalidation at generator start.

Calling invalidateCache() at the beginning ensures fresh docgen and tsconfig data for each manifest generation run.


44-48: LGTM - Story file resolution and component extraction.

The code correctly resolves the story file path and extracts the component name from the CSF meta.


67-73: LGTM - Component matching with fallback assignment.

The logic correctly finds the component by matching local or import names, with appropriate fallback to title matching when componentName is not specified. The nullish assignment on Line 73 is a clean way to set componentName when it's initially undefined.


107-114: LGTM - Base manifest structure with import field.

The base manifest correctly includes all required fields including the new import field set to calculatedImports.


116-134: LGTM - Appropriate error handling for missing component.

The code correctly checks for missing componentPath and returns appropriate error messages distinguishing between missing meta.component and unresolvable component imports.


136-155: LGTM - Docgen integration with discriminated union handling.

The code correctly:

  • Calls getReactDocgen with componentPath and importName
  • Extracts docgen data and errors from the discriminated union
  • Populates the manifest with description, summary, import, and JSDoc tags
  • Includes the reactDocgen data and any errors in the final manifest

90-105: The review comment is incorrect. No changes needed.

The code properly handles cases where componentName is undefined through the existing invariant check in getCodeSnippet. When componentName is undefined and the function cannot generate a snippet, the invariant throws with a clear error message: "Could not generate snippet without component name." This error is caught by the try-catch block surrounding the getCodeSnippet call at line 90–105 in generator.ts, and the error is gracefully captured and returned as part of the stories array rather than crashing the entire process.

Likely an incorrect or invalid review comment.

Copy link
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: 0

♻️ Duplicate comments (1)
code/renderers/react/src/componentManifest/getComponentImports.ts (1)

108-108: Remove duplicate comment.

The comment "// missing binding -> keep (will become null import)" appears twice on line 108.

Apply this diff:

-    } // missing binding -> keep (will become null import) // missing binding -> keep (will become null import)
+    } // missing binding -> keep (will become null import)
🧹 Nitpick comments (1)
code/renderers/react/src/componentManifest/getComponentImports.ts (1)

23-27: Consider using a Set for deduplication.

The addUniqueBy helper uses array.find() for uniqueness checks, which can result in O(n²) behavior when called repeatedly in loops. For typical import counts this is unlikely to be problematic, but using a Set with custom keys would be more efficient.

Example approach:

// Track seen items with a Set of string keys
const addUniqueWithSet = <T>(
  arr: T[], 
  seen: Set<string>, 
  item: T, 
  keyFn: (a: T) => string
) => {
  const key = keyFn(item);
  if (!seen.has(key)) {
    seen.add(key);
    arr.push(item);
  }
};

Then maintain a Set<string> alongside each array (defaults, namespaces, named) in the bucket and use the Set for O(1) lookups.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3de6fad and 80b0ad2.

📒 Files selected for processing (2)
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts (1 hunks)
  • code/renderers/react/src/componentManifest/getComponentImports.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.ts
**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Export functions from modules when they need to be unit-tested

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.ts
code/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.ts
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.ts
🧠 Learnings (6)
📓 Common learnings
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.
📚 Learning: 2025-10-01T15:24:01.060Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.{ts,tsx,js,jsx,mjs} : Export functions from modules when they need to be unit-tested

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to {code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs} : Do not use `console.log`, `console.warn`, or `console.error` directly unless in isolated files where importing loggers would significantly increase bundle size

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid inline mock implementations within test cases

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.@(test|spec).{ts,tsx,js,jsx} : Unit tests should import and execute the functions under test rather than only asserting on syntax patterns

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.ts
🧬 Code graph analysis (1)
code/renderers/react/src/componentManifest/getComponentImports.ts (1)
code/core/src/csf-tools/CsfFile.ts (1)
  • CsfFile (281-1042)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: normal
  • GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (4)
code/renderers/react/src/componentManifest/getComponentImports.ts (4)

1-11: LGTM!

The imports and ComponentRef type definition are well-structured. The type clearly captures all necessary metadata for component import resolution.


29-158: Well-structured component extraction logic.

The getComponents function correctly:

  • Identifies React components from JSX (uppercase convention)
  • Handles member expressions (e.g., Namespace.Component)
  • Filters type-only imports at both declaration and specifier levels
  • Distinguishes imported components from locally-defined ones
  • Resolves namespace imports with member access

The logic for building localToImport and filtering locally-defined components is sound.


160-327: Complex but correct import merging logic.

The getImports function handles the intricate task of merging and rewriting import declarations. Key strengths:

  • Correctly respects ES module semantics (namespace imports can combine with default but not named specifiers)
  • Handles packageName rewrites by converting relative defaults to named and expanding namespaces to used members
  • Preserves original import order through the order field
  • Includes defensive guards for TypeScript (lines 216-218, 236-238, 256-258)

The logic for bucketing, rewriting, and printing is sound, though admittedly complex due to the various import shapes and rewrite rules.


329-339: LGTM!

The getComponentImports function provides a clean public API by orchestrating getComponents and getImports. The implementation is straightforward and well-typed.

Copy link
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: 2

♻️ Duplicate comments (2)
code/renderers/react/src/componentManifest/generator.test.ts (1)

11-35: Add spy: true to every Vitest mock.

Per the repository guidelines, all vi.mock() calls in tests must opt into spy: true. That’s currently missing for storybook/internal/common, node:fs/promises, node:fs, empathic/find, and tsconfig-paths. Please update each call accordingly. As per coding guidelines

Apply this diff:

-vi.mock('storybook/internal/common', async (importOriginal) => ({
+vi.mock('storybook/internal/common', async (importOriginal) => ({
   ...(await importOriginal()),
   // Keep it simple: hardcode known inputs to expected outputs for this test.
   resolveImport: (id: string) => {
     return {
       './Button': './src/stories/Button.tsx',
       './Header': './src/stories/Header.tsx',
     }[id];
   },
   JsPackageManagerFactory: {
     getPackageManager: () => ({
       primaryPackageJson: {
         packageJson: {
           name: 'some-package',
         },
       },
     }),
   },
-}));
-vi.mock('node:fs/promises', async () => (await import('memfs')).fs.promises);
-vi.mock('node:fs', async () => (await import('memfs')).fs);
+}), { spy: true });
+vi.mock('node:fs/promises', async () => (await import('memfs')).fs.promises, { spy: true });
+vi.mock('node:fs', async () => (await import('memfs')).fs, { spy: true });
 
-vi.mock('empathic/find', async () => ({
+vi.mock('empathic/find', async () => ({
   up: (path: string) => '/app/package.json',
-}));
-vi.mock('tsconfig-paths', () => ({ loadConfig: () => ({ resultType: null!, message: null! }) }));
+}), { spy: true });
+vi.mock('tsconfig-paths', () => ({ loadConfig: () => ({ resultType: null!, message: null! }) }), {
+  spy: true,
+});
code/renderers/react/src/componentManifest/generator.ts (1)

59-61: Add error handling for package.json parsing.

The JSON.parse call could throw if package.json is malformed. This was flagged in a previous review but remains unaddressed.

-        const packageName = nearestPkg
-          ? JSON.parse(await readFile(nearestPkg, 'utf-8')).name
-          : undefined;
+        let packageName: string | undefined;
+        if (nearestPkg) {
+          try {
+            packageName = JSON.parse(await readFile(nearestPkg, 'utf-8')).name;
+          } catch {
+            packageName = undefined;
+          }
+        }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 08bdc82 and 50be8d7.

📒 Files selected for processing (11)
  • code/core/src/core-server/manifest.ts (4 hunks)
  • code/core/src/types/modules/core-common.ts (1 hunks)
  • code/renderers/react/src/componentManifest/generator.test.ts (10 hunks)
  • code/renderers/react/src/componentManifest/generator.ts (5 hunks)
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts (1 hunks)
  • code/renderers/react/src/componentManifest/getComponentImports.ts (1 hunks)
  • code/renderers/react/src/componentManifest/reactDocgen.test.ts (1 hunks)
  • code/renderers/react/src/componentManifest/reactDocgen.ts (3 hunks)
  • code/renderers/react/src/componentManifest/test-utils.ts (1 hunks)
  • code/renderers/react/src/componentManifest/utils.test.ts (1 hunks)
  • code/renderers/react/src/componentManifest/utils.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • code/core/src/core-server/manifest.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • code/renderers/react/src/componentManifest/getComponentImports.ts
🧰 Additional context used
📓 Path-based instructions (7)
code/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

code/**/*.{test,spec}.{ts,tsx}: Place all test files under the code/ directory
Name test files as *.test.ts, *.test.tsx, *.spec.ts, or *.spec.tsx

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/reactDocgen.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/spy-mocking.mdc)

**/*.test.{ts,tsx,js,jsx}: Use vi.mock() with the spy: true option for all package and file mocks in Vitest tests
Place all mocks at the top of the test file before any test cases
Use vi.mocked() to type and access mocked functions
Implement mock behaviors in beforeEach blocks
Mock all required dependencies that the test subject uses
Mock implementations should be placed in beforeEach blocks
Each mock implementation should return a Promise for async functions
Mock implementations should match the expected return type of the original function
Use vi.mocked() to access and implement mock behaviors
Mock all required properties and methods that the test subject uses
Avoid direct function mocking without vi.mocked()
Avoid mock implementations outside of beforeEach blocks
Avoid mocking without the spy: true option
Avoid inline mock implementations within test cases
Avoid mocking only a subset of required dependencies
Mock at the highest level of abstraction needed
Keep mock implementations simple and focused
Use type-safe mocking with vi.mocked()
Document complex mock behaviors
Group related mocks together

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/reactDocgen.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/types/modules/core-common.ts
  • code/renderers/react/src/componentManifest/utils.ts
  • code/renderers/react/src/componentManifest/reactDocgen.test.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
  • code/renderers/react/src/componentManifest/test-utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
**/*.@(test|spec).{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.@(test|spec).{ts,tsx,js,jsx}: Unit tests should import and execute the functions under test rather than only asserting on syntax patterns
Mock external dependencies in tests using vi.mock() (e.g., filesystem, loggers)

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/reactDocgen.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Export functions from modules when they need to be unit-tested

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/types/modules/core-common.ts
  • code/renderers/react/src/componentManifest/utils.ts
  • code/renderers/react/src/componentManifest/reactDocgen.test.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
  • code/renderers/react/src/componentManifest/test-utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
code/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/types/modules/core-common.ts
  • code/renderers/react/src/componentManifest/utils.ts
  • code/renderers/react/src/componentManifest/reactDocgen.test.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
  • code/renderers/react/src/componentManifest/test-utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/types/modules/core-common.ts
  • code/renderers/react/src/componentManifest/utils.ts
  • code/renderers/react/src/componentManifest/reactDocgen.test.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
  • code/renderers/react/src/componentManifest/test-utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
🧠 Learnings (28)
📓 Common learnings
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.@(test|spec).{ts,tsx,js,jsx} : Unit tests should import and execute the functions under test rather than only asserting on syntax patterns

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking only a subset of required dependencies

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/test-utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.{ts,tsx,js,jsx,mjs} : Export functions from modules when they need to be unit-tested

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/reactDocgen.test.ts
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Document complex mock behaviors

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/test-utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid inline mock implementations within test cases

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/test-utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock all required dependencies that the test subject uses

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/test-utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Group related mocks together

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/test-utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Keep mock implementations simple and focused

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/test-utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock all required properties and methods that the test subject uses

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/test-utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
📚 Learning: 2025-10-01T15:24:01.060Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mock implementations outside of beforeEach blocks

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock implementations should be placed in beforeEach blocks

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to code/**/*.{ts,tsx,js,jsx,mjs} : In application code, use Storybook loggers instead of `console.*` (client code: `storybook/internal/client-logger`; server code: `storybook/internal/node-logger`)

Applied to files:

  • code/renderers/react/src/componentManifest/generator.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to scripts/**/*.{ts,js,mjs} : In Node.js scripts, use `storybook/internal/node-logger` instead of `console.*`

Applied to files:

  • code/renderers/react/src/componentManifest/generator.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to {code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs} : Do not use `console.log`, `console.warn`, or `console.error` directly unless in isolated files where importing loggers would significantly increase bundle size

Applied to files:

  • code/renderers/react/src/componentManifest/generator.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.@(test|spec).{ts,tsx,js,jsx} : Mock external dependencies in tests using `vi.mock()` (e.g., filesystem, loggers)

Applied to files:

  • code/renderers/react/src/componentManifest/test-utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock at the highest level of abstraction needed

Applied to files:

  • code/renderers/react/src/componentManifest/test-utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use vi.mocked() to access and implement mock behaviors

Applied to files:

  • code/renderers/react/src/componentManifest/test-utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Implement mock behaviors in beforeEach blocks

Applied to files:

  • code/renderers/react/src/componentManifest/test-utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to test-storybooks/** : Maintain test Storybook configurations under `test-storybooks/` for E2E and visual testing scenarios

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use vi.mock() with the spy: true option for all package and file mocks in Vitest tests

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking without the spy: true option

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid direct function mocking without vi.mocked()

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/utils.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use vi.mocked() to type and access mocked functions

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use type-safe mocking with vi.mocked()

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock implementations should match the expected return type of the original function

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to code/.storybook/** : Place internal UI Storybook configuration in `code/.storybook/` and maintain it there

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
🧬 Code graph analysis (7)
code/renderers/react/src/componentManifest/getComponentImports.test.ts (2)
code/renderers/react/src/componentManifest/test-utils.ts (1)
  • fsMocks (3-112)
code/renderers/react/src/componentManifest/getComponentImports.ts (2)
  • getImports (183-356)
  • getComponentImports (358-387)
code/renderers/react/src/componentManifest/generator.ts (7)
code/core/src/types/modules/core-common.ts (2)
  • ComponentManifest (348-364)
  • PresetPropertyFn (656-661)
code/renderers/react/src/componentManifest/reactDocgen.ts (2)
  • DocObj (24-28)
  • getReactDocgen (76-131)
code/renderers/react/src/componentManifest/utils.ts (1)
  • invalidateCache (95-99)
code/renderers/react/src/componentManifest/getComponentImports.ts (1)
  • getComponentImports (358-387)
code/core/src/csf-tools/enrichCsf.ts (1)
  • extractDescription (158-178)
code/renderers/react/src/componentManifest/jsdocTags.ts (1)
  • extractJSDocInfo (5-21)
code/renderers/react/src/componentManifest/generateCodeSnippet.ts (1)
  • getCodeSnippet (6-227)
code/renderers/react/src/componentManifest/reactDocgen.test.ts (1)
code/renderers/react/src/componentManifest/reactDocgen.ts (1)
  • parseWithReactDocgen (67-74)
code/renderers/react/src/componentManifest/reactDocgen.ts (4)
code/core/src/common/utils/interpret-files.ts (1)
  • supportedExtensions (6-17)
code/renderers/react/src/componentManifest/utils.ts (1)
  • cached (36-93)
code/core/src/common/utils/paths.ts (1)
  • getProjectRoot (11-57)
code/renderers/react/src/componentManifest/jsdocTags.ts (1)
  • extractJSDocInfo (5-21)
code/renderers/react/src/componentManifest/test-utils.ts (1)
scripts/utils/tools.ts (1)
  • dedent (118-118)
code/renderers/react/src/componentManifest/generator.test.ts (2)
code/renderers/react/src/componentManifest/test-utils.ts (1)
  • fsMocks (3-112)
code/renderers/react/src/componentManifest/generator.ts (1)
  • componentManifestGenerator (24-180)
code/renderers/react/src/componentManifest/utils.test.ts (1)
code/renderers/react/src/componentManifest/utils.ts (4)
  • groupBy (2-12)
  • invariant (15-23)
  • cached (36-93)
  • invalidateCache (95-99)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: normal
  • GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (12)
code/renderers/react/src/componentManifest/generator.ts (5)

71-71: Verify the nullish coalescing operator behavior with empty strings.

The ?? operator only catches null or undefined. When imports is empty, .join('\n').trim() returns '' (empty string), which is falsy but not nullish. If the intent is to fall back to fallbackImport when the trimmed result is empty, use || instead.

A previous review marked this as addressed, but the ?? operator is still present. Please confirm whether empty string should trigger the fallback.

-        const calculatedImports = componentImports.imports.join('\n').trim() ?? fallbackImport;
+        const calculatedImports = componentImports.imports.join('\n').trim() || fallbackImport;

46-48: LGTM: Manifest tag filtering at component level.

Correctly filters out components tagged with !manifest early in the pipeline.


73-87: LGTM: Comprehensive component resolution logic.

The component matching uses both name-based and title-based fallback strategies, with a clear precedence chain for componentName resolution. This handles various import patterns robustly.


95-97: LGTM: Story-level manifest tag filtering.

Properly excludes individual stories tagged with !manifest while still processing the component.


148-151: LGTM: Proper discriminated union handling for docgen results.

The docgen result handling correctly extracts data or error based on the discriminated type field, ensuring type safety.

code/renderers/react/src/componentManifest/reactDocgen.ts (7)

76-131: LGTM: Comprehensive error handling in getReactDocgen.

The function properly handles multiple error scenarios with structured error returns:

  • File read failures (lines 84-94)
  • Missing component definitions (lines 96-108, 114-115, 126-128)
  • General docgen evaluation failures (lines 117-123)

The discriminated union return type ensures type-safe error handling in consumers. The error messages are descriptive and include actionable guidance for users.


35-46: LGTM: Well-structured docgen matching logic.

The function correctly handles multiple matching strategies with clear precedence: single docgen, exportName match, displayName/actualName fallback, or first docgen as last resort.


48-60: LGTM: Proper tsconfig path resolution.

The matchPath function correctly loads tsconfig via the cached helper and uses tsconfig-paths to resolve module aliases with supported extensions. The nullish coalescing fallback is appropriate here.


67-74: LGTM: Clean docgen parsing wrapper.

The parseWithReactDocgen function properly configures react-docgen with custom resolver, handlers, importer, and filename for accurate parsing.


133-158: LGTM: React-native to react-native-web fallback logic.

The custom importer properly resolves imports via tsconfig paths, handles the react-native → react-native-web polyfill mapping, validates supported extensions, and throws descriptive errors for unsupported imports.


160-164: LGTM: Extraction of JSDoc import tag.

Correctly extracts the @import tag from component docgen description for manual import overrides.


62-65: Caching implementation is correct and properly memoizes getTsConfig.

The cached() wrapper correctly:

  • Derives stable cache keys from the cwd argument using JSON.stringify(args)
  • Populates the cache on first invocation (syncStore.set(k, result))
  • Returns cached results on subsequent calls with the same cwd without recomputing

Multiple calls to getTsConfig with the same working directory will hit the cache and avoid redundant tsconfig reloading.

Comment on lines +11 to +24
vi.mock('node:fs/promises', async () => (await import('memfs')).fs.promises);
vi.mock('node:fs', async () => (await import('memfs')).fs);
vi.mock('tsconfig-paths', () => ({ loadConfig: () => ({ resultType: null!, message: null! }) }));

// Mock resolveImport to deterministically resolve known relative imports for these tests
vi.mock('storybook/internal/common', async (importOriginal) => ({
...(await importOriginal()),
resolveImport: (id: string) => {
return {
'./Button': './src/stories/Button.tsx',
'./Header': './src/stories/Header.tsx',
}[id];
},
}));
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Ensure Vitest mocks use spy: true.

The coding guidelines require { spy: true } on every vi.mock() in tests. Please add the option to the mocks for node:fs/promises, node:fs, tsconfig-paths, and storybook/internal/common. As per coding guidelines

Apply this diff:

-vi.mock('node:fs/promises', async () => (await import('memfs')).fs.promises);
-vi.mock('node:fs', async () => (await import('memfs')).fs);
-vi.mock('tsconfig-paths', () => ({ loadConfig: () => ({ resultType: null!, message: null! }) }));
+vi.mock('node:fs/promises', async () => (await import('memfs')).fs.promises, { spy: true });
+vi.mock('node:fs', async () => (await import('memfs')).fs, { spy: true });
+vi.mock('tsconfig-paths', () => ({ loadConfig: () => ({ resultType: null!, message: null! }) }), {
+  spy: true,
+});
 
 // Mock resolveImport to deterministically resolve known relative imports for these tests
-vi.mock('storybook/internal/common', async (importOriginal) => ({
+vi.mock('storybook/internal/common', async (importOriginal) => ({
   ...(await importOriginal()),
   resolveImport: (id: string) => {
     return {
       './Button': './src/stories/Button.tsx',
       './Header': './src/stories/Header.tsx',
     }[id];
   },
-}));
+}), { spy: true });
🤖 Prompt for AI Agents
In code/renderers/react/src/componentManifest/getComponentImports.test.ts around
lines 11 to 24, the Vitest mocks are missing the required option { spy: true };
update each vi.mock call for 'node:fs/promises', 'node:fs', 'tsconfig-paths',
and 'storybook/internal/common' to include the { spy: true } argument (e.g.,
vi.mock('module', async () => ..., { spy: true })) so all mocks comply with the
coding guideline.

Copy link
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

♻️ Duplicate comments (6)
code/renderers/react/src/componentManifest/generator.test.ts (2)

11-35: Restore required spy: true on every Vitest mock
All module mocks still omit the { spy: true } option mandated by the repo test guidelines, so the previous feedback hasn’t been applied. Please add the spy flag to each vi.mock in this block.

-vi.mock('storybook/internal/common', async (importOriginal) => ({
+vi.mock('storybook/internal/common', async (importOriginal) => ({
   ...(await importOriginal()),
   resolveImport: (id: string) => {
     return {
       './Button': './src/stories/Button.tsx',
       './Header': './src/stories/Header.tsx',
     }[id];
   },
-}));
-vi.mock('node:fs/promises', async () => (await import('memfs')).fs.promises);
-vi.mock('node:fs', async () => (await import('memfs')).fs);
-vi.mock('empathic/find', async () => ({
+}), { spy: true });
+vi.mock('node:fs/promises', async () => (await import('memfs')).fs.promises, { spy: true });
+vi.mock('node:fs', async () => (await import('memfs')).fs, { spy: true });
+vi.mock('empathic/find', async () => ({
   up: (path: string) => '/app/package.json',
-}));
-vi.mock('tsconfig-paths', () => ({ loadConfig: () => ({ resultType: null!, message: null! }) }));
+}), { spy: true });
+vi.mock('tsconfig-paths', () => ({ loadConfig: () => ({ resultType: null!, message: null! }) }), {
+  spy: true,
+});

As per coding guidelines.


120-123: Seed memfs under /app
The virtual FS is still written at the default root, so the generator reads /app/... paths that don’t exist and the tests fail immediately. Please seed the volume under /app as previously requested.

-  vol.fromJSON(fsMocks);
+  vol.fromJSON(fsMocks, '/app');
code/renderers/react/src/componentManifest/generator.ts (2)

73-74: Use || so fallback imports work
trim() returns '', which isn’t nullish, so the fallback never executes and we emit empty import strings. This regresses manifest output (and triggers a warning). Please revert to ||.

-      const calculatedImports = componentImports.imports.join('\n').trim() ?? fallbackImport;
+      const calculatedImports = componentImports.imports.join('\n').trim() || fallbackImport;

57-63: Guard package.json parsing
JSON.parse can still throw on malformed package.json, collapsing manifest generation. Wrap it in try/catch so we degrade gracefully and continue without the package name.

-      const packageName = nearestPkg
-        ? JSON.parse(cachedReadFileSync(nearestPkg, 'utf-8') as string).name
-        : undefined;
+      let packageName: string | undefined;
+      if (nearestPkg) {
+        try {
+          packageName = JSON.parse(cachedReadFileSync(nearestPkg, 'utf-8') as string).name;
+        } catch (error) {
+          logger.warn(`Failed to parse ${nearestPkg}: ${(error as Error).message}`);
+        }
+      }
code/core/src/core-server/manifest.ts (1)

787-794: Escape c.import before rendering
We’re interpolating c.import directly into HTML, allowing crafted story metadata to inject arbitrary markup. Please wrap it with esc(...).

-                <pre><code>${c.import}</code></pre>
+                <pre><code>${esc(c.import)}</code></pre>
code/renderers/react/src/componentManifest/getComponentImports.test.ts (1)

11-24: Add { spy: true } to these mocks as well
The Vitest mocks in this file still miss the required spy configuration, so we’re not following the repo test rules. Please add { spy: true } to each vi.mock call.

-vi.mock('node:fs/promises', async () => (await import('memfs')).fs.promises);
-vi.mock('node:fs', async () => (await import('memfs')).fs);
-vi.mock('tsconfig-paths', () => ({ loadConfig: () => ({ resultType: null!, message: null! }) }));
+vi.mock('node:fs/promises', async () => (await import('memfs')).fs.promises, { spy: true });
+vi.mock('node:fs', async () => (await import('memfs')).fs, { spy: true });
+vi.mock('tsconfig-paths', () => ({ loadConfig: () => ({ resultType: null!, message: null! }) }), {
+  spy: true,
+});
 
 // Mock resolveImport to deterministically resolve known relative imports for these tests
-vi.mock('storybook/internal/common', async (importOriginal) => ({
+vi.mock('storybook/internal/common', async (importOriginal) => ({
   ...(await importOriginal()),
   resolveImport: (id: string) => {
     return {
       './Button': './src/stories/Button.tsx',
       './Header': './src/stories/Header.tsx',
     }[id];
   },
-}));
+}), { spy: true });

As per coding guidelines.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 50be8d7 and 70e8504.

📒 Files selected for processing (8)
  • code/core/src/core-server/dev-server.ts (3 hunks)
  • code/core/src/core-server/manifest.ts (4 hunks)
  • code/renderers/react/src/componentManifest/generator.test.ts (14 hunks)
  • code/renderers/react/src/componentManifest/generator.ts (2 hunks)
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts (1 hunks)
  • code/renderers/react/src/componentManifest/getComponentImports.ts (1 hunks)
  • code/renderers/react/src/componentManifest/reactDocgen.ts (3 hunks)
  • code/renderers/react/src/componentManifest/utils.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/core/src/core-server/dev-server.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/core-server/manifest.ts
  • code/renderers/react/src/componentManifest/getComponentImports.ts
  • code/renderers/react/src/componentManifest/utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Export functions from modules when they need to be unit-tested

Files:

  • code/core/src/core-server/dev-server.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/core-server/manifest.ts
  • code/renderers/react/src/componentManifest/getComponentImports.ts
  • code/renderers/react/src/componentManifest/utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
code/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/core/src/core-server/dev-server.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/core-server/manifest.ts
  • code/renderers/react/src/componentManifest/getComponentImports.ts
  • code/renderers/react/src/componentManifest/utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/core/src/core-server/dev-server.ts
  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/core-server/manifest.ts
  • code/renderers/react/src/componentManifest/getComponentImports.ts
  • code/renderers/react/src/componentManifest/utils.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
code/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

code/**/*.{test,spec}.{ts,tsx}: Place all test files under the code/ directory
Name test files as *.test.ts, *.test.tsx, *.spec.ts, or *.spec.tsx

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/spy-mocking.mdc)

**/*.test.{ts,tsx,js,jsx}: Use vi.mock() with the spy: true option for all package and file mocks in Vitest tests
Place all mocks at the top of the test file before any test cases
Use vi.mocked() to type and access mocked functions
Implement mock behaviors in beforeEach blocks
Mock all required dependencies that the test subject uses
Mock implementations should be placed in beforeEach blocks
Each mock implementation should return a Promise for async functions
Mock implementations should match the expected return type of the original function
Use vi.mocked() to access and implement mock behaviors
Mock all required properties and methods that the test subject uses
Avoid direct function mocking without vi.mocked()
Avoid mock implementations outside of beforeEach blocks
Avoid mocking without the spy: true option
Avoid inline mock implementations within test cases
Avoid mocking only a subset of required dependencies
Mock at the highest level of abstraction needed
Keep mock implementations simple and focused
Use type-safe mocking with vi.mocked()
Document complex mock behaviors
Group related mocks together

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
**/*.@(test|spec).{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.@(test|spec).{ts,tsx,js,jsx}: Unit tests should import and execute the functions under test rather than only asserting on syntax patterns
Mock external dependencies in tests using vi.mock() (e.g., filesystem, loggers)

Files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
🧠 Learnings (29)
📓 Common learnings
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.@(test|spec).{ts,tsx,js,jsx} : Unit tests should import and execute the functions under test rather than only asserting on syntax patterns

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking only a subset of required dependencies

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.{ts,tsx,js,jsx,mjs} : Export functions from modules when they need to be unit-tested

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Document complex mock behaviors

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid inline mock implementations within test cases

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock all required dependencies that the test subject uses

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Group related mocks together

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Keep mock implementations simple and focused

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock all required properties and methods that the test subject uses

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use vi.mock() with the spy: true option for all package and file mocks in Vitest tests

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking without the spy: true option

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.@(test|spec).{ts,tsx,js,jsx} : Mock external dependencies in tests using `vi.mock()` (e.g., filesystem, loggers)

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid direct function mocking without vi.mocked()

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use vi.mocked() to access and implement mock behaviors

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use vi.mocked() to type and access mocked functions

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use type-safe mocking with vi.mocked()

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-10-01T15:24:01.060Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/getComponentImports.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mock implementations outside of beforeEach blocks

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Implement mock behaviors in beforeEach blocks

Applied to files:

  • code/renderers/react/src/componentManifest/getComponentImports.test.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to code/**/*.{ts,tsx,js,jsx,mjs} : In application code, use Storybook loggers instead of `console.*` (client code: `storybook/internal/client-logger`; server code: `storybook/internal/node-logger`)

Applied to files:

  • code/renderers/react/src/componentManifest/generator.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to scripts/**/*.{ts,js,mjs} : In Node.js scripts, use `storybook/internal/node-logger` instead of `console.*`

Applied to files:

  • code/renderers/react/src/componentManifest/generator.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to {code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs} : Do not use `console.log`, `console.warn`, or `console.error` directly unless in isolated files where importing loggers would significantly increase bundle size

Applied to files:

  • code/renderers/react/src/componentManifest/generator.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to test-storybooks/** : Maintain test Storybook configurations under `test-storybooks/` for E2E and visual testing scenarios

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock at the highest level of abstraction needed

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock implementations should be placed in beforeEach blocks

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Place all mocks at the top of the test file before any test cases

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock implementations should match the expected return type of the original function

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to code/.storybook/** : Place internal UI Storybook configuration in `code/.storybook/` and maintain it there

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
🧬 Code graph analysis (6)
code/core/src/core-server/dev-server.ts (3)
code/renderers/react/src/componentManifest/generator.ts (1)
  • componentManifestGenerator (22-183)
code/renderers/react/src/preset.ts (1)
  • componentManifestGenerator (11-11)
code/renderers/react/src/componentManifest/utils.ts (1)
  • invariant (23-31)
code/renderers/react/src/componentManifest/getComponentImports.test.ts (3)
code/renderers/react/src/componentManifest/test-utils.ts (1)
  • fsMocks (3-112)
code/renderers/react/src/componentManifest/getComponentImports.ts (2)
  • getImports (188-438)
  • getComponentImports (440-468)
code/core/src/csf-tools/CsfFile.ts (1)
  • loadCsf (1060-1064)
code/renderers/react/src/componentManifest/generator.ts (7)
code/core/src/types/modules/core-common.ts (2)
  • ComponentManifest (348-364)
  • PresetPropertyFn (656-661)
code/renderers/react/src/componentManifest/reactDocgen.ts (2)
  • DocObj (23-27)
  • getReactDocgen (81-146)
code/renderers/react/src/componentManifest/utils.ts (4)
  • invalidateCache (117-121)
  • cachedReadFileSync (123-123)
  • cachedFindUp (125-125)
  • invariant (23-31)
code/renderers/react/src/componentManifest/getComponentImports.ts (1)
  • getComponentImports (440-468)
code/core/src/csf-tools/enrichCsf.ts (1)
  • extractDescription (158-178)
code/renderers/react/src/componentManifest/jsdocTags.ts (1)
  • extractJSDocInfo (5-21)
code/renderers/react/src/componentManifest/generateCodeSnippet.ts (1)
  • getCodeSnippet (6-227)
code/renderers/react/src/componentManifest/getComponentImports.ts (3)
code/renderers/react/src/componentManifest/utils.ts (1)
  • cached (44-115)
code/core/src/common/utils/interpret-files.ts (1)
  • resolveImport (25-58)
code/renderers/react/src/componentManifest/reactDocgen.ts (3)
  • matchPath (47-59)
  • getReactDocgen (81-146)
  • getImportTag (175-179)
code/renderers/react/src/componentManifest/generator.test.ts (3)
code/renderers/react/src/componentManifest/test-utils.ts (1)
  • fsMocks (3-112)
code/renderers/react/src/componentManifest/generator.ts (1)
  • componentManifestGenerator (22-183)
code/core/src/core-server/utils/StoryIndexGenerator.ts (1)
  • StoryIndexGenerator (104-874)
code/renderers/react/src/componentManifest/reactDocgen.ts (6)
code/core/src/common/utils/interpret-files.ts (1)
  • supportedExtensions (6-17)
code/renderers/react/src/componentManifest/utils.ts (2)
  • cached (44-115)
  • cachedReadFileSync (123-123)
code/core/src/common/utils/paths.ts (1)
  • getProjectRoot (11-57)
code/presets/react-webpack/src/loaders/react-docgen-loader.ts (1)
  • getReactDocgenImporter (150-169)
code/frameworks/react-vite/src/plugins/react-docgen.ts (1)
  • getReactDocgenImporter (100-130)
code/renderers/react/src/componentManifest/jsdocTags.ts (1)
  • extractJSDocInfo (5-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: normal
  • GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (1)
code/renderers/react/src/componentManifest/getComponentImports.ts (1)

1-11: Replace console.error with Storybook logger

Line 179 still emits console.error, which violates the repository rule to use Storybook’s loggers in code/**. Switch to storybook/internal/node-logger instead. As per coding guidelines.

 import { resolveImport } from 'storybook/internal/common';
 import { type CsfFile } from 'storybook/internal/csf-tools';
+import { logger } from 'storybook/internal/node-logger';
@@
-      } catch (e) {
-        console.error(e);
+      } catch (e) {
+        logger.error(
+          `Failed to resolve import "${component.importId}" from "${storyFilePath ?? 'unknown'}":`,
+          e
+        );
       }

[scratchpad_end -->
Oops need to correct comment this contains scratchpad closing? Wait we included [scratchpad_end?], we must keep comment.

Need to ensure comment ended properly: <!-- review_comment_end -->. Also remove stray [scratchpad_end --> we added by accident. Let's fix final snippet.

Redo comment:

Need to produce final comment with correct format, no stray.

Let's craft.

Also applies to: 178-180

Copy link
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

♻️ Duplicate comments (1)
code/renderers/react/src/componentManifest/generator.ts (1)

60-62: Add error handling for malformed package.json.

The JSON.parse call on line 61 can throw if package.json is malformed, potentially crashing the manifest generation. While cachedReadFileSync handles file I/O errors, it doesn't protect against invalid JSON.

Apply this diff to add a try-catch:

-      const packageName = nearestPkg
-        ? JSON.parse(cachedReadFileSync(nearestPkg, 'utf-8') as string).name
-        : undefined;
+      let packageName: string | undefined;
+      if (nearestPkg) {
+        try {
+          packageName = JSON.parse(cachedReadFileSync(nearestPkg, 'utf-8') as string).name;
+        } catch (e) {
+          // Skip if package.json is malformed
+          packageName = undefined;
+        }
+      }

This ensures manifest generation continues even if a package.json file is corrupted or syntactically invalid.

🧹 Nitpick comments (1)
code/renderers/react/src/componentManifest/reactDocgen.ts (1)

167-211: Consider using a more stable cache key.

Line 210 concatenates path + JSON.stringify(component) as the cache key. If the component object has properties added in non-deterministic order, this could produce different keys for semantically identical inputs, reducing cache effectiveness.

Consider using specific fields from component for the key:

-  { name: 'getReactDocgen', key: (path, component) => path + JSON.stringify(component) }
+  { 
+    name: 'getReactDocgen', 
+    key: (path, component) => 
+      `${path}:${component.componentName}:${component.importName ?? ''}:${component.localImportName ?? ''}`
+  }

Alternatively, ensure component properties are serialized in a stable order, or rely on the default JSON.stringify behavior if property insertion order is guaranteed in your runtime.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7ab7295 and d9cc661.

📒 Files selected for processing (4)
  • code/renderers/react/src/componentManifest/generator.ts (2 hunks)
  • code/renderers/react/src/componentManifest/getComponentImports.ts (1 hunks)
  • code/renderers/react/src/componentManifest/reactDocgen.ts (3 hunks)
  • code/renderers/react/src/componentManifest/utils.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • code/renderers/react/src/componentManifest/getComponentImports.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/renderers/react/src/componentManifest/utils.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Export functions from modules when they need to be unit-tested

Files:

  • code/renderers/react/src/componentManifest/utils.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
code/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/renderers/react/src/componentManifest/utils.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/renderers/react/src/componentManifest/utils.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/renderers/react/src/componentManifest/reactDocgen.ts
🧠 Learnings (5)
📓 Common learnings
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to code/**/*.{ts,tsx,js,jsx,mjs} : In application code, use Storybook loggers instead of `console.*` (client code: `storybook/internal/client-logger`; server code: `storybook/internal/node-logger`)

Applied to files:

  • code/renderers/react/src/componentManifest/generator.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to scripts/**/*.{ts,js,mjs} : In Node.js scripts, use `storybook/internal/node-logger` instead of `console.*`

Applied to files:

  • code/renderers/react/src/componentManifest/generator.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to {code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs} : Do not use `console.log`, `console.warn`, or `console.error` directly unless in isolated files where importing loggers would significantly increase bundle size

Applied to files:

  • code/renderers/react/src/componentManifest/generator.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.{ts,tsx,js,jsx,mjs} : Export functions from modules when they need to be unit-tested

Applied to files:

  • code/renderers/react/src/componentManifest/reactDocgen.ts
🧬 Code graph analysis (2)
code/renderers/react/src/componentManifest/generator.ts (7)
code/core/src/types/modules/core-common.ts (2)
  • ComponentManifest (348-364)
  • PresetPropertyFn (656-661)
code/renderers/react/src/componentManifest/reactDocgen.ts (2)
  • DocObj (24-28)
  • getReactDocgen (167-211)
code/renderers/react/src/componentManifest/utils.ts (4)
  • invalidateCache (118-122)
  • cachedReadFileSync (124-124)
  • cachedFindUp (126-126)
  • invariant (24-32)
code/renderers/react/src/componentManifest/getComponentImports.ts (1)
  • getComponentImports (438-466)
code/core/src/csf-tools/enrichCsf.ts (1)
  • extractDescription (158-178)
code/renderers/react/src/componentManifest/jsdocTags.ts (1)
  • extractJSDocInfo (5-21)
code/renderers/react/src/componentManifest/generateCodeSnippet.ts (1)
  • getCodeSnippet (6-227)
code/renderers/react/src/componentManifest/reactDocgen.ts (5)
code/renderers/react/src/componentManifest/getComponentImports.ts (1)
  • ComponentRef (11-19)
code/core/src/common/utils/interpret-files.ts (1)
  • supportedExtensions (6-17)
code/renderers/react/src/componentManifest/utils.ts (3)
  • cached (45-116)
  • cachedResolveImport (128-128)
  • cachedReadFileSync (124-124)
code/core/src/common/utils/paths.ts (1)
  • getProjectRoot (11-57)
code/renderers/react/src/componentManifest/jsdocTags.ts (1)
  • extractJSDocInfo (5-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: normal
  • GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (5)
code/renderers/react/src/componentManifest/utils.ts (1)

34-116: Well-designed caching implementation.

The module-level memoization stores and generic cached() helper provide a solid foundation for performance optimization. Key strengths:

  • WeakMap-based stores allow GC when functions are dereferenced
  • Separate handling for sync/async results with resolved-value-only caching
  • Graceful fallback on serialization errors
  • Verbose logging for cache diagnostics

Note: The implementation intentionally does not de-duplicate concurrent calls (as documented in the comment on line 44), so simultaneous calls for the same uncached key will both compute the result.

code/renderers/react/src/componentManifest/reactDocgen.ts (2)

35-55: Improved component matching logic.

The refactored getMatchingDocgen now checks multiple identifier variants (importName, localImportName, componentName) against docgen metadata (exportName, displayName, actualName), providing more robust matching for different import patterns and component definitions.


71-211: Robust docgen integration with caching and error handling.

The cached helpers (getTsConfig, parseWithReactDocgen, gatherDocgensForPath, getReactDocgen) form a well-structured pipeline:

  • TypeScript path mapping support via matchPath
  • Recursive re-export resolution with depth limiting (max depth 5, filters node_modules)
  • Discriminated union return type clearly separates success/error cases
  • Detailed error messages with analyzed file context for debugging

The use of cached() wrappers eliminates the cache-population bug flagged in earlier reviews.

code/renderers/react/src/componentManifest/generator.ts (2)

25-29: Good practice: Cache invalidation and performance instrumentation.

Calling invalidateCache() at the start (line 25) ensures fresh results per build, avoiding stale cached data across runs. The performance timing logs (lines 27-29, 174) provide valuable diagnostics for optimization efforts.


42-172: Streamlined manifest generation with improved import resolution.

The refactored flow effectively integrates the new caching infrastructure:

  • Uses cachedReadFileSync to minimize I/O overhead
  • Leverages getComponentImports for comprehensive import analysis
  • Matches components by multiple identifiers (name, localImportName, importName) and title patterns
  • Enriches per-story metadata with JSDoc-derived descriptions and summaries
  • Returns discriminated union from getReactDocgen for explicit success/error handling

The fallback error messages for missing meta.component and unresolved imports provide clear guidance to users.

Comment on lines +49 to +59
const keyOf: (...args: A) => string =
opts.key ??
((...args: A) => {
try {
// Prefer a stable string key based on the full arguments list
return JSON.stringify(args) ?? String(args[0]);
} catch {
// Fallback: use the first argument if it is not serializable
return String(args[0]);
}
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove dead code in fallback logic.

The nullish coalescing operator on line 54 is unreachable. JSON.stringify(args) either returns a string or throws (caught by the catch block); it never returns null or undefined. The ?? String(args[0]) fallback is dead code.

Apply this diff to simplify:

-        return JSON.stringify(args) ?? String(args[0]);
+        return JSON.stringify(args);

The catch block already handles serialization failures by falling back to String(args[0]), making this ternary unnecessary.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const keyOf: (...args: A) => string =
opts.key ??
((...args: A) => {
try {
// Prefer a stable string key based on the full arguments list
return JSON.stringify(args) ?? String(args[0]);
} catch {
// Fallback: use the first argument if it is not serializable
return String(args[0]);
}
});
const keyOf: (...args: A) => string =
opts.key ??
((...args: A) => {
try {
// Prefer a stable string key based on the full arguments list
return JSON.stringify(args);
} catch {
// Fallback: use the first argument if it is not serializable
return String(args[0]);
}
});
🤖 Prompt for AI Agents
In code/renderers/react/src/componentManifest/utils.ts around lines 49 to 59,
the fallback operator "?? String(args[0])" after JSON.stringify(args) is dead
code because JSON.stringify either returns a string or throws; remove the
nullish coalescing and simplify the function to return JSON.stringify(args)
directly in the try block and keep the existing catch that falls back to
String(args[0]).

@kasperpeulen kasperpeulen changed the title React: Add imports automatically to manifest React: Auto calculate imports, support barrel files, auto detect. components and other small tweaks Nov 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants