andreashasse

andreashasse

PhoenixSpectral - FastAPI-style type-driven APIs for Phoenix

Hi all,

I’ve been working on PhoenixSpectral, a library that makes Phoenix controller @spec annotations drive both OpenAPI generation and runtime request/response validation — no separate schema definitions.

The main design departure from standard Phoenix is the action signature. Instead of action(conn, params), controllers receive five explicit arguments — (conn, path_args, query_params, headers, body):

@spec update(Plug.Conn.t(), %{id: integer()}, %{notify: boolean()}, %{"x-api-key": String.t()}, User.t()) ::
        {200, %{}, User.t()} | {404, %{}, Error.t()}
def update(_conn, %{id: id}, %{notify: notify}, %{"x-api-key": _key}, body) do
  case MyApp.Users.update(id, body, notify: notify) do
    {:ok, user} -> {200, %{}, user}
    :not_found  -> {404, %{}, %Error{message: "User not found"}}
  end
end

By the time update/5 is called, the incoming HTTP request has already been validated and decoded against the typespec: id is an integer() (not a string), body is a fully populated %User{} struct, etc. Invalid requests are rejected with a 400 before reaching the function. Each source is kept separate because the body is a typed struct (which can’t be merged into a flat map), and the OpenAPI generator needs to know whether a field comes from path, query, header, or body to emit a correct spec. Actions return a {status, headers, body} 3-tuple (union return types produce multiple OpenAPI response entries automatically) or a Plug.Conn directly for streaming and file responses. The repo also contains an example app.

Before stabilising the API I’d love to hear your feedback. Eg, Does five separate arguments feel ergonomic? Does {status, headers, body} as a return type feel right?

Thanks for any thoughts!

Where Next?

Trending in RFCs Top

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
type1fool
I just stumbled on a newly redesigned elixir-lang.org. :tada: It looks like @Software_Mansion did the work, and I think it is generally a...
New
akoutmos
@hugobarauna and I (Alex Koutmos) have been hard at work on writing a book on Nerves that takes you from simply blinking LEDs to building...
New

We're in Beta

About us Mission Statement