defmodule Microwaveprop.MixProject do use Mix.Project def project do [ app: :microwaveprop, version: "0.1.0", elixir: "~> 1.15", elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, aliases: aliases(), deps: deps(), compilers: [:phoenix_live_view] ++ Mix.compilers(), listeners: [Phoenix.CodeReloader], dialyzer: [ plt_add_apps: [:mix, :ex_unit], plt_file: {:no_warn, "priv/plts/project.plt"}, flags: [ :error_handling, :unknown, :unmatched_returns, :extra_return, :missing_return ] ] ] end # Configuration for the OTP application. # # Type `mix help compile.app` for more information. def application do [ mod: {Microwaveprop.Application, []}, extra_applications: [:logger, :runtime_tools, :os_mon, :xmerl] ] end def cli do [ preferred_envs: [precommit: :test] ] end # Specifies which paths to compile per environment. defp elixirc_paths(:test), do: ["lib", "lib_ml", "test/support"] defp elixirc_paths(:dev), do: ["lib", "lib_ml"] defp elixirc_paths(_), do: ["lib"] # Specifies your project dependencies. # # Type `mix help deps` for examples and options. defp deps do [ {:bcrypt_elixir, "~> 3.0"}, {:phoenix, "~> 1.8.3"}, {:phoenix_ecto, "~> 4.5"}, {:ecto_sql, "~> 3.13"}, {:postgrex, ">= 0.0.0"}, {:phoenix_html, "~> 4.1"}, {:phoenix_live_reload, "~> 1.2", only: :dev}, {:phoenix_live_view, "~> 1.1.0"}, {:lazy_html, ">= 0.1.0", only: :test}, {:stream_data, "~> 1.0", only: :test}, {:live_stash, "~> 0.1"}, {:phoenix_live_dashboard, "~> 0.8.3"}, {:esbuild, "~> 0.10", runtime: Mix.env() == :dev}, {:tailwind, "~> 0.3", runtime: Mix.env() == :dev}, {:heroicons, github: "tailwindlabs/heroicons", tag: "v2.2.0", sparse: "optimized", app: false, compile: false, depth: 1}, {:swoosh, "~> 1.16"}, {:gen_smtp, "~> 1.2"}, {:req, "~> 0.5"}, {:telemetry_metrics, "~> 1.0"}, {:telemetry_poller, "~> 1.0"}, {:prom_ex, "~> 1.11"}, # OpenTelemetry — traces only. Exporter ships via OTLP/gRPC to # the cluster Collector at OTEL_EXPORTER_OTLP_ENDPOINT. The # *_phoenix / *_oban / *_bandit helper packages auto-instrument # those libraries via their telemetry events. opentelemetry_ecto # deliberately omitted: one span per query produced Oban-job # traces with thousands of child spans that crashed Tempo. {:opentelemetry, "~> 1.5"}, {:opentelemetry_api, "~> 1.4"}, {:opentelemetry_exporter, "~> 1.8"}, {:opentelemetry_phoenix, "~> 2.0"}, {:opentelemetry_oban, "~> 1.1"}, {:opentelemetry_bandit, "~> 0.2"}, {:gettext, "~> 0.26"}, {:jason, "~> 1.2"}, {:msgpax, "~> 2.4"}, {:bandit, "~> 1.5"}, {:styler, "~> 1.11", only: [:dev, :test], runtime: false}, {:oban, "~> 2.21"}, {:oban_met, "~> 1.0", path: "vendor/oban_met", override: true}, {:oban_pro, "~> 1.6", path: "vendor/oban_pro"}, {:oban_web, "~> 2.12", path: "vendor/oban_web", override: true}, {:credo, "~> 1.7", only: [:dev, :test], runtime: false}, {:nx, "~> 0.9", only: [:dev, :test]}, {:axon, "~> 0.7", only: [:dev, :test]}, {:exla, "~> 0.9", only: [:dev, :test]}, {:polaris, "~> 0.1", only: [:dev, :test]}, {:tidewave, "~> 0.5", only: :dev}, {:libcluster, "~> 3.4"}, {:ecto_psql_extras, "~> 0.8"}, {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}, {:live_table, "~> 0.4.1"}, {:sutra_ui, "~> 0.3.0"}, # Required as a compile-time build dependency for live_table; its mix # tasks (lib/mix/tasks/live_table.gen.live.ex, live_table.install.ex) # unconditionally `use Igniter.Mix.Task` so the dep has to exist in # every env live_table is compiled in, not just dev/test. runtime: false # keeps it out of the release bundle. {:igniter, "~> 0.7", runtime: false} ] end # Aliases are shortcuts or tasks specific to the current project. # For example, to install project dependencies and perform other setup tasks, run: # # $ mix setup # # See the documentation for `Mix` for more info on aliases. defp aliases do [ setup: ["deps.get", "ecto.setup", "assets.setup", "assets.build"], "deps.get": ["deps.get", &apply_dep_patches/1], "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"], "ecto.reset": ["ecto.drop", "ecto.setup"], test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"], "assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"], "assets.build": ["compile", "tailwind microwaveprop", "esbuild microwaveprop"], "assets.deploy": [ "tailwind microwaveprop --minify", "esbuild microwaveprop --minify", "phx.digest" ], precommit: ["compile --warnings-as-errors", "deps.unlock --unused", "format", "test"] ] end # Applies every patch file in `priv/dep_patches/*.patch` to its corresponding # dependency under `deps/`. Inlined here (instead of a `Mix.Task` module # under `lib/mix/tasks/`) so it can run during `mix deps.get` itself — # `lib/` isn't compiled yet at that point, so a proper task would not be # resolvable. Idempotent: a sentinel file per patch prevents re-application. @patches_dir "priv/dep_patches" defp apply_dep_patches(_args) do case File.ls(@patches_dir) do {:ok, entries} -> entries |> Enum.filter(&String.ends_with?(&1, ".patch")) |> Enum.sort() |> Enum.each(&apply_single_patch/1) {:error, :enoent} -> :ok end end defp apply_single_patch(filename) do dep_name = filename |> Path.basename(".patch") |> String.split("-") |> Enum.drop(-1) |> Enum.join("-") dep_dir = Path.join("deps", dep_name) sentinel = Path.join(dep_dir, ".#{filename}.applied") cond do not File.dir?(dep_dir) -> Mix.shell().info("deps.patch: skipping #{filename} — deps/#{dep_name} not present") File.exists?(sentinel) -> Mix.shell().info("deps.patch: #{filename} already applied") true -> patch_path = Path.absname(Path.join(@patches_dir, filename)) {output, exit_code} = System.cmd("patch", ["-p1", "-i", patch_path], cd: dep_dir) if exit_code == 0 do Mix.shell().info("deps.patch: applied #{filename}") File.touch!(sentinel) else Mix.raise("deps.patch: failed to apply #{filename}:\n#{output}") end end end end