go-todos-app/main.go
Michael Thomson c7c4f35bb4
All checks were successful
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/dryrun Pipeline was successful
ci/woodpecker/push/publish-tag Pipeline was successful
ci/woodpecker/push/publish-latest Pipeline was successful
ci/woodpecker/pr/publish-latest Pipeline was successful
ci/woodpecker/pr/publish-tag Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/dryrun Pipeline was successful
ci/woodpecker/pull_request_closed/build Pipeline was successful
ci/woodpecker/pull_request_closed/dryrun Pipeline was successful
ci/woodpecker/pull_request_closed/publish-latest Pipeline was successful
ci/woodpecker/pull_request_closed/publish-tag Pipeline was successful
fixed no env file case
2024-06-18 14:23:15 -04:00

138 lines
3.2 KiB
Go

package main
import (
"context"
"log"
"net/http"
"os"
"path/filepath"
pgxuuid "github.com/jackc/pgx-gofrs-uuid"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/joho/godotenv"
"michaelthomson.dev/mthomson/go-todos-app/handlers"
"michaelthomson.dev/mthomson/go-todos-app/repositories"
"michaelthomson.dev/mthomson/go-todos-app/services"
)
func main() {
// load environment
err := godotenv.Load()
if err != nil {
log.Printf("Error loading .env file: %v", err)
}
databaseUrl := os.Getenv("DATABASE_URL")
// connect to Db
dbconfig, err := pgxpool.ParseConfig(databaseUrl)
if err != nil {
log.Fatalf("Unable to parse db config: %v", err)
}
dbconfig.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error {
pgxuuid.Register(conn.TypeMap())
return nil
}
dbpool, err := pgxpool.New(context.Background(), databaseUrl)
if err != nil {
log.Fatalf("Unable to create connection pool: %v", err)
}
defer dbpool.Close()
// apply initial sql
log.Print("Applying migrations table")
content, err := os.ReadFile(filepath.Join("sql", "init.sql"))
if err != nil {
log.Fatal(err)
os.Exit(1)
}
_, err = dbpool.Exec(context.Background(), string(content))
if err != nil {
log.Fatal(err)
os.Exit(1)
}
//apply migrations
log.Print("Starting migrations...")
files, err := os.ReadDir("./sql/migrations")
if err != nil {
log.Fatal(err)
os.Exit(1)
}
for _, file := range files {
path := filepath.Join("sql", "migrations", file.Name())
content, err := os.ReadFile(path)
if err != nil {
log.Fatal(err)
os.Exit(1)
}
var count int
err = dbpool.QueryRow(context.Background(), "SELECT COUNT(1) FROM migration WHERE name=$1", file.Name()).Scan(&count)
if err != nil {
log.Fatal(err)
os.Exit(1)
}
if count == 0 {
log.Printf("Running migration: %s", file.Name())
_, err = dbpool.Exec(context.Background(), string(content))
if err != nil {
log.Fatal(err)
os.Exit(1)
}
_, err = dbpool.Exec(context.Background(), "INSERT INTO migration(name) values($1)", file.Name())
if err != nil {
log.Fatal(err)
os.Exit(1)
}
} else {
log.Printf("Migration already exists: %s", file.Name())
}
}
log.Print("Migrations complete")
// set up repositories
todoRepository := repositories.NewPostgresTodoRepository(dbpool)
// set up services
todoService := services.NewTodoService(&todoRepository)
// set up handlers
homeHandler := handlers.NewHomeHandler(todoService)
todoHandler := handlers.NewTodoHandler(todoService)
router := http.NewServeMux()
// Serve static files
fs := http.FileServer(http.Dir("./assets"))
router.Handle("GET /assets/", http.StripPrefix("/assets/", fs))
router.HandleFunc("GET /{$}", homeHandler.Home)
router.HandleFunc("POST /todos", todoHandler.Create)
router.HandleFunc("DELETE /todos/{id}", todoHandler.Delete)
router.HandleFunc("PATCH /todos/{id}/done", todoHandler.Done)
router.HandleFunc("PATCH /todos/{id}/undone", todoHandler.Undone)
server := http.Server{
Addr: "localhost:3000",
Handler: router,
}
log.Fatal(server.ListenAndServe())
}