add ent for sql
some improvements on killing the running process on reboot
This commit is contained in:
parent
45d8e58faa
commit
16cdb66e0d
17 changed files with 226 additions and 19 deletions
24
cli/logger.go
Normal file
24
cli/logger.go
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
)
|
||||
|
||||
func getLogLevel() slog.Level {
|
||||
// Get the log level from the environment variable
|
||||
logLevel := os.Getenv("LOG_LEVEL")
|
||||
switch logLevel {
|
||||
case "DEBUG":
|
||||
return slog.LevelDebug
|
||||
case "INFO":
|
||||
return slog.LevelInfo
|
||||
case "WARN":
|
||||
return slog.LevelWarn
|
||||
case "ERROR":
|
||||
return slog.LevelError
|
||||
default:
|
||||
// Default to INFO if no valid log level is set
|
||||
return slog.LevelInfo
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,10 @@ import (
|
|||
"github.com/maddalax/htmgo/cli/tasks/astgen"
|
||||
"github.com/maddalax/htmgo/cli/tasks/css"
|
||||
"github.com/maddalax/htmgo/cli/tasks/downloadtemplate"
|
||||
"github.com/maddalax/htmgo/cli/tasks/process"
|
||||
"github.com/maddalax/htmgo/cli/tasks/reloader"
|
||||
"github.com/maddalax/htmgo/cli/tasks/run"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
|
@ -17,7 +19,7 @@ func main() {
|
|||
done := RegisterSignals()
|
||||
|
||||
commandMap := make(map[string]*flag.FlagSet)
|
||||
commands := []string{"template", "run", "watch", "build", "setup", "css"}
|
||||
commands := []string{"template", "run", "watch", "build", "setup", "css", "schema"}
|
||||
|
||||
for _, command := range commands {
|
||||
commandMap[command] = flag.NewFlagSet(command, flag.ExitOnError)
|
||||
|
|
@ -44,16 +46,35 @@ func main() {
|
|||
return
|
||||
}
|
||||
|
||||
slog.SetLogLoggerLevel(getLogLevel())
|
||||
|
||||
taskName := os.Args[1]
|
||||
|
||||
slog.Debug("Running task: %s", taskName)
|
||||
slog.Debug("working dir %s", process.GetWorkingDir())
|
||||
|
||||
if taskName == "watch" {
|
||||
os.Setenv("ENV", "development")
|
||||
os.Setenv("WATCH_MODE", "true")
|
||||
astgen.GenAst(true)
|
||||
css.GenerateCss(true)
|
||||
run.EntGenerate()
|
||||
go func() {
|
||||
_ = run.Server(true)
|
||||
}()
|
||||
startWatcher(reloader.OnFileChange)
|
||||
} else {
|
||||
if taskName == "schema" {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
fmt.Print("Enter entity name:")
|
||||
text, _ := reader.ReadString('\n')
|
||||
text = strings.TrimSuffix(text, "\n")
|
||||
run.EntNewSchema(text)
|
||||
}
|
||||
if taskName == "generate" {
|
||||
run.EntGenerate()
|
||||
astgen.GenAst(true)
|
||||
}
|
||||
if taskName == "setup" {
|
||||
run.Setup()
|
||||
} else if taskName == "css" {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
|
@ -16,6 +17,7 @@ var workingDir string
|
|||
var commands = make([]*exec.Cmd, 0)
|
||||
|
||||
func AppendRunning(cmd *exec.Cmd) {
|
||||
slog.Info("running", slog.String("command", strings.Join(cmd.Args, " ")))
|
||||
commands = append(commands, cmd)
|
||||
}
|
||||
|
||||
|
|
@ -154,15 +156,18 @@ func Run(command string, exitOnError bool) error {
|
|||
|
||||
AppendRunning(cmd)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "signal: killed") {
|
||||
return nil
|
||||
}
|
||||
if exitOnError {
|
||||
log.Println(fmt.Sprintf("error: %v", err))
|
||||
os.Exit(1)
|
||||
}
|
||||
return err
|
||||
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
|
||||
if exitOnError {
|
||||
log.Println(fmt.Sprintf("error: %v", err))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if strings.Contains(err.Error(), "signal: killed") {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/maddalax/htmgo/cli/tasks/css"
|
||||
"github.com/maddalax/htmgo/cli/tasks/process"
|
||||
"github.com/maddalax/htmgo/cli/tasks/run"
|
||||
"log/slog"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
|
@ -53,6 +54,7 @@ type Tasks struct {
|
|||
AstGen bool
|
||||
Css bool
|
||||
Run bool
|
||||
Ent bool
|
||||
}
|
||||
|
||||
func OnFileChange(events []*fsnotify.Event) {
|
||||
|
|
@ -61,6 +63,8 @@ func OnFileChange(events []*fsnotify.Event) {
|
|||
for _, event := range events {
|
||||
c := NewChange(event.Name)
|
||||
|
||||
slog.Debug("file changed", slog.String("file", c.Name()))
|
||||
|
||||
if c.IsGenerated() {
|
||||
continue
|
||||
}
|
||||
|
|
@ -77,6 +81,10 @@ func OnFileChange(events []*fsnotify.Event) {
|
|||
if c.HasAnySuffix("tailwind.config.js", ".css") {
|
||||
tasks.Css = true
|
||||
}
|
||||
|
||||
if c.HasAnyPrefix("ent/schema") {
|
||||
tasks.Ent = true
|
||||
}
|
||||
}
|
||||
|
||||
deps := make([]func() any, 0)
|
||||
|
|
@ -93,6 +101,13 @@ func OnFileChange(events []*fsnotify.Event) {
|
|||
})
|
||||
}
|
||||
|
||||
if tasks.Ent {
|
||||
deps = append(deps, func() any {
|
||||
run.EntGenerate()
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
|
||||
for _, dep := range deps {
|
||||
|
|
|
|||
11
cli/tasks/run/entschema.go
Normal file
11
cli/tasks/run/entschema.go
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package run
|
||||
|
||||
import "github.com/maddalax/htmgo/cli/tasks/process"
|
||||
|
||||
func EntNewSchema(name string) {
|
||||
process.RunOrExit("GOWORK=off go run -mod=mod entgo.io/ent/cmd/ent new " + name)
|
||||
}
|
||||
|
||||
func EntGenerate() {
|
||||
process.RunOrExit("GOWORK=off go generate ./ent")
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"log"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
|
@ -11,7 +12,6 @@ import (
|
|||
var ignoredDirs = []string{".git", ".idea", "node_modules", "vendor"}
|
||||
|
||||
func startWatcher(cb func(file []*fsnotify.Event)) {
|
||||
//debouncer := NewDebouncer(time.Millisecond * 100)
|
||||
events := make([]*fsnotify.Event, 0)
|
||||
|
||||
defer func() {
|
||||
|
|
@ -43,7 +43,7 @@ func startWatcher(cb func(file []*fsnotify.Event)) {
|
|||
if !ok {
|
||||
return
|
||||
}
|
||||
log.Println("error:", err)
|
||||
slog.Error("error:", err.Error())
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package ui
|
||||
|
||||
import "github.com/maddalax/htmgo/framework/h"
|
||||
import (
|
||||
"github.com/maddalax/htmgo/framework/h"
|
||||
)
|
||||
|
||||
type InputProps struct {
|
||||
Id string
|
||||
|
|
@ -13,7 +15,6 @@ type InputProps struct {
|
|||
}
|
||||
|
||||
func Input(props InputProps) h.Renderable {
|
||||
|
||||
validation := h.If(props.ValidationPath != "", h.Children(
|
||||
h.Post(props.ValidationPath),
|
||||
h.Trigger("change"),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
package h
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/maddalax/htmgo/framework/util/process"
|
||||
"log/slog"
|
||||
"time"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
|
|
@ -31,10 +35,23 @@ func (a App) start(app *fiber.App) {
|
|||
AddLiveReloadHandler("/livereload", a.Fiber)
|
||||
}
|
||||
|
||||
err := a.Fiber.Listen(":3000")
|
||||
port := ":3000"
|
||||
err := a.Fiber.Listen(port)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
// If we are in watch mode, just try to kill any processes holding that port
|
||||
// and try again
|
||||
if IsDevelopment() && IsWatchMode() {
|
||||
slog.Info("Port already in use, trying to kill the process and start again")
|
||||
process.RunOrExit(fmt.Sprintf("kill -9 $(lsof -t -i%s)", port))
|
||||
time.Sleep(time.Millisecond * 50)
|
||||
err = a.Fiber.Listen(port)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
15
framework/h/env.go
Normal file
15
framework/h/env.go
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
package h
|
||||
|
||||
import "os"
|
||||
|
||||
func IsWatchMode() bool {
|
||||
return os.Getenv("WATCH_MODE") == "true"
|
||||
}
|
||||
|
||||
func IsDevelopment() bool {
|
||||
return os.Getenv("ENV") == "development"
|
||||
}
|
||||
|
||||
func IsProduction() bool {
|
||||
return os.Getenv("ENV") == "production"
|
||||
}
|
||||
18
framework/util/process/process.go
Normal file
18
framework/util/process/process.go
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package process
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
func RunOrExit(command string) {
|
||||
cmd := exec.Command("bash", "-c", command)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
slog.Error("Error running command: ", slog.String("command", command))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
2
notes.md
Normal file
2
notes.md
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
structured logging - https://go.dev/blog/slog
|
||||
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo=
|
||||
github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
|
|
@ -17,6 +19,7 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
|||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
|
|
|
|||
3
setup.md
3
setup.md
|
|
@ -1,2 +1 @@
|
|||
go install github.com/maddalax/htmgo/framework/tooling/htmgo@latest
|
||||
go run htmgo -task template
|
||||
go run github.com/maddalax/cli/htmgo@latest template
|
||||
3
starter-template/ent/generate.go
Normal file
3
starter-template/ent/generate.go
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
package ent
|
||||
|
||||
//go:generate go run -mod=mod entgo.io/ent/cmd/ent generate ./schema
|
||||
42
starter-template/ent/schema/user.go
Normal file
42
starter-template/ent/schema/user.go
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
package schema
|
||||
|
||||
import (
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect/entsql"
|
||||
"entgo.io/ent/schema/field"
|
||||
"time"
|
||||
)
|
||||
|
||||
// User holds the schema definition for the User entity.
|
||||
type User struct {
|
||||
ent.Schema
|
||||
}
|
||||
|
||||
// Fields of the User.
|
||||
func (User) Fields() []ent.Field {
|
||||
return []ent.Field{
|
||||
field.Int("age").
|
||||
Positive(),
|
||||
field.String("name").
|
||||
Default("unknown"),
|
||||
field.String("occupation").Optional(),
|
||||
field.String("email").Optional(),
|
||||
field.String("password").Sensitive().Optional(),
|
||||
field.String("test").Optional(),
|
||||
field.String("test2").Optional(),
|
||||
field.String("test4").Optional(),
|
||||
field.Time("created_at").
|
||||
Default(time.Now).Annotations(
|
||||
entsql.Default("CURRENT_TIMESTAMP"),
|
||||
),
|
||||
field.Time("updated_at").
|
||||
Default(time.Now).Annotations(
|
||||
entsql.Default("CURRENT_TIMESTAMP"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// Edges of the User.
|
||||
func (User) Edges() []ent.Edge {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -3,20 +3,38 @@ module starter-template
|
|||
go 1.23.0
|
||||
|
||||
require (
|
||||
entgo.io/ent v0.14.1
|
||||
github.com/gofiber/fiber/v2 v2.52.5
|
||||
github.com/maddalax/htmgo/framework v0.0.0-20240916224719-9e5d8edada65
|
||||
)
|
||||
|
||||
require (
|
||||
ariga.io/atlas v0.19.1-0.20240203083654-5948b60a8e43 // indirect
|
||||
github.com/agext/levenshtein v1.2.1 // indirect
|
||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
||||
github.com/go-openapi/inflect v0.19.0 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.13.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/klauspost/compress v1.17.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.16 // indirect
|
||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/spf13/cobra v1.7.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.51.0 // indirect
|
||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||
github.com/zclconf/go-cty v1.8.0 // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/maddalax/htmgo/framework/h"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"log"
|
||||
"starter-template/ent"
|
||||
"starter-template/pages"
|
||||
"starter-template/partials/load"
|
||||
"time"
|
||||
|
|
@ -30,6 +33,16 @@ func main() {
|
|||
load.RegisterPartials(f)
|
||||
pages.RegisterPages(f)
|
||||
|
||||
client, err := ent.Open("sqlite3", "file:ent.db?cache=shared&_fk=1")
|
||||
if err != nil {
|
||||
log.Fatalf("failed opening connection to sqlite: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
// Run the auto migration tool.
|
||||
if err := client.Schema.Create(context.Background()); err != nil {
|
||||
log.Fatalf("failed schema resources: %v", err)
|
||||
}
|
||||
|
||||
h.Start(f, h.App{
|
||||
LiveReload: true,
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue