package domain import ( "errors" "fmt" "regexp" "time" ) const ( usernameMinLength = 2 usernameMaxLength = 40 userIDMin = 1 ) var ( ErrUsernameFormat = errors.New("may only contain alphanumeric characters or single hyphens and cannot begin or end with a hyphen") rxAlphanumericHyphens = regexp.MustCompile("^[a-zA-Z0-9]+([-][a-zA-Z0-9]+)*$") ) type User struct { ID int64 Name string CreatedAt time.Time } type CreateUserParams struct { name string } func NewCreateUserParams(name string) (CreateUserParams, error) { if name == "" { return CreateUserParams{}, ValidationError{ Field: "Name", Err: ErrRequired, } } if len(name) < usernameMinLength { return CreateUserParams{}, ValidationError{ Field: "Name", Err: MinLengthError{ Min: usernameMinLength, }, } } if len(name) > usernameMaxLength { return CreateUserParams{}, ValidationError{ Field: "Name", Err: MaxLengthError{ Max: usernameMaxLength, }, } } if !rxAlphanumericHyphens.MatchString(name) { return CreateUserParams{}, ValidationError{ Field: "Name", Err: ErrUsernameFormat, } } return CreateUserParams{name: name}, nil } func (c CreateUserParams) Name() string { return c.name } type UsernameAlreadyTakenError struct { Name string } func (e UsernameAlreadyTakenError) Error() string { return fmt.Sprintf("username '%s' is already taken", e.Name) } func (e UsernameAlreadyTakenError) UserError() string { return e.Error() } func (e UsernameAlreadyTakenError) Code() ErrorCode { return ErrorCodeAlreadyExists } type UserDoesNotExistError struct { ID int64 } func (e UserDoesNotExistError) Error() string { return fmt.Sprintf("user (ID=%d) doesn't exist", e.ID) } func (e UserDoesNotExistError) UserError() string { return e.Error() } func (e UserDoesNotExistError) Code() ErrorCode { return ErrorCodeValidationError } type UserNotFoundError struct { ID int64 } func (e UserNotFoundError) Error() string { return fmt.Sprintf("user (ID=%d) not found", e.ID) } func (e UserNotFoundError) UserError() string { return e.Error() } func (e UserNotFoundError) Code() ErrorCode { return ErrorCodeEntityNotFound }