Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82a3314089 | ||
|
|
73f4e4009b | ||
|
|
c77ccc0796 | ||
|
|
d4b831492e |
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-via/via/h"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
)
|
||||
|
||||
// actionTrigger represents a trigger to an event handler fn
|
||||
|
||||
@@ -2,17 +2,6 @@ package via
|
||||
|
||||
import "github.com/alexedwards/scs/v2"
|
||||
|
||||
// DatastarConfig configures a custom Datastar.js script.
|
||||
type DatastarConfig struct {
|
||||
// Content is the Datastar.js script content.
|
||||
// If nil, the embedded default is used.
|
||||
Content []byte
|
||||
|
||||
// Path is the URL path where the script is served.
|
||||
// Defaults to "/_datastar.js" if empty.
|
||||
Path string
|
||||
}
|
||||
|
||||
type LogLevel int
|
||||
|
||||
const (
|
||||
@@ -49,7 +38,11 @@ type Options struct {
|
||||
// passing it (lifetime, cookie settings, store, etc).
|
||||
SessionManager *scs.SessionManager
|
||||
|
||||
// Datastar configures a custom Datastar.js script.
|
||||
// If nil, Via uses its embedded default.
|
||||
Datastar *DatastarConfig
|
||||
// DatastarContent is the Datastar.js script content.
|
||||
// If nil, the embedded default is used.
|
||||
DatastarContent []byte
|
||||
|
||||
// DatastarPath is the URL path where the script is served.
|
||||
// Defaults to "/_datastar.js" if empty.
|
||||
DatastarPath string
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-via/via/h"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
)
|
||||
|
||||
// Context is the living bridge between Go and the browser.
|
||||
|
||||
7
go.mod
7
go.mod
@@ -1,4 +1,4 @@
|
||||
module github.com/go-via/via
|
||||
module github.com/ryanhamamura/via
|
||||
|
||||
go 1.25.4
|
||||
|
||||
@@ -6,6 +6,8 @@ require maragu.dev/gomponents v1.2.0
|
||||
|
||||
require (
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||
github.com/alexedwards/scs/sqlite3store v0.0.0-20251002162104-209de6e426de
|
||||
github.com/alexedwards/scs/v2 v2.9.0
|
||||
github.com/mattn/go-sqlite3 v1.14.32
|
||||
github.com/starfederation/datastar-go v1.0.3
|
||||
github.com/stretchr/testify v1.10.0
|
||||
@@ -13,13 +15,10 @@ require (
|
||||
|
||||
require (
|
||||
github.com/CAFxX/httpcompression v0.0.9 // indirect
|
||||
github.com/alexedwards/scs/v2 v2.9.0 // indirect
|
||||
github.com/andybalholm/brotli v1.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
11
go.sum
11
go.sum
@@ -2,6 +2,8 @@ github.com/CAFxX/httpcompression v0.0.9 h1:0ue2X8dOLEpxTm8tt+OdHcgA+gbDge0OqFQWG
|
||||
github.com/CAFxX/httpcompression v0.0.9/go.mod h1:XX8oPZA+4IDcfZ0A71Hz0mZsv/YJOgYygkFhizVPilM=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||
github.com/alexedwards/scs/sqlite3store v0.0.0-20251002162104-209de6e426de h1:c72K9HLu6K442et0j3BUL/9HEYaUJouLkkVANdmqTOo=
|
||||
github.com/alexedwards/scs/sqlite3store v0.0.0-20251002162104-209de6e426de/go.mod h1:Iyk7S76cxGaiEX/mSYmTZzYehp4KfyylcLaV3OnToss=
|
||||
github.com/alexedwards/scs/v2 v2.9.0 h1:xa05mVpwTBm1iLeTMNFfAWpKUm4fXAW7CeAViqBVS90=
|
||||
github.com/alexedwards/scs/v2 v2.9.0/go.mod h1:ToaROZxyKukJKT/xLcVQAChi5k6+Pn1Gvmdl7h3RRj8=
|
||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
@@ -17,11 +19,7 @@ github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQs
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
|
||||
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
|
||||
@@ -45,9 +43,8 @@ github.com/valyala/gozstd v1.20.1 h1:xPnnnvjmaDDitMFfDxmQ4vpx0+3CdTg2o3lALvXTU/g
|
||||
github.com/valyala/gozstd v1.20.1/go.mod h1:y5Ew47GLlP37EkTB+B4s7r6A5rdaeB7ftbl9zoYiIPQ=
|
||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -3,8 +3,8 @@ package main
|
||||
import (
|
||||
"math/rand"
|
||||
|
||||
"github.com/go-via/via"
|
||||
"github.com/go-via/via/h"
|
||||
"github.com/ryanhamamura/via"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/go-via/via"
|
||||
"github.com/go-via/via/h"
|
||||
"github.com/ryanhamamura/via"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
)
|
||||
|
||||
type Counter struct{ Count int }
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/go-via/via"
|
||||
"github.com/go-via/via/h"
|
||||
"github.com/ryanhamamura/via"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/go-via/via"
|
||||
"github.com/go-via/via/h"
|
||||
"github.com/ryanhamamura/via"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/go-via/via"
|
||||
"github.com/ryanhamamura/via"
|
||||
// "github.com/go-via/via-plugin-picocss/picocss"
|
||||
"github.com/go-via/via/h"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
)
|
||||
|
||||
type Counter struct{ Count int }
|
||||
|
||||
@@ -3,9 +3,9 @@ package main
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/go-via/via"
|
||||
"github.com/ryanhamamura/via"
|
||||
// "github.com/go-via/via-plugin-picocss/picocss"
|
||||
. "github.com/go-via/via/h"
|
||||
. "github.com/ryanhamamura/via/h"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/go-via/via"
|
||||
"github.com/ryanhamamura/via"
|
||||
// "github.com/go-via/via-plugin-picocss/picocss"
|
||||
"github.com/go-via/via/h"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
)
|
||||
|
||||
type Counter struct{ Count int }
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
_ "embed"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-via/via"
|
||||
"github.com/go-via/via/h"
|
||||
"github.com/ryanhamamura/via"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
)
|
||||
|
||||
// Example of a Via application with a plugin that adds PicoCSS. The plugin
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/go-via/via"
|
||||
"github.com/ryanhamamura/via"
|
||||
// "github.com/go-via/via-plugin-picocss/picocss"
|
||||
"github.com/go-via/via/h"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -1,13 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/go-via/via"
|
||||
"github.com/go-via/via/h"
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/ryanhamamura/via"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Open SQLite database for persistent sessions
|
||||
db, err := sql.Open("sqlite3", "sessions.db")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open database: %v", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
// Create session manager with SQLite store
|
||||
sm, err := via.NewSQLiteSessionManager(db)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to create session manager: %v", err)
|
||||
}
|
||||
|
||||
v := via.New()
|
||||
v.Config(via.Options{ServerAddress: ":7331"})
|
||||
v.Config(via.Options{
|
||||
ServerAddress: ":7331",
|
||||
SessionManager: sm,
|
||||
})
|
||||
|
||||
// Login page
|
||||
v.Page("/login", func(c *via.Context) {
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/go-via/via"
|
||||
"github.com/go-via/via/h"
|
||||
"github.com/ryanhamamura/via"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
|
||||
23
session.go
23
session.go
@@ -2,11 +2,34 @@ package via
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"github.com/alexedwards/scs/sqlite3store"
|
||||
"github.com/alexedwards/scs/v2"
|
||||
)
|
||||
|
||||
// NewSQLiteSessionManager creates a session manager using SQLite for persistence.
|
||||
// Creates the sessions table if it doesn't exist.
|
||||
// The returned manager can be configured further (Lifetime, Cookie settings, etc.)
|
||||
// before passing to Options.SessionManager.
|
||||
func NewSQLiteSessionManager(db *sql.DB) (*scs.SessionManager, error) {
|
||||
_, err := db.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS sessions (
|
||||
token TEXT PRIMARY KEY,
|
||||
data BLOB NOT NULL,
|
||||
expiry REAL NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS sessions_expiry_idx ON sessions(expiry);
|
||||
`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sm := scs.New()
|
||||
sm.Store = sqlite3store.New(db)
|
||||
return sm, nil
|
||||
}
|
||||
|
||||
// Session provides access to the user's session data.
|
||||
// Session data persists across page views for the same browser.
|
||||
type Session struct {
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-via/via/h"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
)
|
||||
|
||||
// Signal represents a value that is reactive in the browser. Signals
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
// "net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/go-via/via/h"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
||||
28
via.go
28
via.go
@@ -22,7 +22,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/alexedwards/scs/v2"
|
||||
"github.com/go-via/via/h"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
"github.com/starfederation/datastar-go/datastar"
|
||||
)
|
||||
|
||||
@@ -42,7 +42,7 @@ type V struct {
|
||||
sessionManager *scs.SessionManager
|
||||
datastarPath string
|
||||
datastarContent []byte
|
||||
datastarHandlerRegistered bool
|
||||
datastarOnce sync.Once
|
||||
}
|
||||
|
||||
func (v *V) logFatal(format string, a ...any) {
|
||||
@@ -111,13 +111,11 @@ func (v *V) Config(cfg Options) {
|
||||
if cfg.SessionManager != nil {
|
||||
v.sessionManager = cfg.SessionManager
|
||||
}
|
||||
if cfg.Datastar != nil {
|
||||
if cfg.Datastar.Content != nil {
|
||||
v.datastarContent = cfg.Datastar.Content
|
||||
}
|
||||
if cfg.Datastar.Path != "" {
|
||||
v.datastarPath = cfg.Datastar.Path
|
||||
if cfg.DatastarContent != nil {
|
||||
v.datastarContent = cfg.DatastarContent
|
||||
}
|
||||
if cfg.DatastarPath != "" {
|
||||
v.datastarPath = cfg.DatastarPath
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,14 +269,12 @@ func (v *V) HTTPServeMux() *http.ServeMux {
|
||||
}
|
||||
|
||||
func (v *V) ensureDatastarHandler() {
|
||||
if v.datastarHandlerRegistered {
|
||||
return
|
||||
}
|
||||
v.datastarHandlerRegistered = true
|
||||
v.datastarOnce.Do(func() {
|
||||
v.mux.HandleFunc("GET "+v.datastarPath, func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/javascript")
|
||||
_, _ = w.Write(v.datastarContent)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func (v *V) devModePersist(c *Context) {
|
||||
@@ -412,10 +408,6 @@ func New() *V {
|
||||
}
|
||||
|
||||
v.mux.HandleFunc("GET /_sse", func(w http.ResponseWriter, r *http.Request) {
|
||||
isReconnect := false
|
||||
if r.Header.Get("last-event-id") == "via" {
|
||||
isReconnect = true
|
||||
}
|
||||
var sigs map[string]any
|
||||
_ = datastar.ReadSignals(r, &sigs)
|
||||
cID, _ := sigs["via-ctx"].(string)
|
||||
@@ -440,11 +432,7 @@ func New() *V {
|
||||
v.logDebug(c, "SSE connection established")
|
||||
|
||||
go func() {
|
||||
if isReconnect || v.cfg.DevMode {
|
||||
c.Sync()
|
||||
return
|
||||
}
|
||||
c.SyncSignals()
|
||||
}()
|
||||
|
||||
for {
|
||||
|
||||
10
via_test.go
10
via_test.go
@@ -5,7 +5,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/go-via/via/h"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -45,9 +45,7 @@ func TestCustomDatastarContent(t *testing.T) {
|
||||
customScript := []byte("// Custom Datastar Script")
|
||||
v := New()
|
||||
v.Config(Options{
|
||||
Datastar: &DatastarConfig{
|
||||
Content: customScript,
|
||||
},
|
||||
DatastarContent: customScript,
|
||||
})
|
||||
v.Page("/", func(c *Context) {
|
||||
c.View(func() h.H { return h.Div() })
|
||||
@@ -65,9 +63,7 @@ func TestCustomDatastarContent(t *testing.T) {
|
||||
func TestCustomDatastarPath(t *testing.T) {
|
||||
v := New()
|
||||
v.Config(Options{
|
||||
Datastar: &DatastarConfig{
|
||||
Path: "/assets/datastar.js",
|
||||
},
|
||||
DatastarPath: "/assets/datastar.js",
|
||||
})
|
||||
v.Page("/test", func(c *Context) {
|
||||
c.View(func() h.H { return h.Div() })
|
||||
|
||||
Reference in New Issue
Block a user