package domain import ( "errors" "fmt" "github.com/gosimple/slug" ) type ValidationError struct { Field string Err error } var _ ErrorWithParams = ValidationError{} func (e ValidationError) Error() string { return fmt.Sprintf("%s: %s", e.Field, e.Err) } func (e ValidationError) Code() ErrorCode { var domainErr Error if errors.As(e.Err, &domainErr) { return domainErr.Code() } return ErrorCodeIncorrectInput } func (e ValidationError) Slug() string { s := "validation" var domainErr Error if errors.As(e.Err, &domainErr) { s = domainErr.Slug() } return fmt.Sprintf("%s-%s", slug.Make(e.Field), s) } func (e ValidationError) Params() map[string]any { var withParams ErrorWithParams ok := errors.As(e.Err, &withParams) if !ok { return nil } return withParams.Params() } type MinGreaterEqualError struct { Min int Current int } var _ ErrorWithParams = MinGreaterEqualError{} func (e MinGreaterEqualError) Error() string { return fmt.Sprintf("must be no less than %d (current: %d)", e.Min, e.Current) } func (e MinGreaterEqualError) Code() ErrorCode { return ErrorCodeIncorrectInput } func (e MinGreaterEqualError) Slug() string { return "min-greater-equal" } func (e MinGreaterEqualError) Params() map[string]any { return map[string]any{ "Min": e.Min, "Current": e.Current, } } type MaxLessEqualError struct { Max int Current int } var _ ErrorWithParams = MaxLessEqualError{} func (e MaxLessEqualError) Error() string { return fmt.Sprintf("must be no greater than %d (current: %d)", e.Max, e.Current) } func (e MaxLessEqualError) Code() ErrorCode { return ErrorCodeIncorrectInput } func (e MaxLessEqualError) Slug() string { return "max-less-equal" } func (e MaxLessEqualError) Params() map[string]any { return map[string]any{ "Max": e.Max, "Current": e.Current, } } type LenOutOfRangeError struct { Min int Max int Current int } var _ ErrorWithParams = LenOutOfRangeError{} func (e LenOutOfRangeError) Error() string { return fmt.Sprintf("length must be between %d and %d (current length: %d)", e.Min, e.Max, e.Current) } func (e LenOutOfRangeError) Code() ErrorCode { return ErrorCodeIncorrectInput } func (e LenOutOfRangeError) Slug() string { return "length-out-of-range" } func (e LenOutOfRangeError) Params() map[string]any { return map[string]any{ "Min": e.Min, "Max": e.Max, "Current": e.Current, } } func validateSliceLen[S ~[]E, E any](s S, min, max int) error { if l := len(s); l > max || l < min { return LenOutOfRangeError{ Min: min, Max: max, Current: l, } } return nil } const ( serverKeyMinLength = 1 serverKeyMaxLength = 10 ) func validateServerKey(key string) error { if l := len(key); l < serverKeyMinLength || l > serverKeyMaxLength { return LenOutOfRangeError{ Min: serverKeyMinLength, Max: serverKeyMaxLength, Current: l, } } return nil } const ( versionCodeMinLength = 2 versionCodeMaxLength = 2 ) func validateVersionCode(code string) error { if l := len(code); l < versionCodeMinLength || l > versionCodeMaxLength { return LenOutOfRangeError{ Min: versionCodeMinLength, Max: versionCodeMaxLength, Current: l, } } return nil }