fir

package module
v0.6.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 30, 2024 License: MIT Imports: 68 Imported by: 1

README

Fir

Go API Reference Alpine API Reference npm version

A Go toolkit to build reactive web interfaces using: Go, html/template and alpinejs.

The Fir toolkit is designed for Go developers with moderate html/css & js skills who want to progressively build reactive web apps without mastering complex web frameworks. It includes a Go library and an Alpine.js plugin. Fir can be used for building passable UIs with low effort and is a good fit for internal tools, interactive forms and real-time feeds.

Fir has a simple and predictable server and client API with only one new (and weird) expression:

  <div @fir:create-chirp:ok::chirp="$fir.prependEl()">
  ...
  </div>

snippet from chirper example

Fir’s magic event handling expression fir:event-name:event-state::template-name piggybacks on alpinejs event binding syntax to declare html/templates to be re-rendered on the server. Once accustomed to this weirdness, Fir unlocks a great deal of productivity while adhering to web standards to enable rich and interactive apps

Fir sits somewhere between Phoenix Liveview and htmx in terms of capabilities. It's event-driven like Liveview but, instead of providing atomic UI diffs, it returns html fragments like htmx. Fir is closer to liveview since it ships with a server library. Similar to Liveview, Fir has the concept of routes: Fir Route, Liveview Router, loading data on page load: Fir OnLoad, Liveview onmount and handling user events: Fir OnEvent, Liveview handle_event.

Feature Highlights:

  • Server rendered: Render HTML on the server using Go’s standard html templating library.
  • DOM Patching: React to user or server events to update only the changed parts of a web page.
  • Progressive enhancement: Begin with a JavaScript-free HTML file and Fir's Go server API for quick setup. Gradually improve to avoid page reloads, using Fir's Alpine.js plugin for DOM updates.
  • Publish over websocket: Broadcast html fragments over websocket in response to both client and server events.
  • Interactivity over standard HTTP: Fir possesses a built-in pubsub over websocket capability to broadcast UI diff changes to connected clients. However, it doesn't solely rely on websockets. It's still possible to disable websockets and benefit from UI diffs sent over standard HTTP.
  • Broadcast from server: Broadcast page changes to specific connected clients.
  • Error tracking: Show and hide user specific errors on the page by simply returning an error or nil.
  • Development live reload: HTML pages reload automatically on edits if development mode is enabled

Usage

Demo & Quickstart

Examples

How it works

CLI

You don't need this to get started but the the cli can be used to generate a simple quickstart boilerplate:

go run github.com/livefir/cli gen project -n quickstart // generates a folder named quickstart
cd quickstart
go run main.go
open localhost:9867

go run github.com/livefir/cli gen route -n index // generates a new route

Community

Documentation

Index

Constants

View Source
const (
	EventSocketConnected    = "fir_socket_connected"
	EventSocketDisconnected = "fir_socket_disconnected"
)

Variables

View Source
var ErrorEventFilterFormat = fmt.Errorf("error parsing event filter. must match ^[a-zA-Z0-9-]+:(ok|pending|error|done)$")

Functions

func RedirectUnauthorisedWebSocket added in v0.5.1

func RedirectUnauthorisedWebSocket(w http.ResponseWriter, r *http.Request, redirect string) bool

RedirectUnauthorisedWebSocket sends a 4001 close message to the client It sends the redirect url in the close message payload If the request is not a websocket request or has error upgrading and writing the close message, it returns false redirect url must be less than 123 bytes

Types

type ContextKey added in v0.1.5

type ContextKey int
const (
	// PathParamsKey is the key for the path params in the request context.
	PathParamsKey ContextKey = iota
	// UserKey is the key for the user id/name in the request context. It is used in the default channel function.
	UserKey
)

type Controller

type Controller interface {
	Route(route Route) http.HandlerFunc
	RouteFunc(options RouteFunc) http.HandlerFunc
}

Controller is an interface which encapsulates a group of views. It routes requests to the appropriate view. It routes events to the appropriate view. It also provides a way to register views.

func NewController

func NewController(name string, options ...ControllerOption) Controller

NewController creates a new controller.

type ControllerOption

type ControllerOption func(*opt)

ControllerOption is an option for the controller.

func DevelopmentMode

func DevelopmentMode(enable bool) ControllerOption

DevelopmentMode is an option to enable development mode. It enables debug logging, template watching, and disables template caching.

func DisableTemplateCache

func DisableTemplateCache() ControllerOption

DisableTemplateCache is an option to disable template caching. This is useful for development.

func EnableDebugLog

func EnableDebugLog() ControllerOption

EnableDebugLog is an option to enable debug logging.

func EnableWatch

func EnableWatch(rootDir string, extensions ...string) ControllerOption

EnableWatch is an option to enable watching template files for changes.

func WithChannelFunc added in v0.1.5

func WithChannelFunc(f func(r *http.Request, viewID string) *string) ControllerOption

WithChannelFunc is an option to set a function to construct the channel name for the controller's views.

func WithDisableWebsocket added in v0.1.2

func WithDisableWebsocket() ControllerOption

WithDisableWebsocket is an option to disable websocket.

func WithDropDuplicateInterval added in v0.6.0

func WithDropDuplicateInterval(interval time.Duration) ControllerOption

WithDropDuplicateInterval is an option to set the interval to drop duplicate events received by the websocket.

func WithEmbedFS

func WithEmbedFS(fs embed.FS) ControllerOption

WithEmbedFS is an option to set the embed.FS for the controller.

func WithFormDecoder

func WithFormDecoder(decoder *schema.Decoder) ControllerOption

WithFormDecoder is an option to set the form decoder(gorilla/schema) for the controller.

func WithFuncMap added in v0.2.11

func WithFuncMap(funcMap template.FuncMap) ControllerOption

func WithOnSocketConnect added in v0.6.0

func WithOnSocketConnect(f func(userOrSessionID string) error) ControllerOption

WithOnSocketConnect takes a function that is called when a new websocket connection is established. The function should return an error if the connection should be rejected. The user or fir's browser session id is passed to the function. user must be set in request.Context with the key UserKey by a developer supplied authentication mechanism. It can be used to track user connections and disconnections. It can be be used to reject connections based on user or session id. It can be used to refresh the page data when a user re-connects.

func WithOnSocketDisconnect added in v0.6.0

func WithOnSocketDisconnect(f func(userOrSessionID string)) ControllerOption

WithOnSocketDisconnect takes a function that is called when a websocket connection is disconnected.

func WithPathParamsFunc added in v0.1.5

func WithPathParamsFunc(f func(r *http.Request) PathParams) ControllerOption

WithPathParamsFunc is an option to set a function to construct the path params for the controller's views.

func WithPublicDir

func WithPublicDir(path string) ControllerOption

WithPublicDir is the path to directory containing the public html template files.

func WithPubsubAdapter

func WithPubsubAdapter(pubsub pubsub.Adapter) ControllerOption

WithPubsubAdapter is an option to set a pubsub adapter for the controller's views.

func WithSessionName added in v0.1.2

func WithSessionName(name string) ControllerOption

WithSessionName is an option to set the session name/cookie name for the controller.

func WithSessionSecrets added in v0.4.0

func WithSessionSecrets(hashKey []byte, blockKey []byte) ControllerOption

WithSessionSecrets is an option to set the session secrets for the controller. used to sign and encrypt the session cookie.

func WithWebsocketUpgrader

func WithWebsocketUpgrader(upgrader websocket.Upgrader) ControllerOption

WithWebsocketUpgrader is an option to set the websocket upgrader for the controller

type Event

type Event struct {
	// ID is the event id
	ID string `json:"event_id"`
	// Params is the data to be passed to the event
	Params json.RawMessage `json:"params"`
	// Target is the dom element id which emitted the event. The DOM events generated by the event will be targeted to this element.
	Target *string `json:"target,omitempty"`
	// IsForm is a boolean that indicates whether the event was triggered by a form submission
	IsForm bool `json:"is_form,omitempty"`
	// SessionID is the id of the session that the event was triggered for
	SessionID  *string `json:"session_id,omitempty"`
	ElementKey *string `json:"element_key,omitempty"`
	Timestamp  int64   `json:"ts,omitempty"`
}

Event is a struct that holds the data for an incoming user event

func NewEvent

func NewEvent(id string, params any) Event

NewEvent creates a new event

func (Event) String

func (e Event) String() string

String returns the string representation of the event

type OnEventFunc

type OnEventFunc func(ctx RouteContext) error

OnEventFunc is a function that handles an http event request

type PathParams added in v0.1.5

type PathParams map[string]any

type Route

type Route interface{ Options() RouteOptions }

Route is an interface that represents a route

type RouteContext

type RouteContext struct {
	// contains filtered or unexported fields
}

RouteContext is the context for a route handler. Its methods are used to return data or patch operations to the client.

func (RouteContext) Bind

func (c RouteContext) Bind(v any) error

Bind decodes the event params into the given struct

func (RouteContext) BindEventParams

func (c RouteContext) BindEventParams(v any) error

func (RouteContext) BindPathParams

func (c RouteContext) BindPathParams(v any) error

func (RouteContext) BindQueryParams

func (c RouteContext) BindQueryParams(v any) error

func (RouteContext) Data

func (c RouteContext) Data(dataset ...any) error

Data sets the data to be hydrated into the route's template or an event's associated template/block action It accepts either a map or struct type so that fir can inject utility functions: fir.Error, fir.ActiveRoute etc. If the data is a struct, it will be converted to a map using github.com/fatih/structs If the data is a pointer to a struct, it will be dereferenced and converted to a map using github.com/fatih/structs If the data is a map, it will be used as is If the data is a pointer to a map, it will be dereferenced and used as is The function will return nil if no data is passed The function accepts variadic arguments so that you can pass multiple structs or maps which will be merged

func (RouteContext) Event

func (c RouteContext) Event() Event

func (RouteContext) FieldError

func (c RouteContext) FieldError(field string, err error) error

FieldError sets the error message for the given field and can be looked up by {{fir.Error "myevent.field"}}

func (RouteContext) FieldErrors

func (c RouteContext) FieldErrors(fields map[string]error) error

FieldErrors sets the error messages for the given fields and can be looked up by {{fir.Error "myevent.field"}}

func (RouteContext) GetUserFromContext added in v0.1.8

func (c RouteContext) GetUserFromContext() string

func (RouteContext) KV

func (c RouteContext) KV(key string, data any) error

KV is a wrapper for ctx.Data(map[string]any{key: data})

func (RouteContext) Redirect

func (c RouteContext) Redirect(url string, status int) error

Redirect redirects the client to the given url

func (RouteContext) Request

func (c RouteContext) Request() *http.Request

Request returns the http.Request for the current context

func (RouteContext) Response

func (c RouteContext) Response() http.ResponseWriter

Response returns the http.ResponseWriter for the current context

func (RouteContext) State added in v0.2.8

func (c RouteContext) State(dataset ...any) error

State data is only passed to event receiver without a bound template it can be acccessed in the event receiver via $event.detail e.g. @fir:myevent:ok="console.log('$event.detail.mykey')"

func (RouteContext) StateKV added in v0.2.8

func (c RouteContext) StateKV(key string, data any) error

KV is a wrapper for ctx.State(map[string]any{key: data})

func (RouteContext) Status added in v0.1.5

func (c RouteContext) Status(code int, err error) error

type RouteDOMContext

type RouteDOMContext struct {
	Name        string
	Development bool
	URLPath     string
	// contains filtered or unexported fields
}

RouteDOMContext is a struct that holds route context data and is passed to the template

func (*RouteDOMContext) ActiveRoute

func (rc *RouteDOMContext) ActiveRoute(path, class string) string

ActiveRoute returns the class if the route is active

func (*RouteDOMContext) Error

func (rc *RouteDOMContext) Error(paths ...string) any

Error can be used to lookup an error by name Example: {{fir.Error "myevent.field"}} will return the error for the field myevent.field Example: {{fir.Error "myevent" "field"}} will return the error for the event myevent.field It can be used in conjunction with ctx.FieldError to get the error for a field

func (*RouteDOMContext) NotActiveRoute

func (rc *RouteDOMContext) NotActiveRoute(path, class string) string

NotActive returns the class if the route is not active

type RouteFunc

type RouteFunc func() RouteOptions

RouteFunc is a function that handles a route

type RouteOption

type RouteOption func(*routeOpt)

RouteOption is a function that sets route options

func Content

func Content(content string) RouteOption

Content sets the content for the route

func ErrorContent added in v0.1.5

func ErrorContent(content string) RouteOption

ErrorContent sets the content for the route

func ErrorLayout added in v0.1.5

func ErrorLayout(layout string) RouteOption

ErrorLayout sets the layout for the route's template engine

func ErrorLayoutContentName added in v0.1.5

func ErrorLayoutContentName(name string) RouteOption

ErrorLayoutContentName sets the name of the template which contains the content.

{{define "layout"}}
{{ define "content" }}
{{ end }}
{{end}}

Here "content" is the default layout content name

func EventSender

func EventSender(eventSender chan Event) RouteOption

EventSender sets the event sender for the route. It can be used to send events for the route without a corresponding user event. This is useful for sending events to the route event handler for use cases like: sending notifications, sending emails, etc.

func Extensions

func Extensions(extensions ...string) RouteOption

Extensions sets the template file extensions read for the route's template engine

func FuncMap

func FuncMap(funcMap template.FuncMap) RouteOption

FuncMap appends to the default template function map for the route's template engine

func ID

func ID(id string) RouteOption

ID sets the route unique identifier. This is used to identify the route in pubsub.

func Layout

func Layout(layout string) RouteOption

Layout sets the layout for the route's template engine

func LayoutContentName

func LayoutContentName(name string) RouteOption

LayoutContentName sets the name of the template which contains the content.

{{define "layout"}}
{{ define "content" }}
{{ end }}
{{end}}

Here "content" is the default layout content name

func OnEvent

func OnEvent(name string, onEventFunc OnEventFunc) RouteOption

OnEvent registers an event handler for the route per unique event name. It can be called multiple times to register multiple event handlers for the route.

func OnLoad

func OnLoad(f OnEventFunc) RouteOption

OnLoad sets the route's onload event handler

func Partials

func Partials(partials ...string) RouteOption

Partials sets the template partials for the route's template engine

type RouteOptions

type RouteOptions []RouteOption

RouteOptions is a slice of RouteOption

type SocketStatus added in v0.6.1

type SocketStatus struct {
	Connected bool
	User      string
}

type Todo added in v0.2.3

type Todo struct {
	ID        uint64    `json:"id" boltholdKey:"ID"`
	Text      string    `json:"text"`
	Done      bool      `json:"done"`
	CreatedAt time.Time `json:"created_at"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL