Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Component Style #54

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ jobs:
test:
strategy:
matrix:
go-version: [1.17.x, 1.18.x]
go-version: [1.18.x]
node-version: [16.x, 17.x]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
Expand Down
54 changes: 25 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,22 @@ func NewThermoModel(s Socket) *ThermoModel {

// thermoMount initialises the thermostat state. Data returned in the mount function will
// automatically be assigned to the socket.
func thermoMount(ctx context.Context, s Socket) (interface{}, error) {
func thermoMount(ctx context.Context, s Socket) (any, error) {
return NewThermoModel(s), nil
}

// tempUp on the temp up event, increase the thermostat temperature by .1 C. An EventHandler function
// is called with the original request context of the socket, the socket itself containing the current
// state and and params that came from the event. Params contain query string parameters and any
// `live-value-` bindings.
func tempUp(ctx context.Context, s Socket, p Params) (interface{}, error) {
func tempUp(ctx context.Context, s Socket, p Params) (any, error) {
model := NewThermoModel(s)
model.C += 0.1
return model, nil
}

// tempDown on the temp down event, decrease the thermostat temperature by .1 C.
func tempDown(ctx context.Context, s Socket, p Params) (interface{}, error) {
func tempDown(ctx context.Context, s Socket, p Params) (any, error) {
model := NewThermoModel(s)
model.C -= 0.1
return model, nil
Expand Down Expand Up @@ -159,39 +159,35 @@ package page

import (
"context"
"io"
"net/http"

"github.com/jfyne/live"
)

// NewGreeter creates a new greeter component.
func NewGreeter(ID string, h live.Handler, s live.Socket, name string) (*Component, error) {
return NewComponent(
ID,
h,
s,
WithMount(func(ctx context.Context, c *Component) error {
c.State = name
return nil
}),
WithRender(func(w io.Writer, c *Component) error {
// Render the greeter, here we are including the script just to make this toy example work.
return HTML(`
<div class="greeter">Hello {{.}}</div>
<script src="/live.js"></script>
`, c).Render(w)
}),
)
type Greeter struct {
Name string

Component
}

func NewGreeter(name string) *Greeter {
return &Greeter{
Name: name,
}
}

func (g Greeter) Render() RenderFunc {
return HTML(`
<div class="greeter">Hello {{.Name}}</div>
<script src="/live.js"></script>
`, g)
}

func Example() {
h := live.NewHandler(
WithComponentMount(func(ctx context.Context, h live.Handler, s live.Socket) (*Component, error) {
return NewGreeter("hello-id", h, s, "World!")
}),
WithComponentRenderer(),
)
h := NewHandler(func(_ context.Context, _ *live.Handler, _ live.Socket) (ComponentLifecycle, error) {
root := NewGreeter("World!")
return root, nil
})

http.Handle("/", live.NewHttpHandler(live.NewCookieStore("session-name", []byte("weak-secret")), h))
http.Handle("/live.js", live.Javascript{})
Expand All @@ -217,7 +213,7 @@ Clicking on this tag will result in the browser URL being updated, and then an e
trigger the handler's `HandleParams` callback. With the query string being available in the params map of the handler.

```go
h.HandleParams(func(s *live.Socket, p live.Params) (interface{}, error) {
h.HandleParams(func(s *live.Socket, p live.Params) (any, error) {
...
page := p.Int("page")
...
Expand Down
21 changes: 21 additions & 0 deletions cmd/example/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package main

import (
"context"
"net/http"

"github.com/jfyne/live"
"github.com/jfyne/live/examples"
"github.com/jfyne/live/page"
)

func main() {
h := page.NewHandler(func(_ context.Context, _ *live.Handler, _ live.Socket) (page.Component, error) {
root := examples.NewApp()
return root, nil
})

http.Handle("/", live.NewHttpHandler(live.NewCookieStore("session-name", []byte("weak-secret")), h))
http.Handle("/live.js", live.Javascript{})
http.ListenAndServe(":8080", nil)
}
26 changes: 13 additions & 13 deletions engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type BroadcastHandler func(ctx context.Context, e Engine, msg Event)
// Engine methods.
type Engine interface {
// Handler takes a handler to configure the lifecycle.
Handler(h Handler)
Handler(h *Handler)
// Mount a user should provide the mount function. This is what
// is called on initial GET request and later when the websocket connects.
// Data to render the handler should be fetched here and returned.
Expand Down Expand Up @@ -52,7 +52,7 @@ type Engine interface {
// HandleBroadcast allows overriding the broadcast functionality.
HandleBroadcast(handler BroadcastHandler)
// Broadcast send a message to all sockets connected to this engine.
Broadcast(event string, data interface{}) error
Broadcast(event string, data any) error

// self sends a message to the socket on this engine.
self(ctx context.Context, sock Socket, msg Event)
Expand All @@ -61,7 +61,7 @@ type Engine interface {
// BaseEngine handles live inner workings.
type BaseEngine struct {
// handler implements all the developer defined logic.
handler Handler
handler *Handler

// broadcastLimiter limit broadcast ratehandler.
broadcastLimiter *rate.Limiter
Expand All @@ -87,7 +87,7 @@ type BaseEngine struct {
}

// NewBaseEngine creates a new base engine.
func NewBaseEngine(h Handler) *BaseEngine {
func NewBaseEngine(h *Handler) *BaseEngine {
const maxUploadSize = 100 * 1024 * 1024
return &BaseEngine{
broadcastLimiter: rate.NewLimiter(rate.Every(time.Millisecond*100), 8),
Expand All @@ -96,40 +96,40 @@ func NewBaseEngine(h Handler) *BaseEngine {
},
socketMap: make(map[SocketID]Socket),
IgnoreFaviconRequest: true,
MaxUploadSize: 100 * 1024 * 1024,
MaxUploadSize: maxUploadSize,
handler: h,
}
}

func (e *BaseEngine) Handler(hand Handler) {
func (e *BaseEngine) Handler(hand *Handler) {
e.handler = hand
}
func (e *BaseEngine) HandleBroadcast(f BroadcastHandler) {
e.broadcastHandler = f
}

func (e *BaseEngine) Mount() MountHandler {
return e.handler.getMount()
return e.handler.mountHandler
}

func (e *BaseEngine) Unmount() UnmountHandler {
return e.handler.getUnmount()
return e.handler.unmountHandler
}

func (e *BaseEngine) Params() []EventHandler {
return e.handler.getParams()
return e.handler.paramsHandlers
}

func (e *BaseEngine) Render() RenderHandler {
return e.handler.getRender()
return e.handler.renderHandler
}

func (e *BaseEngine) Error() ErrorHandler {
return e.handler.getError()
return e.handler.errorHandler
}

// Broadcast send a message to all sockets connected to this engine.
func (e *BaseEngine) Broadcast(event string, data interface{}) error {
func (e *BaseEngine) Broadcast(event string, data any) error {
ev := Event{T: event, SelfData: data}
ctx := context.Background()
e.broadcastLimiter.Wait(ctx)
Expand Down Expand Up @@ -241,7 +241,7 @@ func (e *BaseEngine) CallParams(ctx context.Context, sock Socket, msg Event) err
return fmt.Errorf("received params message and could not extract params: %w", err)
}

for _, ph := range e.handler.getParams() {
for _, ph := range e.handler.paramsHandlers {
data, err := ph(ctx, sock, params)
if err != nil {
return fmt.Errorf("handler params handler error: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion event.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type Event struct {
T string `json:"t"`
ID int `json:"i,omitempty"`
Data json.RawMessage `json:"d,omitempty"`
SelfData interface{} `json:"s,omitempty"`
SelfData any `json:"s,omitempty"`
}

// Params extract params from inbound message.
Expand Down
6 changes: 3 additions & 3 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,22 @@ func NewThermoModel(s Socket) *ThermoModel {

// thermoMount initialises the thermostat state. Data returned in the mount function will
// automatically be assigned to the socket.
func thermoMount(ctx context.Context, s Socket) (interface{}, error) {
func thermoMount(ctx context.Context, s Socket) (any, error) {
return NewThermoModel(s), nil
}

// tempUp on the temp up event, increase the thermostat temperature by .1 C. An EventHandler function
// is called with the original request context of the socket, the socket itself containing the current
// state and and params that came from the event. Params contain query string parameters and any
// `live-value-` bindings.
func tempUp(ctx context.Context, s Socket, p Params) (interface{}, error) {
func tempUp(ctx context.Context, s Socket, p Params) (any, error) {
model := NewThermoModel(s)
model.C += 0.1
return model, nil
}

// tempDown on the temp down event, decrease the thermostat temperature by .1 C.
func tempDown(ctx context.Context, s Socket, p Params) (interface{}, error) {
func tempDown(ctx context.Context, s Socket, p Params) (any, error) {
model := NewThermoModel(s)
model.C -= 0.1
return model, nil
Expand Down
31 changes: 31 additions & 0 deletions examples/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package examples

import "github.com/jfyne/live/page"

type App struct {
Button *Button

page.BaseComponent
}

func NewApp() *App {
return &App{
Button: NewButton(10),
}
}

func (a App) Render() page.RenderFunc {
return page.HTML(`
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Live examples</title>
</head>
<body>
{{ .Button }}
<script src="/live.js"></script>
</body>
</html>
`, a)
}
21 changes: 21 additions & 0 deletions examples/button.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package examples

import (
"github.com/jfyne/live/page"
)

type Button struct {
Count int

page.BaseComponent
}

func NewButton(start int) *Button {
return &Button{Count: start}
}

func (b Button) Render() page.RenderFunc {
return page.HTML(`
{{.Count}}
`, b)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/jfyne/live

go 1.17
go 1.18

require (
github.com/google/go-cmp v0.5.7
Expand Down
Loading