95 lines
2.4 KiB
Go
95 lines
2.4 KiB
Go
|
|
package repository
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"code.cubecraftcreations.com/CubeCraft-Creations/Control-Center/go-backend/internal/models"
|
||
|
|
"github.com/jackc/pgx/v5"
|
||
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
||
|
|
)
|
||
|
|
|
||
|
|
// ProjectRepository provides PostgreSQL-backed CRUD for projects.
|
||
|
|
type ProjectRepository struct {
|
||
|
|
pool *pgxpool.Pool
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewProjectRepository returns a repository wired to the given connection pool.
|
||
|
|
func NewProjectRepository(pool *pgxpool.Pool) *ProjectRepository {
|
||
|
|
return &ProjectRepository{pool: pool}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create inserts a new project. The current projects table only stores
|
||
|
|
// a single agent_id, so we use the first entry from AgentIDs if present.
|
||
|
|
func (r *ProjectRepository) Create(ctx context.Context, p models.Project) (models.Project, error) {
|
||
|
|
now := time.Now().UTC()
|
||
|
|
if p.CreatedAt.IsZero() {
|
||
|
|
p.CreatedAt = now
|
||
|
|
}
|
||
|
|
if p.UpdatedAt.IsZero() {
|
||
|
|
p.UpdatedAt = now
|
||
|
|
}
|
||
|
|
|
||
|
|
var agentID *string
|
||
|
|
if len(p.AgentIDs) > 0 {
|
||
|
|
agentID = &p.AgentIDs[0]
|
||
|
|
}
|
||
|
|
|
||
|
|
err := r.pool.QueryRow(ctx, `
|
||
|
|
INSERT INTO projects (name, description, status, agent_id, created_at, updated_at)
|
||
|
|
VALUES ($1, $2, $3, $4, $5, $6)
|
||
|
|
RETURNING id, name, description, status, agent_id, created_at, updated_at
|
||
|
|
`, p.Name, p.Description, string(p.Status), agentID, p.CreatedAt, p.UpdatedAt).Scan(
|
||
|
|
&p.ID, &p.Name, &p.Description, &p.Status, &agentID,
|
||
|
|
&p.CreatedAt, &p.UpdatedAt,
|
||
|
|
)
|
||
|
|
if err != nil {
|
||
|
|
return p, err
|
||
|
|
}
|
||
|
|
|
||
|
|
if agentID != nil {
|
||
|
|
p.AgentIDs = []string{*agentID}
|
||
|
|
} else {
|
||
|
|
p.AgentIDs = []string{}
|
||
|
|
}
|
||
|
|
|
||
|
|
return p, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// List returns all projects ordered by name.
|
||
|
|
func (r *ProjectRepository) List(ctx context.Context) ([]models.Project, error) {
|
||
|
|
rows, err := r.pool.Query(ctx, `
|
||
|
|
SELECT id, name, description, status, agent_id, created_at, updated_at
|
||
|
|
FROM projects
|
||
|
|
ORDER BY name
|
||
|
|
`)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
defer rows.Close()
|
||
|
|
|
||
|
|
return pgx.CollectRows(rows, func(row pgx.CollectableRow) (models.Project, error) {
|
||
|
|
var p models.Project
|
||
|
|
var agentID *string
|
||
|
|
|
||
|
|
if err := row.Scan(&p.ID, &p.Name, &p.Description, &p.Status,
|
||
|
|
&agentID, &p.CreatedAt, &p.UpdatedAt); err != nil {
|
||
|
|
return p, err
|
||
|
|
}
|
||
|
|
|
||
|
|
if agentID != nil {
|
||
|
|
p.AgentIDs = []string{*agentID}
|
||
|
|
} else {
|
||
|
|
p.AgentIDs = []string{}
|
||
|
|
}
|
||
|
|
return p, nil
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
// Count returns the total number of projects.
|
||
|
|
func (r *ProjectRepository) Count(ctx context.Context) (int, error) {
|
||
|
|
var n int
|
||
|
|
err := r.pool.QueryRow(ctx, `SELECT COUNT(*) FROM projects`).Scan(&n)
|
||
|
|
return n, err
|
||
|
|
}
|