ApiDocs

com.worxbend.wolfram.ApiDocs
object ApiDocs

The OpenAPI document and the Swagger UI that renders it.

Generated from the endpoint values, never written by hand. A checked-in spec is a second statement of the contract, and the two disagree the first time an error output is added — silently, because nothing compiles YAML. Here the document is a projection of the same Endpoints values the server routes on, so "the docs are wrong" is not a state this service can be in.

This replaced a hand-rolled walk of the Tapir endpoint ADT. That version could describe paths, methods, parameters and status codes, but it emitted permissive placeholders where the body schemas belong, because deriving a JSON Schema from Schema[T] is the hard half and tapir-openapi-docs is the thing that does it. The placeholder version documented everything except the part a client generator needs most.

Both JSON and YAML are served. They are the same document; code generators and curl | jq want the first, humans and git diff want the second, and rendering both from one model costs one line.

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
ApiDocs.type

Members list

Value members

Concrete methods

def json(endpoints: List[AnyEndpoint] = ...): Json

The document as JSON — what /openapi.json serves and what the tests assert on.

The document as JSON — what /openapi.json serves and what the tests assert on.

Attributes

def openApi(endpoints: List[AnyEndpoint] = ...): OpenAPI

The document, derived from the public endpoints.

The document, derived from the public endpoints.

Attributes

def routes: List[ServerEndpoint[Any, Future]]

Swagger UI plus the two documents, as server endpoints on this service's own port.

Swagger UI plus the two documents, as server endpoints on this service's own port.

Mounted through the same Vert.x interpreter as the API rather than on a second listener: the UI's "Try it out" button issues a same-origin request, so there is no CORS configuration to get wrong and no second port to expose in compose. The trade is that the docs share the API's lifecycle — if the service is down, so are its docs, which for a document generated from the running build is the honest behaviour anyway.

Attributes

def yaml(endpoints: List[AnyEndpoint] = ...): String

The document as YAML — what /openapi.yaml serves.

The document as YAML — what /openapi.yaml serves.

Attributes

Concrete fields

val ApiVersion: String

The version of the API contract, which is not the build version.

The version of the API contract, which is not the build version.

ADR-adjacent decision worth stating: SERVICE_VERSION changes on every deploy, and putting it here would make every generated client look out of date after a patch release that changed nothing a client can see. This value moves when the contract moves.

Attributes

val DocsPath: String

Where the UI and the YAML document are mounted. /docs is the human entry point; the JSON rendering is served at the conventional root path by AdminRoutes.OpenApiPath, not from here.

Where the UI and the YAML document are mounted. /docs is the human entry point; the JSON rendering is served at the conventional root path by AdminRoutes.OpenApiPath, not from here.

Attributes

val Title: String
val YamlPath: String