defmodule NPM.Package.People do
@moduledoc """
Extracts and analyzes author/contributor information from packages.
"""
@doc """
Extracts the author from package.json data.
"""
@spec author(map()) :: map() | nil
def author(%{"author" => author}) when is_binary(author), do: NPM.Normalize.parse_person(author)
def author(%{"author" => author}) when is_map(author), do: author
def author(_), do: nil
@doc """
Extracts contributors list.
"""
@spec contributors(map()) :: [map()]
def contributors(%{"contributors" => list}) when is_list(list) do
Enum.map(list, fn
person when is_binary(person) -> NPM.Normalize.parse_person(person)
person when is_map(person) -> person
end)
end
def contributors(%{"maintainers" => list}) when is_list(list) do
Enum.map(list, fn
person when is_binary(person) -> NPM.Normalize.parse_person(person)
person when is_map(person) -> person
end)
end
def contributors(_), do: []
@doc """
Returns all people (author + contributors).
"""
@spec all(map()) :: [map()]
def all(data) do
author_list =
case author(data) do
nil -> []
a -> [a]
end
author_list ++ contributors(data)
end
@doc """
Counts unique contributors across multiple packages.
"""
@spec unique_authors([map()]) :: [String.t()]
def unique_authors(packages) do
packages
|> Enum.flat_map(fn data ->
case author(data) do
%{"name" => name} -> [name]
_ -> []
end
end)
|> Enum.uniq()
|> Enum.sort()
end
@doc """
Checks if author info is present.
"""
@spec has_author?(map()) :: boolean()
def has_author?(data), do: author(data) != nil
end