Files
agent 255e8dcf71 feat: initial scaffold of kanban_cpp v2 (issue 0130)
Frontend C++ ImGui (main.cpp + 4 paneles) + backend Go (HTTP + SQLite + fsnotify + SSE).
Reusa parse/scan/watch funcs del registry (issue 0130a).
2026-05-22 22:19:47 +02:00

52 lines
1.0 KiB
Go

package main
import (
"database/sql"
"fmt"
"io/fs"
"sort"
"strings"
_ "github.com/mattn/go-sqlite3"
)
func openDB(path string) (*sql.DB, error) {
dsn := fmt.Sprintf("file:%s?_journal_mode=WAL&_foreign_keys=on", path)
db, err := sql.Open("sqlite3", dsn)
if err != nil {
return nil, err
}
if err := db.Ping(); err != nil {
return nil, err
}
return db, nil
}
func applyMigrations(db *sql.DB) error {
entries, err := fs.ReadDir(migrationsFS, "migrations")
if err != nil {
return err
}
names := []string{}
for _, e := range entries {
if !e.IsDir() && strings.HasSuffix(e.Name(), ".sql") {
names = append(names, e.Name())
}
}
sort.Strings(names)
for _, n := range names {
b, err := fs.ReadFile(migrationsFS, "migrations/"+n)
if err != nil {
return err
}
if _, err := db.Exec(string(b)); err != nil {
low := strings.ToLower(err.Error())
if strings.Contains(low, "duplicate column") || strings.Contains(low, "already exists") {
continue
}
return fmt.Errorf("%s: %w", n, err)
}
}
return nil
}