cleaning up logging, speed up live reload using tailwind watch
This commit is contained in:
parent
f0a38379c3
commit
b610aefa36
20 changed files with 158 additions and 95 deletions
|
|
@ -3,12 +3,13 @@ package main
|
||||||
import (
|
import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getLogLevel() slog.Level {
|
func getLogLevel() slog.Level {
|
||||||
// Get the log level from the environment variable
|
// Get the log level from the environment variable
|
||||||
logLevel := os.Getenv("LOG_LEVEL")
|
logLevel := os.Getenv("LOG_LEVEL")
|
||||||
switch logLevel {
|
switch strings.ToUpper(logLevel) {
|
||||||
case "DEBUG":
|
case "DEBUG":
|
||||||
return slog.LevelDebug
|
return slog.LevelDebug
|
||||||
case "INFO":
|
case "INFO":
|
||||||
|
|
|
||||||
|
|
@ -51,18 +51,21 @@ func main() {
|
||||||
|
|
||||||
taskName := os.Args[1]
|
taskName := os.Args[1]
|
||||||
|
|
||||||
slog.Debug("Running task: %s", taskName)
|
slog.Debug("Running task:", slog.String("task", taskName))
|
||||||
slog.Debug("working dir %s", process.GetWorkingDir())
|
slog.Debug("working dir:", slog.String("dir", process.GetWorkingDir()))
|
||||||
|
|
||||||
if taskName == "watch" {
|
if taskName == "watch" {
|
||||||
os.Setenv("ENV", "development")
|
os.Setenv("ENV", "development")
|
||||||
os.Setenv("WATCH_MODE", "true")
|
os.Setenv("WATCH_MODE", "true")
|
||||||
copyassets.CopyAssets()
|
copyassets.CopyAssets()
|
||||||
astgen.GenAst(true)
|
astgen.GenAst(process.ExitOnError)
|
||||||
css.GenerateCss(true)
|
css.GenerateCss(process.ExitOnError, process.Silent)
|
||||||
run.EntGenerate()
|
run.EntGenerate()
|
||||||
go func() {
|
go func() {
|
||||||
_ = run.Server(true)
|
css.GenerateCssWatch(process.ExitOnError)
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
_ = run.Server(process.ExitOnError)
|
||||||
}()
|
}()
|
||||||
startWatcher(reloader.OnFileChange)
|
startWatcher(reloader.OnFileChange)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -75,18 +78,18 @@ func main() {
|
||||||
}
|
}
|
||||||
if taskName == "generate" {
|
if taskName == "generate" {
|
||||||
run.EntGenerate()
|
run.EntGenerate()
|
||||||
astgen.GenAst(true)
|
astgen.GenAst(process.ExitOnError)
|
||||||
}
|
}
|
||||||
if taskName == "setup" {
|
if taskName == "setup" {
|
||||||
run.Setup()
|
run.Setup()
|
||||||
} else if taskName == "css" {
|
} else if taskName == "css" {
|
||||||
_ = css.GenerateCss(true)
|
_ = css.GenerateCss(process.ExitOnError)
|
||||||
} else if taskName == "ast" {
|
} else if taskName == "ast" {
|
||||||
_ = astgen.GenAst(true)
|
_ = astgen.GenAst(process.ExitOnError)
|
||||||
} else if taskName == "run" {
|
} else if taskName == "run" {
|
||||||
_ = astgen.GenAst(true)
|
_ = astgen.GenAst(process.ExitOnError)
|
||||||
_ = css.GenerateCss(true)
|
_ = css.GenerateCss(process.ExitOnError)
|
||||||
_ = run.Server(true)
|
_ = run.Server(process.ExitOnError)
|
||||||
} else if taskName == "template" {
|
} else if taskName == "template" {
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
fmt.Print("What would you like to call your new app?: ")
|
fmt.Print("What would you like to call your new app?: ")
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"golang.org/x/mod/modfile"
|
"golang.org/x/mod/modfile"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -354,9 +355,9 @@ func GetModuleName() string {
|
||||||
return modName
|
return modName
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenAst(exitOnError bool) error {
|
func GenAst(flags ...process.RunFlag) error {
|
||||||
if GetModuleName() == "" {
|
if GetModuleName() == "" {
|
||||||
if exitOnError {
|
if slices.Contains(flags, process.ExitOnError) {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("error getting module name")
|
return fmt.Errorf("error getting module name")
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"golang.org/x/mod/modfile"
|
"golang.org/x/mod/modfile"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -122,5 +123,5 @@ func CopyAssets() {
|
||||||
log.Fatalf("Error: %v", err)
|
log.Fatalf("Error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("successfully copied assets to %s\n", destDir)
|
slog.Debug("successfully copied assets to %s\n", destDir)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,15 @@ package css
|
||||||
|
|
||||||
import "github.com/maddalax/htmgo/cli/tasks/process"
|
import "github.com/maddalax/htmgo/cli/tasks/process"
|
||||||
|
|
||||||
func GenerateCss(exitOnError bool) error {
|
func GenerateCss(flags ...process.RunFlag) error {
|
||||||
return process.RunMany([]string{
|
return process.RunMany([]string{
|
||||||
"chmod +x ./assets/css/tailwindcss",
|
"chmod +x ./assets/css/tailwindcss",
|
||||||
"./assets/css/tailwindcss -i ./assets/css/input.css -o ./assets/dist/main.css -c ./assets/css/tailwind.config.js",
|
"./assets/css/tailwindcss -i ./assets/css/input.css -o ./assets/dist/main.css -c ./assets/css/tailwind.config.js",
|
||||||
}, exitOnError)
|
}, append(flags, process.Silent)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateCssWatch(flags ...process.RunFlag) error {
|
||||||
|
return process.RunMany([]string{
|
||||||
|
"./assets/css/tailwindcss -i ./assets/css/input.css -o ./assets/dist/main.css -c ./assets/css/tailwind.config.js --watch=always",
|
||||||
|
}, append(flags, process.DontTrack, process.Silent)...)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@ package process
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -17,7 +17,7 @@ var workingDir string
|
||||||
var commands = make([]*exec.Cmd, 0)
|
var commands = make([]*exec.Cmd, 0)
|
||||||
|
|
||||||
func AppendRunning(cmd *exec.Cmd) {
|
func AppendRunning(cmd *exec.Cmd) {
|
||||||
slog.Info("running", slog.String("command", strings.Join(cmd.Args, " ")))
|
slog.Debug("running", slog.String("command", strings.Join(cmd.Args, " ")))
|
||||||
commands = append(commands, cmd)
|
commands = append(commands, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,7 +49,7 @@ func KillAll() {
|
||||||
|
|
||||||
if tries > 50 {
|
if tries > 50 {
|
||||||
args := strings.Join(cmd.Args, " ")
|
args := strings.Join(cmd.Args, " ")
|
||||||
log.Printf("process %v is not running after 50 tries, breaking.\n", args)
|
slog.Debug("process %v is not running after 50 tries, breaking.\n", args)
|
||||||
allFinished = true
|
allFinished = true
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -90,13 +90,13 @@ func KillAll() {
|
||||||
if finished {
|
if finished {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("waiting for all processes to exit\n")
|
slog.Debug("waiting for all processes to exit\n")
|
||||||
time.Sleep(time.Millisecond * 5)
|
time.Sleep(time.Millisecond * 5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
commands = make([]*exec.Cmd, 0)
|
commands = make([]*exec.Cmd, 0)
|
||||||
fmt.Printf("all processes killed\n")
|
slog.Debug("all processes killed\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func PidExists(pid int32) (bool, error) {
|
func PidExists(pid int32) (bool, error) {
|
||||||
|
|
@ -129,14 +129,22 @@ func PidExists(pid int32) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunOrExit(command string) {
|
func RunOrExit(command string) {
|
||||||
_ = Run(command, true)
|
_ = Run(command, ExitOnError)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunMany(commands []string, exitOnError bool) error {
|
type RunFlag int
|
||||||
|
|
||||||
|
const (
|
||||||
|
ExitOnError RunFlag = iota
|
||||||
|
Silent
|
||||||
|
DontTrack
|
||||||
|
)
|
||||||
|
|
||||||
|
func RunMany(commands []string, flags ...RunFlag) error {
|
||||||
for _, command := range commands {
|
for _, command := range commands {
|
||||||
err := Run(command, false)
|
err := Run(command, flags...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if exitOnError {
|
if slices.Contains(flags, ExitOnError) {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
|
@ -145,17 +153,26 @@ func RunMany(commands []string, exitOnError bool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Run(command string, exitOnError bool) error {
|
func Run(command string, flags ...RunFlag) error {
|
||||||
cmd := exec.Command("bash", "-c", command)
|
parts := strings.Fields(command)
|
||||||
|
cmd := exec.Command(parts[0], parts[1:]...)
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
if slices.Contains(flags, Silent) {
|
||||||
|
cmd.Stdout = nil
|
||||||
|
cmd.Stderr = nil
|
||||||
|
} else {
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
}
|
||||||
|
|
||||||
if workingDir != "" {
|
if workingDir != "" {
|
||||||
cmd.Dir = workingDir
|
cmd.Dir = workingDir
|
||||||
}
|
}
|
||||||
|
|
||||||
AppendRunning(cmd)
|
if !slices.Contains(flags, DontTrack) {
|
||||||
|
AppendRunning(cmd)
|
||||||
|
}
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
@ -166,8 +183,10 @@ func Run(command string, exitOnError bool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if exitOnError {
|
if slices.Contains(flags, ExitOnError) {
|
||||||
log.Println(fmt.Sprintf("error: %v", err))
|
slog.Error("Error running command: ",
|
||||||
|
slog.String("error", err.Error()),
|
||||||
|
slog.String("command", command))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,22 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
"github.com/maddalax/htmgo/cli/tasks/astgen"
|
"github.com/maddalax/htmgo/cli/tasks/astgen"
|
||||||
"github.com/maddalax/htmgo/cli/tasks/css"
|
|
||||||
"github.com/maddalax/htmgo/cli/tasks/process"
|
"github.com/maddalax/htmgo/cli/tasks/process"
|
||||||
"github.com/maddalax/htmgo/cli/tasks/run"
|
"github.com/maddalax/htmgo/cli/tasks/run"
|
||||||
|
"github.com/maddalax/htmgo/cli/tasks/util"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Change struct {
|
type Change struct {
|
||||||
name string
|
name string
|
||||||
|
op fsnotify.Op
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewChange(name string) *Change {
|
func NewChange(event *fsnotify.Event) *Change {
|
||||||
return &Change{name: name}
|
return &Change{name: event.Name, op: event.Op}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Change) Name() string {
|
func (c *Change) Name() string {
|
||||||
|
|
@ -46,60 +48,70 @@ func (c *Change) IsGenerated() bool {
|
||||||
return c.HasAnySuffix("generated.go")
|
return c.HasAnySuffix("generated.go")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Change) IsWrite() bool {
|
||||||
|
return c.op == fsnotify.Write
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Change) IsGo() bool {
|
func (c *Change) IsGo() bool {
|
||||||
return c.HasAnySuffix(".go")
|
return c.HasAnySuffix(".go")
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tasks struct {
|
type Tasks struct {
|
||||||
AstGen bool
|
AstGen bool
|
||||||
Css bool
|
|
||||||
Run bool
|
Run bool
|
||||||
Ent bool
|
Ent bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func OnFileChange(events []*fsnotify.Event) {
|
func OnFileChange(events []*fsnotify.Event) {
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
tasks := Tasks{}
|
tasks := Tasks{}
|
||||||
|
|
||||||
for _, event := range events {
|
for _, event := range events {
|
||||||
c := NewChange(event.Name)
|
c := NewChange(event)
|
||||||
|
|
||||||
slog.Debug("file changed", slog.String("file", c.Name()))
|
|
||||||
|
|
||||||
if c.IsGenerated() {
|
if c.IsGenerated() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slog.Debug("file changed", slog.String("file", c.Name()))
|
||||||
|
|
||||||
if c.IsGo() && c.HasAnyPrefix("pages/", "partials/") {
|
if c.IsGo() && c.HasAnyPrefix("pages/", "partials/") {
|
||||||
tasks.AstGen = true
|
tasks.AstGen = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.IsGo() {
|
if c.IsGo() {
|
||||||
tasks.Css = true
|
|
||||||
tasks.Run = true
|
tasks.Run = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.HasAnySuffix("tailwind.config.js", ".css") {
|
if c.HasAnySuffix("tailwind.config.js", ".css") {
|
||||||
tasks.Css = true
|
|
||||||
tasks.Run = true
|
tasks.Run = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.HasAnyPrefix("ent/schema") {
|
if c.HasAnyPrefix("ent/schema") {
|
||||||
tasks.Ent = true
|
tasks.Ent = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slog.Info("file changed", slog.String("file", c.Name()))
|
||||||
}
|
}
|
||||||
|
|
||||||
deps := make([]func() any, 0)
|
deps := make([]func() any, 0)
|
||||||
|
|
||||||
if tasks.AstGen {
|
if tasks.AstGen {
|
||||||
deps = append(deps, func() any {
|
deps = append(deps, func() any {
|
||||||
return astgen.GenAst(false)
|
return util.Trace("generate ast", func() any {
|
||||||
|
astgen.GenAst()
|
||||||
|
return nil
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if tasks.Ent {
|
if tasks.Ent {
|
||||||
deps = append(deps, func() any {
|
deps = append(deps, func() any {
|
||||||
run.EntGenerate()
|
return util.Trace("generate ent", func() any {
|
||||||
return nil
|
run.EntGenerate()
|
||||||
|
return nil
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,14 +131,16 @@ func OnFileChange(events []*fsnotify.Event) {
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
if tasks.Run {
|
if tasks.Run {
|
||||||
process.KillAll()
|
util.Trace("kill all processes", func() any {
|
||||||
}
|
process.KillAll()
|
||||||
|
return nil
|
||||||
if tasks.Css {
|
})
|
||||||
go css.GenerateCss(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if tasks.Run {
|
if tasks.Run {
|
||||||
_ = run.Server(false)
|
go run.Server()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slog.Info("reloaded in", slog.Duration("duration", time.Since(now)))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func Build() {
|
func Build() {
|
||||||
astgen.GenAst(true)
|
astgen.GenAst(process.ExitOnError)
|
||||||
css.GenerateCss(true)
|
css.GenerateCss(process.ExitOnError)
|
||||||
process.RunOrExit("rm -rf ./dist")
|
process.RunOrExit("rm -rf ./dist")
|
||||||
process.RunOrExit("mkdir -p ./dist/assets/dist")
|
process.RunOrExit("mkdir -p ./dist/assets/dist")
|
||||||
process.RunOrExit("cp -r ./assets/dist/* ./dist/assets/dist/")
|
process.RunOrExit("cp -r ./assets/dist/* ./dist/assets/dist/")
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ package run
|
||||||
import "github.com/maddalax/htmgo/cli/tasks/process"
|
import "github.com/maddalax/htmgo/cli/tasks/process"
|
||||||
|
|
||||||
func EntNewSchema(name string) {
|
func EntNewSchema(name string) {
|
||||||
process.RunOrExit("GOWORK=off go run -mod=mod entgo.io/ent/cmd/ent new " + name)
|
process.RunOrExit("bash -c GOWORK=off go run -mod=mod entgo.io/ent/cmd/ent new " + name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func EntGenerate() {
|
func EntGenerate() {
|
||||||
process.RunOrExit("GOWORK=off go generate ./ent")
|
process.RunOrExit("bash -c GOWORK=off go generate ./ent")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,6 @@ package run
|
||||||
|
|
||||||
import "github.com/maddalax/htmgo/cli/tasks/process"
|
import "github.com/maddalax/htmgo/cli/tasks/process"
|
||||||
|
|
||||||
func Server(exitOnError bool) error {
|
func Server(flags ...process.RunFlag) error {
|
||||||
return process.Run("go run .", exitOnError)
|
return process.Run("go run .", flags...)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ func Setup() {
|
||||||
process.RunOrExit("go mod download")
|
process.RunOrExit("go mod download")
|
||||||
process.RunOrExit("go mod tidy")
|
process.RunOrExit("go mod tidy")
|
||||||
copyassets.CopyAssets()
|
copyassets.CopyAssets()
|
||||||
_ = astgen.GenAst(true)
|
_ = astgen.GenAst(process.ExitOnError)
|
||||||
_ = css.GenerateCss(true)
|
_ = css.GenerateCss(process.ExitOnError)
|
||||||
EntGenerate()
|
EntGenerate()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
13
cli/tasks/util/trace.go
Normal file
13
cli/tasks/util/trace.go
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log/slog"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Trace(name string, cb func() any) any {
|
||||||
|
now := time.Now()
|
||||||
|
result := cb()
|
||||||
|
slog.Debug("trace", slog.String("name", name), slog.Duration("duration", time.Since(now)))
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
@ -1,23 +1,23 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
"log"
|
"log"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ignoredDirs = []string{".git", ".idea", "node_modules", "vendor"}
|
var ignoredDirs = []string{".git", ".idea", "node_modules", "vendor"}
|
||||||
|
|
||||||
func startWatcher(cb func(file []*fsnotify.Event)) {
|
func startWatcher(cb func(file []*fsnotify.Event)) {
|
||||||
events := make([]*fsnotify.Event, 0)
|
events := make([]*fsnotify.Event, 0)
|
||||||
|
debouncer := NewDebouncer(100 * time.Millisecond)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
fmt.Println("Recovered from fatal error:", r)
|
slog.Debug("Recovered from fatal error:", slog.String("error", r.(error).Error()))
|
||||||
// You can log the error here or take other corrective actions
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
// Create new watcher.
|
// Create new watcher.
|
||||||
|
|
@ -36,8 +36,10 @@ func startWatcher(cb func(file []*fsnotify.Event)) {
|
||||||
}
|
}
|
||||||
if event.Has(fsnotify.Write) || event.Has(fsnotify.Remove) || event.Has(fsnotify.Rename) {
|
if event.Has(fsnotify.Write) || event.Has(fsnotify.Remove) || event.Has(fsnotify.Rename) {
|
||||||
events = append(events, &event)
|
events = append(events, &event)
|
||||||
go cb(events)
|
debouncer.Do(func() {
|
||||||
events = make([]*fsnotify.Event, 0)
|
cb(events)
|
||||||
|
events = make([]*fsnotify.Event, 0)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
case err, ok := <-watcher.Errors:
|
case err, ok := <-watcher.Errors:
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -64,9 +66,9 @@ func startWatcher(cb func(file []*fsnotify.Event)) {
|
||||||
if info.IsDir() {
|
if info.IsDir() {
|
||||||
err = watcher.Add(path)
|
err = watcher.Add(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error adding directory to watcher:", err)
|
slog.Error("Error adding directory to watcher:", err)
|
||||||
} else {
|
} else {
|
||||||
log.Println("Watching directory:", path)
|
slog.Debug("Watching directory:", slog.String("path", path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ type InputProps struct {
|
||||||
Type string
|
Type string
|
||||||
DefaultValue string
|
DefaultValue string
|
||||||
ValidationPath string
|
ValidationPath string
|
||||||
Childen []h.Renderable
|
Children []h.Renderable
|
||||||
}
|
}
|
||||||
|
|
||||||
func Input(props InputProps) h.Renderable {
|
func Input(props InputProps) h.Renderable {
|
||||||
|
|
@ -27,7 +27,7 @@ func Input(props InputProps) h.Renderable {
|
||||||
h.Class("border p-2 rounded"),
|
h.Class("border p-2 rounded"),
|
||||||
h.If(props.Id != "", h.Id(props.Id)),
|
h.If(props.Id != "", h.Id(props.Id)),
|
||||||
h.If(props.Name != "", h.Name(props.Name)),
|
h.If(props.Name != "", h.Name(props.Name)),
|
||||||
h.If(props.Childen != nil, h.Children(props.Childen...)),
|
h.If(props.Children != nil, h.Children(props.Children...)),
|
||||||
h.If(props.DefaultValue != "", h.Attribute("value", props.DefaultValue)),
|
h.If(props.DefaultValue != "", h.Attribute("value", props.DefaultValue)),
|
||||||
validation,
|
validation,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
2
framework/assets/dist/htmgo.js
vendored
2
framework/assets/dist/htmgo.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -33,14 +33,15 @@ htmx.defineExtension("livereload", {
|
||||||
});
|
});
|
||||||
|
|
||||||
function reload() {
|
function reload() {
|
||||||
fetch(window.location.href).then(response => {
|
window.location.reload()
|
||||||
return response.text();
|
// fetch(window.location.href).then(response => {
|
||||||
}).then(html => {
|
// return response.text();
|
||||||
document.open();
|
// }).then(html => {
|
||||||
document.write(html);
|
// document.open();
|
||||||
document.close();
|
// document.write(html);
|
||||||
}).catch(err => {
|
// document.close();
|
||||||
console.log('failed to fetch live reload', err)
|
// }).catch(err => {
|
||||||
setTimeout(reload, 100)
|
// console.log('failed to fetch live reload', err)
|
||||||
})
|
// setTimeout(reload, 100)
|
||||||
|
// })
|
||||||
}
|
}
|
||||||
|
|
@ -10,16 +10,8 @@ type WsOpts = {
|
||||||
export function createWebSocketClient(opts: WsOpts) {
|
export function createWebSocketClient(opts: WsOpts) {
|
||||||
let socket: WebSocket | null = null;
|
let socket: WebSocket | null = null;
|
||||||
const connect = (tries: number) => {
|
const connect = (tries: number) => {
|
||||||
|
console.log('connecting to ws', opts.url, 'attempt', tries)
|
||||||
if(tries > 50) {
|
|
||||||
console.error('failed to connect to websocket after 50 tries, please reload the page');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
socket = new WebSocket(opts.url);
|
socket = new WebSocket(opts.url);
|
||||||
// Handle connection open
|
|
||||||
socket.onopen = () => {
|
|
||||||
};
|
|
||||||
// Handle incoming messages
|
// Handle incoming messages
|
||||||
socket.onmessage = (event) => {
|
socket.onmessage = (event) => {
|
||||||
opts.onMessage(event.data)
|
opts.onMessage(event.data)
|
||||||
|
|
@ -31,12 +23,14 @@ export function createWebSocketClient(opts: WsOpts) {
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
// noop
|
// noop
|
||||||
}
|
}
|
||||||
let interval = tries * (opts.reconnectInterval || 100);
|
socket = null
|
||||||
|
let interval = tries * (opts.reconnectInterval || 1000);
|
||||||
setTimeout(() => connect(tries + 1), interval);
|
setTimeout(() => connect(tries + 1), interval);
|
||||||
};
|
};
|
||||||
// Handle connection close and attempt reconnection
|
// Handle connection close and attempt reconnection
|
||||||
socket.onclose = () => {
|
socket.onclose = () => {
|
||||||
let interval = tries * (opts.reconnectInterval || 100);
|
socket = null;
|
||||||
|
let interval = tries * (opts.reconnectInterval || 1000);
|
||||||
setTimeout(() => connect(tries + 1), interval);
|
setTimeout(() => connect(tries + 1), interval);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -318,6 +318,10 @@ func NewHeaders(headers ...string) *Headers {
|
||||||
return &m
|
return &m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Checkbox(children ...Renderable) Renderable {
|
||||||
|
return Input("checkbox", children...)
|
||||||
|
}
|
||||||
|
|
||||||
func Input(inputType string, children ...Renderable) Renderable {
|
func Input(inputType string, children ...Renderable) Renderable {
|
||||||
return &Node{
|
return &Node{
|
||||||
tag: "input",
|
tag: "input",
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import "github.com/maddalax/htmgo/framework/h"
|
||||||
|
|
||||||
func RegisterPages(f *echo.Echo) {
|
func RegisterPages(f *echo.Echo) {
|
||||||
f.GET("/", func(ctx echo.Context) error {
|
f.GET("/", func(ctx echo.Context) error {
|
||||||
return h.HtmlView(ctx, IndexPage(ctx))
|
cc := ctx.(*h.RequestContext)
|
||||||
|
return h.HtmlView(ctx, IndexPage(cc))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,18 @@ import "github.com/labstack/echo/v4"
|
||||||
import "starter-template/partials"
|
import "starter-template/partials"
|
||||||
|
|
||||||
func GetPartialFromContext(ctx echo.Context) *h.Partial {
|
func GetPartialFromContext(ctx echo.Context) *h.Partial {
|
||||||
path := ctx.Path()
|
path := ctx.Request().URL.Path
|
||||||
if path == "SamplePartial" || path == "/starter-template/partials.SamplePartial" {
|
if path == "SamplePartial" || path == "/starter-template/partials.SamplePartial" {
|
||||||
return partials.SamplePartial(ctx)
|
cc := ctx.(*h.RequestContext)
|
||||||
|
return partials.SamplePartial(cc)
|
||||||
}
|
}
|
||||||
if path == "NewPartial" || path == "/starter-template/partials.NewPartial" {
|
if path == "NewPartial" || path == "/starter-template/partials.NewPartial" {
|
||||||
return partials.NewPartial(ctx)
|
cc := ctx.(*h.RequestContext)
|
||||||
|
return partials.NewPartial(cc)
|
||||||
}
|
}
|
||||||
if path == "NewPartial2" || path == "/starter-template/partials.NewPartial2" {
|
if path == "NewPartial2" || path == "/starter-template/partials.NewPartial2" {
|
||||||
return partials.NewPartial2(ctx)
|
cc := ctx.(*h.RequestContext)
|
||||||
|
return partials.NewPartial2(cc)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue