defmodule NPM.Package.PublishConfig do
@moduledoc """
Parses the `publishConfig` field from package.json.
Controls behavior when `npm publish` is called — registry,
access level, tag, etc.
"""
@doc """
Extracts publishConfig from package.json data.
"""
@spec extract(map()) :: map()
def extract(%{"publishConfig" => config}) when is_map(config), do: config
def extract(_), do: %{}
@doc """
Returns the publish registry URL.
"""
@spec registry(map()) :: String.t() | nil
def registry(data), do: extract(data) |> Map.get("registry")
@doc """
Returns the access level (public or restricted).
"""
@spec access(map()) :: String.t()
def access(data) do
case extract(data) |> Map.get("access") do
"public" -> "public"
"restricted" -> "restricted"
_ -> default_access(data)
end
end
@doc """
Returns the publish tag (default: "latest").
"""
@spec tag(map()) :: String.t()
def tag(data), do: extract(data) |> Map.get("tag", "latest")
@doc """
Checks if the package would be published as public.
"""
@spec public?(map()) :: boolean()
def public?(data), do: access(data) == "public"
@doc """
Checks if publishConfig is set.
"""
@spec configured?(map()) :: boolean()
def configured?(data), do: extract(data) != %{}
@doc """
Formats publishConfig for display.
"""
@spec format(map()) :: String.t()
def format(data) do
config = extract(data)
if config == %{} do
"No publish configuration."
else
config
|> Enum.map_join(", ", fn {k, v} -> "#{k}: #{v}" end)
|> then(&"Publish config: #{&1}")
end
end
defp default_access(%{"name" => name}) when is_binary(name) do
if NPM.Scope.scoped?(name), do: "restricted", else: "public"
end
defp default_access(_), do: "public"
end