apikit

package module
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Mar 12, 2026 License: MIT Imports: 6 Imported by: 0

README

apikit

Tests Go Report Card

Go toolkit for HTTP handler generation, OpenAPI 3.1 specification generation, and Go SDK generation.

Tools

  • handler gen — Generate HTTP handler wrappers from annotated Go functions
  • openapi gen — Generate OpenAPI 3.1 specs from Go source code (swagger directives)
  • sdk gen — Generate typed Go SDK packages from OpenAPI specs
  • swagger — Download and package Swagger UI assets

Installation

go install github.com/kausys/apikit/cmd/apikit@latest

1. handler gen — HTTP Handler Generation

Generates request parsing, validation, and response handling boilerplate from annotated Go functions.

Quick Start
//go:generate apikit handler gen

type GetUserRequest struct {
    UserID string `path:"id" validate:"required,uuid"`
    Fields string `query:"fields"`
}

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

// apikit:handler
func GetUser(ctx context.Context, req GetUserRequest) (GetUserResponse, error) {
    return GetUserResponse{ID: req.UserID, Name: "John"}, nil
}
go generate ./...
// Standard http
mux.HandleFunc("GET /users/{id}", getUserAPIKit(GetUser))

// Fiber
app.Get("/users/:id", getUserAPIKit(GetUser))

// Gin
router.GET("/users/:id", getUserAPIKit(GetUser))

// Echo
e.GET("/users/:id", getUserAPIKit(GetUser))
Parameter Sources
Tag Source
path:"name" URL path parameter
query:"name" Query string
header:"name" HTTP header
cookie:"name" Cookie
form:"name" Form field / multipart
json:"name" JSON body
Validation

Uses go-playground/validator:

type CreateUserRequest struct {
    Email    string `json:"email" validate:"required,email"`
    Password string `json:"password" validate:"required,min=8"`
    Age      int    `json:"age" validate:"gte=18,lte=120"`
}
File Uploads
type UploadRequest struct {
    File  *multipart.FileHeader   `form:"file"`
    Files []*multipart.FileHeader `form:"files"`
}
Raw HTTP Access
type StreamRequest struct {
    Request *http.Request
    Writer  http.ResponseWriter
    RawBody []byte
}
CLI Reference
apikit handler gen [flags]

Flags:
  -f, --file string        Source file to process (defaults to $GOFILE)
  -o, --output string      Output file (defaults to <source>_apikit.go)
      --framework string   Target framework: http, fiber, gin, echo (default "http")
      --force              Force regeneration even if source is unchanged
      --dry-run            Print output without writing
  -v, --verbose            Verbose output

2. openapi gen — OpenAPI 3.1 Specification Generation

Scans Go source code for swagger directives and generates a complete OpenAPI 3.1 spec.

Supported Directives
Directive Purpose
swagger:meta API metadata (title, version, description)
swagger:model Schema definitions
swagger:route Operation definitions
swagger:parameters Parameter definitions
swagger:enum Enum definitions
Examples
# Generate to openapi.yaml (default)
apikit openapi gen

# Custom output and format
apikit openapi gen -o api.json -f json

# Scan a specific package pattern
apikit openapi gen -p ./api/... -o api.yaml

# Generate multiple specs from spec: directives
apikit openapi gen --multi-specs

# Generate a single named spec
apikit openapi gen --spec public

# Inline $ref schemas
apikit openapi gen --flatten

# Validate the generated spec
apikit openapi gen --validate

# Clean cache and regenerate
apikit openapi clean && apikit openapi gen
CLI Reference
apikit openapi gen [flags]

Flags:
  -o, --output string       Output file path (default "openapi.yaml")
  -f, --format string       Output format: yaml or json (default "yaml")
  -p, --pattern string      Package pattern to scan (default "./...")
  -d, --dir string          Root directory to scan from (default ".")
      --no-cache            Disable incremental caching
      --flatten             Inline $ref schemas instead of using references
      --validate            Validate the generated spec
      --ignore strings      Path patterns to ignore
      --clean-unused        Remove unreferenced schemas
      --multi-specs         Generate multiple specs based on spec: directives
      --spec string         Generate only a specific spec by name
      --no-default          Skip generating the default spec for untagged routes
      --enum-refs           Generate enums as $ref instead of inline

apikit openapi clean        Remove the .openapi cache directory
apikit openapi status       Show cache statistics

3. sdk gen — Go SDK Generation

Generates a complete, typed Go SDK package from an OpenAPI specification and a .sdkgen.yaml config.

Generated Structure
pkg/sdk/pokemon/
├── client/    # HTTP client with middleware chain
├── config/    # Configuration (gookit/config)
├── models/    # Request/response structs and enums
└── services/  # Service methods per API tag
Examples
# Generate SDK to ./pkg/sdk/pokemon
apikit sdk gen pokemon.sdkgen.yaml -o ./pkg/sdk/pokemon

# Override provider name
apikit sdk gen pokemon.sdkgen.yaml -o ./pkg/sdk/pokemon --provider myProvider
CLI Reference
apikit sdk gen <config.sdkgen.yaml> [flags]

Args:
  config.sdkgen.yaml   Path to SDK config file (required)

Flags:
  -o, --output string     Output directory for generated SDK (required)
      --provider string   Override provider name from config

4. swagger — Swagger UI Management

Downloads and packages Swagger UI assets for embedding in Go applications.

Examples
# Download latest Swagger UI
apikit swagger download -o ./pkg/openapi

# Download specific version
apikit swagger download -v 5.29.4 -o ./pkg/openapi

# Download without default customizations
apikit swagger download --with-defaults=false -o ./pkg/openapi

# Single-spec mode initializer
apikit swagger download --simple -o ./pkg/openapi

# Check latest available version
apikit swagger version
Using the Downloaded Assets
//go:embed swagger-ui.zip
var swaggerUIData []byte

handler, err := swagger.New(swaggerUIData, swagger.Config{
    Specs: map[string][]byte{"api": specData},
})
CLI Reference
apikit swagger download [flags]

Flags:
  -o, --output string    Output directory for swagger-ui.zip (default ".")
  -v, --version string   Specific version to download (default: latest)
      --with-defaults    Include default initializer and CSS (default true)
      --simple           Use simple initializer for single-spec mode

apikit swagger version   Show the latest available Swagger UI version

Workspace Architecture

The repository is a Go workspace (go.work) with 5 independent modules:

Module Import Path Purpose
runtime/ github.com/kausys/apikit/runtime HTTP utilities, error types, validation
scanner/ github.com/kausys/apikit/scanner Go AST scanner for swagger directives
openapi/ github.com/kausys/apikit/openapi OpenAPI spec types, generator, SDK gen, swagger
handler/ github.com/kausys/apikit/handler Handler parser and code generator
cmd/ github.com/kausys/apikit/cmd CLI (apikit binary)

Development

# Build all modules
make build

# Run all tests
make test

# Run tests with coverage
make test-coverage

# Lint all modules
make lint

# Format all modules
make fmt

# Tidy all modules
make tidy

# Full CI check (fmt + lint + tidy check + test)
make ci

# Install apikit locally
make install

# Install dev tools
make setup

License

MIT License — see LICENSE for details.

Documentation

Overview

Package apikit provides runtime helpers for APIKit-generated code

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInternalServer is a generic internal server error
	ErrInternalServer = InternalError("internal server error")

	// ErrSomethingWentWrong is a generic internal server error
	ErrSomethingWentWrong = InternalError("something went wrong")

	// ErrNotImplemented indicates the feature is not implemented
	ErrNotImplemented = NotImplemented("not implemented")

	// ErrUnauthorized indicates authentication is required
	ErrUnauthorized = Unauthorized("authentication required")

	// ErrForbidden indicates access is denied
	ErrForbidden = Forbidden("access denied")

	// ErrInvalidRequest indicates the request is invalid
	ErrInvalidRequest = BadRequest("invalid request")

	// ErrTooManyRequests indicates the client has exceeded the rate limit
	ErrTooManyRequests = TooManyRequests("too many requests")
)
View Source
var CommonTimeFormats = []string{
	time.RFC3339,
	"2006-01-02T15:04:05",
	"2006-01-02T15:04:05.999",
	"2006-01-02T15:04:05.999Z",
	"2006-01-02T15:04:05.999-07:00",
	"2006-01-02 15:04:05",
	"2006-01-02",
}

CommonTimeFormats are the formats tried by NewTimeFromString

Functions

func HandleError

func HandleError(w http.ResponseWriter, err error)

HandleError handles errors with custom status codes

func HandleResponse

func HandleResponse(w http.ResponseWriter, response any, err error)

HandleResponse handles both the response and error from a handler This is the main function used by generated code

func NewTimeFromString

func NewTimeFromString(s string) (time.Time, error)

NewTimeFromString parses a time string using common formats This function is used by APIKit-generated code to parse time.Time fields

Supported formats (tried in order):

  • RFC3339: "2006-01-02T15:04:05Z07:00"
  • "2006-01-02T15:04:05"
  • "2006-01-02T15:04:05.999"
  • "2006-01-02T15:04:05.999Z"
  • "2006-01-02T15:04:05.999-07:00"
  • "2006-01-02 15:04:05"
  • "2006-01-02"

Returns the parsed time.Time or an error if no format matches

func SetLogger added in v0.3.1

func SetLogger(l Logger)

SetLogger overrides the global logger used by all generated handlers.

func WriteJSON

func WriteJSON(w http.ResponseWriter, data any)

WriteJSON writes a JSON response with default 200 OK status

Types

type Error

type Error struct {
	// HTTP status code
	Code int `json:"code"`

	// Semantic error code for client handling
	ErrorCode string `json:"errorCode,omitempty"`

	// Human-readable error message
	Message string `json:"message"`

	// Additional error details
	Details any `json:"details,omitempty"`

	// Request ID for correlation
	RequestID string `json:"requestId,omitempty"`
	// contains filtered or unexported fields
}

Error represents an API error with an HTTP status code

func BadRequest

func BadRequest(message string) *Error

BadRequest creates a 400 error

func Conflict

func Conflict(message string) *Error

Conflict creates a 409 error

func Forbidden

func Forbidden(message string) *Error

Forbidden creates a 403 error

func GatewayTimeout

func GatewayTimeout(message string) *Error

GatewayTimeout creates a 504 error

func InternalError

func InternalError(message string) *Error

InternalError creates a 500 error

func NewError

func NewError(code int, message string) *Error

NewError creates a new API error with the given status code and message

func NewErrorWithDetails

func NewErrorWithDetails(code int, message string, details any) *Error

NewErrorWithDetails creates a new API error with additional details

func NewErrorf

func NewErrorf(code int, format string, args ...any) *Error

NewErrorf creates a new API error with a formatted message

func NotAcceptable

func NotAcceptable(message string) *Error

NotAcceptable creates a 406 error

func NotFound

func NotFound(resource string) *Error

NotFound creates a 404 error

func NotImplemented

func NotImplemented(message string) *Error

NotImplemented creates a 501 error

func ServiceUnavailable

func ServiceUnavailable(message string) *Error

ServiceUnavailable creates a 503 error

func TooManyRequests added in v0.3.1

func TooManyRequests(message string) *Error

TooManyRequests creates a 429 error

func Unauthorized

func Unauthorized(message string) *Error

Unauthorized creates a 401 error

func UnprocessableEntity

func UnprocessableEntity(message string) *Error

UnprocessableEntity creates a 422 error

func WrapError

func WrapError(code int, message string, cause error) *Error

WrapError wraps an existing error with an API error

func (*Error) Error

func (e *Error) Error() string

Error implements the error interface

func (*Error) StatusCode

func (e *Error) StatusCode() int

StatusCode returns the HTTP status code for this error

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap returns the underlying error for error chain support

func (*Error) WithCause

func (e *Error) WithCause(cause error) *Error

WithCause wraps an underlying error

func (*Error) WithDetails

func (e *Error) WithDetails(details any) *Error

WithDetails adds details to the error

func (*Error) WithRequestID

func (e *Error) WithRequestID(requestID string) *Error

WithRequestID adds request ID to the error

type HttpResponse

type HttpResponse struct {
	StatusCode  int               `json:"statusCode"`
	Body        any               `json:"body"`
	Headers     map[string]string `json:"headers"`
	ContentType string            `json:"contentType"`
}

HttpResponse represents an HTTP response with status code, body, headers, and content type

func NewHttpResponse

func NewHttpResponse(statusCode int, body any) *HttpResponse

NewHttpResponse creates a new HttpResponse with the given status code and body

func (*HttpResponse) WithContentType

func (r *HttpResponse) WithContentType(contentType string) *HttpResponse

WithContentType sets a custom content type

func (*HttpResponse) WithHeader

func (r *HttpResponse) WithHeader(key, value string) *HttpResponse

WithHeader adds a single header to the response

func (*HttpResponse) WithHeaders

func (r *HttpResponse) WithHeaders(headers map[string]string) *HttpResponse

WithHeaders adds custom headers to the response

type Logger added in v0.3.1

type Logger interface {
	Error(ctx context.Context, msg string, args ...any)
}

Logger defines the interface for logging errors in generated handlers. Implementations should follow the slog-style key-value pattern for structured logging.

func GetLogger added in v0.3.1

func GetLogger() Logger

GetLogger returns the current global logger.

Directories

Path Synopsis
cmd module
handler module
openapi module
scanner module

Jump to

Keyboard shortcuts

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