defmodule Mix.Tasks.Npm.Dedupe do
@shortdoc "Deduplicate packages"
@moduledoc """
Re-resolve dependencies to minimize duplicate packages.
mix npm.dedupe
Re-runs the resolver from scratch to find an optimal solution
with fewer total packages.
"""
use Mix.Task
@impl true
def run([]) do
Application.ensure_all_started(:req)
case NPM.Lockfile.read() do
{:ok, lockfile} when lockfile == %{} ->
Mix.shell().info("No npm.lock found, run `mix npm.install` first.")
{:ok, old_lockfile} ->
count_before = map_size(old_lockfile)
NPM.install([])
report_dedupe(count_before)
{:error, reason} ->
Mix.shell().error("Failed to read lockfile: #{inspect(reason)}")
end
end
def run(_) do
Mix.shell().error("Usage: mix npm.dedupe")
end
defp report_dedupe(count_before) do
{:ok, new_lockfile} = NPM.Lockfile.read()
diff = count_before - map_size(new_lockfile)
print_dedupe_result(diff)
end
defp print_dedupe_result(diff) when diff > 0 do
Mix.shell().info("Removed #{diff} duplicate package#{if diff != 1, do: "s"}")
end
defp print_dedupe_result(_), do: Mix.shell().info("No duplicates found.")
end