mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-13 03:06:15 +00:00
107 lines
2.9 KiB
Elixir
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
|