From 27dc7818f7f087822cd4728b818f2d3f7e02ac6d Mon Sep 17 00:00:00 2001 From: wisplite Date: Tue, 7 Apr 2026 12:01:42 -0500 Subject: [PATCH] basic websocket handling and testing --- engine.go | 10 ++++++++++ example/client/test.ts | 17 +++++++++++++++++ example/main.go | 23 +++++++++++++++++++++++ reactivity/websocket.go | 27 +++++++++++++++++++++++++++ 4 files changed, 77 insertions(+) create mode 100644 example/client/test.ts diff --git a/engine.go b/engine.go index 9acec39..a385052 100644 --- a/engine.go +++ b/engine.go @@ -2,6 +2,7 @@ package tether import ( "log/slog" + "net/http" "github.com/wisplite/tether/reactivity" "gorm.io/gorm" @@ -28,3 +29,12 @@ func (e *Engine) RegisterQuery(name string, query func(ctx *QueryCtx) error) { e.queries[name] = query slog.Debug("Registered query", "name", name) } + +func (e *Engine) CreateTable(name string, schema interface{}) { + e.db.AutoMigrate(schema) + slog.Debug("Created table", "name", name) +} + +func (e *Engine) Handle(w http.ResponseWriter, r *http.Request) { + reactivity.Handle(w, r) +} diff --git a/example/client/test.ts b/example/client/test.ts new file mode 100644 index 0000000..a18c30f --- /dev/null +++ b/example/client/test.ts @@ -0,0 +1,17 @@ +function test() { + const ws = new WebSocket("ws://localhost:8080/tether"); + ws.onmessage = (event) => { + console.log(event.data); + }; + ws.onopen = () => { + console.log("Connected to server"); + ws.send(JSON.stringify({ + type: "subscribe", + channel: "messages", + })); + }; + ws.onclose = () => { + console.log("Disconnected from server"); + }; +} +test(); \ No newline at end of file diff --git a/example/main.go b/example/main.go index 1ba22f0..4824d02 100644 --- a/example/main.go +++ b/example/main.go @@ -1,11 +1,28 @@ package main import ( + "time" + + "net/http" + "github.com/glebarez/sqlite" "github.com/wisplite/tether" "gorm.io/gorm" ) +type User struct { + ID string `gorm:"primaryKey"` + Name string +} + +type Messages struct { + ID string `gorm:"primaryKey"` + Message string + SenderID string + ReceiverID string + CreatedAt time.Time +} + func main() { db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{}) if err != nil { @@ -14,6 +31,9 @@ func main() { engine := tether.NewEngine(db) + engine.CreateTable("users", &User{}) + engine.CreateTable("messages", &Messages{}) + engine.RegisterMutation("createUser", func(ctx *tether.MutationCtx) error { return nil }) @@ -21,4 +41,7 @@ func main() { engine.RegisterQuery("getUser", func(ctx *tether.QueryCtx) error { return nil }) + + http.HandleFunc("/tether", engine.Handle) + http.ListenAndServe(":8080", nil) } diff --git a/reactivity/websocket.go b/reactivity/websocket.go index 4d7eb49..178357d 100644 --- a/reactivity/websocket.go +++ b/reactivity/websocket.go @@ -1 +1,28 @@ package reactivity + +import ( + "log/slog" + "net/http" + + "github.com/gorilla/websocket" +) + +var upgrader = websocket.Upgrader{} + +func Handle(w http.ResponseWriter, r *http.Request) { + ws, err := upgrader.Upgrade(w, r, nil) + if err != nil { + slog.Error("Failed to upgrade to websocket", "error", err) + return + } + defer ws.Close() + + for { + _, message, err := ws.ReadMessage() + if err != nil { + slog.Error("Failed to read message", "error", err) + return + } + slog.Debug("Received message", "message", string(message)) + } +}