Documentation
¶
Overview ¶
Package openapi auto-generates an OpenAPI 3.1 specification from the framework's typed registry and serves it (plus Swagger UI) from a nexus app. Zero hand-written spec, always in sync with the running app.
Wire it up next to your other modules. The plugin reads from the client manifest (which the framework already builds from reflection) and emits an OpenAPI document on demand. No build step, no codegen invocation.
import "github.com/paulmanoni/nexus/extension/openapi"
nexus.Run(
nexus.Config{
Server: nexus.ServerConfig{Addr: ":8080"},
Client: client.Config{Enabled: true}, // the plugin reads from here
},
openapi.Plugin(openapi.Config{
Title: "Pet Shop API",
Version: "1.0.0",
Description: "Catalog + orders + waitlist",
}),
// ... rest of the app
)
What the plugin exposes:
GET /__nexus/openapi/spec.json — the spec (JSON, primary) GET /__nexus/openapi/spec.yaml — same spec, YAML encoding GET /__nexus/openapi/ui — Swagger UI HTML, loads spec.json
And, when Config.PublicRoot is true (the default), additional routes at the API root so customer-facing tooling finds them at the conventional paths:
GET /openapi.json GET /api-docs — Swagger UI
Customers run `openapi-generator-cli` against /openapi.json and get a typed client SDK in any language. The same spec drives Postman collections, Schemathesis fuzzing, Spectral linting.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Plugin ¶
Plugin wires the OpenAPI generator into the app's plugin chain. Generation runs lazily at request time so a freshly-added endpoint shows up in /spec.json without a restart (the live registry is the source). On a stable production app the overhead is one map walk per request; for higher throughput we could cache and invalidate on registry.OnChange, but that's premature for the v1 size.
Types ¶
type Components ¶
type Components struct {
Schemas map[string]*Schema `json:"schemas,omitempty"`
SecuritySchemes map[string]*SecurityScheme `json:"securitySchemes,omitempty"`
}
Components houses reusable schemas + security definitions. The nexus generator only populates Schemas (from registry.Refs) and SecuritySchemes (from auth.ExtractorInfo).
type Config ¶
type Config struct {
// Title is the API name that appears in info.title. Defaults to
// "Nexus API" if empty.
Title string
// Version is info.version. Defaults to "1.0.0". Bump this when
// your wire contract changes — Spectral diff in CI compares
// successive versions of the same spec.
Version string
// Description is info.description. Markdown is permitted (the
// OpenAPI spec allows CommonMark there).
Description string
// Contact is info.contact. Optional; empty means "omitted from
// spec". Most clients ignore this; Stoplight + Postman surface
// it on the docs page.
Contact *Contact
// License is info.license. Optional; same notes as Contact.
License *License
// Servers is the list of base URLs the spec advertises under
// servers[]. When empty, the plugin synthesizes a single entry
// from the request host at serve time so a local dev hit to
// /__nexus/openapi/spec.json still sees "http://localhost:8080"
// without configuration.
Servers []Server
// PublicRoot, when nil or *true, also mounts /openapi.json and
// /api-docs at the API root in addition to the namespaced
// /__nexus/openapi/ paths. Disable only if your gateway already
// hosts these paths and you want the framework to stay out of
// their way.
PublicRoot *bool
// ExcludeAdmin, when nil or *true, omits framework-owned
// /__nexus/* paths from the spec. Customers shouldn't see admin
// routes in the SDK they generate. Flip to *false for an
// admin-facing variant.
ExcludeAdmin *bool
// IncludeGraphQL, when *true, also emits a /graphql operation
// for GraphQL endpoints. Defaults to false because OpenAPI
// describes REST poorly when the underlying transport is
// GraphQL — most teams expose the GraphQL schema separately
// via /graphql?schema or graphql-introspection. The flag is
// here for the rare case where a customer must consume both
// transports through one spec.
IncludeGraphQL *bool
// SwaggerUIVersion pins the CDN version of swagger-ui-dist
// loaded by the /ui page. Default "5.20.1". Override only when
// pinning to an audited release.
SwaggerUIVersion string
}
Config controls the metadata block of the generated spec and a handful of behavior toggles. Everything else (paths, operations, schemas) is derived from the live registry.
type Contact ¶
type Contact struct {
Name string `json:"name,omitempty"`
URL string `json:"url,omitempty"`
Email string `json:"email,omitempty"`
}
Contact / License / Server mirror their OpenAPI counterparts. Repeated here so callers can configure them in Go without dragging in an OpenAPI library as a public dep.
type Document ¶
type Document struct {
OpenAPI string `json:"openapi"`
Info Info `json:"info"`
Servers []Server `json:"servers,omitempty"`
Paths map[string]PathItem `json:"paths"`
Components *Components `json:"components,omitempty"`
Tags []Tag `json:"tags,omitempty"`
Security []SecurityRequirement `json:"security,omitempty"`
}
Document is the root OpenAPI 3.1 object. The order of fields follows the spec's document outline so the serialized output is readable end-to-end.
type Info ¶
type Info struct {
Title string `json:"title"`
Version string `json:"version"`
Description string `json:"description,omitempty"`
TermsOfService string `json:"termsOfService,omitempty"`
Contact *Contact `json:"contact,omitempty"`
License *License `json:"license,omitempty"`
}
Info populates the spec's info block. Required: Title, Version.
type MediaType ¶
type MediaType struct {
Schema *Schema `json:"schema,omitempty"`
}
MediaType carries the schema for one MIME type within a request body or response. The framework writes application/json only; other media types stay open for plugins that wrap multipart, NDJSON, or CSV transports.
type Operation ¶
type Operation struct {
Tags []string `json:"tags,omitempty"`
Summary string `json:"summary,omitempty"`
Description string `json:"description,omitempty"`
OperationID string `json:"operationId,omitempty"`
Parameters []Parameter `json:"parameters,omitempty"`
RequestBody *RequestBody `json:"requestBody,omitempty"`
Responses map[string]Response `json:"responses"`
Security []SecurityRequirement `json:"security,omitempty"`
Deprecated bool `json:"deprecated,omitempty"`
}
Operation describes one method on a path.
type Parameter ¶
type Parameter struct {
Name string `json:"name"`
In string `json:"in"` // "path" | "query" | "header" | "cookie"
Description string `json:"description,omitempty"`
Required bool `json:"required,omitempty"`
Schema *Schema `json:"schema,omitempty"`
Deprecated bool `json:"deprecated,omitempty"`
}
Parameter is a path/query/header/cookie parameter. The framework populates these from path placeholders (":id" → in=path) and from known query-style Args struct fields.
type PathItem ¶
type PathItem struct {
Summary string `json:"summary,omitempty"`
Description string `json:"description,omitempty"`
Get *Operation `json:"get,omitempty"`
Put *Operation `json:"put,omitempty"`
Post *Operation `json:"post,omitempty"`
Delete *Operation `json:"delete,omitempty"`
Patch *Operation `json:"patch,omitempty"`
Head *Operation `json:"head,omitempty"`
Options *Operation `json:"options,omitempty"`
Parameters []Parameter `json:"parameters,omitempty"`
}
PathItem holds the per-method operations for a single URL pattern. OpenAPI calls these "Path Item Objects".
type RequestBody ¶
type RequestBody struct {
Description string `json:"description,omitempty"`
Required bool `json:"required,omitempty"`
Content map[string]MediaType `json:"content"`
}
RequestBody describes a request payload. For nexus the framework always uses application/json; we may add multipart later for file uploads.
type Response ¶
type Response struct {
Description string `json:"description"`
Content map[string]MediaType `json:"content,omitempty"`
}
Response is one entry in the responses map of an Operation. The framework's typed return type populates Content["application/json"].
type Schema ¶
type Schema struct {
Ref string `json:"$ref,omitempty"`
Type string `json:"type,omitempty"` // "string" | "integer" | "number" | "boolean" | "array" | "object"
Format string `json:"format,omitempty"` // "date-time" | "byte" | ...
Description string `json:"description,omitempty"`
Items *Schema `json:"items,omitempty"` // when Type == "array"
Properties map[string]*Schema `json:"properties,omitempty"` // when Type == "object"
Required []string `json:"required,omitempty"` // when Type == "object"
Enum []any `json:"enum,omitempty"`
Nullable bool `json:"nullable,omitempty"` // OpenAPI 3.1 prefers `type: ["string", "null"]` — kept for tooling compat
AdditionalProperties *Schema `json:"additionalProperties,omitempty"` // when Type == "object" (map)
Example any `json:"example,omitempty"`
Deprecated bool `json:"deprecated,omitempty"`
}
Schema is the JSON-Schema-derived subset OpenAPI 3.1 uses for describing types. The framework converts each registry.TypeRef to a Schema; named refs land in Components.Schemas and Schema.Ref points at them.
type SecurityRequirement ¶
SecurityRequirement is the per-operation "this op requires X" map. Each key is a SecurityScheme name; the slice value is a list of scopes (always empty for non-OAuth2 schemes, but the spec demands the array shape).
type SecurityScheme ¶
type SecurityScheme struct {
Type string `json:"type"` // "http" | "apiKey" | "oauth2" | "openIdConnect"
Scheme string `json:"scheme,omitempty"` // "bearer" for type=http
BearerFormat string `json:"bearerFormat,omitempty"` // "JWT" hint when applicable
In string `json:"in,omitempty"` // "header" | "query" | "cookie" — for type=apiKey
Name string `json:"name,omitempty"` // header/cookie/query param name — for type=apiKey
Description string `json:"description,omitempty"`
}
SecurityScheme describes one auth mechanism. nexus generates a "bearer" entry when auth.Bearer is in use, "apiKey" for API key extractors, "cookie" for cookie-based auth.