Documentation
¶
Overview ¶
templ: version: v0.3.1001
Index ¶
- func AvailableTables(db *sql.DB) ([]string, error)
- func CheckHealthProbe(url string) error
- func ClientError(w http.ResponseWriter, title, message string, code int)
- func FormatTimeAgo(ts time.Time, fallbackAfter time.Duration, fallbackLayout string) string
- func HandleError(w http.ResponseWriter, err error) bool
- func MustMigrate(db *sql.DB, migration string)
- func OpenDB(path string) (*sql.DB, error)
- func OpenTestDB(t *testing.T) *sql.DB
- func ServeHealthProbe(db *sql.DB) http.HandlerFunc
- func SystemError(w http.ResponseWriter, msg string, args ...any)
- type App
- type Authenticator
- type EventLogger
- type FormHandler
- type LocalTime
- type PollingFunc
- type Proc
- type ProcMgr
- type Router
- type StreamMux
- type TokenClaimsFunc
- type TokenIssuer
- type Workqueue
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AvailableTables ¶
AvailableTables returns all non-internal, non-sqlite tables in the database.
func CheckHealthProbe ¶
CheckHealthProbe is the client counterpart to ServeHealthProbe: it issues an HTTP GET against url and returns nil iff the response status is 200.
func ClientError ¶
func ClientError(w http.ResponseWriter, title, message string, code int)
ClientError renders a styled HTML error page with the given title, message, and status code.
func FormatTimeAgo ¶
FormatTimeAgo returns a human-readable relative time string like "just now", "3 minutes ago", "2 hours ago", or "5 days ago". If fallbackAfter is positive and the duration exceeds it, the time is formatted using fallbackLayout instead. Pass 0 for fallbackAfter to always use relative formatting.
func HandleError ¶
func HandleError(w http.ResponseWriter, err error) bool
HandleError returns true if err is non-nil, logging the error and sending a 500 response. This allows cleaner error handling in handlers:
if engine.HandleError(w, err) {
return
}
func MustMigrate ¶
MustMigrate applies a migration to the database, panicking on error.
func OpenTestDB ¶
OpenTestDB creates a test database in a temporary directory.
func ServeHealthProbe ¶
func ServeHealthProbe(db *sql.DB) http.HandlerFunc
ServeHealthProbe returns an HTTP handler that verifies db is reachable by opening and rolling back an empty transaction. It responds 200 on success and 500 on any error.
func SystemError ¶
func SystemError(w http.ResponseWriter, msg string, args ...any)
SystemError logs the given message+args while returning a styled 500 error page.
Types ¶
type App ¶
App is a wrapper around the process manager and http router/server concepts defined by this pkg. It represents a set of "modules": types that can run workers or handle http routes. Just load up modules with .Add() and then run the thing with .ProcMgr.Run().
func NewApp ¶
NewApp constructs an App that listens on httpAddr, serves the given router, and persists module configuration in db. The HTTP server is registered as a proc on the embedded ProcMgr and starts when Run is called.
func (*App) Add ¶
Add registers mod with the App. The module may optionally implement any of:
- AttachRoutes(*Router) to register HTTP handlers,
- AttachWorkers(*ProcMgr) to register background procs,
- ConfigSpec() config.Spec to advertise a configuration schema.
Modules that implement none of these are accepted but contribute nothing.
func (*App) ConfigStore ¶
ConfigStore returns the shared config store for typed config loading.
type Authenticator ¶
type Authenticator interface {
WithAuthn(http.HandlerFunc) http.HandlerFunc
WithLeadership(http.HandlerFunc) http.HandlerFunc
}
Authenticator decorates http.HandlerFuncs with authentication and leadership checks. WithAuthn enforces that a request is authenticated; WithLeadership additionally restricts to users acting in a leadership role. The default Router uses a no-op implementation; replace it to enable auth.
type EventLogger ¶
type EventLogger struct {
// contains filtered or unexported fields
}
EventLogger provides centralized event logging for a specific module.
func NewEventLogger ¶
func NewEventLogger(db *sql.DB, module string) *EventLogger
NewEventLogger creates a new EventLogger for the specified module and applies the required migration.
func (*EventLogger) LogEvent ¶
func (e *EventLogger) LogEvent(ctx context.Context, memberID int64, eventType, entityID, entityName string, success bool, details string)
LogEvent records an event to the module_events table.
Parameters:
- memberID: the member ID if applicable, 0 for no member association
- eventType: the type of event (e.g., "WebhookReceived", "RoleSync")
- entityID: module-specific external ID (e.g., stripe_customer_id, discord_user_id, printer_serial)
- entityName: optional display name (e.g., printer_name)
- success: whether the operation succeeded
- details: additional details about the event
type FormHandler ¶
FormHandler backs an HTTP form POST with a single SQL Exec. Query is run using sql.Named parameters: "route_id" is bound from the request path value "id", and each name in Fields is bound from the corresponding form value.
func (*FormHandler) Handler ¶
func (f *FormHandler) Handler(db *sql.DB) http.HandlerFunc
Handler returns an http.HandlerFunc that executes f.Query against db using the bindings described on FormHandler, then redirects (303) back to the request's Referer. Errors are surfaced via SystemError.
type LocalTime ¶
LocalTime is a time.Time wrapper that implements sql.Scanner for columns stored as int64 Unix epoch seconds (UTC). Scanned values are converted to the America/Chicago time zone.
type PollingFunc ¶
PollingFunc is invoked on every tick of a Poll/DynamicPoll loop. It should return true if it processed an item and wants to be invoked again immediately (e.g. to drain a queue), or false to wait for the next interval.
func Cleanup ¶
func Cleanup(db *sql.DB, name, query string, args ...any) PollingFunc
Cleanup returns a PollingFunc that periodically runs a DELETE query. It logs errors and successful cleanups (when rows are affected).
func PollWorkqueue ¶
func PollWorkqueue[T any](wq Workqueue[T]) PollingFunc
PollWorkqueue implements a very basic workqueue. For every call to the returned polling func: - The next item is found (if any) - The item is processed - The item is either marked as complete or failed
The polling func always returns true after processing an item so that the next visible item will be picked up without waiting for the polling interval. So it's important to either return a nil item or sql.ErrNoRows from GetNext when no more items are ready to be processed.
Items might be logged so it's recommended that T is a stringer.
type Proc ¶
Proc is a long-running worker function managed by a ProcMgr. A Proc is expected to run until its context is canceled; returning early (with or without an error) before cancellation is treated as a fatal bug.
func DynamicPoll ¶
func DynamicPoll(intervalFn func() time.Duration, fn PollingFunc) Proc
DynamicPoll is like Poll but accepts a function that returns the interval, allowing the interval to be changed at runtime.
type ProcMgr ¶
type ProcMgr struct {
// contains filtered or unexported fields
}
ProcMgr is like a fancy implementation of sync.WaitGroup: it owns a set of Procs, runs them concurrently, and waits for all of them to exit.
type Router ¶
type Router struct {
// Authenticator can be used to pass an authenticator implementation to other handlers.
Authenticator
// contains filtered or unexported fields
}
Router wraps http.ServeMux to add request-level access logging, styled error pages, and an embedded Authenticator. The package's static assets directory is automatically mounted at "/".
func NewRouter ¶
func NewRouter() *Router
NewRouter constructs a Router with a fresh ServeMux, mounts the embedded assets/ filesystem at "/", and installs a no-op Authenticator that callers can replace by assigning to the embedded field.
func (*Router) HandleFunc ¶
func (r *Router) HandleFunc(route string, fn http.HandlerFunc)
HandleFunc registers fn as the handler for route, wrapping it with response status capture and structured slog access logging (path, method, user agent, latency, status).
type StreamMux ¶
type StreamMux struct {
// contains filtered or unexported fields
}
StreamMux multiplexes a single data source to multiple subscribers. It lazily starts the source when the first subscriber connects and automatically stops it when the last subscriber disconnects.
func NewStreamMux ¶
NewStreamMux constructs a StreamMux backed by source. The source function is invoked lazily on the first Subscribe call; the context it receives is canceled when the last subscriber disconnects (or Stop is called).
func (*StreamMux) ClientCount ¶
ClientCount returns the current number of subscribers.
func (*StreamMux) Stop ¶
func (s *StreamMux) Stop()
Stop cancels the source and closes all client channels.
func (*StreamMux) Subscribe ¶
Subscribe returns a channel that receives stream data. The caller must call Unsubscribe when done to avoid resource leaks. If the source fails to start, returns nil.
func (*StreamMux) Unsubscribe ¶
Unsubscribe removes a client from the stream. When the last client unsubscribes, the source is stopped.
type TokenClaimsFunc ¶
type TokenClaimsFunc func() *jwt.RegisteredClaims
TokenClaimsFunc returns a freshly populated claims struct each time the OAuth2 TokenSource needs to mint a new token.
type TokenIssuer ¶
type TokenIssuer struct {
Key *rsa.PrivateKey
}
TokenIssuer signs and verifies JWTs using an RSA private key (RS256).
func NewTokenIssuer ¶
func NewTokenIssuer(keyFile string) *TokenIssuer
NewTokenIssuer returns a TokenIssuer whose key is loaded from keyFile. If the file does not exist, a fresh 2048-bit RSA key is generated and written to keyFile with mode 0600. Any I/O or parse error panics.
func (*TokenIssuer) OAuth2 ¶
func (t *TokenIssuer) OAuth2(tcf TokenClaimsFunc) oauth2.TokenSource
OAuth2 adapts the issuer to an oauth2.TokenSource. Each refresh signs a new JWT built from tcf(); the result is wrapped in oauth2.ReuseTokenSource so the same token is reused until it expires.
func (*TokenIssuer) Sign ¶
func (t *TokenIssuer) Sign(claims *jwt.RegisteredClaims) (string, error)
Sign returns a JWT signed with the issuer's RSA key (RS256) for claims.
func (*TokenIssuer) Verify ¶
func (t *TokenIssuer) Verify(tok string) (*jwt.RegisteredClaims, error)
Verify parses and validates tok against the issuer's public key, returning the embedded registered claims. It returns an error if the signature is invalid or the token is otherwise unacceptable.
type Workqueue ¶
type Workqueue[T any] interface { GetItem(context.Context) (T, error) ProcessItem(context.Context, T) error UpdateItem(ctx context.Context, item T, success bool) error }
Workqueue is the generic interface consumed by PollWorkqueue and WithRateLimiting. Implementations supply an item source (GetItem), a per-item processor (ProcessItem), and an outcome reporter (UpdateItem) invoked with success=true iff ProcessItem returned nil.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package config provides a declarative configuration system for modules.
|
Package config provides a declarative configuration system for modules. |
|
Package oauthlogin extracts the common Discord/Google OAuth2 login flow.
|
Package oauthlogin extracts the common Discord/Google OAuth2 login flow. |