Created a base to build on
This commit is contained in:
138
cmd/api/main.go
Normal file
138
cmd/api/main.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/danielgtaylor/huma/v2"
|
||||
"github.com/danielgtaylor/huma/v2/adapters/humaecho"
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
_ "github.com/golang-migrate/migrate/v4/database/postgres"
|
||||
_ "github.com/golang-migrate/migrate/v4/source/file"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
_ "github.com/lib/pq"
|
||||
|
||||
"completed/internal/api"
|
||||
"completed/internal/db"
|
||||
)
|
||||
|
||||
func ensureDatabase(dbURL string) error {
|
||||
u, err := url.Parse(dbURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dbName := strings.TrimPrefix(u.Path, "/")
|
||||
if dbName == "" {
|
||||
return fmt.Errorf("database name is empty in URL: %s", dbURL)
|
||||
}
|
||||
|
||||
// Connect to 'postgres' database to create the new DB
|
||||
u.Path = "/postgres"
|
||||
db, err := sql.Open("postgres", u.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
// Check if DB exists
|
||||
var exists bool
|
||||
err = db.QueryRow("SELECT EXISTS(SELECT 1 FROM pg_database WHERE datname = $1)", dbName).Scan(&exists)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !exists {
|
||||
fmt.Printf("Database '%s' does not exist. Creating...\n", dbName)
|
||||
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE \"%s\"", dbName))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Database '%s' created successfully.\n", dbName)
|
||||
} else {
|
||||
fmt.Printf("Database '%s' already exists.\n", dbName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runMigrations(dbURL string) {
|
||||
m, err := migrate.New(
|
||||
"file:///app/db/migrations", // Path inside Docker container
|
||||
dbURL,
|
||||
)
|
||||
if err != nil {
|
||||
// Fallback for local development if not in /app
|
||||
if os.Getenv("MIGRATION_PATH") != "" {
|
||||
m, err = migrate.New(
|
||||
"file://"+os.Getenv("MIGRATION_PATH"),
|
||||
dbURL,
|
||||
)
|
||||
} else {
|
||||
// Try relative path default
|
||||
m, err = migrate.New(
|
||||
"file://db/migrations",
|
||||
dbURL,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Migration initialization failed: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := m.Up(); err != nil && err != migrate.ErrNoChange {
|
||||
fmt.Fprintf(os.Stderr, "Migration failed: %v\n", err)
|
||||
} else {
|
||||
fmt.Println("Migrations ran successfully")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 1. Database connection
|
||||
dbURL := os.Getenv("DATABASE_URL")
|
||||
if dbURL == "" {
|
||||
dbURL = "postgres://user:password@localhost:5432/dbname?sslmode=disable"
|
||||
}
|
||||
|
||||
// Ensure Database Exists
|
||||
if err := ensureDatabase(dbURL); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to ensure database: %v\n", err)
|
||||
}
|
||||
|
||||
// Run Migrations
|
||||
runMigrations(dbURL)
|
||||
|
||||
pool, err := pgxpool.New(context.Background(), dbURL)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer pool.Close()
|
||||
|
||||
queries := db.New(pool)
|
||||
|
||||
// 2. Setup Echo
|
||||
e := echo.New()
|
||||
e.Use(middleware.Logger())
|
||||
e.Use(middleware.Recover())
|
||||
|
||||
// 3. Setup Huma
|
||||
humaApi := humaecho.New(e, huma.DefaultConfig("My API", "1.0.0"))
|
||||
|
||||
// 4. Register Routes
|
||||
api.RegisterRoutes(humaApi, queries)
|
||||
|
||||
// 5. Start Server
|
||||
port := os.Getenv("PORT")
|
||||
if port == "" {
|
||||
port = "8080"
|
||||
}
|
||||
e.Logger.Fatal(e.Start(":" + port))
|
||||
}
|
||||
Reference in New Issue
Block a user