From 2679c8843e08db715bf8bcb8a59de1c019f00152 Mon Sep 17 00:00:00 2001 From: crbelaus Date: Sat, 5 Apr 2025 17:34:23 +0200 Subject: [PATCH 1/7] Add Igniter dependency --- mix.exs | 4 +++- mix.lock | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index 56bb047..a826a1c 100644 --- a/mix.exs +++ b/mix.exs @@ -99,7 +99,9 @@ defmodule ErrorTracker.MixProject do {:ex_doc, "~> 0.33", only: :dev}, {:phoenix_live_reload, ">= 0.0.0", only: :dev}, {:plug_cowboy, ">= 0.0.0", only: :dev}, - {:tailwind, "~> 0.2", only: :dev} + {:tailwind, "~> 0.2", only: :dev}, + # Optional dependencies + {:igniter, "~> 0.5", optional: true} ] end diff --git a/mix.lock b/mix.lock index b65cc5f..e8dfa60 100644 --- a/mix.lock +++ b/mix.lock @@ -17,13 +17,22 @@ "ex_doc": {:hex, :ex_doc, "0.37.3", "f7816881a443cd77872b7d6118e8a55f547f49903aef8747dbcb345a75b462f9", [:mix], [{:earmark_parser, "~> 1.4.42", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "e6aebca7156e7c29b5da4daa17f6361205b2ae5f26e5c7d8ca0d3f7e18972233"}, "exqlite": {:hex, :exqlite, "0.23.0", "6e851c937a033299d0784994c66da24845415072adbc455a337e20087bce9033", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "404341cceec5e6466aaed160cf0b58be2019b60af82588c215e1224ebd3ec831"}, "file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"}, + "finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"}, + "glob_ex": {:hex, :glob_ex, "0.1.11", "cb50d3f1ef53f6ca04d6252c7fde09fd7a1cf63387714fe96f340a1349e62c93", [:mix], [], "hexpm", "342729363056e3145e61766b416769984c329e4378f1d558b63e341020525de4"}, + "hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"}, + "igniter": {:hex, :igniter, "0.5.43", "92dcc3e58f7cc78bacc0e560516020e14d5f01b3ac3761e32816e1e8d101eea7", [:mix], [{:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:inflex, "~> 2.0", [hex: :inflex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:owl, "~> 0.11", [hex: :owl, repo: "hexpm", optional: false]}, {:phx_new, "~> 1.7", [hex: :phx_new, repo: "hexpm", optional: true]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:rewrite, ">= 1.1.1 and < 2.0.0-0", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "d206f9699b4e94d133abaeadbd18a2b2a89bcb3456facb2e1f4d79cd03327bdc"}, + "inflex": {:hex, :inflex, "2.1.0", "a365cf0821a9dacb65067abd95008ca1b0bb7dcdd85ae59965deef2aa062924c", [:mix], [], "hexpm", "14c17d05db4ee9b6d319b0bff1bdf22aa389a25398d1952c7a0b5f3d93162dd8"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"}, "makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"}, "makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"}, "mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"}, + "mint": {:hex, :mint, "1.7.1", "113fdb2b2f3b59e47c7955971854641c61f378549d73e829e1768de90fc1abf1", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "fceba0a4d0f24301ddee3024ae116df1c3f4bb7a563a731f45fdfeb9d39a231b"}, "myxql": {:hex, :myxql, "0.6.4", "1502ea37ee23c31b79725b95d4cc3553693c2bda7421b1febc50722fd988c918", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:geo, "~> 3.4", [hex: :geo, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "a3307f4671f3009d3708283649adf205bfe280f7e036fc8ef7f16dbf821ab8e9"}, + "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, + "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, + "owl": {:hex, :owl, "0.12.2", "65906b525e5c3ef51bab6cba7687152be017aebe1da077bb719a5ee9f7e60762", [:mix], [{:ucwidth, "~> 0.2", [hex: :ucwidth, repo: "hexpm", optional: true]}], "hexpm", "6398efa9e1fea70a04d24231e10dcd66c1ac1aa2da418d20ef5357ec61de2880"}, "phoenix": {:hex, :phoenix, "1.7.12", "1cc589e0eab99f593a8aa38ec45f15d25297dd6187ee801c8de8947090b5a9d3", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "d646192fbade9f485b01bc9920c139bfdd19d0f8df3d73fd8eaf2dfbe0d2837c"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.2", "3b83b24ab5a2eb071a20372f740d7118767c272db386831b2e77638c4dcc606d", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "3f94d025f59de86be00f5f8c5dd7b5965a3298458d21ab1c328488be3b5fcd59"}, "phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"}, @@ -36,8 +45,13 @@ "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"}, "postgrex": {:hex, :postgrex, "0.18.0", "f34664101eaca11ff24481ed4c378492fed2ff416cd9b06c399e90f321867d7e", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "a042989ba1bc1cca7383ebb9e461398e3f89f868c92ce6671feb7ef132a252d1"}, "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, + "req": {:hex, :req, "0.5.1", "90584216d064389a4ff2d4279fe2c11ff6c812ab00fa01a9fb9d15457f65ba70", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "7ea96a1a95388eb0fefa92d89466cdfedba24032794e5c1147d78ec90db7edca"}, + "rewrite": {:hex, :rewrite, "1.1.2", "f5a5d10f5fed1491a6ff48e078d4585882695962ccc9e6c779bae025d1f92eda", [:mix], [{:glob_ex, "~> 0.1", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.0", [hex: :sourceror, repo: "hexpm", optional: false]}, {:text_diff, "~> 0.1", [hex: :text_diff, repo: "hexpm", optional: false]}], "hexpm", "7f8b94b1e3528d0a47b3e8b7bfeca559d2948a65fa7418a9ad7d7712703d39d4"}, + "sourceror": {:hex, :sourceror, "1.8.2", "f486ddded3b884175583413b431178b691b42d3e616f1ee80bed15503c5f7fd7", [:mix], [], "hexpm", "3f3126d50c222e1029c31861165e73e9c89ebcd543d2896192e2c1d792688fef"}, + "spitfire": {:hex, :spitfire, "0.2.0", "0de1f519a23f65bde40d316adad53c07a9563f25cc68915d639d8a509a0aad8a", [:mix], [], "hexpm", "743daaee2d81a0d8095431729f478ce49b47ea8943c7d770de86704975cb7775"}, "tailwind": {:hex, :tailwind, "0.2.2", "9e27288b568ede1d88517e8c61259bc214a12d7eed271e102db4c93fcca9b2cd", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "ccfb5025179ea307f7f899d1bb3905cd0ac9f687ed77feebc8f67bdca78565c4"}, "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, + "text_diff": {:hex, :text_diff, "0.1.0", "1caf3175e11a53a9a139bc9339bd607c47b9e376b073d4571c031913317fecaa", [:mix], [], "hexpm", "d1ffaaecab338e49357b6daa82e435f877e0649041ace7755583a0ea3362dbd7"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.6", "0437fe56e093fd4ac422de33bf8fc89f7bc1416a3f2d732d8b2c8fd54792fe60", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "e04378d26b0af627817ae84c92083b7e97aca3121196679b73c73b99d0d133ea"}, } From 4f3230400bd4d0bcfd444475c60c0b9ba7ff7f7f Mon Sep 17 00:00:00 2001 From: crbelaus Date: Sat, 5 Apr 2025 17:35:10 +0200 Subject: [PATCH 2/7] Create error_tracker.install task --- lib/mix/tasks/error_tracker.install.ex | 124 +++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 lib/mix/tasks/error_tracker.install.ex diff --git a/lib/mix/tasks/error_tracker.install.ex b/lib/mix/tasks/error_tracker.install.ex new file mode 100644 index 0000000..40de254 --- /dev/null +++ b/lib/mix/tasks/error_tracker.install.ex @@ -0,0 +1,124 @@ +defmodule Mix.Tasks.ErrorTracker.Install.Docs do + @moduledoc false + + def short_doc do + "Install and configure ErrorTracker for use in this application." + end + + def example do + "mix error_tracker.install" + end + + def long_doc do + """ + #{short_doc()} + + ## Example + + ```bash + #{example()} + ``` + """ + end +end + +if Code.ensure_loaded?(Igniter) do + defmodule Mix.Tasks.ErrorTracker.Install do + @shortdoc "#{__MODULE__.Docs.short_doc()}" + + @moduledoc __MODULE__.Docs.long_doc() + + use Igniter.Mix.Task + + @impl Igniter.Mix.Task + def info(_argv, _composing_task) do + %Igniter.Mix.Task.Info{ + # Groups allow for overlapping arguments for tasks by the same author + # See the generators guide for more. + group: :error_tracker, + # *other* dependencies to add + # i.e `{:foo, "~> 2.0"}` + adds_deps: [], + # *other* dependencies to add and call their associated installers, if they exist + # i.e `{:foo, "~> 2.0"}` + installs: [], + # An example invocation + example: __MODULE__.Docs.example(), + # A list of environments that this should be installed in. + only: nil, + # a list of positional arguments, i.e `[:file]` + positional: [], + # Other tasks your task composes using `Igniter.compose_task`, passing in the CLI argv + # This ensures your option schema includes options from nested tasks + composes: [], + # `OptionParser` schema + schema: [], + # Default values for the options in the `schema` + defaults: [], + # CLI aliases + aliases: [], + # A list of options in the schema that are required + required: [] + } + end + + @impl Igniter.Mix.Task + def igniter(igniter) do + app_name = Igniter.Project.Application.app_name(igniter) + repo_module = Igniter.Project.Module.module_name(igniter, "Repo") + web_module = Igniter.Libs.Phoenix.web_module(igniter) + + igniter + |> configure(app_name, repo_module) + |> set_up_database(repo_module) + |> set_up_web_ui(web_module) + end + + defp configure(igniter, app_name, repo_module) do + igniter + |> Igniter.Project.Config.configure("config.exs", :error_tracker, [:repo], repo_module) + |> Igniter.Project.Config.configure("config.exs", :error_tracker, [:otp_app], app_name) + |> Igniter.Project.Config.configure("config.exs", :error_tracker, [:enabled], true) + end + + defp set_up_database(igniter, repo_module) do + migration_body = """ + def up, do: ErrorTracker.Migration.up() + def down, do: ErrorTracker.Migration.down(version: 1) + """ + + Igniter.Libs.Ecto.gen_migration(igniter, repo_module, "add_error_tracker", + body: migration_body, + on_exists: :skip + ) + end + + defp set_up_web_ui(igniter, web_module) do + content = + """ + # TODO: This path should be protected from unauthorized user access + error_tracker_dashboard "/errors" + """ + + Igniter.Libs.Phoenix.append_to_scope(igniter, "/", content, arg2: web_module) + end + end +else + defmodule Mix.Tasks.ErrorTracker.Install do + @shortdoc "#{__MODULE__.Docs.short_doc()} | Install `igniter` to use" + + @moduledoc __MODULE__.Docs.long_doc() + + use Mix.Task + + def run(_argv) do + Mix.shell().error(""" + The task 'error_tracker.install' requires igniter. Please install igniter and try again. + + For more information, see: https://hexdocs.pm/igniter/readme.html#installation + """) + + exit({:shutdown, 1}) + end + end +end From e9a6b83728b3f0809099acb51e59188422386747 Mon Sep 17 00:00:00 2001 From: crbelaus Date: Sun, 6 Apr 2025 12:06:56 +0200 Subject: [PATCH 3/7] Keep existing config if present --- lib/mix/tasks/error_tracker.install.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/mix/tasks/error_tracker.install.ex b/lib/mix/tasks/error_tracker.install.ex index 40de254..93d8415 100644 --- a/lib/mix/tasks/error_tracker.install.ex +++ b/lib/mix/tasks/error_tracker.install.ex @@ -76,9 +76,9 @@ if Code.ensure_loaded?(Igniter) do defp configure(igniter, app_name, repo_module) do igniter - |> Igniter.Project.Config.configure("config.exs", :error_tracker, [:repo], repo_module) - |> Igniter.Project.Config.configure("config.exs", :error_tracker, [:otp_app], app_name) - |> Igniter.Project.Config.configure("config.exs", :error_tracker, [:enabled], true) + |> Igniter.Project.Config.configure_new("config.exs", :error_tracker, [:repo], repo_module) + |> Igniter.Project.Config.configure_new("config.exs", :error_tracker, [:otp_app], app_name) + |> Igniter.Project.Config.configure_new("config.exs", :error_tracker, [:enabled], true) end defp set_up_database(igniter, repo_module) do From 61dcdeec56d34b50d251c0ef2d35b3fa450899e0 Mon Sep 17 00:00:00 2001 From: crbelaus Date: Sun, 6 Apr 2025 12:17:02 +0200 Subject: [PATCH 4/7] Mount dashboard in /dev scope --- lib/mix/tasks/error_tracker.install.ex | 42 ++++++++++++++++++++------ 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/lib/mix/tasks/error_tracker.install.ex b/lib/mix/tasks/error_tracker.install.ex index 93d8415..d944dcb 100644 --- a/lib/mix/tasks/error_tracker.install.ex +++ b/lib/mix/tasks/error_tracker.install.ex @@ -66,12 +66,12 @@ if Code.ensure_loaded?(Igniter) do def igniter(igniter) do app_name = Igniter.Project.Application.app_name(igniter) repo_module = Igniter.Project.Module.module_name(igniter, "Repo") - web_module = Igniter.Libs.Phoenix.web_module(igniter) + {igniter, router} = Igniter.Libs.Phoenix.select_router(igniter) igniter |> configure(app_name, repo_module) |> set_up_database(repo_module) - |> set_up_web_ui(web_module) + |> set_up_web_ui(app_name, router) end defp configure(igniter, app_name, repo_module) do @@ -93,14 +93,36 @@ if Code.ensure_loaded?(Igniter) do ) end - defp set_up_web_ui(igniter, web_module) do - content = - """ - # TODO: This path should be protected from unauthorized user access - error_tracker_dashboard "/errors" - """ - - Igniter.Libs.Phoenix.append_to_scope(igniter, "/", content, arg2: web_module) + defp set_up_web_ui(igniter, app_name, router) do + if router do + Igniter.Project.Module.find_and_update_module!(igniter, router, fn zipper -> + zipper = + Igniter.Code.Common.add_code( + zipper, + """ + if Application.compile_env(#{inspect(app_name)}, :dev_routes) do + use ErrorTracker.Web, :router + + scope "/dev" do + pipe_through :browser + + error_tracker_dashboard "/errors" + end + end + """, + placement: :after + ) + + {:ok, zipper} + end) + else + Igniter.add_warning(igniter, """ + No Phoenix router found or selected. Please ensure that Phoenix is set up + and then run this installer again with + + mix igniter.install error_tracker + """) + end end end else From f5ef77ce8980099ef610d92c517945c0e18c4fd4 Mon Sep 17 00:00:00 2001 From: crbelaus Date: Sun, 6 Apr 2025 14:06:06 +0200 Subject: [PATCH 5/7] Improve Ecto repo detection --- lib/mix/tasks/error_tracker.install.ex | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/mix/tasks/error_tracker.install.ex b/lib/mix/tasks/error_tracker.install.ex index d944dcb..ddf37c4 100644 --- a/lib/mix/tasks/error_tracker.install.ex +++ b/lib/mix/tasks/error_tracker.install.ex @@ -65,29 +65,29 @@ if Code.ensure_loaded?(Igniter) do @impl Igniter.Mix.Task def igniter(igniter) do app_name = Igniter.Project.Application.app_name(igniter) - repo_module = Igniter.Project.Module.module_name(igniter, "Repo") + {igniter, repo} = Igniter.Libs.Ecto.select_repo(igniter) {igniter, router} = Igniter.Libs.Phoenix.select_router(igniter) igniter - |> configure(app_name, repo_module) - |> set_up_database(repo_module) + |> configure(app_name, repo) + |> set_up_database(repo) |> set_up_web_ui(app_name, router) end - defp configure(igniter, app_name, repo_module) do + defp configure(igniter, app_name, repo) do igniter - |> Igniter.Project.Config.configure_new("config.exs", :error_tracker, [:repo], repo_module) + |> Igniter.Project.Config.configure_new("config.exs", :error_tracker, [:repo], repo) |> Igniter.Project.Config.configure_new("config.exs", :error_tracker, [:otp_app], app_name) |> Igniter.Project.Config.configure_new("config.exs", :error_tracker, [:enabled], true) end - defp set_up_database(igniter, repo_module) do + defp set_up_database(igniter, repo) do migration_body = """ def up, do: ErrorTracker.Migration.up() def down, do: ErrorTracker.Migration.down(version: 1) """ - Igniter.Libs.Ecto.gen_migration(igniter, repo_module, "add_error_tracker", + Igniter.Libs.Ecto.gen_migration(igniter, repo, "add_error_tracker", body: migration_body, on_exists: :skip ) From 046f288798317f6151a4b09607c10993b7929fc1 Mon Sep 17 00:00:00 2001 From: crbelaus Date: Sun, 6 Apr 2025 14:07:51 +0200 Subject: [PATCH 6/7] Update formatter --- lib/mix/tasks/error_tracker.install.ex | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/mix/tasks/error_tracker.install.ex b/lib/mix/tasks/error_tracker.install.ex index ddf37c4..0c1361f 100644 --- a/lib/mix/tasks/error_tracker.install.ex +++ b/lib/mix/tasks/error_tracker.install.ex @@ -69,18 +69,23 @@ if Code.ensure_loaded?(Igniter) do {igniter, router} = Igniter.Libs.Phoenix.select_router(igniter) igniter - |> configure(app_name, repo) + |> set_up_configuration(app_name, repo) + |> set_up_formatter() |> set_up_database(repo) |> set_up_web_ui(app_name, router) end - defp configure(igniter, app_name, repo) do + defp set_up_configuration(igniter, app_name, repo) do igniter |> Igniter.Project.Config.configure_new("config.exs", :error_tracker, [:repo], repo) |> Igniter.Project.Config.configure_new("config.exs", :error_tracker, [:otp_app], app_name) |> Igniter.Project.Config.configure_new("config.exs", :error_tracker, [:enabled], true) end + defp set_up_formatter(igniter) do + Igniter.Project.Formatter.import_dep(igniter, :error_tracker) + end + defp set_up_database(igniter, repo) do migration_body = """ def up, do: ErrorTracker.Migration.up() From 6cbaa850c703bd45f64f655d988cf3104f7ce52f Mon Sep 17 00:00:00 2001 From: crbelaus Date: Sun, 4 May 2025 11:30:05 +0200 Subject: [PATCH 7/7] Update Getting Started guide --- guides/Getting Started.md | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/guides/Getting Started.md b/guides/Getting Started.md index d94c3bc..bc0146e 100644 --- a/guides/Getting Started.md +++ b/guides/Getting Started.md @@ -6,7 +6,35 @@ In this guide we will learn how to install ErrorTracker in an Elixir project so **This guide requires you to have set up Ecto with PostgreSQL, MySQL/MariaDB or SQLite3 beforehand.** -## Installing ErrorTracker as a dependency +## Automatic installation using Igniter + +The ErrorTracker includes an [igniter](https://hex.pm/packages/igniter) installer that will add the latest version of ErrorTracker to your dependencies before running the installer. Installation will use the application's default Ecto repo and Phoenix router, configure ErrorTracker and create the necessary database migrations. It will basically automate all the installation steps listed in the [manual installation](#manual-installation) section. + +### If Igniter is already available + +ErrorTracker may be installed and configured with a single command: + +```bash +mix igniter.install error_tracker +``` + +### If Igniter is not yet available + +If the `igniter.install` escript is not available. First, add `error_tracker` and `igniter` to your deps in `mix.exs`: + +```elixir +{:error_tracker, "~> 0.6"}, +{:igniter, "~> 0.5", only: [:dev]}, +``` + +Run `mix deps.get` to fetch the dependencies, then run the install task: + +```bash +mix error_tracker.install +``` + + +## Manual Installation The first step to add ErrorTracker to your application is to declare the package as a dependency in your `mix.exs` file: @@ -25,7 +53,7 @@ Once ErrorTracker is declared as a dependency of your application, you can insta mix deps.get ``` -## Configuring ErrorTracker +### Configuring ErrorTracker ErrorTracker needs a few configuration options to work. This configuration should be added to your `config/config.exs` file: @@ -42,7 +70,7 @@ The `:otp_app` option specifies your application name. When an error occurs, Err The `:enabled` option (defaults to `true` if not present) allows to disable the ErrorTracker on certain environments. This is useful to avoid filling your dev database with errors, for example. -## Setting up the database +### Setting up the database Since ErrorTracker stores errors in the database you must create a database migration to add the required tables: