defmodule Mix.Tasks.Npm.View do @shortdoc "View detailed registry info for a package" @moduledoc """ View detailed information about a package from the registry. mix npm.view react mix npm.view lodash versions mix npm.view express dependencies Shows name, version, description, dependencies, engines, and more. """ use Mix.Task @impl true def run([name | fields]) do Application.ensure_all_started(:req) case NPM.Registry.get_packument(name) do {:ok, packument} -> latest = latest_version(packument) if fields == [] do print_full(name, packument, latest) else print_fields(packument, latest, fields) end {:error, :not_found} -> Mix.shell().error("Package #{name} not found.") {:error, reason} -> Mix.shell().error("Error: #{inspect(reason)}") end end def run([]) do Mix.shell().error("Usage: mix npm.view [field...]") end defp print_full(name, packument, latest) do info = Map.get(packument.versions, latest) Mix.shell().info("#{name}@#{latest}") if info do deps = info.dependencies if map_size(deps) > 0, do: print_map("dependencies", deps) peers = info.peer_dependencies if map_size(peers) > 0, do: print_map("peerDependencies", peers) engines = info.engines if map_size(engines) > 0, do: print_map("engines", engines) end Mix.shell().info("\nversions: #{map_size(packument.versions)}") end defp print_fields(packument, latest, fields) do info = Map.get(packument.versions, latest) Enum.each(fields, fn field -> value = get_field(packument, info, field) Mix.shell().info("#{field}: #{format_value(value)}") end) end defp get_field(packument, _info, "versions") do Map.keys(packument.versions) |> Enum.sort() end defp get_field(_packument, info, "dependencies"), do: info.dependencies defp get_field(_packument, info, "engines"), do: info.engines defp get_field(_packument, info, "peerDependencies"), do: info.peer_dependencies defp get_field(_packument, _info, _), do: nil defp format_value(nil), do: "(not available)" defp format_value(map) when is_map(map), do: inspect(map) defp format_value(list) when is_list(list), do: Enum.join(list, ", ") defp format_value(v), do: to_string(v) defp print_map(label, map) do Mix.shell().info("\n#{label}:") Enum.each(map, fn {k, v} -> Mix.shell().info(" #{k}: #{v}") end) end defp latest_version(packument) do packument.versions |> Map.keys() |> NPM.VersionUtil.sort() |> List.last() end end