Docgen: Wire up react-component-meta with DocgenService#34963
Draft
JReinhold wants to merge 10 commits into
Draft
Docgen: Wire up react-component-meta with DocgenService#34963JReinhold wants to merge 10 commits into
JReinhold wants to merge 10 commits into
Conversation
Adds ComponentMetaManager.extractDocForComponent(storyRefs) — a thin wrapper around batchExtract that returns the first resolved ComponentDoc. The docgen open service will call this once per componentId in phase 3; keeping the helper on ComponentMetaManager means successive calls share the file-snapshot cache, TS program, and watcher already maintained there. Three new tests cover the surface that matters for the docgen use case: returning a doc for a single-component subset, sharing fsFileSnapshots across separate per-component calls, and producing fresh docs after an onFilesChanged-driven invalidation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-2-rcm-per-component
Replaces the mock React provider with a real RCM-backed implementation. The provider receives an IndexEntry[] for one componentId, picks the authoritative entry (story over docs), parses the CSF file, resolves the component reference plus any declared subcomponents via the existing getComponents flow, batch-extracts ComponentDoc data through the process-wide ComponentMetaManager singleton, and maps the result into a DocgenPayload — including props, JSDoc tags, subcomponent docs, and per-story snippets with errors surfaced inline. Schemas tighten alongside: DocgenPayload now expresses real props, subcomponents, stories[], jsDocTags, and an optional error field. The new types are re-exported through storybook/internal/types so renderers and addon authors can build conforming providers. The addon-docs provider follows the new shape — it still appends a '(docs enabled)' marker to description but now forwards subcomponents, stories, and jsDocTags from downstream unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
|
…-3-rcm-provider # Conflicts: # code/addons/docs/src/docgen.ts # code/core/src/shared/open-service/services/docgen/definition.ts # code/core/src/shared/open-service/services/docgen/server.test.ts # code/renderers/react/src/docgen/preset.ts
8 tasks
…-3-rcm-provider # Conflicts: # code/addons/docs/src/docgen.ts # code/renderers/react/src/docgen/preset.ts
…-3-rcm-provider # Conflicts: # code/core/src/types/modules/core-common.ts # code/renderers/react/src/docgen/preset.ts
8 tasks
Two phase-2/3 follow-ups from review:
1. Pre-boot the TypeScript ComponentMetaManager. The first docgen request
was paying 4-5s to `import('typescript')` (a multi-MB module) on the
critical path. The React provider now kicks getManager() off
fire-and-forget at chain-build time, so the import warms up in parallel
with the rest of server startup and `await getManager()` in the request
path usually resolves instantly.
2. Loosen the docgen payload schema. The previous `DocgenProp` shape was a
verbatim copy of react-docgen-typescript's PropItem, baking one engine's
structure into the core service contract — but the docgen service is
meant to interface with other integrations (vue-docgen, future
extractors) whose props look nothing like RCM's. Following the pattern
in Storybook MCP's manifest types (which keep `reactComponentMeta` etc.
as `any`), `props` is now `unknown[]` in both the payload and
subcomponents, and the `DocgenProp` type is removed from the core
contract. The React renderer keeps a local `ReactDocgenProp` type for
its own emitted shape; consumers branch on the producing integration
when they need concrete prop types. Identity and human-readable fields
(componentId, name, description, summary, jsDocTags, stories) stay
strictly typed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
extractDocForComponent was added in phase 2 as a speculative per-component entry point, but the actual consumer (buildDocgenPayload) never used it. buildDocgen needs the ComponentDoc for the primary component AND each subcomponent — it calls batchExtract (which mutates every StoryRef in place) and reads .reactComponentMeta off each ref. extractDocForComponent returns only the first doc, so it never fit that need. batchExtract (which predates phase 2) is the real API. Its cache-sharing and invalidation behavior is already covered by the existing project-level ComponentMetaManager tests and end-to-end by buildDocgen.test.ts, so the three extractDocForComponent tests are removed alongside the method. The now-orphaned ComponentDoc import is dropped too. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The manifest generator and the docgen provider both ran the same pipeline to turn one CSF story file into resolved components (read CSF → getComponents → match primary + subcomponents) and to extract per-story snippets. The docgen provider was a parallel re-implementation that even reached into generator.ts for findMatchingComponent. Extract that shared work into componentManifest/resolveComponents.ts: - resolveStoryFileComponents(): one CSF file → ResolvedStoryFile (the unit the manifest maps over per component, and the docgen provider runs once). - findMatchingComponent(): moved here from generator.ts. - extractStorySnippets(): unifies the near-identical extractStories / buildStories; an optional filter set models the manifest's tag filtering. Both callers now resolve via the shared module and keep only their output-specific shaping. batchExtract intentionally stays with each caller: the manifest batches across all files in one call (its main perf win) while the docgen provider batches its single file — folding extraction into the shared function would have regressed the manifest's program-build batching. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What I did
Combined phases 2 and 3 of the docgen-service rollout. Phase 2 was small enough on its own (one method + three tests) that splitting it from phase 3 didn't add value. Telescopes on top of #34954; merge after that lands. Phase-2's standalone PR (#34956) was closed in favor of this one.
Phase 2 — per-component RCM extraction API
Adds
ComponentMetaManager.extractDocForComponent(storyRefs)— a thin wrapper around the existingbatchExtractthat returns the first resolvedComponentDoc. Keeping the per-component path on the manager means successive calls share the file-snapshot cache, TS program, and watcher.Three tests prove the docgen-service-facing surface: single-component subset extraction,
fsFileSnapshotsreuse across separate per-component calls, and fresh docs after anonFilesChanged-driven invalidation between calls.Phase 3 — real RCM-backed React provider + tightened schema
Replaces the phase-1 mock React provider with a real RCM-backed implementation. The provider:
DocgenProviderPresettype (nextDocgennon-nullable, no?.noise){ importPath }from the docgen servicenextDocgenfor non-CSF paths (.mdxattached-docs) and when TypeScript isn't availablegetComponents, batch-extractsComponentDocs through a module-scopedComponentMetaManagersingleton so the file-snapshot cache stays hot across callsDocgenPayloadwith name, description, props, jsDocTags, subcomponents, and per-story snippets{ ...downstream, ...ours }spread idiom so any unknown future fields downstream sets survive intactnextDocgen(rather than returning empty data) when extraction failsSchemas tighten alongside.
DocgenPayloadnow expresses:DocgenProp(mirrors RCM'sPropItem—name,required,type,defaultValue,description, optionaljsDocTags)subcomponents: Record<string, DocgenSubcomponent>walked from CSFmeta.subcomponentsstories: DocgenStory[]with per-story snippets and inlineerrorfieldsjsDocTags,summary, and optionalerrorNew types (
DocgenProp,DocgenStory,DocgenSubcomponent,DocgenError,DocgenJsDocTags) are re-exported throughstorybook/internal/typesfor downstream provider authors.addon-docs provider is updated to the tightened schema: the synthetic
{ source, kind }marker-prop from phase 1 is dropped (doesn't match the realDocgenPropshape), so it's now a pure description enricher that spreads downstream and appends(docs enabled).Telescoping plan
experimental_docgenProviderpreset +experimentalDocgenServerfeature flag + mock React providerChecklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Three new integration-style tests in
code/renderers/react/src/docgen/buildDocgen.test.tsdrive real story files throughbuildDocgenPayload: component-level extraction (name/description/props/snippet),undefinedreturn when the file is missing, and subcomponent extraction.Three new tests in
ComponentMetaManager.test.tscover the per-component extraction API: single-subset extraction, cache reuse across calls, and source-edit invalidation.Manual testing
experimentalDocgenServer: truealready enabled incode/.storybook/main.ts(from Docgen: Add mock open service #34954), runcd code && yarn storybook:ui:buildcode/storybook-static/services/core/docgen/<componentId>.jsonfiles contain realname,description,propsarray, andstoriesarray with snippets — not the mock placeholder strings from phase 1(docs enabled)(proving the addon-docs enricher ran on top of the React provider)Documentation
Checklist for Maintainers
🦋 Canary release
This PR does not have a canary release associated.
🤖 Generated with Claude Code