From 51b5d57222bf7a237e45131bef57437cb3ded51a Mon Sep 17 00:00:00 2001 From: Prad Nukala Date: Wed, 7 Jan 2026 21:09:24 -0500 Subject: [PATCH] refactor(server): move server command into its own package and executable --- Makefile | 7 +- handlers/routes.go | 176 ------------------------------------------ layouts/base.templ | 46 ++++++----- layouts/base_templ.go | 116 +++++++++++++++++++++++++--- main.go | 18 ----- 5 files changed, 138 insertions(+), 225 deletions(-) delete mode 100644 handlers/routes.go delete mode 100644 main.go diff --git a/Makefile b/Makefile index 9e6bcef..c10487d 100644 --- a/Makefile +++ b/Makefile @@ -4,10 +4,13 @@ all: gen start open gen: @templ generate +build: + @go build -o nebula ./cmd/server + start: - @go run main.go + @go run ./cmd/server open: @open http://localhost:8080 -.PHONY: gen start +.PHONY: gen build start open all diff --git a/handlers/routes.go b/handlers/routes.go deleted file mode 100644 index 68b7f75..0000000 --- a/handlers/routes.go +++ /dev/null @@ -1,176 +0,0 @@ -package handlers - -import ( - "net/http" - "strconv" - - "nebula/models" - "nebula/views" -) - -func RegisterRoutes(mux *http.ServeMux) { - mux.HandleFunc("GET /", handleWelcome) - mux.HandleFunc("GET /welcome", handleWelcome) - mux.HandleFunc("GET /welcome/step/{step}", handleWelcomeStep) - - mux.HandleFunc("GET /register", handleRegister) - mux.HandleFunc("GET /register/step/{step}", handleRegisterStep) - mux.HandleFunc("GET /register/capabilities", handleRegisterCapabilities) - mux.HandleFunc("POST /register/verify-code", handleRegisterVerifyCode) - - mux.HandleFunc("GET /login", handleLogin) - mux.HandleFunc("GET /login/step/{step}", handleLoginStep) - mux.HandleFunc("GET /login/qr-status", handleLoginQRStatus) - - mux.HandleFunc("GET /authorize", handleAuthorize) - mux.HandleFunc("POST /authorize/approve", handleAuthorizeApprove) - mux.HandleFunc("POST /authorize/deny", handleAuthorizeDeny) - - mux.HandleFunc("GET /dashboard", handleDashboard) - - mux.HandleFunc("GET /settings", handleSettings) -} - -// handleWelcome renders the full welcome page at step 1 -func handleWelcome(w http.ResponseWriter, r *http.Request) { - views.WelcomePage(1).Render(r.Context(), w) -} - -// handleWelcomeStep handles HTMX partial updates for step navigation -func handleWelcomeStep(w http.ResponseWriter, r *http.Request) { - stepStr := r.PathValue("step") - step, err := strconv.Atoi(stepStr) - if err != nil || step < 1 || step > 3 { - step = 1 - } - - // Check if this is an HTMX request - if r.Header.Get("HX-Request") == "true" { - // Return step content with OOB stepper update (HTMX 4 pattern) - views.WelcomeStepWithStepper(step).Render(r.Context(), w) - return - } - - views.WelcomePage(step).Render(r.Context(), w) -} - -func handleRegister(w http.ResponseWriter, r *http.Request) { - state := models.RegisterState{Step: 1} - views.RegisterPage(state).Render(r.Context(), w) -} - -func handleRegisterStep(w http.ResponseWriter, r *http.Request) { - stepStr := r.PathValue("step") - step, err := strconv.Atoi(stepStr) - if err != nil || step < 1 || step > 3 { - step = 1 - } - - method := r.URL.Query().Get("method") - if method == "" { - method = "passkey" - } - - state := models.RegisterState{Step: step, Method: method} - - if r.Header.Get("HX-Request") == "true" { - views.RegisterStepWithStepper(state).Render(r.Context(), w) - return - } - - views.RegisterPage(state).Render(r.Context(), w) -} - -func handleRegisterCapabilities(w http.ResponseWriter, r *http.Request) { - caps := models.DeviceCapabilities{ - Platform: true, - CrossPlatform: true, - Conditional: true, - } - views.CapabilitiesResult(caps).Render(r.Context(), w) -} - -func handleRegisterVerifyCode(w http.ResponseWriter, r *http.Request) { - state := models.RegisterState{Step: 3} - if r.Header.Get("HX-Request") == "true" { - views.RegisterStepWithStepper(state).Render(r.Context(), w) - return - } - views.RegisterPage(state).Render(r.Context(), w) -} - -func handleLogin(w http.ResponseWriter, r *http.Request) { - state := models.LoginState{Step: "1"} - views.LoginPage(state).Render(r.Context(), w) -} - -func handleLoginStep(w http.ResponseWriter, r *http.Request) { - step := r.PathValue("step") - if step == "" { - step = "1" - } - - state := models.LoginState{Step: step} - - if r.Header.Get("HX-Request") == "true" { - views.LoginStepWithOOB(state).Render(r.Context(), w) - return - } - - views.LoginPage(state).Render(r.Context(), w) -} - -var qrPollCount = 0 - -func handleLoginQRStatus(w http.ResponseWriter, r *http.Request) { - qrPollCount++ - if qrPollCount >= 3 { - qrPollCount = 0 - views.QRStatusSuccess().Render(r.Context(), w) - return - } - views.QRStatusWaiting().Render(r.Context(), w) -} - -func handleAuthorize(w http.ResponseWriter, r *http.Request) { - reqType := r.URL.Query().Get("type") - req := models.DefaultAuthRequest(reqType) - views.AuthorizePage(req).Render(r.Context(), w) -} - -func handleAuthorizeApprove(w http.ResponseWriter, r *http.Request) { - r.ParseForm() - actionType := r.FormValue("type") - if actionType == "" { - actionType = "connect" - } - views.AuthResultSuccess(actionType).Render(r.Context(), w) -} - -func handleAuthorizeDeny(w http.ResponseWriter, r *http.Request) { - views.AuthResultDenied().Render(r.Context(), w) -} - -func handleDashboard(w http.ResponseWriter, r *http.Request) { - tab := r.URL.Query().Get("tab") - if tab == "" { - tab = "overview" - } - data := models.DefaultDashboardData() - - if r.Header.Get("HX-Request") == "true" { - views.DashboardContent(data, tab).Render(r.Context(), w) - return - } - - views.DashboardPage(data, tab).Render(r.Context(), w) -} - -func handleSettings(w http.ResponseWriter, r *http.Request) { - tab := r.URL.Query().Get("tab") - if tab == "" { - tab = "profile" - } - data := models.DefaultSettingsData() - views.SettingsPage(data, tab).Render(r.Context(), w) -} diff --git a/layouts/base.templ b/layouts/base.templ index b72db92..439febb 100644 --- a/layouts/base.templ +++ b/layouts/base.templ @@ -1,36 +1,44 @@ package layouts -// Base provides the HTML document structure for all pages +import "nebula/pkg/config" + templ Base(title string) { - + - { title } - Sonr Motr Wallet + + { title } - { config.FromContext(ctx).AppTitle } - + if config.FromContext(ctx).Preload { + + } - + @baseStyles() { children... } } + +templ baseStyles() { + +} diff --git a/layouts/base_templ.go b/layouts/base_templ.go index 39f25d5..20115e0 100644 --- a/layouts/base_templ.go +++ b/layouts/base_templ.go @@ -8,7 +8,8 @@ package layouts import "github.com/a-h/templ" import templruntime "github.com/a-h/templ/runtime" -// Base provides the HTML document structure for all pages +import "nebula" + func Base(title string) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context @@ -30,20 +31,86 @@ func Base(title string) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var2 string - templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `layouts/base.templ`, Line: 11, Col: 17} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) + var templ_7745c5c3_Var2 = []any{"wa-cloak", nebula.ConfigFromContext(ctx).ThemeClass()} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " - Sonr Motr Wallet") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var5 string + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(title) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `layouts/base.templ`, Line: 13, Col: 17} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, " - ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var6 string + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(nebula.ConfigFromContext(ctx).AppTitle) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `layouts/base.templ`, Line: 13, Col: 62} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if nebula.ConfigFromContext(ctx).Preload { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = baseStyles().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -51,7 +118,36 @@ func Base(title string) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) +} + +func baseStyles() templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var7 := templ.GetChildren(ctx) + if templ_7745c5c3_Var7 == nil { + templ_7745c5c3_Var7 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/main.go b/main.go deleted file mode 100644 index 9418173..0000000 --- a/main.go +++ /dev/null @@ -1,18 +0,0 @@ -package main - -import ( - "fmt" - "log" - "net/http" - - "nebula/handlers" -) - -func main() { - mux := http.NewServeMux() - handlers.RegisterRoutes(mux) - - addr := ":8080" - fmt.Printf("Starting server at http://localhost%s\n", addr) - log.Fatal(http.ListenAndServe(addr, mux)) -}