Documentation
¶
Overview ¶
Package web is a web framework for Vuka: routes, views and services are declared with decorators, and web.New gathers them into an app.
@web.Get("/pets/{id}")
@web.Template("pet.html")
func ShowPet(id int, store *PetStore) Result[Pet] { … }
func main() { web.New().Run(":8080") }
Everything a decorator declares can also be registered from plain Go (App.Get, App.Provide, …); see the README.
Index ¶
- Constants
- Variables
- func AddPanel(name string, render func(notes []any) ui.Node)
- func Broadcast(ctx context.Context, topic string, msg any) error
- func Controller(prefix string) func(*vuka.Type)
- func Delete(path string) func(*vuka.Decl)
- func Env[T any](key string, def ...T) T
- func Get(path string) func(*vuka.Decl)
- func Handle(method, path string) func(*vuka.Decl)
- func Live(path string, opts ...LiveOption) func(*vuka.Type)
- func LoadEnv(files ...string) error
- func MustEnv[T any](key string) T
- func Note(ctx context.Context, panel string, v any)
- func NoteStatement(ctx context.Context, q Statement)
- func Patch(path string) func(*vuka.Decl)
- func Post(path string) func(*vuka.Decl)
- func Put(path string) func(*vuka.Decl)
- func RegisterCSS(name string, css []byte)
- func Request(ctx context.Context) *http.Request
- func Resolve[T any](a *App) (T, error)
- func ResponseWriter(ctx context.Context) http.ResponseWriter
- func Service(t *vuka.Type)
- func Template(f vuka.File, name ...string) func(*vuka.Decl)
- type App
- func (a *App) Broadcast(ctx context.Context, topic string, msg any) error
- func (a *App) Build() error
- func (a *App) Check(fn func(*App) error) *App
- func (a *App) Delete(path string, fn any, opts ...RouteOption) *App
- func (a *App) Eager(ctors ...any) *App
- func (a *App) Get(path string, fn any, opts ...RouteOption) *App
- func (a *App) Handle(method, path string, fn any, opts ...RouteOption) *App
- func (a *App) Handler() http.Handler
- func (a *App) Live(path string, component ui.Stateful, opts ...LiveOption) *App
- func (a *App) OnStart(fn func(context.Context) error) *App
- func (a *App) OnStop(fn func(context.Context) error) *App
- func (a *App) Patch(path string, fn any, opts ...RouteOption) *App
- func (a *App) Post(path string, fn any, opts ...RouteOption) *App
- func (a *App) Provide(ctors ...any) *App
- func (a *App) Put(path string, fn any, opts ...RouteOption) *App
- func (a *App) Run(addr string) error
- func (a *App) Start(ctx context.Context) error
- func (a *App) Static(prefix string, fsys fs.FS) *App
- func (a *App) Stop(ctx context.Context) error
- func (a *App) Toolbar() bool
- func (a *App) Use(mw ...Middleware) *App
- type Error
- type LiveOption
- type Middleware
- type Option
- func Check(fn func(*App) error) Option
- func Dev() Option
- func DotEnv(files ...string) Option
- func Eager(ctors ...any) Option
- func LiveKey(key []byte) Option
- func LiveLayout(layout func(page ui.Node) ui.Node) Option
- func LiveOrigins(patterns ...string) Option
- func LiveProtocol(v int) Option
- func LiveTokenTTL(d time.Duration) Option
- func NoDotEnv() Option
- func NoTailwind() Option
- func NoToolbar() Option
- func OnError(f func(w http.ResponseWriter, r *http.Request, e *Error, html bool)) Option
- func OnStart(fn func(context.Context) error) Option
- func OnStop(fn func(context.Context) error) Option
- func Only(pkgs ...string) Option
- func Options(opts ...Option) Option
- func Provide(ctors ...any) Option
- func Require(keys ...string) Option
- func Tailwind(path string) Option
- func WithRelay(r Relay) Option
- func WithRouter(r Router) Option
- type OptionFunc
- type Redirect
- type Relay
- type RouteOption
- type Router
- type ServeMux
- type Starter
- type Statement
- type Stopper
- type URLParams
- type Uses
Constants ¶
const ( // ToolbarHeader names the toolbar record of a development app's // response; the toolbar lists a page's fetch and XHR calls by it. ToolbarHeader = "X-Vuka-Toolbar" // DevDirEnv names the session directory vuka run passes the app: the // toolbar is on, and with -watch the directory's build.json says how // the next build is going. DevDirEnv = "VUKA_DEV_DIR" )
const (
// CSSEnv names the stylesheet file vuka run keeps up to date.
CSSEnv = "VUKA_TAILWIND_CSS"
)
Variables ¶
var ( NotFound = &Error{Status: http.StatusNotFound, Message: "not found"} Forbidden = &Error{Status: http.StatusForbidden, Message: "forbidden"} Conflict = &Error{Status: http.StatusConflict, Message: "conflict"} )
Functions ¶
func AddPanel ¶ added in v0.9.0
AddPanel adds a panel to the development toolbar: render draws it for a request from the values the request noted for it (Note), in order. A panel added again under the same name replaces it.
func Broadcast ¶ added in v0.2.0
Broadcast delivers msg to the Update methods of every live component subscribed to topic, in every connected page of the app serving ctx (a request's, or a live event's), and sends each page what changed. A topic of "" reaches every component.
func Controller ¶
Controller makes a struct a service whose route methods are served under prefix.
func Env ¶ added in v0.2.0
Env returns the environment variable key as a T: a string, bool, integer, float, time.Duration, *url.URL (absolute), a type implementing encoding.TextUnmarshaler, or a slice of those (comma-separated). When key is unset or empty it returns def (or the zero value); when the value doesn't convert, it returns def too and the next Build or Start reports the error.
func Handle ¶
Handle declares a route for method and path: @web.Handle("OPTIONS", "/x"). Path segments in braces bind parameters of the same name: "/pets/{id}"; "{rest...}" matches the rest of the path.
func Live ¶ added in v0.2.0
func Live(path string, opts ...LiveOption) func(*vuka.Type)
Live serves a stateful component as a page at path, a GET route:
@web.Live("/rooms/{room}")
type Chat struct {
vuka.Live
Room string // a prop bound from the path segment, else ?room=
Store *ChatStore // a prop of a provided type, injected
log []string // state
}
Its exported fields of provided types are injected; the others that hold text bind from the path segment or query parameter of their name. The page is the component inside the app's layout (LiveLayout), or the one Layout names, or else a bare HTML document. Use adds middleware.
func LoadEnv ¶ added in v0.2.0
LoadEnv reads env files into the process environment, as New does: for code that needs their values before New, such as options built from them. No files means the default list (see the README); a key is set only when the environment doesn't have it yet, and the first file listed wins over the later ones. Loading the same files again is a no-op, so New reading them afterwards changes nothing.
func MustEnv ¶ added in v0.2.0
MustEnv is Env for values that must be there: it panics, naming key, when the variable is unset, empty or doesn't convert.
func Note ¶ added in v0.9.0
Note records v for the toolbar's panel named panel, drawn by the function AddPanel registered for it, else as a list of the values. It does nothing for a context that no development toolbar watches, so it can stay in production code.
func NoteStatement ¶ added in v0.9.0
NoteStatement records a statement the request of ctx (or its live page's socket message) ran, for the toolbar's SQL panel. It does nothing for a context that no development toolbar watches.
func RegisterCSS ¶ added in v0.6.0
RegisterCSS registers a stylesheet the app serves at /_vuka/<name>; the one named "app.css" is linked from every full page. vuka build calls it from a file it generates in the main package, with the Tailwind CSS built for the binary.
func Request ¶
Request is the request being served, from a context.Context a handler received: call decorators reach it through c.Context().
func ResponseWriter ¶
func ResponseWriter(ctx context.Context) http.ResponseWriter
ResponseWriter is the response being written, from a handler's context.
func Service ¶
Service makes a struct a dependency: a lazy singleton built from its fields, each injected by type.
Types ¶
type App ¶
type App struct {
// contains filtered or unexported fields
}
App is a web application: the routes, services and controllers declared with decorators, and whatever was added in code.
func New ¶
New makes an app of every route, service and controller declared so far (each app takes its own snapshot, with its own singletons). It first reads the env files into the process environment (see LoadEnv), so constructors and Start methods see their values through os.Getenv.
func (*App) Broadcast ¶ added in v0.2.0
Broadcast delivers msg to the components subscribed to topic, as the package's Broadcast does.
func (*App) Build ¶
Build resolves the app: every route's parameters, results and view, and the dependency graph. It reports every problem at once, before anything is served; Handler, Start and Run call it.
func (*App) Check ¶ added in v0.2.0
Check adds fn to the checks Build runs once the routes are compiled; its error is reported with Build's own.
func (*App) Eager ¶ added in v0.2.0
Eager adds constructors whose values Start builds (and starts, when they implement Starter) even when nothing needs them. Provided values that aren't functions always start; constructors otherwise only when needed.
func (*App) Handle ¶
func (a *App) Handle(method, path string, fn any, opts ...RouteOption) *App
Handle registers fn for method and path, bound as a decorated handler is.
func (*App) Handler ¶
Handler is the app as an http.Handler, to serve or mount anywhere. It panics when Build fails.
func (*App) Live ¶ added in v0.2.0
Live serves component (a pointer to a stateful component, whose fields are the defaults) as a page at path, as the Live decorator does.
func (*App) OnStart ¶ added in v0.2.0
OnStart adds fn to the app's start sequence, after the values supplied and the hooks added before it and before the values Start constructs.
func (*App) OnStop ¶ added in v0.2.0
OnStop adds fn to the app's stop sequence, which runs in the reverse order of the start sequence: fn runs after everything started after it was added has stopped.
func (*App) Run ¶
Run serves the app on addr (":" + $PORT, else ":8080", when empty) until SIGINT or SIGTERM, then shuts down gracefully and stops the services.
func (*App) Start ¶
Start builds every dependency the routes need and every Eager one, then runs the start sequence: each supplied or built value implementing Starter and each OnStart hook, in dependency order (supplied values and hooks as added, before the values built from constructors).
func (*App) Stop ¶
Stop runs the stop sequence: each value implementing Stopper and each OnStop hook, in the reverse order of the start sequence.
func (*App) Toolbar ¶ added in v0.9.0
Toolbar reports whether the app shows the development toolbar: for a library feeding it (NoteStatement) only then.
func (*App) Use ¶
func (a *App) Use(mw ...Middleware) *App
Use adds app-wide middleware; the first added runs first.
type Error ¶
Error is an error with an HTTP status. Returned by a handler (wrapped or not), it answers with that status and message: an HTML page for an HTML route, JSON otherwise.
type LiveOption ¶ added in v0.2.0
type LiveOption interface {
// contains filtered or unexported methods
}
LiveOption configures a page declared with Live.
type Middleware ¶
Middleware wraps an http.Handler.
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option configures an App.
func Dev ¶
func Dev() Option
Dev shows the messages of internal errors in responses; so does the environment variable VUKA_ENV=development.
func DotEnv ¶ added in v0.2.0
DotEnv replaces the env files New reads (see LoadEnv); the first listed wins. Relative paths are read from the working directory, or the nearest parent up to the module root holding one of them.
func Eager ¶ added in v0.2.0
Eager provides constructors whose values are built and started by Start even when no route needs them (workers, schedulers).
func LiveKey ¶ added in v0.2.0
LiveKey is the key signing live pages' join tokens. Without it each app draws a random one, so a page rendered by one process can't join another: set it when several replicas serve the app.
func LiveLayout ¶ added in v0.2.0
LiveLayout is the layout of every Live page without its own.
func LiveOrigins ¶ added in v0.2.0
LiveOrigins lets pages of other origins open live connections: host patterns as path.Match takes them ("app.example.com", "*.example.com"). By default only the app's own origin may.
func LiveProtocol ¶ added in v0.3.0
LiveProtocol caps the live protocol version the app speaks: 2 (render trees: a page gets each component's statics once, then only the dynamics that changed) by default, or 1 (each changed component's HTML). A page asks for the newest it knows and gets at most this; v2 also needs a Vuka live session that speaks it, else pages get v1.
func LiveTokenTTL ¶ added in v0.2.0
LiveTokenTTL is how long a rendered live page may (re)join; 12 hours by default. A page older than that reloads when it reconnects.
func NoTailwind ¶ added in v0.6.0
func NoTailwind() Option
NoTailwind turns the app's stylesheet off: pages get no link to /_vuka/app.css and the vuka command builds none.
func NoToolbar ¶ added in v0.9.0
func NoToolbar() Option
NoToolbar turns the development toolbar off.
func Only ¶
Only limits the declared routes, services and controllers an app takes to those of the given packages (import paths; "main" for the main package).
func Options ¶ added in v0.2.0
Options is one Option applying opts in order; nil options are skipped.
func Provide ¶
Provide adds constructors to the app's container: func(deps…) T or func(deps…) (T, error). A value that isn't a function is provided as is.
func Require ¶ added in v0.2.0
Require fails Build when one of the environment variables is unset or empty, naming each missing one and the env files looked for.
func Tailwind ¶ added in v0.6.0
Tailwind names the project's Tailwind stylesheet, relative to the module root, when it isn't app.css or styles/app.css. The vuka command reads the path from the source, so it must be a string literal.
func WithRelay ¶ added in v0.2.0
WithRelay sends the app's broadcasts through r instead of delivering them in-process only.
func WithRouter ¶
WithRouter serves the app's routes with r instead of net/http's ServeMux.
type OptionFunc ¶ added in v0.2.0
type OptionFunc func(*App)
OptionFunc is an Option written as a function of the App, for libraries defining their own options: it runs inside New, before Build, and may call any of the App's methods (Provide, Use, Handle, OnStart, Check, …).
type Redirect ¶
type Redirect string
Redirect, returned by a handler as its result or as its error, redirects to the URL: 302 for GET and HEAD, 303 See Other otherwise. It is also a vuka.Node, so a handler returning a page can redirect instead.
type Relay ¶ added in v0.2.0
type Relay interface {
Publish(ctx context.Context, topic string, msg any) error
Subscribe(deliver func(topic string, msg any))
}
Relay carries broadcasts between the replicas of an app: Publish sends a message to every replica, and each calls the function Subscribe was given with what arrives (its own messages included). Encoding the messages, whose dynamic types pick the Update methods they reach, is the relay's business.
type RouteOption ¶
type RouteOption func(*routeSpec)
RouteOption configures a route registered in code.
func Params ¶
func Params(names ...string) RouteOption
Params names a handler's parameters in order, which reflection can't see: scalar parameters bind by name.
func View ¶
func View(f vuka.File, name ...string) RouteOption
View renders the route's result with a view, as @web.Template does.
func Wrap ¶
func Wrap(mw ...Middleware) RouteOption
Wrap adds middleware to the route, as @web.Use does.
type Router ¶
type Router interface {
http.Handler
Handle(method, pattern string, h http.Handler)
Param(r *http.Request, name string) string
}
Router matches requests to routes. Patterns use the canonical syntax: "/pets/{id}" binds a segment, "/files/{path...}" the rest of the path, and a pattern matches its path exactly. Param returns a bound value for a request the router dispatched.
type ServeMux ¶
type ServeMux struct {
// contains filtered or unexported fields
}
ServeMux is the default Router: net/http's ServeMux with Go 1.22 patterns.
func NewServeMux ¶
func NewServeMux() *ServeMux
type Starter ¶
Starter is a provided value with work to do when the app starts: Run calls Start in dependency order.
type Statement ¶ added in v0.9.0
type Statement struct {
SQL string
Args []any
DB string // the database's name
Start time.Time
Duration time.Duration
Rows int64 // rows affected; -1 for a query
Err error
// Refused is a statement the database layer refused before sending it;
// Err says why.
Refused bool
}
Statement is a statement for the toolbar's SQL panel: what a database layer passes NoteStatement. orm's ormweb reports the ORM's statements by itself.
type Stopper ¶
Stopper is a provided value with work to do when the app stops: Stop is called in the reverse order of construction.
type URLParams ¶ added in v0.7.0
type URLParams struct{}
URLParams, embedded in a struct, makes it the parameters a Live page's Update method takes when the page is patched — moved to another URL of its route, the component staying mounted:
type ShelfParams struct {
web.URLParams
Page int // ?page=
}
func (s *Shelf) Update(p ShelfParams) { s.load(p.Page) }
Its fields bind from the new URL as the component's props do (path segment, else query parameter, of their name); the component's props are bound again too. Update runs before the patch renders, and an error it returns is the patch's, shown as a handler's. Mount, not Update, sees the first URL.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
pets/model
Package model holds the pets app's data types, shared by its handlers and its views.
|
Package model holds the pets app's data types, shared by its handlers and its views. |
|
internal
|
|
|
chrome
Package chrome drives a headless Chrome over the DevTools protocol, for the tests of live pages: open pages, click, type, press keys and evaluate JavaScript.
|
Package chrome drives a headless Chrome over the DevTools protocol, for the tests of live pages: open pages, click, type, press keys and evaluate JavaScript. |
|
liveproto
Package liveproto is the seam between the web framework's live transport and the Vuka live session it drives: a Session speaks the protocol version its page joined with (v1: HTML, v2: render trees) and answers each client message with the message to send back.
|
Package liveproto is the seam between the web framework's live transport and the Vuka live session it drives: a Session speaks the protocol version its page joined with (v1: HTML, v2: render trees) and answers each client message with the message to send back. |
|
livetree
Package livetree is a stand-in for the Vuka live session's protocol v2 until the session speaks it: it runs a v1 session and turns the HTML of each changed instance into render trees and their changes, in the format of Vuka's "Protocol v2: render trees" (docs/features/components.md).
|
Package livetree is a stand-in for the Vuka live session's protocol v2 until the session speaks it: it runs a v1 session and turns the HTML of each changed instance into render trees and their changes, in the format of Vuka's "Protocol v2: render trees" (docs/features/components.md). |