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
|
||||
if value >= -9.0e15 and value <= 9.0e15 do
|
||||
value * 1.0
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -77,7 +75,6 @@ defmodule Aprsme.EncodingUtils do
|
|||
|
||||
def to_float(_), do: nil
|
||||
|
||||
|
||||
@doc """
|
||||
Converts various types to Decimal for database storage.
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ defmodule AprsmeWeb.TimeHelpers do
|
|||
@doc """
|
||||
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(%NaiveDateTime{} = naive_datetime) do
|
||||
|
|
@ -42,6 +43,7 @@ defmodule AprsmeWeb.TimeHelpers do
|
|||
Handles ISO 8601 strings, Unix timestamps in milliseconds, and existing
|
||||
DateTime or NaiveDateTime structs.
|
||||
"""
|
||||
@spec to_datetime(String.t() | integer() | DateTime.t() | NaiveDateTime.t() | any()) :: DateTime.t() | nil
|
||||
def to_datetime(ts) do
|
||||
cond do
|
||||
is_binary(ts) ->
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ defmodule AprsmeWeb.UserAuth do
|
|||
# Make the remember me cookie valid for 60 days.
|
||||
# If you want bump or reduce this value, also change
|
||||
# the token expiry itself in UserToken.
|
||||
alias Phoenix.LiveView.Socket
|
||||
|
||||
@max_age 60 * 60 * 24 * 60
|
||||
@remember_me_cookie "_aprs_web_user_remember_me"
|
||||
@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
|
||||
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
|
||||
token = Accounts.generate_user_session_token(user)
|
||||
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.
|
||||
"""
|
||||
@spec log_out_user(Plug.Conn.t()) :: Plug.Conn.t()
|
||||
def log_out_user(conn) do
|
||||
user_token = get_session(conn, :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
|
||||
and remember me token.
|
||||
"""
|
||||
@spec fetch_current_user(Plug.Conn.t(), any()) :: Plug.Conn.t()
|
||||
def fetch_current_user(conn, _opts) do
|
||||
{user_token, conn} = ensure_user_token(conn)
|
||||
user = user_token && Accounts.get_user_by_session_token(user_token)
|
||||
|
|
@ -144,6 +149,7 @@ defmodule AprsmeWeb.UserAuth do
|
|||
live "/profile", ProfileLive, :index
|
||||
end
|
||||
"""
|
||||
@spec on_mount(atom(), map(), map(), Socket.t()) :: {:cont | :halt, Socket.t()}
|
||||
def on_mount(:mount_current_user, _params, session, socket) do
|
||||
{:cont, mount_current_user(session, socket)}
|
||||
end
|
||||
|
|
@ -189,6 +195,7 @@ defmodule AprsmeWeb.UserAuth do
|
|||
@doc """
|
||||
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
|
||||
case conn.assigns[:current_user] do
|
||||
nil ->
|
||||
|
|
@ -207,6 +214,7 @@ defmodule AprsmeWeb.UserAuth do
|
|||
If you want to enforce the user email is confirmed before
|
||||
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
|
||||
case conn.assigns[:current_user] do
|
||||
nil ->
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ defmodule AprsmeWeb.WeatherUnits do
|
|||
Determines the unit system based on locale.
|
||||
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
|
||||
case locale do
|
||||
# Default to imperial for English
|
||||
|
|
@ -32,6 +33,7 @@ defmodule AprsmeWeb.WeatherUnits do
|
|||
Converts temperature from Fahrenheit to Celsius if needed.
|
||||
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
|
||||
case unit_system(locale) do
|
||||
:imperial -> {temp, "°F"}
|
||||
|
|
@ -45,6 +47,7 @@ defmodule AprsmeWeb.WeatherUnits do
|
|||
Converts wind speed from mph to km/h if needed.
|
||||
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
|
||||
case unit_system(locale) do
|
||||
:imperial -> {speed, "mph"}
|
||||
|
|
@ -58,6 +61,7 @@ defmodule AprsmeWeb.WeatherUnits do
|
|||
Converts rain from inches to mm if needed.
|
||||
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
|
||||
case unit_system(locale) do
|
||||
:imperial -> {rain, "in"}
|
||||
|
|
@ -70,6 +74,7 @@ defmodule AprsmeWeb.WeatherUnits do
|
|||
@doc """
|
||||
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
|
||||
{pressure, "hPa"}
|
||||
end
|
||||
|
|
@ -79,6 +84,12 @@ defmodule AprsmeWeb.WeatherUnits do
|
|||
@doc """
|
||||
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
|
||||
case unit_system(locale) do
|
||||
:imperial ->
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue