Files
wanderer/lib/wanderer_app_web/api_router/route_spec.ex
2025-07-16 23:17:47 +00:00

107 lines
2.9 KiB
Elixir

defmodule WandererAppWeb.ApiRouter.RouteSpec do
@moduledoc """
Structured specification for API routes.
This module defines the RouteSpec struct that contains all metadata
needed for routing, feature detection, and API documentation.
"""
@type verb :: :get | :post | :put | :patch | :delete
@type segment :: String.t() | atom()
@type t :: %__MODULE__{
verb: verb(),
path: [segment()],
controller: module(),
action: atom(),
features: [String.t()],
metadata: map()
}
@enforce_keys [:verb, :path, :controller, :action]
defstruct [
:verb,
:path,
:controller,
:action,
features: [],
metadata: %{}
]
@doc """
Creates a new RouteSpec with default metadata.
"""
def new(verb, path, controller, action, opts \\ []) do
features = Keyword.get(opts, :features, [])
metadata = Keyword.get(opts, :metadata, %{})
%__MODULE__{
verb: verb,
path: path,
controller: controller,
action: action,
features: features,
metadata: Map.merge(default_metadata(), metadata)
}
end
@doc """
Returns default metadata for routes.
"""
def default_metadata do
%{
auth_required: false,
rate_limit: :standard,
success_status: 200,
content_type: "application/vnd.api+json",
description: ""
}
end
@doc """
Validates a RouteSpec for completeness and correctness.
"""
def validate(%__MODULE__{} = route_spec) do
with :ok <- validate_verb(route_spec.verb),
:ok <- validate_path(route_spec.path),
:ok <- validate_controller(route_spec.controller),
:ok <- validate_action(route_spec.action),
:ok <- validate_features(route_spec.features),
:ok <- validate_metadata(route_spec.metadata) do
{:ok, route_spec}
end
end
defp validate_verb(verb) when verb in [:get, :post, :put, :patch, :delete], do: :ok
defp validate_verb(verb), do: {:error, {:invalid_verb, verb}}
defp validate_path(path) when is_list(path) do
if Enum.all?(path, &(is_binary(&1) or is_atom(&1))) do
:ok
else
{:error, {:invalid_path_segments, path}}
end
end
defp validate_path(path), do: {:error, {:invalid_path, path}}
defp validate_controller(controller) when is_atom(controller), do: :ok
defp validate_controller(controller), do: {:error, {:invalid_controller, controller}}
defp validate_action(action) when is_atom(action), do: :ok
defp validate_action(action), do: {:error, {:invalid_action, action}}
defp validate_features(features) when is_list(features) do
if Enum.all?(features, &is_binary/1) do
:ok
else
{:error, {:invalid_features, features}}
end
end
defp validate_features(features), do: {:error, {:invalid_features, features}}
defp validate_metadata(metadata) when is_map(metadata), do: :ok
defp validate_metadata(metadata), do: {:error, {:invalid_metadata, metadata}}
end