Skip to content

Commit

Permalink
feat: Introduce SelfHandler which passes data directly with no Params. (
Browse files Browse the repository at this point in the history
  • Loading branch information
jfyne committed Jan 4, 2022
1 parent ccefddf commit d1928d5
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 36 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ an interactive web app just using Go and its templates.
The structures provided in this package are compatible with `net/http`, so will play
nicely with middleware and other frameworks.

- [Fiber](https://github.com/jfyne/live-contrib/tree/main/livefiber)
## Other implementations

- [Fiber](https://github.com/jfyne/live-contrib/tree/main/livefiber) a live handler for [Fiber](https://github.com/gofiber/fiber).

## Community

Expand Down
14 changes: 2 additions & 12 deletions engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package live

import (
"context"
"encoding/json"
"fmt"
"log"
"sync"
Expand Down Expand Up @@ -108,11 +107,7 @@ func (e *BaseEngine) Error() ErrorHandler {

// Broadcast send a message to all sockets connected to this engine.
func (e *BaseEngine) Broadcast(event string, data interface{}) error {
payload, err := json.Marshal(data)
if err != nil {
return fmt.Errorf("could not encode data for broadcast: %w", err)
}
ev := Event{T: event, Data: payload}
ev := Event{T: event, SelfData: data}
ctx := context.Background()
e.broadcastLimiter.Wait(ctx)
e.broadcastHandler(ctx, e, ev)
Expand Down Expand Up @@ -191,12 +186,7 @@ func (e *BaseEngine) handleSelf(ctx context.Context, t string, sock Socket, msg
return fmt.Errorf("no self event handler for %s: %w", t, ErrNoEventHandler)
}

params, err := msg.Params()
if err != nil {
return fmt.Errorf("received self message and could not extract params: %w", err)
}

data, err := handler(ctx, sock, params)
data, err := handler(ctx, sock, msg.SelfData)
if err != nil {
return fmt.Errorf("handler self event handler error [%s]: %w", t, err)
}
Expand Down
12 changes: 4 additions & 8 deletions event.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
package live

import (
"context"
"encoding/json"
)

// EventHandler a function to handle events, returns the data that should
// be set to the socket after handling.
type EventHandler func(context.Context, Socket, Params) (interface{}, error)

// EventConfig configures an event.
type EventConfig func(e *Event) error

Expand All @@ -33,9 +28,10 @@ const (
// Event messages that are sent and received by the
// socket.
type Event struct {
T string `json:"t"`
ID int `json:"i,omitempty"`
Data json.RawMessage `json:"d,omitempty"`
T string `json:"t"`
ID int `json:"i,omitempty"`
Data json.RawMessage `json:"d,omitempty"`
SelfData interface{} `json:"-"`
}

// Params extract params from inbound message.
Expand Down
20 changes: 14 additions & 6 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ type RenderHandler func(ctx context.Context, data interface{}) (io.Reader, error
// a handler of this type will be called.
type ErrorHandler func(ctx context.Context, err error)

// EventHandler a function to handle events, returns the data that should
// be set to the socket after handling.
type EventHandler func(context.Context, Socket, Params) (interface{}, error)

// SelfHandler a function to handle self events, returns the data that should
// be set to the socket after handling.
type SelfHandler func(context.Context, Socket, interface{}) (interface{}, error)

// Handler methods.
type Handler interface {
// HandleMount handles initial setup on first request, and then later when
Expand All @@ -40,7 +48,7 @@ type Handler interface {
HandleEvent(t string, handler EventHandler)
// HandleSelf handles an event that comes from the server side socket. For example calling
// h.Self(socket, msg) will be handled here.
HandleSelf(t string, handler EventHandler)
HandleSelf(t string, handler SelfHandler)
// HandleParams handles a URL query parameter change. This is useful for handling
// things like pagincation, or some filtering.
HandleParams(handler EventHandler)
Expand All @@ -49,7 +57,7 @@ type Handler interface {
getRender() RenderHandler
getError() ErrorHandler
getEvent(t string) (EventHandler, error)
getSelf(t string) (EventHandler, error)
getSelf(t string) (SelfHandler, error)
getParams() []EventHandler
}

Expand All @@ -68,7 +76,7 @@ type BaseHandler struct {
// eventHandlers the map of client event handlers.
eventHandlers map[string]EventHandler
// selfHandlers the map of handler event handlers.
selfHandlers map[string]EventHandler
selfHandlers map[string]SelfHandler
// paramsHandlers a slice of handlers which respond to a change in URL parameters.
paramsHandlers []EventHandler
}
Expand All @@ -77,7 +85,7 @@ type BaseHandler struct {
func NewHandler(configs ...HandlerConfig) *BaseHandler {
h := &BaseHandler{
eventHandlers: make(map[string]EventHandler),
selfHandlers: make(map[string]EventHandler),
selfHandlers: make(map[string]SelfHandler),
paramsHandlers: []EventHandler{},
mountHandler: func(ctx context.Context, s Socket) (interface{}, error) {
return nil, nil
Expand Down Expand Up @@ -119,7 +127,7 @@ func (h *BaseHandler) HandleEvent(t string, handler EventHandler) {

// HandleSelf handles an event that comes from the server side socket. For example calling
// h.Self(socket, msg) will be handled here.
func (h *BaseHandler) HandleSelf(t string, handler EventHandler) {
func (h *BaseHandler) HandleSelf(t string, handler SelfHandler) {
h.selfHandlers[t] = handler
}

Expand All @@ -145,7 +153,7 @@ func (h *BaseHandler) getEvent(t string) (EventHandler, error) {
}
return handler, nil
}
func (h *BaseHandler) getSelf(t string) (EventHandler, error) {
func (h *BaseHandler) getSelf(t string) (SelfHandler, error) {
handler, ok := h.selfHandlers[t]
if !ok {
return nil, fmt.Errorf("no self handler for %s: %w", t, ErrNoEventHandler)
Expand Down
12 changes: 8 additions & 4 deletions page/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ type MountHandler func(ctx context.Context, c *Component) error
type RenderHandler func(w io.Writer, c *Component) error

// EventHandler for a component, only needs the params as the event is scoped to both the socket and then component
// iteslef. Returns any component state that needs updating.
// itself. Returns any component state that needs updating.
type EventHandler func(ctx context.Context, p live.Params) (interface{}, error)

// SelfHandler for a component, only needs the data as the event is scoped to both the socket and then component
// itself. Returns any component state that needs updating.
type SelfHandler func(ctx context.Context, data interface{}) (interface{}, error)

// ComponentConstructor a func for creating a new component.
type ComponentConstructor func(ctx context.Context, h live.Handler, s live.Socket) (*Component, error)

Expand Down Expand Up @@ -93,9 +97,9 @@ func (c *Component) Self(ctx context.Context, s live.Socket, event string, data
}

// HandleSelf handles scoped incoming events send by a components Self function.
func (c *Component) HandleSelf(event string, handler EventHandler) {
c.Handler.HandleSelf(c.Event(event), func(ctx context.Context, s live.Socket, p live.Params) (interface{}, error) {
state, err := handler(ctx, p)
func (c *Component) HandleSelf(event string, handler SelfHandler) {
c.Handler.HandleSelf(c.Event(event), func(ctx context.Context, s live.Socket, d interface{}) (interface{}, error) {
state, err := handler(ctx, d)
if err != nil {
return s.Assigns(), err
}
Expand Down
6 changes: 1 addition & 5 deletions socket.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,7 @@ func (s *BaseSocket) Connected() bool {
// Self send an event to this socket itself. Will be handled in the
// handlers HandleSelf function.
func (s *BaseSocket) Self(ctx context.Context, event string, data interface{}) error {
payload, err := json.Marshal(data)
if err != nil {
return fmt.Errorf("could not encode data for self: %w", err)
}
msg := Event{T: event, Data: payload}
msg := Event{T: event, SelfData: data}
s.engine.self(ctx, s, msg)
return nil
}
Expand Down

0 comments on commit d1928d5

Please sign in to comment.