github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/internal/errs/userfacing.go (about)

     1  package errs
     2  
     3  import (
     4  	"errors"
     5  )
     6  
     7  type UserFacingError interface {
     8  	error
     9  	UserError() string
    10  }
    11  
    12  type ErrOpt func(err *userFacingError)
    13  
    14  type userFacingError struct {
    15  	wrapped error
    16  	message string
    17  	input   bool
    18  	tips    []string
    19  }
    20  
    21  func (e *userFacingError) Error() string {
    22  	return "User Facing Error: " + e.UserError()
    23  }
    24  
    25  func (e *userFacingError) UserError() string {
    26  	return e.message
    27  }
    28  
    29  func (e *userFacingError) ErrorTips() []string {
    30  	return e.tips
    31  }
    32  
    33  func (e *userFacingError) InputError() bool {
    34  	return e.input
    35  }
    36  
    37  func (e *userFacingError) Unwrap() error {
    38  	return e.wrapped
    39  }
    40  
    41  func NewUserFacing(message string, opts ...ErrOpt) *userFacingError {
    42  	return WrapUserFacing(nil, message, opts...)
    43  }
    44  
    45  func WrapUserFacing(wrapTarget error, message string, opts ...ErrOpt) *userFacingError {
    46  	err := &userFacingError{
    47  		wrapTarget,
    48  		message,
    49  		false,
    50  		nil,
    51  	}
    52  
    53  	for _, opt := range opts {
    54  		opt(err)
    55  	}
    56  
    57  	return err
    58  }
    59  
    60  func IsUserFacing(err error) bool {
    61  	var userFacingError UserFacingError
    62  	return errors.As(err, &userFacingError)
    63  }
    64  
    65  // SetIf is a helper for setting options if some conditional evaluated to true.
    66  // This is mainly intended for setting tips, as without this you'd have to evaluate your conditional outside of
    67  // NewUserFacing/WrapUserFacing, adding to the boilerplate.
    68  func SetIf(evaluated bool, opt ErrOpt) ErrOpt {
    69  	if evaluated {
    70  		return opt
    71  	}
    72  	return func(err *userFacingError) {}
    73  }
    74  
    75  func SetTips(tips ...string) ErrOpt {
    76  	return func(err *userFacingError) {
    77  		err.tips = append(err.tips, tips...)
    78  	}
    79  }
    80  
    81  func SetInput() ErrOpt {
    82  	return func(err *userFacingError) {
    83  		err.input = true
    84  	}
    85  }