pub fn all_transitive_closures<L: Lockfile + ?Sized>(
    lockfile: &L,
    workspaces: HashMap<String, HashMap<String, String>>,
    ignore_missing_packages: bool,
) -> Result<HashMap<String, HashSet<Package>>, Error> {
    workspaces
        .into_par_iter()
        .map(|(workspace, unresolved_deps)| {
            let closure = transitive_closure(
                lockfile,
                &workspace,
                unresolved_deps,
                ignore_missing_packages,
            )?;
            Ok((workspace, closure))
        })
        .collect()
}
Takes a lockfile, and a map of workspace directory paths -> (package name,
version) and calculates the transitive closures for all of them
crates/turborepo-lockfiles/src/lib.rs