Add missing type specifications to improve type safety
- Add @spec annotations to all public functions in time_helpers.ex
- Add @spec annotations to all public functions in weather_units.ex
- Add @spec annotations to authentication functions in user_auth.ex
- Fix User struct type reference (use %Aprsme.Accounts.User{} instead of t())
- All dialyzer checks now pass successfully
These type specifications improve code documentation and enable better
compile-time type checking with dialyzer.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
a0258c0ff0
commit
c8ae4aecaf
4 changed files with 21 additions and 3 deletions
|
|
@ -56,8 +56,6 @@ defmodule Aprsme.EncodingUtils do
|
||||||
def to_float(value) when is_integer(value) do
|
def to_float(value) when is_integer(value) do
|
||||||
if value >= -9.0e15 and value <= 9.0e15 do
|
if value >= -9.0e15 and value <= 9.0e15 do
|
||||||
value * 1.0
|
value * 1.0
|
||||||
else
|
|
||||||
nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -77,7 +75,6 @@ defmodule Aprsme.EncodingUtils do
|
||||||
|
|
||||||
def to_float(_), do: nil
|
def to_float(_), do: nil
|
||||||
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Converts various types to Decimal for database storage.
|
Converts various types to Decimal for database storage.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ defmodule AprsmeWeb.TimeHelpers do
|
||||||
@doc """
|
@doc """
|
||||||
Returns a human-readable string for how long ago the given DateTime was.
|
Returns a human-readable string for how long ago the given DateTime was.
|
||||||
"""
|
"""
|
||||||
|
@spec time_ago_in_words(nil | NaiveDateTime.t() | DateTime.t()) :: String.t()
|
||||||
def time_ago_in_words(nil), do: gettext("unknown time") <> " " <> gettext("ago")
|
def time_ago_in_words(nil), do: gettext("unknown time") <> " " <> gettext("ago")
|
||||||
|
|
||||||
def time_ago_in_words(%NaiveDateTime{} = naive_datetime) do
|
def time_ago_in_words(%NaiveDateTime{} = naive_datetime) do
|
||||||
|
|
@ -42,6 +43,7 @@ defmodule AprsmeWeb.TimeHelpers do
|
||||||
Handles ISO 8601 strings, Unix timestamps in milliseconds, and existing
|
Handles ISO 8601 strings, Unix timestamps in milliseconds, and existing
|
||||||
DateTime or NaiveDateTime structs.
|
DateTime or NaiveDateTime structs.
|
||||||
"""
|
"""
|
||||||
|
@spec to_datetime(String.t() | integer() | DateTime.t() | NaiveDateTime.t() | any()) :: DateTime.t() | nil
|
||||||
def to_datetime(ts) do
|
def to_datetime(ts) do
|
||||||
cond do
|
cond do
|
||||||
is_binary(ts) ->
|
is_binary(ts) ->
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ defmodule AprsmeWeb.UserAuth do
|
||||||
# Make the remember me cookie valid for 60 days.
|
# Make the remember me cookie valid for 60 days.
|
||||||
# If you want bump or reduce this value, also change
|
# If you want bump or reduce this value, also change
|
||||||
# the token expiry itself in UserToken.
|
# the token expiry itself in UserToken.
|
||||||
|
alias Phoenix.LiveView.Socket
|
||||||
|
|
||||||
@max_age 60 * 60 * 24 * 60
|
@max_age 60 * 60 * 24 * 60
|
||||||
@remember_me_cookie "_aprs_web_user_remember_me"
|
@remember_me_cookie "_aprs_web_user_remember_me"
|
||||||
@remember_me_options [sign: true, max_age: @max_age, same_site: "Lax"]
|
@remember_me_options [sign: true, max_age: @max_age, same_site: "Lax"]
|
||||||
|
|
@ -26,6 +28,7 @@ defmodule AprsmeWeb.UserAuth do
|
||||||
disconnected on log out. The line can be safely removed
|
disconnected on log out. The line can be safely removed
|
||||||
if you are not using LiveView.
|
if you are not using LiveView.
|
||||||
"""
|
"""
|
||||||
|
@spec log_in_user(Plug.Conn.t(), %Aprsme.Accounts.User{}, map()) :: Plug.Conn.t()
|
||||||
def log_in_user(conn, user, params \\ %{}) do
|
def log_in_user(conn, user, params \\ %{}) do
|
||||||
token = Accounts.generate_user_session_token(user)
|
token = Accounts.generate_user_session_token(user)
|
||||||
user_return_to = get_session(conn, :user_return_to)
|
user_return_to = get_session(conn, :user_return_to)
|
||||||
|
|
@ -69,6 +72,7 @@ defmodule AprsmeWeb.UserAuth do
|
||||||
|
|
||||||
It clears all session data for safety. See renew_session.
|
It clears all session data for safety. See renew_session.
|
||||||
"""
|
"""
|
||||||
|
@spec log_out_user(Plug.Conn.t()) :: Plug.Conn.t()
|
||||||
def log_out_user(conn) do
|
def log_out_user(conn) do
|
||||||
user_token = get_session(conn, :user_token)
|
user_token = get_session(conn, :user_token)
|
||||||
user_token && Accounts.delete_user_session_token(user_token)
|
user_token && Accounts.delete_user_session_token(user_token)
|
||||||
|
|
@ -87,6 +91,7 @@ defmodule AprsmeWeb.UserAuth do
|
||||||
Authenticates the user by looking into the session
|
Authenticates the user by looking into the session
|
||||||
and remember me token.
|
and remember me token.
|
||||||
"""
|
"""
|
||||||
|
@spec fetch_current_user(Plug.Conn.t(), any()) :: Plug.Conn.t()
|
||||||
def fetch_current_user(conn, _opts) do
|
def fetch_current_user(conn, _opts) do
|
||||||
{user_token, conn} = ensure_user_token(conn)
|
{user_token, conn} = ensure_user_token(conn)
|
||||||
user = user_token && Accounts.get_user_by_session_token(user_token)
|
user = user_token && Accounts.get_user_by_session_token(user_token)
|
||||||
|
|
@ -144,6 +149,7 @@ defmodule AprsmeWeb.UserAuth do
|
||||||
live "/profile", ProfileLive, :index
|
live "/profile", ProfileLive, :index
|
||||||
end
|
end
|
||||||
"""
|
"""
|
||||||
|
@spec on_mount(atom(), map(), map(), Socket.t()) :: {:cont | :halt, Socket.t()}
|
||||||
def on_mount(:mount_current_user, _params, session, socket) do
|
def on_mount(:mount_current_user, _params, session, socket) do
|
||||||
{:cont, mount_current_user(session, socket)}
|
{:cont, mount_current_user(session, socket)}
|
||||||
end
|
end
|
||||||
|
|
@ -189,6 +195,7 @@ defmodule AprsmeWeb.UserAuth do
|
||||||
@doc """
|
@doc """
|
||||||
Used for routes that require the user to not be authenticated.
|
Used for routes that require the user to not be authenticated.
|
||||||
"""
|
"""
|
||||||
|
@spec redirect_if_user_is_authenticated(Plug.Conn.t(), any()) :: Plug.Conn.t()
|
||||||
def redirect_if_user_is_authenticated(conn, _opts) do
|
def redirect_if_user_is_authenticated(conn, _opts) do
|
||||||
case conn.assigns[:current_user] do
|
case conn.assigns[:current_user] do
|
||||||
nil ->
|
nil ->
|
||||||
|
|
@ -207,6 +214,7 @@ defmodule AprsmeWeb.UserAuth do
|
||||||
If you want to enforce the user email is confirmed before
|
If you want to enforce the user email is confirmed before
|
||||||
they use the application at all, here would be a good place.
|
they use the application at all, here would be a good place.
|
||||||
"""
|
"""
|
||||||
|
@spec require_authenticated_user(Plug.Conn.t(), any()) :: Plug.Conn.t()
|
||||||
def require_authenticated_user(conn, _opts) do
|
def require_authenticated_user(conn, _opts) do
|
||||||
case conn.assigns[:current_user] do
|
case conn.assigns[:current_user] do
|
||||||
nil ->
|
nil ->
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ defmodule AprsmeWeb.WeatherUnits do
|
||||||
Determines the unit system based on locale.
|
Determines the unit system based on locale.
|
||||||
Returns :imperial for US, :metric for most other countries.
|
Returns :imperial for US, :metric for most other countries.
|
||||||
"""
|
"""
|
||||||
|
@spec unit_system(String.t() | nil | any()) :: :imperial | :metric
|
||||||
def unit_system(locale) when is_binary(locale) do
|
def unit_system(locale) when is_binary(locale) do
|
||||||
case locale do
|
case locale do
|
||||||
# Default to imperial for English
|
# Default to imperial for English
|
||||||
|
|
@ -32,6 +33,7 @@ defmodule AprsmeWeb.WeatherUnits do
|
||||||
Converts temperature from Fahrenheit to Celsius if needed.
|
Converts temperature from Fahrenheit to Celsius if needed.
|
||||||
Returns the temperature in the appropriate unit for the locale.
|
Returns the temperature in the appropriate unit for the locale.
|
||||||
"""
|
"""
|
||||||
|
@spec format_temperature(number() | any(), String.t()) :: {number() | any(), String.t()}
|
||||||
def format_temperature(temp, locale) when is_number(temp) do
|
def format_temperature(temp, locale) when is_number(temp) do
|
||||||
case unit_system(locale) do
|
case unit_system(locale) do
|
||||||
:imperial -> {temp, "°F"}
|
:imperial -> {temp, "°F"}
|
||||||
|
|
@ -45,6 +47,7 @@ defmodule AprsmeWeb.WeatherUnits do
|
||||||
Converts wind speed from mph to km/h if needed.
|
Converts wind speed from mph to km/h if needed.
|
||||||
Returns the wind speed in the appropriate unit for the locale.
|
Returns the wind speed in the appropriate unit for the locale.
|
||||||
"""
|
"""
|
||||||
|
@spec format_wind_speed(number() | any(), String.t()) :: {number() | any(), String.t()}
|
||||||
def format_wind_speed(speed, locale) when is_number(speed) do
|
def format_wind_speed(speed, locale) when is_number(speed) do
|
||||||
case unit_system(locale) do
|
case unit_system(locale) do
|
||||||
:imperial -> {speed, "mph"}
|
:imperial -> {speed, "mph"}
|
||||||
|
|
@ -58,6 +61,7 @@ defmodule AprsmeWeb.WeatherUnits do
|
||||||
Converts rain from inches to mm if needed.
|
Converts rain from inches to mm if needed.
|
||||||
Returns the rain amount in the appropriate unit for the locale.
|
Returns the rain amount in the appropriate unit for the locale.
|
||||||
"""
|
"""
|
||||||
|
@spec format_rain(number() | any(), String.t()) :: {number() | any(), String.t()}
|
||||||
def format_rain(rain, locale) when is_number(rain) do
|
def format_rain(rain, locale) when is_number(rain) do
|
||||||
case unit_system(locale) do
|
case unit_system(locale) do
|
||||||
:imperial -> {rain, "in"}
|
:imperial -> {rain, "in"}
|
||||||
|
|
@ -70,6 +74,7 @@ defmodule AprsmeWeb.WeatherUnits do
|
||||||
@doc """
|
@doc """
|
||||||
Formats pressure (keeps hPa for all locales as it's standard).
|
Formats pressure (keeps hPa for all locales as it's standard).
|
||||||
"""
|
"""
|
||||||
|
@spec format_pressure(number() | any(), any()) :: {number() | any(), String.t()}
|
||||||
def format_pressure(pressure, _locale) when is_number(pressure) do
|
def format_pressure(pressure, _locale) when is_number(pressure) do
|
||||||
{pressure, "hPa"}
|
{pressure, "hPa"}
|
||||||
end
|
end
|
||||||
|
|
@ -79,6 +84,12 @@ defmodule AprsmeWeb.WeatherUnits do
|
||||||
@doc """
|
@doc """
|
||||||
Gets the appropriate unit labels for the locale.
|
Gets the appropriate unit labels for the locale.
|
||||||
"""
|
"""
|
||||||
|
@spec unit_labels(String.t()) :: %{
|
||||||
|
temperature: String.t(),
|
||||||
|
wind_speed: String.t(),
|
||||||
|
rain: String.t(),
|
||||||
|
pressure: String.t()
|
||||||
|
}
|
||||||
def unit_labels(locale) do
|
def unit_labels(locale) do
|
||||||
case unit_system(locale) do
|
case unit_system(locale) do
|
||||||
:imperial ->
|
:imperial ->
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue