46 lines
1.4 KiB
Go
46 lines
1.4 KiB
Go
package store
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/logger"
|
|
)
|
|
|
|
// Open opens (or creates) the SQLite database at path and runs GORM
|
|
// AutoMigrate for all models. SQLite with WAL is used for single-instance
|
|
// durability; the abstraction lives entirely in this package so a future
|
|
// migration to Postgres stays localised.
|
|
func Open(path string) (*gorm.DB, error) {
|
|
// _busy_timeout helps under concurrent writes; _foreign_keys enforces FK
|
|
// constraints that GORM expects; _journal_mode=WAL improves read/write
|
|
// concurrency for the single-file database.
|
|
dsn := fmt.Sprintf("%s?_busy_timeout=5000&_foreign_keys=on&_journal_mode=WAL", path)
|
|
db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{
|
|
// Silent: our handlers emit their own HTTP errors and frequently run
|
|
// "first-or-create" / 404 lookups whose ErrRecordNotFound would
|
|
// otherwise spam the operator's logs.
|
|
Logger: logger.Default.LogMode(logger.Silent),
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("open sqlite: %w", err)
|
|
}
|
|
|
|
if err := db.AutoMigrate(
|
|
&AdminUser{},
|
|
&App{},
|
|
&ModelConfig{},
|
|
&Skill{},
|
|
&Session{},
|
|
&Message{},
|
|
&AuditLog{},
|
|
); err != nil {
|
|
return nil, fmt.Errorf("auto-migrate: %w", err)
|
|
}
|
|
|
|
// Compound uniqueness: a skill slug is unique per app. Enforced in code
|
|
// to avoid depending on DB-specific index syntax during migration.
|
|
return db, nil
|
|
}
|