Repository navigation
Open-Service: Type getService for core services per runtime - #35242
Conversation
Adds per-runtime core-service maps so getService('core/...') is typed
without an explicit generic, while keeping the generic fallback for addon
services. Splits the server extraction-service registration into per-service
registrar files and preserves the literal service id through defineService so
the maps derive their keys from each definition.
Co-authored-by: Cursor <cursoragent@cursor.com>
… into split/typed-core-getservice Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # code/core/src/shared/open-service/services/docgen/server.ts
Constrains the extraction registrar's command names to keys of the service's commands (matching queryName) and adds invariants that the query/command names exist on the definition, so a wiring typo fails at the boundary instead of silently registering nothing. Also clarifies that the core-service-types membership test guards the registrar-file convention, not the actual call site. Co-authored-by: Cursor <cursoragent@cursor.com>
Package BenchmarksCommit: The following packages have significant changes to their size or dependencies:
|
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 72 | 72 | 0 |
| Self size | 21.14 MB | 21.68 MB | 🚨 +531 KB 🚨 |
| Dependency size | 36.44 MB | 36.44 MB | 0 B |
| Bundle Size Analyzer | Link | Link |
@storybook/cli
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 204 | 204 | 0 |
| Self size | 821 KB | 821 KB | 🎉 -84 B 🎉 |
| Dependency size | 90.18 MB | 90.71 MB | 🚨 +531 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/codemod
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 197 | 197 | 0 |
| Self size | 32 KB | 32 KB | 0 B |
| Dependency size | 88.66 MB | 89.19 MB | 🚨 +531 KB 🚨 |
| Bundle Size Analyzer | Link | Link |
create-storybook
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 73 | 73 | 0 |
| Self size | 1.09 MB | 1.09 MB | 0 B |
| Dependency size | 57.58 MB | 58.11 MB | 🚨 +531 KB 🚨 |
| Bundle Size Analyzer | node | node |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds typed core-service ChangesTyped core getService and split extraction service registration
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
✨ Finishing Touches📝 Generate docstrings
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
code/core/src/shared/open-service/services/extraction-service.server.ts (1)
72-74: 💤 Low valueConsider logging refresh failures for observability.
Errors from individual component refreshes are silently swallowed. While this prevents one failure from breaking others, it may make debugging harder when extractions fail unexpectedly.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@code/core/src/shared/open-service/services/extraction-service.server.ts` around lines 72 - 74, The refreshComponent call within the idsToRefresh.map() is silently catching and ignoring errors with .catch(() => undefined), which prevents visibility into refresh failures. Modify the catch handler for refreshComponent to log the error details before returning undefined, so that individual refresh failures are recorded for debugging purposes while still allowing other refresh operations to continue without interruption.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@code/core/src/shared/open-service/services/story-docs/story-docs-source-before-each.ts`:
- Around line 23-25: The variable `service` is declared without a type
annotation, which loses the compile-time safety benefits of the typed
`getService('core/story-docs')` function. Replace the bare `let service;`
declaration with a properly typed declaration that captures the return type from
`getService('core/story-docs')`, so that subsequent operations like
`service.queries.getStoryDocs` remain statically type-checked. Use the
appropriate type or let TypeScript infer it from the initial assignment within
the try block.
---
Nitpick comments:
In `@code/core/src/shared/open-service/services/extraction-service.server.ts`:
- Around line 72-74: The refreshComponent call within the idsToRefresh.map() is
silently catching and ignoring errors with .catch(() => undefined), which
prevents visibility into refresh failures. Modify the catch handler for
refreshComponent to log the error details before returning undefined, so that
individual refresh failures are recorded for debugging purposes while still
allowing other refresh operations to continue without interruption.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e9908a5b-c7b4-461c-ac1f-c0197b037ed9
📒 Files selected for processing (24)
code/addons/docs/src/blocks/blocks/use-service-docgen.tscode/addons/docs/src/blocks/blocks/use-service-story-docs.tscode/core/src/controls/manager.tsxcode/core/src/core-server/change-detection/change-detection-service.tscode/core/src/core-server/presets/common-preset.tscode/core/src/core-server/utils/manifests/manifests.test.tscode/core/src/core-server/utils/manifests/manifests.tscode/core/src/shared/open-service/README.mdcode/core/src/shared/open-service/core-service-types.test.tscode/core/src/shared/open-service/core-service-types.tscode/core/src/shared/open-service/manager.test-d.tscode/core/src/shared/open-service/manager.tscode/core/src/shared/open-service/preview.test-d.tscode/core/src/shared/open-service/preview.tscode/core/src/shared/open-service/server.test-d.tscode/core/src/shared/open-service/server.tscode/core/src/shared/open-service/service-definition.tscode/core/src/shared/open-service/services/docgen/server.test.tscode/core/src/shared/open-service/services/docgen/server.tscode/core/src/shared/open-service/services/extraction-service.server.tscode/core/src/shared/open-service/services/story-docs/server.test.tscode/core/src/shared/open-service/services/story-docs/server.tscode/core/src/shared/open-service/services/story-docs/story-docs-source-before-each.tscode/core/src/shared/open-service/types.ts
Use an IIFE so the service handle keeps its inferred preview type instead of widening through an untyped let declaration. Co-authored-by: Cursor <cursoragent@cursor.com>
Resolve conflicts from the query rename (drop redundant `get` prefix) while keeping per-service registrars and typed getService. Update query/command wiring to docgen, storyDocs, and latestStoryChanges. Co-authored-by: Cursor <cursoragent@cursor.com>
Closes #
What I did
Makes module-level
getService('core/...')type-aware at compile time for core services, per runtime (manager, preview, server), without requiring an explicit generic. Addon services keep the existinggetService<MyService>('my-addon/service')path.core-service-types.tswith per-runtime definition lists as the single source of truth;*CoreServicestypes andTypedGetServiceoverloads derive from those lists.defineService/ServiceDefinitionwith aTIdgeneric so service ids stay as string literals (e.g.'core/docgen') for map key derivation.extraction-service.server.tsplus per-servicedocgen/server.tsandstory-docs/server.tsregistrars (one registrar file per service per runtime).keyof TCommands, and invariants assert query/command names exist on the definition before registration.open-service/README.md.Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
Caution
This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!
No additional manual QA beyond the automated checks below is required for this PR: the change is compile-time typing and internal registration wiring with no user-visible UI surface. A maintainer can still spot-check the extraction services if desired.
From the repo root, run the focused unit and type tests:
Expect all tests to pass with no type errors.
Confirm TypeScript is clean for
core:Expect
✅ No type errors.(Optional regression check) If
experimentalDocgenServeris enabled in the internal Storybook UI, open a docs story and confirm Controls / Source blocks still load docgen and story-docs data without console errors:Areas most likely to regress: server-side docgen/story-docs extraction and hot-refresh re-extraction after story file changes (touched by the extraction-service split).
Documentation
MIGRATION.MD
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.🦋 Canary release
This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the
@storybookjs/coreteam here.core team members can create a canary release here or locally with
gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER>Made with Cursor
Summary by CodeRabbit
getServicetyping across manager, preview, and server using core service id inference, with unknown ids falling back to a generic runtime type.idas a literal type.getServicetyping (including fallback/override behavior).