@@ -4,6 +4,7 @@ import { parse } from "yaml";
44import {
55 collectCurrentShrinkwrapOverrides ,
66 collectPnpmLockViolations ,
7+ mergeOverrides ,
78 parsePnpmPackageKey ,
89 readShrinkwrapOverrides ,
910} from "../scripts/generate-npm-shrinkwrap.mjs" ;
@@ -132,6 +133,82 @@ describe("package manager build policy", () => {
132133 } ) ;
133134 } ) ;
134135
136+ it ( "merges exact current shrinkwrap pins with nested lock-derived pins" , ( ) => {
137+ expect (
138+ mergeOverrides (
139+ { "@mistralai/mistralai" : "2.2.1" } ,
140+ { "@mistralai/mistralai" : { "." : "2.2.1" , zod : "4.4.3" } } ,
141+ { } ,
142+ ) ,
143+ ) . toEqual ( {
144+ "@mistralai/mistralai" : { "." : "2.2.1" , zod : "4.4.3" } ,
145+ } ) ;
146+ } ) ;
147+
148+ it ( "preserves npm alias pins when merging nested lock-derived pins" , ( ) => {
149+ expect (
150+ mergeOverrides (
151+ { "node-domexception" : "npm:@nolyfill/domexception@1.0.28" } ,
152+ { "node-domexception" : { "." : "1.0.28" , child : "2.0.0" } } ,
153+ { } ,
154+ ) ,
155+ ) . toEqual ( {
156+ "node-domexception" : {
157+ "." : "npm:@nolyfill/domexception@1.0.28" ,
158+ child : "2.0.0" ,
159+ } ,
160+ } ) ;
161+ } ) ;
162+
163+ it ( "preserves later npm alias pins when nested pins are already merged" , ( ) => {
164+ expect (
165+ mergeOverrides (
166+ { "node-domexception" : { "." : "1.0.28" , child : "2.0.0" } } ,
167+ { "node-domexception" : "npm:@nolyfill/domexception@1.0.28" } ,
168+ { } ,
169+ ) ,
170+ ) . toEqual ( {
171+ "node-domexception" : {
172+ "." : "npm:@nolyfill/domexception@1.0.28" ,
173+ child : "2.0.0" ,
174+ } ,
175+ } ) ;
176+ } ) ;
177+
178+ it ( "rejects non-exact root pins when merging nested pins" , ( ) => {
179+ expect ( ( ) =>
180+ mergeOverrides (
181+ { "floating-package" : "^1.0.0" } ,
182+ { "floating-package" : { "." : "~1.0.0" , child : "2.0.0" } } ,
183+ { } ,
184+ ) ,
185+ ) . toThrow ( / c o n f l i c t s w i t h p n p m l o c k p o l i c y / u) ;
186+ expect ( ( ) =>
187+ mergeOverrides (
188+ { "floating-package" : { "." : "^1.0.0" , child : "2.0.0" } } ,
189+ { "floating-package" : "~1.0.0" } ,
190+ { } ,
191+ ) ,
192+ ) . toThrow ( / c o n f l i c t s w i t h p n p m l o c k p o l i c y / u) ;
193+ } ) ;
194+
195+ it ( "rejects distinct npm alias targets with matching versions" , ( ) => {
196+ expect ( ( ) =>
197+ mergeOverrides (
198+ { "aliased-package" : "npm:@safe/foo@1.0.0" } ,
199+ { "aliased-package" : { "." : "npm:@other/foo@1.0.0" , child : "2.0.0" } } ,
200+ { } ,
201+ ) ,
202+ ) . toThrow ( / c o n f l i c t s w i t h p n p m l o c k p o l i c y / u) ;
203+ expect ( ( ) =>
204+ mergeOverrides (
205+ { "aliased-package" : { "." : "npm:@safe/foo@1.0.0" , child : "2.0.0" } } ,
206+ { "aliased-package" : "npm:@other/foo@1.0.0" } ,
207+ { } ,
208+ ) ,
209+ ) . toThrow ( / c o n f l i c t s w i t h p n p m l o c k p o l i c y / u) ;
210+ } ) ;
211+
135212 it ( "keeps npm shrinkwrap package versions inside the pnpm lock graph" , ( ) => {
136213 const pnpmLockPackages = collectPnpmLockPackages ( ) ;
137214 const shrinkwrapPaths = [
0 commit comments