htmgo/cli/htmgo/tasks/reloader/reloader.go
2024-09-20 11:45:23 -05:00

150 lines
2.4 KiB
Go

package reloader
import (
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/maddalax/htmgo/cli/tasks/astgen"
"github.com/maddalax/htmgo/cli/tasks/process"
"github.com/maddalax/htmgo/cli/tasks/run"
"github.com/maddalax/htmgo/cli/tasks/util"
"log/slog"
"strings"
"sync"
"time"
)
type Change struct {
name string
op fsnotify.Op
}
func NewChange(event *fsnotify.Event) *Change {
return &Change{name: event.Name, op: event.Op}
}
func (c *Change) Name() string {
return c.name
}
func (c *Change) HasAnyPrefix(prefix ...string) bool {
for _, s := range prefix {
if strings.HasPrefix(c.name, s) {
return true
}
}
return false
}
func (c *Change) HasAnySuffix(suffix ...string) bool {
for _, s := range suffix {
if strings.HasSuffix(c.name, s) {
return true
}
}
return false
}
func (c *Change) IsGenerated() bool {
return c.HasAnySuffix("generated.go")
}
func (c *Change) IsWrite() bool {
return c.op == fsnotify.Write
}
func (c *Change) IsGo() bool {
return c.HasAnySuffix(".go")
}
type Tasks struct {
AstGen bool
Run bool
Ent bool
}
func OnFileChange(events []*fsnotify.Event) {
now := time.Now()
tasks := Tasks{}
for _, event := range events {
c := NewChange(event)
if c.IsGenerated() {
continue
}
slog.Debug("file changed", slog.String("file", c.Name()))
if c.IsGo() && c.HasAnyPrefix("pages/", "partials/") {
tasks.AstGen = true
}
if c.IsGo() {
tasks.Run = true
}
if c.HasAnySuffix(".md") {
tasks.Run = true
}
if c.HasAnySuffix("tailwind.config.js", ".css") {
tasks.Run = true
}
if c.HasAnyPrefix("ent/schema") {
tasks.Ent = true
}
slog.Info("file changed", slog.String("file", c.Name()))
}
deps := make([]func() any, 0)
if tasks.AstGen {
deps = append(deps, func() any {
return util.Trace("generate ast", func() any {
astgen.GenAst()
return nil
})
})
}
if tasks.Ent {
deps = append(deps, func() any {
return util.Trace("generate ent", func() any {
run.EntGenerate()
return nil
})
})
}
wg := sync.WaitGroup{}
for _, dep := range deps {
wg.Add(1)
go func(dep func() any) {
defer wg.Done()
err := dep()
if err != nil {
fmt.Println(err)
}
}(dep)
}
wg.Wait()
if tasks.Run {
util.Trace("kill all processes", func() any {
process.KillAll(process.KillOnlyOnExit)
return nil
})
}
if tasks.Run {
go run.Server()
}
slog.Info("reloaded in", slog.Duration("duration", time.Since(now)))
}