diff --git a/internal/connections/service.go b/internal/connections/service.go index b1f7cf8..59e25c9 100644 --- a/internal/connections/service.go +++ b/internal/connections/service.go @@ -4,6 +4,7 @@ import ( "database/sql" "encoding/json" "fmt" + "log/slog" "strings" "time" ) @@ -311,6 +312,12 @@ func scanConnections(rows *sql.Rows) ([]Connection, error) { } func (s *ConnectionService) UpdateConnection(id int64, input UpdateConnectionInput) (*Connection, error) { + slog.Info("UpdateConnection called", + "id", id, + "name", input.Name, + "credentialID", input.CredentialID, + "groupID", input.GroupID, + ) setClauses := []string{"updated_at = CURRENT_TIMESTAMP"} args := []interface{}{} @@ -330,9 +337,13 @@ func (s *ConnectionService) UpdateConnection(id int64, input UpdateConnectionInp setClauses = append(setClauses, "group_id = ?") args = append(args, *input.GroupID) } + // Always update credential_id — nil clears it, non-nil sets it. + // Unlike other fields, credential assignment is explicit on every save. + setClauses = append(setClauses, "credential_id = ?") if input.CredentialID != nil { - setClauses = append(setClauses, "credential_id = ?") args = append(args, *input.CredentialID) + } else { + args = append(args, nil) } if input.Tags != nil { tags, _ := json.Marshal(input.Tags) diff --git a/main.go b/main.go index d9a8caa..79fb0e5 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,8 @@ import ( "embed" "log" "log/slog" + "os" + "path/filepath" wraithapp "github.com/vstockwell/wraith/internal/app" "github.com/wailsapp/wails/v3/pkg/application" @@ -16,7 +18,11 @@ var version = "dev" var assets embed.FS func main() { - slog.Info("starting Wraith") + // Set up file logging so we can debug without a console window + if logFile := setupFileLogging(); logFile != nil { + defer logFile.Close() + } + slog.Info("starting Wraith", "version", version) wraith, err := wraithapp.New(version) if err != nil { @@ -57,3 +63,29 @@ func main() { log.Fatal(err) } } + +// setupFileLogging configures slog to write to %APPDATA%\Wraith\wraith.log (Windows) +// or ~/.local/share/wraith/wraith.log (macOS/Linux). Returns the file handle for deferred close. +func setupFileLogging() *os.File { + var logDir string + if appData := os.Getenv("APPDATA"); appData != "" { + logDir = filepath.Join(appData, "Wraith") + } else if home, err := os.UserHomeDir(); err == nil { + logDir = filepath.Join(home, ".local", "share", "wraith") + } else { + return nil + } + + os.MkdirAll(logDir, 0755) + logPath := filepath.Join(logDir, "wraith.log") + + f, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) + if err != nil { + return nil + } + + handler := slog.NewTextHandler(f, &slog.HandlerOptions{Level: slog.LevelDebug}) + slog.SetDefault(slog.New(handler)) + log.SetOutput(f) + return f +}