mirror of
https://github.com/versia-pub/versia-go.git
synced 2026-03-13 04:29:15 +01:00
chore: init
This commit is contained in:
commit
320715f3e7
174 changed files with 42083 additions and 0 deletions
86
internal/api_schema/api.go
Normal file
86
internal/api_schema/api.go
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
package api_schema
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type APIError struct {
|
||||
StatusCode int `json:"status_code"`
|
||||
Description string `json:"description"`
|
||||
Metadata map[string]any `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
func (e APIError) Error() string {
|
||||
if e.Metadata == nil || len(e.Metadata) == 0 {
|
||||
return fmt.Sprintf("APIError: %d - %s", e.StatusCode, e.Description)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("APIError: %d - %s, %s", e.StatusCode, e.Description, stringifyErrorMetadata(e.Metadata))
|
||||
}
|
||||
|
||||
func stringifyErrorMetadata(m map[string]any) string {
|
||||
sb := strings.Builder{}
|
||||
for key, value := range m {
|
||||
sb.WriteString(fmt.Sprintf("%s=%v, ", key, value))
|
||||
}
|
||||
return strings.TrimSuffix(sb.String(), ", ")
|
||||
}
|
||||
|
||||
func (e APIError) Equals(other any) bool {
|
||||
var err *APIError
|
||||
|
||||
switch raw := other.(type) {
|
||||
case *APIError:
|
||||
err = raw
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
return e.StatusCode == err.StatusCode && e.Description == err.Description
|
||||
}
|
||||
|
||||
func (e APIError) URLEncode() (string, error) {
|
||||
v := url.Values{}
|
||||
v.Set("status_code", fmt.Sprintf("%d", e.StatusCode))
|
||||
v.Set("description", e.Description)
|
||||
|
||||
if e.Metadata != nil {
|
||||
b, err := json.Marshal(e.Metadata)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
v.Set("metadata", string(b))
|
||||
}
|
||||
|
||||
// Fix up spaces because Golang's net/url.URL encodes " " as "+" instead of "%20"
|
||||
// https://github.com/golang/go/issues/13982
|
||||
return strings.ReplaceAll(v.Encode(), "+", "%20"), nil
|
||||
}
|
||||
|
||||
func NewAPIError(code int, description string) func(metadata map[string]any) *APIError {
|
||||
return func(metadata map[string]any) *APIError {
|
||||
return &APIError{StatusCode: code, Description: description, Metadata: metadata}
|
||||
}
|
||||
}
|
||||
|
||||
type APIResponse[T any] struct {
|
||||
Ok bool `json:"ok"`
|
||||
Data *T `json:"data"`
|
||||
Error *APIError `json:"error"`
|
||||
}
|
||||
|
||||
func NewFailedAPIResponse[T any](err error) APIResponse[T] {
|
||||
var e *APIError
|
||||
|
||||
if errors.As(err, &e) {
|
||||
} else {
|
||||
e = NewAPIError(500, err.Error())(nil)
|
||||
}
|
||||
|
||||
return APIResponse[T]{Ok: false, Error: e}
|
||||
}
|
||||
15
internal/api_schema/errors.go
Normal file
15
internal/api_schema/errors.go
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
package api_schema
|
||||
|
||||
var (
|
||||
ErrBadRequest = NewAPIError(400, "Bad request")
|
||||
ErrInvalidRequestBody = NewAPIError(400, "Invalid request body")
|
||||
ErrUnauthorized = NewAPIError(401, "Unauthorized")
|
||||
ErrForbidden = NewAPIError(403, "Forbidden")
|
||||
ErrNotFound = NewAPIError(404, "Not found")
|
||||
ErrConflict = NewAPIError(409, "Conflict")
|
||||
ErrUsernameTaken = NewAPIError(409, "Username is taken")
|
||||
ErrRateLimitExceeded = NewAPIError(429, "Rate limit exceeded")
|
||||
|
||||
ErrInternalServerError = NewAPIError(500, "Internal server error")
|
||||
ErrNotImplemented = NewAPIError(501, "Not implemented")
|
||||
)
|
||||
18
internal/api_schema/notes.go
Normal file
18
internal/api_schema/notes.go
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package api_schema
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/lysand-org/versia-go/pkg/lysand"
|
||||
)
|
||||
|
||||
type Note struct {
|
||||
ID uuid.UUID `json:"id,string"`
|
||||
}
|
||||
|
||||
type FetchNoteResponse = APIResponse[Note]
|
||||
|
||||
type CreateNoteRequest struct {
|
||||
Content string `json:"content" validate:"required,min=1,max=1024"`
|
||||
Visibility lysand.PublicationVisibility `json:"visibility" validate:"required,oneof=public private direct"`
|
||||
Mentions []lysand.URL `json:"mentions"`
|
||||
}
|
||||
17
internal/api_schema/users.go
Normal file
17
internal/api_schema/users.go
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package api_schema
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID uuid.UUID `json:"id,string"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
type FetchUserResponse = APIResponse[User]
|
||||
|
||||
type CreateUserRequest struct {
|
||||
Username string `json:"username" validate:"required,username_regex,min=3,max=32"`
|
||||
Password string `json:"password" validate:"required,min=8,max=256"`
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue