Fix BASE_URL config loading, add tasks/projects; robust .env path resolution

- Config: try ENV_FILE, .env, ../.env for loading; trim trailing slash from BaseURL
- Log BASE_URL at server startup for verification
- .env.example: document BASE_URL
- Tasks, projects, tags, migrations and related API/handlers

Made-with: Cursor
This commit is contained in:
Michilis
2026-03-09 18:57:51 +00:00
parent 75105b8b46
commit bd24545b7b
61 changed files with 6595 additions and 90 deletions

View File

@@ -0,0 +1,147 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: task_dependencies.sql
package repository
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const addTaskDependency = `-- name: AddTaskDependency :exec
INSERT INTO task_dependencies (task_id, blocks_task_id)
VALUES ($1, $2)
ON CONFLICT (task_id, blocks_task_id) DO NOTHING
`
type AddTaskDependencyParams struct {
TaskID pgtype.UUID `json:"task_id"`
BlocksTaskID pgtype.UUID `json:"blocks_task_id"`
}
func (q *Queries) AddTaskDependency(ctx context.Context, arg AddTaskDependencyParams) error {
_, err := q.db.Exec(ctx, addTaskDependency, arg.TaskID, arg.BlocksTaskID)
return err
}
const checkDirectCircularDependency = `-- name: CheckDirectCircularDependency :one
SELECT EXISTS(
SELECT 1 FROM task_dependencies
WHERE task_id = $2 AND blocks_task_id = $1
) AS has_circle
`
type CheckDirectCircularDependencyParams struct {
BlocksTaskID pgtype.UUID `json:"blocks_task_id"`
TaskID pgtype.UUID `json:"task_id"`
}
// Direct cycle: blocks_task_id is blocked by task_id (would create A->B and B->A)
func (q *Queries) CheckDirectCircularDependency(ctx context.Context, arg CheckDirectCircularDependencyParams) (bool, error) {
row := q.db.QueryRow(ctx, checkDirectCircularDependency, arg.BlocksTaskID, arg.TaskID)
var has_circle bool
err := row.Scan(&has_circle)
return has_circle, err
}
const listTaskBlockers = `-- name: ListTaskBlockers :many
SELECT t.id, t.owner_id, t.title, t.description, t.status, t.priority, t.due_date, t.completed_at, t.created_at, t.updated_at, t.deleted_at, t.project_id, t.parent_id, t.sort_order, t.recurrence_rule FROM tasks t
JOIN task_dependencies td ON td.blocks_task_id = t.id
WHERE td.task_id = $1 AND t.deleted_at IS NULL
`
func (q *Queries) ListTaskBlockers(ctx context.Context, taskID pgtype.UUID) ([]Task, error) {
rows, err := q.db.Query(ctx, listTaskBlockers, taskID)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Task{}
for rows.Next() {
var i Task
if err := rows.Scan(
&i.ID,
&i.OwnerID,
&i.Title,
&i.Description,
&i.Status,
&i.Priority,
&i.DueDate,
&i.CompletedAt,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.ProjectID,
&i.ParentID,
&i.SortOrder,
&i.RecurrenceRule,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listTasksBlockedBy = `-- name: ListTasksBlockedBy :many
SELECT t.id, t.owner_id, t.title, t.description, t.status, t.priority, t.due_date, t.completed_at, t.created_at, t.updated_at, t.deleted_at, t.project_id, t.parent_id, t.sort_order, t.recurrence_rule FROM tasks t
JOIN task_dependencies td ON td.task_id = t.id
WHERE td.blocks_task_id = $1 AND t.deleted_at IS NULL
`
func (q *Queries) ListTasksBlockedBy(ctx context.Context, blocksTaskID pgtype.UUID) ([]Task, error) {
rows, err := q.db.Query(ctx, listTasksBlockedBy, blocksTaskID)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Task{}
for rows.Next() {
var i Task
if err := rows.Scan(
&i.ID,
&i.OwnerID,
&i.Title,
&i.Description,
&i.Status,
&i.Priority,
&i.DueDate,
&i.CompletedAt,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.ProjectID,
&i.ParentID,
&i.SortOrder,
&i.RecurrenceRule,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const removeTaskDependency = `-- name: RemoveTaskDependency :exec
DELETE FROM task_dependencies
WHERE task_id = $1 AND blocks_task_id = $2
`
type RemoveTaskDependencyParams struct {
TaskID pgtype.UUID `json:"task_id"`
BlocksTaskID pgtype.UUID `json:"blocks_task_id"`
}
func (q *Queries) RemoveTaskDependency(ctx context.Context, arg RemoveTaskDependencyParams) error {
_, err := q.db.Exec(ctx, removeTaskDependency, arg.TaskID, arg.BlocksTaskID)
return err
}