@@ -305,11 +305,60 @@ function mergeOverrideEntry(merged, name, spec) {
305305 }
306306 return ;
307307 }
308+ if (
309+ typeof current === "string" &&
310+ isPlainObject ( spec ) &&
311+ typeof spec [ "." ] === "string" &&
312+ exactOverrideVersionsMatch ( current , spec [ "." ] )
313+ ) {
314+ merged [ name ] = { "." : preferredExactOverrideRootSpec ( current , spec [ "." ] ) } ;
315+ for ( const [ nestedName , nestedSpec ] of Object . entries ( spec ) ) {
316+ if ( nestedName === "." ) {
317+ continue ;
318+ }
319+ mergeOverrideEntry ( merged [ name ] , nestedName , nestedSpec ) ;
320+ }
321+ return ;
322+ }
323+ if (
324+ isPlainObject ( current ) &&
325+ typeof spec === "string" &&
326+ typeof current [ "." ] === "string" &&
327+ exactOverrideVersionsMatch ( current [ "." ] , spec )
328+ ) {
329+ current [ "." ] = preferredExactOverrideRootSpec ( current [ "." ] , spec ) ;
330+ return ;
331+ }
308332 if ( JSON . stringify ( current ) !== JSON . stringify ( spec ) ) {
309333 throw new Error ( `package.json overrides.${ name } conflicts with pnpm lock policy for ${ name } ` ) ;
310334 }
311335}
312336
337+ function preferredExactOverrideRootSpec ( current , incoming ) {
338+ return incoming . startsWith ( "npm:" ) ? incoming : current ;
339+ }
340+
341+ function exactOverrideVersionsMatch ( left , right ) {
342+ const leftVersion = exactVersionFromOverrideSpec ( left ) ;
343+ if ( leftVersion === null || leftVersion !== exactVersionFromOverrideSpec ( right ) ) {
344+ return false ;
345+ }
346+ const leftAlias = parseNpmAliasOverrideSpec ( left ) ;
347+ const rightAlias = parseNpmAliasOverrideSpec ( right ) ;
348+ return ! leftAlias || ! rightAlias || leftAlias . name === rightAlias . name ;
349+ }
350+
351+ function parseNpmAliasOverrideSpec ( spec ) {
352+ if ( ! spec . startsWith ( "npm:" ) ) {
353+ return null ;
354+ }
355+ const versionIndex = spec . lastIndexOf ( "@" ) ;
356+ if ( versionIndex <= "npm:" . length ) {
357+ return null ;
358+ }
359+ return { name : spec . slice ( "npm:" . length , versionIndex ) } ;
360+ }
361+
313362function mergeOverrides ( packageOverrides , workspaceOverrides , pnpmLockOverrides ) {
314363 const merged = normalizeOverrides ( packageOverrides ) ;
315364 for ( const [ name , spec ] of [
0 commit comments