Documentation
¶
Overview ¶
Package goenax is a code-as-source-of-truth registry for HTTP endpoints.
An endpoint is declared once — typed request/response plus metadata — and the registry projects that declaration into OpenAPI (and, downstream, Postman and TypeScript). Because the request/response schemas are taken from real Go types, the contract cannot lie about the shapes the handler binds and returns.
The package is deliberately self-contained (standard library only) so it can later be lifted into its own module/repo with no untangling. See DESIGN.md.
Index ¶
- type Endpoint
- type ErrorSpec
- type ExtraResponse
- type Info
- type Option
- func Also(status int, desc string) Option
- func AlsoJSON[T any](status int, desc string) Option
- func Compose(opts ...Option) Option
- func DependsOn(ids ...string) Option
- func Description(s string) Option
- func Error(status int, code, message string) Option
- func HTML() Option
- func Header(name string, required bool, desc string) Option
- func NoContent(status int) Option
- func Owner(s string) Option
- func PathParam(name, desc string) Option
- func Query(name string, required bool, desc string) Option
- func Request[T any]() Option
- func RespHeader(name, desc string) Option
- func Response[T any](status int) Option
- func Secured() Option
- func Summary(s string) Option
- func Tags(tags ...string) Option
- type Param
- type Registry
- func (r *Registry) Add(e Endpoint)
- func (r *Registry) Coverage(actual []Route) (undocumented, unmounted []Route)
- func (r *Registry) Endpoints() []Endpoint
- func (r *Registry) Lookup(method, path string) (Endpoint, bool)
- func (r *Registry) OpenAPI(info Info) ([]byte, error)
- func (r *Registry) Validate() []ValidationError
- func (r *Registry) ValidateResponse(method, path string, body []byte) error
- type ResponseHeader
- type Route
- type Schema
- type Server
- type ValidationError
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Endpoint ¶
type Endpoint struct {
Method string
Path string
Summary string
Desc string
Owner string
Tags []string
Request reflect.Type // nil = no request body
Response reflect.Type // nil = empty response (e.g. 204)
Status int // success status code (200/201/204)
Secured bool // true = requires a bearer session
SuccessHTML bool // success renders text/html rather than JSON
Params []Param
RespHeaders []ResponseHeader // headers on the success response
Also []ExtraResponse
Errors []ErrorSpec
DependsOn []string // IDs of endpoints that must run first (QA scenarios)
}
Endpoint is the full contract of a single route: how it is called plus the metadata our policy gate requires. Request and Response hold the Go types of the bodies (nil when there is none); their JSON schemas are derived from those types in a later phase.
type ErrorSpec ¶
type ErrorSpec struct {
Status int
Code string // short machine-readable slug, e.g. "validation"
Message string // human-readable example message
}
ErrorSpec is one documented non-2xx outcome of an endpoint.
type ExtraResponse ¶
ExtraResponse is an additional documented response (e.g. a 202 alternative to the primary success). Type is optional — nil means the response has no body.
type Option ¶
type Option func(*Endpoint)
Option mutates an Endpoint during Define.
This is the functional-options pattern: each helper below returns a small function that sets one field, and Define applies them in order. It keeps declarations readable and lets us add new metadata later without changing every call site.
func Also ¶
Also documents an additional response status alongside the primary success, without a body.
func AlsoJSON ¶
AlsoJSON documents an additional response status that carries a JSON body of type T (e.g. a 202 with a { "status": … } payload).
func Compose ¶
Compose bundles several options into one. It lets a middleware ship its own documentation — e.g. a rate limiter that contributes a 429 response, or a captcha that contributes a header and its rejection — so routes opt into the behaviour and its docs together.
func HTML ¶
func HTML() Option
HTML marks the success response as text/html (e.g. email-link landing pages).
func PathParam ¶
PathParam documents a path parameter (always required, must appear as {name} in the route path).
func Request ¶
Request declares the request body type, written as goenax.Request[fooRequest]().
It is generic so the caller names the type instead of passing a value. reflect.TypeFor[T]() (Go 1.22+) captures that type at compile time, so the schema is bound to the exact struct the handler binds — no annotations, and the compiler guarantees the type exists.
func RespHeader ¶
RespHeader documents a header returned on the success response.
func Response ¶
Response declares the success body type and status, e.g. goenax.Response[sessionResponse](200).
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
func (*Registry) Coverage ¶
Coverage compares the routes actually registered on a router with the endpoints declared in the registry. A shared route table makes the two match by construction; Coverage catches the case a table can't — a route mounted (or removed) directly, out of band. It returns:
- undocumented: on the router but not in the registry (missing from the spec)
- unmounted: in the registry but never registered (a dead spec entry)
Pass the router's routes via an adapter helper, e.g. echoadapter.Routes(e) or ginadapter.Routes(engine). (net/http's ServeMux exposes no route list, so it has no helper — feed it a Route slice you build yourself.)
func (*Registry) OpenAPI ¶
OpenAPI projects the registry into an OpenAPI 3.1 document and returns it as indented JSON. Map keys (paths, methods, status codes) serialise in a stable order, so the output is deterministic and safe to diff / drift-check.
func (*Registry) Validate ¶
func (r *Registry) Validate() []ValidationError
Validate checks every endpoint against the policy and structural rules, and returns one ValidationError per offending endpoint (nil = all good).
Policy (kept small, not bureaucratic): every endpoint needs a summary, description, owner and tag; mutating methods need at least one error response. Structural: no two endpoints share a method+path, and path {tokens} match the declared PathParam names. Request bodies and the success status are not checked (action POSTs carry no body; the status is auto-defaulted).
func (*Registry) ValidateResponse ¶
ValidateResponse checks that a JSON response body conforms to the schema of an endpoint's declared Response type. It closes the gap between what an endpoint *promises* (Response[T]) and what the handler actually returns: call it from a handler test on the real response, and a shape that has drifted from the contract fails the test.
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
if err := reg.ValidateResponse("POST", "/api/login", rec.Body.Bytes()); err != nil {
t.Fatalf("response breaks its contract: %v", err)
}
It checks the declared shape (types, required properties, enums) and allows unknown extra properties, so a forward-compatible addition doesn't fail a test.
type ResponseHeader ¶
ResponseHeader documents a header returned on the success response.
type Schema ¶
type Schema struct {
Ref string `json:"$ref,omitempty"`
Type string `json:"type,omitempty"`
Format string `json:"format,omitempty"`
Enum []string `json:"enum,omitempty"`
Example any `json:"example,omitempty"`
MinLength *int `json:"minLength,omitempty"`
MaxLength *int `json:"maxLength,omitempty"`
Minimum *float64 `json:"minimum,omitempty"`
Maximum *float64 `json:"maximum,omitempty"`
Properties map[string]*Schema `json:"properties,omitempty"`
Items *Schema `json:"items,omitempty"`
AdditionalProperties *Schema `json:"additionalProperties,omitempty"`
Required []string `json:"required,omitempty"`
}
Schema is a JSON Schema node — the shared shape behind an endpoint's request and response bodies. It maps directly onto the schema object OpenAPI 3.1 uses. When Ref is set the node is only a reference into components/schemas.
type ValidationError ¶
type ValidationError struct {
Endpoint string // "POST /api/contact"
Problems []string // ["description", "owner", "duplicate route"]
}
ValidationError lists everything wrong with one endpoint — missing metadata, a duplicate route, or a path/parameter mismatch.
func (ValidationError) Error ¶
func (e ValidationError) Error() string
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
adapter
|
|
|
echo
Package echoadapter mounts routes on an Echo router while recording each route's contract in an goenax.Registry — one declaration, two outputs: a live route and a spec entry.
|
Package echoadapter mounts routes on an Echo router while recording each route's contract in an goenax.Registry — one declaration, two outputs: a live route and a spec entry. |
|
gin
Package ginadapter mounts routes on a Gin router while recording each route's contract in an goenax.Registry — one declaration, two outputs.
|
Package ginadapter mounts routes on a Gin router while recording each route's contract in an goenax.Registry — one declaration, two outputs. |
|
nethttp
Package nethttpadapter mounts routes on a net/http ServeMux while recording each route's contract in an goenax.Registry — one declaration, two outputs.
|
Package nethttpadapter mounts routes on a net/http ServeMux while recording each route's contract in an goenax.Registry — one declaration, two outputs. |