feat: update main module to use task repository

This commit is contained in:
2026-03-29 22:46:15 -05:00
parent a49fd2d0d7
commit b515f1c8f6

View File

@@ -6,9 +6,11 @@ import (
"log" "log"
"os" "os"
"git.ksdemosapps.com/kylesoda/pgx-learning/internal/config"
"git.ksdemosapps.com/kylesoda/pgx-learning/internal/db/postgres"
"git.ksdemosapps.com/kylesoda/pgx-learning/internal/models" "git.ksdemosapps.com/kylesoda/pgx-learning/internal/models"
"git.ksdemosapps.com/kylesoda/pgx-learning/internal/repository"
"github.com/jackc/pgx/v5/pgxpool" "github.com/jackc/pgx/v5/pgxpool"
"github.com/joho/godotenv"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
@@ -16,12 +18,8 @@ var pool *pgxpool.Pool
var ctx = context.Background() var ctx = context.Background()
func init() { func init() {
if err := godotenv.Load(); err != nil {
log.Fatal("Error al cargar el archivo .env", err)
}
var err error var err error
pool, err = pgxpool.New(ctx, os.Getenv("PG_FROM_DB_URL")) pool, err = pgxpool.New(ctx, config.Db.Url)
if err != nil { if err != nil {
log.Fatal("Unable to connect to database:", err) log.Fatal("Unable to connect to database:", err)
} }
@@ -34,11 +32,17 @@ func init() {
} }
func main() { func main() {
taskRespository := postgres.NewTaskRepository(pool)
app := &cli.App{ app := &cli.App{
Name: "gotodo", Name: "gotodo",
Usage: "A simple CLI program to manage your tasks", Usage: "A simple CLI program to manage your tasks",
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
tasks, err := getPendingTasks() completedState := false
tasks, err := taskRespository.GetAll(ctx, repository.GetAllTaskFilters{
Limit: 100,
Completed: &completedState,
})
if err != nil { if err != nil {
return err return err
} }
@@ -57,7 +61,10 @@ func main() {
if text == "" { if text == "" {
return fmt.Errorf("task text cannot be empty") return fmt.Errorf("task text cannot be empty")
} }
return createTask(text)
return taskRespository.Save(ctx, &models.Task{
Text: text,
})
}, },
}, },
{ {
@@ -75,13 +82,23 @@ func main() {
title := "Pending Tasks:" title := "Pending Tasks:"
if c.Bool("all") { if c.Bool("all") {
tasks, err = getAllTasks() tasks, err = taskRespository.GetAll(ctx, repository.GetAllTaskFilters{
Limit: 100,
})
title = "All Tasks:" title = "All Tasks:"
} else if c.Bool("completed") { } else if c.Bool("completed") {
tasks, err = getCompletedTasks() completedState := true
tasks, err = taskRespository.GetAll(ctx, repository.GetAllTaskFilters{
Limit: 100,
Completed: &completedState,
})
title = "Completed Tasks:" title = "Completed Tasks:"
} else { } else {
tasks, err = getPendingTasks() completedState := false
tasks, err = taskRespository.GetAll(ctx, repository.GetAllTaskFilters{
Limit: 100,
Completed: &completedState,
})
title = "Pending Tasks:" title = "Pending Tasks:"
} }
@@ -107,7 +124,13 @@ func main() {
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil { if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
return fmt.Errorf("invalid task ID: %s", idStr) return fmt.Errorf("invalid task ID: %s", idStr)
} }
return completeTask(id)
completedState := true
_, err := taskRespository.Update(ctx, id, &models.UpdateTaskInput{
Completed: &completedState,
})
return err
}, },
}, },
{ {
@@ -123,7 +146,13 @@ func main() {
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil { if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
return fmt.Errorf("invalid task ID: %s", idStr) return fmt.Errorf("invalid task ID: %s", idStr)
} }
return undoTask(id)
completedState := false
_, err := taskRespository.Update(ctx, id, &models.UpdateTaskInput{
Completed: &completedState,
})
return err
}, },
}, },
{ {
@@ -139,7 +168,8 @@ func main() {
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil { if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
return fmt.Errorf("invalid task ID: %s", idStr) return fmt.Errorf("invalid task ID: %s", idStr)
} }
return deleteTask(id)
return taskRespository.Delete(ctx, id)
}, },
}, },
}, },
@@ -151,187 +181,6 @@ func main() {
} }
} }
func createTask(text string) error {
sql := `
INSERT INTO tasks (text, completed)
VALUES ($1, $2)
RETURNING id
`
var id int
err := pool.QueryRow(ctx, sql, text, false).Scan(&id)
if err != nil {
return fmt.Errorf("error creating task: %w", err)
}
fmt.Printf("Created task with ID: %d\n", id)
return nil
}
func getAllTasks() ([]models.Task, error) {
sql := `
SELECT id, text, completed, created_at, updated_at
FROM tasks
ORDER BY created_at DESC
LIMIT 1000
`
rows, err := pool.Query(ctx, sql)
if err != nil {
return nil, fmt.Errorf("error querying tasks: %w", err)
}
defer rows.Close()
var tasks []models.Task
for rows.Next() {
var task models.Task
err := rows.Scan(
&task.Id,
&task.Text,
&task.Completed,
&task.CreatedAt,
&task.UpdatedAt,
)
if err != nil {
return nil, fmt.Errorf("error scanning task row: %w", err)
}
tasks = append(tasks, task)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("error iterating task rows: %w", err)
}
return tasks, nil
}
func completeTask(id int) error {
sql := `
UPDATE tasks
SET completed = true, updated_at = NOW()
WHERE id = $1
`
commandTag, err := pool.Exec(ctx, sql, id)
if err != nil {
return fmt.Errorf("error completing task: %w", err)
}
if commandTag.RowsAffected() == 0 {
return fmt.Errorf("no task found with id %d", id)
}
return nil
}
func undoTask(id int) error {
sql := `
UPDATE tasks
SET completed = false, updated_at = NOW()
WHERE id = $1
`
commandTag, err := pool.Exec(ctx, sql, id)
if err != nil {
return fmt.Errorf("error updating task: %w", err)
}
if commandTag.RowsAffected() == 0 {
return fmt.Errorf("no task found with id %d", id)
}
return nil
}
func deleteTask(id int) error {
sql := `DELETE FROM tasks WHERE id = $1`
commandTag, err := pool.Exec(ctx, sql, id)
if err != nil {
return fmt.Errorf("error deleting task: %w", err)
}
if commandTag.RowsAffected() == 0 {
return fmt.Errorf("no task found with id %d", id)
}
return nil
}
func getPendingTasks() ([]models.Task, error) {
sql := `
SELECT id, text, completed, created_at, updated_at
FROM tasks
WHERE completed = false
ORDER BY created_at DESC
`
rows, err := pool.Query(ctx, sql)
if err != nil {
return nil, fmt.Errorf("error querying pending tasks: %w", err)
}
defer rows.Close()
var tasks []models.Task
for rows.Next() {
var task models.Task
err := rows.Scan(
&task.Id,
&task.Text,
&task.Completed,
&task.CreatedAt,
&task.UpdatedAt,
)
if err != nil {
return nil, fmt.Errorf("error scanning task row: %w", err)
}
tasks = append(tasks, task)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("error iterating task rows: %w", err)
}
return tasks, nil
}
func getCompletedTasks() ([]models.Task, error) {
sql := `
SELECT id, text, completed, created_at, updated_at
FROM tasks
WHERE completed = true
ORDER BY created_at DESC
`
rows, err := pool.Query(ctx, sql)
if err != nil {
return nil, fmt.Errorf("error querying completed tasks: %w", err)
}
defer rows.Close()
var tasks []models.Task
for rows.Next() {
var task models.Task
err := rows.Scan(
&task.Id,
&task.Text,
&task.Completed,
&task.CreatedAt,
&task.UpdatedAt,
)
if err != nil {
return nil, fmt.Errorf("error scanning task row: %w", err)
}
tasks = append(tasks, task)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("error iterating task rows: %w", err)
}
return tasks, nil
}
func printTasks(tasks []models.Task) { func printTasks(tasks []models.Task) {
if len(tasks) == 0 { if len(tasks) == 0 {
fmt.Println("No tasks found") fmt.Println("No tasks found")