Documentation
¶
Overview ¶
Package goai generates OpenAPI 3.0.3 documents from a gone-framework route tree without forcing handlers into a special shape.
goai is intentionally additive to ghttp: nothing in this package mutates existing route or handler types. Operations registered via goai.Register receive fully fleshed-out request/response schemas; the rest appear with auto-discovered paths and method shapes only.
Optional handler/acceptance interfaces ¶
Implement these to refine the generated spec without touching goai's API:
- SpecProvider — supplies one Spec applied to every HTTP method on the handler. Use for the common case where all methods share metadata.
- <Method>SpecProvider — per-Go-method Spec providers (IndexSpecProvider, GetSpecProvider, CreateSpecProvider, PostSpecProvider, PatchSpecProvider, PutSpecProvider, DeleteSpecProvider, OptionsSpecProvider, TraceSpecProvider). Each method name mirrors the handler's Go method on the struct (Get → GOAIGetSpec, Post → GOAIPostSpec, ...). Per-method providers override SpecProvider when both are implemented.
- SecurityProvider — declares required security scheme + scopes.
- PathParamInjector — declares which path parameters this acceptance injects into the request (e.g. {organization_id}).
- ProfileScope — declares which output profiles this node belongs to (e.g. mgmt-only).
Quick start ¶
From a project's bootstrap:
goai.Register(myhandler.HandlerMe, "Get",
nil, (*myhandler.MeGetResponse)(nil),
goai.WithTag("User"),
goai.WithDescription("Returns the current authenticated user."))
To serve the spec at runtime:
route.SetEndpoint("/openapi.yaml", goai.Handler(&route))
To generate a spec file from a CLI binary:
goai.RunCLI(factory, goai.RunOptions{
Title: "My API",
Version: "1.0.0",
DefaultOutput: "docs/openapi.yaml",
})
OpenAPI 3.0.3 coverage ¶
All Object types defined by the OpenAPI 3.0.3 specification are modeled in openapi.go — including License, ServerVariable, ExternalDocumentation, Encoding, Example, Link, Callback, Discriminator, and XML. Specification Extensions ("x-*" fields) are supported on every applicable object via the inline `Extensions map[string]any` field.
Examples ¶
Each subdirectory under `examples/` is a runnable program demonstrating one feature: quickstart, customschema, docstring, full, runtime, merge.
See README.md for the full reference.
Index ¶
- Constants
- func BuiltinClassify(c OperationCandidate) []string
- func CountOperations(doc *Document) int
- func EmitYAML(doc *Document) ([]byte, error)
- func Handler(route ghttp.RouteEntriesProvider, opts ...RuntimeOption) ghttp.HandlerTask
- func LookupAll(handler ghttp.HandlerTask) map[string]Entry
- func Merge3Way(generated, existing, overrides []byte) ([]byte, error)
- func Register(handler ghttp.HandlerTask, method string, req any, resp any, opts ...Option)
- func Reset()
- func RunCLI(factory RouteFactory, opts RunOptions)
- func RunCLIFromConfig(configPath string, factory RouteFactory, opts ...RunFromConfigOption)
- type AcceptanceSecurityRule
- type BuildOptions
- type Callback
- type Classifier
- type Components
- type Config
- type ConfigProfile
- type Contact
- type CreateSpecProvider
- type DeleteSpecProvider
- type Discriminator
- type Document
- type EmissionAwareParamInjector
- type EmissionContext
- type Encoding
- type Entry
- type Example
- type ExternalDocumentation
- type GetSpecProvider
- type Header
- type HeaderDef
- type Hidden
- type IndexSpecProvider
- type Info
- type ItemIDProvider
- type License
- type Link
- type LintReport
- type MediaType
- type MethodAwareSecurityProvider
- type OAuthFlow
- type OAuthFlows
- type Operation
- type OperationCandidate
- type OperationDoc
- type OperationDocExtractor
- type OperationEndpoint
- type Option
- func WithCallback(name string, callback Callback) Option
- func WithDeprecated() Option
- func WithDescription(description string) Option
- func WithExample(mediaType string, example any) Option
- func WithExampleObject(mediaType, name string, ex *Example) Option
- func WithExternalDocs(url, description string) Option
- func WithHeader(h HeaderDef) Option
- func WithOperationID(id string) Option
- func WithOperationServer(server Server) Option
- func WithParam(p PathParam) Option
- func WithRequestDescription(description string) Option
- func WithRequestMediaType(mediaType string) Option
- func WithResponse(status string, description string, opts ...ResponseOption) Option
- func WithSecurity(scheme string, scopes ...string) Option
- func WithSuccessDescription(description string) Option
- func WithSummary(summary string) Option
- func WithTag(tags ...string) Option
- type OptionsSpecProvider
- type Parameter
- type PatchSpecProvider
- type PathAwareParamInjector
- type PathItem
- type PathParam
- type PathParamInjector
- type PathTagRule
- type PostSpecProvider
- type Profile
- type ProfileScope
- type PutSpecProvider
- type RequestBody
- type Response
- type ResponseOption
- func WithResponseExample(example any) ResponseOption
- func WithResponseExampleObject(name string, example *Example) ResponseOption
- func WithResponseHeader(h HeaderDef) ResponseOption
- func WithResponseMediaType(mediaType string) ResponseOption
- func WithResponseSchema(t reflect.Type) ResponseOption
- func WithResponseSchemaPrebuilt(schema *Schema) ResponseOption
- type ResponseSpec
- type RouteFactory
- type RunFromConfigOption
- type RunOptions
- type RuntimeOption
- type Schema
- type SchemaNameProvider
- type SecurityProvider
- type SecurityRef
- type SecurityScheme
- type Selector
- type Server
- type ServerVariable
- type Spec
- func (s Spec) Callbacks() map[string]Callback
- func (s Spec) Deprecated() bool
- func (s Spec) Description() string
- func (s Spec) Examples() map[string]any
- func (s Spec) ExternalDocs() *ExternalDocumentation
- func (s Spec) ExtraHeaders() []HeaderDef
- func (s Spec) ExtraParams() []PathParam
- func (s Spec) MultiExamples() map[string]map[string]*Example
- func (s Spec) OperationID() string
- func (s Spec) OperationServers() []Server
- func (s Spec) RequestDescription() string
- func (s Spec) RequestMediaType() string
- func (s Spec) Responses() map[string]*ResponseSpec
- func (s Spec) Security() []SecurityRef
- func (s Spec) SuccessDescription() string
- func (s Spec) Summary() string
- func (s Spec) Tags() []string
- type SpecProvider
- type Tag
- type TraceSpecProvider
- type XML
Constants ¶
const Version = "0.2.0"
Version reports the goai package version. It is bumped manually on every release of github.com/yetiz-org/gone that contains visible goai changes.
Variables ¶
This section is empty.
Functions ¶
func BuiltinClassify ¶
func BuiltinClassify(c OperationCandidate) []string
BuiltinClassify is the no-op fallback classifier: every candidate lands in the "all" profile. Projects that need profile splits (public / internal / admin / etc.) supply their own classifier through BuildOptions, since the path conventions for those splits are project-specific.
func CountOperations ¶
CountOperations returns the total number of HTTP operations declared in the document across all paths and methods. Useful for CLI diagnostics and snapshot tests.
func EmitYAML ¶
EmitYAML serialises a Document into deterministic YAML bytes with two space indentation. Stable output is mandatory because both file diff tools and Merge3Way depend on byte-identical re-emission for unchanged inputs.
func Handler ¶
func Handler(route ghttp.RouteEntriesProvider, opts ...RuntimeOption) ghttp.HandlerTask
Handler returns a ghttp.HandlerTask that responds to GET with an OpenAPI YAML document derived from the supplied route tree. POST/PATCH/ other verbs return NotImplemented.
The handler caches the emitted bytes when WithRuntimeCacheTTL is > 0. Caching is invalidated lazily on TTL expiry.
func LookupAll ¶
func LookupAll(handler ghttp.HandlerTask) map[string]Entry
LookupAll returns every Entry registered for handler, indexed by method. The returned map is a copy and safe to iterate.
func Merge3Way ¶
Merge3Way overlays an auto-generated OpenAPI document onto a hand-tuned existing document, preserving the hand-tuned content as the source of truth.
Merge policy:
- Top-level scalars/maps (openapi, info, servers, security) are taken verbatim from `existing` when present. The hand-tuned document is the canonical author of prose and metadata.
- `tags`: union — every tag in `existing` is kept in its original order, then any tag in `generated` whose name is missing from `existing` is appended.
- `paths`: per-path union — every path in `existing` is kept verbatim (including hand-curated descriptions, parameters, examples, $refs). Any path present in `generated` but missing from `existing` is appended at the end of the paths map, so routes discovered in source code surface in the spec automatically without disturbing the hand-tuned prose for existing routes.
- `components.*`: per-name union for every sub-map defined by OpenAPI 3.0.3 — schemas, responses, parameters, examples, requestBodies, headers, securitySchemes, links, callbacks. Existing entries always win; generated entries fill gaps only. Hand-tuned schema $refs always remain wired correctly.
When `existing` is empty, the generated bytes are returned unchanged so the caller does not have to special-case "no baseline yet".
func Register ¶
Register associates a Spec, request type and response type with a (handler, method) pair. method is normalised to upper-case. req and resp may be nil; if non-nil, they should be a typed-nil pointer (e.g. (*MyResp)(nil)) so that reflect can extract the element type regardless of whether the value is the zero value of a struct.
Calling Register more than once for the same handler+method overwrites the existing entry; this lets generated init() files coexist with hand-written project-level overrides.
func RunCLI ¶
func RunCLI(factory RouteFactory, opts RunOptions)
RunCLI is the canonical entry point for project-side `cmd/goaispec` (or equivalent) binaries. It parses CLI flags, walks the supplied route tree, builds an OpenAPI 3.0.3 document, and writes the yaml to the resolved output destination.
Typical usage:
func main() {
os.Setenv("APP_DEBUG", "true")
goai.RunCLI(
func() ghttp.RouteEntriesProvider { return handlers.NewAppRoute() },
goai.RunOptions{
Title: "My API",
Version: "1.0.0",
Servers: []goai.Server{{URL: "https://api.example.com"}},
DefaultOutput: "docs/openapi.yaml",
SecuritySchemes: map[string]*goai.SecurityScheme{
"OAuth2": {Type: "oauth2", Flows: ...},
},
},
)
}
RunCLI does NOT panic on failure; it writes a diagnostic to Stderr and invokes Exit(1). Callers that want non-fatal behaviour should call Walk, Build and EmitYAML directly.
func RunCLIFromConfig ¶
func RunCLIFromConfig(configPath string, factory RouteFactory, opts ...RunFromConfigOption)
RunCLIFromConfig is the multi-output entry point. It loads goai.yaml from configPath, walks the route tree once, and emits one yaml per declared profile in the config (or a single yaml when no profiles are declared). The hand-tuned base spec, when configured, is merged into every emitted yaml.
configPath may point at either the goai.yaml file directly or the directory containing it.
Types ¶
type AcceptanceSecurityRule ¶
type AcceptanceSecurityRule struct {
// TypeName is matched against the unqualified Go type name of each
// acceptance in the chain. Match is case-sensitive substring; the first
// acceptance whose type name contains TypeName wins.
TypeName string
Scheme string
Scopes []string
}
AcceptanceSecurityRule maps an acceptance type-name match to a security scheme reference.
type BuildOptions ¶
type BuildOptions struct {
Title string
Description string
Version string
TermsOfService string
Contact *Contact
License *License
Servers []Server
Tags []Tag
GlobalSecurity []map[string][]string
// ExternalDocs populates the top-level Document.ExternalDocs.
ExternalDocs *ExternalDocumentation
// Classifier returns the set of profile names a candidate belongs to
// when the candidate did not declare any via ProfileScope. nil means
// "use BuiltinClassify".
Classifier func(c OperationCandidate) []string
// TagSecurityClassifier provides default tags + security refs when a
// candidate has no explicit Spec entry. nil means "use DefaultClassifier".
TagSecurityClassifier *Classifier
// SuppressEmptySchemas, when true, omits the application/json content
// block on responses where the registered response type is nil. This
// produces tighter yaml for operations without registered response types.
SuppressEmptySchemas bool
// OperationDocExtractor, when non-nil, is consulted as a fallback
// source for operation-level OpenAPI metadata. Explicit Spec values,
// route-derived parameters, generated schemas, and acceptance-derived
// security always win; docstring content fills gaps.
//
// Use DefaultOperationDocExtractor() to enable the built-in AST-based
// implementation. nil disables the fallback.
OperationDocExtractor OperationDocExtractor
}
BuildOptions tunes Build behaviour.
type Callback ¶
Callback is a map of expressions (e.g. "{$request.body#/callbackUrl}") to PathItem values. Per the OpenAPI 3.0.3 spec, the keys are "Runtime Expression" strings; x-* extension keys may appear at the same level alongside expression keys. yaml.v3 cannot carry two inline maps on one struct, so Callback is modeled as a plain map[string]*PathItem and any extension keys live alongside the expressions in this same map.
type Classifier ¶
type Classifier struct {
// PathTagRules maps a path-prefix glob to a tag name. The first matching
// rule wins; "**" matches anything.
PathTagRules []PathTagRule
// AcceptanceSecurityRules maps an acceptance type-name suffix to a
// (scheme, scopes) pair. The first matching rule per acceptance wins.
// Type-name suffix is matched case-sensitively against the unqualified
// Go type name of the acceptance value.
AcceptanceSecurityRules []AcceptanceSecurityRule
}
Classifier turns a route path and its acceptance chain into reasonable default tag + security values. Builder consults it ONLY when a candidate has no explicit Spec entry from SpecProvider / goai.Register / SecurityProvider.
Classifier is the zero-config fallback: it lets a project bootstrap a spec before any handler implements SpecProvider. Once handlers self-declare metadata, project-level Classifier rules become noise — prefer the per-handler interfaces and let the rule list decay to whatever truly belongs at the framework level (static assets, well-known routes, etc.).
func DefaultClassifier ¶
func DefaultClassifier() *Classifier
DefaultClassifier returns an empty classifier. Projects supply their own PathTagRules and AcceptanceSecurityRules through BuildOptions; goai itself has no opinion on what tags or security schemes a route should map to.
func (*Classifier) ClassifySecurity ¶
func (c *Classifier) ClassifySecurity(acceptances []ghttp.Acceptance) []SecurityRef
ClassifySecurity returns the security refs derived from the acceptance chain. An acceptance that already implements SecurityProvider is honoured as-is; for all others, the type-name rules are consulted.
func (*Classifier) ClassifyTag ¶
func (c *Classifier) ClassifyTag(path string) string
ClassifyTag returns the first matching tag for path, or "" if none match.
type Components ¶
type Components struct {
Schemas map[string]*Schema `yaml:"schemas,omitempty"`
Responses map[string]*Response `yaml:"responses,omitempty"`
Parameters map[string]*Parameter `yaml:"parameters,omitempty"`
Examples map[string]*Example `yaml:"examples,omitempty"`
RequestBodies map[string]*RequestBody `yaml:"requestBodies,omitempty"`
Headers map[string]*Header `yaml:"headers,omitempty"`
SecuritySchemes map[string]*SecurityScheme `yaml:"securitySchemes,omitempty"`
Links map[string]*Link `yaml:"links,omitempty"`
Callbacks map[string]Callback `yaml:"callbacks,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
Components is the reusable definitions block.
func NewComponents ¶
func NewComponents() *Components
NewComponents returns a Components value with all submaps preallocated.
type Config ¶
type Config struct {
Title string `yaml:"title,omitempty"`
Description string `yaml:"description,omitempty"`
Version string `yaml:"version,omitempty"`
TermsOfService string `yaml:"termsOfService,omitempty"`
Contact *Contact `yaml:"contact,omitempty"`
License *License `yaml:"license,omitempty"`
ExternalDocs *ExternalDocumentation `yaml:"externalDocs,omitempty"`
Servers []Server `yaml:"servers,omitempty"`
Tags []Tag `yaml:"tags,omitempty"`
GlobalSecurity []map[string][]string `yaml:"security,omitempty"`
SecuritySchemes map[string]*SecurityScheme `yaml:"securitySchemes,omitempty"`
// DefaultOutput is the single-output target used when neither Profiles
// nor Output declare anything. Empty falls back to "openapi.generated.yaml".
DefaultOutput string `yaml:"defaultOutput,omitempty"`
// BaseSpecPath, when set, enables three-way merge with the hand-tuned
// base yaml.
BaseSpecPath string `yaml:"baseSpecPath,omitempty"`
// RestrictToBaseSpecPaths constrains the generator to paths already
// declared in the base spec.
RestrictToBaseSpecPaths bool `yaml:"restrictToBaseSpecPaths,omitempty"`
// ExcludePaths is the framework-level path blocklist (static assets,
// well-known framework routes, …). Per-handler exclusion belongs on the
// handler itself via the Hidden interface.
ExcludePaths []string `yaml:"excludePaths,omitempty"`
// Profiles is keyed by profile name and contains include/exclude rules.
Profiles map[string]ConfigProfile `yaml:"profiles,omitempty"`
// Output describes where to write each profile's yaml. Keyed by profile
// name; value is a relative path from the config file's directory.
Output map[string]string `yaml:"output,omitempty"`
// EnableDocstringExtraction toggles source-level Go doc-comment
// extraction for operation-level OpenAPI metadata. When true,
// RunCLIFromConfig wires DefaultOperationDocExtractorWithBuildTags()
// into the build pipeline, which reads only namespaced handler
// `@goai.*` directives. Ordinary Go comments remain source-only.
// Explicit Spec values, route-derived parameters, generated schemas, and
// acceptance-derived security continue to win; docstring extraction
// only fills gaps.
EnableDocstringExtraction bool `yaml:"enableDocstringExtraction,omitempty"`
// DocstringBuildTags are passed to DefaultOperationDocExtractorWithBuildTags
// when EnableDocstringExtraction is true. Use this when handler docs or
// schema structs live in files guarded by custom Go build tags.
DocstringBuildTags []string `yaml:"docstringBuildTags,omitempty"`
}
Config is the project-level goai.yaml schema. Every field has a sensible default so projects can opt in incrementally.
func DefaultConfig ¶
func DefaultConfig() *Config
DefaultConfig returns a Config populated with profile buckets keyed off ProfileScope declarations. Selector.Profiles matches the names produced by handler / acceptance GOAIProfileScope so a handler that declares `[]string{"public"}` lands in the "public" output bucket.
func LoadConfig ¶
LoadConfig reads goai.yaml from dir and returns a parsed Config. When the file is absent, a Config populated with builtin defaults is returned and err is nil — projects can run goai before authoring a config.
func (*Config) BuildProfile ¶
BuildProfile materialises a Profile struct from one entry in c.Profiles.
func (*Config) ProfileNames ¶
ProfileNames returns the configured profile names in deterministic order.
func (*Config) ToBuildOptions ¶
func (c *Config) ToBuildOptions() BuildOptions
ToBuildOptions projects the Config onto a BuildOptions, used by the multi-output driver where one Walk feeds many Build calls.
func (*Config) ToRunOptions ¶
func (c *Config) ToRunOptions() RunOptions
ToRunOptions projects the Config onto a RunOptions for single-output generation. The Profiles / Output maps are NOT projected — multi-output drivers (RunCLIFromConfig) consult those directly.
type ConfigProfile ¶
type ConfigProfile struct {
Include Selector `yaml:"include,omitempty"`
Exclude Selector `yaml:"exclude,omitempty"`
}
ConfigProfile is the on-disk shape of one profile's selector pair.
type Contact ¶
type Contact struct {
Name string `yaml:"name,omitempty"`
URL string `yaml:"url,omitempty"`
Email string `yaml:"email,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
Contact is the optional API contact block.
type CreateSpecProvider ¶
type CreateSpecProvider interface {
GOAICreateSpec() Spec
}
CreateSpecProvider supplies the Spec for the handler's Create() method (HTTP POST that creates a collection member).
type DeleteSpecProvider ¶
type DeleteSpecProvider interface {
GOAIDeleteSpec() Spec
}
DeleteSpecProvider supplies the Spec for the handler's Delete() method (HTTP DELETE).
type Discriminator ¶
type Discriminator struct {
PropertyName string `yaml:"propertyName"`
Mapping map[string]string `yaml:"mapping,omitempty"`
}
Discriminator supports oneOf/anyOf polymorphism by naming the property whose value selects the concrete sub-schema.
type Document ¶
type Document struct {
OpenAPI string `yaml:"openapi"`
Info Info `yaml:"info"`
Servers []Server `yaml:"servers,omitempty"`
Tags []Tag `yaml:"tags,omitempty"`
Paths map[string]*PathItem `yaml:"paths"`
Components *Components `yaml:"components,omitempty"`
Security []map[string][]string `yaml:"security,omitempty"`
ExternalDocs *ExternalDocumentation `yaml:"externalDocs,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
Document is the root of an OpenAPI 3.0.3 specification.
func Build ¶
func Build(candidates []OperationCandidate, profile *Profile, opts BuildOptions) *Document
Build assembles a single OpenAPI Document from candidates that match the supplied profile. profile may be nil, in which case all candidates pass.
type EmissionAwareParamInjector ¶
type EmissionAwareParamInjector interface {
InjectedParamsForEmission(routePath string, ctx EmissionContext) []PathParam
}
EmissionAwareParamInjector lets an injector tailor PathParam output per (route, emission) pair. This is required for routes whose base spec uses different placeholder shapes for collection-level Index vs item-level Get / Patch / Delete emissions — e.g. base spec entries of /<action> for Index alongside /{id}/<action> for item ops, where a single PathParam slice cannot satisfy both shapes.
When an acceptance implements EmissionAwareParamInjector, the walker calls InjectedParamsForEmission once per emission and ignores the other path-injection interfaces. Implementors typically delegate to PathAwareParamInjector or PathParamInjector when emission context is not needed.
type EmissionContext ¶
EmissionContext carries the per-emission information passed to EmissionAwareParamInjector. ItemLevel mirrors the walker's classification: false for Index / Create-style collection emissions, true for Get / Patch / Put / Delete-style item emissions where the walker normally appends a trailing /{id} placeholder.
type Encoding ¶
type Encoding struct {
ContentType string `yaml:"contentType,omitempty"`
Headers map[string]*Header `yaml:"headers,omitempty"`
Style string `yaml:"style,omitempty"`
Explode *bool `yaml:"explode,omitempty"`
AllowReserved bool `yaml:"allowReserved,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
Encoding describes a single multipart/form-encoded property.
type Entry ¶
type Entry struct {
Handler ghttp.HandlerTask
Method string // upper-case HTTP method
ReqType reflect.Type
RespType reflect.Type
Spec Spec
}
Entry captures a single registration: which handler+method, and which Go types describe its request/response bodies. req or resp may be nil when the operation takes no body or returns no body.
type Example ¶
type Example struct {
Summary string `yaml:"summary,omitempty"`
Description string `yaml:"description,omitempty"`
Value any `yaml:"value,omitempty"`
ExternalValue string `yaml:"externalValue,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
Example is the OpenAPI Example Object. Use Value for inline JSON-y examples, or ExternalValue when the example lives in a separate file.
type ExternalDocumentation ¶
type ExternalDocumentation struct {
Description string `yaml:"description,omitempty"`
URL string `yaml:"url"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
ExternalDocumentation references additional external documentation.
type GetSpecProvider ¶
type GetSpecProvider interface {
GOAIGetSpec() Spec
}
GetSpecProvider supplies the Spec for the handler's Get() method (HTTP GET — either an item read on a collection-style handler or a singleton fetch).
type Header ¶
type Header struct {
Description string `yaml:"description,omitempty"`
Required bool `yaml:"required,omitempty"`
Deprecated bool `yaml:"deprecated,omitempty"`
AllowEmptyValue bool `yaml:"allowEmptyValue,omitempty"`
Style string `yaml:"style,omitempty"`
Explode *bool `yaml:"explode,omitempty"`
AllowReserved bool `yaml:"allowReserved,omitempty"`
Schema *Schema `yaml:"schema,omitempty"`
Example any `yaml:"example,omitempty"`
Examples map[string]*Example `yaml:"examples,omitempty"`
Content map[string]*MediaType `yaml:"content,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
Header is the response header object. Per OpenAPI 3.0.3 it is a Parameter without `name` and `in`.
type HeaderDef ¶
type HeaderDef struct {
Name string
In string // "header" | "response"
Description string
Required bool
Example string
}
HeaderDef declares an extra response or request header that goai should document on the operation, on top of whatever the request body or query params already produce.
type Hidden ¶
type Hidden interface {
Hidden() bool
}
Hidden lets a handler declare it should not appear in any generated spec. Returning true drops every method on the handler from Walker output before Build sees them. Use for framework-internal handlers (static asset servers, health probes that should not be public-documented, etc.).
type IndexSpecProvider ¶
type IndexSpecProvider interface {
GOAIIndexSpec() Spec
}
IndexSpecProvider supplies the Spec for the handler's Index() method (a collection-style HTTP GET that returns a list).
type Info ¶
type Info struct {
Title string `yaml:"title"`
Description string `yaml:"description,omitempty"`
TermsOfService string `yaml:"termsOfService,omitempty"`
Contact *Contact `yaml:"contact,omitempty"`
License *License `yaml:"license,omitempty"`
Version string `yaml:"version"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
Info carries metadata about the API.
type ItemIDProvider ¶
type ItemIDProvider interface {
GOAIItemIDName() string
}
ItemIDProvider lets a handler override the path-parameter name the walker uses when auto-appending an item-level segment to a collection-style handler. The default name is `<last route segment>_id` (e.g. /albums → /albums/{albums_id}); implement this interface to choose a different name. Returning an empty string falls back to the default.
type License ¶
type License struct {
Name string `yaml:"name"`
URL string `yaml:"url,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
License is the optional API license block. Required field: Name.
type Link ¶
type Link struct {
OperationRef string `yaml:"operationRef,omitempty"`
OperationID string `yaml:"operationId,omitempty"`
Parameters map[string]any `yaml:"parameters,omitempty"`
RequestBody any `yaml:"requestBody,omitempty"`
Description string `yaml:"description,omitempty"`
Server *Server `yaml:"server,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
Link Object — describes a possible design-time link from a response to another operation. OperationRef and OperationID are mutually exclusive.
type LintReport ¶
LintReport is the structured outcome of a LintYAML pass. Errors carries human-readable messages; Paths and Operations are headline counts that callers (CI badges, status lines) can surface verbatim.
func LintYAML ¶
func LintYAML(body []byte) (*LintReport, error)
LintYAML performs a lightweight structural check on an OpenAPI 3.0.x yaml document. The check is intentionally tighter than "did it parse" but looser than a full Spectral / Redocly validation:
- The document MUST parse as yaml.
- The root MUST be a mapping.
- openapi MUST be present and start with "3.".
- info MUST be present, be a mapping, and carry a non-empty title.
- paths MUST be present and contain at least one entry.
- Every entry under paths MUST be a mapping.
The intent is to catch the common "shipped a broken yaml" failure modes in CI without standing up a full validator pipeline. Returns a non-nil LintReport even when errors exist; the caller decides whether to fail.
type MediaType ¶
type MediaType struct {
Schema *Schema `yaml:"schema,omitempty"`
Example any `yaml:"example,omitempty"`
Examples map[string]*Example `yaml:"examples,omitempty"`
Encoding map[string]*Encoding `yaml:"encoding,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
MediaType describes one entry under content (per media-type key).
type MethodAwareSecurityProvider ¶
type MethodAwareSecurityProvider interface {
SecurityRequirementFor(method string) (scheme string, scopes []string)
}
MethodAwareSecurityProvider is the per-HTTP-method variant of SecurityProvider. Returning ("", nil) for a method means "this acceptance does not contribute a security requirement on that method" — useful when the acceptance bypasses authentication for one method (e.g. RFC 7662 token introspection at POST /tokeninfo with bearer-less form auth).
method is the upper-case HTTP method ("GET", "POST", ...). Implementing MethodAwareSecurityProvider does NOT also require implementing SecurityProvider; the walker calls the method-aware variant first and only falls back to the static provider when the acceptance does not implement it.
type OAuthFlow ¶
type OAuthFlow struct {
AuthorizationURL string `yaml:"authorizationUrl,omitempty"`
TokenURL string `yaml:"tokenUrl,omitempty"`
RefreshURL string `yaml:"refreshUrl,omitempty"`
Scopes map[string]string `yaml:"scopes,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
OAuthFlow is one specific OAuth2 flow.
type OAuthFlows ¶
type OAuthFlows struct {
Implicit *OAuthFlow `yaml:"implicit,omitempty"`
Password *OAuthFlow `yaml:"password,omitempty"`
ClientCredentials *OAuthFlow `yaml:"clientCredentials,omitempty"`
AuthorizationCode *OAuthFlow `yaml:"authorizationCode,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
OAuthFlows aggregates all flow types under a SecurityScheme.
type Operation ¶
type Operation struct {
Tags []string `yaml:"tags,omitempty"`
Summary string `yaml:"summary,omitempty"`
Description string `yaml:"description,omitempty"`
ExternalDocs *ExternalDocumentation `yaml:"externalDocs,omitempty"`
OperationID string `yaml:"operationId,omitempty"`
Parameters []*Parameter `yaml:"parameters,omitempty"`
RequestBody *RequestBody `yaml:"requestBody,omitempty"`
Responses map[string]*Response `yaml:"responses,omitempty"`
Callbacks map[string]Callback `yaml:"callbacks,omitempty"`
Deprecated bool `yaml:"deprecated,omitempty"`
// Security is a pointer so the encoder can distinguish three states:
// nil → inherit document-level Security (default).
// &[] → explicit "no security required"; overrides document
// default with an empty array per OpenAPI 3.0.3.
// &[{...}, ..] → operation-level requirement set; overrides document
// default with the supplied alternatives.
Security *[]map[string][]string `yaml:"security,omitempty"`
Servers []Server `yaml:"servers,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
Operation describes a single HTTP operation.
type OperationCandidate ¶
type OperationCandidate struct {
Path string
Method string
Handler ghttp.HandlerTask
Acceptances []ghttp.Acceptance
// HandlerMethod is the Go method name (Index/Get/Post/Patch/Put/Delete/
// Options/Create) that produced this candidate. Builder uses it together
// with Method to choose registry lookup keys and operationId components.
HandlerMethod string
// PathParams collected from upstream PathParamInjectors plus any leaf id
// the walker auto-appends (item-level operations get an "id" path param).
PathParams []PathParam
// SecurityRefs collected from upstream SecurityProviders.
SecurityRefs []SecurityRef
// SecurityExplicitlyEmpty is true when at least one acceptance
// implements MethodAwareSecurityProvider AND its generic
// SecurityProvider would have advertised a scheme, but its method-aware
// variant returned ("", nil) for this candidate's HTTP method. The
// builder uses it to emit `security: []` so that the operation
// overrides any document-level GlobalSecurity inheritance.
SecurityExplicitlyEmpty bool
// Profiles aggregated from ProfileScope-implementing nodes; empty means
// "let the classifier decide".
Profiles []string
}
OperationCandidate is one candidate operation extracted from the route tree. Builder later filters by profile and combines with registry entries to produce the final OpenAPI operation.
func Walk ¶
func Walk(route ghttp.RouteEntriesProvider) []OperationCandidate
Walk traverses the route tree from the supplied RouteEntriesProvider and returns one OperationCandidate per (path, supported HTTP method).
Detection is done by reflecting on the handler value: a handler-method is considered "implemented" when its function pointer differs from the corresponding default on ghttp.DefaultHTTPHandlerTask.
gone routes follow a REST-style convention where one handler can serve both a collection and an item endpoint. The walker mirrors that convention by emitting two distinct paths when both styles are present:
- Index → bare path (collection list)
- Create → bare path (collection create)
- Post → bare path (collection / leaf action)
- Get → bare path + "/{id}" when the handler is collection-style; otherwise the bare path (singleton-style)
- Patch / Put / Delete → bare path + "/{id}" when collection-style; otherwise the bare path
- Options → bare path
"Collection-style" means the handler overrides Index AND at least one of Get / Patch / Put / Delete. Handlers that only override item-level methods (a singleton resource exposing Get only, for example) are treated as singleton-style and emitted on the bare path.
type OperationDoc ¶ added in v1.15.1
type OperationDoc struct {
Endpoint OperationEndpoint
Operation Operation
Schemas map[string]*Schema
SchemaPackages map[string]string
}
OperationDoc is the doc-comment metadata for one handler method.
type OperationDocExtractor ¶ added in v1.15.1
type OperationDocExtractor func(handler any, methodName string) (*OperationDoc, bool)
OperationDocExtractor returns OpenAPI operation metadata extracted from a handler method's source-code doc comment. The default implementation only reads namespaced `@goai.*` directives, keeping surrounding Go comments private to source readers.
func DefaultOperationDocExtractor ¶ added in v1.15.1
func DefaultOperationDocExtractor() OperationDocExtractor
DefaultOperationDocExtractor returns the built-in extractor that locates each method's source file via runtime.FuncForPC, parses it with go/ast, and pulls the doc comment off the matching FuncDecl. Parsed files are cached, so repeat lookups are cheap.
Parse strategy:
- The file path is derived from runtime.FuncForPC; when the binary was built from a different module path or the source is not on disk (e.g. embedded compilation), the extractor returns no operation.
- Only `@goai.*` directives are public OpenAPI input. Text before, between, or after directives is considered source-only documentation.
- Complex OpenAPI objects can be supplied as compact JSON values on namespaced directives such as `@goai.callback` and `schema=...`.
The returned extractor is safe for concurrent use.
func DefaultOperationDocExtractorWithBuildTags ¶ added in v1.15.1
func DefaultOperationDocExtractorWithBuildTags(tags ...string) OperationDocExtractor
DefaultOperationDocExtractorWithBuildTags returns the built-in docstring extractor using the supplied build tags when scanning sibling files for handler type docs and schema structs. Use this when the goai generator is compiled with custom build tags and schema/helper types live behind the same tags in separate files.
type OperationEndpoint ¶ added in v1.15.1
OperationEndpoint is the optional endpoint declaration parsed from `@goai.endpoint METHOD /path`. It documents which HTTP operation the comment describes; the route walker remains authoritative.
type Option ¶
type Option func(*Spec)
Option mutates a Spec during NewSpec or Register.
func WithCallback ¶
WithCallback registers a callback under the operation's callbacks map. `name` is the local identifier; `callback` is a map of runtime expressions (e.g. "{$request.body#/callbackUrl}") to PathItems.
func WithDeprecated ¶
func WithDeprecated() Option
WithDeprecated marks the operation as deprecated.
func WithDescription ¶
WithDescription sets the long-form operation description.
func WithExample ¶
WithExample attaches an example value for a given media type (e.g. "application/json").
func WithExampleObject ¶
WithExampleObject attaches a named Example Object under a media type. Use this when you need richer metadata (summary, description, externalValue) than WithExample provides.
func WithExternalDocs ¶
WithExternalDocs attaches an operation-level externalDocs entry.
func WithHeader ¶
WithHeader documents an extra header. Use multiple times for multiple headers.
func WithOperationID ¶
WithOperationID sets the operationId field. When omitted, builder synthesises it from package + handler + method.
func WithOperationServer ¶
WithOperationServer adds a server entry that overrides the document / path-level servers for this single operation.
func WithParam ¶
WithParam documents an extra parameter (path/query/header) that goai cannot detect from the route tree alone.
func WithRequestDescription ¶ added in v1.15.1
WithRequestDescription sets the operation's request body description. Renders under requestBody.description in the emitted yaml.
func WithRequestMediaType ¶
WithRequestMediaType overrides the default "application/json" media type used when goai auto-builds the request body schema from a registered request type. Use for operations that consume e.g. multipart/form-data or application/x-www-form-urlencoded.
func WithResponse ¶ added in v1.15.1
func WithResponse(status string, description string, opts ...ResponseOption) Option
WithResponse declares an operation response under the given HTTP status code. Use multiple times for distinct status codes (e.g. "400", "404", "default"). description should be a short human-readable explanation of what the status code means in the operation's context. Additional content (schema, examples, headers) is layered on via ResponseOption.
Calling WithResponse with the operation's conventional success status (matching successStatus(httpMethod)) updates that response's description in the same way as WithSuccessDescription, but lets the caller also attach a custom schema or examples — useful for handlers that document a response shape distinct from the registered Go response type.
func WithSecurity ¶
WithSecurity appends a SecurityRef. Multiple calls combine as logical OR at the operation level (per OpenAPI semantics).
func WithSuccessDescription ¶ added in v1.15.1
WithSuccessDescription overrides the method default response description emitted under the conventional success status code (200 / 201 / 204). Use this when the success response merits a richer description than the generic default.
func WithSummary ¶
WithSummary sets the operation summary (one-line title shown by Swagger UI).
type OptionsSpecProvider ¶
type OptionsSpecProvider interface {
GOAIOptionsSpec() Spec
}
OptionsSpecProvider supplies the Spec for the handler's Options() method (HTTP OPTIONS).
type Parameter ¶
type Parameter struct {
Name string `yaml:"name"`
In string `yaml:"in"`
Description string `yaml:"description,omitempty"`
Required bool `yaml:"required,omitempty"`
Deprecated bool `yaml:"deprecated,omitempty"`
AllowEmptyValue bool `yaml:"allowEmptyValue,omitempty"`
Style string `yaml:"style,omitempty"`
Explode *bool `yaml:"explode,omitempty"`
AllowReserved bool `yaml:"allowReserved,omitempty"`
Schema *Schema `yaml:"schema,omitempty"`
Example any `yaml:"example,omitempty"`
Examples map[string]*Example `yaml:"examples,omitempty"`
Content map[string]*MediaType `yaml:"content,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
Parameter is a path/query/header/cookie parameter, or a top-level entry inside Components.Parameters. Either Schema or Content (but not both) describes the value's shape; for simple parameters use Schema, for complex media-typed ones use Content.
type PatchSpecProvider ¶
type PatchSpecProvider interface {
GOAIPatchSpec() Spec
}
PatchSpecProvider supplies the Spec for the handler's Patch() method (HTTP PATCH).
type PathAwareParamInjector ¶
PathAwareParamInjector is a path-aware specialization of PathParamInjector. When an injector is reused under multiple route subtrees that follow different path-parameter conventions (e.g. /api/v1/teams/{teams_id}/... vs /admin/v1/teams/{id}/...), the bare InjectedParams contract is too coarse — it cannot distinguish action endpoints under the same anchor segment from sub-resource endpoints. The walker calls InjectedParamsFor with the literal route path so the injector can return a tailored slice (or nil, to suppress injection entirely for that route).
When an acceptance implements both PathParamInjector and PathAwareParamInjector, the walker calls InjectedParamsFor and ignores InjectedParams. Implementors typically delegate to the bare method when no path-specific tailoring is needed.
type PathItem ¶
type PathItem struct {
Ref string `yaml:"$ref,omitempty"`
Summary string `yaml:"summary,omitempty"`
Description string `yaml:"description,omitempty"`
Get *Operation `yaml:"get,omitempty"`
Put *Operation `yaml:"put,omitempty"`
Post *Operation `yaml:"post,omitempty"`
Delete *Operation `yaml:"delete,omitempty"`
Options *Operation `yaml:"options,omitempty"`
Head *Operation `yaml:"head,omitempty"`
Patch *Operation `yaml:"patch,omitempty"`
Trace *Operation `yaml:"trace,omitempty"`
Servers []Server `yaml:"servers,omitempty"`
Parameters []*Parameter `yaml:"parameters,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
PathItem holds the operations defined for a single path.
func (*PathItem) SetOperation ¶
SetOperation assigns op under the slot for the given upper-case method. Unknown methods are silently ignored.
type PathParam ¶
type PathParam struct {
Name string
In string // typically "path"; "query" / "header" allowed
Style string // OpenAPI parameter style; default "simple"
Description string
AnchorAfter string
Example string
Required bool
IsItemIdentifier bool
}
PathParam describes a path-level parameter injected by an upstream acceptance/minortask. AnchorAfter, when non-empty, indicates the path segment after which this parameter should be inserted; an empty AnchorAfter means "append to the end of the inherited path".
IsItemIdentifier signals that this placeholder is the item-level entity identifier for the operation. The walker's item-level emission auto-appends /{<lastSegment>_id} to a path that does not already end in a placeholder, on the assumption that the last segment is a collection that needs an item suffix. Routes whose last segment is a verb / action (e.g. /admin/v1/teams/{teams_id}/activate) opt out of that auto-suffix because the item identifier is the segment BEFORE the verb, not after it. Setting IsItemIdentifier=true on the {teams_id} param tells the walker the item id is already declared.
type PathParamInjector ¶
type PathParamInjector interface {
InjectedParams() []PathParam
}
PathParamInjector lets an acceptance / minortask declare which path parameters it injects into params. Builder uses this to expand the route node's static path with {param} placeholders.
type PathTagRule ¶
PathTagRule maps one path glob to a tag.
Glob syntax:
- "*" matches a single path segment.
- "**" matches any number of segments (including zero).
- Literal segments match exactly.
type PostSpecProvider ¶
type PostSpecProvider interface {
GOAIPostSpec() Spec
}
PostSpecProvider supplies the Spec for the handler's Post() method (HTTP POST — either a bare-path action or an item-level action depending on whether the handler also defines Create()).
type Profile ¶
Profile is one named output bucket. Operations whose path/package/tag matches Include and does not match Exclude are emitted under this profile's output file.
func (*Profile) Matches ¶
func (p *Profile) Matches(c OperationCandidate, declaredProfiles, operationTags []string) bool
Matches returns true when the candidate should appear in this profile's output. declaredProfiles supplies the values produced by ProfileScope or the BuiltinClassify result, so explicit profile declarations are respected. operationTags supplies the OpenAPI tags attached to this operation, so tag-based selectors work as the README documents.
type ProfileScope ¶
type ProfileScope interface {
GOAIProfileScope() []string
}
ProfileScope lets a handler or acceptance declare which output profiles the operation belongs to. Returning an empty slice means "no preference" and lets the builder's classifier decide. The method name mirrors the interface name so its purpose is obvious at the call site.
type PutSpecProvider ¶
type PutSpecProvider interface {
GOAIPutSpec() Spec
}
PutSpecProvider supplies the Spec for the handler's Put() method (HTTP PUT).
type RequestBody ¶
type RequestBody struct {
Description string `yaml:"description,omitempty"`
Content map[string]*MediaType `yaml:"content,omitempty"`
Required bool `yaml:"required,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
RequestBody describes an operation request body.
type Response ¶
type Response struct {
Description string `yaml:"description"`
Headers map[string]*Header `yaml:"headers,omitempty"`
Content map[string]*MediaType `yaml:"content,omitempty"`
Links map[string]*Link `yaml:"links,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
Response describes a single HTTP status code response.
type ResponseOption ¶ added in v1.15.1
type ResponseOption func(*ResponseSpec)
ResponseOption mutates a ResponseSpec built by WithResponse.
func WithResponseExample ¶ added in v1.15.1
func WithResponseExample(example any) ResponseOption
WithResponseExample attaches a single inline example to the response content block.
func WithResponseExampleObject ¶ added in v1.15.1
func WithResponseExampleObject(name string, example *Example) ResponseOption
WithResponseExampleObject attaches a named Example Object to the response content block. Use multiple times for distinct named examples.
func WithResponseHeader ¶ added in v1.15.1
func WithResponseHeader(h HeaderDef) ResponseOption
WithResponseHeader documents a response header attached to this status code's response. Use multiple times for distinct headers.
func WithResponseMediaType ¶ added in v1.15.1
func WithResponseMediaType(mediaType string) ResponseOption
WithResponseMediaType overrides the response content media type (default "application/json").
func WithResponseSchema ¶ added in v1.15.1
func WithResponseSchema(t reflect.Type) ResponseOption
WithResponseSchema attaches a Go type whose synthesised schema becomes the response body. Use for non-success responses whose body shape is not captured by the registered (handler, method) response type — e.g. an error envelope on a 400 / 404 branch. Pointer types are automatically unwrapped so that *T behaves like T.
func WithResponseSchemaPrebuilt ¶ added in v1.15.1
func WithResponseSchemaPrebuilt(schema *Schema) ResponseOption
WithResponseSchemaPrebuilt attaches a pre-built Schema verbatim under the response content block. Use for $ref-based reuse or when the schema is hand-authored.
type ResponseSpec ¶ added in v1.15.1
type ResponseSpec struct {
// Description is rendered verbatim under responses.<status>.description.
Description string
// SchemaType, when non-nil, drives schema synthesis from a Go type
// (the same path used for request bodies and successful response
// bodies registered via goai.Register). Mutually exclusive with
// Schema; Schema wins when both are set.
SchemaType reflect.Type
// Schema, when non-nil, is used directly without further synthesis.
// Use this for hand-tuned schemas, $ref-based reuse, or to attach
// schemas the schema builder cannot derive (e.g. raw JSON Schema
// objects).
Schema *Schema
// MediaType overrides the response content media type. Empty falls
// back to "application/json" when Schema or SchemaType is set; when
// both Schema and SchemaType are nil the response carries no
// content block regardless of MediaType.
MediaType string
// Example is a single inline example. Use Examples when richer
// metadata (named summaries / descriptions / external values) is
// needed.
Example any
// Examples is the per-name Example map. Mutually compatible with
// Example — yaml encoders emit both fields.
Examples map[string]*Example
// Headers documents response headers attached to this status code.
Headers []HeaderDef
}
ResponseSpec describes a single status-code response declared on an operation via WithResponse. All fields are optional; Description is the only one builder treats as required by OpenAPI semantics. When empty, success responses use the method default, recognised HTTP status codes use net/http.StatusText, "default" uses "Default response", and unknown status keys fall back to "OK" so the emitted yaml stays valid.
type RouteFactory ¶
type RouteFactory func() ghttp.RouteEntriesProvider
RouteFactory builds the project's route tree on demand. RunCLI calls it after ghttp.SetSkipHandlerRegister(true) so route construction must not depend on real DB/cache/queue connectivity.
type RunFromConfigOption ¶
type RunFromConfigOption func(*runFromConfigOpts)
RunFromConfigOption tunes RunCLIFromConfig.
func WithClassifier ¶
func WithClassifier(c *Classifier) RunFromConfigOption
WithClassifier injects a fallback Classifier for handlers that do not implement SpecProvider or SecurityProvider.
type RunOptions ¶
type RunOptions struct {
// Title is the OpenAPI info.title default. CLI flag -title overrides.
Title string
// Description is the OpenAPI info.description.
Description string
// Version is the OpenAPI info.version default. CLI flag -version overrides.
Version string
// TermsOfService is the OpenAPI info.termsOfService URL.
TermsOfService string
// Contact populates Document.Info.Contact.
Contact *Contact
// License populates Document.Info.License (e.g. {Name: "MIT"}).
License *License
// ExternalDocs populates the top-level Document.ExternalDocs.
ExternalDocs *ExternalDocumentation
// Servers populates Document.Servers verbatim.
Servers []Server
// Tags populates Document.Tags verbatim. Hand-listing them controls the
// final tag ordering in the emitted yaml.
Tags []Tag
// GlobalSecurity is propagated as Document.Security (the top-level
// requirement applied to every operation that does not declare its own).
GlobalSecurity []map[string][]string
// TagSecurityClassifier provides per-path tag and per-acceptance security
// fallbacks. nil → goai.DefaultClassifier() inside Build.
TagSecurityClassifier *Classifier
// SecuritySchemes are merged into Document.Components.SecuritySchemes
// after Build. Wins over any classifier-injected scheme reference that
// happens to share a name.
SecuritySchemes map[string]*SecurityScheme
// DefaultOutput is the -o flag default. Must be a writable file path or
// "-" for stdout. Empty string falls back to "openapi.generated.yaml".
DefaultOutput string
// BaseSpec, when non-nil, is the hand-tuned OpenAPI yaml that the
// auto-generated structure is merged onto. The hand-tuned content wins
// for everything that is already present (info, tags, paths,
// components.schemas, components.securitySchemes); auto-discovered
// entries fill gaps. Use this when the project keeps a curated
// `docs/openapi/openapi.yaml` as the canonical source of truth and
// wants the generator to surface routes absent from it.
//
// Mutually exclusive with BaseSpecPath; BaseSpec wins when both are set.
BaseSpec []byte
// BaseSpecPath, when non-empty, is the filesystem path to the
// hand-tuned OpenAPI yaml. RunCLI loads it on startup and feeds the
// bytes through the same merge path as BaseSpec. Empty path means "no
// merge, emit pure auto-generated yaml".
BaseSpecPath string
// RestrictToBaseSpecPaths, when true and a base spec is supplied,
// constrains the generator to ONLY emit operations whose path also
// appears in the base spec. Auto-discovered routes absent from the
// hand-tuned yaml are dropped from the output.
//
// Use this when the curated `docs/openapi/openapi.yaml` is treated as
// the canonical endpoint registry — i.e. a route does not "exist" for
// API consumers until it has been documented. This is the strict
// inverse of the default behavior, which surfaces every walked route
// regardless of base-spec coverage.
RestrictToBaseSpecPaths bool
// ExcludePaths is an explicit blocklist of path globs. Paths matching
// any of these patterns are dropped from the generated document
// before merge, regardless of whether RestrictToBaseSpecPaths is set.
//
// Glob syntax: "*" matches one segment, "**" matches any number of
// segments. Examples:
//
// {"/static/**", "/favicon.ico", "/robots.txt"} // drop static asset routes
// {"/debug/**"} // drop debug-only routes
ExcludePaths []string
// OperationDocExtractor enables source-level Go doc-comment extraction
// for operation-level OpenAPI metadata. The built-in extractor only
// reads namespaced `@goai.*` directives from handler struct and method
// docs, so ordinary implementation comments stay private. Use
// DefaultOperationDocExtractor() or
// DefaultOperationDocExtractorWithBuildTags() to turn on the AST-based
// implementation; pass nil (the default) to disable docstring
// fallback entirely.
//
// Explicit Spec values, route-derived parameters, generated schemas,
// and acceptance-derived security always win; docstring content only
// fills gaps.
OperationDocExtractor OperationDocExtractor
// Args is the argv slice the CLI parses. nil → os.Args[1:].
Args []string
// Stdout is where yaml goes when DefaultOutput resolves to "-". nil →
// os.Stdout. Tests inject a buffer here.
Stdout io.Writer
// Stderr is where progress and error messages go. nil → os.Stderr.
Stderr io.Writer
// Exit is invoked on terminal failure with a non-zero code. nil →
// os.Exit. Tests inject a recorder.
Exit func(int)
}
RunOptions holds the project-specific spec configuration. Only Servers, Tags, GlobalSecurity and SecuritySchemes are typically project-specific — the rest have sensible defaults.
type RuntimeOption ¶
type RuntimeOption func(*runtimeConfig)
RuntimeOption configures the http handler returned by Handler.
func WithRuntimeBuildOptions ¶
func WithRuntimeBuildOptions(opts BuildOptions) RuntimeOption
WithRuntimeBuildOptions overrides the BuildOptions used at runtime (Title, Servers, Tags, etc.).
func WithRuntimeCacheTTL ¶
func WithRuntimeCacheTTL(d time.Duration) RuntimeOption
WithRuntimeCacheTTL sets how long the emitted yaml is cached before re-walking the route tree. The default is 0, which disables caching (every request rebuilds — fine for local dev, tune for production).
func WithRuntimeProfile ¶
func WithRuntimeProfile(name string) RuntimeOption
WithRuntimeProfile names the profile to emit. Defaults to "all".
type Schema ¶
type Schema struct {
Ref string `yaml:"$ref,omitempty"`
Title string `yaml:"title,omitempty"`
Type string `yaml:"type,omitempty"`
Format string `yaml:"format,omitempty"`
Description string `yaml:"description,omitempty"`
// Numeric validation
MultipleOf *float64 `yaml:"multipleOf,omitempty"`
Maximum *float64 `yaml:"maximum,omitempty"`
ExclusiveMaximum bool `yaml:"exclusiveMaximum,omitempty"`
Minimum *float64 `yaml:"minimum,omitempty"`
ExclusiveMinimum bool `yaml:"exclusiveMinimum,omitempty"`
// String validation
MaxLength *uint64 `yaml:"maxLength,omitempty"`
MinLength *uint64 `yaml:"minLength,omitempty"`
Pattern string `yaml:"pattern,omitempty"`
// Array validation
MaxItems *uint64 `yaml:"maxItems,omitempty"`
MinItems *uint64 `yaml:"minItems,omitempty"`
UniqueItems bool `yaml:"uniqueItems,omitempty"`
// Object validation
MaxProperties *uint64 `yaml:"maxProperties,omitempty"`
MinProperties *uint64 `yaml:"minProperties,omitempty"`
// Enumeration / fixed
Enum []any `yaml:"enum,omitempty"`
Default any `yaml:"default,omitempty"`
// Composition
OneOf []*Schema `yaml:"oneOf,omitempty"`
AllOf []*Schema `yaml:"allOf,omitempty"`
AnyOf []*Schema `yaml:"anyOf,omitempty"`
Not *Schema `yaml:"not,omitempty"`
// Object
Properties map[string]*Schema `yaml:"properties,omitempty"`
Required []string `yaml:"required,omitempty"`
AdditionalProperties any `yaml:"additionalProperties,omitempty"`
// Array
Items *Schema `yaml:"items,omitempty"`
// OAS-specific
Nullable bool `yaml:"nullable,omitempty"`
Discriminator *Discriminator `yaml:"discriminator,omitempty"`
ReadOnly bool `yaml:"readOnly,omitempty"`
WriteOnly bool `yaml:"writeOnly,omitempty"`
XML *XML `yaml:"xml,omitempty"`
ExternalDocs *ExternalDocumentation `yaml:"externalDocs,omitempty"`
Example any `yaml:"example,omitempty"`
Deprecated bool `yaml:"deprecated,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
Schema is the OpenAPI 3.0.3 Schema Object — a strict subset of JSON Schema Draft 4 with OAS-specific keywords (nullable, discriminator, readOnly/writeOnly, xml, externalDocs, example).
type SchemaNameProvider ¶ added in v1.15.1
type SchemaNameProvider interface {
GOAISchemaName() string
}
SchemaNameProvider lets a struct type choose its OpenAPI component schema name when goai builds schemas from reflection.
type SecurityProvider ¶
SecurityProvider lets an acceptance declare that it enforces a particular security scheme for every HTTP method on every guarded route. Each acceptance can return one scheme + scopes. Builder aggregates these along the inherited acceptance chain.
Acceptances that conditionally skip enforcement on certain HTTP methods (e.g. CSRF acceptances that exempt GET) should implement MethodAwareSecurityProvider instead — the walker prefers it when present so the OpenAPI security requirement matches actual runtime enforcement per method.
type SecurityRef ¶
SecurityRef binds an operation to a named security scheme with optional scopes (used by OAuth2-style schemes).
type SecurityScheme ¶
type SecurityScheme struct {
Type string `yaml:"type"`
Description string `yaml:"description,omitempty"`
Name string `yaml:"name,omitempty"`
In string `yaml:"in,omitempty"`
Scheme string `yaml:"scheme,omitempty"`
BearerFormat string `yaml:"bearerFormat,omitempty"`
Flows *OAuthFlows `yaml:"flows,omitempty"`
OpenIDConnectURL string `yaml:"openIdConnectUrl,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
SecurityScheme is the security scheme object. Supported types per the spec: apiKey, http, oauth2, openIdConnect.
type Selector ¶
type Selector struct {
Paths []string `yaml:"paths,omitempty"`
Packages []string `yaml:"packages,omitempty"`
Tags []string `yaml:"tags,omitempty"`
Profiles []string `yaml:"profiles,omitempty"`
}
Selector chooses operations by path patterns, package paths, OpenAPI tags, or declared profile scopes. All non-empty fields combine with logical AND. A nil/empty Selector matches everything.
Patterns:
- Paths use simple glob with "*" matching one segment and "**" matching any number of segments.
- Packages match by literal prefix.
- Tags match the OpenAPI operation tags declared via Spec WithTag / handler-level SpecProvider.GOAISpec / per-method providers, docstring @goai.tag directives, or via goai.Register. This is what the README "tag-based filtering" copy actually refers to.
- Profiles match the names returned by ProfileScope.GOAIProfileScope (handler or acceptance level). Use this to attach an operation to one of the profile buckets defined in goai.yaml when the operation does not have a corresponding OpenAPI tag.
func (Selector) Match ¶
func (s Selector) Match(c OperationCandidate, declaredProfiles, operationTags []string) bool
Match reports whether the candidate matches every non-empty field on the selector. declaredProfiles is the union returned by ProfileScope across the handler and its acceptance chain; operationTags is the union of OpenAPI tags assigned to this operation by Spec / Register / classifier.
type Server ¶
type Server struct {
URL string `yaml:"url"`
Description string `yaml:"description,omitempty"`
Variables map[string]*ServerVariable `yaml:"variables,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
Server represents one entry in the top-level servers array, or in PathItem.Servers / Operation.Servers when overriding the global value.
type ServerVariable ¶
type ServerVariable struct {
Enum []string `yaml:"enum,omitempty"`
Default string `yaml:"default"`
Description string `yaml:"description,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
ServerVariable describes one URL template variable for a Server URL. Default is required by the spec; Enum constrains the allowed values.
type Spec ¶
type Spec struct {
// contains filtered or unexported fields
}
Spec carries optional metadata for a single (handler, method) operation. All fields are deliberately unexported; callers shape Spec values through functional options exclusively. This keeps the public API forward compatible — new fields can be added without breaking call sites.
func NewSpec ¶
NewSpec returns a Spec built from the supplied options. Useful when an optional SpecProvider.GOAISpec returns Spec values.
func (Spec) Deprecated ¶
Deprecated reports whether the operation is deprecated.
func (Spec) Description ¶
Description reports the spec description.
func (Spec) ExternalDocs ¶
func (s Spec) ExternalDocs() *ExternalDocumentation
ExternalDocs returns the operation-level external docs reference, or nil.
func (Spec) ExtraHeaders ¶
ExtraHeaders returns extra headers configured for the operation.
func (Spec) ExtraParams ¶
ExtraParams returns extra parameters configured for the operation.
func (Spec) MultiExamples ¶
MultiExamples returns the per-media-type, per-name Example map. The returned map and its inner buckets must not be mutated by callers.
func (Spec) OperationID ¶
OperationID reports the explicit operation id, or empty if unset.
func (Spec) OperationServers ¶
OperationServers returns the operation-level servers, if any.
func (Spec) RequestDescription ¶ added in v1.15.1
RequestDescription returns the operation request body description, or empty string when unset.
func (Spec) RequestMediaType ¶
RequestMediaType returns the operator-overridden request media type, or empty string when goai should fall back to "application/json".
func (Spec) Responses ¶ added in v1.15.1
func (s Spec) Responses() map[string]*ResponseSpec
Responses returns the per-status response specs declared via WithResponse. The returned map and its entries must not be mutated by callers.
func (Spec) Security ¶
func (s Spec) Security() []SecurityRef
Security returns the configured security refs.
func (Spec) SuccessDescription ¶ added in v1.15.1
SuccessDescription returns the override for the success response description, or empty string when the builder should use its default.
type SpecProvider ¶
type SpecProvider interface {
GOAISpec() Spec
}
SpecProvider supplies a Spec that applies to every HTTP method the handler implements. Use this when the spec metadata (tags, security, deprecated) is the same for all methods on the handler, or when the handler only implements one HTTP method — the most common case. The GOAI prefix on the method name keeps it distinct from the handler's HTTP method functions (Get, Post, ...) on the same struct, and the method name mirrors the returned Spec type.
For handlers that need different specs per HTTP method, implement one of the per-method providers below (IndexSpecProvider, GetSpecProvider, ...). The per-method providers override SpecProvider when both are implemented.
type Tag ¶
type Tag struct {
Name string `yaml:"name"`
Description string `yaml:"description,omitempty"`
ExternalDocs *ExternalDocumentation `yaml:"externalDocs,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
Tag is a top-level tag definition.
type TraceSpecProvider ¶
type TraceSpecProvider interface {
GOAITraceSpec() Spec
}
TraceSpecProvider supplies the Spec for the handler's Trace() method (HTTP TRACE).
type XML ¶
type XML struct {
Name string `yaml:"name,omitempty"`
Namespace string `yaml:"namespace,omitempty"`
Prefix string `yaml:"prefix,omitempty"`
Attribute bool `yaml:"attribute,omitempty"`
Wrapped bool `yaml:"wrapped,omitempty"`
Extensions map[string]any `yaml:",inline,omitempty"`
}
XML adds XML serialization metadata to a Schema.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
goai
command
Command goai is the OpenAPI generation CLI for gone-framework projects.
|
Command goai is the OpenAPI generation CLI for gone-framework projects. |
|
examples
|
|
|
customschema
command
Customschema example: register Go types with goai.Register so that the generated spec carries fully fleshed-out request and response schemas, then drive validation constraints via the `goai:"..."` struct tag.
|
Customschema example: register Go types with goai.Register so that the generated spec carries fully fleshed-out request and response schemas, then drive validation constraints via the `goai:"..."` struct tag. |
|
docstring
command
Docstring example: generate OpenAPI metadata from namespaced handler doc-comment directives instead of goai.Register calls.
|
Docstring example: generate OpenAPI metadata from namespaced handler doc-comment directives instead of goai.Register calls. |
|
full
command
Full example: drive RunCLI with the complete RunOptions surface so the generated YAML exercises every Document-level OpenAPI 3.0.3 feature goai supports — License, Contact, TermsOfService, ExternalDocs, multiple Servers with ServerVariables, multiple Tags, GlobalSecurity, SecuritySchemes, and a custom DefaultOutput path.
|
Full example: drive RunCLI with the complete RunOptions surface so the generated YAML exercises every Document-level OpenAPI 3.0.3 feature goai supports — License, Contact, TermsOfService, ExternalDocs, multiple Servers with ServerVariables, multiple Tags, GlobalSecurity, SecuritySchemes, and a custom DefaultOutput path. |
|
merge
command
Merge example: walk a route tree, generate a fresh spec, then layer it onto a hand-tuned `openapi.yaml` baseline using goai.Merge3Way.
|
Merge example: walk a route tree, generate a fresh spec, then layer it onto a hand-tuned `openapi.yaml` baseline using goai.Merge3Way. |
|
quickstart
command
Quickstart example: build a minimal route tree, walk it, and print the generated OpenAPI 3.0.3 YAML to stdout.
|
Quickstart example: build a minimal route tree, walk it, and print the generated OpenAPI 3.0.3 YAML to stdout. |
|
runtime
command
Runtime example: serve the generated OpenAPI YAML at /openapi.yaml from inside a running gone HTTP server, instead of generating it ahead of time from a CLI.
|
Runtime example: serve the generated OpenAPI YAML at /openapi.yaml from inside a running gone HTTP server, instead of generating it ahead of time from a CLI. |
|
internal
|
|