Documentation
¶
Index ¶
- type App
- func (a *App) Handler() http.Handler
- func (a *App) Routes() internal.RouteMap
- func (a *App) Service(name string) *Service
- func (a *App) WithErrorTransformer(fn ErrorTransformer) *App
- func (a *App) WithLogger(logger *slog.Logger) *App
- func (a *App) WithMaskInternalErrors() *App
- func (a *App) WithMaxRequestBodySize(size uint64) *App
- func (a *App) WithMiddleware(mw func(http.Handler) http.Handler) *App
- func (a *App) WithUnaryInterceptor(i UnaryInterceptor) *App
- type CacheConfig
- type Context
- type Empty
- type Endpoint
- type Error
- type ErrorCode
- type ErrorTransformer
- type ExecHandler
- func (h *ExecHandler[Req, Res]) Metadata() *internal.MethodMetadata
- func (h *ExecHandler[Req, Res]) WithMaxRequestBodySize(size uint64) *ExecHandler[Req, Res]
- func (h *ExecHandler[Req, Res]) WithSkipValidation() *ExecHandler[Req, Res]
- func (h *ExecHandler[Req, Res]) WithUnaryInterceptor(i UnaryInterceptor) *ExecHandler[Req, Res]
- type HandlerFunc
- type QueryHandler
- func (h *QueryHandler[Req, Res]) CacheControl(cfg CacheConfig) *QueryHandler[Req, Res]
- func (h *QueryHandler[Req, Res]) Metadata() *internal.MethodMetadata
- func (h *QueryHandler[Req, Res]) WithSkipValidation() *QueryHandler[Req, Res]
- func (h *QueryHandler[Req, Res]) WithStrictQueryParams() *QueryHandler[Req, Res]
- func (h *QueryHandler[Req, Res]) WithUnaryInterceptor(i UnaryInterceptor) *QueryHandler[Req, Res]
- type Service
- type UnaryInterceptor
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type App ¶ added in v0.6.1
type App struct {
// contains filtered or unexported fields
}
App is the central router for API handlers. It manages route registration, middleware, interceptors, and error handling. Use Handler() to get an http.Handler for use with http.ListenAndServe.
func (*App) Handler ¶ added in v0.6.1
Handler returns an http.Handler for use with http.ListenAndServe or other HTTP servers. The returned handler includes all configured middleware.
Example:
app := tygor.NewApp().WithMiddleware(cors)
http.ListenAndServe(":8080", app.Handler())
func (*App) Routes ¶ added in v0.6.1
Routes returns route metadata for code generation. The return type is internal; this method is for use by tygorgen only.
func (*App) WithErrorTransformer ¶ added in v0.6.1
func (a *App) WithErrorTransformer(fn ErrorTransformer) *App
WithErrorTransformer adds a custom error transformer. It returns the app for chaining.
func (*App) WithLogger ¶ added in v0.6.1
WithLogger sets a custom logger for the app. If not set, slog.Default() will be used.
func (*App) WithMaskInternalErrors ¶ added in v0.6.1
WithMaskInternalErrors enables masking of internal error messages. This is useful in production to avoid leaking sensitive information. The original error is still available to interceptors and logging.
func (*App) WithMaxRequestBodySize ¶ added in v0.6.1
WithMaxRequestBodySize sets the default maximum request body size for all handlers. Individual handlers can override this with Handler.WithMaxRequestBodySize. A value of 0 means no limit. Default is 1MB (1 << 20).
func (*App) WithMiddleware ¶ added in v0.6.1
WithMiddleware adds an HTTP middleware to wrap the app. Middleware is applied in the order added (first added is outermost).
func (*App) WithUnaryInterceptor ¶ added in v0.6.1
func (a *App) WithUnaryInterceptor(i UnaryInterceptor) *App
WithUnaryInterceptor adds a global interceptor. Global interceptors are executed before service-level and handler-level interceptors.
Interceptor execution order:
- Global interceptors (added via App.WithUnaryInterceptor)
- Service interceptors (added via Service.WithUnaryInterceptor)
- Handler interceptors (added via Handler.WithUnaryInterceptor)
- Handler function
Within each level, interceptors execute in the order they were added.
type CacheConfig ¶
type CacheConfig struct {
// MaxAge specifies the maximum time a resource is considered fresh (RFC 9111 Section 5.2.2.1).
// After this time, caches must revalidate before serving the cached response.
MaxAge time.Duration
// SMaxAge is like MaxAge but only applies to shared caches like CDNs (RFC 9111 Section 5.2.2.10).
// Overrides MaxAge for shared caches. Private caches ignore this directive.
SMaxAge time.Duration
// StaleWhileRevalidate allows serving stale content while revalidating in the background (RFC 5861).
// Example: MaxAge=60s, StaleWhileRevalidate=300s means serve from cache for 60s,
// then serve stale content for up to 300s more while fetching fresh data in background.
StaleWhileRevalidate time.Duration
// StaleIfError allows serving stale content if the origin server is unavailable (RFC 5861).
// Example: StaleIfError=86400 allows serving day-old stale content if origin returns 5xx errors.
StaleIfError time.Duration
// Public indicates the response may be cached by any cache, including CDNs (RFC 9111 Section 5.2.2.9).
// Default is false (private), meaning only the user's browser cache may store it.
// Set to true for responses that are safe to cache publicly.
Public bool
// MustRevalidate requires caches to revalidate stale responses with the origin before serving (RFC 9111 Section 5.2.2.2).
// Prevents serving stale content. Useful when stale data could cause problems.
MustRevalidate bool
// Immutable indicates the response will never change during its freshness lifetime (RFC 8246).
// Browsers won't send conditional requests for immutable resources within MaxAge period.
// Useful for content-addressed assets like "bundle.abc123.js".
Immutable bool
}
CacheConfig defines HTTP cache directives for GET requests. See RFC 9111 (HTTP Caching) for detailed semantics.
Common patterns:
- Simple caching: CacheConfig{MaxAge: 5*time.Minute}
- Public CDN caching: CacheConfig{MaxAge: 5*time.Minute, Public: true}
- Stale-while-revalidate: CacheConfig{MaxAge: 1*time.Minute, StaleWhileRevalidate: 5*time.Minute}
- Immutable assets: CacheConfig{MaxAge: 365*24*time.Hour, Immutable: true}
type Context ¶ added in v0.6.0
type Context interface {
context.Context
// Service returns the name of the service being called.
Service() string
// EndpointID returns the full identifier for the endpoint being called (e.g., "Users.Create").
EndpointID() string
// HTTPRequest returns the underlying HTTP request.
HTTPRequest() *http.Request
// HTTPWriter returns the underlying HTTP response writer.
// Use with caution in handlers - prefer returning errors to writing directly.
// This is useful for setting response headers.
HTTPWriter() http.ResponseWriter
}
Context provides type-safe access to request metadata and HTTP primitives. It embeds context.Context, so it can be used anywhere a context.Context is expected.
Interceptors receive Context directly for convenient access to request metadata. Handlers receive context.Context but can use FromContext to get the Context if needed.
For testing interceptors, implement this interface with your own type:
type testContext struct {
context.Context
service, method string
}
func (c *testContext) Service() string { return c.service }
func (c *testContext) EndpointID() string { return c.service + "." + c.method }
func (c *testContext) HTTPRequest() *http.Request { return nil }
func (c *testContext) HTTPWriter() http.ResponseWriter { return nil }
func FromContext ¶ added in v0.6.0
FromContext extracts the Context from a context.Context. Returns the Context and true if found, or nil and false if not in a tygor handler context.
This is useful in handlers that receive context.Context but need access to request metadata:
func (s *MyService) GetThing(ctx context.Context, req *GetThingRequest) (*GetThingResponse, error) {
tc, ok := tygor.FromContext(ctx)
if ok {
log.Printf("handling %s", tc.EndpointID())
}
// ...
}
type Empty ¶
type Empty *struct{}
Empty represents a void request or response. Use this for operations that don't return meaningful data. The zero value is nil, which serializes to JSON null.
Example:
func DeleteUser(ctx context.Context, req *DeleteUserRequest) (tygor.Empty, error) {
// ... delete user
return nil, nil
}
Wire format: {"result": null}
type Endpoint ¶ added in v0.7.0
type Endpoint interface {
// Metadata returns route metadata for code generation.
// The return type is internal; this method is for use by tygorgen only.
Metadata() *internal.MethodMetadata
}
Endpoint is the interface for handlers that can be registered with Service.Register.
Implementations:
- *ExecHandler - for POST requests (created with Exec)
- *QueryHandler - for GET requests (created with Query)
type Error ¶
type Error struct {
Code ErrorCode `json:"code"`
Message string `json:"message"`
Details map[string]any `json:"details,omitempty"`
}
Error is the standard JSON error envelope.
func DefaultErrorTransformer ¶
DefaultErrorTransformer maps standard Go errors to service errors.
func (*Error) WithDetail ¶ added in v0.6.1
WithDetail returns a new Error with the key-value pair added to details.
type ErrorCode ¶
type ErrorCode string
ErrorCode represents a machine-readable error code.
const ( CodeInvalidArgument ErrorCode = "invalid_argument" CodeUnauthenticated ErrorCode = "unauthenticated" CodePermissionDenied ErrorCode = "permission_denied" CodeNotFound ErrorCode = "not_found" CodeMethodNotAllowed ErrorCode = "method_not_allowed" CodeConflict ErrorCode = "conflict" CodeAlreadyExists ErrorCode = "already_exists" // Alias for conflict, used when resource already exists CodeGone ErrorCode = "gone" CodeResourceExhausted ErrorCode = "resource_exhausted" CodeCanceled ErrorCode = "canceled" CodeInternal ErrorCode = "internal" CodeNotImplemented ErrorCode = "not_implemented" CodeDeadlineExceeded ErrorCode = "deadline_exceeded" )
func (ErrorCode) HTTPStatus ¶ added in v0.6.0
HTTPStatus maps an ErrorCode to an HTTP status code.
type ErrorTransformer ¶
ErrorTransformer is a function that maps an application error to a service error. If it returns nil, the default transformer logic should be applied.
type ExecHandler ¶ added in v0.6.2
ExecHandler implements Endpoint for POST requests (state-changing operations).
Request Type Guidelines:
- Use struct or pointer types
- Request is decoded from JSON body
Example:
func CreateUser(ctx context.Context, req *CreateUserRequest) (*User, error) { ... }
Exec(CreateUser)
func UpdatePost(ctx context.Context, req *UpdatePostRequest) (*Post, error) { ... }
Exec(UpdatePost).WithUnaryInterceptor(requireAuth)
func Exec ¶ added in v0.6.2
Exec creates a new POST handler from a generic function for non-streaming API calls.
The handler function signature is func(context.Context, Req) (Res, error). Requests are decoded from JSON body.
For GET requests (cacheable reads), use Query instead.
func (*ExecHandler[Req, Res]) Metadata ¶ added in v0.6.2
func (h *ExecHandler[Req, Res]) Metadata() *internal.MethodMetadata
Metadata implements Endpoint.
func (*ExecHandler[Req, Res]) WithMaxRequestBodySize ¶ added in v0.6.2
func (h *ExecHandler[Req, Res]) WithMaxRequestBodySize(size uint64) *ExecHandler[Req, Res]
WithMaxRequestBodySize sets the maximum request body size for this handler. This overrides the registry-level default. A value of 0 means no limit.
func (*ExecHandler[Req, Res]) WithSkipValidation ¶ added in v0.6.2
func (h *ExecHandler[Req, Res]) WithSkipValidation() *ExecHandler[Req, Res]
WithSkipValidation disables validation for this handler. By default, all handlers validate requests using the validator package. Use this when you need to handle validation manually or when the request type has no validation tags.
func (*ExecHandler[Req, Res]) WithUnaryInterceptor ¶ added in v0.6.2
func (h *ExecHandler[Req, Res]) WithUnaryInterceptor(i UnaryInterceptor) *ExecHandler[Req, Res]
WithUnaryInterceptor adds an interceptor to this handler. Handler interceptors execute after global and service interceptors. See App.WithUnaryInterceptor for the complete execution order.
type HandlerFunc ¶
HandlerFunc represents the next handler in an interceptor chain. It is passed to UnaryInterceptor functions to invoke the next interceptor or the final handler.
type QueryHandler ¶ added in v0.6.2
QueryHandler implements Endpoint for GET requests (cacheable read operations).
Request Type Guidelines:
- Use struct types for simple cases, pointer types when you need optional fields
- Request parameters are decoded from URL query string
Struct vs Pointer Types:
- Struct types (e.g., ListParams): Query parameters are decoded directly into the struct
- Pointer types (e.g., *ListParams): A new instance is created and query parameters are decoded into it
Example:
func ListPosts(ctx context.Context, req ListPostsParams) ([]*Post, error) { ... }
Query(ListPosts).CacheControl(tygor.CacheConfig{
MaxAge: 5 * time.Minute,
Public: true,
})
func Query ¶ added in v0.6.2
Query creates a new GET handler from a generic function for cacheable read operations.
The handler function signature is func(context.Context, Req) (Res, error). Requests are decoded from URL query parameters.
Use CacheControl() to configure HTTP caching behavior.
func (*QueryHandler[Req, Res]) CacheControl ¶ added in v0.6.2
func (h *QueryHandler[Req, Res]) CacheControl(cfg CacheConfig) *QueryHandler[Req, Res]
CacheControl sets detailed HTTP cache directives for the handler. See CacheConfig documentation and RFC 9111 for directive semantics.
Example:
Query(ListPosts).CacheControl(tygor.CacheConfig{
MaxAge: 5 * time.Minute,
StaleWhileRevalidate: 1 * time.Minute,
Public: true,
})
// Sets: Cache-Control: public, max-age=300, stale-while-revalidate=60
func (*QueryHandler[Req, Res]) Metadata ¶ added in v0.6.2
func (h *QueryHandler[Req, Res]) Metadata() *internal.MethodMetadata
Metadata implements Endpoint.
func (*QueryHandler[Req, Res]) WithSkipValidation ¶ added in v0.6.2
func (h *QueryHandler[Req, Res]) WithSkipValidation() *QueryHandler[Req, Res]
WithSkipValidation disables validation for this handler. By default, all handlers validate requests using the validator package. Use this when you need to handle validation manually or when the request type has no validation tags.
func (*QueryHandler[Req, Res]) WithStrictQueryParams ¶ added in v0.6.2
func (h *QueryHandler[Req, Res]) WithStrictQueryParams() *QueryHandler[Req, Res]
WithStrictQueryParams enables strict query parameter validation for GET requests. By default, unknown query parameters are ignored (lenient mode). When enabled, requests with unknown query parameters will return an error. This helps catch typos and enforces exact parameter expectations.
func (*QueryHandler[Req, Res]) WithUnaryInterceptor ¶ added in v0.6.2
func (h *QueryHandler[Req, Res]) WithUnaryInterceptor(i UnaryInterceptor) *QueryHandler[Req, Res]
WithUnaryInterceptor adds an interceptor to this handler. Handler interceptors execute after global and service interceptors. See App.WithUnaryInterceptor for the complete execution order.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
func (*Service) Register ¶
Register registers a handler for the given operation name. If a handler is already registered for this service and method, it will be replaced and a warning will be logged.
func (*Service) WithUnaryInterceptor ¶
func (s *Service) WithUnaryInterceptor(i UnaryInterceptor) *Service
WithUnaryInterceptor adds an interceptor to this service. Service interceptors execute after global interceptors but before handler interceptors. See App.WithUnaryInterceptor for the complete execution order.
type UnaryInterceptor ¶
type UnaryInterceptor func(ctx Context, req any, handler HandlerFunc) (res any, err error)
UnaryInterceptor is a hook that wraps handler execution for unary (non-streaming) calls.
Interceptors receive Context for type-safe access to request metadata:
func loggingInterceptor(ctx tygor.Context, req any, handler tygor.HandlerFunc) (any, error) {
start := time.Now()
res, err := handler(ctx, req)
log.Printf("%s took %v", ctx.EndpointID(), time.Since(start))
return res, err
}
The handler parameter is the next handler in the chain. Interceptors can:
- Inspect/modify the request before calling handler
- Inspect/modify the response after calling handler
- Short-circuit by returning an error without calling handler
- Add values to context using context.WithValue
req/res are pointers to the request/response structs.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package devtools provides a devtools service for the tygor vite plugin.
|
Package devtools provides a devtools service for the tygor vite plugin. |
|
Package discovery provides utilities for serving API discovery documents.
|
Package discovery provides utilities for serving API discovery documents. |
|
doc
|
|
|
examples/quickstart
Package quickstart provides simple example code for documentation.
|
Package quickstart provides simple example code for documentation. |
|
examples/tygorgen
Package tygorgen provides example usage for tygorgen documentation.
|
Package tygorgen provides example usage for tygorgen documentation. |
|
examples
module
|
|
|
Package internal contains types for code generation.
|
Package internal contains types for code generation. |
|
testfixtures
Package testfixtures provides types used for testing the tygorgen package.
|
Package testfixtures provides types used for testing the tygorgen package. |
|
tgrcontext
Package tgrcontext provides the shared context key for tygor.
|
Package tgrcontext provides the shared context key for tygor. |
|
tygortest
Package tygortest provides testing helpers for HTTP handlers and tygor service handlers.
|
Package tygortest provides testing helpers for HTTP handlers and tygor service handlers. |
|
ir
Package ir defines the Intermediate Representation for Go type descriptors.
|
Package ir defines the Intermediate Representation for Go type descriptors. |
|
provider
Package provider implements input providers for extracting type information from Go code.
|
Package provider implements input providers for extracting type information from Go code. |
|
sink
Package sink provides output destinations for generated code.
|
Package sink provides output destinations for generated code. |
|
typescript
Package typescript generates TypeScript type definitions from IR schemas.
|
Package typescript generates TypeScript type definitions from IR schemas. |
|
typescript/flavor
Package flavor provides the interface and utilities for TypeScript output flavors.
|
Package flavor provides the interface and utilities for TypeScript output flavors. |