Design: antd doctor — Ecosystem peerDeps Compatibility Check#
Date: 2026-03-24
Status: Approved
Summary#
Extend antd doctor to dynamically scan all installed @ant-design/* packages and verify that each package's peerDependencies are satisfied by the currently installed environment. This covers both:
- Ecosystem → antd: does the installed antd version satisfy what pro-components / charts / etc. require?
- Ecosystem → other deps: does the installed react / cssinjs / icons version satisfy each ecosystem package's requirements?
Background#
The current doctor command already checks:
cssinjs-compat: from antd's peerDeps perspective — does installed cssinjs satisfy antd's requirement?icons-compat: same for icons
These are kept as-is. The new check is complementary: it goes in the other direction, asking "does the installed environment satisfy what each ecosystem package needs?"
Design#
Data Collection (DoctorContext)#
Add to buildContext():
- Scan
node_modules/@ant-design/(i.e.readdirSync(join(cwd, 'node_modules', '@ant-design'))) to discover all installed scoped packages. Note:antditself lives atnode_modules/antd/, NOT under@ant-design/, so it will never appear in this scan. - For each entry, read
node_modules/@ant-design/<entry>/package.jsonto extract:version,peerDependencies,peerDependenciesMeta - Add
ecosystemPackages: EcosystemPackage[]field toDoctorContext - Add
getInstalledVersion(cwd, pkgName): string | nullhelper function that readsnode_modules/<pkgName>/package.json. This is a standalone helper and is self-contained within the new check; it does not replace existingctx.cssinjsPkg/ctx.iconsPkgfields used by existing checks.
interface EcosystemPackage {
name: string; // e.g. "@ant-design/pro-components"
shortName: string; // e.g. "pro-components"
version: string;
peerDependencies: Record<string, string>;
peerDependenciesMeta: Record<string, { optional?: boolean }>;
}
New Check Function#
checkEcosystemPeerDeps(ctx: DoctorContext): CheckResult[]
Algorithm per installed ecosystem package:
- Skip packages with no
peerDependenciesfield (no check emitted) - For each entry in
peerDependencies:- Look up installed version of that dep via
getInstalledVersion() - If not installed:
warn(regardless of optional/required — follows the same pattern ascheckCssinjsCompat) - If installed but version doesn't satisfy range (via
satisfies()):failwith severity=error - Range format limitation:
satisfies()does not support compound ranges like">=5.0.0 <6.0.0"or">=4 || >=5". For any range thatsatisfies()cannot parse, it fails-open (returnstrue, i.e. treated as compatible). This is intentional v1 scope: false negatives are preferred over false positives for unknown range formats.
- Look up installed version of that dep via
- Aggregate violations for the package into one
CheckResult:- Any version-incompatible dep →
status: 'fail',severity: 'error' - Only missing deps (not installed) →
status: 'warn',severity: 'warning' - No issues →
status: 'pass'
- Any version-incompatible dep →
nameformat:ecosystem-compat:<shortName>(e.g.ecosystem-compat:pro-components)
message/suggestion split#
For a failing check:
message:"@ant-design/pro-components 2.7.0 peerDep issues: antd requires >=5.16.0 (installed: 5.10.0)"— summarizes the violation(s) in the messagesuggestion:"Run \npm install antd@latest`"` — the actionable fix
For multiple violations, the message concatenates them with ; .
Integration#
In registerDoctorCommand action:
const checks: CheckResult[] = [
// existing checks...
...checkEcosystemPeerDeps(ctx),
];
The function returns CheckResult[] (empty if no ecosystem packages are found).
Skip Logic#
Packages to skip during ecosystem scan:
antditself- Packages with no
peerDependenciesfield (e.g. icon SVG assets, color utilities)
Output (text format)#
antd Doctor
✓ [antd-installed] antd 5.10.0 is installed
✓ [react-compat] React 18.2.0 is compatible with antd 5.10.0
...
✗ [ecosystem-compat:pro-components] @ant-design/pro-components 2.7.0 peerDep issues:
→ antd requires >=5.16.0 (installed: 5.10.0) — run `npm install antd@latest`
✓ [ecosystem-compat:icons] @ant-design/icons 5.3.0 satisfies all peerDependencies
✓ [ecosystem-compat:cssinjs] @ant-design/cssinjs 1.11.0 satisfies all peerDependencies
Summary: 5 passed, 0 warnings, 1 failed
Output (JSON format, appended to existing checks array)#
{
"name": "ecosystem-compat:pro-components",
"status": "fail",
"severity": "error",
"message": "@ant-design/pro-components 2.7.0 peerDep issues: antd requires >=5.16.0 (installed: 5.10.0)",
"suggestion": "Run `npm install antd@latest` to satisfy @ant-design/pro-components peerDependencies"
}
Files Changed#
src/commands/doctor.ts— main changesspec.md— update doctor checks listsrc/__tests__/cli.test.ts— add ecosystem peerDep test cases
Testing#
- Mock
node_modules/@ant-design/pro-components/package.jsonwith peerDeps - Test: incompatible antd version →
status: 'fail',severity: 'error' - Test: missing optional peerDep (via
peerDependenciesMeta) →status: 'warn' - Test: missing required (non-optional) peerDep →
status: 'warn'(followscheckCssinjsCompatprecedent: "not installed" = warn, not fail) - Test: all satisfied →
status: 'pass' - Test: no ecosystem packages installed → no new checks added
- Test: package with no peerDependencies → skipped (no check emitted)
- Test: compound range (
>=5.0.0 <6.0.0) thatsatisfies()cannot parse → treated as compatible (fail-open)
Non-Goals#
- Network requests to npm registry (all checks are local file reads only)
- Checking non-
@ant-design/*packages (e.g.,antd-mobile) - Modifying existing
cssinjs-compat/icons-compatchecks (kept as-is)