Repository navigation
Angular: Add an in-process docgen analyzer, replacing Compodoc under the flag - #35805
Conversation
The fixture suites prove the Angular extractor against components written to exercise it. They cannot catch what only shows up across a whole project: component name collisions, imports that resolve to the wrong file, components the tsconfig never covered. A static Storybook build under experimentalDocgenServer already writes one docgen payload per component. This reads that output, strips the parts that are machine-specific or engine-specific, and keeps the result in the repo so a provider change becomes a reviewable diff. Findings are split by severity: a regression means docgen got worse and wants a fix, a change means it moved without getting worse and is adopted by re-recording. Both fail the run. CI verifies after building any sandbox that has baselines committed, derived from what is on disk so adding a directory is all it takes to gate a template.
The recorded baselines are captured from this sandbox's static build, and that build only writes per-component docgen snapshots when both flags are on. Until now no sandbox turned server-side Angular docgen on, so nothing exercised it end to end in CI.
…lines The monorepo's shared template stories reference their component as `globalThis.__TEMPLATE_COMPONENTS__.*`, so there is no import to resolve and no scanned file to find. All 74 of them errored by construction, which says something about the template-story harness rather than about docgen, and they buried the components that carry real signal. The Angular recording goes from 111 components to 37: 30 documented, 7 Angular classes declared inline in story files.
Attaching a `message` listener to a worker re-references its port, so calling `unref()` before the listeners are on leaves the worker holding the event loop open. `build-storybook` finished its work and then hung indefinitely, which on CI showed up as a ten-minute no-output timeout rather than as a failure. Only reachable with experimentalDocgenServer enabled, which no sandbox did until now.
Turning the flags on for the existing Angular sandbox would have swapped what that sandbox guards, leaving today's browser docgen untested while the server path is still experimental. A separate template keeps both covered. Runs daily rather than on every PR: it doubles the Angular sandbox cost and the configuration it guards is not the shipping one yet. Marked in-development so CI generates it from scratch until it is published to the sandboxes repository.
The sandbox now exists on the sandboxes repository, so CI clones it like every other template instead of scaffolding it from scratch on each run.
The sandbox differs from `angular-vite/default-ts` only by two feature flags, so visual output is already covered there on every run and repeating it doubles the Angular cost for no extra signal. `test-runner` is skipped alongside it because the job list adds a test-runner job precisely when chromatic is skipped, so skipping only chromatic would have swapped one job for another rather than dropping one.
…lags There was a hardcoded default template in the recorder and a separate disk-existence check in the CI config, so three places had to agree on which sandboxes carry docgen baselines. Now the flags on the template definition are the only source: a sandbox that turns on server docgen is baselined, and one that does not is not. A flagged template with nothing recorded yet fails instead of skipping quietly, which is the case the disk check used to swallow.
The derivation is exercised by the recorder and the generated CI config, so the unit test was duplicating that. `enablesDocgenServer` goes back to module-private with it, since exporting it was only for the test. Also reframes the cadence TODO: after 11.0 the standard sandboxes ship the new docgen approach by default, so this template gets removed rather than promoted.
Package BenchmarksCommit: The following packages have significant changes to their size or dependencies:
|
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 29 | 29 | 0 |
| Self size | 23.05 MB | 23.00 MB | 🎉 -49 KB 🎉 |
| Dependency size | 12.68 MB | 12.68 MB | 0 B |
| Bundle Size Analyzer | Link | Link |
|
Quick heads-up on the red The failing step is
Same job, same step, a different spec each time. That is a flaky suite rather than a deterministic break. For what it is worth on the other side: this branch touches no file under
|
|
@coderabbitai review |
|
|
@coderabbitai full review |
|
Both the React and the Angular component-meta analyzers keep one TypeScript LanguageService per matched tsconfig, and both need the same thing from it: which files the project claims, what version each is on, when a change event invalidates a snapshot, and how to stay fresh when an edit races the debounced watcher. React had all of that inline. `ProjectFileTracker` owns it once. React loses about 150 lines of it and reads the same behaviour back; the Angular analyzer arriving next consumes it instead of writing a second copy. The tracker deliberately knows nothing about either renderer: it takes a structural `ProjectFileSystem` rather than importing `typescript`, so `typeof ts` satisfies it without core naming the package.
Angular docgen goes through Compodoc, which shells out to a separate CLI, re-parses the whole project on every run and only reports what its own JSON schema can express. That is slow, hard to keep incremental, and loses type information the compiler already has. This adds @storybook/angular-cm, an analyzer that runs inside the Storybook process on a TypeScript LanguageService. It reads decorator and signal based inputs and outputs, follows inheritance across files, renders declared types through the checker, and carries JSDoc onto the members it emits. The manager keeps one project per tsconfig and reuses the service between runs so a file change re-checks only what it touched. The extraction rules here already include the corrections found by running the analyzer against real-world Angular repositories: ES-private and non-public DI members stay out of argTypes, import() qualifiers are stripped from rendered types, function members render their signature instead of a bare "function", accessor inputs keep their JSDoc tags, and getters carrying @output() are recognized.
6ce2dbc to
b9fc3bd
Compare
Co-authored-by: Valentin Palkovic <dev@valentinpalkovic.dev>
The review suggestions were applied through the GitHub web editor, which left the closing `*/` of two shortened docblocks flush against the margin. oxfmt wants a leading space, so `format-check` failed on both files.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
code/lib/angular-cm/src/analyzer/class-members.ts (1)
21-28: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winConsider a locale-independent comparator for deterministic ordering.
localeComparewithout an explicit locale depends on the host ICU data and locale environment. The emitted order feeds the committed argTypes baselines, so two machines can produce different member order for the same source.type-index.tstoMiscellaneoususes the same pattern.If you want the order pinned across environments, pass a fixed locale or compare code units.
♻️ Proposed change
function sortMembers(members: ClassMembers): void { + const collator = new Intl.Collator('en', { sensitivity: 'variant' }); const byName = (a: MemberEntry<{ name: string }>, b: MemberEntry<{ name: string }>) => - a.value.name.localeCompare(b.value.name); + collator.compare(a.value.name, b.value.name); members.inputs.sort(byName); members.outputs.sort(byName); members.properties.sort(byName); members.methods.sort(byName); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@code/lib/angular-cm/src/analyzer/class-members.ts` around lines 21 - 28, Update the byName comparator in sortMembers to use a locale-independent, deterministic name comparison, such as an explicit fixed locale or code-unit ordering. Apply the same ordering fix to type-index.ts toMiscellaneous, preserving the existing member sorting behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@code/lib/angular-cm/src/analyzer/type-index.ts`:
- Around line 62-75: Update TypeIndex.render’s function/constructor type-node
branch to render typeNode.typeParameters and include the resulting generic
parameter list before the parameter list. Preserve the existing constructor
prefix, parameter rendering, and return-type rendering so types such as generic
function signatures retain valid metadata text.
---
Nitpick comments:
In `@code/lib/angular-cm/src/analyzer/class-members.ts`:
- Around line 21-28: Update the byName comparator in sortMembers to use a
locale-independent, deterministic name comparison, such as an explicit fixed
locale or code-unit ordering. Apply the same ordering fix to type-index.ts
toMiscellaneous, preserving the existing member sorting behavior.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 05fddd2a-e45a-42b7-8c28-e14bda94af17
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (85)
code/core/src/common/utils/resolve-meta-component.test.tscode/core/src/common/utils/resolve-meta-component.tscode/core/src/component-meta/ComponentMetaManager.tscode/core/src/component-meta/ProjectFileTracker.test.tscode/core/src/component-meta/ProjectFileTracker.tscode/core/src/component-meta/index.tscode/core/src/component-meta/types.tscode/core/src/shared/open-service/services/docgen/worker/docgen-worker-client.test.tscode/core/src/shared/open-service/services/docgen/worker/docgen-worker-client.tscode/frameworks/angular-vite/package.jsoncode/frameworks/angular-vite/src/compodoc-config.tscode/frameworks/angular-vite/src/compodoc/ensure-documentation.tscode/frameworks/angular-vite/src/docgen/build-docgen.integration.test.tscode/frameworks/angular-vite/src/docgen/build-docgen.test.tscode/frameworks/angular-vite/src/docgen/build-docgen.tscode/frameworks/angular-vite/src/docgen/docgen-worker.test.tscode/frameworks/angular-vite/src/docgen/docgen-worker.tscode/frameworks/angular-vite/src/docgen/preset.test.tscode/frameworks/angular-vite/src/docgen/preset.tscode/frameworks/angular-vite/src/docgen/resolve-component.test.tscode/frameworks/angular-vite/src/preset.tscode/lib/angular-cm/README.mdcode/lib/angular-cm/package.jsoncode/lib/angular-cm/src/analyzer/__testutils__/inline-source.tscode/lib/angular-cm/src/analyzer/analyze-file.test.tscode/lib/angular-cm/src/analyzer/analyze-file.tscode/lib/angular-cm/src/analyzer/class-members.tscode/lib/angular-cm/src/analyzer/context.tscode/lib/angular-cm/src/analyzer/decorators.tscode/lib/angular-cm/src/analyzer/inheritance.tscode/lib/angular-cm/src/analyzer/jsdoc.tscode/lib/angular-cm/src/analyzer/members.test.tscode/lib/angular-cm/src/analyzer/members.tscode/lib/angular-cm/src/analyzer/node-text.tscode/lib/angular-cm/src/analyzer/signals.tscode/lib/angular-cm/src/analyzer/type-index.tscode/lib/angular-cm/src/extract-arg-types.tscode/lib/angular-cm/src/index.tscode/lib/angular-cm/src/manager.test.tscode/lib/angular-cm/src/manager.tscode/lib/angular-cm/src/project.tscode/lib/angular-cm/src/types.tscode/lib/angular-compodoc/README.mdcode/lib/angular-compodoc/package.jsoncode/lib/angular-compodoc/src/compodoc-types.tscode/lib/angular-compodoc/src/extract-arg-types.test.tscode/lib/angular-compodoc/src/extract-arg-types.tscode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/example-button.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/example-header.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/example-page.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-argtypes-doc-button.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-argtypes-doc-directive.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-argtypes-doc-injectable.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-argtypes-doc-pipe.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-angular-forms-customcontrolvalueaccessor-custom-cva-component.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-complex-selectors-attribute-selectors-component.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-complex-selectors-class-selector-component.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-complex-selectors-multiple-class-selector-component.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-complex-selectors-multiple-selector-component.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-enums-enums-component.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-inheritance-base-button.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-inheritance-icon-button.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-ng-content-ng-content-about-parent.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-ng-on-destroy-component-with-on-destroy.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-on-push-on-push.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-pipe-custom-pipes.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-provider-di-component.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-template-template.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-without-selector-without-selector-ng-component-outlet.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-without-selector-without-selector.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-ng-module-import-module-chip.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-ng-module-import-module-for-root.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-ng-module-import-module.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-core-decorators-componentwrapperdecorator-decorators.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-core-decorators-theme-decorator-decorators.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-core-modulemetadata-in-export-default.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-core-modulemetadata-in-stories.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-core-modulemetadata-merge-default-and-story.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-core-styles-story-styles.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-others-app-initializer-use-factory.jsoncode/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-others-issues-12009-unknown-component.jsoncode/lib/docgen-harness/src/sandbox-baselines/read-static-docgen.tscode/playwright.config.tsscripts/ci/sandboxes.tsscripts/ci/utils/helpers.ts
💤 Files with no reviewable changes (15)
- code/lib/docgen-harness/src/sandbox-baselines/baselines/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-ng-content-ng-content-about-parent.json
- code/lib/docgen-harness/src/sandbox-baselines/baselines/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-others-app-initializer-use-factory.json
- code/lib/docgen-harness/src/sandbox-baselines/baselines/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-pipe-custom-pipes.json
- code/lib/docgen-harness/src/sandbox-baselines/baselines/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-without-selector-without-selector-ng-component-outlet.json
- code/lib/docgen-harness/src/sandbox-baselines/baselines/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-template-template.json
- code/lib/docgen-harness/src/sandbox-baselines/baselines/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-ng-on-destroy-component-with-on-destroy.json
- code/lib/docgen-harness/src/sandbox-baselines/baselines/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-complex-selectors-class-selector-component.json
- code/lib/docgen-harness/src/sandbox-baselines/baselines/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-others-issues-12009-unknown-component.json
- code/lib/docgen-harness/src/sandbox-baselines/baselines/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-complex-selectors-multiple-selector-component.json
- code/lib/docgen-harness/src/sandbox-baselines/baselines/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-complex-selectors-attribute-selectors-component.json
- code/lib/docgen-harness/src/sandbox-baselines/baselines/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-core-decorators-componentwrapperdecorator-decorators.json
- code/lib/docgen-harness/src/sandbox-baselines/baselines/angular-vite-docgen-server-ts/example-page.json
- code/lib/docgen-harness/src/sandbox-baselines/baselines/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-without-selector-without-selector.json
- code/lib/docgen-harness/src/sandbox-baselines/baselines/angular-vite-docgen-server-ts/example-header.json
- code/lib/docgen-harness/src/sandbox-baselines/baselines/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-complex-selectors-multiple-class-selector-component.json
🚧 Files skipped from review as they are similar to previous changes (21)
- code/frameworks/angular-vite/package.json
- code/frameworks/angular-vite/src/preset.ts
- code/frameworks/angular-vite/src/compodoc/ensure-documentation.ts
- code/frameworks/angular-vite/src/docgen/build-docgen.integration.test.ts
- code/lib/angular-cm/src/manager.test.ts
- code/frameworks/angular-vite/src/compodoc-config.ts
- code/lib/angular-compodoc/package.json
- code/lib/angular-compodoc/README.md
- code/lib/angular-cm/src/manager.ts
- code/lib/angular-cm/src/analyzer/analyze-file.ts
- code/lib/angular-compodoc/src/extract-arg-types.test.ts
- code/lib/angular-cm/src/analyzer/jsdoc.ts
- code/core/src/common/utils/resolve-meta-component.ts
- code/frameworks/angular-vite/src/docgen/resolve-component.test.ts
- code/lib/angular-compodoc/src/compodoc-types.ts
- code/lib/angular-compodoc/src/extract-arg-types.ts
- code/core/src/shared/open-service/services/docgen/worker/docgen-worker-client.ts
- code/lib/angular-cm/src/analyzer/members.test.ts
- code/frameworks/angular-vite/src/docgen/build-docgen.ts
- code/core/src/shared/open-service/services/docgen/worker/docgen-worker-client.test.ts
- code/frameworks/angular-vite/src/docgen/build-docgen.test.ts
The review suggestion shortened this docblock through the GitHub web editor and
dropped its closing `*/`, so the declaration below it became comment text:
/**
* Token standing in for the sandbox directory inside recorded strings.
export const SANDBOX_TOKEN = '<sandbox>';
Still valid syntax, so lint and oxfmt passed and only `check` caught it:
read-static-docgen.test.ts(6,10): error TS2305: Module has no exported
member 'SANDBOX_TOKEN'.
read-static-docgen.ts(43,29): error TS2304: Cannot find name 'SANDBOX_TOKEN'.
huang-julien
left a comment
There was a problem hiding this comment.
Tests and case coverage looks good to me :)
TypeIndex.render dropped typeNode.typeParameters, so <T>(value: T) => T rendered as (value: T) => T, an invalid type text in generated metadata.
…project' into HEAD # Conflicts: # code/core/src/component-meta/ProjectFileTracker.test.ts # code/core/src/component-meta/ProjectFileTracker.ts # code/core/src/component-meta/index.ts # code/core/src/shared/open-service/services/docgen/worker/docgen-worker-client.test.ts # code/core/src/shared/open-service/services/docgen/worker/docgen-worker-client.ts # code/lib/cli-storybook/src/sandbox-templates.ts # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/example-button.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/example-header.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/example-page.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-argtypes-doc-button.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-argtypes-doc-directive.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-argtypes-doc-injectable.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-argtypes-doc-pipe.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-angular-forms-customcontrolvalueaccessor-custom-cva-component.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-complex-selectors-attribute-selectors-component.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-complex-selectors-class-selector-component.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-complex-selectors-multiple-class-selector-component.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-complex-selectors-multiple-selector-component.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-enums-enums-component.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-inheritance-base-button.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-inheritance-icon-button.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-ng-content-ng-content-about-parent.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-ng-on-destroy-component-with-on-destroy.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-on-push-on-push.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-pipe-custom-pipes.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-provider-di-component.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-with-template-template.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-without-selector-without-selector-ng-component-outlet.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-component-without-selector-without-selector.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-ng-module-import-module-chip.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-ng-module-import-module-for-root.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-basics-ng-module-import-module.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-core-decorators-componentwrapperdecorator-decorators.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-core-decorators-theme-decorator-decorators.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-core-modulemetadata-in-export-default.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-core-modulemetadata-in-stories.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-core-modulemetadata-merge-default-and-story.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-core-styles-story-styles.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-others-app-initializer-use-factory.json # code/lib/docgen-harness/src/sandbox-baselines/__baselines__/angular-vite-docgen-server-ts/stories-frameworks-angular-vite-others-issues-12009-unknown-component.json # code/lib/docgen-harness/src/sandbox-baselines/read-static-docgen.ts # code/lib/docgen-harness/src/sandbox-baselines/run.ts # scripts/ci/utils/helpers.ts
…project' into HEAD
Matches React's ComponentMetaProject now that the base carries a Source type parameter.
Resolve the component-meta path-helper conflict: next moved normalizePath and isInNodeModules out of ProjectFileTracker into shared/utils/paths.ts (as slash and isInNodeModules). angular-cm now imports both from storybook/internal/common, which already re-exports that module.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
scripts/ci/utils/helpers.ts (1)
249-255: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winDisable the orb cache.
cache-version: 'v4'only changes the cache key. Becausewith-cachedefaults totrue, the orb still restores and saves itsnode-deps-*cache alongsideNODE_MODULES_CACHE_KEY. Set'with-cache': false.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/ci/utils/helpers.ts` around lines 249 - 255, Disable the orb-managed cache by setting its with-cache option to false in the relevant helper configuration, while preserving the existing NODE_MODULES_CACHE_KEY handling and yarn install behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@scripts/ci/utils/helpers.ts`:
- Around line 249-255: Disable the orb-managed cache by setting its with-cache
option to false in the relevant helper configuration, while preserving the
existing NODE_MODULES_CACHE_KEY handling and yarn install behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 691ebd37-8451-413a-92eb-1dcd561d2557
📒 Files selected for processing (6)
code/core/src/component-meta/ComponentMetaManager.tscode/core/src/shared/open-service/services/docgen/worker/docgen-worker-client.test.tscode/lib/angular-cm/src/analyzer/type-index.tscode/lib/angular-cm/src/project.tscode/lib/docgen-harness/src/sandbox-baselines/read-static-docgen.tsscripts/ci/utils/helpers.ts
🚧 Files skipped from review as they are similar to previous changes (5)
- code/lib/docgen-harness/src/sandbox-baselines/read-static-docgen.ts
- code/core/src/component-meta/ComponentMetaManager.ts
- code/core/src/shared/open-service/services/docgen/worker/docgen-worker-client.test.ts
- code/lib/angular-cm/src/project.ts
- code/lib/angular-cm/src/analyzer/type-index.ts
## Dependency Updates | Package | From | To | Type | | --- | --- | --- | --- | | `storybook` | 10.5.10 | 10.6.0 | minor | ## Release Notes <details> <summary><b>storybook</b> (10.5.10 → 10.6.0)</summary> ## 10.6.0 > New skills architecture for agentic workflows Storybook 10.6 contains hundreds of fixes and improvements: - 💻 CLI bindings for agent tools/skills -🅰️ Angular-Vite MCP/skills support and improved docgen/snippets (experimental) - 🟢 Vue MCP/skills support and improved docgen/snippets (experimental) - 🧩 Tanstack / NextJS-Vite framework bugfixes - ⚡ Improved performance and reduced bundle size <details> <summary>List of all updates</summary> - Addon MCP: Stop silently dropping composed refs from MCP composition - [#36077](storybookjs/storybook#36077), thanks @<!---->kasperpeulen! - Addon Vitest: Pin storybook/test in optimizeDeps so its CJS-only deps are prebundled - [#35572](storybookjs/storybook#35572), thanks @<!---->Nic-Polumeyv! - Addon Vitest: Report test runs with failures as failed tool outcomes - [#36080](storybookjs/storybook#36080), thanks @<!---->kasperpeulen! - Addon Vitest: Resolve story test globs against the project root - [#36103](storybookjs/storybook#36103), thanks @<!---->kasperpeulen! - Addon-vitest: Filter Storybook instrumentation from reported stack traces - [#36120](storybookjs/storybook#36120), thanks @<!---->ghengeveld! - Angular Vite: Resolve tsConfig against the workspace root - [#36026](storybookjs/storybook#36026), thanks @<!---->ndelangen! - Angular-Vite: Run Compodoc on demand - [#35776](storybookjs/storybook#35776), thanks @<!---->valentinpalkovic! - Angular: Add an in-process docgen analyzer, replacing Compodoc under the flag - [#35805](storybookjs/storybook#35805), thanks @<!---->valentinpalkovic! - Angular: Bind only what the component accepts in story snippets, and report the rest - [#35943](storybookjs/storybook#35943), thanks @<!---->valentinpalkovic! - Angular: Decide the migration\'s zone.js import from the dependency tree - [#36008](https://github.com/story …[full notes](https://github.com/storybookjs/storybook/releases/tag/v10.6.0) </details> --- *This PR was auto-generated by [catalog-update-action](https://github.com/brandhaug/catalog-update-action).* Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
## Dependency Updates | Package | From | To | Type | | --- | --- | --- | --- | | `@storybook/react-vite` | 10.5.10 | 10.6.0 | minor | ## Release Notes <details> <summary><b>@<!---->storybook/react-vite</b> (10.5.10 → 10.6.0)</summary> ## 10.6.0 > New skills architecture for agentic workflows Storybook 10.6 contains hundreds of fixes and improvements: - 💻 CLI bindings for agent tools/skills -🅰️ Angular-Vite MCP/skills support and improved docgen/snippets (experimental) - 🟢 Vue MCP/skills support and improved docgen/snippets (experimental) - 🧩 Tanstack / NextJS-Vite framework bugfixes - ⚡ Improved performance and reduced bundle size <details> <summary>List of all updates</summary> - Addon MCP: Stop silently dropping composed refs from MCP composition - [#36077](storybookjs/storybook#36077), thanks @<!---->kasperpeulen! - Addon Vitest: Pin storybook/test in optimizeDeps so its CJS-only deps are prebundled - [#35572](storybookjs/storybook#35572), thanks @<!---->Nic-Polumeyv! - Addon Vitest: Report test runs with failures as failed tool outcomes - [#36080](storybookjs/storybook#36080), thanks @<!---->kasperpeulen! - Addon Vitest: Resolve story test globs against the project root - [#36103](storybookjs/storybook#36103), thanks @<!---->kasperpeulen! - Addon-vitest: Filter Storybook instrumentation from reported stack traces - [#36120](storybookjs/storybook#36120), thanks @<!---->ghengeveld! - Angular Vite: Resolve tsConfig against the workspace root - [#36026](storybookjs/storybook#36026), thanks @<!---->ndelangen! - Angular-Vite: Run Compodoc on demand - [#35776](storybookjs/storybook#35776), thanks @<!---->valentinpalkovic! - Angular: Add an in-process docgen analyzer, replacing Compodoc under the flag - [#35805](storybookjs/storybook#35805), thanks @<!---->valentinpalkovic! - Angular: Bind only what the component accepts in story snippets, and report the rest - [#35943](storybookjs/storybook#35943), thanks @<!---->valentinpalkovic! - Angular: Decide the migration\'s zone.js import from the dependency tree - [#36008](https://github.com/story …[full notes](https://github.com/storybookjs/storybook/releases/tag/v10.6.0) </details> --- *This PR was auto-generated by [catalog-update-action](https://github.com/brandhaug/catalog-update-action).* Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
What I did
Angular is the only framework whose docgen needs a second tool. Under
experimentalDocgenServer, Storybook shells out to Compodoc, which re-parses the whole project and writes adocumentation.json. That is where the Angular server-docgen path spends its time, and it is why a one-line edit costs about as much as a cold start.This adds
AngularComponentMetaManager, an in-process analyzer that reads component metadata straight from TypeScript sources through a warmLanguageService, one per matched tsconfig. Under the flag it powers docgen end to end and Compodoc is not on that pipeline at all. With the flag off nothing changes: Compodoc still writesdocumentation.jsonand still powers the controls in the preview.The analyzer emits the same Compodoc-JSON subset the existing conversion already consumes, so there is still one conversion with two producers. That was the design constraint: no second argTypes implementation to keep in sync.
What it produces
Given this component:
the analyzer emits the Compodoc-JSON subset (trimmed to the two members):
{ "name": "BadgeComponent", "type": "component", "selector": "sb-badge", "inputsClass": [ { "name": "size", "type": "BadgeSize", "optional": false, "defaultValue": "'medium'", "description": "Controls the badge footprint." } ], "outputsClass": [ { "name": "dismissed", "type": "EventEmitter", "defaultValue": "new EventEmitter<string>()", "description": "Emitted when the badge is dismissed." } ] }and the shared conversion turns that into argTypes.
sizeresolves through the alias to its literals, which is what makes it a radio group rather than a text field:{ "size": { "name": "size", "description": "Controls the badge footprint.", "type": { "name": "enum", "value": ["small", "medium", "large"] }, "table": { "category": "inputs", "type": { "summary": "BadgeSize", "required": true }, "defaultValue": { "summary": "medium" } } }, "dismissed": { "name": "dismissed", "type": { "name": "other", "value": "void" }, "action": "dismissed", "table": { "category": "outputs", "type": { "summary": "EventEmitter", "required": true } } } }Performance
Full profile, 6 repetitions, generated Angular project, same machine:
The cold number is like-for-like: 1300 documented members on both sides. The warm number is not a fair ratio and the harness says so in its own output - Compodoc re-documents all 1301 members on every save, the analyzer re-documents the 14 that changed. That difference is the point of the change, but it is not a 160x speedup of the same work.
Extraction freshness is scoped to the component's transitive import closure rather than to every file the project has ever cached. On a synthetic 2002-file project with 300 components that is the difference between 598,897 and 1,495
getModifiedTimecalls, and it was about 97% of the extraction loop's wall time.Reproduce with
yarn workspace @storybook/docgen-harness bench:docgen-perffrom the repo root. The methodology is incode/lib/docgen-harness/src/perf/PERF-METHODOLOGY.md.Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
yarn task sandbox --template angular-vite/docgen-server-ts --start-from autocd ../storybook-sandboxes/angular-vite-docgen-server-ts && yarn storybookPROPERTIES,INPUTSandOUTPUTS, with descriptions and defaults filled in:labelis astringwith defaultButtonprimaryis abooleanwith defaultfalsesizerenders as a radio group ofsmall/medium/large, not a text field - that is the literal-union-to-enum rule shown aboveonClicksits underOUTPUTSwith summaryEventEmittersrc/stories/button.component.tsand save:proberow with that description and ana/bradio control, without a restart. That is the incremental watch; Compodoc would have re-parsed the project to answer the same question.features.experimentalDocgenServertofalsein.storybook/main.ts, restart, and confirm the Docs page is exactly what it is onnext. Compodoc runs, the analyzer does not.Note
Step 1 currently needs
typescript@^6in the sandbox: Compodoc 2 crashes on TypeScript 7, and a freshly generated Angular sandbox resolves TypeScript 7. The template pins it. This affects the flag-off path only, since the analyzer does not run Compodoc.Documentation
MIGRATION.MD
The analyzer's limitations are documented next to the analyzer. Nothing here is user-facing yet: the flag is experimental.
Checklist for Maintainers
When this PR is ready for testing, make sure to add
ci:normal,ci:mergedorci:dailyGH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found incode/lib/cli-storybook/src/sandbox-templates.tsDeclare whether manual QA will be needed for this PR during the next release, through
qa:neededorqa:skipMake 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.