Introduction

API reference

Complete function signatures for every exported type, function, and constant across all framework packages. Use this page to discover exact APIs without reading source code.


pkg/http

import "github.com/stanza-go/framework/pkg/http"

Type aliases

type Handler = net/http.Handler
type HandlerFunc = net/http.HandlerFunc
type ResponseWriter = net/http.ResponseWriter
type Request = net/http.Request
type Middleware func(Handler) Handler

Router

func NewRouter() *Router
func (r *Router) HandleFunc(pattern string, handler func(ResponseWriter, *Request))
func (r *Router) Handle(pattern string, handler Handler)
func (r *Router) Use(mw ...Middleware)
func (r *Router) Group(prefix string) *Group
func (r *Router) Routes() []Route
func (r *Router) ServeHTTP(w ResponseWriter, req *Request)

Group has the same registration methods:

func (g *Group) HandleFunc(pattern string, handler func(ResponseWriter, *Request))
func (g *Group) Handle(pattern string, handler Handler)
func (g *Group) Use(mw ...Middleware)
func (g *Group) Group(prefix string) *Group

Route — returned by Routes():

type Route struct {
    Method string
    Path   string
}

Server

func NewServer(handler Handler, opts ...ServerOption) *Server
func (s *Server) Start(ctx context.Context) error
func (s *Server) Stop(ctx context.Context) error
func (s *Server) Addr() string

// Options
func WithAddr(addr string) ServerOption
func WithReadTimeout(d time.Duration) ServerOption
func WithWriteTimeout(d time.Duration) ServerOption
func WithIdleTimeout(d time.Duration) ServerOption
func WithMaxHeaderBytes(n int) ServerOption

Response writing

func WriteJSON(w ResponseWriter, status int, v any)
func WriteError(w ResponseWriter, status int, message string)
func WriteServerError(w ResponseWriter, r *Request, message string, err error)
func WriteCSV(w ResponseWriter, entity string, header []string, fn func() []string)

Request parsing

// Path parameters
func PathParam(r *Request, name string) string
func PathParamInt64(w ResponseWriter, r *Request, name string) (int64, bool)

// Query parameters
func QueryParam(r *Request, name string) string
func QueryParamOr(r *Request, name, fallback string) string
func QueryParamInt(r *Request, name string, fallback int) int
func QueryParamSort(r *Request, allowed []string, defaultCol, defaultDir string) (string, string)
    // Reads ?sort=col&order=ASC|DESC from query string. Validates col against allowed list.

// Request body
func ReadJSON(r *Request, v any) error
func ReadJSONLimit(r *Request, v any, maxBytes int64) error
func BindJSON(w ResponseWriter, r *Request, v any) bool

Pagination

type Pagination struct {
    Limit  int
    Offset int
}

func ParsePagination(r *Request, defaultLimit, maxLimit int) Pagination
func PaginatedResponse(w ResponseWriter, key string, items any, total int)
func CheckBulkIDs(w ResponseWriter, ids []int64, maxCount int) bool

Middleware

func Recovery(onPanic func(recovered any, stack []byte)) Middleware
func RequestLogger(logger *log.Logger) Middleware
func MaxBody(limit int64) Middleware
func SecureHeaders(cfg SecureHeadersConfig) Middleware
func CORS(cfg CORSConfig) Middleware
func RateLimit(cfg RateLimitConfig) Middleware
func RequestID(cfg RequestIDConfig) Middleware
func Compress(cfg CompressConfig) Middleware
func ETag(cfg ETagConfig) Middleware

Config structs:

type SecureHeadersConfig struct {
    FrameOptions        string
    ReferrerPolicy      string
    PermissionsPolicy   string
    HSTSMaxAge          int
    ContentSecurityPolicy string
}

type CORSConfig struct {
    AllowOrigins     []string
    AllowMethods     []string
    AllowHeaders     []string
    AllowCredentials bool
    MaxAge           int
}

type RateLimitConfig struct {
    Limit   int
    Window  time.Duration
    KeyFunc func(*Request) string
    Message string
}

type RequestIDConfig struct {
    Header    string
    Generator func() string
}

type CompressConfig struct {
    Level        int
    MinSize      int
    ContentTypes []string
}

type ETagConfig struct {
    Weak bool
}

Request utilities

func ClientIP(r *Request) string
func GetRequestID(r *Request) string

Static file serving

func Static(fsys fs.FS) Handler

Server-Sent Events

func NewSSEWriter(w ResponseWriter) *SSEWriter
func (s *SSEWriter) Event(event, data string) error
func (s *SSEWriter) Data(data string) error
func (s *SSEWriter) Comment(text string) error
func (s *SSEWriter) Retry(ms int) error

WebSocket

type Upgrader struct {
    ReadBufferSize  int
    WriteBufferSize int
    CheckOrigin     func(r *Request) bool
}

func (u Upgrader) Upgrade(w ResponseWriter, r *Request) (*Conn, error)

func (c *Conn) ReadMessage() (MessageType, []byte, error)
func (c *Conn) WriteMessage(messageType MessageType, data []byte) error
func (c *Conn) WritePing(data []byte) error
func (c *Conn) WritePong(data []byte) error
func (c *Conn) Close() error
func (c *Conn) CloseWithMessage(code int, text string) error
func (c *Conn) SetMaxMessageSize(limit int64)
func (c *Conn) SetReadDeadline(t time.Time) error
func (c *Conn) SetWriteDeadline(t time.Time) error
func (c *Conn) SetPingHandler(h func(data []byte) error)
func (c *Conn) SetPongHandler(h func(data []byte) error)
func (c *Conn) RemoteAddr() net.Addr
func GenerateKey() string

Message types: TextMessage = 1, BinaryMessage = 2, CloseMessage = 8, PingMessage = 9, PongMessage = 10

Close codes: CloseNormalClosure = 1000, CloseGoingAway = 1001, CloseProtocolError = 1002, CloseUnsupportedData = 1003, CloseNoStatusReceived = 1005, CloseAbnormalClosure = 1006, CloseInvalidPayload = 1007, ClosePolicyViolation = 1008, CloseMessageTooBig = 1009

Metrics

func NewMetrics() *Metrics
func (m *Metrics) Middleware() Middleware
func (m *Metrics) Stats() MetricsStats

type MetricsStats struct {
    TotalRequests  int64
    ActiveRequests int64
    Status2xx      int64
    Status3xx      int64
    Status4xx      int64
    Status5xx      int64
    BytesWritten   int64
    AvgDurationMs  float64
}

Prometheus

func RuntimeMetrics() []PrometheusMetric
func PrometheusHandler(collect func() []PrometheusMetric) HandlerFunc

type PrometheusMetric struct {
    Name  string
    Help  string
    Type  string
    Value float64
}

HTTP status constants

ConstantValue
StatusOK200
StatusCreated201
StatusNoContent204
StatusMovedPermanently301
StatusFound302
StatusSeeOther303
StatusNotModified304
StatusTemporaryRedirect307
StatusPermanentRedirect308
StatusBadRequest400
StatusUnauthorized401
StatusForbidden403
StatusNotFound404
StatusMethodNotAllowed405
StatusConflict409
StatusGone410
StatusRequestEntityTooLarge413
StatusUnprocessableEntity422
StatusTooManyRequests429
StatusInternalServerError500
StatusBadGateway502
StatusServiceUnavailable503

Errors

var ErrBodyTooLarge = errors.New("http: request body too large")
var ErrCloseSent = errors.New("websocket: close frame already sent")
var ErrReadLimit = errors.New("websocket: message exceeds read limit")

pkg/sqlite

import "github.com/stanza-go/framework/pkg/sqlite"

Database

func New(path string, opts ...Option) *DB
func (db *DB) Start(ctx context.Context) error
func (db *DB) Stop(ctx context.Context) error
func (db *DB) Path() string
func (db *DB) Stats() DBStats
func (db *DB) IntegrityCheck() error
func (db *DB) Optimize() error
func (db *DB) Backup(destPath string) error
func (db *DB) LastBackupPath() string

// Options
func WithBusyTimeout(ms int) Option
func WithReadPoolSize(n int) Option
func WithPragma(pragma string) Option
func WithLogger(l *log.Logger) Option
func WithSlowThreshold(d time.Duration) Option

DBStats fields: ReadPoolSize int, ReadPoolAvailable int, ReadPoolInUse int, TotalReads int64, TotalWrites int64, PoolWaits int64, PoolWaitTime time.Duration, FileSize int64, WALSize int64

Queries

func (db *DB) Exec(sql string, args ...any) (Result, error)
func (db *DB) Query(sql string, args ...any) (*Rows, error)
func (db *DB) QueryRow(sql string, args ...any) *Row
func (db *DB) Count(sb *SelectBuilder) (int, error)
func (db *DB) Insert(ib *InsertBuilder) (int64, error)
func (db *DB) Update(ub *UpdateBuilder) (int64, error)
func (db *DB) Delete(d *DeleteBuilder) (int64, error)

Result fields: LastInsertID int64, RowsAffected int64

Generic query helpers

func QueryOne[T any](db *DB, sql string, args []any, scan func(*Rows) (T, error)) (T, error)
func QueryAll[T any](db *DB, sql string, args []any, scan func(*Rows) (T, error)) ([]T, error)

Rows and Row

func (r *Rows) Next() bool
func (r *Rows) Scan(dest ...any) error
func (r *Rows) Columns() []string
func (r *Rows) Err() error
func (r *Rows) Close() error

func (r *Row) Scan(dest ...any) error
func (r *Row) Err() error

Transactions

func (db *DB) Begin() (*Tx, error)
func (db *DB) InTx(fn func(*Tx) error) error

func (tx *Tx) Commit() error
func (tx *Tx) Rollback() error
func (tx *Tx) Exec(sql string, args ...any) (Result, error)
func (tx *Tx) Query(sql string, args ...any) (*Rows, error)
func (tx *Tx) QueryRow(sql string, args ...any) *Row
func (tx *Tx) ExecMany(sql string, argSets [][]any) error
func (tx *Tx) Insert(ib *InsertBuilder) (int64, error)
func (tx *Tx) Update(ub *UpdateBuilder) (int64, error)
func (tx *Tx) Delete(d *DeleteBuilder) (int64, error)

Migrations

func (db *DB) AddMigration(version int64, name string, up, down func(tx *Tx) error)
func (db *DB) Migrate() (int, error)
func (db *DB) Rollback() (int64, error)

Execution interfaces

// Satisfied by DB and Tx — accepted by builder execution methods.
type Execer interface {
    Exec(sql string, args ...any) (Result, error)
}
type Querier interface {
    Query(sql string, args ...any) (*Rows, error)
    QueryRow(sql string, args ...any) *Row
}

SelectBuilder

func Select(columns ...string) *SelectBuilder
func (b *SelectBuilder) From(table string) *SelectBuilder
func (b *SelectBuilder) Distinct() *SelectBuilder
func (b *SelectBuilder) Where(cond string, args ...any) *SelectBuilder
func (b *SelectBuilder) WhereNull(column string) *SelectBuilder
func (b *SelectBuilder) WhereNotNull(column string) *SelectBuilder
func (b *SelectBuilder) WhereIn(column string, values ...any) *SelectBuilder
func (b *SelectBuilder) WhereNotIn(column string, values ...any) *SelectBuilder
func (b *SelectBuilder) WhereOr(conds ...Condition) *SelectBuilder
func (b *SelectBuilder) WhereSearch(search string, columns ...string) *SelectBuilder
func (b *SelectBuilder) WhereInSelect(column string, sub *SelectBuilder) *SelectBuilder
func (b *SelectBuilder) WhereNotInSelect(column string, sub *SelectBuilder) *SelectBuilder
func (b *SelectBuilder) WhereExists(sub *SelectBuilder) *SelectBuilder
func (b *SelectBuilder) WhereNotExists(sub *SelectBuilder) *SelectBuilder
func (b *SelectBuilder) Join(table, on string) *SelectBuilder
func (b *SelectBuilder) LeftJoin(table, on string) *SelectBuilder
func (b *SelectBuilder) GroupBy(columns ...string) *SelectBuilder
func (b *SelectBuilder) Having(cond string, args ...any) *SelectBuilder
func (b *SelectBuilder) OrderBy(column, dir string) *SelectBuilder
func (b *SelectBuilder) Limit(n int) *SelectBuilder
func (b *SelectBuilder) Offset(n int) *SelectBuilder
func (b *SelectBuilder) Build() (string, []any)
func (b *SelectBuilder) Query(q Querier) (*Rows, error)
func (b *SelectBuilder) QueryRow(q Querier) *Row

CountBuilder

func Count(table string) *CountBuilder
func CountFrom(sb *SelectBuilder) *CountBuilder
func (b *CountBuilder) Where(cond string, args ...any) *CountBuilder
func (b *CountBuilder) WhereNull(column string) *CountBuilder
func (b *CountBuilder) WhereNotNull(column string) *CountBuilder
func (b *CountBuilder) WhereIn(column string, values ...any) *CountBuilder
func (b *CountBuilder) WhereNotIn(column string, values ...any) *CountBuilder
func (b *CountBuilder) WhereOr(conds ...Condition) *CountBuilder
func (b *CountBuilder) WhereSearch(search string, columns ...string) *CountBuilder
func (b *CountBuilder) WhereInSelect(column string, sub *SelectBuilder) *CountBuilder
func (b *CountBuilder) WhereNotInSelect(column string, sub *SelectBuilder) *CountBuilder
func (b *CountBuilder) WhereExists(sub *SelectBuilder) *CountBuilder
func (b *CountBuilder) WhereNotExists(sub *SelectBuilder) *CountBuilder
func (b *CountBuilder) Build() (string, []any)
func (b *CountBuilder) Count(q Querier) (int, error)

InsertBuilder

func Insert(table string) *InsertBuilder
func (b *InsertBuilder) Set(column string, value any) *InsertBuilder
func (b *InsertBuilder) OrIgnore() *InsertBuilder
func (b *InsertBuilder) OnConflict(conflictColumns, updateColumns []string) *InsertBuilder
func (b *InsertBuilder) Build() (string, []any)
func (b *InsertBuilder) Exec(e Execer) (int64, error)

InsertBatchBuilder

func InsertBatch(table string) *InsertBatchBuilder
func (b *InsertBatchBuilder) Columns(columns ...string) *InsertBatchBuilder
func (b *InsertBatchBuilder) Row(values ...any) *InsertBatchBuilder
func (b *InsertBatchBuilder) OrIgnore() *InsertBatchBuilder
func (b *InsertBatchBuilder) OnConflict(conflictColumns, updateColumns []string) *InsertBatchBuilder
func (b *InsertBatchBuilder) Build() (string, []any)
func (b *InsertBatchBuilder) Exec(e Execer) (int64, error)

UpdateBuilder

func Update(table string) *UpdateBuilder
func (b *UpdateBuilder) Set(column string, value any) *UpdateBuilder
func (b *UpdateBuilder) SetExpr(column, expr string, args ...any) *UpdateBuilder
func (b *UpdateBuilder) Where(cond string, args ...any) *UpdateBuilder
func (b *UpdateBuilder) WhereNull(column string) *UpdateBuilder
func (b *UpdateBuilder) WhereNotNull(column string) *UpdateBuilder
func (b *UpdateBuilder) WhereIn(column string, values ...any) *UpdateBuilder
func (b *UpdateBuilder) WhereNotIn(column string, values ...any) *UpdateBuilder
func (b *UpdateBuilder) WhereOr(conds ...Condition) *UpdateBuilder
func (b *UpdateBuilder) WhereSearch(search string, columns ...string) *UpdateBuilder
func (b *UpdateBuilder) WhereInSelect(column string, sub *SelectBuilder) *UpdateBuilder
func (b *UpdateBuilder) WhereNotInSelect(column string, sub *SelectBuilder) *UpdateBuilder
func (b *UpdateBuilder) WhereExists(sub *SelectBuilder) *UpdateBuilder
func (b *UpdateBuilder) WhereNotExists(sub *SelectBuilder) *UpdateBuilder
func (b *UpdateBuilder) Build() (string, []any)
func (b *UpdateBuilder) Exec(e Execer) (int64, error)

DeleteBuilder

func Delete(table string) *DeleteBuilder
func (b *DeleteBuilder) Where(cond string, args ...any) *DeleteBuilder
func (b *DeleteBuilder) WhereNull(column string) *DeleteBuilder
func (b *DeleteBuilder) WhereNotNull(column string) *DeleteBuilder
func (b *DeleteBuilder) WhereIn(column string, values ...any) *DeleteBuilder
func (b *DeleteBuilder) WhereNotIn(column string, values ...any) *DeleteBuilder
func (b *DeleteBuilder) WhereOr(conds ...Condition) *DeleteBuilder
func (b *DeleteBuilder) WhereSearch(search string, columns ...string) *DeleteBuilder
func (b *DeleteBuilder) WhereInSelect(column string, sub *SelectBuilder) *DeleteBuilder
func (b *DeleteBuilder) WhereNotInSelect(column string, sub *SelectBuilder) *DeleteBuilder
func (b *DeleteBuilder) WhereExists(sub *SelectBuilder) *DeleteBuilder
func (b *DeleteBuilder) WhereNotExists(sub *SelectBuilder) *DeleteBuilder
func (b *DeleteBuilder) Build() (string, []any)
func (b *DeleteBuilder) Exec(e Execer) (int64, error)

Condition (for WhereOr)

func Cond(cond string, args ...any) Condition

SQL helpers

func EscapeLike(s string) string
func Sum(column string) string
func Avg(column string) string
func Min(column string) string
func Max(column string) string
func As(expr, alias string) string
func Coalesce(column, fallback string) string
func CoalesceEmpty(column string) string
func FormatTime(t time.Time) string
func Now() string
func FormatID(id int64) string

Error handling

var ErrNoRows = errors.New("sqlite: no rows")

func IsConstraintError(err error) bool
func IsUniqueConstraintError(err error) bool
func IsForeignKeyConstraintError(err error) bool
func IsNotNullConstraintError(err error) bool

Error codes: CodeConstraint = 19, CodeConstraintCheck = 275, CodeConstraintForeignKey = 787, CodeConstraintNotNull = 1299, CodeConstraintPrimaryKey = 1555, CodeConstraintUnique = 2067


pkg/auth

import "github.com/stanza-go/framework/pkg/auth"

Auth

func New(signingKey []byte, opts ...Option) *Auth
func (a *Auth) IssueAccessToken(uid string, scopes []string) (string, error)
func (a *Auth) ValidateAccessToken(token string) (Claims, error)
func (a *Auth) AccessTokenTTL() time.Duration
func (a *Auth) RefreshTokenTTL() time.Duration
func (a *Auth) Stats() AuthStats

// Options
func WithAccessTokenTTL(d time.Duration) Option
func WithRefreshTokenTTL(d time.Duration) Option
func WithCookiePath(path string) Option
func WithSecureCookies(secure bool) Option

AuthStats fields: Issued int64, Accepted int64, Rejected int64

Cookies

func (a *Auth) SetAccessTokenCookie(w http.ResponseWriter, token string)
func (a *Auth) SetRefreshTokenCookie(w http.ResponseWriter, token string)
func (a *Auth) ClearAccessTokenCookie(w http.ResponseWriter)
func (a *Auth) ClearRefreshTokenCookie(w http.ResponseWriter)
func (a *Auth) ClearAllCookies(w http.ResponseWriter)
func ReadAccessToken(r *http.Request) (string, error)
func ReadRefreshToken(r *http.Request) (string, error)

Cookie names: AccessTokenCookie = "access_token", RefreshTokenCookie = "refresh_token"

Claims

type Claims struct {
    UID       string
    Scopes    []string
    IssuedAt  int64
    ExpiresAt int64
}

func (c Claims) Valid() bool
func (c Claims) IntUID() int64
func (c Claims) HasScope(scope string) bool

Middleware

func (a *Auth) RequireAuth() func(http.Handler) http.Handler
func (a *Auth) RequireAuthOrAPIKey(validator KeyValidator) func(http.Handler) http.Handler
func RequireAPIKey(validator KeyValidator) func(http.Handler) http.Handler
func RequireScope(scope string) func(http.Handler) http.Handler

KeyValidator type: func(keyHash string) (Claims, error)

Context

func ClaimsFromContext(ctx context.Context) (Claims, bool)
func WithClaimsForTest(ctx context.Context, claims Claims) context.Context

Token utilities

func CreateJWT(key []byte, claims Claims) (string, error)
func ValidateJWT(key []byte, token string) (Claims, error)
func GenerateRefreshToken() (string, error)
func HashToken(token string) string
func GenerateID() (string, error)
func GenerateAPIKey(prefix string) (fullKey, displayPrefix, keyHash string, err error)

Password

func HashPassword(password string) (string, error)
func VerifyPassword(hash, password string) bool

Errors

var ErrInvalidToken
var ErrTokenExpired
var ErrNoToken

pkg/validate

import "github.com/stanza-go/framework/pkg/validate"

Validator

func Fields(checks ...*FieldError) *Validator
func (v *Validator) HasErrors() bool
func (v *Validator) Errors() map[string]string
func (v *Validator) Add(checks ...*FieldError)
func (v *Validator) WriteError(w http.ResponseWriter)

type FieldError struct {
    Field   string
    Message string
}

Check functions

All return *FieldErrornil on success, error on failure. All skip empty strings except Required.

func Required(field, value string) *FieldError
func MinLen(field, value string, min int) *FieldError
func MaxLen(field, value string, max int) *FieldError
func Email(field, value string) *FieldError
func URL(field, value string) *FieldError
func PublicURL(field, value string) *FieldError
func OneOf(field, value string, allowed ...string) *FieldError
func Positive(field string, value int) *FieldError
func InRange(field string, value, min, max int) *FieldError
func FutureDate(field, value string) *FieldError
func Slug(field, value string) *FieldError
func Check(field string, ok bool, message string) *FieldError

pkg/queue

import "github.com/stanza-go/framework/pkg/queue"

Queue

func New(db *sqlite.DB, opts ...Option) *Queue
func (q *Queue) Register(jobType string, handler HandlerFunc)
func (q *Queue) Enqueue(_ context.Context, jobType string, payload []byte, opts ...EnqueueOption) (int64, error)
func (q *Queue) Start(_ context.Context) error
func (q *Queue) Stop(ctx context.Context) error
func (q *Queue) Stats() (Stats, error)
func (q *Queue) Job(id int64) (Job, error)
func (q *Queue) JobCount(f Filter) (int, error)
func (q *Queue) Jobs(f Filter) ([]Job, error)
func (q *Queue) Retry(id int64) error
func (q *Queue) Cancel(id int64) error
func (q *Queue) Purge(olderThan time.Duration) (int64, error)

type HandlerFunc func(ctx context.Context, payload []byte) error

Queue options

func WithWorkers(n int) Option
func WithPollInterval(d time.Duration) Option
func WithLogger(l *log.Logger) Option
func WithMaxAttempts(n int) Option
func WithRetryDelay(d time.Duration) Option
func WithDefaultTimeout(d time.Duration) Option

Enqueue options

func Delay(d time.Duration) EnqueueOption
func MaxAttempts(n int) EnqueueOption
func Timeout(d time.Duration) EnqueueOption
func OnQueue(name string) EnqueueOption

Job

type Job struct {
    ID          int64
    Queue       string
    Type        string
    Payload     []byte
    Status      string
    Attempts    int
    MaxAttempts int
    Timeout     time.Duration
    LastError   string
    RunAt       time.Time
    StartedAt   time.Time
    CompletedAt time.Time
    CreatedAt   time.Time
    UpdatedAt   time.Time
}

Filter and Stats

type Filter struct {
    Queue  string
    Type   string
    Status string
    Limit  int
    Offset int
}

type Stats struct {
    Pending   int
    Running   int
    Completed int
    Failed    int
    Dead      int
    Cancelled int
}

Status constants

StatusPending = "pending", StatusRunning = "running", StatusCompleted = "completed", StatusFailed = "failed", StatusDead = "dead", StatusCancelled = "cancelled"


pkg/cron

import "github.com/stanza-go/framework/pkg/cron"

Scheduler

func NewScheduler(opts ...Option) *Scheduler
func (s *Scheduler) Add(name, expr string, fn Func, opts ...JobOption) error
func (s *Scheduler) Start(ctx context.Context) error
func (s *Scheduler) Stop(ctx context.Context) error
func (s *Scheduler) Entries() []Entry
func (s *Scheduler) Stats() SchedulerStats
func (s *Scheduler) Enable(name string) error
func (s *Scheduler) Disable(name string) error
func (s *Scheduler) Trigger(name string) error

type Func func(ctx context.Context) error

Options

func WithLocation(loc *time.Location) Option
func WithLogger(l *log.Logger) Option
func WithOnComplete(fn func(CompletedRun)) Option
func WithDefaultTimeout(d time.Duration) Option
func Timeout(d time.Duration) JobOption

Entry and Stats

type Entry struct {
    Name     string
    Schedule string
    Enabled  bool
    Running  bool
    LastRun  time.Time
    NextRun  time.Time
    LastErr  error
    Timeout  time.Duration
}

type CompletedRun struct {
    Name     string
    Started  time.Time
    Duration time.Duration
    Err      error
}

type SchedulerStats struct {
    Jobs      int
    Completed int64
    Failed    int64
    Skipped   int64
}

pkg/task

import "github.com/stanza-go/framework/pkg/task"

Pool

func New(opts ...Option) *Pool
func (p *Pool) Start(_ context.Context) error
func (p *Pool) Stop(_ context.Context) error
func (p *Pool) Submit(fn func()) bool
func (p *Pool) Stats() Stats

// Options
func WithWorkers(n int) Option
func WithBuffer(n int) Option
func WithLogger(l *log.Logger) Option

Stats

type Stats struct {
    Workers   int
    Buffer    int
    Pending   int
    Submitted int64
    Completed int64
    Panics    int64
    Dropped   int64
}

pkg/log

import "github.com/stanza-go/framework/pkg/log"

Logger

func New(opts ...Option) *Logger
func (l *Logger) Debug(msg string, fields ...Field)
func (l *Logger) Info(msg string, fields ...Field)
func (l *Logger) Warn(msg string, fields ...Field)
func (l *Logger) Error(msg string, fields ...Field)
func (l *Logger) With(fields ...Field) *Logger

// Options
func WithLevel(level Level) Option
func WithWriter(w io.Writer) Option
func WithFields(fields ...Field) Option

Levels

func ParseLevel(s string) Level

const LevelDebug Level = iota
const LevelInfo
const LevelWarn
const LevelError

Fields

func String(key, val string) Field
func Int(key string, val int) Field
func Int64(key string, val int64) Field
func Float64(key string, val float64) Field
func Bool(key string, val bool) Field
func Err(err error) Field
func Duration(key string, val time.Duration) Field
func Time(key string, val time.Time) Field
func Any(key string, val any) Field

File writer

func NewFileWriter(dir string, opts ...FileOption) (*FileWriter, error)
func (fw *FileWriter) Write(p []byte) (int, error)
func (fw *FileWriter) Close() error

// Options
func WithMaxSize(bytes int64) FileOption
func WithMaxFiles(n int) FileOption

Context

func NewContext(ctx context.Context, l *Logger) context.Context
func FromContext(ctx context.Context) *Logger

pkg/config

import "github.com/stanza-go/framework/pkg/config"

Config

func New(opts ...Option) *Config
func Load(path string, opts ...Option) (*Config, error)
func (c *Config) Validate() error
func (c *Config) GetString(key string) string
func (c *Config) GetStringOr(key, fallback string) string
func (c *Config) GetInt(key string) int
func (c *Config) GetInt64(key string) int64
func (c *Config) GetFloat64(key string) float64
func (c *Config) GetBool(key string) bool
func (c *Config) GetDuration(key string) time.Duration
func (c *Config) Has(key string) bool

// Options
func WithDefaults(defaults map[string]string) Option
func WithEnvPrefix(prefix string) Option
func WithRequired(keys ...string) Option

pkg/lifecycle

import "github.com/stanza-go/framework/pkg/lifecycle"

App

func New(opts ...Option) *App
func (a *App) Start(ctx context.Context) error
func (a *App) Stop(ctx context.Context) error
func (a *App) Run() error
func (a *App) Err() error
func (a *App) Shutdown()

// Options
func Provide(constructors ...any) Option
func Invoke(funcs ...any) Option
func WithStartTimeout(d time.Duration) Option
func WithStopTimeout(d time.Duration) Option

Lifecycle hooks

type Hook struct {
    OnStart func(context.Context) error
    OnStop  func(context.Context) error
}

func (l *Lifecycle) Append(h Hook)

pkg/cmd

import "github.com/stanza-go/framework/pkg/cmd"

App

func New(name string, opts ...Option) *App
func (a *App) Command(name, desc string, run func(*Context) error, opts ...CommandOption) *Command
func (a *App) Run(args []string) error

// Options
func WithVersion(v string) Option
func WithDescription(d string) Option
func WithOutput(w io.Writer) Option
func WithDefaultCommand(name string) Option

Command

func (c *Command) Command(name, desc string, run func(*Context) error, opts ...CommandOption) *Command

// Flag options (passed as CommandOption)
func StringFlag(name, def, desc string) CommandOption
func IntFlag(name string, def int, desc string) CommandOption
func BoolFlag(name string, def bool, desc string) CommandOption
func DurationFlag(name string, def time.Duration, desc string) CommandOption

Context

func (c *Context) String(name string) string
func (c *Context) Int(name string) int
func (c *Context) Bool(name string) bool
func (c *Context) Duration(name string) time.Duration
func (c *Context) Has(name string) bool
func (c *Context) Args() []string
func (c *Context) Arg(i int) string

pkg/email

import "github.com/stanza-go/framework/pkg/email"

Client

func New(apiKey string, opts ...Option) *Client
func (c *Client) Send(ctx context.Context, msg Message) (SendResult, error)
func (c *Client) Configured() bool
func (c *Client) Stats() EmailStats

// Options
func WithFrom(from string) Option
func WithEndpoint(endpoint string) Option
func WithTimeout(d time.Duration) Option

Message

type Message struct {
    To      []string
    Subject string
    HTML    string
    Text    string
    From    string
    ReplyTo []string
}

type SendResult struct {
    ID string
}

type EmailStats struct {
    Sent   int64
    Errors int64
}

Errors

var ErrNoRecipient = errors.New("email: at least one recipient is required")
var ErrNoSubject = errors.New("email: subject is required")
var ErrNoBody = errors.New("email: at least one of HTML or Text body is required")
var ErrNoFrom = errors.New("email: sender address is required (set via WithFrom or Message.From)")
var ErrNoAPIKey = errors.New("email: API key is required")

type APIError struct {
    StatusCode int
    Body       string
}
func (e *APIError) Error() string

pkg/cache

import "github.com/stanza-go/framework/pkg/cache"

Cache

func New[V any](opts ...Option[V]) *Cache[V]
func (c *Cache[V]) Get(key string) (V, bool)
func (c *Cache[V]) Set(key string, value V)
func (c *Cache[V]) SetWithTTL(key string, value V, ttl time.Duration)
func (c *Cache[V]) GetOrSet(key string, fn func() (V, error)) (V, error)
func (c *Cache[V]) GetOrSetWithTTL(key string, ttl time.Duration, fn func() (V, error)) (V, error)
func (c *Cache[V]) Delete(key string)
func (c *Cache[V]) Clear()
func (c *Cache[V]) Len() int
func (c *Cache[V]) Keys() []string
func (c *Cache[V]) Stats() CacheStats
func (c *Cache[V]) Close()

// Options
func WithTTL[V any](d time.Duration) Option[V]
func WithMaxSize[V any](n int) Option[V]
func WithCleanupInterval[V any](d time.Duration) Option[V]
func WithOnEvict[V any](fn func(key string, value V)) Option[V]

CacheStats

type CacheStats struct {
    Size      int
    MaxSize   int
    Hits      int64
    Misses    int64
    Evictions int64
}

pkg/webhook

import "github.com/stanza-go/framework/pkg/webhook"

Client

func NewClient(opts ...Option) *Client
func (c *Client) Send(ctx context.Context, d *Delivery) (*Result, error)
func (c *Client) SendWithRetry(ctx context.Context, d *Delivery) (*Result, error)
func (c *Client) Stats() ClientStats

// Options
func WithTimeout(d time.Duration) Option
func WithMaxRetries(n int) Option
func WithRetryBaseDelay(d time.Duration) Option
func WithRetryMaxDelay(d time.Duration) Option

Delivery and Result

type Delivery struct {
    URL     string
    Secret  string
    Event   string
    Payload []byte
    Headers map[string]string
}

type Result struct {
    StatusCode int
    Body       string
    Attempts   int
    DeliveryID string
}

type ClientStats struct {
    Sends     int64
    Successes int64
    Failures  int64
    Retries   int64
    Errors    int64
}

Signing

func Sign(secret, id, timestamp string, body []byte) string
func Verify(secret, id, timestamp, signature string, body []byte) bool

Header constants

HeaderID = "X-Webhook-ID", HeaderTimestamp = "X-Webhook-Timestamp", HeaderSignature = "X-Webhook-Signature", HeaderEvent = "X-Webhook-Event"

Errors

var ErrNoURL = fmt.Errorf("webhook: URL is required")
Previous
Customizing your fork