Documentation
¶
Overview ¶
Package transport defines the contract between the tether framework and its transport implementations (WebSocket, SSE). It lives in an internal package so that the main tether package can import the concrete ws and sse packages without creating a circular dependency.
User code should use the type aliases in the tether package ([tether.Transport], [tether.Event], [tether.Heartbeater]) rather than importing this package directly.
Index ¶
- type Event
- func (e Event) Bind(dest any) error
- func (e Event) Bool(key string) bool
- func (e Event) Float64(key string) (float64, error)
- func (e Event) Get(key string) (string, bool)
- func (e Event) Int(key string) (int, error)
- func (e Event) Key() string
- func (e Event) Value() string
- func (e Event) WithAction(action string) Event
- type Heartbeater
- type Transport
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Event ¶
type Event struct {
Type event.Type `json:"type"`
Action string `json:"action"`
Target string `json:"target,omitempty"`
Data map[string]string `json:"data,omitempty"`
EventID string `json:"event_id,omitempty"`
}
Event is the message the client sends to the server when the user interacts with the page. The client JS intercepts DOM events on elements annotated with data-tether-* attributes and serialises them into this structure.
Type is the DOM event type (e.g. click, input, submit, navigate). Action is the application-defined name that the Handle function switches on. Data carries event-specific key-value pairs.
EventID is a monotonically increasing counter generated by the client JS and echoed back in the server's response. The client uses it to correlate responses with specific events.
func (Event) Bind ¶
Bind decodes the event's Data map into a struct. Fields are matched by the "tether" struct tag; untagged exported fields use their lowercased name. Supported field types: string, int, int64, float64, bool.
This is the multi-field counterpart to the single-value helpers (Value, Key, Int, Bool). Use Bind when a form submit sends several named fields at once:
var form struct {
Email string `tether:"email"`
Age int `tether:"age"`
}
if err := ev.Bind(&form); err != nil {
s.TodoError = err.Error()
return s
}
func (Event) Bool ¶
Bool returns true when the data value for key is the string "true". All other values - including missing keys - return false.
func (Event) Float64 ¶
Float64 returns the data value for key parsed as a float. If the key is missing or the value is not a valid number, it returns 0 and an error.
func (Event) Int ¶
Int returns the data value for key parsed as an integer. If the key is missing or the value is not a valid integer, it returns 0 and an error.
func (Event) Key ¶
Key returns the key name from a keydown event. This is a convenience for ev.Data["key"], which the client JS populates automatically for keydown events (e.g. "Enter", "Escape", "ArrowUp").
func (Event) Value ¶
Value returns the input element's value from the event data. This is a convenience for ev.Data["value"], which the client JS populates automatically for input and change events.
func (Event) WithAction ¶
WithAction returns a copy of the event with a different Action. Used by component routing to strip the component prefix before forwarding the event to a component's Handle method.
type Heartbeater ¶
Heartbeater is an optional interface for transports that need periodic keep-alive activity. Both built-in transports implement it: SSE sends comment lines to prevent proxy timeouts; WebSocket sends ping frames and sets read deadlines to detect silently dropped connections.
When the handler detects that a transport implements Heartbeater, it calls StartHeartbeat with the configured interval after the session is established.
type Transport ¶
type Transport interface {
// Send writes pre-encoded bytes to the client. The session
// encodes updates before calling Send, so implementations only
// need to frame and transmit the data.
Send(data []byte) error
// ReceiveEvent blocks until the next client event arrives. Returns
// io.EOF when the connection is closed cleanly. Any other error is
// treated as an unrecoverable connection failure and terminates the
// session.
ReceiveEvent() (Event, error)
// Close terminates the connection. Must be safe to call from any
// goroutine and safe to call more than once.
Close() error
}
Transport abstracts the persistent connection between server and client. The session event loop calls ReceiveEvent in a tight loop and calls Send after each state change. Implementations must be safe for concurrent use: Send may be called from any goroutine, while ReceiveEvent is only called from the event loop goroutine.
Send receives pre-encoded bytes - the session handles all encoding so transports only deal with raw bytes.