mix.exs

defmodule Vodozemac.MixProject do
  use Mix.Project

  @version "0.1.2"
  @source_url "https://git.sr.ht/~sbr/vodozemac"

  def project do
    [
      app: :vodozemac,
      version: @version,
      elixir: "~> 1.15",
      elixirc_paths: elixirc_paths(Mix.env()),
      start_permanent: Mix.env() == :prod,
      deps: deps(),
      aliases: aliases(),
      description: description(),
      package: package(),
      docs: docs(),
      dialyzer: dialyzer(),
      source_url: @source_url,
      homepage_url: @source_url
    ]
    |> Keyword.merge(umbrella_paths())
  end

  def application do
    [extra_applications: [:logger]]
  end

  # `mix precommit` chains `mix test` as one of its steps; without this
  # block Mix runs the whole alias in :dev and `mix test` complains
  # about the env mismatch. Switching the alias to :test is fine —
  # format/credo/audit/dialyzer/hex.build are all env-agnostic.
  def cli do
    [preferred_envs: [precommit: :test]]
  end

  defp elixirc_paths(:test), do: ["lib", "test/support"]
  defp elixirc_paths(_), do: ["lib"]

  defp deps do
    [
      {:rustler_precompiled, "~> 0.8"},
      # 0.1.0 ships source-only — `force_build: true` in Vodozemac.Native
      # means rustler_precompiled hands compilation off to rustler on
      # every consumer build, so rustler must actually be present.
      # Flip back to `optional: true` once 0.1.1 ships the precompiled
      # tarballs (most consumers won't compile from source then).
      {:rustler, "~> 0.36"},
      {:ex_doc, "~> 0.34", only: :dev, runtime: false},

      # Static analysis + audit, all dev/test-only.
      {:credo, "~> 1.7", only: [:dev, :test], runtime: false},
      # ExSlop bundles credo checks for AI-generated-code antipatterns.
      # See https://github.com/elixir-vibe/ex_slop. Opt-in via
      # `EX_SLOP=1 mix credo` (.credo.exs reads the env var).
      {:ex_slop, "~> 0.1", only: [:dev, :test], runtime: false},
      {:mix_audit, "~> 2.1", only: [:dev, :test], runtime: false},
      {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}
    ]
  end

  defp aliases do
    [
      # Run before every commit / release. `mix hex.publish` runs
      # `hex.build` internally, so no need to chain it here.
      precommit: [
        "format --check-formatted",
        "credo",
        "deps.audit",
        "dialyzer",
        "test"
      ]
    ]
  end

  defp dialyzer do
    [
      plt_add_apps: [:ex_unit, :mix],
      flags: [:error_handling, :unknown, :underspecs],
      ignore_warnings: ".dialyzer_ignore.exs"
    ]
  end

  defp description do
    "Elixir bindings to Matrix's Olm and Megolm primitives via Element's " <>
      "vodozemac (Rust) — the successor to the deprecated libolm."
  end

  defp package do
    [
      # TODO: fill these in before `mix hex.publish`.
      maintainers: ["sbr"],
      licenses: ["BSD-3-Clause"],
      links: %{
        "Source" => @source_url,
        "Changelog" => @source_url <> "/tree/main/item/CHANGELOG.md",
        "vodozemac (upstream Rust)" => "https://github.com/matrix-org/vodozemac"
      },
      # checksum-Elixir.Vodozemac.Native.exs is regenerated after
      # precompiled artifacts are uploaded for a tagged release; add
      # it here for 0.1.1 when binaries start shipping.
      files: ~w(
        lib
        native/vodozemac_nif/Cargo.toml
        native/vodozemac_nif/src
        mix.exs
        README.md
        CHANGELOG.md
        LICENSE
        LICENSE-APACHE
      )
    ]
  end

  defp docs do
    [
      main: "readme",
      extras: ["README.md", "CHANGELOG.md", "LICENSE"],
      source_ref: "v#{@version}"
    ]
  end

  # When the package lives inside the 8by3 umbrella, share the parent
  # build/deps directories. After extraction into its own repo (no
  # `../../mix.exs` next to us), the parent dirs don't exist and we
  # build standalone. Same mix.exs works in both places.
  defp umbrella_paths do
    if File.exists?(Path.expand("../../mix.exs", __DIR__)) do
      [
        build_path: "../../_build",
        config_path: "../../config/config.exs",
        deps_path: "../../deps",
        lockfile: "../../mix.lock"
      ]
    else
      []
    end
  end
end