+52
-4
cmd/main.go
+52
-4
cmd/main.go
···
1
1
package main
2
2
3
3
import (
4
+
"context"
4
5
"log"
5
-
"log/slog"
6
6
"os"
7
7
8
+
_ "github.com/joho/godotenv/autoload"
9
+
"github.com/urfave/cli/v3"
8
10
"tangled.org/dane.is.extraordinarily.cool/pallet/internal/app"
9
11
"tangled.org/dane.is.extraordinarily.cool/pallet/internal/db"
12
+
"tangled.org/dane.is.extraordinarily.cool/pallet/internal/logger"
10
13
)
14
+
11
15
12
16
func main() {
13
-
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
17
+
if err := run(os.Args); err != nil {
18
+
log.Fatal(err)
19
+
os.Exit(-1)
20
+
}
21
+
}
22
+
23
+
func run(args []string) error {
24
+
app := &cli.Command{
25
+
Name: "pallet",
26
+
Usage: "pallet app server",
27
+
}
28
+
29
+
app.Flags = []cli.Flag{
30
+
&cli.StringFlag{
31
+
Name: "log-level",
32
+
Usage: "log verbosity level (eg: warn, info, debug)",
33
+
Sources: cli.EnvVars("GO_LOG_LEVEL", "LOG_LEVEL"),
34
+
},
35
+
}
36
+
37
+
app.Commands = []*cli.Command{
38
+
&cli.Command{
39
+
Name: "start",
40
+
Usage: "start the pallet app server",
41
+
Action: runServer,
42
+
Flags: []cli.Flag{
43
+
&cli.StringFlag{
44
+
Name: "port",
45
+
Usage: "Port to bind the HTTP server to",
46
+
Value: ":8080",
47
+
Sources: cli.EnvVars("SERVER_PORT"),
48
+
},
49
+
},
50
+
},
51
+
}
52
+
53
+
54
+
return app.Run(context.Background(), args)
55
+
}
56
+
57
+
func runServer(ctx context.Context, cmd *cli.Command) error {
58
+
logger := logger.NewLogger(cmd.String("log-level"), os.Stdout)
14
59
db, err := db.NewSQLiteDB()
15
60
if err != nil {
16
61
log.Fatal(err)
17
62
}
18
-
// remove hardcoded port, use env var
19
-
server := app.NewServer(":8080", db, logger)
63
+
logger.Info("database created")
64
+
65
+
server := app.NewServer(cmd.String("SERVER_PORT"), db, logger)
20
66
21
67
if err := server.Start(); err != nil {
22
68
log.Fatal(err)
23
69
}
70
+
71
+
return nil
24
72
}
+5
-2
go.mod
+5
-2
go.mod
···
3
3
go 1.23.4
4
4
5
5
require (
6
-
github.com/gorilla/mux v1.8.1 // indirect
7
-
github.com/mattn/go-sqlite3 v1.14.32 // indirect
6
+
github.com/gorilla/mux v1.8.1
7
+
github.com/mattn/go-sqlite3 v1.14.32
8
+
github.com/urfave/cli/v3 v3.6.1
8
9
)
10
+
11
+
require github.com/joho/godotenv v1.5.1 // indirect
+12
go.sum
+12
go.sum
···
1
+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2
+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1
3
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
2
4
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
5
+
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
6
+
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
3
7
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
4
8
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
9
+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
10
+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
11
+
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
12
+
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
13
+
github.com/urfave/cli/v3 v3.6.1 h1:j8Qq8NyUawj/7rTYdBGrxcH7A/j7/G8Q5LhWEW4G3Mo=
14
+
github.com/urfave/cli/v3 v3.6.1/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
15
+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
16
+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+10
-2
internal/app/app.go
+10
-2
internal/app/app.go
···
4
4
"database/sql"
5
5
"log/slog"
6
6
"net/http"
7
+
"time"
7
8
8
9
"github.com/gorilla/mux"
9
10
)
···
24
25
25
26
func (s *Server) Start() error {
26
27
router := mux.NewRouter()
27
-
28
+
server := &http.Server{
29
+
Addr: s.addr,
30
+
WriteTimeout: 5 * time.Second,
31
+
ReadTimeout: 10 * time.Second,
32
+
IdleTimeout: 30 * time.Second,
33
+
Handler: router,
34
+
}
35
+
28
36
s.logger.Info("app server started")
29
-
return http.ListenAndServe(s.addr, router)
37
+
return server.ListenAndServe()
30
38
}
+1
-1
internal/db/db.go
+1
-1
internal/db/db.go
+30
internal/logger/logger.go
+30
internal/logger/logger.go
···
1
+
package logger
2
+
3
+
import (
4
+
"io"
5
+
"log/slog"
6
+
)
7
+
8
+
func NewLogger(level string, writer io.Writer) *slog.Logger {
9
+
var logLevel slog.Level
10
+
11
+
switch level {
12
+
case "error":
13
+
logLevel = slog.LevelError
14
+
case "warn":
15
+
logLevel = slog.LevelWarn
16
+
case "info":
17
+
logLevel = slog.LevelInfo
18
+
case "debug":
19
+
logLevel = slog.LevelDebug
20
+
default:
21
+
logLevel = slog.LevelInfo
22
+
}
23
+
24
+
logger := slog.New(slog.NewJSONHandler(writer, &slog.HandlerOptions{
25
+
Level: logLevel,
26
+
}))
27
+
28
+
slog.SetDefault(logger)
29
+
return logger
30
+
}