diff --git a/.credo.exs b/.credo.exs index b02a03d5050b..381ca5ae2f43 100644 --- a/.credo.exs +++ b/.credo.exs @@ -119,16 +119,15 @@ {Credo.Check.Refactor.CyclomaticComplexity, false}, {Credo.Check.Refactor.FilterCount, []}, {Credo.Check.Refactor.FilterFilter, []}, - {Credo.Check.Refactor.MatchInCondition, []}, + {Credo.Check.Refactor.MatchInCondition, [allow_operators: true]}, {Credo.Check.Refactor.RedundantWithClauseResult, []}, {Credo.Check.Refactor.RejectReject, []}, {Credo.Check.Refactor.FunctionArity, []}, {Credo.Check.Refactor.LongQuoteBlocks, []}, - {Credo.Check.Refactor.MatchInCondition, []}, {Credo.Check.Refactor.MapJoin, []}, {Credo.Check.Refactor.NegatedConditionsInUnless, []}, {Credo.Check.Refactor.NegatedConditionsWithElse, false}, - {Credo.Check.Refactor.Nesting, []}, + {Credo.Check.Refactor.Nesting, [max_nesting: 3]}, {Credo.Check.Refactor.UnlessWithElse, []}, {Credo.Check.Refactor.WithClauses, []}, {Credo.Check.Refactor.FilterFilter, []}, diff --git a/.dialyzer_ignore.exs b/.dialyzer_ignore.exs new file mode 100644 index 000000000000..b1a8b46e39eb --- /dev/null +++ b/.dialyzer_ignore.exs @@ -0,0 +1,6 @@ +[ + {"lib/plausible/goals/goals.ex", :call_without_opaque}, + {"lib/plausible/sites.ex", :call_without_opaque}, + {"lib/plausible/teams/invitations.ex", :call_without_opaque}, + {"lib/plausible_web/live/components/modal.ex", :pattern_match, 1} +] diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml index 2ebb5fe0185a..067f63419946 100644 --- a/.github/workflows/elixir.yml +++ b/.github/workflows/elixir.yml @@ -11,7 +11,7 @@ concurrency: cancel-in-progress: true env: - CACHE_VERSION: v17 + CACHE_VERSION: v18 PERSISTENT_CACHE_DIR: cached jobs: diff --git a/.tool-versions b/.tool-versions index d1ef1f421bca..b9393f6f8a57 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ -erlang 27.3.4.6 -elixir 1.19.4-otp-27 +erlang 28.5.0.3 +elixir 1.20.2-otp-28 nodejs 23.2.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 58fd7d5a89d4..a580d8ca5e74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to this project will be documented in this file. ### Removed - Removed the standalone team switcher page; team switching is now done from the topbar dropdown only +- Removed `Bamboo.SMTPAdapter` from supported e-mail adapters; the library is no longer in active developments and does not compile under Elixir 1.20+ ### Changed diff --git a/Dockerfile b/Dockerfile index df6a1f42d16b..3a90f786d0d1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,9 @@ # we can not use the pre-built tar because the distribution is # platform specific, it makes sense to build it in the docker -ARG ALPINE_VERSION=3.22.2 #### Builder -FROM hexpm/elixir:1.19.4-erlang-27.3.4.6-alpine-${ALPINE_VERSION} AS buildcontainer +FROM hexpm/elixir:1.20.2-erlang-28.5.0.3-alpine-3.22.5@sha256:8875407828c1b789485f9fcc6006e1ace39bb073b0467a95df3a3905d8d86d30 AS buildcontainer ARG MIX_ENV=ce @@ -55,7 +54,7 @@ COPY rel rel RUN mix release plausible # Main Docker Image -FROM alpine:${ALPINE_VERSION} +FROM alpine:3.22.5@sha256:14358309a308569c32bdc37e2e0e9694be33a9d99e68afb0f5ff33cc1f695dce LABEL maintainer="plausible.io " ARG BUILD_METADATA={} diff --git a/config/runtime.exs b/config/runtime.exs index 3d3194df891d..b4b7195ed18c 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -742,20 +742,6 @@ case mailer_adapter do hackney_opts: [recv_timeout: :timer.seconds(10)], api_key: get_var_from_path_or_env(config_dir, "SENDGRID_API_KEY") - "Bamboo.SMTPAdapter" -> - config :plausible, Plausible.Mailer, - adapter: Bamboo.SMTPAdapter, - server: get_var_from_path_or_env(config_dir, "SMTP_HOST_ADDR", "mail"), - hostname: base_url.host, - port: get_var_from_path_or_env(config_dir, "SMTP_HOST_PORT", "25"), - username: get_var_from_path_or_env(config_dir, "SMTP_USER_NAME"), - password: get_var_from_path_or_env(config_dir, "SMTP_USER_PWD"), - tls: :if_available, - allowed_tls_versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"], - ssl: get_bool_from_path_or_env(config_dir, "SMTP_HOST_SSL_ENABLED", false), - retries: get_var_from_path_or_env(config_dir, "SMTP_RETRIES") || 2, - no_mx_lookups: get_bool_from_path_or_env(config_dir, "SMTP_MX_LOOKUPS_ENABLED", true) - "Bamboo.Mua" -> config :plausible, Plausible.Mailer, adapter: Bamboo.Mua diff --git a/extra/lib/license.ex b/extra/lib/license.ex index 7685914d5704..74b04405e898 100644 --- a/extra/lib/license.ex +++ b/extra/lib/license.ex @@ -10,9 +10,9 @@ defmodule Plausible.License do at hello@plausible.io to discuss obtaining a license. """ - require Logger - if Mix.env() == :prod do + require Logger + def ensure_valid_license do if has_valid_license?() do :ok diff --git a/extra/lib/plausible/audit/encoder.ex b/extra/lib/plausible/audit/encoder.ex index 7b8b1ceb1008..39cc17baedfd 100644 --- a/extra/lib/plausible/audit/encoder.ex +++ b/extra/lib/plausible/audit/encoder.ex @@ -3,11 +3,13 @@ defmodule Plausible.Audit.EncoderError do end defprotocol Plausible.Audit.Encoder do - def encode(x, opts \\ []) + def encode(x) + + def encode(x, opts) end defimpl Plausible.Audit.Encoder, for: Ecto.Changeset do - def encode(changeset, opts) do + def encode(changeset, opts \\ []) do changes = Enum.reduce(changeset.changes, %{}, fn {k, v}, acc -> Map.put(acc, k, Plausible.Audit.Encoder.encode(v, opts)) @@ -32,7 +34,7 @@ defimpl Plausible.Audit.Encoder, for: Ecto.Changeset do end defimpl Plausible.Audit.Encoder, for: Map do - def encode(x, opts) do + def encode(x, opts \\ []) do {allow_not_loaded, data} = Map.pop(x, :__allow_not_loaded__) raise_on_not_loaded? = Keyword.get(opts, :raise_on_not_loaded?, true) @@ -53,14 +55,16 @@ defimpl Plausible.Audit.Encoder, for: Map do end defimpl Plausible.Audit.Encoder, for: [Integer, BitString, Float] do - def encode(x, _opts), do: x + def encode(x, _opts \\ []), do: x end defimpl Plausible.Audit.Encoder, for: [DateTime, Date, NaiveDateTime, Time] do - def encode(x, _opts), do: to_string(x) + def encode(x, _opts \\ []), do: to_string(x) end defimpl Plausible.Audit.Encoder, for: Atom do + def encode(x, opts \\ []) + def encode(nil, _opts), do: nil def encode(true, _opts), do: true def encode(false, _opts), do: false @@ -68,7 +72,7 @@ defimpl Plausible.Audit.Encoder, for: Atom do end defimpl Plausible.Audit.Encoder, for: List do - def encode(x, opts) do + def encode(x, opts \\ []) do Enum.map(x, &Plausible.Audit.Encoder.encode(&1, opts)) end end @@ -116,12 +120,13 @@ defimpl Plausible.Audit.Encoder, for: Any do quote do defimpl Plausible.Audit.Encoder, for: unquote(module) do - def encode(struct, opts) do + def encode(struct, opts \\ []) do Plausible.Audit.Encoder.encode(unquote(extractor), opts) end end end end + def encode(_), do: raise("Implement me") def encode(_, _), do: raise("Implement me") end diff --git a/extra/lib/plausible/auth/sso/domain/verification.ex b/extra/lib/plausible/auth/sso/domain/verification.ex index 77b64102d6fa..329fec425d9e 100644 --- a/extra/lib/plausible/auth/sso/domain/verification.ex +++ b/extra/lib/plausible/auth/sso/domain/verification.ex @@ -19,7 +19,6 @@ defmodule Plausible.Auth.SSO.Domain.Verification do """ alias Plausible.Auth.SSO.Domain - require Domain @prefix "plausible-sso-verification" diff --git a/extra/lib/plausible/installation_support/detection/diagnostics.ex b/extra/lib/plausible/installation_support/detection/diagnostics.ex index 4e4b40527057..21b2701335fc 100644 --- a/extra/lib/plausible/installation_support/detection/diagnostics.ex +++ b/extra/lib/plausible/installation_support/detection/diagnostics.ex @@ -2,7 +2,6 @@ defmodule Plausible.InstallationSupport.Detection.Diagnostics do @moduledoc """ Module responsible for translating diagnostics to user-friendly errors and recommendations. """ - require Logger # in this struct, nil means indeterminate defstruct v1_detected: nil, diff --git a/extra/lib/plausible/installation_support/verification/diagnostics.ex b/extra/lib/plausible/installation_support/verification/diagnostics.ex index afe06b4012bd..0773c07550f8 100644 --- a/extra/lib/plausible/installation_support/verification/diagnostics.ex +++ b/extra/lib/plausible/installation_support/verification/diagnostics.ex @@ -2,7 +2,6 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do @moduledoc """ Module responsible for translating diagnostics to user-friendly errors and recommendations. """ - require Logger # In this struct # - the default nil value for each field means that the value is indeterminate (e.g. we didn't even get to the part where response_status is set) diff --git a/extra/lib/plausible_web/live/customer_support/team/components/billing.ex b/extra/lib/plausible_web/live/customer_support/team/components/billing.ex index e4e7a4c88c7d..3a482b9d5953 100644 --- a/extra/lib/plausible_web/live/customer_support/team/components/billing.ex +++ b/extra/lib/plausible_web/live/customer_support/team/components/billing.ex @@ -11,8 +11,6 @@ defmodule PlausibleWeb.CustomerSupport.Team.Components.Billing do import Ecto.Query, only: [from: 2] import PlausibleWeb.Components.Generic - require Plausible.Billing.Subscription.Status - def update(%{team: team}, socket) do usage = Teams.Billing.quota_usage(team, with_features: true) diff --git a/lib/mix/tasks/create_free_subscription.ex b/lib/mix/tasks/create_free_subscription.ex index 785463c7ef4a..9f2fc53b20e1 100644 --- a/lib/mix/tasks/create_free_subscription.ex +++ b/lib/mix/tasks/create_free_subscription.ex @@ -1,7 +1,9 @@ defmodule Mix.Tasks.CreateFreeSubscription do + @moduledoc false + use Mix.Task use Plausible.Repo - require Logger + alias Plausible.Billing.Subscription # coveralls-ignore-start diff --git a/lib/mix/tasks/generate_referrer_favicons.ex b/lib/mix/tasks/generate_referrer_favicons.ex index 93ba338137c1..08fe38d3e9d6 100644 --- a/lib/mix/tasks/generate_referrer_favicons.ex +++ b/lib/mix/tasks/generate_referrer_favicons.ex @@ -1,7 +1,8 @@ defmodule Mix.Tasks.GenerateReferrerFavicons do + @moduledoc false + use Mix.Task use Plausible.Repo - require Logger @dialyzer {:nowarn_function, run: 1} # coveralls-ignore-start diff --git a/lib/mix/tasks/send_pageview.ex b/lib/mix/tasks/send_pageview.ex index 0ab839ff0011..686a2991aff0 100644 --- a/lib/mix/tasks/send_pageview.ex +++ b/lib/mix/tasks/send_pageview.ex @@ -7,7 +7,6 @@ defmodule Mix.Tasks.SendPageview do """ use Mix.Task - require Logger @default_host "http://localhost:8000" @default_ip_address "127.0.0.1" diff --git a/lib/plausible.ex b/lib/plausible.ex index 39b39aa66aca..1c529debad76 100644 --- a/lib/plausible.ex +++ b/lib/plausible.ex @@ -26,7 +26,13 @@ defmodule Plausible do defmacro always(term) do quote do - :erlang.phash2(1, 1) == 0 && unquote(term) + case :erlang.phash2(1, 1) do + 0 -> + unquote(term) + + 1 -> + not unquote(term) + end end end diff --git a/lib/plausible/application.ex b/lib/plausible/application.ex index be485d3af971..20191fc70189 100644 --- a/lib/plausible/application.ex +++ b/lib/plausible/application.ex @@ -4,8 +4,6 @@ defmodule Plausible.Application do use Application use Plausible - require Logger - def start(_type, _args) do on_ee(do: Plausible.License.ensure_valid_license()) on_ce(do: :inet_db.set_tcp_module(:happy_tcp)) @@ -360,7 +358,7 @@ defmodule Plausible.Application do end def setup_sentry() do - Logger.add_backend(Sentry.LoggerBackend) + LoggerBackends.add(Sentry.LoggerBackend) :telemetry.attach_many( "oban-errors", diff --git a/lib/plausible/billing/billing.ex b/lib/plausible/billing/billing.ex index 16fb1a045e0c..a6599160c22d 100644 --- a/lib/plausible/billing/billing.ex +++ b/lib/plausible/billing/billing.ex @@ -6,7 +6,7 @@ defmodule Plausible.Billing do """ use Plausible use Plausible.Repo - require Plausible.Billing.Subscription.Status + alias Plausible.Auth alias Plausible.Billing.Subscription alias Plausible.Teams diff --git a/lib/plausible/data_migration/populate_event_session_columns.ex b/lib/plausible/data_migration/populate_event_session_columns.ex index fdf04fa1f496..02ffc79045a2 100644 --- a/lib/plausible/data_migration/populate_event_session_columns.ex +++ b/lib/plausible/data_migration/populate_event_session_columns.ex @@ -12,8 +12,6 @@ defmodule Plausible.DataMigration.PopulateEventSessionColumns do """ use Plausible.DataMigration, dir: "PopulateEventSessionColumns", repo: Plausible.IngestRepo - require Logger - # See https://clickhouse.com/docs/en/sql-reference/dictionaries#cache for meaning of these defaults @default_dictionary_config %{ lifetime: 600_000, diff --git a/lib/plausible/ecto/types/compiled_regex.ex b/lib/plausible/ecto/types/compiled_regex.ex index 3728a1194283..e748ad6abc78 100644 --- a/lib/plausible/ecto/types/compiled_regex.ex +++ b/lib/plausible/ecto/types/compiled_regex.ex @@ -9,6 +9,6 @@ defmodule Plausible.Ecto.Types.CompiledRegex do def cast(val) when is_binary(val), do: {:ok, val} def cast(_), do: :error - def load(val), do: {:ok, Regex.compile!(val)} + def load(val), do: {:ok, Regex.compile!(val, "E")} def dump(val), do: {:ok, val} end diff --git a/lib/plausible/exports.ex b/lib/plausible/exports.ex index 77d770593045..86734aed19c7 100644 --- a/lib/plausible/exports.ex +++ b/lib/plausible/exports.ex @@ -167,7 +167,7 @@ defmodule Plausible.Exports do {:error, {:http_error, 404, _response}} -> nil - {:error, %Mint.TransportError{} = e} -> + {:error, %Finch.TransportError{} = e} -> raise e end end diff --git a/lib/plausible/google/api.ex b/lib/plausible/google/api.ex index 60945d295769..8dde546d031f 100644 --- a/lib/plausible/google/api.ex +++ b/lib/plausible/google/api.ex @@ -7,8 +7,6 @@ defmodule Plausible.Google.API do alias Plausible.Google.SearchConsole alias Plausible.Stats.Query - require Logger - @search_console_scope URI.encode_www_form( "email https://www.googleapis.com/auth/webmasters.readonly" ) diff --git a/lib/plausible/http_client.ex b/lib/plausible/http_client.ex index f79bb5106f5d..f6c17efa6ad7 100644 --- a/lib/plausible/http_client.ex +++ b/lib/plausible/http_client.ex @@ -1,4 +1,6 @@ defmodule Plausible.HTTPClient.Non200Error do + @moduledoc false + defstruct reason: nil @type t :: %__MODULE__{reason: Finch.Response.t()} @@ -11,13 +13,17 @@ defmodule Plausible.HTTPClient.Non200Error do end defmodule Plausible.HTTPClient.Interface do + @moduledoc false + + @type t() :: module() + @type finch_request_opts() :: Keyword.t() @type url() :: Finch.Request.url() @type headers() :: Finch.Request.headers() @type params() :: Finch.Request.body() | map() @type response() :: {:ok, Finch.Response.t()} - | {:error, Mint.Types.error() | Finch.Error.t() | Plausible.HTTPClient.Non200Error.t()} + | {:error, Finch.error() | Plausible.HTTPClient.Non200Error.t()} @callback get(url(), headers(), params()) :: response() @callback get(url(), headers()) :: response() @@ -58,9 +64,7 @@ defmodule Plausible.HTTPClient do call(:get, url, headers, params) end - # TODO: Is it possible to tell the type checker that we're returning a module that conforms to the - # Plausible.HTTPClient.Interface behaviour? - @spec impl() :: Plausible.HTTPClient + @spec impl() :: Plausible.HTTPClient.Interface.t() def impl() do Application.get_env(:plausible, :http_impl, __MODULE__) end diff --git a/lib/plausible/ingestion/counters.ex b/lib/plausible/ingestion/counters.ex index 2799fe5491bd..818f86937a3f 100644 --- a/lib/plausible/ingestion/counters.ex +++ b/lib/plausible/ingestion/counters.ex @@ -20,8 +20,6 @@ defmodule Plausible.Ingestion.Counters do @behaviour :gen_cycle - require Logger - alias Plausible.Ingestion.Counters.Buffer alias Plausible.Ingestion.Counters.Record alias Plausible.Ingestion.Counters.TelemetryHandler diff --git a/lib/plausible/ingestion/persistor/embedded.ex b/lib/plausible/ingestion/persistor/embedded.ex index fadbc1d5b82c..b11c471ada7f 100644 --- a/lib/plausible/ingestion/persistor/embedded.ex +++ b/lib/plausible/ingestion/persistor/embedded.ex @@ -5,8 +5,6 @@ defmodule Plausible.Ingestion.Persistor.Embedded do alias Plausible.ClickhouseEventV2 - require Logger - def persist_event(ingest_event, previous_user_id, opts) do event = ingest_event.clickhouse_event session_attrs = ingest_event.clickhouse_session_attrs diff --git a/lib/plausible/open_telemetry.ex b/lib/plausible/open_telemetry.ex index 24b11bc1b6fb..1112b785e8c3 100644 --- a/lib/plausible/open_telemetry.ex +++ b/lib/plausible/open_telemetry.ex @@ -1,10 +1,10 @@ defmodule Plausible.OpenTelemetry do @moduledoc false - require OpenTelemetry.Tracer, as: Tracer + alias OpenTelemetry.Tracer def current_trace_id do - case OpenTelemetry.Tracer.current_span_ctx() do + case Tracer.current_span_ctx() do :undefined -> nil diff --git a/lib/plausible/open_telemetry/logger.ex b/lib/plausible/open_telemetry/logger.ex index c44fcd558af7..1511887bbae2 100644 --- a/lib/plausible/open_telemetry/logger.ex +++ b/lib/plausible/open_telemetry/logger.ex @@ -7,8 +7,6 @@ defmodule Plausible.OpenTelemetry.Logger do to the Logger metadata when Phoenix router dispatch starts. """ - require Logger - @doc """ Attaches telemetry handlers to set trace_id in Logger metadata. diff --git a/lib/plausible/session/cache_store.ex b/lib/plausible/session/cache_store.ex index d7f6f3de65f9..05b3998e06ce 100644 --- a/lib/plausible/session/cache_store.ex +++ b/lib/plausible/session/cache_store.ex @@ -1,5 +1,8 @@ defmodule Plausible.Session.CacheStore do - require Logger + @moduledoc """ + Session management on the basis of incoming events. + """ + alias Plausible.Session.WriteBuffer @lock_timeout 1000 diff --git a/lib/plausible/site/gate_keeper.ex b/lib/plausible/site/gate_keeper.ex index 8e0634950472..67f79d2790bc 100644 --- a/lib/plausible/site/gate_keeper.ex +++ b/lib/plausible/site/gate_keeper.ex @@ -27,8 +27,6 @@ defmodule Plausible.Site.GateKeeper do alias Plausible.{Site, RateLimit} alias Plausible.Site.Cache - require Logger - @spec check(String.t(), Keyword.t()) :: t() def check(domain, opts \\ []) when is_binary(domain) do case policy(domain, opts) do diff --git a/lib/plausible/stats/query.ex b/lib/plausible/stats/query.ex index cf4fdfffed63..5330b7bd0c7a 100644 --- a/lib/plausible/stats/query.ex +++ b/lib/plausible/stats/query.ex @@ -32,7 +32,7 @@ defmodule Plausible.Stats.Query do sql_join_type: :left, smear_session_metrics: false - require OpenTelemetry.Tracer, as: Tracer + alias OpenTelemetry.Tracer alias Plausible.Stats.{ DateTimeRange, diff --git a/lib/plausible/stats/sparkline.ex b/lib/plausible/stats/sparkline.ex index 3eb0752214cf..b3527230e97e 100644 --- a/lib/plausible/stats/sparkline.ex +++ b/lib/plausible/stats/sparkline.ex @@ -6,7 +6,6 @@ defmodule Plausible.Stats.Sparkline do alias Plausible.{Site, Stats} alias Plausible.Stats.QueryBuilder - require Logger @spec parallel_overview([Site.t()], NaiveDateTime.t()) :: map() def parallel_overview(sites, now \\ NaiveDateTime.utc_now()) when is_list(sites) do diff --git a/lib/plausible/teams/billing.ex b/lib/plausible/teams/billing.ex index da06e0eaa464..0e815f0d7de6 100644 --- a/lib/plausible/teams/billing.ex +++ b/lib/plausible/teams/billing.ex @@ -251,7 +251,7 @@ defmodule Plausible.Teams.Billing do else def team_member_limit(_team), do: :unlimited - def solo?(_team), do: false + def solo?(_team), do: always(false) end @doc """ @@ -316,11 +316,9 @@ defmodule Plausible.Teams.Billing do @monthly_pageview_limit_for_free_10k _any -> - if subscription do - Sentry.capture_message("Unknown monthly pageview limit for plan", - extra: %{paddle_plan_id: subscription.paddle_plan_id} - ) - end + Sentry.capture_message("Unknown monthly pageview limit for plan", + extra: %{paddle_plan_id: subscription.paddle_plan_id} + ) @monthly_pageview_limit_for_trials end diff --git a/lib/plausible/teams/invitations.ex b/lib/plausible/teams/invitations.ex index 1cac3517f4b9..cb849b53266b 100644 --- a/lib/plausible/teams/invitations.ex +++ b/lib/plausible/teams/invitations.ex @@ -543,7 +543,11 @@ defmodule Plausible.Teams.Invitations do end else def ensure_can_take_ownership(_site, _team, _opts) do - always(:ok) + if always(true) do + :ok + else + {:error, :no_plan} + end end end diff --git a/lib/plausible_release.ex b/lib/plausible_release.ex index 14c9f91089be..4dc21555519c 100644 --- a/lib/plausible_release.ex +++ b/lib/plausible_release.ex @@ -1,7 +1,11 @@ defmodule Plausible.Release do + @moduledoc """ + Utility functions used by release scripts for routine tasks, + like migrations. + """ + use Plausible use Plausible.Repo - require Logger @app :plausible @start_apps [ @@ -257,7 +261,7 @@ defmodule Plausible.Release do end defp run_rollbacks_for(repo, step) do - app = Keyword.get(repo.config, :otp_app) + app = Keyword.get(repo.config(), :otp_app) IO.puts("Running rollbacks for #{app} (STEP=#{step})") {:ok, _, _} = @@ -281,7 +285,7 @@ defmodule Plausible.Release do defp seeds_path(repo), do: priv_path_for(repo, "seeds.exs") defp priv_path_for(repo, filename) do - app = Keyword.get(repo.config, :otp_app) + app = Keyword.get(repo.config(), :otp_app) IO.puts("App: #{app}") repo_underscore = repo |> Module.split() |> List.last() |> Macro.underscore() Path.join([priv_dir(app), repo_underscore, filename]) diff --git a/lib/plausible_web.ex b/lib/plausible_web.ex index a79614f03844..67ba7b156589 100644 --- a/lib/plausible_web.ex +++ b/lib/plausible_web.ex @@ -1,4 +1,6 @@ defmodule PlausibleWeb do + @moduledoc false + use Plausible def live_view(opts \\ []) do @@ -63,7 +65,7 @@ defmodule PlausibleWeb do # Import convenience functions from controllers import Phoenix.Controller, only: [view_module: 1] - use Phoenix.Component + use Phoenix.Component, global_prefixes: ~w(x-) import PlausibleWeb.Components.Generic import PlausibleWeb.Live.Components.Form diff --git a/lib/plausible_web/controllers/google_analytics_controller.ex b/lib/plausible_web/controllers/google_analytics_controller.ex index 32c9a6ae883d..7d85452cc007 100644 --- a/lib/plausible_web/controllers/google_analytics_controller.ex +++ b/lib/plausible_web/controllers/google_analytics_controller.ex @@ -5,8 +5,6 @@ defmodule PlausibleWeb.GoogleAnalyticsController do alias Plausible.Imported use Plausible - require Plausible.Imported.SiteImport - plug(PlausibleWeb.RequireAccountPlug) plug(PlausibleWeb.Plugs.AuthorizeSiteAccess, [:owner, :editor, :admin, :super_admin]) diff --git a/lib/plausible_web/live/choose_plan.ex b/lib/plausible_web/live/choose_plan.ex index 3e78a5bd5fd6..8559a139c0cf 100644 --- a/lib/plausible_web/live/choose_plan.ex +++ b/lib/plausible_web/live/choose_plan.ex @@ -4,8 +4,6 @@ defmodule PlausibleWeb.Live.ChoosePlan do """ use PlausibleWeb, :live_view - require Plausible.Billing.Subscription.Status - alias PlausibleWeb.Components.Billing.{PlanBox, Notice, PageviewSlider} alias Plausible.Billing.{Plans, Quota, PlanBenefits} alias PlausibleWeb.Router.Helpers, as: Routes diff --git a/lib/plausible_web/live/components/modal.ex b/lib/plausible_web/live/components/modal.ex index 51f473183be6..c1480bbb8066 100644 --- a/lib/plausible_web/live/components/modal.ex +++ b/lib/plausible_web/live/components/modal.ex @@ -136,7 +136,7 @@ defmodule PlausibleWeb.Live.Components.Modal do # NOTE: This is a workaround for @test_preload_override? being computed # at build time, where Mix.env() is available. Otherwise, dialyzer # complains. - preload_override? = :erlang.phash2(1, 1) == 0 and @test_preload_override? + preload_override? = @test_preload_override? and :erlang.phash2(1, 1) == 0 preload? = preload_override? || Map.get(assigns, :preload?, true) socket = diff --git a/lib/plausible_web/live/csv_import.ex b/lib/plausible_web/live/csv_import.ex index 96a566e8dc34..1dfc899a4d70 100644 --- a/lib/plausible_web/live/csv_import.ex +++ b/lib/plausible_web/live/csv_import.ex @@ -5,7 +5,6 @@ defmodule PlausibleWeb.Live.CSVImport do use PlausibleWeb, :live_view - require Plausible.Imported.SiteImport alias Plausible.Imported.CSVImporter alias Plausible.Imported diff --git a/lib/plausible_web/live/goal_settings.ex b/lib/plausible_web/live/goal_settings.ex index 3ac88bd2ab87..457502db67d6 100644 --- a/lib/plausible_web/live/goal_settings.ex +++ b/lib/plausible_web/live/goal_settings.ex @@ -78,12 +78,14 @@ defmodule PlausibleWeb.Live.GoalSettings do

Define actions that you want your users to take, like visiting a certain page, submitting a form, etc.

-

- You can also - <.styled_link href={Routes.site_path(@socket, :settings_funnels, @domain)}> - compose goals into funnels. - -

+ <%= on_ee do %> +

+ You can also + <.styled_link href={Routes.site_path(@socket, :settings_funnels, @domain)}> + compose goals into funnels. + +

+ <% end %> <.live_component :let={modal_unique_id} module={Modal} preload?={false} id="goals-form-modal"> <.live_component diff --git a/lib/plausible_web/live/installation.ex b/lib/plausible_web/live/installation.ex index e54e5d4aac0c..4e865013b9ff 100644 --- a/lib/plausible_web/live/installation.ex +++ b/lib/plausible_web/live/installation.ex @@ -6,8 +6,6 @@ defmodule PlausibleWeb.Live.Installation do use Plausible use PlausibleWeb, :live_view - require Logger - alias PlausibleWeb.Flows alias Phoenix.LiveView.AsyncResult alias PlausibleWeb.Live.Installation.Icons diff --git a/lib/plausible_web/live/sites.ex b/lib/plausible_web/live/sites.ex index 0b86591b42a5..11217bd370a1 100644 --- a/lib/plausible_web/live/sites.ex +++ b/lib/plausible_web/live/sites.ex @@ -6,7 +6,6 @@ defmodule PlausibleWeb.Live.Sites do use PlausibleWeb, :live_view import PlausibleWeb.Live.Components.Pagination import PlausibleWeb.StatsView, only: [large_number_format: 1] - require Logger alias Plausible.Sites alias Plausible.Sites.Index diff --git a/lib/plausible_web/live/subscription_settings.ex b/lib/plausible_web/live/subscription_settings.ex index 4b5aa5155eee..ea3ada30a69c 100644 --- a/lib/plausible_web/live/subscription_settings.ex +++ b/lib/plausible_web/live/subscription_settings.ex @@ -121,8 +121,7 @@ defmodule PlausibleWeb.Live.SubscriptionSettings do
<.button_link :if={ - @subscription && - Plausible.Billing.Subscriptions.resumable?(@subscription) && + Plausible.Billing.Subscriptions.resumable?(@subscription) && @subscription.update_url } theme="secondary" diff --git a/lib/plausible_web/user_auth.ex b/lib/plausible_web/user_auth.ex index 48c782efbc58..2b9a7b69c7db 100644 --- a/lib/plausible_web/user_auth.ex +++ b/lib/plausible_web/user_auth.ex @@ -10,8 +10,6 @@ defmodule PlausibleWeb.UserAuth do alias PlausibleWeb.Router.Helpers, as: Routes - require Logger - on_ee do @type login_subject() :: Auth.User.t() | Auth.SSO.Identity.t() else diff --git a/lib/plausible_web/views/settings_view.ex b/lib/plausible_web/views/settings_view.ex index e4e217de465e..f1a07ed0d071 100644 --- a/lib/plausible_web/views/settings_view.ex +++ b/lib/plausible_web/views/settings_view.ex @@ -1,5 +1,4 @@ defmodule PlausibleWeb.SettingsView do use PlausibleWeb, :view - use Phoenix.Component, global_prefixes: ~w(x-) use Plausible end diff --git a/lib/sentry_filter.ex b/lib/sentry_filter.ex index 4e496d8ec733..77edbf59e6ac 100644 --- a/lib/sentry_filter.ex +++ b/lib/sentry_filter.ex @@ -25,7 +25,7 @@ defmodule Plausible.SentryFilter do def before_send( %{ - exception: [%{type: "Mint.TransportError"}], + exception: [%{type: "Finch.TransportError"}], original_exception: %{reason: reason} } = event ) do @@ -35,7 +35,7 @@ defmodule Plausible.SentryFilter do def before_send( %{source: :logger, message: %{formatted: "Ch.Connection (#PID<" <> rest}} = event ) do - if String.ends_with?(rest, ")) disconnected: ** (Mint.HTTPError) the connection is closed") do + if String.ends_with?(rest, ")) disconnected: ** (Finch.HTTPError) the connection is closed") do false else event diff --git a/lib/workers/import_analytics.ex b/lib/workers/import_analytics.ex index a5f0c5e67790..6bcc0ec6e3dc 100644 --- a/lib/workers/import_analytics.ex +++ b/lib/workers/import_analytics.ex @@ -4,7 +4,6 @@ defmodule Plausible.Workers.ImportAnalytics do """ use Plausible.Repo - require Logger use Oban.Worker, queue: :analytics_imports, diff --git a/lib/workers/schedule_email_reports.ex b/lib/workers/schedule_email_reports.ex index f338072fb4e4..82dbf063deac 100644 --- a/lib/workers/schedule_email_reports.ex +++ b/lib/workers/schedule_email_reports.ex @@ -1,8 +1,10 @@ defmodule Plausible.Workers.ScheduleEmailReports do + @moduledoc """ + Job scheduling dispatch of weekly and monthly email reports. + """ use Plausible.Repo use Oban.Worker, queue: :schedule_email_reports alias Plausible.Workers.SendEmailReport - require Logger @impl Oban.Worker @doc """ diff --git a/lib/workers/send_site_setup_emails.ex b/lib/workers/send_site_setup_emails.ex index 68dfc20c5e94..c3eef54666ba 100644 --- a/lib/workers/send_site_setup_emails.ex +++ b/lib/workers/send_site_setup_emails.ex @@ -1,7 +1,10 @@ defmodule Plausible.Workers.SendSiteSetupEmails do + @moduledoc """ + Job sending site setup emails. + """ + use Plausible.Repo use Oban.Worker, queue: :site_setup_emails - require Logger @impl Oban.Worker def perform(_job) do diff --git a/lib/workers/send_trial_notifications.ex b/lib/workers/send_trial_notifications.ex index be0c57d0bb48..8269f749dedf 100644 --- a/lib/workers/send_trial_notifications.ex +++ b/lib/workers/send_trial_notifications.ex @@ -1,4 +1,7 @@ defmodule Plausible.Workers.SendTrialNotifications do + @moduledoc """ + Job sending trial end notification emails. + """ use Plausible.Repo use Oban.Worker, @@ -7,8 +10,6 @@ defmodule Plausible.Workers.SendTrialNotifications do alias Plausible.Teams - require Logger - @impl Oban.Worker def perform(_job) do teams = @@ -22,30 +23,23 @@ defmodule Plausible.Workers.SendTrialNotifications do order_by: t.inserted_at, preload: [owners: o, billing_members: bm] ) + |> Enum.filter(&Teams.has_active_sites?/1) for team <- teams do recipients = team.owners ++ team.billing_members case Date.diff(team.trial_expiry_date, Date.utc_today()) do 7 -> - if Teams.has_active_sites?(team) do - send_one_week_reminder(recipients, team) - end + send_one_week_reminder(recipients, team) 1 -> - if Teams.has_active_sites?(team) do - send_tomorrow_reminder(recipients, team) - end + send_tomorrow_reminder(recipients, team) 0 -> - if Teams.has_active_sites?(team) do - send_today_reminder(recipients, team) - end + send_today_reminder(recipients, team) -1 -> - if Teams.has_active_sites?(team) do - send_over_reminder(recipients, team) - end + send_over_reminder(recipients, team) _ -> nil diff --git a/mix.exs b/mix.exs index a6cd3f0b0f16..052f80b29441 100644 --- a/mix.exs +++ b/mix.exs @@ -75,7 +75,6 @@ defmodule Plausible.MixProject do [ {:bamboo, "~> 2.3", override: true}, {:bamboo_postmark, git: "https://github.com/plausible/bamboo_postmark.git", branch: "main"}, - {:bamboo_smtp, "~> 4.1"}, {:bamboo_mua, "~> 0.2.0"}, {:bcrypt_elixir, "~> 3.3"}, {:bypass, "~> 2.1", only: [:dev, :test, :ce_test, :e2e_test]}, @@ -93,7 +92,7 @@ defmodule Plausible.MixProject do {:eqrcode, "~> 0.2.1"}, {:ex_machina, "~> 2.3", only: [:dev, :test, :ce_dev, :ce_test, :e2e_test]}, {:excoveralls, "~> 0.10", only: :test}, - {:finch, "~> 0.20.0"}, + {:finch, "~> 0.23"}, {:lazy_html, "~> 0.1.8"}, {:fun_with_flags, "~> 1.13.0"}, {:fun_with_flags_ui, "~> 1.0"}, @@ -138,7 +137,7 @@ defmodule Plausible.MixProject do {:prima, "~> 0.2.6"}, {:plug_cowboy, "~> 2.3"}, {:polymorphic_embed, "~> 5.0"}, - {:postgrex, "~> 0.21.1"}, + {:postgrex, "~> 0.22.2"}, {:prom_ex, "~> 1.8"}, {:peep, "~> 3.0"}, {:public_suffix, git: "https://github.com/axelson/publicsuffix-elixir"}, @@ -152,7 +151,7 @@ defmodule Plausible.MixProject do {:timex, "~> 3.7"}, {:ua_inspector, "~> 3.12"}, {:ex_doc, "~> 0.28", only: :dev, runtime: false}, - {:ex_money, "~> 5.12"}, + {:ex_money, "~> 5.24.2"}, {:mjml_eex, "~> 0.12.0"}, {:mjml, "~> 4.0.0"}, {:heroicons, "~> 0.5.0"}, @@ -170,7 +169,7 @@ defmodule Plausible.MixProject do {:zstream, "~> 0.6.4"}, {:con_cache, git: "https://github.com/aerosol/con_cache", branch: "ensure-dirty-ops-emit-telemetry"}, - {:req, "~> 0.5.16"}, + {:req, "~> 0.6"}, {:opentelemetry_req, "~> 1.0"}, {:happy_tcp, github: "ruslandoga/happy_tcp", only: [:ce, :ce_dev, :ce_test, :e2e_test]}, {:ex_json_schema, "~> 0.11.1"}, @@ -179,7 +178,8 @@ defmodule Plausible.MixProject do {:site_encrypt, github: "sasa1977/site_encrypt", only: [:ce, :ce_dev, :ce_test, :e2e_test]}, {:phoenix_html_helpers, "~> 1.0"}, {:libcluster, "~> 3.5"}, - {:decimal, "~> 3.0", override: true} + {:decimal, "~> 3.0", override: true}, + {:logger_backends, "~> 1.0.0"} ] end diff --git a/mix.lock b/mix.lock index 9a33e3e0aa99..1ec2693e1faf 100644 --- a/mix.lock +++ b/mix.lock @@ -4,16 +4,15 @@ "bamboo": {:hex, :bamboo, "2.5.0", "973f5cb1471a1d2d7d9da7b8e4f6096afb6a133f85394631184fd40be8adb8ab", [:mix], [{:hackney, ">= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.4 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "35c8635ff6677a81ab7258944ff15739280f3254a041b6f0229dddeb9b90ad3d"}, "bamboo_mua": {:hex, :bamboo_mua, "0.2.4", "1143cb64e0455bd496d4da14132308d1e44a825c2ba5e295c6c2adc33dff3af0", [:mix], [{:bamboo, "~> 2.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:mail, "~> 0.4.0", [hex: :mail, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: false]}], "hexpm", "6802c491f8585b047d7f75f0d57f44398b44d105614115a3346710c2de75cc1f"}, "bamboo_postmark": {:git, "https://github.com/plausible/bamboo_postmark.git", "c6a773d1b7a4e5c9ec802ace64b5bb526504c25a", [branch: "main"]}, - "bamboo_smtp": {:hex, :bamboo_smtp, "4.2.2", "e9f57a2300df9cb496c48751bd7668a86a2b89aa2e79ccaa34e0c46a5f64c3ae", [:mix], [{:bamboo, "~> 2.2.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:gen_smtp, "~> 1.2.0", [hex: :gen_smtp, repo: "hexpm", optional: false]}], "hexpm", "28cac2ec8adaae02aed663bf68163992891a3b44cfd7ada0bebe3e09bed7207f"}, "bcrypt_elixir": {:hex, :bcrypt_elixir, "3.3.2", "d50091e3c9492d73e17fc1e1619a9b09d6a5ef99160eb4d736926fd475a16ca3", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "471be5151874ae7931911057d1467d908955f93554f7a6cd1b7d804cac8cef53"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "bypass": {:hex, :bypass, "2.1.0", "909782781bf8e20ee86a9cabde36b259d44af8b9f38756173e8f5e2e1fabb9b1", [:mix], [{:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "d9b5df8fa5b7a6efa08384e9bbecfe4ce61c77d28a4282f79e02f1ef78d96b80"}, - "castore": {:hex, :castore, "1.0.17", "4f9770d2d45fbd91dcf6bd404cf64e7e58fed04fadda0923dc32acca0badffa2", [:mix], [], "hexpm", "12d24b9d80b910dd3953e165636d68f147a31db945d2dcb9365e441f8b5351e5"}, + "castore": {:hex, :castore, "1.0.19", "6903cabdfd9d1af46454126e7c8385186659dd33ecfb74a885cae52221ad6109", [:mix], [], "hexpm", "3669e6cab13f54c2df26b3e6833745d647f35b6e30d8ddd5975df0d5c842ca98"}, "cc_precompiler": {:hex, :cc_precompiler, "0.1.11", "8c844d0b9fb98a3edea067f94f616b3f6b29b959b6b3bf25fee94ffe34364768", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3427232caf0835f94680e5bcf082408a70b48ad68a5f5c0b02a3bea9f3a075b9"}, "certifi": {:hex, :certifi, "2.15.0", "0e6e882fcdaaa0a5a9f2b3db55b1394dba07e8d6d9bcad08318fb604c6839712", [:rebar3], [], "hexpm", "b147ed22ce71d72eafdad94f055165c1c182f61a2ff49df28bcc71d1d5b94a60"}, "ch": {:hex, :ch, "0.7.1", "116c08094b30d095c3bd6a8fe4ebe19fdaaf3dce84e2413cfdd6af157baf6303", [:mix], [{:db_connection, "~> 2.9.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.13.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "3c1c900291ff9c4c077cd1dc0c265051a3f1d26320d58b37ed9e91b33d41a868"}, "chatterbox": {:hex, :ts_chatterbox, "0.15.1", "5cac4d15dd7ad61fc3c4415ce4826fc563d4643dee897a558ec4ea0b1c835c9c", [:rebar3], [{:hpack, "~> 0.3.0", [hex: :hpack_erl, repo: "hexpm", optional: false]}], "hexpm", "4f75b91451338bc0da5f52f3480fa6ef6e3a2aeecfc33686d6b3d0a0948f31aa"}, - "cldr_utils": {:hex, :cldr_utils, "2.29.1", "11ff0a50a36a7e5f3bd9fc2fb8486a4c1bcca3081d9c080bf9e48fe0e6742e2d", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.5", [hex: :certifi, repo: "hexpm", optional: true]}, {:decimal, "~> 1.9 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "3844a0a0ed7f42e6590ddd8bd37eb4b1556b112898f67dea3ba068c29aabd6c2"}, + "cldr_utils": {:hex, :cldr_utils, "2.29.7", "2189bc0117efe91c684558e79174b45eb43135595b7d1fe9b57f53917be195c1", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.5", [hex: :certifi, repo: "hexpm", optional: true]}, {:decimal, "~> 1.9 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "4bddcd597fee34e2d2829ae9ef62bcfef8d97ae5f6b75f0c6ee37a3db31aa73a"}, "cloak": {:hex, :cloak, "1.1.4", "aba387b22ea4d80d92d38ab1890cc528b06e0e7ef2a4581d71c3fdad59e997e7", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "92b20527b9aba3d939fab0dd32ce592ff86361547cfdc87d74edce6f980eb3d7"}, "cloak_ecto": {:hex, :cloak_ecto, "1.3.0", "0de127c857d7452ba3c3367f53fb814b0410ff9c680a8d20fbe8b9a3c57a1118", [:mix], [{:cloak, "~> 1.1.1", [hex: :cloak, repo: "hexpm", optional: false]}, {:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}], "hexpm", "314beb0c123b8a800418ca1d51065b27ba3b15f085977e65c0f7b2adab2de1cc"}, "combination": {:hex, :combination, "0.0.3", "746aedca63d833293ec6e835aa1f34974868829b1486b1e1cb0685f0b2ae1f41", [:mix], [], "hexpm", "72b099f463df42ef7dc6371d250c7070b57b6c5902853f69deb894f79eda18ca"}, @@ -21,15 +20,15 @@ "comeonin": {:hex, :comeonin, "5.5.1", "5113e5f3800799787de08a6e0db307133850e635d34e9fab23c70b6501669510", [:mix], [], "hexpm", "65aac8f19938145377cee73973f192c5645873dcf550a8a6b18187d17c13ccdb"}, "con_cache": {:git, "https://github.com/aerosol/con_cache", "d050e133742e512cf2caa4598607e60dd0161072", [branch: "ensure-dirty-ops-emit-telemetry"]}, "cors_plug": {:hex, :cors_plug, "3.0.3", "7c3ac52b39624bc616db2e937c282f3f623f25f8d550068b6710e58d04a0e330", [:mix], [{:plug, "~> 1.13", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "3f2d759e8c272ed3835fab2ef11b46bddab8c1ab9528167bd463b6452edf830d"}, - "cowboy": {:hex, :cowboy, "2.14.2", "4008be1df6ade45e4f2a4e9e2d22b36d0b5aba4e20b0a0d7049e28d124e34847", [:make, :rebar3], [{:cowlib, ">= 2.16.0 and < 3.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, ">= 1.8.0 and < 3.0.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "569081da046e7b41b5df36aa359be71a0c8874e5b9cff6f747073fc57baf1ab9"}, + "cowboy": {:hex, :cowboy, "2.16.1", "fa04080b602ff25c40a7700f2dc0152dbc1ba26b42093ae0fa9bb7a337d5a242", [:make, :rebar3], [{:cowlib, ">= 2.16.0 and < 3.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, ">= 1.8.0 and < 3.0.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "b8ea4dd317a043e3177ec840cfa3bcb47cfb41035d3abb24d954dc7d51def399"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, - "cowlib": {:hex, :cowlib, "2.16.0", "54592074ebbbb92ee4746c8a8846e5605052f29309d3a873468d76cdf932076f", [:make, :rebar3], [], "hexpm", "7f478d80d66b747344f0ea7708c187645cfcc08b11aa424632f78e25bf05db51"}, - "credo": {:hex, :credo, "1.7.7", "771445037228f763f9b2afd612b6aa2fd8e28432a95dbbc60d8e03ce71ba4446", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8bc87496c9aaacdc3f90f01b7b0582467b69b4bd2441fe8aae3109d843cc2f2e"}, + "cowlib": {:hex, :cowlib, "2.18.0", "4a3ef8cb012c21c7cbb7c925f75405e26d7fcd393fd78c46187539dbc9a48310", [:make, :rebar3], [], "hexpm", "c4f89d33a61162d4cfdcb5a1af7e562d80a700b2573cc71020ce6521b152dc1a"}, + "credo": {:hex, :credo, "1.7.19", "cc52129665fc7c15143d47838fda0f9cd6dac9ceced7bf4da6f85fcbfe64b12a", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "2d8bc95d5a7bb99dd2613621d4f08c6a3575c3fd4b62e6a2b48a100352a557b8"}, "ctx": {:hex, :ctx, "0.6.0", "8ff88b70e6400c4df90142e7f130625b82086077a45364a78d208ed3ed53c7fe", [:rebar3], [], "hexpm", "a14ed2d1b67723dbebbe423b28d7615eb0bdcba6ff28f2d1f1b0a7e1d4aa5fc2"}, "db_connection": {:hex, :db_connection, "2.9.0", "a6a97c5c958a2d7091a58a9be40caf41ab496b0701d21e1d1abff3fa27a7f371", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "17d502eacaf61829db98facf6f20808ed33da6ccf495354a41e64fe42f9c509c"}, - "decimal": {:hex, :decimal, "3.1.0", "9ede268cff827e6f0c4fb1b34747c82630dce5d7b877dfb22ec8f0cb25855fce", [:mix], [], "hexpm", "e8b3efb3bb3a13cb5e4268ffe128569067b1972e9dee013537c71a5b073168f9"}, + "decimal": {:hex, :decimal, "3.1.1", "430d87b04011ce6cbd4fd205be758311a81f87d552d40904abd00f015935b1d0", [:mix], [], "hexpm", "c5f25f2ced74a0587d03e6023f595db8e924c9d3922c8c8ffd9edfc4498cf1f6"}, "dialyxir": {:hex, :dialyxir, "1.4.7", "dda948fcee52962e4b6c5b4b16b2d8fa7d50d8645bbae8b8685c3f9ecb7f5f4d", [:mix], [{:erlex, ">= 0.2.8", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b34527202e6eb8cee198efec110996c25c5898f43a4094df157f8d28f27d9efe"}, - "digital_token": {:hex, :digital_token, "1.0.0", "454a4444061943f7349a51ef74b7fb1ebd19e6a94f43ef711f7dae88c09347df", [:mix], [{:cldr_utils, "~> 2.17", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "8ed6f5a8c2fa7b07147b9963db506a1b4c7475d9afca6492136535b064c9e9e6"}, + "digital_token": {:hex, :digital_token, "2.0.0", "fb3c74411790994895c4a61387ab322b64a682995ef2f54a4627c92d46be5d62", [:mix], [], "hexpm", "cbd2fff52770284a8251540a4b4e529e9738c6fe052d7f3c3428eb5c817385cd"}, "double": {:hex, :double, "0.8.2", "8e1cfcccdaef76c18846bc08e555555a2a699b806fa207b6468572a60513cc6a", [:mix], [], "hexpm", "90287642b2ec86125e0457aaba2ab0e80f7d7050cc80a0cef733e59bd70aa67c"}, "earmark_parser": {:hex, :earmark_parser, "1.4.41", "ab34711c9dc6212dda44fcd20ecb87ac3f3fce6f0ca2f28d4a00e4154f8cd599", [:mix], [], "hexpm", "a81a04c7e34b6617c2792e291b5a2e57ab316365c2644ddc553bb9ed863ebefa"}, "ecto": {:hex, :ecto, "3.13.6", "352135b474f91d1ab99a1b502171d207e9db60421c9e3d0ecab4c7ab96b24d14", [:mix], [{:decimal, "~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "8afa059bc16cd2c94739ec0a11e3e5df69d828125119109bef35f20a21a76af2"}, @@ -43,23 +42,22 @@ "esbuild": {:hex, :esbuild, "0.10.0", "b0aa3388a1c23e727c5a3e7427c932d89ee791746b0081bbe56103e9ef3d291f", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "468489cda427b974a7cc9f03ace55368a83e1a7be12fba7e30969af78e5f8c70"}, "ex_aws": {:hex, :ex_aws, "2.5.1", "7418917974ea42e9e84b25e88b9f3d21a861d5f953ad453e212f48e593d8d39f", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8 or ~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:mime, "~> 1.2 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "1b95431f70c446fa1871f0eb9b183043c5a625f75f9948a42d25f43ae2eff12b"}, "ex_aws_s3": {:hex, :ex_aws_s3, "2.5.3", "422468e5c3e1a4da5298e66c3468b465cfd354b842e512cb1f6fbbe4e2f5bdaf", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "4f09dd372cc386550e484808c5ac5027766c8d0cd8271ccc578b82ee6ef4f3b8"}, - "ex_cldr": {:hex, :ex_cldr, "2.44.1", "0d220b175874e1ce77a0f7213bdfe700b9be11aefbf35933a0e98837803ebdc5", [:mix], [{:cldr_utils, "~> 2.28", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:gettext, "~> 0.19 or ~> 1.0", [hex: :gettext, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: true]}], "hexpm", "3880cd6137ea21c74250cd870d3330c4a9fdec07fabd5e37d1b239547929e29b"}, - "ex_cldr_currencies": {:hex, :ex_cldr_currencies, "2.16.5", "9b8065605bf0c77b6b07b8fd05d26f34f848b8f5ead2343837f0f4bbf3ac2f10", [:mix], [{:ex_cldr, "~> 2.38", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "4397179028f0a7389de278afd0239771f39ba8d1984ce072bc9b715fa28f30d3"}, - "ex_cldr_numbers": {:hex, :ex_cldr_numbers, "2.36.0", "d0de502db2fa24eeae16749af1af0093f24fb823e8715c66076cd8c6a3a960e3", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:digital_token, "~> 0.3 or ~> 1.0", [hex: :digital_token, repo: "hexpm", optional: false]}, {:ex_cldr, "~> 2.44", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_currencies, "~> 2.16", [hex: :ex_cldr_currencies, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "17640b8daf2580a0a11317a720a26079e774d4c36f939d82f4e9f7075269897d"}, + "ex_cldr": {:hex, :ex_cldr, "2.47.4", "64e1efda73d6c5fa0342d5b6554f39b740fa02ed540dc03997facf573101ad9e", [:mix], [{:cldr_utils, "~> 2.29", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:gettext, "~> 0.19 or ~> 1.0", [hex: :gettext, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: true]}], "hexpm", "918aabc032955f3eac70abbdf2c5469433132edfaaaccee55451f074ee1ccdba"}, + "ex_cldr_currencies": {:hex, :ex_cldr_currencies, "2.17.2", "4892b5255a205e8133297b702abbe13c9b51d0281fa8c2ea100f51df9657c3c7", [:mix], [{:ex_cldr, "~> 2.38", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "797095c106a2fe6632981531e29cfb1d2f8ee7de626f4d6243f974d6f74a0112"}, + "ex_cldr_numbers": {:hex, :ex_cldr_numbers, "2.38.3", "64a99531df09397174b7f477785c43016f223d01856725b541a19d36b8149523", [:mix], [{:decimal, "~> 1.6 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:digital_token, "~> 1.0 or ~> 2.0", [hex: :digital_token, repo: "hexpm", optional: false]}, {:ex_cldr, "~> 2.45", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_currencies, "~> 2.17", [hex: :ex_cldr_currencies, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "3a0d87ef2747c66d78ae8967023d415d3d76aa310981047ad601e3287e8fe73c"}, "ex_doc": {:hex, :ex_doc, "0.35.1", "de804c590d3df2d9d5b8aec77d758b00c814b356119b3d4455e4b8a8687aecaf", [:mix], [{:earmark_parser, "~> 1.4.39", [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", "2121c6402c8d44b05622677b761371a759143b958c6c19f6558ff64d0aed40df"}, "ex_json_logger": {:hex, :ex_json_logger, "1.4.0", "ad1dcc1cfe6940ee1d9d489b20757c89769626ce34c4957548d6fbe155cd96f1", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "7548a1ecba290746e06214d2b3d8783c76760c779a8903a8e44bfd23a7340444"}, "ex_json_schema": {:hex, :ex_json_schema, "0.11.1", "b593f92937a095f66054bb318681397dfe7304e7d2b6b1a7534ea3aa40024f8c", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "32d651a575a6ce2fd613f140b0fef8dd0acc7cf8e8bcd29a3a1be5c945700dd5"}, "ex_machina": {:hex, :ex_machina, "2.7.0", "b792cc3127fd0680fecdb6299235b4727a4944a09ff0fa904cc639272cd92dc7", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "419aa7a39bde11894c87a615c4ecaa52d8f107bbdd81d810465186f783245bf8"}, - "ex_money": {:hex, :ex_money, "5.23.0", "d3454358de76c561470e4f50ce044d45d6df2d4e2600315cf32b93036410e94e", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ex_cldr_numbers, "~> 2.34", [hex: :ex_cldr_numbers, repo: "hexpm", optional: false]}, {:ex_cldr_units, "~> 3.19", [hex: :ex_cldr_units, repo: "hexpm", optional: true]}, {:gringotts, "~> 1.1", [hex: :gringotts, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.0 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0 or ~> 6.0", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm", "397f77b02a7939fa0e8286819f18406540be201f7f3d6c04070654995dac32d2"}, + "ex_money": {:hex, :ex_money, "5.24.2", "131eda8a404b654dbf787ca71a8b782e11112e64726d85c27540856f94d4aee5", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ex_cldr, "~> 2.46", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_numbers, "~> 2.38", [hex: :ex_cldr_numbers, repo: "hexpm", optional: false]}, {:ex_cldr_units, "~> 3.19", [hex: :ex_cldr_units, repo: "hexpm", optional: true]}, {:gringotts, "~> 1.1", [hex: :gringotts, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.0 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0 or ~> 6.0", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm", "707bf02c99537d6cd93e5e5fd7f4faedde3ea2a7a932032b48e5ba0173307920"}, "excoveralls": {:hex, :excoveralls, "0.18.0", "b92497e69465dc51bc37a6422226ee690ab437e4c06877e836f1c18daeb35da9", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1109bb911f3cb583401760be49c02cbbd16aed66ea9509fc5479335d284da60b"}, "expo": {:hex, :expo, "1.1.1", "4202e1d2ca6e2b3b63e02f69cfe0a404f77702b041d02b58597c00992b601db5", [:mix], [], "hexpm", "5fb308b9cb359ae200b7e23d37c76978673aa1b06e2b3075d814ce12c5811640"}, "file_system": {:hex, :file_system, "1.1.1", "31864f4685b0148f25bd3fbef2b1228457c0c89024ad67f7a81a3ffbc0bbad3a", [:mix], [], "hexpm", "7a15ff97dfe526aeefb090a7a9d3d03aa907e100e262a0f8f7746b78f8f87a5d"}, - "finch": {:hex, :finch, "0.20.0", "5330aefb6b010f424dcbbc4615d914e9e3deae40095e73ab0c1bb0968933cadf", [: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", "2658131a74d051aabfcba936093c903b8e89da9a1b63e430bee62045fa9b2ee2"}, + "finch": {:hex, :finch, "0.23.0", "e3f9287ac25a8832f848b144c2b57346aac65b205e2e0629a52adfe6507fd837", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.8", [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", "80e58d3f936f57e3fdf404f83a3642897ae6d9fb642934e46da4d8fe761b99d5"}, "fine": {:hex, :fine, "0.1.4", "b19a89c1476c7c57afb5f9314aed5960b5bc95d5277de4cb5ee8e1d1616ce379", [:mix], [], "hexpm", "be3324cc454a42d80951cf6023b9954e9ff27c6daa255483b3e8d608670303f5"}, "fun_with_flags": {:hex, :fun_with_flags, "1.13.0", "8e8eddd6b723691211387923b160bc779fa593f59485209a058c90ea4bbb1cd5", [:mix], [{:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: true]}, {:redix, "~> 1.0", [hex: :redix, repo: "hexpm", optional: true]}, {:telemetry, "~> 1.3", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dbbbff607e6f096d3857c88530d1a4e178d9eeec5dc00118e2cc1d076578710a"}, "fun_with_flags_ui": {:hex, :fun_with_flags_ui, "1.1.0", "61a394cd7d80c09943a4b02e07c9ab8899781f3392a157b45527d22731bf871a", [:mix], [{:cowboy, ">= 2.0.0", [hex: :cowboy, repo: "hexpm", optional: true]}, {:fun_with_flags, "~> 1.12", [hex: :fun_with_flags, repo: "hexpm", optional: false]}, {:plug, "~> 1.12", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 2.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "99b578a250141537ff7774abb832427f3406a4faff3cfc4f074788beeef38f5d"}, "gen_cycle": {:hex, :gen_cycle, "1.0.4", "2315199f1256116328fad6a9d4371c2fb0bc39c7f5111b88d2de582300c931cc", [:rebar3], [], "hexpm", "67817e31b352bb00715f80a5571b3c069e26e994b2ebafa376acf76a2d0f66d8"}, - "gen_smtp": {:hex, :gen_smtp, "1.2.0", "9cfc75c72a8821588b9b9fe947ae5ab2aed95a052b81237e0928633a13276fd3", [:rebar3], [{:ranch, ">= 1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "5ee0375680bca8f20c4d85f58c2894441443a743355430ff33a783fe03296779"}, "gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"}, "gproc": {:hex, :gproc, "0.9.1", "f1df0364423539cf0b80e8201c8b1839e229e5f9b3ccb944c5834626998f5b8c", [:rebar3], [], "hexpm", "905088e32e72127ed9466f0bac0d8e65704ca5e73ee5a62cb073c3117916d507"}, "grpcbox": {:hex, :grpcbox, "0.17.1", "6e040ab3ef16fe699ffb513b0ef8e2e896da7b18931a1ef817143037c454bcce", [:rebar3], [{:acceptor_pool, "~> 1.0.0", [hex: :acceptor_pool, repo: "hexpm", optional: false]}, {:chatterbox, "~> 0.15.1", [hex: :ts_chatterbox, repo: "hexpm", optional: false]}, {:ctx, "~> 0.6.0", [hex: :ctx, repo: "hexpm", optional: false]}, {:gproc, "~> 0.9.1", [hex: :gproc, repo: "hexpm", optional: false]}], "hexpm", "4a3b5d7111daabc569dc9cbd9b202a3237d81c80bf97212fbc676832cb0ceb17"}, @@ -67,7 +65,7 @@ "happy_tcp": {:git, "https://github.com/ruslandoga/happy_tcp.git", "d639436bf8e7b456abc86bac13b722a2b6d60725", []}, "heroicons": {:hex, :heroicons, "0.5.6", "95d730e7179c633df32d95c1fdaaecdf81b0da11010b89b737b843ac176a7eb5", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:phoenix_live_view, ">= 0.18.2", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "ca267f02a5fa695a4178a737b649fb6644a2e399639d4ba7964c18e8a58c2352"}, "hpack": {:hex, :hpack_erl, "0.3.0", "2461899cc4ab6a0ef8e970c1661c5fc6a52d3c25580bc6dd204f84ce94669926", [:rebar3], [], "hexpm", "d6137d7079169d8c485c6962dfe261af5b9ef60fbc557344511c1e65e3d95fb0"}, - "hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"}, + "hpax": {:hex, :hpax, "1.0.4", "777de5d433b0fbdc7c418159c8055910faa8047ffdb3d6b31098d2a46cd7685c", [:mix], [], "hexpm", "afc7cb142ebcc2d01ce7816190b98ce5dd49e799111b24249f3443d730f377ca"}, "httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "jason": {:hex, :jason, "1.4.5", "2e3a008590b0b8d7388c20293e9dcc9cf3e5d642fd2a114e4cbbb52e595d940a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b0c823996102bcd0239b3c2444eb00409b72f6a140c1950bc8b457d836b30684"}, @@ -77,6 +75,7 @@ "libcluster": {:hex, :libcluster, "3.5.0", "5ee4cfde4bdf32b2fef271e33ce3241e89509f4344f6c6a8d4069937484866ba", [:mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.3", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ebf6561fcedd765a4cd43b4b8c04b1c87f4177b5fb3cbdfe40a780499d72f743"}, "location": {:git, "https://github.com/plausible/location.git", "a89bf79985c3c3d0830477ae587001156a646ce8", []}, "locus": {:hex, :locus, "2.3.12", "aa3992023363a523e5c6d0d104da1cd1026626d16b32a480903083201057f281", [:rebar3], [{:tls_certificate_check, "~> 1.9", [hex: :tls_certificate_check, repo: "hexpm", optional: false]}], "hexpm", "e9bacd644127c5aaac478461e8b4bcd49479e7bb9f665b48ab4ebac2b7adc1ec"}, + "logger_backends": {:hex, :logger_backends, "1.0.1", "08a9bd09eed271eac41ff35dd7603b6abf9e0f8b6ffe40359846cb0bfd37704f", [:mix], [], "hexpm", "d7903244fe8d84eeb3d3d42f8d7de080fd0409b613040df54c78b3591672d652"}, "mail": {:hex, :mail, "0.4.4", "2ed92e3b2dedb2013ba8eef9fb7ace3892e0eae1f45c0658738a72c195f7649b", [:mix], [], "hexpm", "bd44bf3e253d8be9c7f2e59b3253aff1efc1c9fa7d8ab4430c96780683faa8e2"}, "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"}, @@ -84,7 +83,7 @@ "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"}, "mimerl": {:hex, :mimerl, "1.4.0", "3882a5ca67fbbe7117ba8947f27643557adec38fa2307490c4c4207624cb213b", [:rebar3], [], "hexpm", "13af15f9f68c65884ecca3a3891d50a7b57d82152792f3e19d88650aa126b144"}, - "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"}, + "mint": {:hex, :mint, "1.9.1", "3bc120b743ed2e99ad920910f2613e9faebabb2257731b0e2ea4d8ccd9eceede", [: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", "831101bd560b086316fab5f7adb21a4f3455717d8e4bc8368b052e09aa9163e0"}, "mjml": {:hex, :mjml, "4.0.0", "3418c1a975112766f92b8786a17d53640a4a1c8c7dedb621016a08e1e1447d20", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.7.0", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "0886a411f9a850bc4ac6b878c9c0dbea168669176fde1f6583acf55fa8b628dd"}, "mjml_eex": {:hex, :mjml_eex, "0.12.0", "ee7e58a0b2f361812c024ddd2dd57ccd4107e486632016fcf707d4d0eaa04d62", [:mix], [{:erlexec, "~> 2.0.7", [hex: :erlexec, repo: "hexpm", optional: true]}, {:mjml, "~> 4.0", [hex: :mjml, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.2 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6ca41f6252669b709d31d8b7c74db00c8bc3784dea1913b406a68c12763c5bcb"}, "mox": {:hex, :mox, "1.2.0", "a2cd96b4b80a3883e3100a221e8adc1b98e4c3a332a8fc434c39526babafd5b3", [:mix], [{:nimble_ownership, "~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}], "hexpm", "c7b92b3cc69ee24a7eeeaf944cd7be22013c52fcb580c1f33f50845ec821089a"}, @@ -119,7 +118,7 @@ "parent": {:hex, :parent, "0.12.1", "495c4386f06de0df492e0a7a7199c10323a55e9e933b27222060dd86dccd6d62", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2ab589ef1f37bfcedbfb5ecfbab93354972fb7391201b8907a866dadd20b39d1"}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "peep": {:hex, :peep, "3.4.2", "49d4ca116d994779351959dfee971fb2c7d6506f1821374f3cc4fd39a3d3fadb", [:mix], [{:nimble_options, "~> 1.1", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:plug, "~> 1.16", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "cae224b09e224bf5584f5375108becf71e2288572a099a122e66735289cd33f4"}, - "phoenix": {:hex, :phoenix, "1.8.7", "d8d755b4ff4b449f610223dd706b4ae64155cb720d3dc09c706c079ecea189e4", [:mix], [{:bandit, "~> 1.0", [hex: :bandit, repo: "hexpm", optional: true]}, {: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", "47352f72d6ab31009ef77516b1b3a14745be97b54061fd458031b9d8294869d5"}, + "phoenix": {:hex, :phoenix, "1.8.9", "a63ed0962ed5b903b146dab0ae8eb8387fe478f8171a5e26d56a165f35996fe1", [:mix], [{:bandit, "~> 1.0", [hex: :bandit, repo: "hexpm", optional: true]}, {: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", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "3477e2dd5a4f61820341169031bdfe21275f659923bea9c5c0ea2aa1c3fcc046"}, "phoenix_bakery": {:hex, :phoenix_bakery, "0.1.2", "ca57673caea1a98f1cc763f94032796a015774d27eaa3ce5feef172195470452", [:mix], [{:brotli, "~> 0.3.0", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "45cc8cecc5c3002b922447c16389761718c07c360432328b04680034e893ea5b"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.7.0", "75c4b9dfb3efdc42aec2bd5f8bccd978aca0651dbcbc7a3f362ea5d9d43153c6", [: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", "1d75011e4254cb4ddf823e81823a9629559a1be93b4321a6a5f11a5306fbf4cc"}, "phoenix_html": {:hex, :phoenix_html, "4.3.0", "d3577a5df4b6954cd7890c84d955c470b5310bb49647f0a114a6eeecc850f7ad", [:mix], [], "hexpm", "3eaa290a78bab0f075f791a46a981bbe769d94bc776869f4f3063a14f30497ad"}, @@ -134,7 +133,7 @@ "plug_cowboy": {:hex, :plug_cowboy, "2.8.1", "5aa391a5e8d1ac3192e36a3bcaff12b5fd6ef6c7e29b53a38e63a860783e77d0", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "4c200288673d5bc86a0ab7dc6a2a069176a74e5d573ef62740a1c517458a5f26"}, "plug_crypto": {:hex, :plug_crypto, "1.2.5", "918772575e48e81e455818229bf719d4ab4181fcbf7f85b68a35620f78d89ced", [:mix], [], "hexpm", "26549a1d6345e2172eb1c233866756ae44a9609bd33ee6f99147ab3fd87fd842"}, "polymorphic_embed": {:hex, :polymorphic_embed, "5.0.3", "37444e0af941026a2c29b0539b6471bdd6737a6492a19264bf2bb0118e3ac242", [:mix], [{:attrs, "~> 0.6", [hex: :attrs, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_html_helpers, "~> 1.0", [hex: :phoenix_html_helpers, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}], "hexpm", "2fed44f57abf0a0fc7642e0eb0807a55b65de1562712cc0620772cbbb80e49c1"}, - "postgrex": {:hex, :postgrex, "0.21.1", "2c5cc830ec11e7a0067dd4d623c049b3ef807e9507a424985b8dcf921224cd88", [: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", "27d8d21c103c3cc68851b533ff99eef353e6a0ff98dc444ea751de43eb48bdac"}, + "postgrex": {:hex, :postgrex, "0.22.2", "4aec14df2a72722aee92492566edbeeb44e233ecb86b1915d03136297ef1385d", [:mix], [{:db_connection, "~> 2.9", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0 or ~> 3.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", "8946382ddb06294f56026ac4278b3cc212bac8a2c82ed68b4087819ed1abc53b"}, "prima": {:hex, :prima, "0.2.6", "a40993d108760a711c2da183cff20234497e977f6155aad1ee5e17a3b00a46b6", [:mix], [{:esbuild, "~> 0.7", [hex: :esbuild, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "00ec378bd7b0c58d58043e59581f9aa5ba35a0d5031e011e36c449d3a0b7418c"}, "prom_ex": {:hex, :prom_ex, "1.11.0", "1f6d67f2dead92224cb4f59beb3e4d319257c5728d9638b4a5e8ceb51a4f9c7e", [:mix], [{:absinthe, ">= 1.7.0", [hex: :absinthe, repo: "hexpm", optional: true]}, {:broadway, ">= 1.1.0", [hex: :broadway, repo: "hexpm", optional: true]}, {:ecto, ">= 3.11.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:finch, "~> 0.18", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, ">= 2.10.0", [hex: :oban, repo: "hexpm", optional: true]}, {:octo_fetch, "~> 0.4", [hex: :octo_fetch, repo: "hexpm", optional: false]}, {:peep, "~> 3.0", [hex: :peep, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.0", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, ">= 0.20.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, ">= 1.16.0", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 2.6.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, ">= 1.0.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}, {:telemetry_metrics_prometheus_core, "~> 1.2", [hex: :telemetry_metrics_prometheus_core, repo: "hexpm", optional: false]}, {:telemetry_poller, "~> 1.1", [hex: :telemetry_poller, repo: "hexpm", optional: false]}], "hexpm", "76b074bc3730f0802978a7eb5c7091a65473eaaf07e99ec9e933138dcc327805"}, "public_suffix": {:git, "https://github.com/axelson/publicsuffix-elixir", "fa40c243d4b5d8598b90cff268bc4e33f3bb63f1", []}, @@ -142,7 +141,7 @@ "recon": {:hex, :recon, "2.5.4", "05dd52a119ee4059fa9daa1ab7ce81bc7a8161a2f12e9d42e9d551ffd2ba901c", [:mix, :rebar3], [], "hexpm", "e9ab01ac7fc8572e41eb59385efeb3fb0ff5bf02103816535bacaedf327d0263"}, "ref_inspector": {:hex, :ref_inspector, "2.0.0", "f3e97e51d9782de4c792f56eed26c80903bc39174c878285392ce76d5e67fe98", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:yamerl, "~> 0.7", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "bf62f3f1a87d6b8b30f457a480668f965373e64f184611282b5e89d8dd81fd33"}, "referrer_blocklist": {:git, "https://github.com/plausible/referrer-blocklist.git", "d6f52c225cccb4f04b80e3a5d588868ec234139d", []}, - "req": {:hex, :req, "0.5.16", "99ba6a36b014458e52a8b9a0543bfa752cb0344b2a9d756651db1281d4ba4450", [: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, "~> 2.0.6 or ~> 2.1", [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", "974a7a27982b9b791df84e8f6687d21483795882a7840e8309abdbe08bb06f09"}, + "req": {:hex, :req, "0.6.2", "b9b2024f35bcf60a92cc8cad2eaaf9d4e7aace463ff74be1afe5986830184413", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.21", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [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", "cc9cd30a2ddd04989929b887178e1610c940456d962c6c3a52df6146d2eef9bf"}, "rustler_precompiled": {:hex, :rustler_precompiled, "0.7.3", "42cb9449785cd86c87453e39afdd27a0bdfa5c77a4ec5dc5ce45112e06b9f89b", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "cbc4b3777682e5f6f43ed39b0e0b4a42dccde8053aba91b4514e8f5ff9a5ac6d"}, "saxy": {:hex, :saxy, "1.6.0", "02cb4e9bd045f25ac0c70fae8164754878327ee393c338a090288210b02317ee", [:mix], [], "hexpm", "ef42eb4ac983ca77d650fbdb68368b26570f6cc5895f0faa04d34a6f384abad3"}, "sentry": {:hex, :sentry, "11.0.4", "60371c96cefd247e0fc98840bba2648f64f19aa0b8db8e938f5a98421f55b619", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:igniter, "~> 0.5", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_ownership, "~> 0.3.0 or ~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:opentelemetry, ">= 0.0.0", [hex: :opentelemetry, repo: "hexpm", optional: true]}, {:opentelemetry_api, ">= 0.0.0", [hex: :opentelemetry_api, repo: "hexpm", optional: true]}, {:opentelemetry_exporter, ">= 0.0.0", [hex: :opentelemetry_exporter, repo: "hexpm", optional: true]}, {:opentelemetry_semantic_conventions, ">= 0.0.0", [hex: :opentelemetry_semantic_conventions, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "feaafc284dc204c82aadaddc884227aeaa3480decb274d30e184b9d41a700c66"}, @@ -164,7 +163,7 @@ "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.1", "a48703a25c170eedadca83b11e88985af08d35f37c6f664d6dcfb106a97782fc", [:rebar3], [], "hexpm", "b3a917854ce3ae233619744ad1e0102e05673136776fb2fa76234f3e03b23642"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.9", "43dc3ba6d89ef5dec5b1d0a39698436a1e856d000d84bf31a3149862b01a287f", [: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", "5534d5c9adad3c18a0f58a9371220d75a803bf0b9a3d87e6fe072faaeed76a08"}, - "x509": {:hex, :x509, "0.9.1", "c92026a17b7d93f19029842ca218f82ec1f1e7cc9d4aa0c48327ee778f7f482e", [:mix], [], "hexpm", "99328951a1480cfd7b1b8aa688f857f7f5bbea03077b78cad211fb3b30c2f4a8"}, + "x509": {:hex, :x509, "0.9.2", "a75aa605348abd905990f3d2dc1b155fcde4e030fa2f90c4a91534405dce0f6e", [:mix], [], "hexpm", "4c5ede75697e565d4b0f5be04c3b71bb1fd3a090ea243af4bd7dae144e48cfc7"}, "xml_builder": {:hex, :xml_builder, "2.4.0", "b20d23077266c81f593360dc037ea398461dddb6638a329743da6c73afa56725", [:mix], [], "hexpm", "833e325bb997f032b5a1b740d2fd6feed3c18ca74627f9f5f30513a9ae1a232d"}, "yamerl": {:hex, :yamerl, "0.10.0", "4ff81fee2f1f6a46f1700c0d880b24d193ddb74bd14ef42cb0bcf46e81ef2f8e", [:rebar3], [], "hexpm", "346adb2963f1051dc837a2364e4acf6eb7d80097c0f53cbdc3046ec8ec4b4e6e"}, "zstream": {:hex, :zstream, "0.6.7", "ae74c7544f4e0563ffbe71324bf1c9bbc0ab33bb580a0ae718da511fb8a5c9d6", [:mix], [], "hexpm", "48c43ae0f00cfcda1ccb69c1d044755663d43b2ee8a0a65763648bf2078d634d"}, diff --git a/test/plausible/audit_test.exs b/test/plausible/audit_test.exs index a1450c069f70..244f4928048f 100644 --- a/test/plausible/audit_test.exs +++ b/test/plausible/audit_test.exs @@ -110,14 +110,6 @@ defmodule Plausible.AuditTest do changeset = %Ecto.Changeset{data: data, changes: changes} assert Encoder.encode(changeset) == %{before: %{foo: "bar"}, after: %{foo: "baz"}} end - - test "raises if encoder is not derived for a struct" do - struct = %{__struct__: Foo, foo: 1, bar: 2} - - assert_raise Protocol.UndefinedError, fn -> - Encoder.encode(struct) - end - end end describe "Audit.Entry" do diff --git a/test/plausible/auth/totp/recovery_code_test.exs b/test/plausible/auth/totp/recovery_code_test.exs index d3cbb4ee0f3b..2163e107171b 100644 --- a/test/plausible/auth/totp/recovery_code_test.exs +++ b/test/plausible/auth/totp/recovery_code_test.exs @@ -48,10 +48,6 @@ defmodule Plausible.Auth.TOTP.RecoveryCodeTest do assert_raise FunctionClauseError, fn -> RecoveryCode.changeset(user, "INVALID") end - - assert_raise FunctionClauseError, fn -> - RecoveryCode.changeset(user, 123) - end end end diff --git a/test/plausible/billing/plans_test.exs b/test/plausible/billing/plans_test.exs index 6b897b7d21dc..569f5d774362 100644 --- a/test/plausible/billing/plans_test.exs +++ b/test/plausible/billing/plans_test.exs @@ -135,11 +135,11 @@ defmodule Plausible.Billing.PlansTest do Plans.available_plans_for(subscription, with_prices: true, customer_ip: "127.0.0.1") assert Enum.find(growth_plans, fn plan -> - (%Money{} = plan.monthly_cost) && plan.monthly_product_id == @v2_plan_id + plan.monthly_cost && plan.monthly_product_id == @v2_plan_id end) assert Enum.find(business_plans, fn plan -> - (%Money{} = plan.monthly_cost) && plan.monthly_product_id == @v3_business_plan_id + plan.monthly_cost && plan.monthly_product_id == @v3_business_plan_id end) end diff --git a/test/plausible/billing/subscription/status_test.exs b/test/plausible/billing/subscription/status_test.exs index 4575457b5242..763c4b292b36 100644 --- a/test/plausible/billing/subscription/status_test.exs +++ b/test/plausible/billing/subscription/status_test.exs @@ -18,15 +18,15 @@ defmodule Plausible.Billing.Subscription.StatusTest do end test "in?/2 returns true when subscription status is in list" do - assert in?(%Plausible.Billing.Subscription{status: past_due()}, [active(), past_due()]) + assert in?(subscription(past_due()), [active(), past_due()]) end test "in?/2 returns false when subscription status is not in list" do - refute in?(%Plausible.Billing.Subscription{status: paused()}, [active(), past_due()]) + refute in?(subscription(paused()), [active(), past_due()]) end test "in?/2 returns false when subscription is nil" do - refute in?(nil, [active(), past_due()]) + refute in?(subscription(nil), [active(), past_due()]) end test "in?/2 raises ArgumentError when list includes invalid statuses" do @@ -43,4 +43,22 @@ defmodule Plausible.Billing.Subscription.StatusTest do ) end end + + # Workaround for type checker in Elixir 1.20+ being + # too smart about literals passed to macros. + defp subscription(nil) do + if :erlang.phash2(1, 1) == 0 do + nil + else + %Plausible.Billing.Subscription{} + end + end + + defp subscription(status) do + if :erlang.phash2(1, 1) == 0 do + %Plausible.Billing.Subscription{status: status} + else + nil + end + end end diff --git a/test/plausible/config_test.exs b/test/plausible/config_test.exs index c42fe4fdbc82..89c9523da6d2 100644 --- a/test/plausible/config_test.exs +++ b/test/plausible/config_test.exs @@ -151,33 +151,6 @@ defmodule Plausible.ConfigTest do ] end - test "Bamboo.SMTPAdapter" do - env = [ - {"MAILER_ADAPTER", "Bamboo.SMTPAdapter"}, - {"SMTP_HOST_ADDR", "localhost"}, - {"SMTP_HOST_PORT", "2525"}, - {"SMTP_USER_NAME", "neo"}, - {"SMTP_USER_PWD", "one"}, - {"SMTP_HOST_SSL_ENABLED", "true"}, - {"SMTP_RETRIES", "3"}, - {"SMTP_MX_LOOKUPS_ENABLED", "true"} - ] - - assert get_in(runtime_config(env), [:plausible, Plausible.Mailer]) == [ - {:adapter, Bamboo.SMTPAdapter}, - {:server, "localhost"}, - {:hostname, "localhost"}, - {:port, "2525"}, - {:username, "neo"}, - {:password, "one"}, - {:tls, :if_available}, - {:allowed_tls_versions, [:tlsv1, :"tlsv1.1", :"tlsv1.2"]}, - {:ssl, true}, - {:retries, "3"}, - {:no_mx_lookups, true} - ] - end - test "Bamboo.Mua (no config)" do env = [{"MAILER_ADAPTER", "Bamboo.Mua"}] diff --git a/test/plausible/consolidated_view_test.exs b/test/plausible/consolidated_view_test.exs index 1d83f60eed14..990bf14f7376 100644 --- a/test/plausible/consolidated_view_test.exs +++ b/test/plausible/consolidated_view_test.exs @@ -136,9 +136,6 @@ defmodule Plausible.ConsolidatedViewTest do refute ConsolidatedView.get(team) end - @tag :skip - test "returns {:error, :upgrade_required} when team ineligible for this feature" - test "creates consolidated view with stats start dates of the oldest site", %{team: team} do team = Teams.complete_setup(team) diff --git a/test/plausible/http_client_test.exs b/test/plausible/http_client_test.exs index ad90fed7d683..e2f600057a6c 100644 --- a/test/plausible/http_client_test.exs +++ b/test/plausible/http_client_test.exs @@ -109,7 +109,7 @@ defmodule Plausible.HTTPClientTest do Conn.resp(conn, 200, "ok") end) - assert {:error, %Mint.TransportError{reason: :timeout}} == + assert {:error, %Finch.TransportError{reason: :timeout}} = HTTPClient.post(bypass_url(bypass, path: "/timeout"), [], %{}, receive_timeout: 100) Bypass.pass(bypass) diff --git a/test/plausible/ingestion/event_test.exs b/test/plausible/ingestion/event_test.exs index bf8be438438c..43a0a06e2d53 100644 --- a/test/plausible/ingestion/event_test.exs +++ b/test/plausible/ingestion/event_test.exs @@ -71,7 +71,7 @@ defmodule Plausible.Ingestion.EventTest do conn = :post |> build_conn("/api/events", payload) - |> Plug.Conn.put_req_header("user-agent", :binary.copy("a", 1024 * 8)) + |> Plug.Conn.put_req_header("user-agent", :binary.copy("a", 1024 * 32)) assert {:ok, request, _conn} = Request.build(conn) diff --git a/test/plausible/shield/hostname_rule_cache_test.exs b/test/plausible/shield/hostname_rule_cache_test.exs index 0cc66995bed1..91f50b831201 100644 --- a/test/plausible/shield/hostname_rule_cache_test.exs +++ b/test/plausible/shield/hostname_rule_cache_test.exs @@ -56,7 +56,7 @@ defmodule Plausible.Shield.HostnameRuleCacheTest do {:ok, _} = Shields.add_hostname_rule(site, %{"hostname" => "*example.com"}) :ok = HostnameRuleCache.refresh_all(cache_name: test) assert regex = HostnameRuleCache.get(site.domain, cache_opts).hostname_pattern - assert regex == ~r/^.*example\.com$/ + assert Regex.source(regex) == "^.*example\\.com$" end test "cache allows lookups for hostname paths on sites with changed domain", %{test: test} do @@ -93,9 +93,11 @@ defmodule Plausible.Shield.HostnameRuleCacheTest do assert :ok = HostnameRuleCache.refresh_updated_recently(cache_opts) - assert %{hostname_pattern: ~r/^test2\.example\.com$/} = + assert %{hostname_pattern: hostname_pattern} = HostnameRuleCache.get(domain, cache_opts) + assert Regex.source(hostname_pattern) == "^test2\\.example\\.com$" + assert :ok = HostnameRuleCache.refresh_all(cache_opts) assert [_, _] = HostnameRuleCache.get(domain, cache_opts) diff --git a/test/plausible/shield/page_rule_cache_test.exs b/test/plausible/shield/page_rule_cache_test.exs index ba26f3cf962b..c6533e770a4d 100644 --- a/test/plausible/shield/page_rule_cache_test.exs +++ b/test/plausible/shield/page_rule_cache_test.exs @@ -55,7 +55,7 @@ defmodule Plausible.Shield.PageRuleCacheTest do {:ok, _} = Shields.add_page_rule(site, %{"page_path" => "/hello/**/world"}) :ok = PageRuleCache.refresh_all(cache_name: test) assert regex = PageRuleCache.get(site.domain, cache_opts).page_path_pattern - assert regex == ~r/^\/hello\/.*\/world$/ + assert Regex.source(regex) == "^\/hello\/.*\/world$" end test "cache allows lookups for page paths on sites with changed domain", %{test: test} do @@ -92,7 +92,8 @@ defmodule Plausible.Shield.PageRuleCacheTest do assert :ok = PageRuleCache.refresh_updated_recently(cache_opts) - assert %{page_path_pattern: ~r[^/test/2$]} = PageRuleCache.get(domain, cache_opts) + assert %{page_path_pattern: path_pattern} = PageRuleCache.get(domain, cache_opts) + assert Regex.source(path_pattern) == "^\/test\/2$" assert :ok = PageRuleCache.refresh_all(cache_opts) diff --git a/test/plausible/teams/sites/transfer_test.exs b/test/plausible/teams/sites/transfer_test.exs index 2536146030bc..06f584cd5f67 100644 --- a/test/plausible/teams/sites/transfer_test.exs +++ b/test/plausible/teams/sites/transfer_test.exs @@ -1,5 +1,4 @@ defmodule Plausible.Teams.Sites.TransferTest do - require Plausible.Billing.Subscription.Status use Plausible.DataCase, async: true use Bamboo.Test diff --git a/test/plausible_web/controllers/google_analytics_controller_test.exs b/test/plausible_web/controllers/google_analytics_controller_test.exs index 816c388ab3c2..5ecfc5712bad 100644 --- a/test/plausible_web/controllers/google_analytics_controller_test.exs +++ b/test/plausible_web/controllers/google_analytics_controller_test.exs @@ -149,7 +149,7 @@ defmodule PlausibleWeb.GoogleAnalyticsControllerTest do Plausible.HTTPClient.Mock, :get, fn _url, _opts -> - {:error, %Mint.TransportError{reason: :timeout}} + {:error, %Finch.TransportError{reason: :timeout}} end ) @@ -478,7 +478,7 @@ defmodule PlausibleWeb.GoogleAnalyticsControllerTest do Plausible.HTTPClient.Mock, :post, fn _url, _opts, _params -> - {:error, %Mint.TransportError{reason: :timeout}} + {:error, %Finch.TransportError{reason: :timeout}} end ) @@ -701,7 +701,7 @@ defmodule PlausibleWeb.GoogleAnalyticsControllerTest do Plausible.HTTPClient.Mock, :get, fn _url, _params -> - {:error, %Mint.TransportError{reason: :timeout}} + {:error, %Finch.TransportError{reason: :timeout}} end ) diff --git a/test/plausible_web/live/change_domain_test.exs b/test/plausible_web/live/change_domain_test.exs index 3e50e4840310..80c5a430c687 100644 --- a/test/plausible_web/live/change_domain_test.exs +++ b/test/plausible_web/live/change_domain_test.exs @@ -16,7 +16,7 @@ defmodule PlausibleWeb.Live.ChangeDomainTest do setup do # mock all domains resolve Plausible.DnsLookup.Mock - |> expect(:lookup, fn _domain, _type, _record, _opts, _timeout -> + |> stub(:lookup, fn _domain, _type, _record, _opts, _timeout -> [{192, 168, 1, 2}] end) diff --git a/test/plausible_web/live/goal_settings/form_test.exs b/test/plausible_web/live/goal_settings/form_test.exs index 5ab5fd036d20..7d6774dbb4e7 100644 --- a/test/plausible_web/live/goal_settings/form_test.exs +++ b/test/plausible_web/live/goal_settings/form_test.exs @@ -480,6 +480,9 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do |> element("#goals-form-modalseq0 form") |> render_submit(%{goal: %{event_name: "Purchase"}}) + # Helps avoid premature close of DB connection and logging error in test output + _ = render(lv) + updated_goal = Plausible.Goals.get(site, goal.id) refute Plausible.Goal.has_custom_props?(updated_goal) assert updated_goal.custom_props == %{} diff --git a/test/plausible_web/plugs/favicon_test.exs b/test/plausible_web/plugs/favicon_test.exs index 964cf39bccda..97db7d6dbf34 100644 --- a/test/plausible_web/plugs/favicon_test.exs +++ b/test/plausible_web/plugs/favicon_test.exs @@ -198,7 +198,7 @@ defmodule PlausibleWeb.FaviconTest do Plausible.HTTPClient.Mock, :get, fn "https://icons.duckduckgo.com/ip3/plausible.io.ico" -> - {:error, %Mint.TransportError{reason: :closed}} + {:error, %Finch.TransportError{reason: :closed}} end ) diff --git a/test/support/test_utils.ex b/test/support/test_utils.ex index c8dd10755509..b4a7266b9f2e 100644 --- a/test/support/test_utils.ex +++ b/test/support/test_utils.ex @@ -1,4 +1,6 @@ defmodule Plausible.TestUtils do + @moduledoc false + use Plausible.Repo use Plausible alias Plausible.Factory @@ -277,7 +279,7 @@ defmodule Plausible.TestUtils do case Finch.request(healthcheck_req, Plausible.Finch) do {:ok, %Finch.Response{}} -> true - {:error, %Mint.TransportError{reason: :econnrefused}} -> false + {:error, %Finch.TransportError{reason: :econnrefused}} -> false end end