M go.mod => go.mod +2 -1
@@ 15,6 15,7 @@ require (
github.com/aws/aws-sdk-go-v2 v1.37.1
github.com/aws/aws-sdk-go-v2/credentials v1.18.2
github.com/aws/aws-sdk-go-v2/service/s3 v1.85.1
+ github.com/aws/smithy-go v1.22.5
github.com/emersion/go-message v0.18.2
github.com/emersion/go-pgpmail v0.2.2
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43
@@ 26,6 27,7 @@ require (
github.com/google/uuid v1.6.0
github.com/kavu/go_reuseport v1.5.0
github.com/lib/pq v1.10.9
+ github.com/oklog/ulid/v2 v2.1.1
github.com/prometheus/client_golang v1.16.0
github.com/stretchr/testify v1.10.0
github.com/vaughan0/go-ini v0.0.0-20130923145212-a98ad7ee00ec
@@ 42,7 44,6 @@ require (
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.1 // indirect
- github.com/aws/smithy-go v1.22.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cloudflare/circl v1.6.0 // indirect
M go.sum => go.sum +3 -0
@@ 150,10 150,13 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
+github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
+github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
+github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
A model/id.go => model/id.go +71 -0
@@ 0,0 1,71 @@
+package model
+
+import (
+ "encoding/base32"
+ "fmt"
+ "io"
+
+ "github.com/google/uuid"
+)
+
+// Crockford's low-ambiguity base32 alphabet
+var base32Encoding = base32.
+ NewEncoding("0123456789ABCDEFGHJKMNPQRSTVWXYZ").
+ WithPadding(base32.NoPadding)
+
+type ID struct {
+ uuid uuid.UUID
+}
+
+// Creates a new resource ID.
+func NewID() ID {
+ uuid, err := uuid.NewV7()
+ if err != nil {
+ panic(err)
+ }
+ return ID {
+ uuid: uuid,
+ }
+}
+
+// Returns the UUID representation of this ID.
+func (id *ID) UUID() uuid.UUID {
+ return id.uuid
+}
+
+// Returns the string representation of this ID.
+func (id *ID) String() string {
+ return base32Encoding.EncodeToString(id.uuid[:])
+}
+
+func (id ID) MarshalGQL(w io.Writer) {
+ w.Write([]byte(fmt.Sprintf(`"%s"`, id.String())))
+}
+
+func (id *ID) UnmarshalGQL(v interface{}) error {
+ switch v := v.(type) {
+ case string:
+ bytes, err := base32Encoding.DecodeString(v)
+ if err != nil {
+ return err
+ }
+ id.uuid, err = uuid.FromBytes(bytes)
+ if err != nil {
+ return err
+ }
+ return nil
+ default:
+ return fmt.Errorf("%T is not a valid ID", v)
+ }
+}
+
+// database/sql.Scanner
+func (id *ID) Scan(src any) error {
+ var uuid uuid.UUID
+ err := uuid.Scan(src)
+ if err != nil {
+ return err
+ }
+ id.uuid = uuid
+ return nil
+}