feat: serve API docs at /docs/api
- /docs/api → LiveView rendering README.md as HTML - /docs/api/openapi.yaml → raw OpenAPI 3.1 spec - /docs/api/README.md → raw markdown source
This commit is contained in:
parent
c6d2c48264
commit
c56b55d5af
5 changed files with 99 additions and 0 deletions
35
lib/microwaveprop_web/controllers/api_docs_controller.ex
Normal file
35
lib/microwaveprop_web/controllers/api_docs_controller.ex
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
defmodule MicrowavepropWeb.ApiDocsController do
|
||||
@moduledoc """
|
||||
Serves the static `docs/api/` artifacts:
|
||||
|
||||
* `GET /docs/api/openapi.yaml` — OpenAPI 3.1 spec as `application/yaml`.
|
||||
* `GET /docs/api/README.md` — raw markdown source (for agents that
|
||||
prefer markdown over the rendered LiveView page).
|
||||
|
||||
The human-facing rendered docs live at `/docs/api` via
|
||||
`MicrowavepropWeb.ApiDocsLive`.
|
||||
"""
|
||||
use MicrowavepropWeb, :controller
|
||||
|
||||
@external_resource "docs/api/openapi.yaml"
|
||||
@external_resource "docs/api/README.md"
|
||||
|
||||
@openapi_yaml File.read!("docs/api/openapi.yaml")
|
||||
@readme_markdown File.read!("docs/api/README.md")
|
||||
|
||||
@spec openapi_yaml(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
def openapi_yaml(conn, _params) do
|
||||
conn
|
||||
|> put_resp_content_type("application/yaml", "utf-8")
|
||||
|> put_resp_header("cache-control", "public, max-age=3600")
|
||||
|> send_resp(200, @openapi_yaml)
|
||||
end
|
||||
|
||||
@spec readme_markdown(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
def readme_markdown(conn, _params) do
|
||||
conn
|
||||
|> put_resp_content_type("text/markdown", "utf-8")
|
||||
|> put_resp_header("cache-control", "public, max-age=3600")
|
||||
|> send_resp(200, @readme_markdown)
|
||||
end
|
||||
end
|
||||
23
lib/microwaveprop_web/live/api_docs_live.ex
Normal file
23
lib/microwaveprop_web/live/api_docs_live.ex
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
defmodule MicrowavepropWeb.ApiDocsLive do
|
||||
@moduledoc "Renders `docs/api/README.md` as HTML at `/docs/api`."
|
||||
use MicrowavepropWeb, :live_view
|
||||
|
||||
@external_resource "docs/api/README.md"
|
||||
@docs_html "docs/api/README.md" |> File.read!() |> Microwaveprop.Markdown.to_html!()
|
||||
|
||||
@impl true
|
||||
def mount(_params, _session, socket) do
|
||||
{:ok, assign(socket, page_title: "API Documentation", content: @docs_html)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<Layouts.app flash={@flash} current_scope={@current_scope}>
|
||||
<div class="markdown-content">
|
||||
{raw(@content)}
|
||||
</div>
|
||||
</Layouts.app>
|
||||
"""
|
||||
end
|
||||
end
|
||||
|
|
@ -212,7 +212,13 @@ defmodule MicrowavepropWeb.Router do
|
|||
get "/weather/cells", WeatherTileController, :cells
|
||||
get "/scores/cells", ScoresController, :cells
|
||||
|
||||
# Static API doc artifacts. Outside the live_session so the
|
||||
# raw-format endpoints don't get the LiveView root layout.
|
||||
get "/docs/api/openapi.yaml", ApiDocsController, :openapi_yaml
|
||||
get "/docs/api/README.md", ApiDocsController, :readme_markdown
|
||||
|
||||
live_session :public, on_mount: [{MicrowavepropWeb.UserAuth, :default}] do
|
||||
live "/docs/api", ApiDocsLive
|
||||
live "/submit", SubmitLive
|
||||
live "/imports/:id", ImportLive
|
||||
live "/map", MapLive
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
defmodule MicrowavepropWeb.ApiDocsControllerTest do
|
||||
use MicrowavepropWeb.ConnCase, async: true
|
||||
|
||||
describe "GET /docs/api/openapi.yaml" do
|
||||
test "serves the OpenAPI spec as application/yaml", %{conn: conn} do
|
||||
conn = get(conn, ~p"/docs/api/openapi.yaml")
|
||||
assert conn.status == 200
|
||||
assert get_resp_header(conn, "content-type") == ["application/yaml; charset=utf-8"]
|
||||
assert conn.resp_body =~ "openapi: 3.1.0"
|
||||
assert conn.resp_body =~ "/api/v1"
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /docs/api/README.md" do
|
||||
test "serves the README markdown source", %{conn: conn} do
|
||||
conn = get(conn, ~p"/docs/api/README.md")
|
||||
assert conn.status == 200
|
||||
assert get_resp_header(conn, "content-type") == ["text/markdown; charset=utf-8"]
|
||||
assert conn.resp_body =~ "# Microwaveprop REST API"
|
||||
end
|
||||
end
|
||||
end
|
||||
13
test/microwaveprop_web/live/api_docs_live_test.exs
Normal file
13
test/microwaveprop_web/live/api_docs_live_test.exs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
defmodule MicrowavepropWeb.ApiDocsLiveTest do
|
||||
use MicrowavepropWeb.ConnCase, async: true
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
|
||||
test "renders the API reference at /docs/api", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/docs/api")
|
||||
|
||||
assert html =~ "Microwaveprop REST API"
|
||||
assert html =~ "/api/v1"
|
||||
assert html =~ "POST /auth/tokens"
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue