65 lines
1.6 KiB
Go
65 lines
1.6 KiB
Go
package dbx
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log/slog"
|
|
|
|
"github.com/segmentio/ksuid"
|
|
)
|
|
|
|
// UUID is a wrapper around ksuid.KSUID that implements the
|
|
// graphql.Unmarshaler and graphql.Marshaler interfaces for use in GraphQL APIs.
|
|
// It also provides additional convenience functions such as ParseUUID and NewUUID.
|
|
type UUID struct {
|
|
ksuid.KSUID
|
|
}
|
|
|
|
type uuidTransport struct {
|
|
UUIDStr string `json:"uuid_str"`
|
|
}
|
|
|
|
// Generates a new, wrapped KSUID. In the strange case that random bytes can't be read, it will panic.
|
|
func NewUUID() UUID {
|
|
return UUID{KSUID: ksuid.New()}
|
|
}
|
|
|
|
// ParseUUID parses a UUID from a string. If the string is not a valid UUID, it will return an error.
|
|
func ParseUUID(s string) (UUID, error) {
|
|
ksuid, err := ksuid.Parse(s)
|
|
if err != nil {
|
|
return UUID{}, err
|
|
}
|
|
return UUID{KSUID: ksuid}, nil
|
|
}
|
|
|
|
// UnmarshalGQL implements the graphql.Unmarshaler interface
|
|
func (u *UUID) UnmarshalGQL(value interface{}) error {
|
|
slog.Debug("uuid unmarshaling from gql", "val", value)
|
|
str, ok := value.(string)
|
|
if !ok {
|
|
return fmt.Errorf("GraphQL failed to unmarshal UUID value: %v", value)
|
|
}
|
|
|
|
if err := u.UnmarshalText([]byte(str)); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// MarshalGQL implements the graphql.Marshaler interface
|
|
func (u UUID) MarshalGQL(w io.Writer) {
|
|
transport := uuidTransport{UUIDStr: u.String()}
|
|
json, err := json.Marshal(transport)
|
|
if err != nil {
|
|
panic(fmt.Errorf("GraphQL failed to JSON-marshal UUID value: %s", err))
|
|
}
|
|
slog.Debug("uuid marshaling to gql", "uuid", u.String(), "json", string(json))
|
|
_, err = w.Write(json)
|
|
if err != nil {
|
|
panic(fmt.Errorf("GraphQL failed to write UUID value: %s", string(json)))
|
|
}
|
|
}
|