notatest/server/main.go
ae 62b1a58e56
feat!: trimming & logic/schema improvements
- build: somewhat polished dockerization setup
- build: io/fs migrations with `golang-migrate`
- feat: automatic init. admin account creation (.env creds)
- feat(routers): combined user & token routers into single auth router
- feat(routers): improved route layouts (`Routes`)
- feat(middlewares): removed redundant `userCtx` middleware
- fix(schema): note <-> note_versions relation (versioning)
- feat(queries): removed redundant rollback functionality
- feat(queries): combined duplicate version check & insertion/creation
- tests: decreased redundancy by removing 'unnecessary' unit tests
- refactor: hid internal packages behind `server/internal`
- docs: notes & auth handler comments
2025-04-09 01:58:38 +03:00

93 lines
2.5 KiB
Go

package main
import (
"context"
"embed"
"fmt"
"os"
"git.umbrella.haus/ae/notatest/internal/data"
"git.umbrella.haus/ae/notatest/internal/service"
"github.com/caarlos0/env/v10"
"github.com/golang-migrate/migrate/v4"
_ "github.com/golang-migrate/migrate/v4/database/postgres"
"github.com/golang-migrate/migrate/v4/source/iofs"
"github.com/jackc/pgx/v5"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
//go:embed sql/migrations/*.sql
var migrationsFS embed.FS
var (
config Config
)
type Config struct {
JWTSecret string `env:"JWT_SECRET,notEmpty"`
DatabaseURL string `env:"DB_URL,notEmpty"`
LogLevel string `env:"LOG_LEVEL" envDefault:"info"`
AdminUsername string `env:"ADMIN_USERNAME,notEmpty,unset"`
AdminPassword string `env:"ADMIN_PASSWORD,notEmpty,unset"`
}
func init() {
config = Config{}
if err := env.Parse(&config); err != nil {
log.Fatal().Err(err).Msg("Failed to parse environment variables")
}
initLogger()
log.Debug().Msg("Initialization completed")
}
func main() {
log.Debug().Msgf("Database URL: %s", config.DatabaseURL)
conn, err := pgx.Connect(context.Background(), config.DatabaseURL)
if err != nil {
log.Fatal().Err(err).Msg("Failed to connect to database")
}
log.Info().Msg("Successfully connected to the database")
log.Info().Msg("Applying migrations...")
d, err := iofs.New(migrationsFS, "sql/migrations")
if err != nil {
log.Fatal().Err(err).Msg("Failed constructing io/fs driver")
}
migrator, err := migrate.NewWithSourceInstance("iofs", d, config.DatabaseURL)
if err != nil {
log.Fatal().Err(err).Msg("Failed to apply migrations")
}
defer migrator.Close()
if err := migrator.Up(); err != nil && err != migrate.ErrNoChange {
log.Fatal().Err(err).Msg("Failed to apply migrations")
}
q := data.New(conn)
err = service.CreateAdminIfNotExists(context.Background(), q, config.AdminUsername, config.AdminPassword)
if err != nil {
log.Fatal().Err(err).Msg("Failed initial admin account creation")
}
log.Info().Msg("Migrations applied succesfully, proceeding to HTTP server startup")
service.Run(conn, q, config.JWTSecret)
}
func initLogger() {
fmt.Println(config.LogLevel)
level, err := zerolog.ParseLevel(config.LogLevel)
if err != nil {
level = zerolog.InfoLevel
}
zerolog.SetGlobalLevel(level)
output := zerolog.ConsoleWriter{
Out: os.Stdout,
TimeFormat: "2006-01-02 15:04:05",
}
log.Logger = log.Output(output).With().Timestamp().Caller().Logger()
log.Info().Msgf("Logger initialized (log level: %s)", level)
}