clearspec

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2025 License: MIT Imports: 9 Imported by: 0

README

ClearSpec

Automatically generate OpenAPI/Swagger documentation for your Fiber web applications.

Why This Tool?

This tool was created as an alternative to swag, which generates Swagger documentation from comments in your code. While comment-based generation works, it has several drawbacks:

  • Code pollution: Your handlers become cluttered with lengthy comment blocks
  • Maintenance burden: Comments can easily get out of sync with actual code
  • Poor developer experience: Writing and maintaining complex comment syntax is tedious
  • Type safety: No compile-time validation of your documentation

This generator takes a different approach by using Go's type system and programmatic registration, providing:

  • Clean code: No comment pollution in your handlers
  • 🔄 Always in sync: Documentation is generated from actual types and code
  • 🛡️ Type safe: Compile-time validation ensures correctness
  • 🎯 Developer friendly: Simple, intuitive API for documentation

Features

  • 🚀 Auto-generation from Go types and handlers
  • 📝 Multiple status codes for each endpoint
  • 🔒 Security definitions support
  • 🏷️ Struct tags for validation and documentation
  • 🎨 Built-in Swagger UI

Installation

go get github.com/kxrxh/clearspec

Quick Start

package main

import (
    "github.com/gofiber/fiber/v2"
    "github.com/kxrxh/clearspec"
)

type User struct {
    ID    int    `json:"id" description:"User ID"`
    Name  string `json:"name" validate:"required" description:"User name"`
    Email string `json:"email" validate:"required,email" description:"User email"`
}

func main() {
    app := fiber.New()

    // Create generator
    generator := clearspec.NewGenerator(clearspec.SwaggerInfo{
        Title:       "My API",
        Description: "Simple user management API",
        Version:     "1.0.0",
    })

    // Register routes
    generator.RegisterRoute("GET", "/users", getUsers,
        clearspec.WithTags("Users"),
        clearspec.WithSummary("Get all users"),
        clearspec.WithSuccessResponse([]User{}, "Success"),
    )

    // Setup Swagger
    generator.SetupFiberSwagger(app, "/swagger.json")
    generator.SetupSwaggerUI(app, "/swagger.json", "/docs")

    // Register Fiber routes
    app.Get("/users", getUsers)

    app.Listen(":3000")
}

func getUsers(c *fiber.Ctx) error {
    return c.JSON([]User{{ID: 1, Name: "John", Email: "john@example.com"}})
}

Visit http://localhost:3000/docs to see your Swagger UI.

Examples

Check out the examples directory for complete working examples:

API Reference

Generator
// Create generator
generator := clearspec.NewGenerator(clearspec.SwaggerInfo{
    Title:       "API Title",
    Description: "API Description", 
    Version:     "1.0.0",
})

// Configure
generator.SetHost("localhost:3000")
generator.SetBasePath("/api")

// Register route
generator.RegisterRoute(method, path, handler, options...)
Route Options
// Basic info
clearspec.WithTags("Users")
clearspec.WithSummary("Short description")
clearspec.WithDescription("Detailed description")

// Request/Response
clearspec.WithRequestType(RequestStruct{})
clearspec.WithSuccessResponse(ResponseStruct{}, "Success")

// Common responses
clearspec.WithCreatedResponse(type, "Created")        // 201
clearspec.WithBadRequestResponse(type, "Bad request") // 400
clearspec.WithNotFoundResponse(type, "Not found")    // 404

// Custom response
clearspec.WithResponse(statusCode, type, "Description")

// Security
clearspec.WithSecurity(map[string][]string{"bearerAuth": {}})

Struct Tags

Use these tags to enhance your documentation:

type User struct {
    ID    int    `json:"id" description:"User ID"`
    Name  string `json:"name" validate:"required,min=2" description:"Name"`
    Email string `json:"email" validate:"required,email" description:"Email"`
    Age   int    `json:"age" validate:"min=18" description:"Age"`
    Role  string `json:"role" enum:"user,admin" description:"User role"`
}

type QueryParams struct {
    Limit int `query:"limit" description:"Results limit"`
    Page  int `query:"page" description:"Page number"`
}

Supported tags:

  • json - JSON field name
  • description - Field description
  • validate - Validation rules (auto-extracts required, min, max, etc.)
  • enum - Enum values
  • query - Query parameter
  • form - Form parameter

Multiple Response Types

generator.RegisterRoute("POST", "/users", createUser,
    clearspec.WithTags("Users"),
    clearspec.WithRequestType(CreateUserRequest{}),
    clearspec.WithCreatedResponse(User{}, "User created"),
    clearspec.WithBadRequestResponse(ValidationError{}, "Invalid data"),
    clearspec.WithResponse(409, ConflictError{}, "User exists"),
)

Security

// Add security definition
generator.AddSecurityDefinition("bearerAuth", map[string]interface{}{
    "type":         "http",
    "scheme":       "bearer",
    "bearerFormat": "JWT",
})

// Use in routes
generator.RegisterRoute("DELETE", "/users/:id", deleteUser,
    clearspec.WithSecurity(map[string][]string{"bearerAuth": []string{}}),
    // ... other options
)

Type Support

Go Type OpenAPI Type
string string
int, int32 integer
int64 integer (int64)
float32, float64 number
bool boolean
time.Time string (date-time)
[]T array
map[string]T object
struct object

License

MIT License - see LICENSE file for details.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetSwaggerTag

func GetSwaggerTag(field reflect.StructField) map[string]string

GetSwaggerTag extracts swagger information from struct tags

Types

type Generator

type Generator struct {
	// contains filtered or unexported fields
}

Generator handles the automatic generation of Swagger documentation

func NewGenerator

func NewGenerator(info SwaggerInfo) *Generator

NewGenerator creates a new swagger generator

func (*Generator) AddSecurityDefinition

func (g *Generator) AddSecurityDefinition(name string, definition interface{})

AddSecurityDefinition adds a security definition

func (*Generator) GenerateSwagger

func (g *Generator) GenerateSwagger() *Swagger

GenerateSwagger creates the complete Swagger document

func (*Generator) GetSwagger

func (g *Generator) GetSwagger() *Swagger

GetSwagger returns the generated swagger document

func (*Generator) RegisterRoute

func (g *Generator) RegisterRoute(method, path string, handler interface{}, options ...RouteOption)

RegisterRoute registers a route with swagger metadata

func (*Generator) SetBasePath

func (g *Generator) SetBasePath(basePath string)

SetBasePath sets the base path for all API endpoints

func (*Generator) SetHost

func (g *Generator) SetHost(host string)

SetHost sets the host for the API

func (*Generator) SetSchemes

func (g *Generator) SetSchemes(schemes []string)

SetSchemes sets the supported schemes (http, https)

func (*Generator) SetupFiberSwagger

func (g *Generator) SetupFiberSwagger(app *fiber.App, path string)

SetupFiberSwagger sets up swagger generation with Fiber app

func (*Generator) SetupFiberSwaggerYAML

func (g *Generator) SetupFiberSwaggerYAML(app *fiber.App, path string)

SetupFiberSwaggerYAML sets up YAML swagger generation with Fiber app

func (*Generator) SetupSwaggerUI

func (g *Generator) SetupSwaggerUI(app *fiber.App, swaggerPath, uiPath string)

SetupSwaggerUI sets up Swagger UI endpoint

func (*Generator) ToJSON

func (g *Generator) ToJSON() ([]byte, error)

ToJSON converts the swagger document to JSON

func (*Generator) ToYAML

func (g *Generator) ToYAML() ([]byte, error)

ToYAML converts the swagger document to YAML

type HandlerAnnotation

type HandlerAnnotation struct {
	Tags        []string
	Summary     string
	Description string
	Security    []string
}

HandlerAnnotation contains swagger annotations for handlers

type Header struct {
	Type        string `json:"type"`
	Format      string `json:"format,omitempty"`
	Description string `json:"description,omitempty"`
}

Header represents a response header

type Items

type Items struct {
	Type   string `json:"type"`
	Format string `json:"format,omitempty"`
}

Items represents the items schema for array parameters

type MiddlewareConfig

type MiddlewareConfig struct {
	BasePath string
	Path     string
	Title    string
}

MiddlewareConfig configuration for the swagger middleware

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"`
	Consumes    []string              `json:"consumes,omitempty"`
	Produces    []string              `json:"produces,omitempty"`
	Parameters  []Parameter           `json:"parameters,omitempty"`
	Responses   map[string]Response   `json:"responses"`
	Security    []map[string][]string `json:"security,omitempty"`
	Deprecated  bool                  `json:"deprecated,omitempty"`
}

Operation represents a single API operation

type Parameter

type Parameter struct {
	Name             string   `json:"name"`
	In               string   `json:"in"` // "query", "header", "path", "formData", "body"
	Description      string   `json:"description,omitempty"`
	Required         bool     `json:"required,omitempty"`
	Type             string   `json:"type,omitempty"`
	Format           string   `json:"format,omitempty"`
	Schema           *Schema  `json:"schema,omitempty"`
	Items            *Items   `json:"items,omitempty"`
	CollectionFormat string   `json:"collectionFormat,omitempty"`
	Minimum          *float64 `json:"minimum,omitempty"`
	Maximum          *float64 `json:"maximum,omitempty"`
	Enum             []string `json:"enum,omitempty"`
}

Parameter represents an operation parameter

type Response

type Response struct {
	Description string            `json:"description"`
	Schema      *Schema           `json:"schema,omitempty"`
	Headers     map[string]Header `json:"headers,omitempty"`
}

Response represents an operation response

type ResponseInfo

type ResponseInfo struct {
	StatusCode  int
	Description string
	Type        reflect.Type
	Headers     map[string]string
}

ResponseInfo represents a response for a specific status code

type RouteInfo

type RouteInfo struct {
	Method       string
	Path         string
	Handler      interface{}
	Tags         []string
	Summary      string
	Description  string
	RequestType  reflect.Type
	ResponseType reflect.Type
	Responses    []ResponseInfo // Multiple responses for different status codes
	Security     map[string][]string
	Deprecated   bool
	Produces     []string
	Consumes     []string
}

RouteInfo contains metadata about a route

type RouteOption

type RouteOption func(*RouteInfo)

RouteOption is a function that configures route metadata

func WithBadRequestResponse

func WithBadRequestResponse(errorType interface{}, description string) RouteOption

WithBadRequestResponse adds a bad request response (400)

func WithConsumes

func WithConsumes(consumes []string) RouteOption

WithConsumes sets the content types the route consumes

func WithCreatedResponse

func WithCreatedResponse(responseType interface{}, description string) RouteOption

WithCreatedResponse adds a created response (201)

func WithDeprecated

func WithDeprecated(deprecated bool) RouteOption

WithDeprecated marks the route as deprecated

func WithDescription

func WithDescription(description string) RouteOption

WithDescription sets the description for the route

func WithErrorResponse

func WithErrorResponse(statusCode int, errorType interface{}, description string) RouteOption

WithErrorResponse adds a common error response

func WithForbiddenResponse

func WithForbiddenResponse(errorType interface{}, description string) RouteOption

WithForbiddenResponse adds a forbidden response (403)

func WithInternalServerErrorResponse

func WithInternalServerErrorResponse(errorType interface{}, description string) RouteOption

WithInternalServerErrorResponse adds an internal server error response (500)

func WithNoContentResponse

func WithNoContentResponse(description string) RouteOption

WithNoContentResponse adds a no content response (204)

func WithNotFoundResponse

func WithNotFoundResponse(errorType interface{}, description string) RouteOption

WithNotFoundResponse adds a not found response (404)

func WithProduces

func WithProduces(produces []string) RouteOption

WithProduces sets the content types the route produces

func WithRequestType

func WithRequestType(t interface{}) RouteOption

WithRequestType sets the request body type

func WithResponse

func WithResponse(statusCode int, responseType interface{}, description string) RouteOption

WithResponse adds a response for a specific status code

func WithResponseHeaders

func WithResponseHeaders(headers map[string]string) RouteOption

WithResponseHeaders adds headers to the last added response

func WithResponseType

func WithResponseType(t interface{}) RouteOption

WithResponseType sets the response type

func WithSecurity

func WithSecurity(security map[string][]string) RouteOption

WithSecurity adds security requirements to the route

func WithSuccessResponse

func WithSuccessResponse(responseType interface{}, description string) RouteOption

WithSuccessResponse adds a success response (200)

func WithSummary

func WithSummary(summary string) RouteOption

WithSummary sets the summary for the route

func WithTags

func WithTags(tags ...string) RouteOption

WithTags sets the tags for the route

func WithUnauthorizedResponse

func WithUnauthorizedResponse(errorType interface{}, description string) RouteOption

WithUnauthorizedResponse adds an unauthorized response (401)

type Schema

type Schema struct {
	Type                 string             `json:"type,omitempty"`
	Format               string             `json:"format,omitempty"`
	Description          string             `json:"description,omitempty"`
	Required             []string           `json:"required,omitempty"`
	Properties           map[string]*Schema `json:"properties,omitempty"`
	Items                *Schema            `json:"items,omitempty"`
	Ref                  string             `json:"$ref,omitempty"`
	Example              interface{}        `json:"example,omitempty"`
	AdditionalProperties *Schema            `json:"additionalProperties,omitempty"`
	Enum                 []interface{}      `json:"enum,omitempty"`
}

Schema represents a data schema

func GetTypeSwagger

func GetTypeSwagger(t reflect.Type) *Schema

GetTypeSwagger extracts swagger info from Go types

type SecurityDefinition

type SecurityDefinition struct {
	Type         string `json:"type"`
	In           string `json:"in,omitempty"`
	Name         string `json:"name,omitempty"`
	Scheme       string `json:"scheme,omitempty"`
	BearerFormat string `json:"bearerFormat,omitempty"`
}

SecurityDefinition represents a security definition

type Swagger

type Swagger struct {
	Swagger             string                          `json:"swagger"`
	Info                SwaggerInfo                     `json:"info"`
	Host                string                          `json:"host,omitempty"`
	BasePath            string                          `json:"basePath,omitempty"`
	Schemes             []string                        `json:"schemes,omitempty"`
	Consumes            []string                        `json:"consumes,omitempty"`
	Produces            []string                        `json:"produces,omitempty"`
	Paths               map[string]map[string]Operation `json:"paths"`
	Definitions         map[string]*Schema              `json:"definitions"`
	Security            []map[string][]string           `json:"security,omitempty"`
	SecurityDefinitions map[string]SecurityDefinition   `json:"securityDefinitions,omitempty"`
}

Swagger represents the complete OpenAPI document

type SwaggerInfo

type SwaggerInfo struct {
	Title       string `json:"title"`
	Description string `json:"description"`
	Version     string `json:"version"`
	Host        string `json:"host,omitempty"`
	BasePath    string `json:"basePath,omitempty"`
}

SwaggerInfo contains the basic API information

type SwaggerMiddleware

type SwaggerMiddleware struct {
	// contains filtered or unexported fields
}

SwaggerMiddleware creates a middleware that generates and serves swagger docs

func NewMiddleware

func NewMiddleware(info SwaggerInfo, config MiddlewareConfig) *SwaggerMiddleware

NewMiddleware creates a new swagger middleware

func (*SwaggerMiddleware) GetSwagger

func (m *SwaggerMiddleware) GetSwagger() *Swagger

GetSwagger returns the generated swagger document

func (*SwaggerMiddleware) Handler

func (m *SwaggerMiddleware) Handler() fiber.Handler

Handler returns the middleware handler that serves swagger documentation

func (*SwaggerMiddleware) Route

func (m *SwaggerMiddleware) Route(method, path string, handler fiber.Handler, options ...RouteOption) fiber.Handler

Route registers a route with swagger documentation

func (*SwaggerMiddleware) ToJSON

func (m *SwaggerMiddleware) ToJSON() ([]byte, error)

ToJSON returns the swagger document as JSON bytes

Jump to

Keyboard shortcuts

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