diff --git a/lib/aura/model/hex_package.ex b/lib/aura/model/hex_package.ex index 959150d..aff222b 100644 --- a/lib/aura/model/hex_package.ex +++ b/lib/aura/model/hex_package.ex @@ -5,8 +5,8 @@ defmodule Aura.Model.HexPackage do alias Aura.Model.DownloadStats alias Aura.Model.HexPackage + alias Aura.Model.HexRelease alias Aura.Model.PackageMeta - alias Aura.Model.Release DownloadStats @@ -36,7 +36,7 @@ defmodule Aura.Model.HexPackage do defp serialize(:meta, v), do: PackageMeta.build(v) defp serialize(:downloads, v), do: DownloadStats.build(v) - defp serialize(:releases, v), do: Enum.map(v, &Release.build/1) + defp serialize(:releases, v), do: Enum.map(v, &HexRelease.build/1) defp serialize(_k, v), do: v end @@ -47,7 +47,6 @@ defmodule Aura.Model.PackageMeta do import Aura.Model.Common defstruct [ - # :maintainers, :links, :licenses, @@ -75,19 +74,3 @@ defmodule Aura.Model.DownloadStats do struct(Aura.Model.DownloadStats, fields) end end - -defmodule Aura.Model.Release do - @moduledoc false - - import Aura.Model.Common - - defstruct [ - :version, - :url - ] - - def build(m) when is_map(m) do - fields = prepare(m) - struct(Aura.Model.Release, fields) - end -end diff --git a/lib/aura/model/hex_release.ex b/lib/aura/model/hex_release.ex new file mode 100644 index 0000000..4c9de8e --- /dev/null +++ b/lib/aura/model/hex_release.ex @@ -0,0 +1,50 @@ +defmodule Aura.Model.HexRelease do + @moduledoc false + + import Aura.Model.Common + + defstruct [ + :checksum, + :configs, + :docs_html_url, + :downloads, + :has_docs, + :html_url, + :inserted_at, + :meta, + :package_url, + :publisher, + :requirements, + :retirement, + :updated_at, + :version, + :url + ] + + def build(m) when is_map(m) do + fields = + m + |> prepare() + |> Map.new(fn {k, v} -> {k, serialize(k, v)} end) + + struct(Aura.Model.HexRelease, fields) + end + + defp serialize(_k, nil), do: nil + defp serialize(:meta, v), do: v |> prepare() |> Map.new() + defp serialize(:publisher, v), do: v |> prepare() |> Map.new() + + defp serialize(:requirements, v) do + v + |> Map.values() + |> Enum.map(fn m -> m |> prepare() |> Map.new() end) + end + + defp serialize(:retirement, v) do + v + |> prepare() + |> Map.new(fn {k, v} -> if k == :reason, do: {k, String.to_atom(v)}, else: {k, v} end) + end + + defp serialize(_k, v), do: v +end diff --git a/lib/aura/releases.ex b/lib/aura/releases.ex new file mode 100644 index 0000000..7f2e0f6 --- /dev/null +++ b/lib/aura/releases.ex @@ -0,0 +1,12 @@ +defmodule Aura.Releases do + @moduledoc false + + alias Aura.Model.HexRelease + alias Aura.Requester + + def get_release(package_name, version) do + with {:ok, %{body: body}} <- Requester.get("/packages/#{package_name}/releases/#{version}") do + {:ok, HexRelease.build(body)} + end + end +end diff --git a/lib/aura/util/requester.ex b/lib/aura/util/requester.ex index d390dff..19a79bc 100644 --- a/lib/aura/util/requester.ex +++ b/lib/aura/util/requester.ex @@ -67,7 +67,7 @@ defmodule Aura.Requester do version = config[:version] || "0.0.0" e_version = System.version() mix_env = Mix.env() - user_agent = "#{app}/#{version} (Elixir/#{e_version}) (OTP/#{otp_version()})(#{mix_env})" + user_agent = "#{app}/#{version} (Elixir/#{e_version}) (OTP/#{otp_version()}) (#{mix_env})" {"User-Agent", user_agent} end diff --git a/test/aura/model/hex_package_test.exs b/test/aura/model/hex_package_test.exs new file mode 100644 index 0000000..c7bd2c1 --- /dev/null +++ b/test/aura/model/hex_package_test.exs @@ -0,0 +1,14 @@ +defmodule Aura.Model.HexPackageTest do + use ExUnit.Case + + import Aura.Factory + + alias Aura.Model.HexPackage + + doctest HexPackage + + test "build many" do + list = build_list(100, :hex_package) + assert Enum.count(list) == 100 + end +end diff --git a/test/aura/model/hex_release_test.exs b/test/aura/model/hex_release_test.exs new file mode 100644 index 0000000..c311138 --- /dev/null +++ b/test/aura/model/hex_release_test.exs @@ -0,0 +1,15 @@ +defmodule Aura.Model.HexReleaseTest do + use ExUnit.Case + + import Aura.Factory + + alias Aura.Model.HexRelease + + @moduletag :capture_log + doctest HexRelease + + test "build many" do + list = build_list(100, :hex_release) + assert Enum.count(list) == 100 + end +end diff --git a/test/aura/model/aura/model/hex_repo_test.exs b/test/aura/model/hex_repo_test.exs similarity index 100% rename from test/aura/model/aura/model/hex_repo_test.exs rename to test/aura/model/hex_repo_test.exs diff --git a/test/aura/releases_test.exs b/test/aura/releases_test.exs new file mode 100644 index 0000000..74a7bd8 --- /dev/null +++ b/test/aura/releases_test.exs @@ -0,0 +1,20 @@ +defmodule Aura.ReleasesTest do + use ExUnit.Case + + alias Aura.Packages + alias Aura.Releases + + @moduletag :capture_log + + doctest Releases + + test "get_release" do + [package] = Enum.take(Packages.list_packages(), 1) + version = package.releases |> hd() |> Map.get(:version) + assert {:ok, release} = Releases.get_release(package.name, version) + assert release.publisher + + assert {:ok, release} = Releases.get_release("ex_ftp", "0.9.2") + assert release.retirement.message + end +end diff --git a/test/support/factories/hex_package_factory.ex b/test/support/factories/hex_package_factory.ex new file mode 100644 index 0000000..03cff62 --- /dev/null +++ b/test/support/factories/hex_package_factory.ex @@ -0,0 +1,55 @@ +defmodule Aura.Factory.HexPackageFactory do + @moduledoc false + + defmacro __using__(_opts) do + quote do + def hex_package_factory(attrs) do + inserted_at = Faker.DateTime.backward(40) + meta = build(:package_meta) + downloads = build(:package_downloads) + releases = build_list(5, :hex_release) + + %Aura.Model.HexPackage{ + name: Faker.Internet.user_name(), + repository: Faker.Internet.user_name(), + private: Enum.random([true, false]), + meta: meta, + downloads: downloads, + releases: releases, + inserted_at: inserted_at, + url: Faker.Internet.url(), + html_url: Faker.Internet.url(), + docs_html_url: Faker.Internet.url(), + updated_at: Faker.DateTime.between(inserted_at, DateTime.now!("Etc/UTC")) + } + |> merge_attributes(attrs) + |> evaluate_lazy_attributes() + end + + def package_meta_factory(attrs) do + %Aura.Model.PackageMeta{ + maintainers: Enum.map(1..5, fn _ -> Faker.Internet.user_name() end), + links: Enum.map(1..5, fn _ -> Faker.Internet.url() end), + licenses: Enum.map(1..5, fn _ -> Faker.Internet.slug() end), + description: Faker.Lorem.sentence() + } + |> merge_attributes(attrs) + |> evaluate_lazy_attributes() + end + + def package_downloads_factory(attrs) do + day = Faker.random_between(10, 100) + week = day + Faker.random_between(10, 100) + all = week + Faker.random_between(10, 100) + + %Aura.Model.DownloadStats{ + all: all, + week: week, + day: day + } + |> merge_attributes(attrs) + |> evaluate_lazy_attributes() + end + end + end +end diff --git a/test/support/factories/hex_release_factory.ex b/test/support/factories/hex_release_factory.ex new file mode 100644 index 0000000..904ae7e --- /dev/null +++ b/test/support/factories/hex_release_factory.ex @@ -0,0 +1,61 @@ +defmodule Aura.Factory.HexReleaseFactory do + @moduledoc false + + defmacro __using__(_opts) do + quote do + def hex_release_factory(attrs) do + name = Faker.Internet.slug() + + requirements = + Enum.map(1..5, fn _ -> + %{optional: Enum.random([true, false]), app: Faker.Internet.slug(), requirement: "~> #{Faker.App.semver()}"} + end) + + meta = %{elixir: "~> 1.18", app: name, build_tools: ["mix"]} + + configs = + %{ + "erlang.mk" => "#{name} = hex 0.9.2", + "mix.exs" => "{:#{name}, \"~> 0.9.2\"}", + "rebar.config" => "{#{name}, \"0.9.2\"}" + } + + publisher = + Enum.map(1..5, fn _ -> + %{url: Faker.Internet.url(), email: Faker.Internet.email(), username: Faker.Internet.user_name()} + end) + + inserted_at = Faker.DateTime.backward(40) + has_docs = Enum.random([true, false]) + docs_html_url = if has_docs, do: Faker.Internet.url() + retired? = Enum.random([true, false]) + + retirement = + if retired?, + do: %{ + message: Faker.Lorem.sentence(), + reason: Enum.random([:other, :invalid, :security, :deprecated, :renamed]) + } + + %Aura.Model.HexRelease{ + configs: configs, + meta: meta, + checksum: Faker.Lorem.characters(65), + version: Faker.App.semver(), + url: Faker.Internet.url(), + docs_html_url: docs_html_url, + html_url: Faker.Internet.url(), + has_docs: has_docs, + package_url: Faker.Internet.url(), + downloads: Faker.random_between(10, 100), + publisher: publisher, + retirement: retirement, + inserted_at: inserted_at, + updated_at: Faker.DateTime.between(inserted_at, DateTime.now!("Etc/UTC")) + } + |> merge_attributes(attrs) + |> evaluate_lazy_attributes() + end + end + end +end diff --git a/test/support/factory.ex b/test/support/factory.ex index cf8b135..b69d14a 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -2,4 +2,6 @@ defmodule Aura.Factory do @moduledoc false use ExMachina use Aura.Factory.HexRepoFactory + use Aura.Factory.HexPackageFactory + use Aura.Factory.HexReleaseFactory end