feat: add PR diff, PR review, and structured error handling commands
This commit is contained in:
parent
3db03ed5e2
commit
50191cc542
10 changed files with 1008 additions and 13 deletions
76
cmd/errors.go
Normal file
76
cmd/errors.go
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"codeberg.org/romaintb/fgj/internal/api"
|
||||
)
|
||||
|
||||
// Error codes for structured error output.
|
||||
const (
|
||||
ErrAuthRequired = "auth_required"
|
||||
ErrNotFound = "not_found"
|
||||
ErrAPIError = "api_error"
|
||||
ErrInvalidInput = "invalid_input"
|
||||
ErrGitDetectionFailed = "git_detection_failed"
|
||||
ErrNetworkError = "network_error"
|
||||
)
|
||||
|
||||
// CLIError is a structured error type for machine-readable output.
|
||||
type CLIError struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Detail string `json:"detail,omitempty"`
|
||||
Status int `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
func (e *CLIError) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
// NewCLIError creates a new CLIError with the given code and message.
|
||||
func NewCLIError(code, message string) *CLIError {
|
||||
return &CLIError{Code: code, Message: message}
|
||||
}
|
||||
|
||||
// NewAPIError creates a CLIError from an HTTP status and message.
|
||||
func NewAPIError(status int, message string) *CLIError {
|
||||
return &CLIError{Code: ErrAPIError, Message: message, Status: status}
|
||||
}
|
||||
|
||||
// writeJSONError writes a structured JSON error to stderr.
|
||||
// It attempts to extract structured info from known error types.
|
||||
// WriteJSONError writes a structured JSON error to stderr.
|
||||
// It is exported for use from main.go.
|
||||
func WriteJSONError(err error) {
|
||||
cliErr := &CLIError{
|
||||
Code: ErrAPIError,
|
||||
Message: err.Error(),
|
||||
}
|
||||
|
||||
// Try to extract structured info from the error chain.
|
||||
var apiErr *api.APIError
|
||||
var cErr *CLIError
|
||||
|
||||
switch {
|
||||
case errors.As(err, &cErr):
|
||||
cliErr = cErr
|
||||
case errors.As(err, &apiErr):
|
||||
cliErr.Status = apiErr.StatusCode
|
||||
cliErr.Detail = apiErr.Body
|
||||
switch {
|
||||
case apiErr.StatusCode == 401 || apiErr.StatusCode == 403:
|
||||
cliErr.Code = ErrAuthRequired
|
||||
case apiErr.StatusCode == 404:
|
||||
cliErr.Code = ErrNotFound
|
||||
default:
|
||||
cliErr.Code = ErrAPIError
|
||||
}
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(os.Stderr)
|
||||
enc.SetIndent("", " ")
|
||||
_ = enc.Encode(cliErr)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue