refactor!: add missing fields and docs

This commit is contained in:
DevMiner 2024-08-22 23:03:38 +02:00
parent 61891d891a
commit 6e59386f60
73 changed files with 726 additions and 580 deletions

View file

@ -0,0 +1,85 @@
package versiautils
import (
"encoding/json"
"slices"
"github.com/rs/zerolog/log"
)
var (
validTextContentTypes = []string{"text/html", "text/plain"}
validImageContentTypes = []string{"image/png", "image/jpeg", "image/gif", "image/svg+xml"}
)
// ContentTypeMap is a map of content types to their respective content.
type ContentTypeMap[T any] map[string]T
func (m *ContentTypeMap[T]) unmarshalJSON(raw []byte, valid []string) error {
var cm map[string]json.RawMessage
if err := json.Unmarshal(raw, &cm); err != nil {
return err
}
*m = make(ContentTypeMap[T])
for k, v := range cm {
if !slices.Contains(valid, k) {
// TODO: replace with logr
log.Debug().Caller().Str("mimetype", k).Msg("unexpected content type, skipping")
continue
}
var c T
if err := json.Unmarshal(v, &c); err != nil {
return err
}
(*m)[k] = c
}
return nil
}
func (m ContentTypeMap[T]) getPreferred(preferred []string) *T {
for _, v := range preferred {
if c, ok := m[v]; ok {
return &c
}
}
return nil
}
type TextContent struct {
Content string `json:"content"`
}
type TextContentTypeMap ContentTypeMap[TextContent]
func (t *TextContentTypeMap) UnmarshalJSON(data []byte) error {
return (*ContentTypeMap[TextContent])(t).unmarshalJSON(data, validTextContentTypes)
}
func (t TextContentTypeMap) String() string {
if c := (ContentTypeMap[TextContent])(t).getPreferred(validTextContentTypes); c != nil {
return c.Content
}
return ""
}
type ImageContent struct {
Content *URL `json:"content"`
}
type ImageContentTypeMap ContentTypeMap[ImageContent]
func (i *ImageContentTypeMap) UnmarshalJSON(data []byte) error {
return (*ContentTypeMap[ImageContent])(i).unmarshalJSON(data, validImageContentTypes)
}
func (i ImageContentTypeMap) String() string {
if c := (ContentTypeMap[ImageContent])(i).getPreferred(validImageContentTypes); c != nil {
return c.Content.String()
}
return ""
}

57
pkg/versia/utils/time.go Normal file
View file

@ -0,0 +1,57 @@
package versiautils
import (
"encoding/json"
"time"
)
const ISO8601 = "2006-01-02T15:04:05.000Z"
func ParseTime(s string) (Time, error) {
t, err := time.Parse(ISO8601, s)
return Time(t), err
}
// Time is a type that represents a time in the ISO8601 format.
type Time time.Time
// String returns the time in the ISO8601 format.
func (t Time) String() string {
return t.ToStd().Format(ISO8601)
}
// UnmarshalJSON decodes the time from a string in the ISO8601 format.
func (t *Time) UnmarshalJSON(data []byte) error {
raw := ""
if err := json.Unmarshal(data, &raw); err != nil {
return err
}
parsed, err := time.Parse(ISO8601, raw)
if err != nil {
return err
}
*t = Time(parsed)
return nil
}
// MarshalJSON marshals the time to a string in the ISO8601 format.
func (t Time) MarshalJSON() ([]byte, error) {
return json.Marshal(t.String())
}
// ToStd converts the time to a [time.Time].
func (t Time) ToStd() time.Time {
return time.Time(t)
}
// TimeFromStd converts a [time.Time] to a Time.
func TimeFromStd(u time.Time) Time {
return Time(u)
}
func TimeNow() Time {
return Time(time.Now())
}

54
pkg/versia/utils/url.go Normal file
View file

@ -0,0 +1,54 @@
package versiautils
import (
"encoding/json"
"net/url"
)
// URL is a type that represents a URL, represented by a string in JSON, instead of a JSON object.
type URL url.URL
func (u *URL) ResolveReference(ref *url.URL) *URL {
return URLFromStd(u.ToStd().ResolveReference(ref))
}
func (u *URL) String() string {
return u.ToStd().String()
}
func (u *URL) UnmarshalJSON(data []byte) error {
raw := ""
if err := json.Unmarshal(data, &raw); err != nil {
return err
}
parsed, err := url.Parse(raw)
if err != nil {
return err
}
*u = URL(*parsed)
return nil
}
func (u *URL) MarshalJSON() ([]byte, error) {
return json.Marshal(u.String())
}
func (u *URL) ToStd() *url.URL {
return (*url.URL)(u)
}
func URLFromStd(u *url.URL) *URL {
return (*URL)(u)
}
func ParseURL(raw string) (*URL, error) {
parsed, err := url.Parse(raw)
if err != nil {
return nil, err
}
return URLFromStd(parsed), nil
}