spec

package module
v0.3.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 5, 2025 License: MIT Imports: 20 Imported by: 19

README ΒΆ

oaswrap/spec

CI codecov Go Reference Go Report Card Go Version License

A lightweight, framework-agnostic OpenAPI 3.x specification builder for Go that gives you complete control over your API documentation without vendor lock-in.

Why oaswrap/spec?

  • 🎯 Framework Agnostic β€” Works with any Go web framework or as a standalone tool
  • ⚑ Zero Dependencies β€” Powered by swaggest/openapi-go with minimal overhead
  • πŸ”§ Programmatic Control β€” Build specs in pure Go code with full type safety
  • πŸš€ Adapter Ecosystem β€” Seamless integration with popular frameworks via dedicated adapters
  • πŸ“ CI/CD Ready β€” Generate specs at build time for documentation pipelines

Installation

go get github.com/oaswrap/spec

Quick Start

Static Spec Generation

For CI/CD pipelines and build-time spec generation:

package main

import (
	"log"

	"github.com/oaswrap/spec"
	"github.com/oaswrap/spec/option"
)

func main() {
	// Create a new OpenAPI router
	r := spec.NewRouter(
		option.WithTitle("My API"),
		option.WithVersion("1.0.0"),
		option.WithServer("https://api.example.com"),
		option.WithSecurity("bearerAuth", option.SecurityHTTPBearer("Bearer")),
	)

	// Add routes
	v1 := r.Group("/api/v1")

	v1.Post("/login",
		option.Summary("User login"),
		option.Request(new(LoginRequest)),
		option.Response(200, new(LoginResponse)),
	)

	auth := v1.Group("/", option.GroupSecurity("bearerAuth"))

	auth.Get("/users/{id}",
		option.Summary("Get user by ID"),
		option.Request(new(GetUserRequest)),
		option.Response(200, new(User)),
	)

	// Generate OpenAPI spec
	if err := r.WriteSchemaTo("openapi.yaml"); err != nil {
		log.Fatal(err)
	}

	log.Println("βœ… OpenAPI spec generated at openapi.yaml")
}

type LoginRequest struct {
	Username string `json:"username" required:"true"`
	Password string `json:"password" required:"true"`
}

type LoginResponse struct {
	Token string `json:"token"`
}

type GetUserRequest struct {
	ID string `path:"id" required:"true"`
}

type User struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

πŸ“– View the generated spec on Rest.Wiki

Framework Integration

For seamless HTTP server integration, use one of our framework adapters:

Framework Package
Chi chiopenapi
Echo echoopenapi
Gin ginopenapi
Fiber fiberopenapi
HTTP httpopenapi
Mux muxopenapi
HTTPRouter httprouteropenapi

Each adapter provides:

  • βœ… Automatic spec generation from your routes
  • πŸ“š Built-in documentation UI at /docs
  • πŸ“„ YAML spec endpoints at /docs/openapi.yaml
  • πŸ”§ Inline OpenAPI options with route definitions

Visit the individual adapter repositories for framework-specific examples and detailed integration guides.

When to Use What?

βœ… Use spec for static generation when you:
  • Generate OpenAPI files at build time
  • Integrate with CI/CD pipelines
  • Build custom documentation tools
  • Need static spec generation
βœ… Use framework adapters when you:
  • Want automatic spec generation from routes
  • Need zero-configuration setup
  • Prefer inline OpenAPI configuration
  • Want route registration + documentation in one step

Configuration Options

The option package provides comprehensive OpenAPI configuration:

Basic Information
option.WithOpenAPIVersion("3.0.3") // Default: "3.0.3"
option.WithTitle("My API")
option.WithDescription("API description")
option.WithVersion("1.2.3")
option.WithContact(openapi.Contact{
	Name:  "Support Team",
	URL:   "https://support.example.com",
	Email: "support@example.com",
})
option.WithLicense(openapi.License{
	Name: "MIT License",
	URL:  "https://opensource.org/licenses/MIT",
})
option.WithExternalDocs("https://docs.example.com", "API Documentation")
option.WithTags(
	openapi.Tag{
		Name:        "User Management",
		Description: "Operations related to user management",
	},
	openapi.Tag{
		Name:        "Authentication", 
		Description: "Authentication related operations",
	},
)
Servers
option.WithServer("https://api.example.com")
option.WithServer("https://api-example.com/{version}",
	option.ServerDescription("Production Server"),
	option.ServerVariables(map[string]openapi.ServerVariable{
		"version": {
			Default:     "v1",
			Enum:        []string{"v1", "v2"},
			Description: "API version",
		},
	}),
)
Security Schemes
// Bearer token
option.WithSecurity("bearerAuth", option.SecurityHTTPBearer("Bearer"))

// API Key
option.WithSecurity("apiKey", option.SecurityAPIKey("X-API-Key", "header"))

// OAuth2
option.WithSecurity("oauth2", option.SecurityOAuth2(
	openapi.OAuthFlows{
		Implicit: &openapi.OAuthFlowsImplicit{
			AuthorizationURL: "https://auth.example.com/authorize",
			Scopes: map[string]string{
				"read":  "Read access",
				"write": "Write access",
			},
		},
	},
))
Route Documentation
option.OperationID("getUserByID")					// Unique operation ID
option.Summary("Short description")					// Brief summary
option.Description("Detailed description")			// Full description
option.Tags("User Management", "Authentication")	// Group by tags
option.Request(new(RequestModel))					// Request body model
option.Response(200, new(ResponseModel),			// Response model
	option.ContentDescription("Successful response"),
	option.ContentType("application/json"),
	option.ContentDefault(true),
)
option.Security("bearerAuth")					// Apply security scheme
option.Deprecated()								// Mark as deprecated
option.Hidden()									// Hide from spec
Parameter Definition

Define parameters using struct tags in your request models:

type GetUserRequest struct {
	ID     string `path:"id" required:"true" description:"User identifier"`
	Limit  int    `query:"limit" description:"Maximum number of results"`
	APIKey string `header:"X-API-Key" description:"API authentication key"`
}
Group-Level Configuration

Apply settings to all routes within a group:

// Apply to all routes in the group
adminGroup := r.Group("/admin",
	option.GroupTags("Administration"),
	option.GroupSecurity("bearerAuth"),
	option.GroupDeprecated(),
)

// Hide internal routes from documentation
internalGroup := r.Group("/internal",
	option.GroupHidden(),
)

Advanced Features

Rich Schema Documentation
type CreateUserRequest struct {
	Name     string   `json:"name" required:"true" minLength:"2" maxLength:"50"`
	Email    string   `json:"email" required:"true" format:"email"`
	Age      int      `json:"age" minimum:"18" maximum:"120"`
	Tags     []string `json:"tags" maxItems:"10"`
}

For comprehensive struct tag documentation, see swaggest/openapi-go and swaggest/jsonschema-go.

Generic Response Types
type APIResponse[T any] struct {
	Success   bool   `json:"success"`
	Data      T      `json:"data,omitempty"`
	Error     string `json:"error,omitempty"`
	Timestamp string `json:"timestamp"`
}

// Usage
option.Response(200, new(APIResponse[User]))
option.Response(200, new(APIResponse[[]Product]))

Examples

Explore complete working examples in the examples/ directory:

  • Basic β€” Standalone spec generation
  • Basic-HTTP β€” Built-in HTTP server with OpenAPI docs
  • Petstore β€” Full Petstore API with routes and models

API Reference

Complete documentation at pkg.go.dev/github.com/oaswrap/spec.

Key packages:

  • spec β€” Core router and spec builder
  • option β€” Configuration options

FAQ

Q: Can I use this with my existing API?
A: Absolutely! Use the standalone version to document existing APIs, or gradually migrate to framework adapters.

Q: How does this compare to swag/swaggo?
A: While swag uses code comments, oaswrap uses pure Go code for type safety and better IDE support. Both have their merits - swag is annotation-based while oaswrap is code-first.

Q: How does this compare to Huma?
A: Both are excellent choices with different philosophies:

  • Huma is a complete HTTP framework with built-in OpenAPI generation, validation, and middleware
  • oaswrap/spec is a lightweight, framework-agnostic documentation builder that works with your existing setup
  • Use Huma if you're building a new API and want an all-in-one solution with automatic validation
  • Use oaswrap if you have existing code, prefer framework flexibility, or need standalone spec generation

Q: Is this production ready?
A: The library is in active development. While core functionality is solid, consider it beta software. Thorough testing is recommended before production use.

Q: How do I handle authentication in the generated docs?
A: Define security schemes using option.WithSecurity() and apply them to routes with option.Security(). The generated docs will include authentication UI.

Contributing

We welcome contributions! Here's how you can help:

  1. πŸ› Report bugs β€” Open an issue with reproduction steps
  2. πŸ’‘ Suggest features β€” Share your ideas for improvements
  3. πŸ“ Improve docs β€” Help make our documentation clearer
  4. πŸ”§ Submit PRs β€” Fix bugs or add features

Please check existing issues and discussions before starting work on new features.

License

MIT

Documentation ΒΆ

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

This section is empty.

Functions ΒΆ

This section is empty.

Types ΒΆ

type Generator ΒΆ

type Generator interface {
	Router

	// Config returns the OpenAPI configuration used by the Generator.
	Config() *specopenapi.Config

	// GenerateSchema generates the OpenAPI schema in the specified format.
	// By default, it generates YAML. Pass "json" to generate JSON instead.
	GenerateSchema(formats ...string) ([]byte, error)

	// MarshalYAML returns the OpenAPI specification marshaled as YAML.
	MarshalYAML() ([]byte, error)

	// MarshalJSON returns the OpenAPI specification marshaled as JSON.
	MarshalJSON() ([]byte, error)

	// Validate checks whether the OpenAPI specification is valid.
	Validate() error

	// WriteSchemaTo writes the OpenAPI schema to a file.
	// The format is inferred from the file extension: ".yaml" for YAML, ".json" for JSON.
	WriteSchemaTo(path string) error
}

Generator defines an interface for building and exporting OpenAPI specifications.

func NewGenerator ΒΆ

func NewGenerator(opts ...option.OpenAPIOption) Generator

NewGenerator returns a new Generator instance using the given OpenAPI options.

It initializes the OpenAPI reflector and configuration.

func NewRouter ΒΆ added in v0.1.3

func NewRouter(opts ...option.OpenAPIOption) Generator

NewRouter returns a new Router instance using the given OpenAPI options.

It is equivalent to NewGenerator.

See also: NewGenerator.

type Route ΒΆ added in v0.1.3

type Route interface {
	// Method sets the HTTP method for the route.
	Method(method string) Route
	// Path sets the HTTP path for the route.
	Path(path string) Route
	// With applies additional operation options to the route.
	With(opts ...option.OperationOption) Route
}

Route represents a single API route in the OpenAPI specification.

type Router ΒΆ added in v0.1.3

type Router interface {
	// Get registers a GET operation for the given path and options.
	Get(path string, opts ...option.OperationOption) Route

	// Post registers a POST operation for the given path and options.
	Post(path string, opts ...option.OperationOption) Route

	// Put registers a PUT operation for the given path and options.
	Put(path string, opts ...option.OperationOption) Route

	// Delete registers a DELETE operation for the given path and options.
	Delete(path string, opts ...option.OperationOption) Route

	// Patch registers a PATCH operation for the given path and options.
	Patch(path string, opts ...option.OperationOption) Route

	// Options registers an OPTIONS operation for the given path and options.
	Options(path string, opts ...option.OperationOption) Route

	// Head registers a HEAD operation for the given path and options.
	Head(path string, opts ...option.OperationOption) Route

	// Trace registers a TRACE operation for the given path and options.
	Trace(path string, opts ...option.OperationOption) Route

	// Add registers an operation for the given HTTP method, path, and options.
	Add(method, path string, opts ...option.OperationOption) Route

	// NewRoute creates a new route with the given options.
	NewRoute(opts ...option.OperationOption) Route

	// Route registers a nested route under the given pattern.
	// The provided function receives a Router to define sub-routes.
	Route(pattern string, fn func(router Router), opts ...option.GroupOption) Router

	// Group creates a new sub-router with the given path prefix and group options.
	Group(pattern string, opts ...option.GroupOption) Router

	// With applies one or more group options to the router.
	With(opts ...option.GroupOption) Router
}

Router defines methods for registering API routes and operations in an OpenAPI specification. It lets you describe HTTP methods, paths, and options.

Directories ΒΆ

Path Synopsis
adapter
chiopenapi module
echoopenapi module
fiberopenapi module
ginopenapi module
httpopenapi module
muxopenapi module
adapters
chiopenapi module
echoopenapi module
fiberopenapi module
ginopenapi module
httpopenapi module
internal
module
specui module
Package option provides functional options for configuring OpenAPI generation, including server setup, group settings, operation options, and reflector behavior.
Package option provides functional options for configuring OpenAPI generation, including server setup, group settings, operation options, and reflector behavior.
pkg
dto

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL