@@ -700,6 +700,7 @@ export function rewriteStandaloneProject(
700700 rewritePnpmWorkspaceYaml ( projectPath ) ;
701701 }
702702 let extractedStagedConfig : Record < string , string | string [ ] > | null = null ;
703+ let remainingPnpmOverrides : Record < string , string > | undefined ;
703704 editJsonFile < {
704705 overrides ?: Record < string , string > ;
705706 resolutions ?: Record < string , string > ;
@@ -739,22 +740,40 @@ export function rewriteStandaloneProject(
739740 } ,
740741 } ;
741742 } else {
742- // pnpm uses overrides/peerDependencyRules from pnpm-workspace.yaml
743- // clean up any existing entries from package.json
743+ // Remove Vite-managed keys from pnpm.overrides
744744 for ( const key of [ ...overrideKeys , ...REMOVE_PACKAGES ] ) {
745745 if ( pkg . pnpm ?. overrides ?. [ key ] ) {
746746 delete pkg . pnpm . overrides [ key ] ;
747747 }
748748 }
749- delete pkg . pnpm ?. peerDependencyRules ;
750- if ( pkg . pnpm ?. overrides && Object . keys ( pkg . pnpm . overrides ) . length === 0 ) {
751- delete pkg . pnpm . overrides ;
749+ // Remove dependency selectors targeting vite
750+ for ( const key in pkg . pnpm ?. overrides ) {
751+ if ( key . includes ( '>' ) ) {
752+ const splits = key . split ( '>' ) ;
753+ if ( splits [ splits . length - 1 ] . trim ( ) === 'vite' ) {
754+ delete pkg . pnpm . overrides [ key ] ;
755+ }
756+ }
757+ }
758+ // Move any remaining overrides to pnpm-workspace.yaml then delete all
759+ // (pnpm ignores workspace-level overrides when pnpm.overrides exists in package.json)
760+ if ( pkg . pnpm ?. overrides && Object . keys ( pkg . pnpm . overrides ) . length > 0 ) {
761+ remainingPnpmOverrides = { ...pkg . pnpm . overrides } ;
762+ }
763+ delete pkg . pnpm ?. overrides ;
764+ // Only remove Vite-managed peerDependencyRules entries, preserve custom ones
765+ cleanupPeerDependencyRules ( pkg . pnpm ?. peerDependencyRules , overrideKeys ) ;
766+ if (
767+ pkg . pnpm ?. peerDependencyRules &&
768+ Object . keys ( pkg . pnpm . peerDependencyRules ) . length === 0
769+ ) {
770+ delete pkg . pnpm . peerDependencyRules ;
752771 }
753772 if ( pkg . pnpm && Object . keys ( pkg . pnpm ) . length === 0 ) {
754773 delete pkg . pnpm ;
755774 }
756775 }
757- // remove dependency selector from vite, e.g. "vite-plugin-svgr>vite"
776+ // remove dependency selector from vite in force-override mode
758777 for ( const key in pkg . pnpm ?. overrides ) {
759778 if ( key . includes ( '>' ) ) {
760779 const splits = key . split ( '>' ) ;
@@ -784,6 +803,11 @@ export function rewriteStandaloneProject(
784803 return pkg ;
785804 } ) ;
786805
806+ // Move remaining non-Vite pnpm.overrides to pnpm-workspace.yaml
807+ if ( remainingPnpmOverrides ) {
808+ migratePnpmOverridesToWorkspaceYaml ( projectPath , remainingPnpmOverrides ) ;
809+ }
810+
787811 // Merge extracted staged config into vite.config.ts, then remove lint-staged from package.json
788812 if ( extractedStagedConfig ) {
789813 if ( mergeStagedConfigToViteConfig ( projectPath , extractedStagedConfig , silent , report ) ) {
@@ -983,6 +1007,55 @@ function rewritePnpmWorkspaceYaml(projectPath: string): void {
9831007 } ) ;
9841008}
9851009
1010+ /**
1011+ * Move remaining non-Vite pnpm.overrides from package.json to pnpm-workspace.yaml.
1012+ * pnpm ignores workspace-level overrides when pnpm.overrides exists in package.json,
1013+ * so all overrides must live in pnpm-workspace.yaml.
1014+ */
1015+ function migratePnpmOverridesToWorkspaceYaml (
1016+ projectPath : string ,
1017+ overrides : Record < string , string > ,
1018+ ) : void {
1019+ const pnpmWorkspaceYamlPath = path . join ( projectPath , 'pnpm-workspace.yaml' ) ;
1020+ editYamlFile ( pnpmWorkspaceYamlPath , ( doc ) => {
1021+ for ( const [ key , value ] of Object . entries ( overrides ) ) {
1022+ if ( ! doc . hasIn ( [ 'overrides' , key ] ) ) {
1023+ doc . setIn ( [ 'overrides' , scalarString ( key ) ] , scalarString ( value ) ) ;
1024+ }
1025+ }
1026+ } ) ;
1027+ }
1028+
1029+ /**
1030+ * Remove only Vite-managed entries from peerDependencyRules, preserving custom ones.
1031+ */
1032+ function cleanupPeerDependencyRules (
1033+ peerDependencyRules :
1034+ | { allowAny ?: string [ ] ; allowedVersions ?: Record < string , string > }
1035+ | undefined ,
1036+ overrideKeys : string [ ] ,
1037+ ) : void {
1038+ if ( ! peerDependencyRules ) {
1039+ return ;
1040+ }
1041+ if ( Array . isArray ( peerDependencyRules . allowAny ) ) {
1042+ peerDependencyRules . allowAny = peerDependencyRules . allowAny . filter (
1043+ ( key ) => ! overrideKeys . includes ( key ) ,
1044+ ) ;
1045+ if ( peerDependencyRules . allowAny . length === 0 ) {
1046+ delete peerDependencyRules . allowAny ;
1047+ }
1048+ }
1049+ if ( peerDependencyRules . allowedVersions ) {
1050+ for ( const key of overrideKeys ) {
1051+ delete peerDependencyRules . allowedVersions [ key ] ;
1052+ }
1053+ if ( Object . keys ( peerDependencyRules . allowedVersions ) . length === 0 ) {
1054+ delete peerDependencyRules . allowedVersions ;
1055+ }
1056+ }
1057+ }
1058+
9861059/**
9871060 * Rewrite .yarnrc.yml to add vite-plus dependencies
9881061 * @param projectPath - The path to the project
@@ -1085,13 +1158,17 @@ function rewriteRootWorkspacePackageJson(
10851158 return ;
10861159 }
10871160
1161+ let remainingPnpmOverrides : Record < string , string > | undefined ;
10881162 editJsonFile < {
10891163 resolutions ?: Record < string , string > ;
10901164 overrides ?: Record < string , string > ;
10911165 devDependencies ?: Record < string , string > ;
10921166 pnpm ?: {
10931167 overrides ?: Record < string , string > ;
1094- peerDependencyRules ?: Record < string , unknown > ;
1168+ peerDependencyRules ?: {
1169+ allowAny ?: string [ ] ;
1170+ allowedVersions ?: Record < string , string > ;
1171+ } ;
10951172 } ;
10961173 } > ( packageJsonPath , ( pkg ) => {
10971174 if ( packageManager === PackageManager . yarn ) {
@@ -1109,6 +1186,7 @@ function rewriteRootWorkspacePackageJson(
11091186 } else if ( packageManager === PackageManager . bun ) {
11101187 // bun overrides are handled in rewriteBunCatalog() with catalog: references
11111188 } else if ( packageManager === PackageManager . pnpm ) {
1189+ const overrideKeys = Object . keys ( VITE_PLUS_OVERRIDE_PACKAGES ) ;
11121190 if ( isForceOverrideMode ( ) ) {
11131191 // In force-override mode, keep overrides in package.json pnpm.overrides
11141192 // because pnpm ignores pnpm-workspace.yaml overrides when pnpm.overrides
@@ -1122,27 +1200,43 @@ function rewriteRootWorkspacePackageJson(
11221200 } ,
11231201 } ;
11241202 } else {
1125- // pnpm use overrides field at pnpm-workspace.yaml
1126- // so we don't need to set overrides field at package.json
1127- // remove packages from `resolutions` field and `pnpm.overrides` field if they exist
1128- // https://pnpm.io/9.x/package_json#resolutions
1129- for ( const key of [ ...Object . keys ( VITE_PLUS_OVERRIDE_PACKAGES ) , ...REMOVE_PACKAGES ] ) {
1203+ // Remove Vite-managed keys from pnpm.overrides
1204+ for ( const key of [ ...overrideKeys , ...REMOVE_PACKAGES ] ) {
11301205 if ( pkg . pnpm ?. overrides ?. [ key ] ) {
11311206 delete pkg . pnpm . overrides [ key ] ;
11321207 }
11331208 if ( pkg . resolutions ?. [ key ] ) {
11341209 delete pkg . resolutions [ key ] ;
11351210 }
11361211 }
1137- delete pkg . pnpm ?. peerDependencyRules ;
1138- if ( pkg . pnpm ?. overrides && Object . keys ( pkg . pnpm . overrides ) . length === 0 ) {
1139- delete pkg . pnpm . overrides ;
1212+ // Remove dependency selectors targeting vite
1213+ for ( const key in pkg . pnpm ?. overrides ) {
1214+ if ( key . includes ( '>' ) ) {
1215+ const splits = key . split ( '>' ) ;
1216+ if ( splits [ splits . length - 1 ] . trim ( ) === 'vite' ) {
1217+ delete pkg . pnpm . overrides [ key ] ;
1218+ }
1219+ }
1220+ }
1221+ // Move any remaining overrides to pnpm-workspace.yaml then delete all
1222+ // (pnpm ignores workspace-level overrides when pnpm.overrides exists in package.json)
1223+ if ( pkg . pnpm ?. overrides && Object . keys ( pkg . pnpm . overrides ) . length > 0 ) {
1224+ remainingPnpmOverrides = { ...pkg . pnpm . overrides } ;
1225+ }
1226+ delete pkg . pnpm ?. overrides ;
1227+ // Only remove Vite-managed peerDependencyRules entries, preserve custom ones
1228+ cleanupPeerDependencyRules ( pkg . pnpm ?. peerDependencyRules , overrideKeys ) ;
1229+ if (
1230+ pkg . pnpm ?. peerDependencyRules &&
1231+ Object . keys ( pkg . pnpm . peerDependencyRules ) . length === 0
1232+ ) {
1233+ delete pkg . pnpm . peerDependencyRules ;
11401234 }
11411235 if ( pkg . pnpm && Object . keys ( pkg . pnpm ) . length === 0 ) {
11421236 delete pkg . pnpm ;
11431237 }
11441238 }
1145- // remove dependency selector from vite, e.g. "vite-plugin-svgr>vite": "npm:vite@7.0.12"
1239+ // remove dependency selector from vite in force-override mode
11461240 for ( const key in pkg . pnpm ?. overrides ) {
11471241 if ( key . includes ( '>' ) ) {
11481242 const splits = key . split ( '>' ) ;
@@ -1166,6 +1260,11 @@ function rewriteRootWorkspacePackageJson(
11661260 return pkg ;
11671261 } ) ;
11681262
1263+ // Move remaining non-Vite pnpm.overrides to pnpm-workspace.yaml
1264+ if ( remainingPnpmOverrides ) {
1265+ migratePnpmOverridesToWorkspaceYaml ( projectPath , remainingPnpmOverrides ) ;
1266+ }
1267+
11691268 // rewrite package.json
11701269 rewriteMonorepoProject ( projectPath , packageManager , skipStagedMigration ) ;
11711270}
0 commit comments