Skip to content

Commit 1615c6e

Browse files
authored
Igniter installer (#149)
This pull request adds a `mix error_tracker.install` task that installs the error tracker using [Igniter]. This task automates the installation and configuration steps detailed in the [Getting Started] guide by: 1. Adding ErrorTracker as a dependency 2. Updating `config.exs` to configure the ErrorTracker application 3. Create a new DB migration to set up the ErrorTracker tables 4. Update the `router.ex` file to mount the ErrorTracker dashboard <details> <summary>Here is the output <code>mix igniter.install error_tracker</code> in a project named <code>wadus</code></summary> ``` Updating project's igniter dependency ✔ checking for igniter in project ✔ compiling igniter ✔ setting up igniter ✔ Update: mix.exs ...| 34 34 | defp deps do 35 35 | [ 36 + | {:error_tracker, [path: "/Users/crbelaus/Developer/error-tracker", override: true]}, 36 37 | {:igniter, "~> 0.5", only: [:dev, :test]}, 37 38 | {:phoenix, "~> 1.7.21"}, ...| These dependencies should be installed before continuing. Modify mix.exs and install? [Y/n] Y compiling error_tracker ✔ `error_tracker.install` ✔ The following installer was found and executed: `error_tracker.install`: Update: config/config.exs ...| 8 8 |import Config 9 9 | 10 + |config :error_tracker, repo: Wadus.Repo, otp_app: :wadus, enabled: true 11 + | 10 12 |config :wadus, 11 13 | ecto_repos: [Wadus.Repo], ...| Update: lib/wadus_web/router.ex ...| 19 19 | 20 20 | get "/", PageController, :home 21 + | # TODO: This path should be protected from unauthorized user access 22 + | error_tracker_dashboard("/errors") 21 23 | end 22 24 | ...| Create: priv/repo/migrations/20250405160735_add_error_tracker.exs 1 |defmodule Wadus.Repo.Migrations.AddErrorTracker do 2 | use Ecto.Migration 3 | 4 | def up, do: ErrorTracker.Migration.up() 5 | def down, do: ErrorTracker.Migration.down(version: 1) 6 |end 7 | Proceed with changes? [Y/n] Y Successfully installed: * error_tracker ``` </details> This task can be used in two ways: 1. If you already have an existing Phoenix project run `mix igniter.install error_tracker`\ Take a look at the [mix igniter.install] docs 3. If you are creating a new Phoenix project run `mix igniter.new app_name --install error_tracker --with phx.new`\ Take a look at the [mix igniter.new] docs [Igniter]: https://hexdocs.pm/igniter/Igniter.html [Getting Started]: https://github.com/elixir-error-tracker/error-tracker/blob/main/guides/Getting%20Started.md [mix igniter.install]: https://hexdocs.pm/igniter_new/Mix.Tasks.Igniter.Install.html [mix igniter.new]: https://hexdocs.pm/igniter_new/Mix.Tasks.Igniter.New.html
1 parent 99c3fb2 commit 1615c6e

File tree

4 files changed

+199
-4
lines changed

4 files changed

+199
-4
lines changed

guides/Getting Started.md

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,35 @@ In this guide we will learn how to install ErrorTracker in an Elixir project so
66

77
**This guide requires you to have set up Ecto with PostgreSQL, MySQL/MariaDB or SQLite3 beforehand.**
88

9-
## Installing ErrorTracker as a dependency
9+
## Automatic installation using Igniter
10+
11+
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.
12+
13+
### If Igniter is already available
14+
15+
ErrorTracker may be installed and configured with a single command:
16+
17+
```bash
18+
mix igniter.install error_tracker
19+
```
20+
21+
### If Igniter is not yet available
22+
23+
If the `igniter.install` escript is not available. First, add `error_tracker` and `igniter` to your deps in `mix.exs`:
24+
25+
```elixir
26+
{:error_tracker, "~> 0.6"},
27+
{:igniter, "~> 0.5", only: [:dev]},
28+
```
29+
30+
Run `mix deps.get` to fetch the dependencies, then run the install task:
31+
32+
```bash
33+
mix error_tracker.install
34+
```
35+
36+
37+
## Manual Installation
1038

1139
The first step to add ErrorTracker to your application is to declare the package as a dependency in your `mix.exs` file:
1240

@@ -25,7 +53,7 @@ Once ErrorTracker is declared as a dependency of your application, you can insta
2553
mix deps.get
2654
```
2755

28-
## Configuring ErrorTracker
56+
### Configuring ErrorTracker
2957

3058
ErrorTracker needs a few configuration options to work. This configuration should be added to your `config/config.exs` file:
3159

@@ -42,7 +70,7 @@ The `:otp_app` option specifies your application name. When an error occurs, Err
4270

4371
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.
4472

45-
## Setting up the database
73+
### Setting up the database
4674

4775
Since ErrorTracker stores errors in the database you must create a database migration to add the required tables:
4876

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
defmodule Mix.Tasks.ErrorTracker.Install.Docs do
2+
@moduledoc false
3+
4+
def short_doc do
5+
"Install and configure ErrorTracker for use in this application."
6+
end
7+
8+
def example do
9+
"mix error_tracker.install"
10+
end
11+
12+
def long_doc do
13+
"""
14+
#{short_doc()}
15+
16+
## Example
17+
18+
```bash
19+
#{example()}
20+
```
21+
"""
22+
end
23+
end
24+
25+
if Code.ensure_loaded?(Igniter) do
26+
defmodule Mix.Tasks.ErrorTracker.Install do
27+
@shortdoc "#{__MODULE__.Docs.short_doc()}"
28+
29+
@moduledoc __MODULE__.Docs.long_doc()
30+
31+
use Igniter.Mix.Task
32+
33+
@impl Igniter.Mix.Task
34+
def info(_argv, _composing_task) do
35+
%Igniter.Mix.Task.Info{
36+
# Groups allow for overlapping arguments for tasks by the same author
37+
# See the generators guide for more.
38+
group: :error_tracker,
39+
# *other* dependencies to add
40+
# i.e `{:foo, "~> 2.0"}`
41+
adds_deps: [],
42+
# *other* dependencies to add and call their associated installers, if they exist
43+
# i.e `{:foo, "~> 2.0"}`
44+
installs: [],
45+
# An example invocation
46+
example: __MODULE__.Docs.example(),
47+
# A list of environments that this should be installed in.
48+
only: nil,
49+
# a list of positional arguments, i.e `[:file]`
50+
positional: [],
51+
# Other tasks your task composes using `Igniter.compose_task`, passing in the CLI argv
52+
# This ensures your option schema includes options from nested tasks
53+
composes: [],
54+
# `OptionParser` schema
55+
schema: [],
56+
# Default values for the options in the `schema`
57+
defaults: [],
58+
# CLI aliases
59+
aliases: [],
60+
# A list of options in the schema that are required
61+
required: []
62+
}
63+
end
64+
65+
@impl Igniter.Mix.Task
66+
def igniter(igniter) do
67+
app_name = Igniter.Project.Application.app_name(igniter)
68+
{igniter, repo} = Igniter.Libs.Ecto.select_repo(igniter)
69+
{igniter, router} = Igniter.Libs.Phoenix.select_router(igniter)
70+
71+
igniter
72+
|> set_up_configuration(app_name, repo)
73+
|> set_up_formatter()
74+
|> set_up_database(repo)
75+
|> set_up_web_ui(app_name, router)
76+
end
77+
78+
defp set_up_configuration(igniter, app_name, repo) do
79+
igniter
80+
|> Igniter.Project.Config.configure_new("config.exs", :error_tracker, [:repo], repo)
81+
|> Igniter.Project.Config.configure_new("config.exs", :error_tracker, [:otp_app], app_name)
82+
|> Igniter.Project.Config.configure_new("config.exs", :error_tracker, [:enabled], true)
83+
end
84+
85+
defp set_up_formatter(igniter) do
86+
Igniter.Project.Formatter.import_dep(igniter, :error_tracker)
87+
end
88+
89+
defp set_up_database(igniter, repo) do
90+
migration_body = """
91+
def up, do: ErrorTracker.Migration.up()
92+
def down, do: ErrorTracker.Migration.down(version: 1)
93+
"""
94+
95+
Igniter.Libs.Ecto.gen_migration(igniter, repo, "add_error_tracker",
96+
body: migration_body,
97+
on_exists: :skip
98+
)
99+
end
100+
101+
defp set_up_web_ui(igniter, app_name, router) do
102+
if router do
103+
Igniter.Project.Module.find_and_update_module!(igniter, router, fn zipper ->
104+
zipper =
105+
Igniter.Code.Common.add_code(
106+
zipper,
107+
"""
108+
if Application.compile_env(#{inspect(app_name)}, :dev_routes) do
109+
use ErrorTracker.Web, :router
110+
111+
scope "/dev" do
112+
pipe_through :browser
113+
114+
error_tracker_dashboard "/errors"
115+
end
116+
end
117+
""",
118+
placement: :after
119+
)
120+
121+
{:ok, zipper}
122+
end)
123+
else
124+
Igniter.add_warning(igniter, """
125+
No Phoenix router found or selected. Please ensure that Phoenix is set up
126+
and then run this installer again with
127+
128+
mix igniter.install error_tracker
129+
""")
130+
end
131+
end
132+
end
133+
else
134+
defmodule Mix.Tasks.ErrorTracker.Install do
135+
@shortdoc "#{__MODULE__.Docs.short_doc()} | Install `igniter` to use"
136+
137+
@moduledoc __MODULE__.Docs.long_doc()
138+
139+
use Mix.Task
140+
141+
def run(_argv) do
142+
Mix.shell().error("""
143+
The task 'error_tracker.install' requires igniter. Please install igniter and try again.
144+
145+
For more information, see: https://hexdocs.pm/igniter/readme.html#installation
146+
""")
147+
148+
exit({:shutdown, 1})
149+
end
150+
end
151+
end

mix.exs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ defmodule ErrorTracker.MixProject do
9999
{:ex_doc, "~> 0.33", only: :dev},
100100
{:phoenix_live_reload, ">= 0.0.0", only: :dev},
101101
{:plug_cowboy, ">= 0.0.0", only: :dev},
102-
{:tailwind, "~> 0.2", only: :dev}
102+
{:tailwind, "~> 0.2", only: :dev},
103+
# Optional dependencies
104+
{:igniter, "~> 0.5", optional: true}
103105
]
104106
end
105107

mix.lock

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,22 @@
1717
"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"},
1818
"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"},
1919
"file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"},
20+
"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"},
21+
"glob_ex": {:hex, :glob_ex, "0.1.11", "cb50d3f1ef53f6ca04d6252c7fde09fd7a1cf63387714fe96f340a1349e62c93", [:mix], [], "hexpm", "342729363056e3145e61766b416769984c329e4378f1d558b63e341020525de4"},
22+
"hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"},
23+
"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"},
24+
"inflex": {:hex, :inflex, "2.1.0", "a365cf0821a9dacb65067abd95008ca1b0bb7dcdd85ae59965deef2aa062924c", [:mix], [], "hexpm", "14c17d05db4ee9b6d319b0bff1bdf22aa389a25398d1952c7a0b5f3d93162dd8"},
2025
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
2126
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
2227
"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"},
2328
"makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"},
2429
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
30+
"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"},
2531
"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"},
32+
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
2633
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
34+
"nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"},
35+
"owl": {:hex, :owl, "0.12.2", "65906b525e5c3ef51bab6cba7687152be017aebe1da077bb719a5ee9f7e60762", [:mix], [{:ucwidth, "~> 0.2", [hex: :ucwidth, repo: "hexpm", optional: true]}], "hexpm", "6398efa9e1fea70a04d24231e10dcd66c1ac1aa2da418d20ef5357ec61de2880"},
2736
"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"},
2837
"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"},
2938
"phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"},
@@ -36,8 +45,13 @@
3645
"plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
3746
"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"},
3847
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
48+
"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"},
49+
"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"},
50+
"sourceror": {:hex, :sourceror, "1.8.2", "f486ddded3b884175583413b431178b691b42d3e616f1ee80bed15503c5f7fd7", [:mix], [], "hexpm", "3f3126d50c222e1029c31861165e73e9c89ebcd543d2896192e2c1d792688fef"},
51+
"spitfire": {:hex, :spitfire, "0.2.0", "0de1f519a23f65bde40d316adad53c07a9563f25cc68915d639d8a509a0aad8a", [:mix], [], "hexpm", "743daaee2d81a0d8095431729f478ce49b47ea8943c7d770de86704975cb7775"},
3952
"tailwind": {:hex, :tailwind, "0.2.2", "9e27288b568ede1d88517e8c61259bc214a12d7eed271e102db4c93fcca9b2cd", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "ccfb5025179ea307f7f899d1bb3905cd0ac9f687ed77feebc8f67bdca78565c4"},
4053
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
54+
"text_diff": {:hex, :text_diff, "0.1.0", "1caf3175e11a53a9a139bc9339bd607c47b9e376b073d4571c031913317fecaa", [:mix], [], "hexpm", "d1ffaaecab338e49357b6daa82e435f877e0649041ace7755583a0ea3362dbd7"},
4155
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
4256
"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"},
4357
}

0 commit comments

Comments
 (0)