contract

package
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Aug 20, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package contract defines Gombit's Huma DTO conventions, the D10 success and error envelopes, and draft §41 application error category mapping.

Public API routes are Huma-typed handlers. Request and response shapes come from Go structs and Huma validation tags — there is no bespoke Bind layer.

Success:

{"data": ...}
{"data": ..., "meta": {"page": 1, "per_page": 20, "total": 125}}

Use contract.DataMeta[T, PageMeta] (or another concrete meta type) so OpenAPI emits a real meta schema. Validation failures (Huma Install path):

{"error":{"code":"validation_error","message":"...","fields":{...},"request_id":"..."}}

Application errors (return contract.NotFound / New / ... via WithContext):

{"error":{"code":"not_found","message":"...","request_id":"..."}}

OpenAPI 3.1 is served at /openapi.json. Interactive docs are at /docs when enabled. Use OpenAPIJSON / WriteOpenAPI to persist the live spec.

See docs/contract.md and docs/openapi.md.

Index

Constants

View Source
const (
	// OpenAPIPath is the Huma OpenAPI prefix. Clients fetch /openapi.json.
	OpenAPIPath = "/openapi"
	// DocsPath is the FastAPI-style interactive docs UI.
	DocsPath = "/docs"
)
View Source
const CodeValidationError = "validation_error"

CodeValidationError is the stable D10 code for request validation failures.

Variables

This section is empty.

Functions

func CodeFor

func CodeFor(cat Category) string

CodeFor returns the stable D10 error.code for a category. Validation keeps the M3-1 / D10 name "validation_error"; other categories use the category string. Unknown categories map to "internal".

func FieldsFromErrors

func FieldsFromErrors(errs ...error) map[string][]string

FieldsFromErrors maps Huma validation detail errors into D10 field errors.

Body locations lose the leading "body." prefix so JSON field names match the request body. Query, path, and header locations keep their prefixes.

func HumaConfig

func HumaConfig(title, version string) huma.Config

HumaConfig returns the default Huma configuration for a Gombit app.

Interactive docs are enabled at /docs (Swagger UI). The schema browser stays disabled. Pass docsEnabled=false to omit the docs route (production default).

func HumaConfigFor

func HumaConfigFor(title, version string, docsEnabled bool) huma.Config

HumaConfigFor returns Huma configuration with docs explicitly enabled or not.

func Install

func Install(opts InstallOptions)

Install replaces Huma's default RFC 9457 Problem Details errors with the D10 envelope. It is safe to call more than once; only the first call applies.

Install only classifies errors built through Huma's NewError hooks (request validation). Application errors from New / NotFound / etc. set status and code via StatusFor / CodeFor and are not reclassified.

func OpenAPIJSON

func OpenAPIJSON(api huma.API) ([]byte, error)

OpenAPIJSON marshals the Huma-generated OpenAPI 3.1 document.

func StatusFor

func StatusFor(cat Category) int

StatusFor returns the HTTP status for a §41 category. Unknown categories map to 500 Internal Server Error.

func WriteOpenAPI

func WriteOpenAPI(path string, api huma.API) error

WriteOpenAPI writes the Huma-generated OpenAPI document to path.

func WriteOpenAPIFile

func WriteOpenAPIFile(path string, spec []byte) error

WriteOpenAPIFile writes a pre-marshaled OpenAPI document to path.

Types

type Category

type Category string

Category is a draft §41 framework error category. Transport adapters map categories to HTTP status codes via StatusFor; they do not leak into service layer return types as raw status integers.

const (
	CategoryValidation            Category = "validation"
	CategoryAuthentication        Category = "authentication"
	CategoryAuthorization         Category = "authorization"
	CategoryNotFound              Category = "not_found"
	CategoryConflict              Category = "conflict"
	CategoryRateLimited           Category = "rate_limited"
	CategoryDependencyUnavailable Category = "dependency_unavailable"
	CategoryInternal              Category = "internal"
)

type Data

type Data[T any] struct {
	Data T `json:"data"`
}

Data is the D10 success envelope without meta: {"data": ...}.

type DataMeta

type DataMeta[T any, M any] struct {
	Data T  `json:"data"`
	Meta *M `json:"meta,omitempty"`
}

DataMeta is the D10 success envelope with typed meta: {"data": ..., "meta": ...}.

Use a concrete meta type so OpenAPI emits a real schema (not empty object). Prefer a pointer meta value so omitempty drops absent meta:

contract.DataMeta[[]Widget, PageMeta]{Data: items, Meta: &contract.PageMeta{...}}

A non-nil zero PageMeta still serializes (omitempty does not treat structs as empty).

type ErrorBody

type ErrorBody struct {
	Code      string              `json:"code"`
	Message   string              `json:"message"`
	Fields    map[string][]string `json:"fields,omitempty"`
	RequestID string              `json:"request_id,omitempty"`
}

ErrorBody is the D10 error object nested under "error".

type ErrorEnvelope

type ErrorEnvelope struct {
	Body ErrorBody `json:"error"`
	// contains filtered or unexported fields
}

ErrorEnvelope is the D10 error response body and a huma.StatusError.

It intentionally does not implement huma.ContentTypeFilter so responses keep Content-Type application/json instead of application/problem+json.

func Authentication

func Authentication(message string) *ErrorEnvelope

Authentication returns an authentication category error (HTTP 401). Wrap with WithContext in handlers to attach request_id.

func Authorization

func Authorization(message string) *ErrorEnvelope

Authorization returns an authorization category error (HTTP 403). Wrap with WithContext in handlers to attach request_id.

func Conflict

func Conflict(message string) *ErrorEnvelope

Conflict returns a conflict category error (HTTP 409). Wrap with WithContext in handlers to attach request_id.

func DependencyUnavailable

func DependencyUnavailable(message string) *ErrorEnvelope

DependencyUnavailable returns a dependency_unavailable error (HTTP 503). Wrap with WithContext in handlers to attach request_id.

func Internal

func Internal(message string) *ErrorEnvelope

Internal returns an internal category error (HTTP 500). Wrap with WithContext in handlers to attach request_id.

func New

func New(cat Category, message string) *ErrorEnvelope

New builds a D10 ErrorEnvelope from a §41 category and message.

Callers should wrap with WithContext so request_id is populated:

return nil, contract.WithContext(ctx, contract.New(contract.CategoryNotFound, "missing"))

func NotFound

func NotFound(message string) *ErrorEnvelope

NotFound returns a not_found category error (HTTP 404). Wrap with WithContext in handlers to attach request_id.

func RateLimited

func RateLimited(message string) *ErrorEnvelope

RateLimited returns a rate_limited category error (HTTP 429). Wrap with WithContext in handlers to attach request_id.

func Validation

func Validation(message string, fields map[string][]string) *ErrorEnvelope

Validation returns a validation category error (HTTP 422, code validation_error). Wrap with WithContext in handlers to attach request_id.

func WithContext

func WithContext(ctx context.Context, err *ErrorEnvelope) *ErrorEnvelope

WithContext returns err with request_id filled from Install's RequestID reader when available. Application handlers should wrap category errors:

return nil, contract.WithContext(ctx, contract.NotFound("missing"))

func (*ErrorEnvelope) Error

func (e *ErrorEnvelope) Error() string

Error satisfies the error interface.

func (*ErrorEnvelope) GetStatus

func (e *ErrorEnvelope) GetStatus() int

GetStatus returns the HTTP status for this error.

func (*ErrorEnvelope) WithFields

func (e *ErrorEnvelope) WithFields(fields map[string][]string) *ErrorEnvelope

WithFields returns a shallow copy with D10 fields set. The error code stays the category code (not forced to validation_error).

func (*ErrorEnvelope) WithRequestID

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

WithRequestID returns a shallow copy with request_id set (for tests/helpers).

type InstallOptions

type InstallOptions struct {
	// RequestID reads the active request ID from a request context.
	RequestID func(context.Context) string
}

InstallOptions configures Huma error installation.

type PageMeta

type PageMeta struct {
	Page    int   `json:"page"`
	PerPage int   `json:"per_page"`
	Total   int64 `json:"total"`
}

PageMeta is the conventional pagination meta object for collection responses. It is the v0.1 typed default for list endpoints; other meta shapes can use the second type parameter on DataMeta when needed.

Jump to

Keyboard shortcuts

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