runtime

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jun 29, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildOpenAPI

func BuildOpenAPI(cfg *ServiceConfig, models map[string]*db.TableInfo) (*openapi3.T, error)

BuildOpenAPI generates an OpenAPI 3.0.3 spec from the service config and registered models.

func Pool

func Pool(pools map[string]any, name string) any

Pool returns a pool by name. Returns nil if not found or not the expected type.

func PoolPG

func PoolPG(pools map[string]any, name string) *pgxpool.Pool

PoolPG returns a *pgxpool.Pool by name.

func PoolSQL

func PoolSQL(pools map[string]any, name string) *sql.DB

PoolSQL returns a *sql.DB by name (for Turso or MySQL).

func RegisterEntries

func RegisterEntries(app *fiber.App, cfg *ServiceConfig, handlers *EntryHandlers, prefix string, natsConns map[string]*events.Conn) error

RegisterEntries iterates over cfg.Entry and registers all HTTP routes on app. natsConns is optional — used for auto-publishing on nats_publish targets.

func TableFor

func TableFor[T any](pools map[string]any, poolName, tableName string) (*db.Table[T], error)

TableFor creates a db.Table[T] for the given pool name and table name.

func WrapTransformHandler

func WrapTransformHandler[T any](handler func(*fiber.Ctx) error, hooks EntryHooks[T]) func(*fiber.Ctx) error

WrapTransformHandler wraps a REST handler with BeforeTransform/AfterTransform hooks. The hooks must implement EntryHooks[T] where T is the request model. BeforeTransform parses the request body into T, calls the hook, stores the result in c.Locals("transformed"), then executes the handler. AfterTransform is called with the response body after the handler completes.

Usage:

svc.WithRest("onTransform", runtime.WrapTransformHandler(
    func(c *fiber.Ctx) error {
        input := c.Locals("transformed").(Product)
        return c.JSON(fiber.Map{"name": input.Name})
    },
    &ProductHooks{},
))

Types

type CORSConf

type CORSConf struct {
	Origins     []string `json:"origins,optional"`
	Methods     []string `json:"methods,optional"`
	Headers     []string `json:"headers,optional"`
	Credentials bool     `json:"credentials,optional"`
	MaxAge      int      `json:"max_age,default=300"`
}

type CRUDOverrides

type CRUDOverrides struct {
	List   string `json:"list,optional"`
	Get    string `json:"get,optional"`
	Create string `json:"create,optional"`
	Update string `json:"update,optional"`
	Delete string `json:"delete,optional"`
}

type CRUDProvider

type CRUDProvider interface {
	List(ctx *fiber.Ctx, params ListParams) error
	Get(ctx *fiber.Ctx, id string) error
	Create(ctx *fiber.Ctx, body []byte) error
	Update(ctx *fiber.Ctx, id string, body []byte) error
	Delete(ctx *fiber.Ctx, id string) error
}

CRUDProvider abstracts typed Table[T] operations for the router.

func NewCRUDProvider

func NewCRUDProvider[T any](table *db.Table[T], hooks EntryHooks[T]) CRUDProvider

NewCRUDProvider wraps a db.Table[T] (PostgreSQL) into a CRUDProvider.

func NewMySQLCRUDProvider

func NewMySQLCRUDProvider[T any](table *db.MySQLTable[T], hooks EntryHooks[T]) CRUDProvider

func NewTursoCRUDProvider

func NewTursoCRUDProvider[T any](table *db.TursoTable[T], hooks EntryHooks[T]) CRUDProvider

type CronJob

type CronJob struct {
	Name     string       `json:"name"`
	Schedule string       `json:"schedule"`
	Mode     string       `json:"mode,default=nats"` // nats, handler, internal
	Publish  *CronPublish `json:"publish,optional"`
	Handler  string       `json:"handler,optional"`
}

func (*CronJob) Validate

func (c *CronJob) Validate() error

type CronJobFunc

type CronJobFunc func(ctx context.Context) error

CronJobFunc is a handler called on cron schedule. Returns error on failure.

type CronPublish

type CronPublish struct {
	Stream  string `json:"stream"`
	Subject string `json:"subject,optional"`
}

type CronScheduler

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

CronScheduler manages periodic jobs defined in cron:[].

func NewCronScheduler

func NewCronScheduler() *CronScheduler

NewCronScheduler creates a new scheduler.

func (*CronScheduler) AddAll

func (s *CronScheduler) AddAll(cronDefs []CronJob, natsConns map[string]*events.Conn, handlers map[string]CronJobFunc) error

AddAll registers all cron jobs from config.

func (*CronScheduler) AddJob

func (s *CronScheduler) AddJob(cfg CronJob, natsConn *events.Conn, handler CronJobFunc) error

AddJob registers a cron job from config. handler is only used for mode=handler. nats is used for mode=nats to publish on schedule.

func (*CronScheduler) Start

func (s *CronScheduler) Start()

Start begins executing scheduled jobs.

func (*CronScheduler) Stop

func (s *CronScheduler) Stop()

Stop stops the scheduler and waits for running jobs to finish.

type DBConfig

type DBConfig struct {
	Name   string    `json:"name"`
	Driver string    `json:"driver,default=postgres"`
	URL    string    `json:"url"`
	Pool   *PoolConf `json:"pool,optional"`
}

func (*DBConfig) Validate

func (d *DBConfig) Validate() error

type DefaultExitHooks

type DefaultExitHooks struct{}

func (DefaultExitHooks) OnError

func (DefaultExitHooks) OnError(_ context.Context, _ error)

func (DefaultExitHooks) OnMessage

func (DefaultExitHooks) OnMessage(_ context.Context, msg []byte) ([]byte, error)

func (DefaultExitHooks) OnSuccess

func (DefaultExitHooks) OnSuccess(_ context.Context)

type DefaultHooks

type DefaultHooks[T any] struct{}

func (DefaultHooks[T]) AfterCreate

func (DefaultHooks[T]) AfterCreate(_ context.Context, _ *T) error

func (DefaultHooks[T]) AfterDelete

func (DefaultHooks[T]) AfterDelete(_ context.Context, _ any) error

func (DefaultHooks[T]) AfterTransform

func (DefaultHooks[T]) AfterTransform(_ context.Context, _ any) error

func (DefaultHooks[T]) AfterUpdate

func (DefaultHooks[T]) AfterUpdate(_ context.Context, _ *T) error

func (DefaultHooks[T]) BeforeCreate

func (DefaultHooks[T]) BeforeCreate(_ context.Context, req T) (T, error)

func (DefaultHooks[T]) BeforeDelete

func (DefaultHooks[T]) BeforeDelete(_ context.Context, _ any) error

func (DefaultHooks[T]) BeforeTransform

func (DefaultHooks[T]) BeforeTransform(_ context.Context, req T) (T, error)

func (DefaultHooks[T]) BeforeUpdate

func (DefaultHooks[T]) BeforeUpdate(_ context.Context, _ any, patch map[string]any) (map[string]any, error)

type EntryDef

type EntryDef struct {
	Type    string `json:"type"` // crud, rest, webhook, websocket, sse, file
	Method  string `json:"method,optional"`
	Path    string `json:"path,optional"`
	Handler string `json:"handler,optional"`
	Auth    bool   `json:"auth,optional"`
	DB      string `json:"db,optional"` // references database name

	// CRUD
	Model     string         `json:"model,optional"`
	Table     string         `json:"table,optional"`
	Resource  string         `json:"resource,optional"`
	Overrides *CRUDOverrides `json:"overrides,optional"`

	// NATS publish after entry
	NATSPublish []NATSPublishTarget `json:"nats_publish,optional"`

	// File
	AllowedTypes []string    `json:"allowed_types,optional"`
	MaxSize      string      `json:"max_size,optional"`
	Storage      *StorageDef `json:"storage,optional"`
}

func (*EntryDef) Validate

func (e *EntryDef) Validate() error

type EntryHandlers

type EntryHandlers struct {
	Rest      map[string]func(*fiber.Ctx) error
	WS        map[string]WSHandler
	SSE       map[string]SSEHandler
	CRUD      map[string]CRUDProvider
	Storage   map[string]server.StorageBackend
	Transform map[string]any // handler name → EntryHooks[T] (untyped due to generics)
}

EntryHandlers holds all named handler functions registered by the user.

type EntryHooks

type EntryHooks[T any] interface {
	BeforeCreate(ctx context.Context, req T) (T, error)
	AfterCreate(ctx context.Context, entity *T) error
	BeforeUpdate(ctx context.Context, id any, patch map[string]any) (map[string]any, error)
	AfterUpdate(ctx context.Context, entity *T) error
	BeforeDelete(ctx context.Context, id any) error
	AfterDelete(ctx context.Context, id any) error
	BeforeTransform(ctx context.Context, req T) (T, error)
	AfterTransform(ctx context.Context, result any) error
}

EntryHooks defines lifecycle callbacks for entry endpoints (HTTP).

type ExitHandler

type ExitHandler func(ctx context.Context, msg []byte) ([]byte, error)

type ExitHooks

type ExitHooks interface {
	OnMessage(ctx context.Context, msg []byte) ([]byte, error)
	OnSuccess(ctx context.Context)
	OnError(ctx context.Context, err error)
}

ExitHooks defines lifecycle callbacks for exit workers (NATS).

type ExitWorker

type ExitWorker struct {
	Name          string       `json:"name"`
	Subscribe     SubscribeDef `json:"subscribe"`
	Handler       string       `json:"handler"`
	MaxConcurrent int          `json:"max_concurrent,default=1"`
	DB            string       `json:"db,optional"`
	Reply         bool         `json:"reply,optional"`
	ReplyTimeout  string       `json:"reply_timeout,default=30s"`
	PullBatch     int          `json:"pull_batch,optional"`
	PullMaxWait   string       `json:"pull_max_wait,optional"`
	ConsumerMode  string       `json:"consumer_mode,optional"` // push or pull
}

func (*ExitWorker) Validate

func (e *ExitWorker) Validate() error

type ExitWorkerManager

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

func NewExitWorkerManager

func NewExitWorkerManager() *ExitWorkerManager

func (*ExitWorkerManager) Shutdown

func (m *ExitWorkerManager) Shutdown(timeout time.Duration)

func (*ExitWorkerManager) Start

func (m *ExitWorkerManager) Start(ctx context.Context, exitDefs []ExitWorker, natsConns map[string]*events.Conn, handlers map[string]ExitHandler, hooks map[string]ExitHooks) error

type ListParams

type ListParams struct {
	Page    int
	Size    int
	Sort    string
	Filters map[string]string
}

ListParams holds query parameters for list endpoints.

type NATSConnConf

type NATSConnConf struct {
	Name          string      `json:"name"`
	URL           string      `json:"url"`
	MaxReconnects int         `json:"max_reconnects,default=10"`
	ReconnectWait string      `json:"reconnect_wait,default=2s"`
	Timeout       string      `json:"timeout,default=5s"`
	RetryOnFail   bool        `json:"retry_on_fail,default=true"`
	Streams       []StreamDef `json:"streams,optional"`
}

func (*NATSConnConf) Validate

func (n *NATSConnConf) Validate() error

type NATSPublishTarget

type NATSPublishTarget struct {
	Stream  string `json:"stream"`
	Subject string `json:"subject,optional"`
}

type OpenAPIConf

type OpenAPIConf struct {
	Enabled  bool   `json:"enabled,optional"`
	Version  string `json:"version,default=1.0.0"`
	SpecPath string `json:"spec_path,default=/openapi.json"`
	DocsPath string `json:"docs_path,default=/docs"`
	Theme    string `json:"theme,default=moon"`
	DarkMode bool   `json:"dark_mode,default=true"`
}

type PaginatedResponse

type PaginatedResponse struct {
	Data  any   `json:"data"`
	Total int64 `json:"total"`
	Page  int   `json:"page"`
	Size  int   `json:"size"`
}

PaginatedResponse is used by tableCRUD.List.

type PoolConf

type PoolConf struct {
	MaxConns          int32  `json:"max_conns,default=10"`
	MinConns          int32  `json:"min_conns,default=2"`
	MaxConnLifetime   string `json:"max_conn_lifetime,optional"`
	MaxConnIdleTime   string `json:"max_conn_idle_time,optional"`
	HealthCheckPeriod string `json:"health_check_period,optional"`
	ReservedConns     int32  `json:"reserved_conns,default=10"`
}

type RouteMW

type RouteMW struct {
	Path  string   `json:"path"`
	Apply []string `json:"apply"`
}

type SSEHandler

type SSEHandler func(ctx context.Context, send func(data string)) error

SSEHandler is called when an SSE client connects.

type ServerConf

type ServerConf struct {
	Host            string       `json:"host,default=0.0.0.0"`
	Prefork         bool         `json:"prefork,optional"`
	BodyLimit       int          `json:"body_limit,default=4194304"`
	Timeout         string       `json:"timeout,default=30s"`
	MaxConns        int          `json:"max_conns,default=1000"`
	MaxBytes        int          `json:"max_bytes,default=4194304"`
	MetricsPath     string       `json:"metrics_path,default=/metrics"`
	HealthPath      string       `json:"health_path,default=/health"`
	ShutdownTimeout string       `json:"shutdown_timeout,default=10s"`
	RecoverStack    bool         `json:"recover_stack,default=true"`
	APIPrefix       string       `json:"api_prefix,default=/api/v1"`
	CORS            *CORSConf    `json:"cors,optional"`
	Middleware      []RouteMW    `json:"middleware,optional"`
	Static          []StaticDef  `json:"static,optional"`
	MaxConnLimit    int          `json:"max_conn_limit,default=1000"`
	OpenAPI         *OpenAPIConf `json:"openapi,optional"`
}

type Service

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

Service is the main runtime orchestrator. It reads a service YAML, initializes databases, NATS connections, entry endpoints, and optionally exit workers and cron jobs.

func New

func New(configPath string) (*Service, error)

New creates a Service from a YAML config file.

func (*Service) App

func (s *Service) App() *fiber.App

App returns the underlying Fiber app.

func (*Service) NATS

func (s *Service) NATS(name string) *events.Conn

NATS returns a NATS connection by name.

func (*Service) Pool

func (s *Service) Pool(name string) any

Pool returns a DB pool by name.

func (*Service) PoolPG

func (s *Service) PoolPG(name string) any

PoolPG returns a *pgxpool.Pool by name.

func (*Service) RegisterModel

func (s *Service) RegisterModel(name string, model any) *Service

RegisterModel registers a model for OpenAPI schema generation. Usage: svc.RegisterModel("Product", (*Product)(nil)).

func (*Service) Run

func (s *Service) Run() error

Run starts the service: init DBs, NATS, register routes, start HTTP server.

func (*Service) RunWithContext

func (s *Service) RunWithContext(ctx context.Context) error

RunWithContext starts the service with a parent context.

func (*Service) WithCRUD

func (s *Service) WithCRUD(model string, provider CRUDProvider) *Service

WithCRUD registers a CRUD provider for a model name.

func (*Service) WithCron

func (s *Service) WithCron(name string, handler CronJobFunc) *Service

WithCron registers a cron handler by name (for mode=handler).

func (*Service) WithExit

func (s *Service) WithExit(name string, h ExitHandler) *Service

WithExit registers an exit handler by name (for NATS workers).

func (*Service) WithExitHooks

func (s *Service) WithExitHooks(h map[string]ExitHooks) *Service

WithExitHooks registers exit hooks by worker name.

func (*Service) WithHandlers

func (s *Service) WithHandlers(h *EntryHandlers) *Service

WithHandlers registers all entry handler functions.

func (*Service) WithHooks

func (s *Service) WithHooks(model string, hooks any) *Service

WithHooks registers entry hooks for a model. The hooks are applied to the corresponding CRUD provider if one has been registered for that model.

func (*Service) WithRest

func (s *Service) WithRest(name string, h func(*fiber.Ctx) error) *Service

WithRest registers a REST handler by name.

func (*Service) WithSSE

func (s *Service) WithSSE(name string, h SSEHandler) *Service

WithSSE registers an SSE handler by name.

func (*Service) WithWS

func (s *Service) WithWS(name string, h WSHandler) *Service

WithWS registers a WebSocket handler by name.

type ServiceConfig

type ServiceConfig struct {
	Name      string         `json:"name"`
	Port      int            `json:"port,default=8080"`
	Server    ServerConf     `json:"server,optional"`
	Databases []DBConfig     `json:"databases,optional"`
	NATS      []NATSConnConf `json:"nats,optional"`
	Entry     []EntryDef     `json:"entry,optional"`
	Exit      []ExitWorker   `json:"exit,optional"`
	Cron      []CronJob      `json:"cron,optional"`
}

func LoadConfig

func LoadConfig(path string) (*ServiceConfig, error)

type StaticDef

type StaticDef struct {
	Prefix string `json:"prefix"`
	Dir    string `json:"dir"`
}

type StorageDef

type StorageDef struct {
	Mode      string `json:"mode"` // s3, local
	Bucket    string `json:"bucket,optional"`
	Path      string `json:"path,optional"`
	Region    string `json:"region,optional"`
	Endpoint  string `json:"endpoint,optional"`
	AccessKey string `json:"access_key,optional"`
	SecretKey string `json:"secret_key,optional"`
}

type StreamDef

type StreamDef struct {
	Name        string `json:"name"`
	MaxAge      string `json:"max_age,optional"`
	MaxBytes    int64  `json:"max_bytes,optional"`
	Storage     string `json:"storage,default=file"`
	Compression string `json:"compression,default=s2"`
}

type SubscribeDef

type SubscribeDef struct {
	Stream  string `json:"stream"`
	Subject string `json:"subject,optional"`
	Durable string `json:"durable,optional"`
}

type WSHandler

type WSHandler func(ctx context.Context, conn *websocket.Conn) error

WSHandler is called when a WebSocket client connects.

Jump to

Keyboard shortcuts

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