@@ -221,6 +221,9 @@ analyze file = context "Analyzing Npm Lockfile (v3)" $ do
221221-- --
222222buildGraph :: PackageLockV3 -> Graphing Dependency
223223buildGraph pkgLockV3 = run . evalGrapher $ do
224+ let initialDevDepPaths = Set. fromList $ map toTopLevelPackage $ Map. keys $ plV3PkgDevDependencies $ rootPackage pkgLockV3
225+ let allDevDepPaths = collectAllTransitivePaths initialDevDepPaths
226+
224227 for_ (Map. toList $ packages pkgLockV3) $ \ (pkgPathKey, pkgMetadata) -> do
225228 case pkgPathKey of
226229 -- For root package,
@@ -262,7 +265,7 @@ buildGraph pkgLockV3 = run . evalGrapher $ do
262265 ]
263266
264267 let resolvedDeps :: [Dependency ]
265- resolvedDeps = mapMaybe toDependency directDeps
268+ resolvedDeps = mapMaybe ( toDependency allDevDepPaths) directDeps
266269
267270 traverse_ direct resolvedDeps
268271
@@ -300,8 +303,11 @@ buildGraph pkgLockV3 = run . evalGrapher $ do
300303 , plV3PkgOptionalDependencies pkgMetadata
301304 ]
302305
306+ let workspaceDevDeps = Set. fromList $ map (vendoredPathElseTopLevelPath workspaceRootPath) $ Map. keys $ plV3PkgDevDependencies pkgMetadata
307+ let workspaceAllDevDeps = allDevDepPaths `Set.union` workspaceDevDeps
308+
303309 let resolvedDeps :: [Dependency ]
304- resolvedDeps = mapMaybe toDependency directDeps
310+ resolvedDeps = mapMaybe ( toDependency workspaceAllDevDeps) directDeps
305311
306312 traverse_ direct resolvedDeps
307313
@@ -329,7 +335,7 @@ buildGraph pkgLockV3 = run . evalGrapher $ do
329335 -- For each transitive dependency, Adds edge between parent package, and transitive dep.
330336 PackageLockV3PathKey prefixPath depPackageName -> do
331337 let currentDep :: Maybe Dependency
332- currentDep = toDependency (PackageLockV3PathKey prefixPath depPackageName)
338+ currentDep = toDependency allDevDepPaths (PackageLockV3PathKey prefixPath depPackageName)
333339
334340 let vendorPathPrefix :: Text
335341 vendorPathPrefix = prefixPath <> (unPackageName depPackageName)
@@ -345,13 +351,45 @@ buildGraph pkgLockV3 = run . evalGrapher $ do
345351 ]
346352
347353 let resolvedDeepDeps :: [Dependency ]
348- resolvedDeepDeps = mapMaybe toDependency deepDeps
354+ resolvedDeepDeps = mapMaybe ( toDependency allDevDepPaths) deepDeps
349355
350356 case currentDep of
351357 Nothing -> pure () -- This will never happen, given that we are iterating on same package path.
352358 Just parentDep -> do
353359 for_ resolvedDeepDeps $ edge parentDep
354360 where
361+ -- Returns the set of all paths that are transitive to the given set of paths.
362+ collectAllTransitivePaths :: Set. Set PackagePath -> Set. Set PackagePath
363+ collectAllTransitivePaths paths =
364+ let go visited toVisit
365+ | Set. null toVisit = visited
366+ | otherwise =
367+ let (current, rest) = Set. deleteFindMin toVisit
368+ in if Set. member current visited
369+ then go visited rest
370+ else
371+ let newChildren = collectTransitivePaths current
372+ newVisited = Set. insert current visited
373+ newToVisit = rest `Set.union` (newChildren `Set.difference` newVisited)
374+ in go newVisited newToVisit
375+ in go Set. empty paths
376+
377+ -- Returns the set of all transitive paths for given package path.
378+ collectTransitivePaths :: PackagePath -> Set. Set PackagePath
379+ collectTransitivePaths pkgPath =
380+ case Map. lookup pkgPath (packages pkgLockV3) of
381+ Nothing -> Set. empty
382+ Just pkgMetadata ->
383+ let vendorPrefix = case pkgPath of
384+ PackageLockV3PathKey prefix pkgName -> prefix <> unPackageName pkgName
385+ _ -> " "
386+ directDeps = concatMap Map. keys
387+ [ plV3PkgDependencies pkgMetadata
388+ , plV3PkgPeerDependencies pkgMetadata
389+ , plV3PkgOptionalDependencies pkgMetadata
390+ ]
391+ in Set. fromList $ map (vendoredPathElseTopLevelPath vendorPrefix) directDeps
392+
355393 -- Prefer resolution path in following order of precedent:
356394 --
357395 -- 1) {prefix}/node_modules/{pkgName}
@@ -374,8 +412,8 @@ buildGraph pkgLockV3 = run . evalGrapher $ do
374412 map (`PackageLockV3PathKey ` pkgName) $
375413 vendorPrefixes prefix (getRootWorkspace prefix)
376414
377- toDependency :: PackagePath -> Maybe Dependency
378- toDependency pkgPath =
415+ toDependency :: Set. Set PackagePath -> PackagePath -> Maybe Dependency
416+ toDependency devPaths pkgPath =
379417 case (pkgPath, Map. lookup pkgPath $ packages pkgLockV3) of
380418 (PackageLockV3PathKey _ packageName, Just meta) ->
381419 Just $
@@ -385,7 +423,7 @@ buildGraph pkgLockV3 = run . evalGrapher $ do
385423 , dependencyVersion = CEq <$> (plV3PkgVersion meta)
386424 , dependencyLocations = catMaybes [unNpmLockV3Resolved $ plV3PkgResolved meta]
387425 , dependencyEnvironments =
388- if plV3PkgDev meta
426+ if plV3PkgDev meta || Set. member pkgPath devPaths
389427 then Set. singleton EnvDevelopment
390428 else Set. singleton EnvProduction
391429 , dependencyTags = Map. empty
0 commit comments