diff --git a/.air.toml b/.air.toml
new file mode 100644
index 0000000..1687879
--- /dev/null
+++ b/.air.toml
@@ -0,0 +1,43 @@
+root = "."
+tmp_dir = "tmp"
+
+[build]
+ args_bin = ["web"]
+ bin = "./tmp/main"
+ cmd = "go build -o ./tmp/main ."
+ delay = 1000
+ exclude_dir = ["docs", "frontend", "prns", "pronounslib", "tmp", "target"]
+ exclude_file = []
+ exclude_regex = ["_test.go"]
+ exclude_unchanged = false
+ follow_symlink = false
+ full_bin = ""
+ include_dir = []
+ include_ext = ["go", "tpl", "tmpl", "html"]
+ include_file = []
+ kill_delay = "0s"
+ log = "build-errors.log"
+ poll = false
+ poll_interval = 0
+ rerun = false
+ rerun_delay = 500
+ send_interrupt = false
+ stop_on_error = false
+
+[color]
+ app = ""
+ build = "yellow"
+ main = "magenta"
+ runner = "green"
+ watcher = "cyan"
+
+[log]
+ main_only = false
+ time = false
+
+[misc]
+ clean_on_exit = false
+
+[screen]
+ clear_on_rebuild = false
+ keep_scroll = true
diff --git a/.gitignore b/.gitignore
index 7cc7eb8..8e5f23c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,4 @@ package
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
target
+tmp
diff --git a/backend/common/generator.go b/backend/common/generator.go
new file mode 100644
index 0000000..33385e1
--- /dev/null
+++ b/backend/common/generator.go
@@ -0,0 +1,65 @@
+package common
+
+import (
+ "math/rand"
+ "sync/atomic"
+ "time"
+)
+
+// Generator is a snowflake generator.
+// For compatibility with other snowflake implementations, both worker and PID are set,
+// but they are randomized for every generator.
+type IDGenerator struct {
+ inc *uint64
+ worker, pid uint64
+}
+
+var defaultGenerator = NewIDGenerator(0, 0)
+
+// NewIDGenerator creates a new ID generator with the given worker and pid.
+// If worker or pid is empty, it will be set to a random number.
+func NewIDGenerator(worker, pid uint64) *IDGenerator {
+ if worker == 0 {
+ worker = rand.Uint64()
+ }
+ if pid == 0 {
+ pid = rand.Uint64()
+ }
+
+ g := &IDGenerator{
+ inc: new(uint64),
+ worker: worker % 32,
+ pid: pid % 32,
+ }
+
+ return g
+}
+
+// GenerateID generates a new snowflake with the default generator.
+// If you need to customize the worker and PID, manually call (*Generator).Generate.
+func GenerateID() Snowflake {
+ return defaultGenerator.Generate()
+}
+
+// GenerateID generates a new snowflake with the given time with the default generator.
+// If you need to customize the worker and PID, manually call (*Generator).GenerateWithTime.
+func GenerateIDWithTime(t time.Time) Snowflake {
+ return defaultGenerator.GenerateWithTime(t)
+}
+
+// Generate generates a snowflake with the current time.
+func (g *IDGenerator) Generate() Snowflake {
+ return g.GenerateWithTime(time.Now())
+}
+
+// GenerateWithTime generates a snowflake with the given time.
+// To generate a snowflake for comparison, use the top-level New function instead.
+func (g *IDGenerator) GenerateWithTime(t time.Time) Snowflake {
+ increment := atomic.AddUint64(g.inc, 1)
+ ts := uint64(t.UnixMilli() - Epoch)
+
+ worker := g.worker << 17
+ pid := g.pid << 12
+
+ return Snowflake(ts<<22 | worker | pid | (increment % 4096))
+}
diff --git a/backend/common/snowflake.go b/backend/common/snowflake.go
new file mode 100644
index 0000000..694ec24
--- /dev/null
+++ b/backend/common/snowflake.go
@@ -0,0 +1,83 @@
+package common
+
+import (
+ "strconv"
+ "strings"
+ "time"
+)
+
+// Epoch is the pronouns.cc epoch (January 1st 2022 at 00:00:00 UTC) in milliseconds.
+const Epoch = 1_640_995_200_000
+const epochDuration = Epoch * time.Millisecond
+
+const NullSnowflake = ^Snowflake(0)
+
+// Snowflake is a 64-bit integer used as a unique ID, with an embedded timestamp.
+type Snowflake uint64
+
+// ID is an alias to Snowflake.
+type ID = Snowflake
+
+// ParseSnowflake parses a snowflake from a string.
+func ParseSnowflake(sf string) (Snowflake, error) {
+ if sf == "null" {
+ return NullSnowflake, nil
+ }
+
+ i, err := strconv.ParseUint(sf, 10, 64)
+ if err != nil {
+ return 0, err
+ }
+
+ return Snowflake(i), nil
+}
+
+// NewSnowflake creates a new snowflake from the given time.
+func NewSnowflake(t time.Time) Snowflake {
+ ts := time.Duration(t.UnixNano()) - epochDuration
+
+ return Snowflake((ts / time.Millisecond) << 22)
+}
+
+// String returns the snowflake as a string.
+func (s Snowflake) String() string { return strconv.FormatUint(uint64(s), 10) }
+
+// Time returns the creation time of the snowflake.
+func (s Snowflake) Time() time.Time {
+ ts := time.Duration(s>>22)*time.Millisecond + epochDuration
+ return time.Unix(0, int64(ts))
+}
+
+func (s Snowflake) IsValid() bool {
+ return s != 0 && s != NullSnowflake
+}
+
+func (s Snowflake) MarshalJSON() ([]byte, error) {
+ if !s.IsValid() {
+ return []byte("null"), nil
+ }
+
+ return []byte(`"` + strconv.FormatUint(uint64(s), 10) + `"`), nil
+}
+
+func (s *Snowflake) UnmarshalJSON(src []byte) error {
+ sf, err := ParseSnowflake(strings.Trim(string(src), `"`))
+ if err != nil {
+ return err
+ }
+
+ *s = sf
+ return nil
+}
+
+func (s Snowflake) Worker() uint8 {
+ return uint8(s & 0x3E0000 >> 17)
+}
+
+func (s Snowflake) PID() uint8 {
+ return uint8(s & 0x1F000 >> 12)
+}
+
+func (s Snowflake) Increment() uint16 {
+ return uint16(s & 0xFFF)
+}
diff --git a/backend/common/snowflake_types.go b/backend/common/snowflake_types.go
new file mode 100644
index 0000000..3e9848f
--- /dev/null
+++ b/backend/common/snowflake_types.go
@@ -0,0 +1,39 @@
+package common
+
+import "time"
+
+type UserID Snowflake
+
+func (id UserID) String() string { return Snowflake(id).String() }
+func (id UserID) Time() time.Time { return Snowflake(id).Time() }
+func (id UserID) IsValid() bool { return Snowflake(id).IsValid() }
+func (id UserID) Worker() uint8 { return Snowflake(id).Worker() }
+func (id UserID) PID() uint8 { return Snowflake(id).PID() }
+func (id UserID) Increment() uint16 { return Snowflake(id).Increment() }
+
+func (id UserID) MarshalJSON() ([]byte, error) { return Snowflake(id).MarshalJSON() }
+func (id *UserID) UnmarshalJSON(src []byte) error { return (*Snowflake)(id).UnmarshalJSON(src) }
+
+type MemberID Snowflake
+
+func (id MemberID) String() string { return Snowflake(id).String() }
+func (id MemberID) Time() time.Time { return Snowflake(id).Time() }
+func (id MemberID) IsValid() bool { return Snowflake(id).IsValid() }
+func (id MemberID) Worker() uint8 { return Snowflake(id).Worker() }
+func (id MemberID) PID() uint8 { return Snowflake(id).PID() }
+func (id MemberID) Increment() uint16 { return Snowflake(id).Increment() }
+
+func (id MemberID) MarshalJSON() ([]byte, error) { return Snowflake(id).MarshalJSON() }
+func (id *MemberID) UnmarshalJSON(src []byte) error { return (*Snowflake)(id).UnmarshalJSON(src) }
+
+type FlagID Snowflake
+
+func (id FlagID) String() string { return Snowflake(id).String() }
+func (id FlagID) Time() time.Time { return Snowflake(id).Time() }
+func (id FlagID) IsValid() bool { return Snowflake(id).IsValid() }
+func (id FlagID) Worker() uint8 { return Snowflake(id).Worker() }
+func (id FlagID) PID() uint8 { return Snowflake(id).PID() }
+func (id FlagID) Increment() uint16 { return Snowflake(id).Increment() }
+
+func (id FlagID) MarshalJSON() ([]byte, error) { return Snowflake(id).MarshalJSON() }
+func (id *FlagID) UnmarshalJSON(src []byte) error { return (*Snowflake)(id).UnmarshalJSON(src) }
diff --git a/backend/db/flags.go b/backend/db/flags.go
index 151cb92..8187c46 100644
--- a/backend/db/flags.go
+++ b/backend/db/flags.go
@@ -9,6 +9,7 @@ import (
"io"
"strings"
+ "codeberg.org/pronounscc/pronouns.cc/backend/common"
"codeberg.org/pronounscc/pronouns.cc/backend/log"
"emperror.dev/errors"
"github.com/davidbyttow/govips/v2/vips"
@@ -20,11 +21,12 @@ import (
)
type PrideFlag struct {
- ID xid.ID `json:"id"`
- UserID xid.ID `json:"-"`
- Hash string `json:"hash"`
- Name string `json:"name"`
- Description *string `json:"description"`
+ ID xid.ID `json:"id"`
+ SnowflakeID common.FlagID `json:"id_new"`
+ UserID xid.ID `json:"-"`
+ Hash string `json:"hash"`
+ Name string `json:"name"`
+ Description *string `json:"description"`
}
type UserFlag struct {
@@ -194,11 +196,12 @@ func (db *DB) CreateFlag(ctx context.Context, tx pgx.Tx, userID xid.ID, name, de
sql, args, err := sq.Insert("pride_flags").
SetMap(map[string]any{
- "id": xid.New(),
- "hash": "",
- "user_id": userID.String(),
- "name": name,
- "description": description,
+ "id": xid.New(),
+ "snowflake_id": common.GenerateID(),
+ "hash": "",
+ "user_id": userID.String(),
+ "name": name,
+ "description": description,
}).Suffix("RETURNING *").ToSql()
if err != nil {
return f, errors.Wrap(err, "building query")
diff --git a/backend/db/member.go b/backend/db/member.go
index 71b3bd0..f301c89 100644
--- a/backend/db/member.go
+++ b/backend/db/member.go
@@ -6,6 +6,7 @@ import (
"strings"
"time"
+ "codeberg.org/pronounscc/pronouns.cc/backend/common"
"emperror.dev/errors"
"github.com/Masterminds/squirrel"
"github.com/georgysavva/scany/v2/pgxscan"
@@ -22,6 +23,7 @@ const (
type Member struct {
ID xid.ID
UserID xid.ID
+ SnowflakeID common.MemberID
SID string `db:"sid"`
Name string
DisplayName *string
@@ -71,9 +73,23 @@ func (db *DB) Member(ctx context.Context, id xid.ID) (m Member, err error) {
return m, nil
}
+func (db *DB) MemberBySnowflake(ctx context.Context, id common.MemberID) (m Member, err error) {
+ sql, args, err := sq.Select("*").From("members").Where("snowflake_id = ?", id).ToSql()
+ if err != nil {
+ return m, errors.Wrap(err, "building sql")
+ }
+
+ err = pgxscan.Get(ctx, db, &m, sql, args...)
+ if err != nil {
+ return m, errors.Wrap(err, "executing query")
+ }
+ return m, nil
+}
+
// UserMember returns a member scoped by user.
func (db *DB) UserMember(ctx context.Context, userID xid.ID, memberRef string) (m Member, err error) {
- sql, args, err := sq.Select("*").From("members").Where("user_id = ?", userID).Where("(id = ? or name = ?)", memberRef, memberRef).ToSql()
+ sf, _ := common.ParseSnowflake(memberRef) // error can be ignored as the zero value will never be used as an ID
+ sql, args, err := sq.Select("*").From("members").Where("user_id = ?", userID).Where("(id = ? or snowflake_id = ? or name = ?)", memberRef, sf, memberRef).ToSql()
if err != nil {
return m, errors.Wrap(err, "building sql")
}
@@ -135,8 +151,8 @@ func (db *DB) CreateMember(
name string, displayName *string, bio string, links []string,
) (m Member, err error) {
sql, args, err := sq.Insert("members").
- Columns("user_id", "id", "sid", "name", "display_name", "bio", "links").
- Values(userID, xid.New(), squirrel.Expr("find_free_member_sid()"), name, displayName, bio, links).
+ Columns("user_id", "snowflake_id", "id", "sid", "name", "display_name", "bio", "links").
+ Values(userID, common.GenerateID(), xid.New(), squirrel.Expr("find_free_member_sid()"), name, displayName, bio, links).
Suffix("RETURNING *").ToSql()
if err != nil {
return m, errors.Wrap(err, "building sql")
diff --git a/backend/db/user.go b/backend/db/user.go
index 95a3355..80d380d 100644
--- a/backend/db/user.go
+++ b/backend/db/user.go
@@ -22,6 +22,7 @@ import (
type User struct {
ID xid.ID
+ SnowflakeID common.UserID
SID string `db:"sid"`
Username string
DisplayName *string
@@ -206,7 +207,7 @@ func (db *DB) CreateUser(ctx context.Context, tx pgx.Tx, username string) (u Use
return u, err
}
- sql, args, err := sq.Insert("users").Columns("id", "username", "sid").Values(xid.New(), username, squirrel.Expr("find_free_user_sid()")).Suffix("RETURNING *").ToSql()
+ sql, args, err := sq.Insert("users").Columns("id", "snowflake_id", "username", "sid").Values(xid.New(), common.GenerateID(), username, squirrel.Expr("find_free_user_sid()")).Suffix("RETURNING *").ToSql()
if err != nil {
return u, errors.Wrap(err, "building sql")
}
@@ -494,6 +495,26 @@ func (db *DB) User(ctx context.Context, id xid.ID) (u User, err error) {
return u, nil
}
+// UserBySnowflake gets a user by their snowflake ID.
+func (db *DB) UserBySnowflake(ctx context.Context, id common.UserID) (u User, err error) {
+ sql, args, err := sq.Select("*", "(SELECT instance FROM fediverse_apps WHERE id = users.fediverse_app_id) AS fediverse_instance").
+ From("users").Where("snowflake_id = ?", id).ToSql()
+ if err != nil {
+ return u, errors.Wrap(err, "building sql")
+ }
+
+ err = pgxscan.Get(ctx, db, &u, sql, args...)
+ if err != nil {
+ if errors.Cause(err) == pgx.ErrNoRows {
+ return u, ErrUserNotFound
+ }
+
+ return u, errors.Wrap(err, "getting user from db")
+ }
+
+ return u, nil
+}
+
// Username gets a user by username.
func (db *DB) Username(ctx context.Context, name string) (u User, err error) {
sql, args, err := sq.Select("*").From("users").Where("username = ?", name).ToSql()
diff --git a/backend/main.go b/backend/main.go
index 7c9226a..008e80f 100644
--- a/backend/main.go
+++ b/backend/main.go
@@ -62,9 +62,8 @@ func run(c *cli.Context) error {
return nil
case err := <-e:
log.Fatalf("Error running server: %v", err)
+ return err
}
-
- return nil
}
const MaxContentLength = 2 * 1024 * 1024
diff --git a/backend/routes/v1/auth/routes.go b/backend/routes/v1/auth/routes.go
index 7699084..103d43e 100644
--- a/backend/routes/v1/auth/routes.go
+++ b/backend/routes/v1/auth/routes.go
@@ -4,6 +4,7 @@ import (
"net/http"
"os"
+ "codeberg.org/pronounscc/pronouns.cc/backend/common"
"codeberg.org/pronounscc/pronouns.cc/backend/db"
"codeberg.org/pronounscc/pronouns.cc/backend/log"
"codeberg.org/pronounscc/pronouns.cc/backend/server"
@@ -25,6 +26,7 @@ type Server struct {
type userResponse struct {
ID xid.ID `json:"id"`
+ SnowflakeID common.UserID `json:"id_new"`
Username string `json:"name"`
DisplayName *string `json:"display_name"`
Bio *string `json:"bio"`
@@ -51,6 +53,7 @@ type userResponse struct {
func dbUserToUserResponse(u db.User, fields []db.Field) *userResponse {
return &userResponse{
ID: u.ID,
+ SnowflakeID: u.SnowflakeID,
Username: u.Username,
DisplayName: u.DisplayName,
Bio: u.Bio,
diff --git a/backend/routes/v1/member/delete_member.go b/backend/routes/v1/member/delete_member.go
index 5ce49c0..4c2abde 100644
--- a/backend/routes/v1/member/delete_member.go
+++ b/backend/routes/v1/member/delete_member.go
@@ -8,12 +8,13 @@ import (
"github.com/go-chi/render"
"github.com/rs/xid"
+ "codeberg.org/pronounscc/pronouns.cc/backend/common"
"codeberg.org/pronounscc/pronouns.cc/backend/db"
"codeberg.org/pronounscc/pronouns.cc/backend/log"
"codeberg.org/pronounscc/pronouns.cc/backend/server"
)
-func (s *Server) deleteMember(w http.ResponseWriter, r *http.Request) error {
+func (s *Server) deleteMember(w http.ResponseWriter, r *http.Request) (err error) {
ctx := r.Context()
claims, _ := server.ClaimsFromContext(ctx)
@@ -22,18 +23,27 @@ func (s *Server) deleteMember(w http.ResponseWriter, r *http.Request) error {
return server.APIError{Code: server.ErrMissingPermissions, Details: "this token is read-only"}
}
- id, err := xid.FromString(chi.URLParam(r, "memberRef"))
- if err != nil {
- return server.APIError{Code: server.ErrMemberNotFound}
- }
+ var m db.Member
+ if id, err := xid.FromString(chi.URLParam(r, "memberRef")); err == nil {
+ m, err = s.DB.Member(ctx, id)
+ if err != nil {
+ if err == db.ErrMemberNotFound {
+ return server.APIError{Code: server.ErrMemberNotFound}
+ }
- m, err := s.DB.Member(ctx, id)
- if err != nil {
- if err == db.ErrMemberNotFound {
- return server.APIError{Code: server.ErrMemberNotFound}
+ return errors.Wrap(err, "getting member")
}
+ } else if id, err := common.ParseSnowflake(chi.URLParam(r, "memberRef")); err == nil {
+ m, err = s.DB.MemberBySnowflake(ctx, common.MemberID(id))
+ if err != nil {
+ if err == db.ErrMemberNotFound {
+ return server.APIError{Code: server.ErrMemberNotFound}
+ }
- return errors.Wrap(err, "getting member")
+ return errors.Wrap(err, "getting member")
+ }
+ } else {
+ return server.APIError{Code: server.ErrMemberNotFound}
}
if m.UserID != claims.UserID {
diff --git a/backend/routes/v1/member/get_member.go b/backend/routes/v1/member/get_member.go
index ddc94d8..2a7d5e6 100644
--- a/backend/routes/v1/member/get_member.go
+++ b/backend/routes/v1/member/get_member.go
@@ -4,7 +4,9 @@ import (
"context"
"net/http"
+ "codeberg.org/pronounscc/pronouns.cc/backend/common"
"codeberg.org/pronounscc/pronouns.cc/backend/db"
+ "codeberg.org/pronounscc/pronouns.cc/backend/log"
"codeberg.org/pronounscc/pronouns.cc/backend/server"
"emperror.dev/errors"
"github.com/go-chi/chi/v5"
@@ -13,13 +15,14 @@ import (
)
type GetMemberResponse struct {
- ID xid.ID `json:"id"`
- SID string `json:"sid"`
- Name string `json:"name"`
- DisplayName *string `json:"display_name"`
- Bio *string `json:"bio"`
- Avatar *string `json:"avatar"`
- Links []string `json:"links"`
+ ID xid.ID `json:"id"`
+ SnowflakeID common.MemberID `json:"id_new"`
+ SID string `json:"sid"`
+ Name string `json:"name"`
+ DisplayName *string `json:"display_name"`
+ Bio *string `json:"bio"`
+ Avatar *string `json:"avatar"`
+ Links []string `json:"links"`
Names []db.FieldEntry `json:"names"`
Pronouns []db.PronounEntry `json:"pronouns"`
@@ -34,6 +37,7 @@ type GetMemberResponse struct {
func dbMemberToMember(u db.User, m db.Member, fields []db.Field, flags []db.MemberFlag, isOwnMember bool) GetMemberResponse {
r := GetMemberResponse{
ID: m.ID,
+ SnowflakeID: m.SnowflakeID,
SID: m.SID,
Name: m.Name,
DisplayName: m.DisplayName,
@@ -48,6 +52,7 @@ func dbMemberToMember(u db.User, m db.Member, fields []db.Field, flags []db.Memb
User: PartialUser{
ID: u.ID,
+ SnowflakeID: u.SnowflakeID,
Username: u.Username,
DisplayName: u.DisplayName,
Avatar: u.Avatar,
@@ -64,26 +69,37 @@ func dbMemberToMember(u db.User, m db.Member, fields []db.Field, flags []db.Memb
type PartialUser struct {
ID xid.ID `json:"id"`
+ SnowflakeID common.UserID `json:"id_new"`
Username string `json:"name"`
DisplayName *string `json:"display_name"`
Avatar *string `json:"avatar"`
CustomPreferences db.CustomPreferences `json:"custom_preferences"`
}
-func (s *Server) getMember(w http.ResponseWriter, r *http.Request) error {
+func (s *Server) getMember(w http.ResponseWriter, r *http.Request) (err error) {
ctx := r.Context()
- id, err := xid.FromString(chi.URLParam(r, "memberRef"))
- if err != nil {
- return server.APIError{
- Code: server.ErrMemberNotFound,
+ var m db.Member
+ if id, err := xid.FromString(chi.URLParam(r, "memberRef")); err == nil {
+ m, err = s.DB.Member(ctx, id)
+ if err != nil {
+ log.Errorf("getting member by xid: %v", err)
}
}
+ // xid was not valid
+ if !m.SnowflakeID.IsValid() {
+ id, err := common.ParseSnowflake(chi.URLParam(r, "memberRef"))
+ if err != nil {
+ return server.APIError{
+ Code: server.ErrMemberNotFound,
+ }
+ }
- m, err := s.DB.Member(ctx, id)
- if err != nil {
- return server.APIError{
- Code: server.ErrMemberNotFound,
+ m, err = s.DB.MemberBySnowflake(ctx, common.MemberID(id))
+ if err != nil {
+ return server.APIError{
+ Code: server.ErrMemberNotFound,
+ }
}
}
@@ -186,12 +202,22 @@ func (s *Server) getMeMember(w http.ResponseWriter, r *http.Request) error {
}
func (s *Server) parseUser(ctx context.Context, userRef string) (u db.User, err error) {
- if id, err := xid.FromString(userRef); err != nil {
+ // check xid first
+ if id, err := xid.FromString(userRef); err == nil {
u, err := s.DB.User(ctx, id)
if err == nil {
return u, nil
}
}
+ // if not an xid, check by snowflake
+ if id, err := common.ParseSnowflake(userRef); err == nil {
+ u, err := s.DB.UserBySnowflake(ctx, common.UserID(id))
+ if err == nil {
+ return u, nil
+ }
+ }
+
+ // else, use username
return s.DB.Username(ctx, userRef)
}
diff --git a/backend/routes/v1/member/get_members.go b/backend/routes/v1/member/get_members.go
index 6b08239..6dba566 100644
--- a/backend/routes/v1/member/get_members.go
+++ b/backend/routes/v1/member/get_members.go
@@ -3,6 +3,7 @@ package member
import (
"net/http"
+ "codeberg.org/pronounscc/pronouns.cc/backend/common"
"codeberg.org/pronounscc/pronouns.cc/backend/db"
"codeberg.org/pronounscc/pronouns.cc/backend/server"
"github.com/go-chi/chi/v5"
@@ -12,6 +13,7 @@ import (
type memberListResponse struct {
ID xid.ID `json:"id"`
+ SnowflakeID common.MemberID `json:"id_new"`
SID string `json:"sid"`
Name string `json:"name"`
DisplayName *string `json:"display_name"`
@@ -28,6 +30,7 @@ func membersToMemberList(ms []db.Member, isSelf bool) []memberListResponse {
for i := range ms {
resps[i] = memberListResponse{
ID: ms[i].ID,
+ SnowflakeID: ms[i].SnowflakeID,
SID: ms[i].SID,
Name: ms[i].Name,
DisplayName: ms[i].DisplayName,
diff --git a/backend/routes/v1/member/patch_member.go b/backend/routes/v1/member/patch_member.go
index 5884efe..956eb13 100644
--- a/backend/routes/v1/member/patch_member.go
+++ b/backend/routes/v1/member/patch_member.go
@@ -38,23 +38,41 @@ func (s *Server) patchMember(w http.ResponseWriter, r *http.Request) error {
return server.APIError{Code: server.ErrMissingPermissions, Details: "This token is read-only"}
}
- id, err := xid.FromString(chi.URLParam(r, "memberRef"))
- if err != nil {
- return server.APIError{Code: server.ErrMemberNotFound}
- }
-
u, err := s.DB.User(ctx, claims.UserID)
if err != nil {
return errors.Wrap(err, "getting user")
}
- m, err := s.DB.Member(ctx, id)
- if err != nil {
- if err == db.ErrMemberNotFound {
+ var m db.Member
+ if id, err := xid.FromString(chi.URLParam(r, "memberRef")); err == nil {
+ log.Debugf("%v/%v is xid", chi.URLParam(r, "memberRef"), id)
+
+ m, err = s.DB.Member(ctx, id)
+ if err != nil {
+ if err == db.ErrMemberNotFound {
+ return server.APIError{Code: server.ErrMemberNotFound}
+ }
+
+ return errors.Wrap(err, "getting member")
+ }
+ } else {
+ id, err := common.ParseSnowflake(chi.URLParam(r, "memberRef"))
+ if err != nil {
+ log.Debugf("%v/%v is not valid snowflake", chi.URLParam(r, "memberRef"), id)
+
return server.APIError{Code: server.ErrMemberNotFound}
}
- return errors.Wrap(err, "getting member")
+ log.Debugf("%v/%v is valid snowflake", chi.URLParam(r, "memberRef"), id)
+
+ m, err = s.DB.MemberBySnowflake(ctx, common.MemberID(id))
+ if err != nil {
+ if err == db.ErrMemberNotFound {
+ return server.APIError{Code: server.ErrMemberNotFound}
+ }
+
+ return errors.Wrap(err, "getting member")
+ }
}
if m.UserID != claims.UserID {
@@ -234,7 +252,7 @@ func (s *Server) patchMember(w http.ResponseWriter, r *http.Request) error {
}
defer tx.Rollback(ctx)
- m, err = s.DB.UpdateMember(ctx, tx, id, req.Name, req.DisplayName, req.Bio, req.Unlisted, req.Links, avatarHash)
+ m, err = s.DB.UpdateMember(ctx, tx, m.ID, req.Name, req.DisplayName, req.Bio, req.Unlisted, req.Links, avatarHash)
if err != nil {
switch errors.Cause(err) {
case db.ErrNothingToUpdate:
@@ -258,9 +276,9 @@ func (s *Server) patchMember(w http.ResponseWriter, r *http.Request) error {
pronouns = *req.Pronouns
}
- err = s.DB.SetMemberNamesPronouns(ctx, tx, id, names, pronouns)
+ err = s.DB.SetMemberNamesPronouns(ctx, tx, m.ID, names, pronouns)
if err != nil {
- log.Errorf("setting names for member %v: %v", id, err)
+ log.Errorf("setting names for member %v: %v", m.ID, err)
return err
}
m.Names = names
@@ -269,16 +287,16 @@ func (s *Server) patchMember(w http.ResponseWriter, r *http.Request) error {
var fields []db.Field
if req.Fields != nil {
- err = s.DB.SetMemberFields(ctx, tx, id, *req.Fields)
+ err = s.DB.SetMemberFields(ctx, tx, m.ID, *req.Fields)
if err != nil {
- log.Errorf("setting fields for member %v: %v", id, err)
+ log.Errorf("setting fields for member %v: %v", m.ID, err)
return err
}
fields = *req.Fields
} else {
- fields, err = s.DB.MemberFields(ctx, id)
+ fields, err = s.DB.MemberFields(ctx, m.ID)
if err != nil {
- log.Errorf("getting fields for member %v: %v", id, err)
+ log.Errorf("getting fields for member %v: %v", m.ID, err)
return err
}
}
@@ -321,7 +339,7 @@ func (s *Server) patchMember(w http.ResponseWriter, r *http.Request) error {
return nil
}
-func (s *Server) rerollMemberSID(w http.ResponseWriter, r *http.Request) error {
+func (s *Server) rerollMemberSID(w http.ResponseWriter, r *http.Request) (err error) {
ctx := r.Context()
claims, _ := server.ClaimsFromContext(ctx)
@@ -330,9 +348,32 @@ func (s *Server) rerollMemberSID(w http.ResponseWriter, r *http.Request) error {
return server.APIError{Code: server.ErrMissingPermissions, Details: "This token is read-only"}
}
- id, err := xid.FromString(chi.URLParam(r, "memberRef"))
- if err != nil {
- return server.APIError{Code: server.ErrMemberNotFound}
+ var m db.Member
+ if id, err := xid.FromString(chi.URLParam(r, "memberRef")); err == nil {
+ m, err = s.DB.Member(ctx, id)
+ if err != nil {
+ if err == db.ErrMemberNotFound {
+ return server.APIError{Code: server.ErrMemberNotFound}
+ }
+
+ log.Errorf("getting user %v: %v", id, err)
+ return errors.Wrap(err, "getting user")
+ }
+ } else {
+ id, err := common.ParseSnowflake(chi.URLParam(r, "memberRef"))
+ if err != nil {
+ return server.APIError{Code: server.ErrMemberNotFound}
+ }
+
+ m, err = s.DB.MemberBySnowflake(ctx, common.MemberID(id))
+ if err != nil {
+ if err == db.ErrMemberNotFound {
+ return server.APIError{Code: server.ErrMemberNotFound}
+ }
+
+ log.Errorf("getting user %v: %v", id, err)
+ return errors.Wrap(err, "getting user")
+ }
}
u, err := s.DB.User(ctx, claims.UserID)
@@ -340,15 +381,6 @@ func (s *Server) rerollMemberSID(w http.ResponseWriter, r *http.Request) error {
return errors.Wrap(err, "getting user")
}
- m, err := s.DB.Member(ctx, id)
- if err != nil {
- if err == db.ErrMemberNotFound {
- return server.APIError{Code: server.ErrMemberNotFound}
- }
-
- return errors.Wrap(err, "getting member")
- }
-
if m.UserID != claims.UserID {
return server.APIError{Code: server.ErrNotOwnMember}
}
diff --git a/backend/routes/v1/mod/create_report.go b/backend/routes/v1/mod/create_report.go
index c9b6377..30969a4 100644
--- a/backend/routes/v1/mod/create_report.go
+++ b/backend/routes/v1/mod/create_report.go
@@ -3,6 +3,7 @@ package mod
import (
"net/http"
+ "codeberg.org/pronounscc/pronouns.cc/backend/common"
"codeberg.org/pronounscc/pronouns.cc/backend/db"
"codeberg.org/pronounscc/pronouns.cc/backend/log"
"codeberg.org/pronounscc/pronouns.cc/backend/server"
@@ -18,7 +19,7 @@ type CreateReportRequest struct {
Reason string `json:"reason"`
}
-func (s *Server) createUserReport(w http.ResponseWriter, r *http.Request) error {
+func (s *Server) createUserReport(w http.ResponseWriter, r *http.Request) (err error) {
ctx := r.Context()
claims, _ := server.ClaimsFromContext(ctx)
@@ -26,19 +27,32 @@ func (s *Server) createUserReport(w http.ResponseWriter, r *http.Request) error
return server.APIError{Code: server.ErrMissingPermissions, Details: "This token is read-only"}
}
- userID, err := xid.FromString(chi.URLParam(r, "id"))
- if err != nil {
- return server.APIError{Code: server.ErrBadRequest, Details: "Invalid user ID"}
- }
+ var u db.User
+ if id, err := xid.FromString(chi.URLParam(r, "id")); err == nil {
+ u, err = s.DB.User(ctx, id)
+ if err != nil {
+ if err == db.ErrUserNotFound {
+ return server.APIError{Code: server.ErrUserNotFound}
+ }
- u, err := s.DB.User(ctx, userID)
- if err != nil {
- if err == db.ErrUserNotFound {
+ log.Errorf("getting user %v: %v", id, err)
+ return errors.Wrap(err, "getting user")
+ }
+ } else {
+ id, err := common.ParseSnowflake(chi.URLParam(r, "id"))
+ if err != nil {
return server.APIError{Code: server.ErrUserNotFound}
}
- log.Errorf("getting user %v: %v", userID, err)
- return errors.Wrap(err, "getting user")
+ u, err = s.DB.UserBySnowflake(ctx, common.UserID(id))
+ if err != nil {
+ if err == db.ErrUserNotFound {
+ return server.APIError{Code: server.ErrUserNotFound}
+ }
+
+ log.Errorf("getting user %v: %v", id, err)
+ return errors.Wrap(err, "getting user")
+ }
}
if u.DeletedAt != nil {
@@ -73,19 +87,32 @@ func (s *Server) createMemberReport(w http.ResponseWriter, r *http.Request) erro
return server.APIError{Code: server.ErrMissingPermissions, Details: "This token is read-only"}
}
- memberID, err := xid.FromString(chi.URLParam(r, "id"))
- if err != nil {
- return server.APIError{Code: server.ErrBadRequest, Details: "Invalid member ID"}
- }
+ var m db.Member
+ if id, err := xid.FromString(chi.URLParam(r, "id")); err == nil {
+ m, err = s.DB.Member(ctx, id)
+ if err != nil {
+ if err == db.ErrMemberNotFound {
+ return server.APIError{Code: server.ErrMemberNotFound}
+ }
- m, err := s.DB.Member(ctx, memberID)
- if err != nil {
- if err == db.ErrMemberNotFound {
- return server.APIError{Code: server.ErrMemberNotFound}
+ log.Errorf("getting user %v: %v", id, err)
+ return errors.Wrap(err, "getting user")
+ }
+ } else {
+ id, err := common.ParseSnowflake(chi.URLParam(r, "id"))
+ if err != nil {
+ return server.APIError{Code: server.ErrUserNotFound}
}
- log.Errorf("getting member %v: %v", memberID, err)
- return errors.Wrap(err, "getting member")
+ m, err = s.DB.MemberBySnowflake(ctx, common.MemberID(id))
+ if err != nil {
+ if err == db.ErrMemberNotFound {
+ return server.APIError{Code: server.ErrMemberNotFound}
+ }
+
+ log.Errorf("getting user %v: %v", id, err)
+ return errors.Wrap(err, "getting user")
+ }
}
u, err := s.DB.User(ctx, m.UserID)
diff --git a/backend/routes/v1/user/flags.go b/backend/routes/v1/user/flags.go
index 899a675..b9c3ced 100644
--- a/backend/routes/v1/user/flags.go
+++ b/backend/routes/v1/user/flags.go
@@ -1,6 +1,7 @@
package user
import (
+ "context"
"fmt"
"net/http"
"strings"
@@ -121,6 +122,24 @@ type patchUserFlagRequest struct {
Description *string `json:"description"`
}
+func (s *Server) parseFlag(ctx context.Context, flags []db.PrideFlag, flagRef string) (db.PrideFlag, bool) {
+ if id, err := xid.FromString(flagRef); err == nil {
+ for _, f := range flags {
+ if f.ID == id {
+ return f, true
+ }
+ }
+ }
+ if id, err := common.ParseSnowflake(flagRef); err == nil {
+ for _, f := range flags {
+ if f.SnowflakeID == common.FlagID(id) {
+ return f, true
+ }
+ }
+ }
+ return db.PrideFlag{}, false
+}
+
func (s *Server) patchUserFlag(w http.ResponseWriter, r *http.Request) error {
ctx := r.Context()
claims, _ := server.ClaimsFromContext(ctx)
@@ -129,28 +148,13 @@ func (s *Server) patchUserFlag(w http.ResponseWriter, r *http.Request) error {
return server.APIError{Code: server.ErrMissingPermissions, Details: "This token is read-only"}
}
- flagID, err := xid.FromString(chi.URLParam(r, "flagID"))
- if err != nil {
- return server.APIError{Code: server.ErrNotFound, Details: "Invalid flag ID"}
- }
-
flags, err := s.DB.AccountFlags(ctx, claims.UserID)
if err != nil {
return errors.Wrap(err, "getting current user flags")
}
- if len(flags) >= db.MaxPrideFlags {
- return server.APIError{
- Code: server.ErrFlagLimitReached,
- }
- }
- var found bool
- for _, flag := range flags {
- if flag.ID == flagID {
- found = true
- break
- }
- }
- if !found {
+
+ flag, ok := s.parseFlag(ctx, flags, chi.URLParam(r, "flagID"))
+ if !ok {
return server.APIError{Code: server.ErrNotFound, Details: "No flag with that ID found"}
}
@@ -190,7 +194,7 @@ func (s *Server) patchUserFlag(w http.ResponseWriter, r *http.Request) error {
}
defer tx.Rollback(ctx)
- flag, err := s.DB.EditFlag(ctx, tx, flagID, req.Name, req.Description, nil)
+ flag, err = s.DB.EditFlag(ctx, tx, flag.ID, req.Name, req.Description, nil)
if err != nil {
return errors.Wrap(err, "updating flag")
}
@@ -212,19 +216,16 @@ func (s *Server) deleteUserFlag(w http.ResponseWriter, r *http.Request) error {
return server.APIError{Code: server.ErrMissingPermissions, Details: "This token is read-only"}
}
- flagID, err := xid.FromString(chi.URLParam(r, "flagID"))
+ flags, err := s.DB.AccountFlags(ctx, claims.UserID)
if err != nil {
- return server.APIError{Code: server.ErrNotFound, Details: "Invalid flag ID"}
+ return errors.Wrap(err, "getting current user flags")
}
- flag, err := s.DB.UserFlag(ctx, flagID)
- if err != nil {
- if err == db.ErrFlagNotFound {
- return server.APIError{Code: server.ErrNotFound, Details: "Flag not found"}
- }
-
- return errors.Wrap(err, "getting flag object")
+ flag, ok := s.parseFlag(ctx, flags, chi.URLParam(r, "flagID"))
+ if !ok {
+ return server.APIError{Code: server.ErrNotFound, Details: "No flag with that ID found"}
}
+
if flag.UserID != claims.UserID {
return server.APIError{Code: server.ErrNotFound, Details: "Flag not found"}
}
diff --git a/backend/routes/v1/user/get_user.go b/backend/routes/v1/user/get_user.go
index d1163a3..af43a4b 100644
--- a/backend/routes/v1/user/get_user.go
+++ b/backend/routes/v1/user/get_user.go
@@ -4,6 +4,7 @@ import (
"net/http"
"time"
+ "codeberg.org/pronounscc/pronouns.cc/backend/common"
"codeberg.org/pronounscc/pronouns.cc/backend/db"
"codeberg.org/pronounscc/pronouns.cc/backend/log"
"codeberg.org/pronounscc/pronouns.cc/backend/server"
@@ -14,6 +15,7 @@ import (
type GetUserResponse struct {
ID xid.ID `json:"id"`
+ SnowflakeID common.UserID `json:"id_new"`
SID string `json:"sid"`
Username string `json:"name"`
DisplayName *string `json:"display_name"`
@@ -58,6 +60,7 @@ type GetMeResponse struct {
type PartialMember struct {
ID xid.ID `json:"id"`
+ SnowflakeID common.MemberID `json:"id_new"`
SID string `json:"sid"`
Name string `json:"name"`
DisplayName *string `json:"display_name"`
@@ -71,6 +74,7 @@ type PartialMember struct {
func dbUserToResponse(u db.User, fields []db.Field, members []db.Member, flags []db.UserFlag) GetUserResponse {
resp := GetUserResponse{
ID: u.ID,
+ SnowflakeID: u.SnowflakeID,
SID: u.SID,
Username: u.Username,
DisplayName: u.DisplayName,
@@ -97,6 +101,7 @@ func dbUserToResponse(u db.User, fields []db.Field, members []db.Member, flags [
for i := range members {
resp.Members[i] = PartialMember{
ID: members[i].ID,
+ SnowflakeID: members[i].SnowflakeID,
SID: members[i].SID,
Name: members[i].Name,
DisplayName: members[i].DisplayName,
@@ -124,6 +129,15 @@ func (s *Server) getUser(w http.ResponseWriter, r *http.Request) (err error) {
}
}
+ if u.ID.IsNil() {
+ if id, err := common.ParseSnowflake(userRef); err == nil {
+ u, err = s.DB.UserBySnowflake(ctx, common.UserID(id))
+ if err != nil {
+ log.Errorf("getting user by snowflake: %v", err)
+ }
+ }
+ }
+
if u.ID.IsNil() {
u, err = s.DB.Username(ctx, userRef)
if err == db.ErrUserNotFound {
diff --git a/frontend/src/lib/api/entities.ts b/frontend/src/lib/api/entities.ts
index b635c8b..1b3a776 100644
--- a/frontend/src/lib/api/entities.ts
+++ b/frontend/src/lib/api/entities.ts
@@ -7,6 +7,7 @@ export const MAX_FLAGS = 500;
export interface User {
id: string;
+ id_new: string;
sid: string;
name: string;
display_name: string | null;
@@ -79,6 +80,7 @@ export interface Pronoun {
export interface PartialMember {
id: string;
+ id_new: string;
sid: string;
name: string;
display_name: string | null;
@@ -99,6 +101,7 @@ export interface Member extends PartialMember {
export interface MemberPartialUser {
id: string;
+ id_new: string;
name: string;
display_name: string | null;
avatar: string | null;
@@ -107,6 +110,7 @@ export interface MemberPartialUser {
export interface PrideFlag {
id: string;
+ id_new: string;
hash: string;
name: string;
description: string | null;
diff --git a/frontend/src/routes/@[username]/+page.svelte b/frontend/src/routes/@[username]/+page.svelte
index 76da6de..56542fc 100644
--- a/frontend/src/routes/@[username]/+page.svelte
+++ b/frontend/src/routes/@[username]/+page.svelte
@@ -274,7 +274,7 @@
/>
{/if}
{#if $userStore && $userStore.id !== data.id}
-
+
{/if}
diff --git a/frontend/src/routes/@[username]/[memberName]/+page.svelte b/frontend/src/routes/@[username]/[memberName]/+page.svelte
index 9089959..cef3271 100644
--- a/frontend/src/routes/@[username]/[memberName]/+page.svelte
+++ b/frontend/src/routes/@[username]/[memberName]/+page.svelte
@@ -170,7 +170,7 @@
/>
{/if}
{#if $userStore && $userStore.id !== data.user.id}
-
+
{/if}
diff --git a/frontend/src/routes/@[username]/[memberName]/edit/+layout.svelte b/frontend/src/routes/@[username]/[memberName]/edit/+layout.svelte
index b5e98a3..df02160 100644
--- a/frontend/src/routes/@[username]/[memberName]/edit/+layout.svelte
+++ b/frontend/src/routes/@[username]/[memberName]/edit/+layout.svelte
@@ -34,7 +34,7 @@
const deleteMember = async () => {
try {
- await fastFetchClient(`/members/${data.member.id}`, "DELETE");
+ await fastFetchClient(`/members/${data.member.id_new}`, "DELETE");
toggleDeleteOpen();
addToast({
@@ -68,7 +68,7 @@
});
try {
- const resp = await apiFetchClient(`/members/${data.member.id}`, "PATCH", {
+ const resp = await apiFetchClient(`/members/${data.member.id_new}`, "PATCH", {
name: $member.name,
display_name: $member.display_name,
avatar: $member.avatar,
diff --git a/frontend/src/routes/@[username]/[memberName]/edit/other/+page.svelte b/frontend/src/routes/@[username]/[memberName]/edit/other/+page.svelte
index ca29a26..9f3f157 100644
--- a/frontend/src/routes/@[username]/[memberName]/edit/other/+page.svelte
+++ b/frontend/src/routes/@[username]/[memberName]/edit/other/+page.svelte
@@ -25,7 +25,7 @@
const rerollSid = async () => {
try {
- const resp = await apiFetchClient(`/members/${data.member.id}/reroll`);
+ const resp = await apiFetchClient(`/members/${data.member.id_new}/reroll`);
addToast({ header: "Success", body: "Rerolled short ID!" });
error = null;
$member.sid = resp.sid;
diff --git a/frontend/src/routes/reports/+page.ts b/frontend/src/routes/reports/+page.ts
index ee1743e..fdeef02 100644
--- a/frontend/src/routes/reports/+page.ts
+++ b/frontend/src/routes/reports/+page.ts
@@ -1,6 +1,5 @@
-import { ErrorCode, type APIError, type Report } from "$lib/api/entities";
+import type { Report } from "$lib/api/entities";
import { apiFetchClient } from "$lib/api/fetch";
-import { error } from "@sveltejs/kit";
export const load = async ({ url }) => {
const { searchParams } = url;
diff --git a/frontend/src/routes/settings/+page.svelte b/frontend/src/routes/settings/+page.svelte
index ee1f0a3..163698d 100644
--- a/frontend/src/routes/settings/+page.svelte
+++ b/frontend/src/routes/settings/+page.svelte
@@ -194,7 +194,11 @@
ID |
- {data.user.id} |
+ {data.user.id_new} |
+
+
+ xid (deprecated) |
+ {data.user.id} |
Account created at |
diff --git a/frontend/src/routes/settings/flags/+page.svelte b/frontend/src/routes/settings/flags/+page.svelte
index 4f69c8f..add8fa0 100644
--- a/frontend/src/routes/settings/flags/+page.svelte
+++ b/frontend/src/routes/settings/flags/+page.svelte
@@ -92,7 +92,7 @@
error = null;
addToast({ header: "Deleted flag", body: "Successfully deleted flag!" });
- data.flags = data.flags.filter((entry) => entry.id !== id);
+ data.flags = data.flags.filter((entry) => entry.id_new !== id);
} catch (e) {
error = e as APIError;
}
diff --git a/frontend/src/routes/settings/flags/Flag.svelte b/frontend/src/routes/settings/flags/Flag.svelte
index eab228f..a7ae53d 100644
--- a/frontend/src/routes/settings/flags/Flag.svelte
+++ b/frontend/src/routes/settings/flags/Flag.svelte
@@ -20,7 +20,7 @@
const updateFlag = async () => {
try {
- const resp = await apiFetchClient(`/users/@me/flags/${flag.id}`, "PATCH", {
+ const resp = await apiFetchClient(`/users/@me/flags/${flag.id_new}`, "PATCH", {
name,
description: description || null,
});
@@ -65,7 +65,7 @@
Are you sure you want to delete the {flag.name} flag? This cannot be undone!
-
+
diff --git a/main.go b/main.go
index 61cac6b..067aafd 100644
--- a/main.go
+++ b/main.go
@@ -13,6 +13,7 @@ import (
"codeberg.org/pronounscc/pronouns.cc/scripts/genkey"
"codeberg.org/pronounscc/pronouns.cc/scripts/migrate"
"codeberg.org/pronounscc/pronouns.cc/scripts/seeddb"
+ "codeberg.org/pronounscc/pronouns.cc/scripts/snowflakes"
"github.com/urfave/cli/v2"
)
@@ -32,6 +33,7 @@ var app = &cli.App{
migrate.Command,
seeddb.Command,
cleandb.Command,
+ snowflakes.Command,
},
},
{
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..fadb53c
--- /dev/null
+++ b/package.json
@@ -0,0 +1,12 @@
+{
+ "name": "pronouns",
+ "private": true,
+ "scripts": {
+ "dev": "concurrently \"air\" \"make dev\""
+ },
+ "author": "sam ",
+ "license": "AGPL-3.0-only",
+ "devDependencies": {
+ "concurrently": "^8.2.1"
+ }
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..23ad836
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,2462 @@
+lockfileVersion: '6.0'
+
+importers:
+
+ .:
+ devDependencies:
+ concurrently:
+ specifier: ^8.2.1
+ version: 8.2.1
+
+ frontend:
+ dependencies:
+ '@fontsource/firago':
+ specifier: ^4.5.3
+ version: 4.5.3
+ '@popperjs/core':
+ specifier: ^2.11.7
+ version: 2.11.7
+ '@sentry/node':
+ specifier: ^7.46.0
+ version: 7.46.0
+ base64-arraybuffer:
+ specifier: ^1.0.2
+ version: 1.0.2
+ bootstrap:
+ specifier: 5.3.0-alpha1
+ version: 5.3.0-alpha1(@popperjs/core@2.11.7)
+ bootstrap-icons:
+ specifier: ^1.10.4
+ version: 1.10.4
+ jose:
+ specifier: ^4.13.1
+ version: 4.13.1
+ luxon:
+ specifier: ^3.3.0
+ version: 3.3.0
+ markdown-it:
+ specifier: ^13.0.1
+ version: 13.0.1
+ pretty-bytes:
+ specifier: ^6.1.0
+ version: 6.1.0
+ sanitize-html:
+ specifier: ^2.10.0
+ version: 2.10.0
+ devDependencies:
+ '@sveltejs/adapter-auto':
+ specifier: ^2.0.0
+ version: 2.0.0(@sveltejs/kit@1.15.0)
+ '@sveltejs/adapter-node':
+ specifier: ^1.2.3
+ version: 1.2.3(@sveltejs/kit@1.15.0)
+ '@sveltejs/kit':
+ specifier: ^1.15.0
+ version: 1.15.0(svelte@3.58.0)(vite@4.2.1)
+ '@types/luxon':
+ specifier: ^3.2.2
+ version: 3.2.2
+ '@types/markdown-it':
+ specifier: ^12.2.3
+ version: 12.2.3
+ '@types/node':
+ specifier: ^18.15.11
+ version: 18.15.11
+ '@types/sanitize-html':
+ specifier: ^2.9.0
+ version: 2.9.0
+ '@typescript-eslint/eslint-plugin':
+ specifier: ^5.57.1
+ version: 5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.37.0)(typescript@4.9.5)
+ '@typescript-eslint/parser':
+ specifier: ^5.57.1
+ version: 5.57.1(eslint@8.37.0)(typescript@4.9.5)
+ eslint:
+ specifier: ^8.37.0
+ version: 8.37.0
+ eslint-config-prettier:
+ specifier: ^8.8.0
+ version: 8.8.0(eslint@8.37.0)
+ eslint-plugin-svelte3:
+ specifier: ^4.0.0
+ version: 4.0.0(eslint@8.37.0)(svelte@3.58.0)
+ prettier:
+ specifier: ^2.8.7
+ version: 2.8.7
+ prettier-plugin-svelte:
+ specifier: ^2.10.0
+ version: 2.10.0(prettier@2.8.7)(svelte@3.58.0)
+ svelte:
+ specifier: ^3.58.0
+ version: 3.58.0
+ svelte-check:
+ specifier: ^3.1.4
+ version: 3.1.4(svelte@3.58.0)
+ svelte-hcaptcha:
+ specifier: ^0.1.1
+ version: 0.1.1
+ sveltestrap:
+ specifier: ^5.10.0
+ version: 5.10.0(svelte@3.58.0)
+ tslib:
+ specifier: ^2.5.0
+ version: 2.5.0
+ typescript:
+ specifier: ^4.9.5
+ version: 4.9.5
+ vite:
+ specifier: ^4.2.1
+ version: 4.2.1(@types/node@18.15.11)
+ vite-plugin-markdown:
+ specifier: ^2.1.0
+ version: 2.1.0(vite@4.2.1)
+
+packages:
+
+ /@aashutoshrathi/word-wrap@1.2.6:
+ resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /@babel/runtime@7.22.15:
+ resolution: {integrity: sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ regenerator-runtime: 0.14.0
+ dev: true
+
+ /@esbuild/android-arm64@0.17.19:
+ resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm@0.17.19:
+ resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-x64@0.17.19:
+ resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-arm64@0.17.19:
+ resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-x64@0.17.19:
+ resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-arm64@0.17.19:
+ resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-x64@0.17.19:
+ resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm64@0.17.19:
+ resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm@0.17.19:
+ resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ia32@0.17.19:
+ resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-loong64@0.17.19:
+ resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-mips64el@0.17.19:
+ resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ppc64@0.17.19:
+ resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-riscv64@0.17.19:
+ resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-s390x@0.17.19:
+ resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-x64@0.17.19:
+ resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/netbsd-x64@0.17.19:
+ resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/openbsd-x64@0.17.19:
+ resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/sunos-x64@0.17.19:
+ resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-arm64@0.17.19:
+ resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-ia32@0.17.19:
+ resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-x64@0.17.19:
+ resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@eslint-community/eslint-utils@4.4.0(eslint@8.37.0):
+ resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+ dependencies:
+ eslint: 8.37.0
+ eslint-visitor-keys: 3.4.3
+ dev: true
+
+ /@eslint-community/regexpp@4.8.0:
+ resolution: {integrity: sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==}
+ engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+ dev: true
+
+ /@eslint/eslintrc@2.1.2:
+ resolution: {integrity: sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ ajv: 6.12.6
+ debug: 4.3.4
+ espree: 9.6.1
+ globals: 13.21.0
+ ignore: 5.2.4
+ import-fresh: 3.3.0
+ js-yaml: 4.1.0
+ minimatch: 3.1.2
+ strip-json-comments: 3.1.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@eslint/js@8.37.0:
+ resolution: {integrity: sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
+ /@fontsource/firago@4.5.3:
+ resolution: {integrity: sha512-Kn6FBi6MGNPYwzVKUtgyWGUj0zV18El263ieZi8A7TM2LPKsfzON5ENeKfjyTKfYErkjg9ktwiNP3SLsEOSBNQ==}
+ dev: false
+
+ /@humanwhocodes/config-array@0.11.11:
+ resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==}
+ engines: {node: '>=10.10.0'}
+ dependencies:
+ '@humanwhocodes/object-schema': 1.2.1
+ debug: 4.3.4
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@humanwhocodes/module-importer@1.0.1:
+ resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
+ engines: {node: '>=12.22'}
+ dev: true
+
+ /@humanwhocodes/object-schema@1.2.1:
+ resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
+ dev: true
+
+ /@jridgewell/resolve-uri@3.1.1:
+ resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
+ engines: {node: '>=6.0.0'}
+ dev: true
+
+ /@jridgewell/sourcemap-codec@1.4.15:
+ resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
+ dev: true
+
+ /@jridgewell/trace-mapping@0.3.19:
+ resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==}
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.1
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: true
+
+ /@nodelib/fs.scandir@2.1.5:
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+ dev: true
+
+ /@nodelib/fs.stat@2.0.5:
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /@nodelib/fs.walk@1.2.8:
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.15.0
+ dev: true
+
+ /@polka/url@1.0.0-next.23:
+ resolution: {integrity: sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==}
+ dev: true
+
+ /@popperjs/core@2.11.7:
+ resolution: {integrity: sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==}
+
+ /@rollup/plugin-commonjs@24.1.0(rollup@3.29.0):
+ resolution: {integrity: sha512-eSL45hjhCWI0jCCXcNtLVqM5N1JlBGvlFfY0m6oOYnLCJ6N0qEXoZql4sY2MOUArzhH4SA/qBpTxvvZp2Sc+DQ==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ rollup: ^2.68.0||^3.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+ dependencies:
+ '@rollup/pluginutils': 5.0.4(rollup@3.29.0)
+ commondir: 1.0.1
+ estree-walker: 2.0.2
+ glob: 8.1.0
+ is-reference: 1.2.1
+ magic-string: 0.27.0
+ rollup: 3.29.0
+ dev: true
+
+ /@rollup/plugin-json@6.0.0(rollup@3.29.0):
+ resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ rollup: ^1.20.0||^2.0.0||^3.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+ dependencies:
+ '@rollup/pluginutils': 5.0.4(rollup@3.29.0)
+ rollup: 3.29.0
+ dev: true
+
+ /@rollup/plugin-node-resolve@15.2.1(rollup@3.29.0):
+ resolution: {integrity: sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ rollup: ^2.78.0||^3.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+ dependencies:
+ '@rollup/pluginutils': 5.0.4(rollup@3.29.0)
+ '@types/resolve': 1.20.2
+ deepmerge: 4.3.1
+ is-builtin-module: 3.2.1
+ is-module: 1.0.0
+ resolve: 1.22.4
+ rollup: 3.29.0
+ dev: true
+
+ /@rollup/pluginutils@5.0.4(rollup@3.29.0):
+ resolution: {integrity: sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ rollup: ^1.20.0||^2.0.0||^3.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+ dependencies:
+ '@types/estree': 1.0.1
+ estree-walker: 2.0.2
+ picomatch: 2.3.1
+ rollup: 3.29.0
+ dev: true
+
+ /@sentry-internal/tracing@7.46.0:
+ resolution: {integrity: sha512-KYoppa7PPL8Er7bdPoxTNUfIY804JL7hhOEomQHYD22rLynwQ4AaLm3YEY75QWwcGb0B7ZDMV+tSumW7Rxuwuw==}
+ engines: {node: '>=8'}
+ dependencies:
+ '@sentry/core': 7.46.0
+ '@sentry/types': 7.46.0
+ '@sentry/utils': 7.46.0
+ tslib: 1.14.1
+ dev: false
+
+ /@sentry/core@7.46.0:
+ resolution: {integrity: sha512-BnNHGh/ZTztqQedFko7vb2u6yLs/kWesOQNivav32ZbsEpVCjcmG1gOJXh2YmGIvj3jXOC9a4xfIuh+lYFcA6A==}
+ engines: {node: '>=8'}
+ dependencies:
+ '@sentry/types': 7.46.0
+ '@sentry/utils': 7.46.0
+ tslib: 1.14.1
+ dev: false
+
+ /@sentry/node@7.46.0:
+ resolution: {integrity: sha512-+GrgJMCye2WXGarRiU5IJHCK27xg7xbPc2XjGojBKbBoZfqxVAWbXEK4bnBQgRGP1pCmrU/M6ZhVgR3dP580xA==}
+ engines: {node: '>=8'}
+ dependencies:
+ '@sentry-internal/tracing': 7.46.0
+ '@sentry/core': 7.46.0
+ '@sentry/types': 7.46.0
+ '@sentry/utils': 7.46.0
+ cookie: 0.4.2
+ https-proxy-agent: 5.0.1
+ lru_map: 0.3.3
+ tslib: 1.14.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
+ /@sentry/types@7.46.0:
+ resolution: {integrity: sha512-2FMEMgt2h6u7AoELhNhu9L54GAh67KKfK2pJ1kEXJHmWxM9FSCkizjLs/t+49xtY7jEXr8qYq8bV967VfDPQ9g==}
+ engines: {node: '>=8'}
+ dev: false
+
+ /@sentry/utils@7.46.0:
+ resolution: {integrity: sha512-elRezDAF84guMG0OVIIZEWm6wUpgbda4HGks98CFnPsrnMm3N1bdBI9XdlxYLtf+ir5KsGR5YlEIf/a0kRUwAQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ '@sentry/types': 7.46.0
+ tslib: 1.14.1
+ dev: false
+
+ /@sveltejs/adapter-auto@2.0.0(@sveltejs/kit@1.15.0):
+ resolution: {integrity: sha512-b+gkHFZgD771kgV3aO4avHFd7y1zhmMYy9i6xOK7m/rwmwaRO8gnF5zBc0Rgca80B2PMU1bKNxyBTHA14OzUAQ==}
+ peerDependencies:
+ '@sveltejs/kit': ^1.0.0
+ dependencies:
+ '@sveltejs/kit': 1.15.0(svelte@3.58.0)(vite@4.2.1)
+ import-meta-resolve: 2.2.2
+ dev: true
+
+ /@sveltejs/adapter-node@1.2.3(@sveltejs/kit@1.15.0):
+ resolution: {integrity: sha512-Fv6NyVpVWYA63KRaV6dDjcU8ytcWFiUr0siJOoHl+oWy5WHNEuRiJOUdiZzYbZo8MmvFaCoxHkTgPrVQhpqaRA==}
+ peerDependencies:
+ '@sveltejs/kit': ^1.0.0
+ dependencies:
+ '@rollup/plugin-commonjs': 24.1.0(rollup@3.29.0)
+ '@rollup/plugin-json': 6.0.0(rollup@3.29.0)
+ '@rollup/plugin-node-resolve': 15.2.1(rollup@3.29.0)
+ '@sveltejs/kit': 1.15.0(svelte@3.58.0)(vite@4.2.1)
+ rollup: 3.29.0
+ dev: true
+
+ /@sveltejs/kit@1.15.0(svelte@3.58.0)(vite@4.2.1):
+ resolution: {integrity: sha512-fvDsW9msxWjDU/j9wwLlxEZ6cpXQYcmcQHq7neJMqibMEl39gI1ztVymGnYqM8KLqZXwNmhKtLu8EPheukKtXQ==}
+ engines: {node: ^16.14 || >=18}
+ hasBin: true
+ requiresBuild: true
+ peerDependencies:
+ svelte: ^3.54.0
+ vite: ^4.0.0
+ dependencies:
+ '@sveltejs/vite-plugin-svelte': 2.4.5(svelte@3.58.0)(vite@4.2.1)
+ '@types/cookie': 0.5.2
+ cookie: 0.5.0
+ devalue: 4.3.2
+ esm-env: 1.0.0
+ kleur: 4.1.5
+ magic-string: 0.30.3
+ mime: 3.0.0
+ sade: 1.8.1
+ set-cookie-parser: 2.6.0
+ sirv: 2.0.3
+ svelte: 3.58.0
+ tiny-glob: 0.2.9
+ undici: 5.21.0
+ vite: 4.2.1(@types/node@18.15.11)
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@sveltejs/vite-plugin-svelte-inspector@1.0.4(@sveltejs/vite-plugin-svelte@2.4.5)(svelte@3.58.0)(vite@4.2.1):
+ resolution: {integrity: sha512-zjiuZ3yydBtwpF3bj0kQNV0YXe+iKE545QGZVTaylW3eAzFr+pJ/cwK8lZEaRp4JtaJXhD5DyWAV4AxLh6DgaQ==}
+ engines: {node: ^14.18.0 || >= 16}
+ peerDependencies:
+ '@sveltejs/vite-plugin-svelte': ^2.2.0
+ svelte: ^3.54.0 || ^4.0.0
+ vite: ^4.0.0
+ dependencies:
+ '@sveltejs/vite-plugin-svelte': 2.4.5(svelte@3.58.0)(vite@4.2.1)
+ debug: 4.3.4
+ svelte: 3.58.0
+ vite: 4.2.1(@types/node@18.15.11)
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@sveltejs/vite-plugin-svelte@2.4.5(svelte@3.58.0)(vite@4.2.1):
+ resolution: {integrity: sha512-UJKsFNwhzCVuiZd06jM/psscyNJNDwjQC+qIeb7GBJK9iWeQCcIyfcPWDvbCudfcJggY9jtxJeeaZH7uny93FQ==}
+ engines: {node: ^14.18.0 || >= 16}
+ peerDependencies:
+ svelte: ^3.54.0 || ^4.0.0
+ vite: ^4.0.0
+ dependencies:
+ '@sveltejs/vite-plugin-svelte-inspector': 1.0.4(@sveltejs/vite-plugin-svelte@2.4.5)(svelte@3.58.0)(vite@4.2.1)
+ debug: 4.3.4
+ deepmerge: 4.3.1
+ kleur: 4.1.5
+ magic-string: 0.30.3
+ svelte: 3.58.0
+ svelte-hmr: 0.15.3(svelte@3.58.0)
+ vite: 4.2.1(@types/node@18.15.11)
+ vitefu: 0.2.4(vite@4.2.1)
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@types/cookie@0.5.2:
+ resolution: {integrity: sha512-DBpRoJGKJZn7RY92dPrgoMew8xCWc2P71beqsjyhEI/Ds9mOyVmBwtekyfhpwFIVt1WrxTonFifiOZ62V8CnNA==}
+ dev: true
+
+ /@types/estree@1.0.1:
+ resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==}
+ dev: true
+
+ /@types/json-schema@7.0.12:
+ resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==}
+ dev: true
+
+ /@types/linkify-it@3.0.3:
+ resolution: {integrity: sha512-pTjcqY9E4nOI55Wgpz7eiI8+LzdYnw3qxXCfHyBDdPbYvbyLgWLJGh8EdPvqawwMK1Uo1794AUkkR38Fr0g+2g==}
+ dev: true
+
+ /@types/luxon@3.2.2:
+ resolution: {integrity: sha512-CuF9hIlsxGpJO4EztrW23/q1L9ctQfb5JM9mnLCJhhA8z81K2b4LTVjQYySXWhFV5SMyUsPYH/IcvvXDCKwa2g==}
+ dev: true
+
+ /@types/markdown-it@12.2.3:
+ resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==}
+ dependencies:
+ '@types/linkify-it': 3.0.3
+ '@types/mdurl': 1.0.2
+ dev: true
+
+ /@types/mdurl@1.0.2:
+ resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==}
+ dev: true
+
+ /@types/node@18.15.11:
+ resolution: {integrity: sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==}
+ dev: true
+
+ /@types/pug@2.0.6:
+ resolution: {integrity: sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==}
+ dev: true
+
+ /@types/resolve@1.20.2:
+ resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
+ dev: true
+
+ /@types/sanitize-html@2.9.0:
+ resolution: {integrity: sha512-4fP/kEcKNj2u39IzrxWYuf/FnCCwwQCpif6wwY6ROUS1EPRIfWJjGkY3HIowY1EX/VbX5e86yq8AAE7UPMgATg==}
+ dependencies:
+ htmlparser2: 8.0.2
+ dev: true
+
+ /@types/semver@7.5.1:
+ resolution: {integrity: sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==}
+ dev: true
+
+ /@typescript-eslint/eslint-plugin@5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.37.0)(typescript@4.9.5):
+ resolution: {integrity: sha512-1MeobQkQ9tztuleT3v72XmY0XuKXVXusAhryoLuU5YZ+mXoYKZP9SQ7Flulh1NX4DTjpGTc2b/eMu4u7M7dhnQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ '@typescript-eslint/parser': ^5.0.0
+ eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@eslint-community/regexpp': 4.8.0
+ '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@4.9.5)
+ '@typescript-eslint/scope-manager': 5.57.1
+ '@typescript-eslint/type-utils': 5.57.1(eslint@8.37.0)(typescript@4.9.5)
+ '@typescript-eslint/utils': 5.57.1(eslint@8.37.0)(typescript@4.9.5)
+ debug: 4.3.4
+ eslint: 8.37.0
+ grapheme-splitter: 1.0.4
+ ignore: 5.2.4
+ natural-compare-lite: 1.4.0
+ semver: 7.5.4
+ tsutils: 3.21.0(typescript@4.9.5)
+ typescript: 4.9.5
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/parser@5.57.1(eslint@8.37.0)(typescript@4.9.5):
+ resolution: {integrity: sha512-hlA0BLeVSA/wBPKdPGxoVr9Pp6GutGoY380FEhbVi0Ph4WNe8kLvqIRx76RSQt1lynZKfrXKs0/XeEk4zZycuA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/scope-manager': 5.57.1
+ '@typescript-eslint/types': 5.57.1
+ '@typescript-eslint/typescript-estree': 5.57.1(typescript@4.9.5)
+ debug: 4.3.4
+ eslint: 8.37.0
+ typescript: 4.9.5
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/scope-manager@5.57.1:
+ resolution: {integrity: sha512-N/RrBwEUKMIYxSKl0oDK5sFVHd6VI7p9K5MyUlVYAY6dyNb/wHUqndkTd3XhpGlXgnQsBkRZuu4f9kAHghvgPw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ '@typescript-eslint/types': 5.57.1
+ '@typescript-eslint/visitor-keys': 5.57.1
+ dev: true
+
+ /@typescript-eslint/type-utils@5.57.1(eslint@8.37.0)(typescript@4.9.5):
+ resolution: {integrity: sha512-/RIPQyx60Pt6ga86hKXesXkJ2WOS4UemFrmmq/7eOyiYjYv/MUSHPlkhU6k9T9W1ytnTJueqASW+wOmW4KrViw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: '*'
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/typescript-estree': 5.57.1(typescript@4.9.5)
+ '@typescript-eslint/utils': 5.57.1(eslint@8.37.0)(typescript@4.9.5)
+ debug: 4.3.4
+ eslint: 8.37.0
+ tsutils: 3.21.0(typescript@4.9.5)
+ typescript: 4.9.5
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/types@5.57.1:
+ resolution: {integrity: sha512-bSs4LOgyV3bJ08F5RDqO2KXqg3WAdwHCu06zOqcQ6vqbTJizyBhuh1o1ImC69X4bV2g1OJxbH71PJqiO7Y1RuA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
+ /@typescript-eslint/typescript-estree@5.57.1(typescript@4.9.5):
+ resolution: {integrity: sha512-A2MZqD8gNT0qHKbk2wRspg7cHbCDCk2tcqt6ScCFLr5Ru8cn+TCfM786DjPhqwseiS+PrYwcXht5ztpEQ6TFTw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/types': 5.57.1
+ '@typescript-eslint/visitor-keys': 5.57.1
+ debug: 4.3.4
+ globby: 11.1.0
+ is-glob: 4.0.3
+ semver: 7.5.4
+ tsutils: 3.21.0(typescript@4.9.5)
+ typescript: 4.9.5
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/utils@5.57.1(eslint@8.37.0)(typescript@4.9.5):
+ resolution: {integrity: sha512-kN6vzzf9NkEtawECqze6v99LtmDiUJCVpvieTFA1uL7/jDghiJGubGZ5csicYHU1Xoqb3oH/R5cN5df6W41Nfg==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.37.0)
+ '@types/json-schema': 7.0.12
+ '@types/semver': 7.5.1
+ '@typescript-eslint/scope-manager': 5.57.1
+ '@typescript-eslint/types': 5.57.1
+ '@typescript-eslint/typescript-estree': 5.57.1(typescript@4.9.5)
+ eslint: 8.37.0
+ eslint-scope: 5.1.1
+ semver: 7.5.4
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+ dev: true
+
+ /@typescript-eslint/visitor-keys@5.57.1:
+ resolution: {integrity: sha512-RjQrAniDU0CEk5r7iphkm731zKlFiUjvcBS2yHAg8WWqFMCaCrD0rKEVOMUyMMcbGPZ0bPp56srkGWrgfZqLRA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ '@typescript-eslint/types': 5.57.1
+ eslint-visitor-keys: 3.4.3
+ dev: true
+
+ /acorn-jsx@5.3.2(acorn@8.10.0):
+ resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+ dependencies:
+ acorn: 8.10.0
+ dev: true
+
+ /acorn@8.10.0:
+ resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+ dev: true
+
+ /agent-base@6.0.2:
+ resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
+ engines: {node: '>= 6.0.0'}
+ dependencies:
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
+ /ajv@6.12.6:
+ resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-json-stable-stringify: 2.1.0
+ json-schema-traverse: 0.4.1
+ uri-js: 4.4.1
+ dev: true
+
+ /ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+ dependencies:
+ color-convert: 2.0.1
+ dev: true
+
+ /anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+ dev: true
+
+ /argparse@1.0.10:
+ resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
+ dependencies:
+ sprintf-js: 1.0.3
+ dev: true
+
+ /argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+
+ /array-union@2.1.0:
+ resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ dev: true
+
+ /base64-arraybuffer@1.0.2:
+ resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==}
+ engines: {node: '>= 0.6.0'}
+ dev: false
+
+ /binary-extensions@2.2.0:
+ resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /bootstrap-icons@1.10.4:
+ resolution: {integrity: sha512-eI3HyIUmpGKRiRv15FCZccV+2sreGE2NnmH8mtxV/nPOzQVu0sPEj8HhF1MwjJ31IhjF0rgMvtYOX5VqIzcb/A==}
+ dev: false
+
+ /bootstrap@5.3.0-alpha1(@popperjs/core@2.11.7):
+ resolution: {integrity: sha512-ABZpKK4ObS3kKlIqH+ZVDqoy5t/bhFG0oHTAzByUdon7YIom0lpCeTqRniDzJmbtcWkNe800VVPBiJgxSYTYew==}
+ peerDependencies:
+ '@popperjs/core': ^2.11.6
+ dependencies:
+ '@popperjs/core': 2.11.7
+ dev: false
+
+ /brace-expansion@1.1.11:
+ resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+ dev: true
+
+ /brace-expansion@2.0.1:
+ resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+ dependencies:
+ balanced-match: 1.0.2
+ dev: true
+
+ /braces@3.0.2:
+ resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
+ engines: {node: '>=8'}
+ dependencies:
+ fill-range: 7.0.1
+ dev: true
+
+ /buffer-crc32@0.2.13:
+ resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
+ dev: true
+
+ /builtin-modules@3.3.0:
+ resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /busboy@1.6.0:
+ resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
+ engines: {node: '>=10.16.0'}
+ dependencies:
+ streamsearch: 1.1.0
+ dev: true
+
+ /callsites@3.1.0:
+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+ dev: true
+
+ /chokidar@3.5.3:
+ resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
+ engines: {node: '>= 8.10.0'}
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.2
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.3
+ dev: true
+
+ /cliui@8.0.1:
+ resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+ dev: true
+
+ /color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+ dependencies:
+ color-name: 1.1.4
+ dev: true
+
+ /color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ dev: true
+
+ /commondir@1.0.1:
+ resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
+ dev: true
+
+ /concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+ dev: true
+
+ /concurrently@8.2.1:
+ resolution: {integrity: sha512-nVraf3aXOpIcNud5pB9M82p1tynmZkrSGQ1p6X/VY8cJ+2LMVqAgXsJxYYefACSHbTYlm92O1xuhdGTjwoEvbQ==}
+ engines: {node: ^14.13.0 || >=16.0.0}
+ hasBin: true
+ dependencies:
+ chalk: 4.1.2
+ date-fns: 2.30.0
+ lodash: 4.17.21
+ rxjs: 7.8.1
+ shell-quote: 1.8.1
+ spawn-command: 0.0.2
+ supports-color: 8.1.1
+ tree-kill: 1.2.2
+ yargs: 17.7.2
+ dev: true
+
+ /cookie@0.4.2:
+ resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==}
+ engines: {node: '>= 0.6'}
+ dev: false
+
+ /cookie@0.5.0:
+ resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
+ engines: {node: '>= 0.6'}
+ dev: true
+
+ /cross-spawn@7.0.3:
+ resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+ engines: {node: '>= 8'}
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+ dev: true
+
+ /date-fns@2.30.0:
+ resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
+ engines: {node: '>=0.11'}
+ dependencies:
+ '@babel/runtime': 7.22.15
+ dev: true
+
+ /debug@4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.2
+
+ /deep-is@0.1.4:
+ resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+ dev: true
+
+ /deepmerge@4.3.1:
+ resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
+ engines: {node: '>=0.10.0'}
+
+ /detect-indent@6.1.0:
+ resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /devalue@4.3.2:
+ resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==}
+ dev: true
+
+ /dir-glob@3.0.1:
+ resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
+ engines: {node: '>=8'}
+ dependencies:
+ path-type: 4.0.0
+ dev: true
+
+ /doctrine@3.0.0:
+ resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ esutils: 2.0.3
+ dev: true
+
+ /dom-serializer@1.4.1:
+ resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==}
+ dependencies:
+ domelementtype: 2.3.0
+ domhandler: 4.3.1
+ entities: 2.2.0
+ dev: true
+
+ /dom-serializer@2.0.0:
+ resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
+ dependencies:
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+ entities: 4.5.0
+
+ /domelementtype@2.3.0:
+ resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
+
+ /domhandler@4.3.1:
+ resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==}
+ engines: {node: '>= 4'}
+ dependencies:
+ domelementtype: 2.3.0
+ dev: true
+
+ /domhandler@5.0.3:
+ resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
+ engines: {node: '>= 4'}
+ dependencies:
+ domelementtype: 2.3.0
+
+ /domutils@2.8.0:
+ resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
+ dependencies:
+ dom-serializer: 1.4.1
+ domelementtype: 2.3.0
+ domhandler: 4.3.1
+ dev: true
+
+ /domutils@3.1.0:
+ resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==}
+ dependencies:
+ dom-serializer: 2.0.0
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+
+ /emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+ dev: true
+
+ /entities@2.1.0:
+ resolution: {integrity: sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==}
+ dev: true
+
+ /entities@2.2.0:
+ resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==}
+ dev: true
+
+ /entities@3.0.1:
+ resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==}
+ engines: {node: '>=0.12'}
+ dev: false
+
+ /entities@4.5.0:
+ resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
+ engines: {node: '>=0.12'}
+
+ /es6-promise@3.3.1:
+ resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==}
+ dev: true
+
+ /esbuild@0.17.19:
+ resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/android-arm': 0.17.19
+ '@esbuild/android-arm64': 0.17.19
+ '@esbuild/android-x64': 0.17.19
+ '@esbuild/darwin-arm64': 0.17.19
+ '@esbuild/darwin-x64': 0.17.19
+ '@esbuild/freebsd-arm64': 0.17.19
+ '@esbuild/freebsd-x64': 0.17.19
+ '@esbuild/linux-arm': 0.17.19
+ '@esbuild/linux-arm64': 0.17.19
+ '@esbuild/linux-ia32': 0.17.19
+ '@esbuild/linux-loong64': 0.17.19
+ '@esbuild/linux-mips64el': 0.17.19
+ '@esbuild/linux-ppc64': 0.17.19
+ '@esbuild/linux-riscv64': 0.17.19
+ '@esbuild/linux-s390x': 0.17.19
+ '@esbuild/linux-x64': 0.17.19
+ '@esbuild/netbsd-x64': 0.17.19
+ '@esbuild/openbsd-x64': 0.17.19
+ '@esbuild/sunos-x64': 0.17.19
+ '@esbuild/win32-arm64': 0.17.19
+ '@esbuild/win32-ia32': 0.17.19
+ '@esbuild/win32-x64': 0.17.19
+ dev: true
+
+ /escalade@3.1.1:
+ resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+
+ /eslint-config-prettier@8.8.0(eslint@8.37.0):
+ resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==}
+ hasBin: true
+ peerDependencies:
+ eslint: '>=7.0.0'
+ dependencies:
+ eslint: 8.37.0
+ dev: true
+
+ /eslint-plugin-svelte3@4.0.0(eslint@8.37.0)(svelte@3.58.0):
+ resolution: {integrity: sha512-OIx9lgaNzD02+MDFNLw0GEUbuovNcglg+wnd/UY0fbZmlQSz7GlQiQ1f+yX0XvC07XPcDOnFcichqI3xCwp71g==}
+ peerDependencies:
+ eslint: '>=8.0.0'
+ svelte: ^3.2.0
+ dependencies:
+ eslint: 8.37.0
+ svelte: 3.58.0
+ dev: true
+
+ /eslint-scope@5.1.1:
+ resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
+ engines: {node: '>=8.0.0'}
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 4.3.0
+ dev: true
+
+ /eslint-scope@7.2.2:
+ resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 5.3.0
+ dev: true
+
+ /eslint-visitor-keys@3.4.3:
+ resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
+ /eslint@8.37.0:
+ resolution: {integrity: sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ hasBin: true
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.37.0)
+ '@eslint-community/regexpp': 4.8.0
+ '@eslint/eslintrc': 2.1.2
+ '@eslint/js': 8.37.0
+ '@humanwhocodes/config-array': 0.11.11
+ '@humanwhocodes/module-importer': 1.0.1
+ '@nodelib/fs.walk': 1.2.8
+ ajv: 6.12.6
+ chalk: 4.1.2
+ cross-spawn: 7.0.3
+ debug: 4.3.4
+ doctrine: 3.0.0
+ escape-string-regexp: 4.0.0
+ eslint-scope: 7.2.2
+ eslint-visitor-keys: 3.4.3
+ espree: 9.6.1
+ esquery: 1.5.0
+ esutils: 2.0.3
+ fast-deep-equal: 3.1.3
+ file-entry-cache: 6.0.1
+ find-up: 5.0.0
+ glob-parent: 6.0.2
+ globals: 13.21.0
+ grapheme-splitter: 1.0.4
+ ignore: 5.2.4
+ import-fresh: 3.3.0
+ imurmurhash: 0.1.4
+ is-glob: 4.0.3
+ is-path-inside: 3.0.3
+ js-sdsl: 4.4.2
+ js-yaml: 4.1.0
+ json-stable-stringify-without-jsonify: 1.0.1
+ levn: 0.4.1
+ lodash.merge: 4.6.2
+ minimatch: 3.1.2
+ natural-compare: 1.4.0
+ optionator: 0.9.3
+ strip-ansi: 6.0.1
+ strip-json-comments: 3.1.1
+ text-table: 0.2.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /esm-env@1.0.0:
+ resolution: {integrity: sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==}
+ dev: true
+
+ /espree@9.6.1:
+ resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ acorn: 8.10.0
+ acorn-jsx: 5.3.2(acorn@8.10.0)
+ eslint-visitor-keys: 3.4.3
+ dev: true
+
+ /esprima@4.0.1:
+ resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
+ engines: {node: '>=4'}
+ hasBin: true
+ dev: true
+
+ /esquery@1.5.0:
+ resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
+ engines: {node: '>=0.10'}
+ dependencies:
+ estraverse: 5.3.0
+ dev: true
+
+ /esrecurse@4.3.0:
+ resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+ engines: {node: '>=4.0'}
+ dependencies:
+ estraverse: 5.3.0
+ dev: true
+
+ /estraverse@4.3.0:
+ resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==}
+ engines: {node: '>=4.0'}
+ dev: true
+
+ /estraverse@5.3.0:
+ resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+ engines: {node: '>=4.0'}
+ dev: true
+
+ /estree-walker@2.0.2:
+ resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+ dev: true
+
+ /esutils@2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+ dev: true
+
+ /fast-glob@3.3.1:
+ resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==}
+ engines: {node: '>=8.6.0'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.5
+ dev: true
+
+ /fast-json-stable-stringify@2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+ dev: true
+
+ /fast-levenshtein@2.0.6:
+ resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+ dev: true
+
+ /fastq@1.15.0:
+ resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==}
+ dependencies:
+ reusify: 1.0.4
+ dev: true
+
+ /file-entry-cache@6.0.1:
+ resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
+ engines: {node: ^10.12.0 || >=12.0.0}
+ dependencies:
+ flat-cache: 3.1.0
+ dev: true
+
+ /fill-range@7.0.1:
+ resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ to-regex-range: 5.0.1
+ dev: true
+
+ /find-up@5.0.0:
+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+ engines: {node: '>=10'}
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+ dev: true
+
+ /flat-cache@3.1.0:
+ resolution: {integrity: sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==}
+ engines: {node: '>=12.0.0'}
+ dependencies:
+ flatted: 3.2.7
+ keyv: 4.5.3
+ rimraf: 3.0.2
+ dev: true
+
+ /flatted@3.2.7:
+ resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
+ dev: true
+
+ /front-matter@4.0.2:
+ resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==}
+ dependencies:
+ js-yaml: 3.14.1
+ dev: true
+
+ /fs.realpath@1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+ dev: true
+
+ /fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /function-bind@1.1.1:
+ resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
+ dev: true
+
+ /get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+ dev: true
+
+ /glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
+ /glob-parent@6.0.2:
+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+ engines: {node: '>=10.13.0'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
+ /glob@7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+ dev: true
+
+ /glob@8.1.0:
+ resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 5.1.6
+ once: 1.4.0
+ dev: true
+
+ /globals@13.21.0:
+ resolution: {integrity: sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==}
+ engines: {node: '>=8'}
+ dependencies:
+ type-fest: 0.20.2
+ dev: true
+
+ /globalyzer@0.1.0:
+ resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==}
+ dev: true
+
+ /globby@11.1.0:
+ resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
+ engines: {node: '>=10'}
+ dependencies:
+ array-union: 2.1.0
+ dir-glob: 3.0.1
+ fast-glob: 3.3.1
+ ignore: 5.2.4
+ merge2: 1.4.1
+ slash: 3.0.0
+ dev: true
+
+ /globrex@0.1.2:
+ resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
+ dev: true
+
+ /graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+ dev: true
+
+ /grapheme-splitter@1.0.4:
+ resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==}
+ dev: true
+
+ /has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /has@1.0.3:
+ resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
+ engines: {node: '>= 0.4.0'}
+ dependencies:
+ function-bind: 1.1.1
+ dev: true
+
+ /htmlparser2@6.1.0:
+ resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==}
+ dependencies:
+ domelementtype: 2.3.0
+ domhandler: 4.3.1
+ domutils: 2.8.0
+ entities: 2.2.0
+ dev: true
+
+ /htmlparser2@8.0.2:
+ resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==}
+ dependencies:
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+ domutils: 3.1.0
+ entities: 4.5.0
+
+ /https-proxy-agent@5.0.1:
+ resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
+ engines: {node: '>= 6'}
+ dependencies:
+ agent-base: 6.0.2
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
+ /ignore@5.2.4:
+ resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
+ engines: {node: '>= 4'}
+ dev: true
+
+ /import-fresh@3.3.0:
+ resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
+ engines: {node: '>=6'}
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+ dev: true
+
+ /import-meta-resolve@2.2.2:
+ resolution: {integrity: sha512-f8KcQ1D80V7RnqVm+/lirO9zkOxjGxhaTC1IPrBGd3MEfNgmNG67tSUO9gTi2F3Blr2Az6g1vocaxzkVnWl9MA==}
+ dev: true
+
+ /imurmurhash@0.1.4:
+ resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+ engines: {node: '>=0.8.19'}
+ dev: true
+
+ /inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+ dev: true
+
+ /inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+ dev: true
+
+ /is-binary-path@2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+ dependencies:
+ binary-extensions: 2.2.0
+ dev: true
+
+ /is-builtin-module@3.2.1:
+ resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==}
+ engines: {node: '>=6'}
+ dependencies:
+ builtin-modules: 3.3.0
+ dev: true
+
+ /is-core-module@2.13.0:
+ resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==}
+ dependencies:
+ has: 1.0.3
+ dev: true
+
+ /is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ is-extglob: 2.1.1
+ dev: true
+
+ /is-module@1.0.0:
+ resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==}
+ dev: true
+
+ /is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+ dev: true
+
+ /is-path-inside@3.0.3:
+ resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-plain-object@5.0.0:
+ resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
+ engines: {node: '>=0.10.0'}
+ dev: false
+
+ /is-reference@1.2.1:
+ resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
+ dependencies:
+ '@types/estree': 1.0.1
+ dev: true
+
+ /isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ dev: true
+
+ /jose@4.13.1:
+ resolution: {integrity: sha512-MSJQC5vXco5Br38mzaQKiq9mwt7lwj2eXpgpRyQYNHYt2lq1PjkWa7DLXX0WVcQLE9HhMh3jPiufS7fhJf+CLQ==}
+ dev: false
+
+ /js-sdsl@4.4.2:
+ resolution: {integrity: sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==}
+ dev: true
+
+ /js-yaml@3.14.1:
+ resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
+ hasBin: true
+ dependencies:
+ argparse: 1.0.10
+ esprima: 4.0.1
+ dev: true
+
+ /js-yaml@4.1.0:
+ resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
+ hasBin: true
+ dependencies:
+ argparse: 2.0.1
+ dev: true
+
+ /json-buffer@3.0.1:
+ resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+ dev: true
+
+ /json-schema-traverse@0.4.1:
+ resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+ dev: true
+
+ /json-stable-stringify-without-jsonify@1.0.1:
+ resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+ dev: true
+
+ /keyv@4.5.3:
+ resolution: {integrity: sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==}
+ dependencies:
+ json-buffer: 3.0.1
+ dev: true
+
+ /kleur@4.1.5:
+ resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /levn@0.4.1:
+ resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ dev: true
+
+ /linkify-it@3.0.3:
+ resolution: {integrity: sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==}
+ dependencies:
+ uc.micro: 1.0.6
+ dev: true
+
+ /linkify-it@4.0.1:
+ resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==}
+ dependencies:
+ uc.micro: 1.0.6
+ dev: false
+
+ /locate-path@6.0.0:
+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-locate: 5.0.0
+ dev: true
+
+ /lodash.merge@4.6.2:
+ resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+ dev: true
+
+ /lodash@4.17.21:
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+ dev: true
+
+ /lru-cache@6.0.0:
+ resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
+ engines: {node: '>=10'}
+ dependencies:
+ yallist: 4.0.0
+ dev: true
+
+ /lru_map@0.3.3:
+ resolution: {integrity: sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==}
+ dev: false
+
+ /luxon@3.3.0:
+ resolution: {integrity: sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==}
+ engines: {node: '>=12'}
+ dev: false
+
+ /magic-string@0.27.0:
+ resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==}
+ engines: {node: '>=12'}
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: true
+
+ /magic-string@0.30.3:
+ resolution: {integrity: sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==}
+ engines: {node: '>=12'}
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: true
+
+ /markdown-it@12.3.2:
+ resolution: {integrity: sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==}
+ hasBin: true
+ dependencies:
+ argparse: 2.0.1
+ entities: 2.1.0
+ linkify-it: 3.0.3
+ mdurl: 1.0.1
+ uc.micro: 1.0.6
+ dev: true
+
+ /markdown-it@13.0.1:
+ resolution: {integrity: sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==}
+ hasBin: true
+ dependencies:
+ argparse: 2.0.1
+ entities: 3.0.1
+ linkify-it: 4.0.1
+ mdurl: 1.0.1
+ uc.micro: 1.0.6
+ dev: false
+
+ /mdurl@1.0.1:
+ resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==}
+
+ /merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /micromatch@4.0.5:
+ resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+ engines: {node: '>=8.6'}
+ dependencies:
+ braces: 3.0.2
+ picomatch: 2.3.1
+ dev: true
+
+ /mime@3.0.0:
+ resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
+ engines: {node: '>=10.0.0'}
+ hasBin: true
+ dev: true
+
+ /min-indent@1.0.1:
+ resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+ dependencies:
+ brace-expansion: 1.1.11
+ dev: true
+
+ /minimatch@5.1.6:
+ resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
+ engines: {node: '>=10'}
+ dependencies:
+ brace-expansion: 2.0.1
+ dev: true
+
+ /minimist@1.2.8:
+ resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+ dev: true
+
+ /mkdirp@0.5.6:
+ resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
+ hasBin: true
+ dependencies:
+ minimist: 1.2.8
+ dev: true
+
+ /mri@1.2.0:
+ resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /mrmime@1.0.1:
+ resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /ms@2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+
+ /nanoid@3.3.6:
+ resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ /natural-compare-lite@1.4.0:
+ resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
+ dev: true
+
+ /natural-compare@1.4.0:
+ resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+ dev: true
+
+ /normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+ dependencies:
+ wrappy: 1.0.2
+ dev: true
+
+ /optionator@0.9.3:
+ resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ '@aashutoshrathi/word-wrap': 1.2.6
+ deep-is: 0.1.4
+ fast-levenshtein: 2.0.6
+ levn: 0.4.1
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ dev: true
+
+ /p-limit@3.1.0:
+ resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ yocto-queue: 0.1.0
+ dev: true
+
+ /p-locate@5.0.0:
+ resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-limit: 3.1.0
+ dev: true
+
+ /parent-module@1.0.1:
+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+ engines: {node: '>=6'}
+ dependencies:
+ callsites: 3.1.0
+ dev: true
+
+ /parse-srcset@1.0.2:
+ resolution: {integrity: sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==}
+ dev: false
+
+ /path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-parse@1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+ dev: true
+
+ /path-type@4.0.0:
+ resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /picocolors@1.0.0:
+ resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+
+ /picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+ dev: true
+
+ /postcss@8.4.29:
+ resolution: {integrity: sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.6
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+
+ /prelude-ls@1.2.1:
+ resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+ engines: {node: '>= 0.8.0'}
+ dev: true
+
+ /prettier-plugin-svelte@2.10.0(prettier@2.8.7)(svelte@3.58.0):
+ resolution: {integrity: sha512-GXMY6t86thctyCvQq+jqElO+MKdB09BkL3hexyGP3Oi8XLKRFaJP1ud/xlWCZ9ZIa2BxHka32zhHfcuU+XsRQg==}
+ peerDependencies:
+ prettier: ^1.16.4 || ^2.0.0
+ svelte: ^3.2.0
+ dependencies:
+ prettier: 2.8.7
+ svelte: 3.58.0
+ dev: true
+
+ /prettier@2.8.7:
+ resolution: {integrity: sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==}
+ engines: {node: '>=10.13.0'}
+ hasBin: true
+ dev: true
+
+ /pretty-bytes@6.1.0:
+ resolution: {integrity: sha512-Rk753HI8f4uivXi4ZCIYdhmG1V+WKzvRMg/X+M42a6t7D07RcmopXJMDNk6N++7Bl75URRGsb40ruvg7Hcp2wQ==}
+ engines: {node: ^14.13.1 || >=16.0.0}
+ dev: false
+
+ /punycode@2.3.0:
+ resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+ dev: true
+
+ /readdirp@3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+ dependencies:
+ picomatch: 2.3.1
+ dev: true
+
+ /regenerator-runtime@0.14.0:
+ resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==}
+ dev: true
+
+ /require-directory@2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /resolve-from@4.0.0:
+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /resolve@1.22.4:
+ resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.13.0
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+ dev: true
+
+ /reusify@1.0.4:
+ resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ dev: true
+
+ /rimraf@2.7.1:
+ resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
+ hasBin: true
+ dependencies:
+ glob: 7.2.3
+ dev: true
+
+ /rimraf@3.0.2:
+ resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+ hasBin: true
+ dependencies:
+ glob: 7.2.3
+ dev: true
+
+ /rollup@3.29.0:
+ resolution: {integrity: sha512-nszM8DINnx1vSS+TpbWKMkxem0CDWk3cSit/WWCBVs9/JZ1I/XLwOsiUglYuYReaeWWSsW9kge5zE5NZtf/a4w==}
+ engines: {node: '>=14.18.0', npm: '>=8.0.0'}
+ hasBin: true
+ optionalDependencies:
+ fsevents: 2.3.3
+ dev: true
+
+ /run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ dependencies:
+ queue-microtask: 1.2.3
+ dev: true
+
+ /rxjs@7.8.1:
+ resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
+ dependencies:
+ tslib: 2.5.0
+ dev: true
+
+ /sade@1.8.1:
+ resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
+ engines: {node: '>=6'}
+ dependencies:
+ mri: 1.2.0
+ dev: true
+
+ /sander@0.5.1:
+ resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==}
+ dependencies:
+ es6-promise: 3.3.1
+ graceful-fs: 4.2.11
+ mkdirp: 0.5.6
+ rimraf: 2.7.1
+ dev: true
+
+ /sanitize-html@2.10.0:
+ resolution: {integrity: sha512-JqdovUd81dG4k87vZt6uA6YhDfWkUGruUu/aPmXLxXi45gZExnt9Bnw/qeQU8oGf82vPyaE0vO4aH0PbobB9JQ==}
+ dependencies:
+ deepmerge: 4.3.1
+ escape-string-regexp: 4.0.0
+ htmlparser2: 8.0.2
+ is-plain-object: 5.0.0
+ parse-srcset: 1.0.2
+ postcss: 8.4.29
+ dev: false
+
+ /semver@7.5.4:
+ resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dependencies:
+ lru-cache: 6.0.0
+ dev: true
+
+ /set-cookie-parser@2.6.0:
+ resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==}
+ dev: true
+
+ /shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+ dependencies:
+ shebang-regex: 3.0.0
+ dev: true
+
+ /shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /shell-quote@1.8.1:
+ resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==}
+ dev: true
+
+ /sirv@2.0.3:
+ resolution: {integrity: sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==}
+ engines: {node: '>= 10'}
+ dependencies:
+ '@polka/url': 1.0.0-next.23
+ mrmime: 1.0.1
+ totalist: 3.0.1
+ dev: true
+
+ /slash@3.0.0:
+ resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /sorcery@0.11.0:
+ resolution: {integrity: sha512-J69LQ22xrQB1cIFJhPfgtLuI6BpWRiWu1Y3vSsIwK/eAScqJxd/+CJlUuHQRdX2C9NGFamq+KqNywGgaThwfHw==}
+ hasBin: true
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.4.15
+ buffer-crc32: 0.2.13
+ minimist: 1.2.8
+ sander: 0.5.1
+ dev: true
+
+ /source-map-js@1.0.2:
+ resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
+ engines: {node: '>=0.10.0'}
+
+ /spawn-command@0.0.2:
+ resolution: {integrity: sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==}
+ dev: true
+
+ /sprintf-js@1.0.3:
+ resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
+ dev: true
+
+ /streamsearch@1.1.0:
+ resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
+ engines: {node: '>=10.0.0'}
+ dev: true
+
+ /string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+ dev: true
+
+ /strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+ dependencies:
+ ansi-regex: 5.0.1
+ dev: true
+
+ /strip-indent@3.0.0:
+ resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ min-indent: 1.0.1
+ dev: true
+
+ /strip-json-comments@3.1.1:
+ resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+ dependencies:
+ has-flag: 4.0.0
+ dev: true
+
+ /supports-color@8.1.1:
+ resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
+ engines: {node: '>=10'}
+ dependencies:
+ has-flag: 4.0.0
+ dev: true
+
+ /supports-preserve-symlinks-flag@1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /svelte-check@3.1.4(svelte@3.58.0):
+ resolution: {integrity: sha512-25Lb46ZS4IK/XpBMe4IBMrtYf23V8alqBX+szXoccb7uM0D2Wqq5rMRzYBONZnFVuU1bQG3R50lyIT5eRewv2g==}
+ hasBin: true
+ peerDependencies:
+ svelte: ^3.55.0
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.19
+ chokidar: 3.5.3
+ fast-glob: 3.3.1
+ import-fresh: 3.3.0
+ picocolors: 1.0.0
+ sade: 1.8.1
+ svelte: 3.58.0
+ svelte-preprocess: 5.0.4(svelte@3.58.0)(typescript@4.9.5)
+ typescript: 4.9.5
+ transitivePeerDependencies:
+ - '@babel/core'
+ - coffeescript
+ - less
+ - postcss
+ - postcss-load-config
+ - pug
+ - sass
+ - stylus
+ - sugarss
+ dev: true
+
+ /svelte-hcaptcha@0.1.1:
+ resolution: {integrity: sha512-iFF3HwfrCRciJnDs4Y9/rpP/BM2U/5zt+vh+9d4tALPAHVkcANiJIKqYuS835pIaTm6gt+xOzjfFI3cgiRI29A==}
+ dev: true
+
+ /svelte-hmr@0.15.3(svelte@3.58.0):
+ resolution: {integrity: sha512-41snaPswvSf8TJUhlkoJBekRrABDXDMdpNpT2tfHIv4JuhgvHqLMhEPGtaQn0BmbNSTkuz2Ed20DF2eHw0SmBQ==}
+ engines: {node: ^12.20 || ^14.13.1 || >= 16}
+ peerDependencies:
+ svelte: ^3.19.0 || ^4.0.0
+ dependencies:
+ svelte: 3.58.0
+ dev: true
+
+ /svelte-preprocess@5.0.4(svelte@3.58.0)(typescript@4.9.5):
+ resolution: {integrity: sha512-ABia2QegosxOGsVlsSBJvoWeXy1wUKSfF7SWJdTjLAbx/Y3SrVevvvbFNQqrSJw89+lNSsM58SipmZJ5SRi5iw==}
+ engines: {node: '>= 14.10.0'}
+ requiresBuild: true
+ peerDependencies:
+ '@babel/core': ^7.10.2
+ coffeescript: ^2.5.1
+ less: ^3.11.3 || ^4.0.0
+ postcss: ^7 || ^8
+ postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0
+ pug: ^3.0.0
+ sass: ^1.26.8
+ stylus: ^0.55.0
+ sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0
+ svelte: ^3.23.0 || ^4.0.0-next.0 || ^4.0.0
+ typescript: '>=3.9.5 || ^4.0.0 || ^5.0.0'
+ peerDependenciesMeta:
+ '@babel/core':
+ optional: true
+ coffeescript:
+ optional: true
+ less:
+ optional: true
+ postcss:
+ optional: true
+ postcss-load-config:
+ optional: true
+ pug:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ typescript:
+ optional: true
+ dependencies:
+ '@types/pug': 2.0.6
+ detect-indent: 6.1.0
+ magic-string: 0.27.0
+ sorcery: 0.11.0
+ strip-indent: 3.0.0
+ svelte: 3.58.0
+ typescript: 4.9.5
+ dev: true
+
+ /svelte@3.58.0:
+ resolution: {integrity: sha512-brIBNNB76mXFmU/Kerm4wFnkskBbluBDCjx/8TcpYRb298Yh2dztS2kQ6bhtjMcvUhd5ynClfwpz5h2gnzdQ1A==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /sveltestrap@5.10.0(svelte@3.58.0):
+ resolution: {integrity: sha512-k6Ob+6G2AMYvBidXHBKM9W28fJqFHbmosqCe/NC8pv6TV7K+v47Yw+zmnLWkjqCzzmjkSLkL48SrHZrlWc9mYQ==}
+ peerDependencies:
+ svelte: ^3.29.0
+ dependencies:
+ '@popperjs/core': 2.11.7
+ svelte: 3.58.0
+ dev: true
+
+ /text-table@0.2.0:
+ resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
+ dev: true
+
+ /tiny-glob@0.2.9:
+ resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==}
+ dependencies:
+ globalyzer: 0.1.0
+ globrex: 0.1.2
+ dev: true
+
+ /to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+ dependencies:
+ is-number: 7.0.0
+ dev: true
+
+ /totalist@3.0.1:
+ resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /tree-kill@1.2.2:
+ resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+ hasBin: true
+ dev: true
+
+ /tslib@1.14.1:
+ resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
+
+ /tslib@2.5.0:
+ resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==}
+ dev: true
+
+ /tsutils@3.21.0(typescript@4.9.5):
+ resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
+ engines: {node: '>= 6'}
+ peerDependencies:
+ typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
+ dependencies:
+ tslib: 1.14.1
+ typescript: 4.9.5
+ dev: true
+
+ /type-check@0.4.0:
+ resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ prelude-ls: 1.2.1
+ dev: true
+
+ /type-fest@0.20.2:
+ resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /typescript@4.9.5:
+ resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==}
+ engines: {node: '>=4.2.0'}
+ hasBin: true
+ dev: true
+
+ /uc.micro@1.0.6:
+ resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==}
+
+ /undici@5.21.0:
+ resolution: {integrity: sha512-HOjK8l6a57b2ZGXOcUsI5NLfoTrfmbOl90ixJDl0AEFG4wgHNDQxtZy15/ZQp7HhjkpaGlp/eneMgtsu1dIlUA==}
+ engines: {node: '>=12.18'}
+ dependencies:
+ busboy: 1.6.0
+ dev: true
+
+ /uri-js@4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+ dependencies:
+ punycode: 2.3.0
+ dev: true
+
+ /vite-plugin-markdown@2.1.0(vite@4.2.1):
+ resolution: {integrity: sha512-eWLlrWzYZXEX3/HaXZo/KLjRpO72IUhbgaoFrbwB07ueXi6QfwqrgdZQfUcXTSofJCkN7GhErMC1K1RTAE0gGQ==}
+ peerDependencies:
+ vite: ^2.0.0 || ^3.0.0
+ dependencies:
+ front-matter: 4.0.2
+ htmlparser2: 6.1.0
+ markdown-it: 12.3.2
+ vite: 4.2.1(@types/node@18.15.11)
+ dev: true
+
+ /vite@4.2.1(@types/node@18.15.11):
+ resolution: {integrity: sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': '>= 14'
+ less: '*'
+ sass: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ dependencies:
+ '@types/node': 18.15.11
+ esbuild: 0.17.19
+ postcss: 8.4.29
+ resolve: 1.22.4
+ rollup: 3.29.0
+ optionalDependencies:
+ fsevents: 2.3.3
+ dev: true
+
+ /vitefu@0.2.4(vite@4.2.1):
+ resolution: {integrity: sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==}
+ peerDependencies:
+ vite: ^3.0.0 || ^4.0.0
+ peerDependenciesMeta:
+ vite:
+ optional: true
+ dependencies:
+ vite: 4.2.1(@types/node@18.15.11)
+ dev: true
+
+ /which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+ dependencies:
+ isexe: 2.0.0
+ dev: true
+
+ /wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ dev: true
+
+ /wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+ dev: true
+
+ /y18n@5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /yallist@4.0.0:
+ resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+ dev: true
+
+ /yargs-parser@21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /yargs@17.7.2:
+ resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+ engines: {node: '>=12'}
+ dependencies:
+ cliui: 8.0.1
+ escalade: 3.1.1
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 21.1.1
+ dev: true
+
+ /yocto-queue@0.1.0:
+ resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+ engines: {node: '>=10'}
+ dev: true
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 0000000..2bac25d
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,3 @@
+packages:
+ - docs
+ - frontend
diff --git a/scripts/migrate/021_snowflakes.sql b/scripts/migrate/021_snowflakes.sql
new file mode 100644
index 0000000..76777c0
--- /dev/null
+++ b/scripts/migrate/021_snowflakes.sql
@@ -0,0 +1,13 @@
+-- 2023-08-17: Add snowflake ID columns
+
+-- +migrate Up
+
+alter table users add column snowflake_id bigint unique;
+alter table members add column snowflake_id bigint unique;
+alter table pride_flags add column snowflake_id bigint unique;
+
+-- +migrate Down
+
+alter table users drop column snowflake_id;
+alter table members drop column snowflake_id;
+alter table pride_flags drop column snowflake_id;
diff --git a/scripts/snowflakes/main.go b/scripts/snowflakes/main.go
new file mode 100644
index 0000000..382035a
--- /dev/null
+++ b/scripts/snowflakes/main.go
@@ -0,0 +1,111 @@
+package snowflakes
+
+import (
+ "os"
+ "time"
+
+ "codeberg.org/pronounscc/pronouns.cc/backend/common"
+ "codeberg.org/pronounscc/pronouns.cc/backend/log"
+ "github.com/georgysavva/scany/v2/pgxscan"
+ "github.com/jackc/pgx/v5"
+ "github.com/joho/godotenv"
+ "github.com/rs/xid"
+ "github.com/urfave/cli/v2"
+)
+
+var Command = &cli.Command{
+ Name: "create-snowflakes",
+ Usage: "Give all users, members, and flags snowflake IDs.",
+ Action: run,
+}
+
+func run(c *cli.Context) error {
+ err := godotenv.Load()
+ if err != nil {
+ log.Error("loading .env file:", err)
+ return err
+ }
+
+ conn, err := pgx.Connect(c.Context, os.Getenv("DATABASE_URL"))
+ if err != nil {
+ log.Error("opening database:", err)
+ return err
+ }
+ defer conn.Close(c.Context)
+ log.Info("opened database")
+
+ tx, err := conn.Begin(c.Context)
+ if err != nil {
+ log.Error("creating transaction:", err)
+ return err
+ }
+ defer tx.Rollback(c.Context)
+
+ var userIDs []xid.ID
+ err = pgxscan.Select(c.Context, conn, &userIDs, "SELECT id FROM users WHERE snowflake_id IS NULL")
+ if err != nil {
+ log.Error("selecting users without snowflake:", err)
+ return err
+ }
+
+ t := time.Now()
+ for _, userID := range userIDs {
+ t := userID.Time()
+ snowflake := common.UserID(common.GenerateIDWithTime(t))
+
+ _, err = tx.Exec(c.Context, "UPDATE users SET snowflake_id = $1 WHERE id = $2", snowflake, userID)
+ if err != nil {
+ log.Errorf("updating user with ID %v: %v", userID, err)
+ return err
+ }
+ }
+ log.Infof("updated %v users in %v", len(userIDs), time.Since(t))
+
+ var memberIDs []xid.ID
+ err = pgxscan.Select(c.Context, conn, &memberIDs, "SELECT id FROM members WHERE snowflake_id IS NULL")
+ if err != nil {
+ log.Error("selecting users without snowflake:", err)
+ return err
+ }
+
+ t = time.Now()
+ for _, memberID := range memberIDs {
+ t := memberID.Time()
+ snowflake := common.MemberID(common.GenerateIDWithTime(t))
+
+ _, err = tx.Exec(c.Context, "UPDATE members SET snowflake_id = $1 WHERE id = $2", snowflake, memberID)
+ if err != nil {
+ log.Errorf("updating user with ID %v: %v", memberID, err)
+ return err
+ }
+ }
+ log.Infof("updated %v members in %v", len(memberIDs), time.Since(t))
+
+ var flagIDs []xid.ID
+ err = pgxscan.Select(c.Context, conn, &flagIDs, "SELECT id FROM pride_flags WHERE snowflake_id IS NULL")
+ if err != nil {
+ log.Error("selecting users without snowflake:", err)
+ return err
+ }
+
+ t = time.Now()
+ for _, flagID := range flagIDs {
+ t := flagID.Time()
+ snowflake := common.FlagID(common.GenerateIDWithTime(t))
+
+ _, err = tx.Exec(c.Context, "UPDATE pride_flags SET snowflake_id = $1 WHERE id = $2", snowflake, flagID)
+ if err != nil {
+ log.Errorf("updating user with ID %v: %v", flagID, err)
+ return err
+ }
+ }
+ log.Infof("updated %v flags in %v", len(flagIDs), time.Since(t))
+
+ err = tx.Commit(c.Context)
+ if err != nil {
+ log.Error("committing transaction:", err)
+ return err
+ }
+
+ return nil
+}