@@ -34,6 +34,8 @@ const getKey = (startNode) => {
3434
3535module . exports = cls => class IsolatedReifier extends cls {
3636 #externalProxies = new Map ( )
37+ #omit = new Set ( )
38+ #rootDeclaredDeps = new Set ( )
3739 #processedEdges = new Set ( )
3840 #workspaceProxies = new Map ( )
3941
@@ -71,7 +73,19 @@ module.exports = cls => class IsolatedReifier extends cls {
7173 **/
7274 async makeIdealGraph ( ) {
7375 const idealTree = this . idealTree
74- const omit = new Set ( this . options . omit )
76+ this . #omit = new Set ( this . options . omit )
77+ const omit = this . #omit
78+
79+ // npm auto-creates 'workspace' edges from root to all workspaces.
80+ // For isolated/linked mode, only include workspaces that root explicitly declares as dependencies.
81+ // When omitting dep types, exclude those from the declared set so their workspaces aren't hoisted.
82+ const rootPkg = idealTree . package
83+ this . #rootDeclaredDeps = new Set ( [
84+ ...Object . keys ( rootPkg . dependencies || { } ) ,
85+ ...( ! omit . has ( 'dev' ) ? Object . keys ( rootPkg . devDependencies || { } ) : [ ] ) ,
86+ ...( ! omit . has ( 'optional' ) ? Object . keys ( rootPkg . optionalDependencies || { } ) : [ ] ) ,
87+ ...( ! omit . has ( 'peer' ) ? Object . keys ( rootPkg . peerDependencies || { } ) : [ ] ) ,
88+ ] )
7589
7690 // XXX this sometimes acts like a node too
7791 this . idealGraph = {
@@ -186,11 +200,34 @@ module.exports = cls => class IsolatedReifier extends cls {
186200 return
187201 }
188202
189- const edges = [ ...node . edgesOut . values ( ) ] . filter ( edge =>
203+ let edges = [ ...node . edgesOut . values ( ) ] . filter ( edge =>
190204 edge . to ?. target &&
191205 ! ( node . package . bundledDependencies || node . package . bundleDependencies ) ?. includes ( edge . to . name )
192206 )
193- const nonOptionalDeps = edges . filter ( edge => ! edge . optional ) . map ( edge => edge . to . target )
207+
208+ // Only omit edge types for root and workspace nodes (matching shouldOmit scope)
209+ if ( ( node . isProjectRoot || node . isWorkspace ) && this . #omit. size ) {
210+ edges = edges . filter ( edge => {
211+ if ( edge . dev && this . #omit. has ( 'dev' ) ) {
212+ return false
213+ }
214+ if ( edge . optional && this . #omit. has ( 'optional' ) ) {
215+ return false
216+ }
217+ if ( edge . peer && this . #omit. has ( 'peer' ) ) {
218+ return false
219+ }
220+ return true
221+ } )
222+ }
223+
224+ let nonOptionalDeps = edges . filter ( edge => ! edge . optional ) . map ( edge => edge . to . target )
225+
226+ // npm auto-creates 'workspace' edges from root to all workspaces.
227+ // For isolated/linked mode, only include workspaces that root explicitly declares as dependencies.
228+ if ( node . isProjectRoot ) {
229+ nonOptionalDeps = nonOptionalDeps . filter ( n => ! n . isWorkspace || this . #rootDeclaredDeps. has ( n . packageName ) )
230+ }
194231
195232 // When legacyPeerDeps is enabled, peer dep edges are not created on the node.
196233 // Resolve them from the tree so they get symlinked in the store.
@@ -293,22 +330,26 @@ module.exports = cls => class IsolatedReifier extends cls {
293330 workspace . isWorkspace = true
294331 root . fsChildren . add ( workspace )
295332 root . inventory . set ( workspace . location , workspace )
333+ root . workspaces . set ( wsName , workspace . path )
296334
297- // Create workspace Link entry in children for _diffTrees lookup
335+ // Create workspace Link. For root declared deps, link at root node_modules/. For undeclared deps, link at the workspace's own node_modules/ (self-link).
336+ const isDeclared = this . #rootDeclaredDeps. has ( wsName )
298337 const wsLink = new IsolatedLink ( {
299- location : join ( 'node_modules' , wsName ) ,
338+ location : isDeclared ? join ( 'node_modules' , wsName ) : join ( c . localLocation , 'node_modules' , wsName ) ,
300339 name : wsName ,
301340 package : workspace . package ,
302341 parent : root ,
303- path : join ( root . path , 'node_modules' , wsName ) ,
342+ path : isDeclared ? join ( root . path , 'node_modules' , wsName ) : join ( root . path , c . localLocation , 'node_modules' , wsName ) ,
304343 realpath : workspace . path ,
305344 root,
306345 target : workspace ,
307346 } )
308347 wsLink . top = root
309- root . children . set ( wsLink . name , wsLink )
348+ if ( ! isDeclared ) {
349+ workspace . children . set ( wsName , wsLink )
350+ }
351+ root . children . set ( wsName , wsLink )
310352 root . inventory . set ( wsLink . location , wsLink )
311- root . workspaces . set ( wsName , workspace . path )
312353 workspace . linksIn . add ( wsLink )
313354 }
314355
0 commit comments