From 400d5a36c1a9ba516e6118a590b7116a6193da66 Mon Sep 17 00:00:00 2001 From: Ralph Slooten Date: Sat, 17 Feb 2024 11:12:37 +1300 Subject: [PATCH 01/11] Chore: Better handling of automatic database compression (vacuuming) after deleting messages --- internal/storage/cron.go | 160 +++++++++++++++++++++++++++++++++ internal/storage/database.go | 15 ++-- internal/storage/migrations.go | 12 +++ internal/storage/search.go | 2 +- internal/storage/settings.go | 75 ++++++++++++++++ internal/storage/utils.go | 129 +------------------------- 6 files changed, 256 insertions(+), 137 deletions(-) create mode 100644 internal/storage/cron.go create mode 100644 internal/storage/settings.go diff --git a/internal/storage/cron.go b/internal/storage/cron.go new file mode 100644 index 000000000..8309d186d --- /dev/null +++ b/internal/storage/cron.go @@ -0,0 +1,160 @@ +package storage + +import ( + "context" + "database/sql" + "strings" + "time" + + "github.com/axllent/mailpit/config" + "github.com/axllent/mailpit/internal/logger" + "github.com/axllent/mailpit/server/websockets" + "github.com/leporo/sqlf" +) + +// Database cron runs every minute +func dbCron() { + for { + time.Sleep(60 * time.Second) + + currentTime := time.Now() + sinceLastDbAction := currentTime.Sub(dbLastAction) + + // only run the database has been idle for 5 minutes + if sinceLastDbAction.Minutes() >= 5 { + deletedSize := getDeletedSize() + + if deletedSize > 0 { + total := totalMessagesSize() + deletedPercent := deletedSize * 100 / total + // only vacuum the DB if at least 1% of mail storage size has been deleted + if deletedPercent >= 1 { + logger.Log().Debugf("[db] deleted messages is %d%% of total size, reclaim space", deletedPercent) + vacuumDb() + } + } + } + + pruneMessages() + } +} + +// PruneMessages will auto-delete the oldest messages if messages > config.MaxMessages. +// Set config.MaxMessages to 0 to disable. +func pruneMessages() { + if config.MaxMessages < 1 { + return + } + + start := time.Now() + + q := sqlf.Select("ID, Size"). + From("mailbox"). + OrderBy("Created DESC"). + Limit(5000). + Offset(config.MaxMessages) + + ids := []string{} + var prunedSize int64 + var size int + if err := q.Query(nil, db, func(row *sql.Rows) { + var id string + + if err := row.Scan(&id, &size); err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + return + } + ids = append(ids, id) + prunedSize = prunedSize + int64(size) + + }); err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + return + } + + if len(ids) == 0 { + return + } + + tx, err := db.BeginTx(context.Background(), nil) + if err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + return + } + + args := make([]interface{}, len(ids)) + for i, id := range ids { + args[i] = id + } + + _, err = tx.Query(`DELETE FROM mailbox WHERE ID IN (?`+strings.Repeat(",?", len(ids)-1)+`)`, args...) // #nosec + if err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + return + } + + _, err = tx.Query(`DELETE FROM mailbox_data WHERE ID IN (?`+strings.Repeat(",?", len(ids)-1)+`)`, args...) // #nosec + if err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + return + } + + _, err = tx.Query(`DELETE FROM message_tags WHERE ID IN (?`+strings.Repeat(",?", len(ids)-1)+`)`, args...) // #nosec + if err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + return + } + + err = tx.Commit() + + if err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + if err := tx.Rollback(); err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + } + } + + if err := pruneUnusedTags(); err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + } + + addDeletedSize(prunedSize) + dbLastAction = time.Now() + + elapsed := time.Since(start) + logger.Log().Debugf("[db] auto-pruned %d messages in %s", len(ids), elapsed) + + logMessagesDeleted(len(ids)) + + websockets.Broadcast("prune", nil) +} + +// Vacuum the database to reclaim space from deleted messages +func vacuumDb() { + start := time.Now() + + // set WAL file checkpoint + if _, err := db.Exec("PRAGMA wal_checkpoint"); err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + return + } + + // vacuum database + if _, err := db.Exec("VACUUM"); err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + return + } + + // truncate WAL file + if _, err := db.Exec("PRAGMA wal_checkpoint(TRUNCATE)"); err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + return + } + + if err := SettingPut("DeletedSize", "0"); err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + } + + elapsed := time.Since(start) + logger.Log().Debugf("[db] vacuumed database in %s", elapsed) +} diff --git a/internal/storage/database.go b/internal/storage/database.go index b3c0189ac..c24c4d297 100644 --- a/internal/storage/database.go +++ b/internal/storage/database.go @@ -37,8 +37,6 @@ var ( dbFile string dbIsTemp bool dbLastAction time.Time - dbIsIdle bool - deletedSize int64 // zstd compression encoder & decoder dbEncoder, _ = zstd.NewWriter(nil) @@ -654,7 +652,7 @@ func DeleteOneMessage(id string) error { } dbLastAction = time.Now() - deletedSize = deletedSize + int64(m.Size) + addDeletedSize(int64(m.Size)) logMessagesDeleted(1) @@ -708,14 +706,13 @@ func DeleteAllMessages() error { return err } - _, err = db.Exec("VACUUM") - if err == nil { - elapsed := time.Since(start) - logger.Log().Debugf("[db] deleted %d messages in %s", total, elapsed) - } + elapsed := time.Since(start) + logger.Log().Debugf("[db] deleted %d messages in %s", total, elapsed) + + vacuumDb() dbLastAction = time.Now() - deletedSize = 0 + SettingPut("DeletedSize", "0") logMessagesDeleted(total) diff --git a/internal/storage/migrations.go b/internal/storage/migrations.go index dc84cecd1..8eb4a1095 100644 --- a/internal/storage/migrations.go +++ b/internal/storage/migrations.go @@ -88,6 +88,18 @@ var ( CREATE INDEX IF NOT EXISTS idx_message_tag_id ON message_tags (ID); CREATE INDEX IF NOT EXISTS idx_message_tag_tagid ON message_tags (TagID);`, }, + { + // assume deleted messages account for 50% of storage + // to handle previously-deleted messages + Version: 1.5, + Description: "Create settings table", + Script: `CREATE TABLE IF NOT EXISTS settings ( + Key TEXT, + Value TEXT + ); + CREATE UNIQUE INDEX IF NOT EXISTS idx_settings_key ON settings (Key); + INSERT INTO settings (Key, Value) VALUES("DeletedSize", (SELECT SUM(Size)/2 FROM mailbox));`, + }, } ) diff --git a/internal/storage/search.go b/internal/storage/search.go index d06591d65..db41826e2 100644 --- a/internal/storage/search.go +++ b/internal/storage/search.go @@ -193,7 +193,7 @@ func DeleteSearch(search string) error { } dbLastAction = time.Now() - deletedSize = deletedSize + int64(deleteSize) + addDeletedSize(int64(deleteSize)) logMessagesDeleted(total) diff --git a/internal/storage/settings.go b/internal/storage/settings.go new file mode 100644 index 000000000..d12cba118 --- /dev/null +++ b/internal/storage/settings.go @@ -0,0 +1,75 @@ +package storage + +import ( + "database/sql" + + "github.com/axllent/mailpit/internal/logger" + "github.com/leporo/sqlf" +) + +// SettingGet returns a setting string value, blank is it does not exist +func SettingGet(k string) string { + var result string + err := sqlf.From("settings"). + Select("Value").To(&result). + Where("Key = ?", k). + Limit(1). + QueryAndClose(nil, db, func(row *sql.Rows) {}) + if err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + return result + } + + return result +} + +// SettingPut sets a setting string value, inserting if new +func SettingPut(k, v string) error { + _, err := db.Exec("INSERT INTO settings (Key, Value) VALUES(?, ?) ON CONFLICT(Key) DO UPDATE SET Value = ?", k, v, v) + if err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + } + + return err +} + +// The total deleted message size as an int64 value +func getDeletedSize() int64 { + var result int64 + err := sqlf.From("settings"). + Select("Value").To(&result). + Where("Key = ?", "DeletedSize"). + Limit(1). + QueryAndClose(nil, db, func(row *sql.Rows) {}) + if err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + return result + } + + return result +} + +// The total raw non-compressed messages size in bytes of all messages in the database +func totalMessagesSize() int64 { + var result int64 + err := sqlf.From("mailbox"). + Select("SUM(Size)").To(&result). + QueryAndClose(nil, db, func(row *sql.Rows) {}) + if err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + return result + } + + return result +} + +// AddDeletedSize will add the value to the DeletedSize setting +func addDeletedSize(v int64) { + if _, err := db.Exec("INSERT OR IGNORE INTO settings (Key, Value) VALUES(?, ?)", "DeletedSize", 0); err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + } + + if _, err := db.Exec("UPDATE settings SET Value = Value + ? WHERE Key = ?", v, "DeletedSize"); err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + } +} diff --git a/internal/storage/utils.go b/internal/storage/utils.go index f9cf8cd34..6dbdd8bd7 100644 --- a/internal/storage/utils.go +++ b/internal/storage/utils.go @@ -1,21 +1,14 @@ package storage import ( - "context" - "database/sql" "net/mail" "os" "regexp" "strings" "sync" - "time" - "github.com/axllent/mailpit/config" "github.com/axllent/mailpit/internal/html2text" - "github.com/axllent/mailpit/internal/logger" - "github.com/axllent/mailpit/server/websockets" "github.com/jhillyerd/enmime" - "github.com/leporo/sqlf" ) var ( @@ -77,124 +70,6 @@ func cleanString(str string) string { return strings.ToLower(strings.Join(strings.Fields(strings.TrimSpace(str)), " ")) } -// Auto-prune runs every minute to automatically delete oldest messages -// if total is greater than the threshold -func dbCron() { - for { - time.Sleep(60 * time.Second) - start := time.Now() - - // check if database contains deleted data and has not been in use - // for 5 minutes, if so VACUUM - currentTime := time.Now() - diff := currentTime.Sub(dbLastAction) - - // get DB file size - fileInfo, err := os.Stat(config.DataFile) - if err != nil { - logger.Log().Errorf("[db] unable to stat database %s: %s", config.DataFile, err.Error()) - continue - } - - deletedPercent := deletedSize * 100 / fileInfo.Size() - - // only vacuum DB when at least 2% of mail storage size has been deleted - // as this saves a lot of CPU on large databases - if deletedPercent >= 1 && diff.Minutes() > 5 { - logger.Log().Debugf("[db] compressing database as %d%% has been deleted", deletedPercent) - deletedSize = 0 - _, err := db.Exec("VACUUM") - if err == nil { - elapsed := time.Since(start) - logger.Log().Debugf("[db] compressed idle database in %s", elapsed) - } - - continue - } - - if config.MaxMessages > 0 { - q := sqlf.Select("ID, Size"). - From("mailbox"). - OrderBy("Created DESC"). - Limit(5000). - Offset(config.MaxMessages) - - ids := []string{} - var prunedSize int64 - var size int - if err := q.Query(nil, db, func(row *sql.Rows) { - var id string - - if err := row.Scan(&id, &size); err != nil { - logger.Log().Errorf("[db] %s", err.Error()) - return - } - ids = append(ids, id) - prunedSize = prunedSize + int64(size) - - }); err != nil { - logger.Log().Errorf("[db] %s", err.Error()) - continue - } - - if len(ids) == 0 { - continue - } - - tx, err := db.BeginTx(context.Background(), nil) - if err != nil { - logger.Log().Errorf("[db] %s", err.Error()) - continue - } - - args := make([]interface{}, len(ids)) - for i, id := range ids { - args[i] = id - } - - _, err = tx.Query(`DELETE FROM mailbox WHERE ID IN (?`+strings.Repeat(",?", len(ids)-1)+`)`, args...) // #nosec - if err != nil { - logger.Log().Errorf("[db] %s", err.Error()) - continue - } - - _, err = tx.Query(`DELETE FROM mailbox_data WHERE ID IN (?`+strings.Repeat(",?", len(ids)-1)+`)`, args...) // #nosec - if err != nil { - logger.Log().Errorf("[db] %s", err.Error()) - continue - } - - _, err = tx.Query(`DELETE FROM message_tags WHERE ID IN (?`+strings.Repeat(",?", len(ids)-1)+`)`, args...) // #nosec - if err != nil { - logger.Log().Errorf("[db] %s", err.Error()) - continue - } - - err = tx.Commit() - - if err != nil { - logger.Log().Errorf("[db] %s", err.Error()) - if err := tx.Rollback(); err != nil { - logger.Log().Errorf("[db] %s", err.Error()) - } - } - - if err := pruneUnusedTags(); err != nil { - logger.Log().Errorf("[db] %s", err.Error()) - } - - deletedSize = deletedSize + prunedSize - - elapsed := time.Since(start) - logger.Log().Debugf("[db] auto-pruned %d messages in %s", len(ids), elapsed) - - logMessagesDeleted(len(ids)) - - websockets.Broadcast("prune", nil) - } - } -} - // LogMessagesDeleted logs the number of messages deleted func logMessagesDeleted(n int) { mu.Lock() @@ -212,7 +87,7 @@ func isFile(path string) bool { return true } -// InArray tests if a string in within an array. It is not case sensitive. +// Tests if a string is within an array. It is not case sensitive. func inArray(k string, arr []string) bool { k = strings.ToLower(k) for _, v := range arr { @@ -224,7 +99,7 @@ func inArray(k string, arr []string) bool { return false } -// escPercentChar replaces `%` with `%%` for SQL searches +// Convert `%` to `%%` for SQL searches func escPercentChar(s string) string { return strings.ReplaceAll(s, "%", "%%") } From b2a0d735726cfb14c68fe9c2d5d3f645986f8827 Mon Sep 17 00:00:00 2001 From: Ralph Slooten Date: Sat, 17 Feb 2024 11:48:42 +1300 Subject: [PATCH 02/11] Chore: Switch to short uuid format for database IDs --- go.mod | 3 ++- go.sum | 3 +++ internal/storage/database.go | 4 ++-- server/apiv1/api.go | 4 ++-- server/smtpd/smtpd.go | 4 ++-- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 0784caf1f..948104677 100644 --- a/go.mod +++ b/go.mod @@ -8,12 +8,12 @@ require ( github.com/axllent/semver v0.0.1 github.com/disintegration/imaging v1.6.2 github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47 - github.com/google/uuid v1.6.0 github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.1 github.com/jhillyerd/enmime v1.1.0 github.com/klauspost/compress v1.17.6 github.com/leporo/sqlf v1.4.0 + github.com/lithammer/shortuuid/v4 v4.0.0 github.com/mhale/smtpd v0.8.2 github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e github.com/sirupsen/logrus v1.9.3 @@ -36,6 +36,7 @@ require ( github.com/cznic/ql v1.2.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/css v1.0.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 // indirect diff --git a/go.sum b/go.sum index 3bd3cdf71..2d7f0d6ea 100644 --- a/go.sum +++ b/go.sum @@ -55,6 +55,7 @@ github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47 h1:k4Tw0nt6lwr github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= @@ -83,6 +84,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leporo/sqlf v1.4.0 h1:SyWnX/8GSGOzVmanG0Ub1c04mR9nNl6Tq3IeFKX2/4c= github.com/leporo/sqlf v1.4.0/go.mod h1:pgN9yKsAnQ+2ewhbZogr98RcasUjPsHF3oXwPPhHvBw= +github.com/lithammer/shortuuid/v4 v4.0.0 h1:QRbbVkfgNippHOS8PXDkti4NaWeyYfcBTHtw7k08o4c= +github.com/lithammer/shortuuid/v4 v4.0.0/go.mod h1:Zs8puNcrvf2rV9rTH51ZLLcj7ZXqQI3lv67aw4KiB1Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= diff --git a/internal/storage/database.go b/internal/storage/database.go index c24c4d297..22b758494 100644 --- a/internal/storage/database.go +++ b/internal/storage/database.go @@ -23,10 +23,10 @@ import ( "github.com/axllent/mailpit/internal/tools" "github.com/axllent/mailpit/server/webhook" "github.com/axllent/mailpit/server/websockets" - "github.com/google/uuid" "github.com/jhillyerd/enmime" "github.com/klauspost/compress/zstd" "github.com/leporo/sqlf" + "github.com/lithammer/shortuuid/v4" // sqlite (native) - https://gitlab.com/cznic/sqlite _ "modernc.org/sqlite" @@ -166,7 +166,7 @@ func Store(body *[]byte) (string, error) { searchText := createSearchText(env) // generate unique ID - id := uuid.New().String() + id := shortuuid.New() summaryJSON, err := json.Marshal(obj) if err != nil { diff --git a/server/apiv1/api.go b/server/apiv1/api.go index 453592e12..cf185e699 100644 --- a/server/apiv1/api.go +++ b/server/apiv1/api.go @@ -19,8 +19,8 @@ import ( "github.com/axllent/mailpit/internal/storage" "github.com/axllent/mailpit/internal/tools" "github.com/axllent/mailpit/server/smtpd" - "github.com/google/uuid" "github.com/gorilla/mux" + "github.com/lithammer/shortuuid/v4" ) // GetMessages returns a paginated list of messages as JSON @@ -696,7 +696,7 @@ func ReleaseMessage(w http.ResponseWriter, r *http.Request) { } // generate unique ID - uid := uuid.New().String() + "@mailpit" + uid := shortuuid.New() + "@mailpit" // update Message-Id with unique ID msg, err = tools.UpdateMessageHeader(msg, "Message-Id", "<"+uid+">") if err != nil { diff --git a/server/smtpd/smtpd.go b/server/smtpd/smtpd.go index 23ec6f31b..e9fb0f400 100644 --- a/server/smtpd/smtpd.go +++ b/server/smtpd/smtpd.go @@ -14,7 +14,7 @@ import ( "github.com/axllent/mailpit/internal/logger" "github.com/axllent/mailpit/internal/stats" "github.com/axllent/mailpit/internal/storage" - "github.com/google/uuid" + "github.com/lithammer/shortuuid/v4" "github.com/mhale/smtpd" ) @@ -63,7 +63,7 @@ func mailHandler(origin net.Addr, from string, to []string, data []byte) error { // add a message ID if not set if messageID == "" { // generate unique ID - messageID = uuid.New().String() + "@mailpit" + messageID = shortuuid.New() + "@mailpit" // add unique ID data = append([]byte("Message-Id: <"+messageID+">\r\n"), data...) } else if config.IgnoreDuplicateIDs { From 26a209567490585f4e693085c31a6a348c22da17 Mon Sep 17 00:00:00 2001 From: Ralph Slooten Date: Sat, 17 Feb 2024 12:38:30 +1300 Subject: [PATCH 03/11] Chore: Security improvements (gosec) --- cmd/root.go | 8 ++++++-- config/config.go | 14 +++++++++++++- internal/linkcheck/status.go | 2 +- internal/logger/logger.go | 3 ++- internal/storage/database.go | 4 +++- internal/storage/search.go | 6 +++--- internal/updater/updater.go | 4 ++-- server/handlers/proxy.go | 6 ++++-- server/server.go | 11 +++++++++-- server/smtpd/smtp.go | 2 +- 10 files changed, 44 insertions(+), 16 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 48d5cd419..f9629786c 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -154,13 +154,17 @@ func initConfigFromEnv() { // UI config.UIAuthFile = os.Getenv("MP_UI_AUTH_FILE") - auth.SetUIAuth(os.Getenv("MP_UI_AUTH")) + if err := auth.SetUIAuth(os.Getenv("MP_UI_AUTH")); err != nil { + logger.Log().Errorf(err.Error()) + } config.UITLSCert = os.Getenv("MP_UI_TLS_CERT") config.UITLSKey = os.Getenv("MP_UI_TLS_KEY") // SMTP config.SMTPAuthFile = os.Getenv("MP_SMTP_AUTH_FILE") - auth.SetSMTPAuth(os.Getenv("MP_SMTP_AUTH")) + if err := auth.SetSMTPAuth(os.Getenv("MP_SMTP_AUTH")); err != nil { + logger.Log().Errorf(err.Error()) + } config.SMTPTLSCert = os.Getenv("MP_SMTP_TLS_CERT") config.SMTPTLSKey = os.Getenv("MP_SMTP_TLS_KEY") if getEnabledFromEnv("MP_SMTP_TLS_REQUIRED") { diff --git a/config/config.go b/config/config.go index 59639b2e8..9b5ad8cf9 100644 --- a/config/config.go +++ b/config/config.go @@ -179,13 +179,17 @@ func VerifyConfig() error { } if UIAuthFile != "" { + UIAuthFile = filepath.Clean(UIAuthFile) + if !isFile(UIAuthFile) { return fmt.Errorf("[ui] HTTP password file not found: %s", UIAuthFile) } + b, err := os.ReadFile(UIAuthFile) if err != nil { return err } + if err := auth.SetUIAuth(string(b)); err != nil { return err } @@ -196,6 +200,8 @@ func VerifyConfig() error { } if UITLSCert != "" { + UITLSCert = filepath.Clean(UITLSCert) + if !isFile(UITLSCert) { return fmt.Errorf("[ui] TLS certificate not found: %s", UITLSCert) } @@ -210,6 +216,8 @@ func VerifyConfig() error { } if SMTPTLSCert != "" { + SMTPTLSCert = filepath.Clean(SMTPTLSCert) + if !isFile(SMTPTLSCert) { return fmt.Errorf("[smtp] TLS certificate not found: %s", SMTPTLSCert) } @@ -226,6 +234,8 @@ func VerifyConfig() error { } if SMTPAuthFile != "" { + SMTPAuthFile = filepath.Clean(SMTPAuthFile) + if !isFile(SMTPAuthFile) { return fmt.Errorf("[smtp] password file not found: %s", SMTPAuthFile) } @@ -324,8 +334,10 @@ func parseRelayConfig(c string) error { return nil } + c = filepath.Clean(c) + if !isFile(c) { - return fmt.Errorf("[smtp] relay configuration not found: %s", SMTPRelayConfigFile) + return fmt.Errorf("[smtp] relay configuration not found: %s", c) } data, err := os.ReadFile(c) diff --git a/internal/linkcheck/status.go b/internal/linkcheck/status.go index 102f61931..e3b59c801 100644 --- a/internal/linkcheck/status.go +++ b/internal/linkcheck/status.go @@ -63,7 +63,7 @@ func doHead(link string, followRedirects bool) (int, error) { tr := &http.Transport{} if config.AllowUntrustedTLS { - tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} // #nosec } client := http.Client{ diff --git a/internal/logger/logger.go b/internal/logger/logger.go index ca213488a..5e00dae5a 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "os" + "path/filepath" "regexp" "github.com/sirupsen/logrus" @@ -39,7 +40,7 @@ func Log() *logrus.Logger { } if LogFile != "" { - file, err := os.OpenFile(LogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0664) + file, err := os.OpenFile(filepath.Clean(LogFile), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0664) // #nosec if err == nil { log.Out = file } else { diff --git a/internal/storage/database.go b/internal/storage/database.go index 22b758494..3e239e039 100644 --- a/internal/storage/database.go +++ b/internal/storage/database.go @@ -712,7 +712,9 @@ func DeleteAllMessages() error { vacuumDb() dbLastAction = time.Now() - SettingPut("DeletedSize", "0") + if err := SettingPut("DeletedSize", "0"); err != nil { + logger.Log().Warnf("[db] %s", err.Error()) + } logMessagesDeleted(total) diff --git a/internal/storage/search.go b/internal/storage/search.go index db41826e2..806852109 100644 --- a/internal/storage/search.go +++ b/internal/storage/search.go @@ -160,21 +160,21 @@ func DeleteSearch(search string) error { delIDs[i] = id } - sqlDelete1 := `DELETE FROM mailbox WHERE ID IN (?` + strings.Repeat(",?", len(ids)-1) + `)` + sqlDelete1 := `DELETE FROM mailbox WHERE ID IN (?` + strings.Repeat(",?", len(ids)-1) + `)` // #nosec _, err = tx.Exec(sqlDelete1, delIDs...) if err != nil { return err } - sqlDelete2 := `DELETE FROM mailbox_data WHERE ID IN (?` + strings.Repeat(",?", len(ids)-1) + `)` + sqlDelete2 := `DELETE FROM mailbox_data WHERE ID IN (?` + strings.Repeat(",?", len(ids)-1) + `)` // #nosec _, err = tx.Exec(sqlDelete2, delIDs...) if err != nil { return err } - sqlDelete3 := `DELETE FROM message_tags WHERE ID IN (?` + strings.Repeat(",?", len(ids)-1) + `)` + sqlDelete3 := `DELETE FROM message_tags WHERE ID IN (?` + strings.Repeat(",?", len(ids)-1) + `)` // #nosec _, err = tx.Exec(sqlDelete3, delIDs...) if err != nil { diff --git a/internal/updater/updater.go b/internal/updater/updater.go index 6c5d2f59f..da83201fc 100644 --- a/internal/updater/updater.go +++ b/internal/updater/updater.go @@ -178,8 +178,8 @@ func GithubUpdate(repo, appName, currentVersion string) (string, error) { } if runtime.GOOS != "windows" { - /* #nosec G302 */ - if err := os.Chmod(newExec, 0755); err != nil { + err := os.Chmod(newExec, 0755) // #nosec + if err != nil { return "", err } } diff --git a/server/handlers/proxy.go b/server/handlers/proxy.go index 0dd360b38..33557c6a8 100644 --- a/server/handlers/proxy.go +++ b/server/handlers/proxy.go @@ -35,7 +35,7 @@ func ProxyHandler(w http.ResponseWriter, r *http.Request) { tr := &http.Transport{} if config.AllowUntrustedTLS { - tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} // #nosec } client := &http.Client{ @@ -108,7 +108,9 @@ func ProxyHandler(w http.ResponseWriter, r *http.Request) { // relay status code - WriteHeader must come after Header.Set() w.WriteHeader(resp.StatusCode) - w.Write(body) + if _, err := w.Write(body); err != nil { + logger.Log().Warnf("[proxy] %s", err.Error()) + } } // AbsoluteURL will return a full URL regardless whether it is relative or absolute diff --git a/server/server.go b/server/server.go index 7f601d8b4..54158389f 100644 --- a/server/server.go +++ b/server/server.go @@ -13,6 +13,7 @@ import ( "strings" "sync/atomic" "text/template" + "time" "github.com/axllent/mailpit/config" "github.com/axllent/mailpit/internal/auth" @@ -94,12 +95,18 @@ func Listen() { logger.Log().Infof("[http] starting on %s", config.HTTPListen) + server := &http.Server{ + Addr: config.HTTPListen, + ReadTimeout: 30 * time.Second, + WriteTimeout: 30 * time.Second, + } + if config.UITLSCert != "" && config.UITLSKey != "" { logger.Log().Infof("[http] accessible via https://%s%s", logger.CleanHTTPIP(config.HTTPListen), config.Webroot) - logger.Log().Fatal(http.ListenAndServeTLS(config.HTTPListen, config.UITLSCert, config.UITLSKey, nil)) + logger.Log().Fatal(server.ListenAndServeTLS(config.UITLSCert, config.UITLSKey)) } else { logger.Log().Infof("[http] accessible via http://%s%s", logger.CleanHTTPIP(config.HTTPListen), config.Webroot) - logger.Log().Fatal(http.ListenAndServe(config.HTTPListen, nil)) + logger.Log().Fatal(server.ListenAndServe()) } } diff --git a/server/smtpd/smtp.go b/server/smtpd/smtp.go index 45d741d45..25f20bb2c 100644 --- a/server/smtpd/smtp.go +++ b/server/smtpd/smtp.go @@ -54,7 +54,7 @@ func Send(from string, to []string, msg []byte) error { defer c.Close() if config.SMTPRelayConfig.STARTTLS { - conf := &tls.Config{ServerName: config.SMTPRelayConfig.Host} + conf := &tls.Config{ServerName: config.SMTPRelayConfig.Host} // #nosec conf.InsecureSkipVerify = config.SMTPRelayConfig.AllowInsecure From 294f9a21e6c7d388037d8e2bc74f5ab1878ba5af Mon Sep 17 00:00:00 2001 From: Ralph Slooten Date: Sat, 17 Feb 2024 22:36:32 +1300 Subject: [PATCH 04/11] Chore: Refactor storage library --- internal/storage/database.go | 610 ----------------- internal/storage/messages.go | 621 ++++++++++++++++++ .../{database_test.go => messages_test.go} | 0 internal/storage/migrationTasks.go | 73 -- internal/storage/migrations.go | 72 +- 5 files changed, 692 insertions(+), 684 deletions(-) create mode 100644 internal/storage/messages.go rename internal/storage/{database_test.go => messages_test.go} (100%) delete mode 100644 internal/storage/migrationTasks.go diff --git a/internal/storage/database.go b/internal/storage/database.go index 3e239e039..540d67c53 100644 --- a/internal/storage/database.go +++ b/internal/storage/database.go @@ -2,31 +2,19 @@ package storage import ( - "bytes" - "context" "database/sql" - "encoding/json" - "errors" "fmt" - "net/http" - "net/mail" "os" "os/signal" "path" "path/filepath" - "strings" "syscall" "time" "github.com/axllent/mailpit/config" "github.com/axllent/mailpit/internal/logger" - "github.com/axllent/mailpit/internal/tools" - "github.com/axllent/mailpit/server/webhook" - "github.com/axllent/mailpit/server/websockets" - "github.com/jhillyerd/enmime" "github.com/klauspost/compress/zstd" "github.com/leporo/sqlf" - "github.com/lithammer/shortuuid/v4" // sqlite (native) - https://gitlab.com/cznic/sqlite _ "modernc.org/sqlite" @@ -126,604 +114,6 @@ func Close() { } } -// Store will save an email to the database tables. -// Returns the database ID of the saved message. -func Store(body *[]byte) (string, error) { - // Parse message body with enmime - env, err := enmime.ReadEnvelope(bytes.NewReader(*body)) - if err != nil { - logger.Log().Warnf("[message] %s", err.Error()) - return "", nil - } - - from := &mail.Address{} - fromJSON := addressToSlice(env, "From") - if len(fromJSON) > 0 { - from = fromJSON[0] - } else if env.GetHeader("From") != "" { - from = &mail.Address{Name: env.GetHeader("From")} - } - - obj := DBMailSummary{ - From: from, - To: addressToSlice(env, "To"), - Cc: addressToSlice(env, "Cc"), - Bcc: addressToSlice(env, "Bcc"), - ReplyTo: addressToSlice(env, "Reply-To"), - } - - messageID := strings.Trim(env.Root.Header.Get("Message-ID"), "<>") - created := time.Now() - - // use message date instead of created date - if config.UseMessageDates { - if mDate, err := env.Date(); err == nil { - created = mDate - } - } - - // generate the search text - searchText := createSearchText(env) - - // generate unique ID - id := shortuuid.New() - - summaryJSON, err := json.Marshal(obj) - if err != nil { - return "", err - } - - // extract tags from body matches based on --tag - tagStr := findTagsInRawMessage(body) - - // extract tags from X-Tags header - headerTags := strings.TrimSpace(env.Root.Header.Get("X-Tags")) - if headerTags != "" { - tagStr += "," + headerTags - } - - tagData := uniqueTagsFromString(tagStr) - - // begin a transaction to ensure both the message - // and data are stored successfully - ctx := context.Background() - tx, err := db.BeginTx(ctx, nil) - if err != nil { - return "", err - } - - // roll back if it fails - defer tx.Rollback() - - subject := env.GetHeader("Subject") - size := len(*body) - inline := len(env.Inlines) - attachments := len(env.Attachments) - snippet := tools.CreateSnippet(env.Text, env.HTML) - - // insert mail summary data - _, err = tx.Exec("INSERT INTO mailbox(Created, ID, MessageID, Subject, Metadata, Size, Inline, Attachments, SearchText, Read, Snippet) values(?,?,?,?,?,?,?,?,?,0,?)", - created.UnixMilli(), id, messageID, subject, string(summaryJSON), size, inline, attachments, searchText, snippet) - if err != nil { - return "", err - } - - // insert compressed raw message - compressed := dbEncoder.EncodeAll(*body, make([]byte, 0, size)) - _, err = tx.Exec("INSERT INTO mailbox_data(ID, Email) values(?,?)", id, string(compressed)) - if err != nil { - return "", err - } - - if err := tx.Commit(); err != nil { - return "", err - } - - if len(tagData) > 0 { - // set tags after tx.Commit() - if err := SetMessageTags(id, tagData); err != nil { - return "", err - } - } - - c := &MessageSummary{} - if err := json.Unmarshal(summaryJSON, c); err != nil { - return "", err - } - - c.Created = created - c.ID = id - c.MessageID = messageID - c.Attachments = attachments - c.Subject = subject - c.Size = size - c.Tags = tagData - c.Snippet = snippet - - websockets.Broadcast("new", c) - webhook.Send(c) - - dbLastAction = time.Now() - - BroadcastMailboxStats() - - return id, nil -} - -// List returns a subset of messages from the mailbox, -// sorted latest to oldest -func List(start, limit int) ([]MessageSummary, error) { - results := []MessageSummary{} - tsStart := time.Now() - - q := sqlf.From("mailbox m"). - Select(`m.Created, m.ID, m.MessageID, m.Subject, m.Metadata, m.Size, m.Attachments, m.Read, m.Snippet`). - OrderBy("m.Created DESC"). - Limit(limit). - Offset(start) - - if err := q.QueryAndClose(nil, db, func(row *sql.Rows) { - var created int64 - var id string - var messageID string - var subject string - var metadata string - var size int - var attachments int - var read int - var snippet string - em := MessageSummary{} - - if err := row.Scan(&created, &id, &messageID, &subject, &metadata, &size, &attachments, &read, &snippet); err != nil { - logger.Log().Errorf("[db] %s", err.Error()) - return - } - - if err := json.Unmarshal([]byte(metadata), &em); err != nil { - logger.Log().Errorf("[json] %s", err.Error()) - return - } - - em.Created = time.UnixMilli(created) - em.ID = id - em.MessageID = messageID - em.Subject = subject - em.Size = size - em.Attachments = attachments - em.Read = read == 1 - em.Snippet = snippet - // artificially generate ReplyTo if legacy data is missing Reply-To field - if em.ReplyTo == nil { - em.ReplyTo = []*mail.Address{} - } - - results = append(results, em) - }); err != nil { - return results, err - } - - // set tags for listed messages only - for i, m := range results { - results[i].Tags = getMessageTags(m.ID) - } - - dbLastAction = time.Now() - - elapsed := time.Since(tsStart) - - logger.Log().Debugf("[db] list INBOX in %s", elapsed) - - return results, nil -} - -// GetMessage returns a Message generated from the mailbox_data collection. -// If the message lacks a date header, then the received datetime is used. -func GetMessage(id string) (*Message, error) { - raw, err := GetMessageRaw(id) - if err != nil { - return nil, err - } - - r := bytes.NewReader(raw) - - env, err := enmime.ReadEnvelope(r) - if err != nil { - return nil, err - } - - var from *mail.Address - fromData := addressToSlice(env, "From") - if len(fromData) > 0 { - from = fromData[0] - } else if env.GetHeader("From") != "" { - from = &mail.Address{Name: env.GetHeader("From")} - } - - messageID := strings.Trim(env.GetHeader("Message-ID"), "<>") - - returnPath := strings.Trim(env.GetHeader("Return-Path"), "<>") - if returnPath == "" && from != nil { - returnPath = from.Address - } - - date, err := env.Date() - if err != nil { - // return received datetime when message does not contain a date header - q := sqlf.From("mailbox"). - Select(`Created`). - Where(`ID = ?`, id) - - if err := q.QueryAndClose(nil, db, func(row *sql.Rows) { - var created int64 - - if err := row.Scan(&created); err != nil { - logger.Log().Errorf("[db] %s", err.Error()) - return - } - - logger.Log().Debugf("[db] %s does not contain a date header, using received datetime", id) - - date = time.UnixMilli(created) - }); err != nil { - logger.Log().Errorf("[db] %s", err.Error()) - } - } - - obj := Message{ - ID: id, - MessageID: messageID, - From: from, - Date: date, - To: addressToSlice(env, "To"), - Cc: addressToSlice(env, "Cc"), - Bcc: addressToSlice(env, "Bcc"), - ReplyTo: addressToSlice(env, "Reply-To"), - ReturnPath: returnPath, - Subject: env.GetHeader("Subject"), - Tags: getMessageTags(id), - Size: len(raw), - Text: env.Text, - } - - obj.HTML = env.HTML - obj.Inline = []Attachment{} - obj.Attachments = []Attachment{} - - for _, i := range env.Inlines { - if i.FileName != "" || i.ContentID != "" { - obj.Inline = append(obj.Inline, AttachmentSummary(i)) - } - } - - for _, i := range env.OtherParts { - if i.FileName != "" || i.ContentID != "" { - obj.Inline = append(obj.Inline, AttachmentSummary(i)) - } - } - - for _, a := range env.Attachments { - if a.FileName != "" || a.ContentID != "" { - obj.Attachments = append(obj.Attachments, AttachmentSummary(a)) - } - } - - // get List-Unsubscribe links if set - obj.ListUnsubscribe = ListUnsubscribe{} - obj.ListUnsubscribe.Links = []string{} - if env.GetHeader("List-Unsubscribe") != "" { - l := env.GetHeader("List-Unsubscribe") - links, err := tools.ListUnsubscribeParser(l) - obj.ListUnsubscribe.Header = l - obj.ListUnsubscribe.Links = links - if err != nil { - obj.ListUnsubscribe.Errors = err.Error() - } - obj.ListUnsubscribe.HeaderPost = env.GetHeader("List-Unsubscribe-Post") - } - - // mark message as read - if err := MarkRead(id); err != nil { - return &obj, err - } - - dbLastAction = time.Now() - - return &obj, nil -} - -// GetMessageRaw returns an []byte of the full message -func GetMessageRaw(id string) ([]byte, error) { - var i string - var msg string - q := sqlf.From("mailbox_data"). - Select(`ID`).To(&i). - Select(`Email`).To(&msg). - Where(`ID = ?`, id) - - err := q.QueryRowAndClose(context.Background(), db) - if err != nil { - return nil, err - } - - if i == "" { - return nil, errors.New("message not found") - } - - raw, err := dbDecoder.DecodeAll([]byte(msg), nil) - if err != nil { - return nil, fmt.Errorf("error decompressing message: %s", err.Error()) - } - - dbLastAction = time.Now() - - return raw, err -} - -// GetAttachmentPart returns an *enmime.Part (attachment or inline) from a message -func GetAttachmentPart(id, partID string) (*enmime.Part, error) { - raw, err := GetMessageRaw(id) - if err != nil { - return nil, err - } - - r := bytes.NewReader(raw) - - env, err := enmime.ReadEnvelope(r) - if err != nil { - return nil, err - } - - for _, a := range env.Inlines { - if a.PartID == partID { - return a, nil - } - } - - for _, a := range env.OtherParts { - if a.PartID == partID { - return a, nil - } - } - - for _, a := range env.Attachments { - if a.PartID == partID { - return a, nil - } - } - - dbLastAction = time.Now() - - return nil, errors.New("attachment not found") -} - -// LatestID returns the latest message ID -// -// If a query argument is set in the request the function will return the -// latest message matching the search -func LatestID(r *http.Request) (string, error) { - var messages []MessageSummary - var err error - - search := strings.TrimSpace(r.URL.Query().Get("query")) - if search != "" { - messages, _, err = Search(search, 0, 1) - if err != nil { - return "", err - } - } else { - messages, err = List(0, 1) - if err != nil { - return "", err - } - } - if len(messages) == 0 { - return "", errors.New("Message not found") - } - - return messages[0].ID, nil -} - -// MarkRead will mark a message as read -func MarkRead(id string) error { - if !IsUnread(id) { - return nil - } - - _, err := sqlf.Update("mailbox"). - Set("Read", 1). - Where("ID = ?", id). - ExecAndClose(context.Background(), db) - - if err == nil { - logger.Log().Debugf("[db] marked message %s as read", id) - } - - BroadcastMailboxStats() - - return err -} - -// MarkAllRead will mark all messages as read -func MarkAllRead() error { - var ( - start = time.Now() - total = CountUnread() - ) - - _, err := sqlf.Update("mailbox"). - Set("Read", 1). - Where("Read = ?", 0). - ExecAndClose(context.Background(), db) - if err != nil { - return err - } - - elapsed := time.Since(start) - logger.Log().Debugf("[db] marked %d messages as read in %s", total, elapsed) - - BroadcastMailboxStats() - - dbLastAction = time.Now() - - return nil -} - -// MarkAllUnread will mark all messages as unread -func MarkAllUnread() error { - var ( - start = time.Now() - total = CountRead() - ) - - _, err := sqlf.Update("mailbox"). - Set("Read", 0). - Where("Read = ?", 1). - ExecAndClose(context.Background(), db) - if err != nil { - return err - } - - elapsed := time.Since(start) - logger.Log().Debugf("[db] marked %d messages as unread in %s", total, elapsed) - - BroadcastMailboxStats() - - dbLastAction = time.Now() - - return nil -} - -// MarkUnread will mark a message as unread -func MarkUnread(id string) error { - if IsUnread(id) { - return nil - } - - _, err := sqlf.Update("mailbox"). - Set("Read", 0). - Where("ID = ?", id). - ExecAndClose(context.Background(), db) - - if err == nil { - logger.Log().Debugf("[db] marked message %s as unread", id) - } - - dbLastAction = time.Now() - - BroadcastMailboxStats() - - return err -} - -// DeleteOneMessage will delete a single message from a mailbox -func DeleteOneMessage(id string) error { - m, err := GetMessage(id) - if err != nil { - return err - } - // begin a transaction to ensure both the message - // and data are deleted successfully - tx, err := db.BeginTx(context.Background(), nil) - if err != nil { - return err - } - - // roll back if it fails - defer tx.Rollback() - - _, err = tx.Exec("DELETE FROM mailbox WHERE ID = ?", id) - if err != nil { - return err - } - - _, err = tx.Exec("DELETE FROM mailbox_data WHERE ID = ?", id) - if err != nil { - return err - } - - err = tx.Commit() - - if err == nil { - logger.Log().Debugf("[db] deleted message %s", id) - } - - if err := DeleteAllMessageTags(id); err != nil { - return err - } - - dbLastAction = time.Now() - addDeletedSize(int64(m.Size)) - - logMessagesDeleted(1) - - BroadcastMailboxStats() - - return err -} - -// DeleteAllMessages will delete all messages from a mailbox -func DeleteAllMessages() error { - var ( - start = time.Now() - total int - ) - - _ = sqlf.From("mailbox"). - Select("COUNT(*)").To(&total). - QueryRowAndClose(nil, db) - - // begin a transaction to ensure both the message - // summaries and data are deleted successfully - tx, err := db.BeginTx(context.Background(), nil) - if err != nil { - return err - } - - // roll back if it fails - defer tx.Rollback() - - _, err = tx.Exec("DELETE FROM mailbox") - if err != nil { - return err - } - - _, err = tx.Exec("DELETE FROM mailbox_data") - if err != nil { - return err - } - - _, err = tx.Exec("DELETE FROM tags") - if err != nil { - return err - } - - _, err = tx.Exec("DELETE FROM message_tags") - if err != nil { - return err - } - - if err := tx.Commit(); err != nil { - return err - } - - elapsed := time.Since(start) - logger.Log().Debugf("[db] deleted %d messages in %s", total, elapsed) - - vacuumDb() - - dbLastAction = time.Now() - if err := SettingPut("DeletedSize", "0"); err != nil { - logger.Log().Warnf("[db] %s", err.Error()) - } - - logMessagesDeleted(total) - - websockets.Broadcast("prune", nil) - BroadcastMailboxStats() - - return err -} - // StatsGet returns the total/unread statistics for a mailbox func StatsGet() MailboxStats { var ( diff --git a/internal/storage/messages.go b/internal/storage/messages.go new file mode 100644 index 000000000..baa003682 --- /dev/null +++ b/internal/storage/messages.go @@ -0,0 +1,621 @@ +package storage + +import ( + "bytes" + "context" + "database/sql" + "encoding/json" + "errors" + "fmt" + "net/http" + "net/mail" + "strings" + "time" + + "github.com/axllent/mailpit/config" + "github.com/axllent/mailpit/internal/logger" + "github.com/axllent/mailpit/internal/tools" + "github.com/axllent/mailpit/server/webhook" + "github.com/axllent/mailpit/server/websockets" + "github.com/jhillyerd/enmime" + "github.com/leporo/sqlf" + "github.com/lithammer/shortuuid/v4" +) + +// Store will save an email to the database tables. +// Returns the database ID of the saved message. +func Store(body *[]byte) (string, error) { + // Parse message body with enmime + env, err := enmime.ReadEnvelope(bytes.NewReader(*body)) + if err != nil { + logger.Log().Warnf("[message] %s", err.Error()) + return "", nil + } + + from := &mail.Address{} + fromJSON := addressToSlice(env, "From") + if len(fromJSON) > 0 { + from = fromJSON[0] + } else if env.GetHeader("From") != "" { + from = &mail.Address{Name: env.GetHeader("From")} + } + + obj := DBMailSummary{ + From: from, + To: addressToSlice(env, "To"), + Cc: addressToSlice(env, "Cc"), + Bcc: addressToSlice(env, "Bcc"), + ReplyTo: addressToSlice(env, "Reply-To"), + } + + messageID := strings.Trim(env.Root.Header.Get("Message-ID"), "<>") + created := time.Now() + + // use message date instead of created date + if config.UseMessageDates { + if mDate, err := env.Date(); err == nil { + created = mDate + } + } + + // generate the search text + searchText := createSearchText(env) + + // generate unique ID + id := shortuuid.New() + + summaryJSON, err := json.Marshal(obj) + if err != nil { + return "", err + } + + // extract tags from body matches based on --tag + tagStr := findTagsInRawMessage(body) + + // extract tags from X-Tags header + headerTags := strings.TrimSpace(env.Root.Header.Get("X-Tags")) + if headerTags != "" { + tagStr += "," + headerTags + } + + tagData := uniqueTagsFromString(tagStr) + + // begin a transaction to ensure both the message + // and data are stored successfully + ctx := context.Background() + tx, err := db.BeginTx(ctx, nil) + if err != nil { + return "", err + } + + // roll back if it fails + defer tx.Rollback() + + subject := env.GetHeader("Subject") + size := len(*body) + inline := len(env.Inlines) + attachments := len(env.Attachments) + snippet := tools.CreateSnippet(env.Text, env.HTML) + + // insert mail summary data + _, err = tx.Exec("INSERT INTO mailbox(Created, ID, MessageID, Subject, Metadata, Size, Inline, Attachments, SearchText, Read, Snippet) values(?,?,?,?,?,?,?,?,?,0,?)", + created.UnixMilli(), id, messageID, subject, string(summaryJSON), size, inline, attachments, searchText, snippet) + if err != nil { + return "", err + } + + // insert compressed raw message + compressed := dbEncoder.EncodeAll(*body, make([]byte, 0, size)) + _, err = tx.Exec("INSERT INTO mailbox_data(ID, Email) values(?,?)", id, string(compressed)) + if err != nil { + return "", err + } + + if err := tx.Commit(); err != nil { + return "", err + } + + if len(tagData) > 0 { + // set tags after tx.Commit() + if err := SetMessageTags(id, tagData); err != nil { + return "", err + } + } + + c := &MessageSummary{} + if err := json.Unmarshal(summaryJSON, c); err != nil { + return "", err + } + + c.Created = created + c.ID = id + c.MessageID = messageID + c.Attachments = attachments + c.Subject = subject + c.Size = size + c.Tags = tagData + c.Snippet = snippet + + websockets.Broadcast("new", c) + webhook.Send(c) + + dbLastAction = time.Now() + + BroadcastMailboxStats() + + return id, nil +} + +// List returns a subset of messages from the mailbox, +// sorted latest to oldest +func List(start, limit int) ([]MessageSummary, error) { + results := []MessageSummary{} + tsStart := time.Now() + + q := sqlf.From("mailbox m"). + Select(`m.Created, m.ID, m.MessageID, m.Subject, m.Metadata, m.Size, m.Attachments, m.Read, m.Snippet`). + OrderBy("m.Created DESC"). + Limit(limit). + Offset(start) + + if err := q.QueryAndClose(nil, db, func(row *sql.Rows) { + var created int64 + var id string + var messageID string + var subject string + var metadata string + var size int + var attachments int + var read int + var snippet string + em := MessageSummary{} + + if err := row.Scan(&created, &id, &messageID, &subject, &metadata, &size, &attachments, &read, &snippet); err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + return + } + + if err := json.Unmarshal([]byte(metadata), &em); err != nil { + logger.Log().Errorf("[json] %s", err.Error()) + return + } + + em.Created = time.UnixMilli(created) + em.ID = id + em.MessageID = messageID + em.Subject = subject + em.Size = size + em.Attachments = attachments + em.Read = read == 1 + em.Snippet = snippet + // artificially generate ReplyTo if legacy data is missing Reply-To field + if em.ReplyTo == nil { + em.ReplyTo = []*mail.Address{} + } + + results = append(results, em) + }); err != nil { + return results, err + } + + // set tags for listed messages only + for i, m := range results { + results[i].Tags = getMessageTags(m.ID) + } + + dbLastAction = time.Now() + + elapsed := time.Since(tsStart) + + logger.Log().Debugf("[db] list INBOX in %s", elapsed) + + return results, nil +} + +// GetMessage returns a Message generated from the mailbox_data collection. +// If the message lacks a date header, then the received datetime is used. +func GetMessage(id string) (*Message, error) { + raw, err := GetMessageRaw(id) + if err != nil { + return nil, err + } + + r := bytes.NewReader(raw) + + env, err := enmime.ReadEnvelope(r) + if err != nil { + return nil, err + } + + var from *mail.Address + fromData := addressToSlice(env, "From") + if len(fromData) > 0 { + from = fromData[0] + } else if env.GetHeader("From") != "" { + from = &mail.Address{Name: env.GetHeader("From")} + } + + messageID := strings.Trim(env.GetHeader("Message-ID"), "<>") + + returnPath := strings.Trim(env.GetHeader("Return-Path"), "<>") + if returnPath == "" && from != nil { + returnPath = from.Address + } + + date, err := env.Date() + if err != nil { + // return received datetime when message does not contain a date header + q := sqlf.From("mailbox"). + Select(`Created`). + Where(`ID = ?`, id) + + if err := q.QueryAndClose(nil, db, func(row *sql.Rows) { + var created int64 + + if err := row.Scan(&created); err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + return + } + + logger.Log().Debugf("[db] %s does not contain a date header, using received datetime", id) + + date = time.UnixMilli(created) + }); err != nil { + logger.Log().Errorf("[db] %s", err.Error()) + } + } + + obj := Message{ + ID: id, + MessageID: messageID, + From: from, + Date: date, + To: addressToSlice(env, "To"), + Cc: addressToSlice(env, "Cc"), + Bcc: addressToSlice(env, "Bcc"), + ReplyTo: addressToSlice(env, "Reply-To"), + ReturnPath: returnPath, + Subject: env.GetHeader("Subject"), + Tags: getMessageTags(id), + Size: len(raw), + Text: env.Text, + } + + obj.HTML = env.HTML + obj.Inline = []Attachment{} + obj.Attachments = []Attachment{} + + for _, i := range env.Inlines { + if i.FileName != "" || i.ContentID != "" { + obj.Inline = append(obj.Inline, AttachmentSummary(i)) + } + } + + for _, i := range env.OtherParts { + if i.FileName != "" || i.ContentID != "" { + obj.Inline = append(obj.Inline, AttachmentSummary(i)) + } + } + + for _, a := range env.Attachments { + if a.FileName != "" || a.ContentID != "" { + obj.Attachments = append(obj.Attachments, AttachmentSummary(a)) + } + } + + // get List-Unsubscribe links if set + obj.ListUnsubscribe = ListUnsubscribe{} + obj.ListUnsubscribe.Links = []string{} + if env.GetHeader("List-Unsubscribe") != "" { + l := env.GetHeader("List-Unsubscribe") + links, err := tools.ListUnsubscribeParser(l) + obj.ListUnsubscribe.Header = l + obj.ListUnsubscribe.Links = links + if err != nil { + obj.ListUnsubscribe.Errors = err.Error() + } + obj.ListUnsubscribe.HeaderPost = env.GetHeader("List-Unsubscribe-Post") + } + + // mark message as read + if err := MarkRead(id); err != nil { + return &obj, err + } + + dbLastAction = time.Now() + + return &obj, nil +} + +// GetMessageRaw returns an []byte of the full message +func GetMessageRaw(id string) ([]byte, error) { + var i string + var msg string + q := sqlf.From("mailbox_data"). + Select(`ID`).To(&i). + Select(`Email`).To(&msg). + Where(`ID = ?`, id) + + err := q.QueryRowAndClose(context.Background(), db) + if err != nil { + return nil, err + } + + if i == "" { + return nil, errors.New("message not found") + } + + raw, err := dbDecoder.DecodeAll([]byte(msg), nil) + if err != nil { + return nil, fmt.Errorf("error decompressing message: %s", err.Error()) + } + + dbLastAction = time.Now() + + return raw, err +} + +// GetAttachmentPart returns an *enmime.Part (attachment or inline) from a message +func GetAttachmentPart(id, partID string) (*enmime.Part, error) { + raw, err := GetMessageRaw(id) + if err != nil { + return nil, err + } + + r := bytes.NewReader(raw) + + env, err := enmime.ReadEnvelope(r) + if err != nil { + return nil, err + } + + for _, a := range env.Inlines { + if a.PartID == partID { + return a, nil + } + } + + for _, a := range env.OtherParts { + if a.PartID == partID { + return a, nil + } + } + + for _, a := range env.Attachments { + if a.PartID == partID { + return a, nil + } + } + + dbLastAction = time.Now() + + return nil, errors.New("attachment not found") +} + +// LatestID returns the latest message ID +// +// If a query argument is set in the request the function will return the +// latest message matching the search +func LatestID(r *http.Request) (string, error) { + var messages []MessageSummary + var err error + + search := strings.TrimSpace(r.URL.Query().Get("query")) + if search != "" { + messages, _, err = Search(search, 0, 1) + if err != nil { + return "", err + } + } else { + messages, err = List(0, 1) + if err != nil { + return "", err + } + } + if len(messages) == 0 { + return "", errors.New("Message not found") + } + + return messages[0].ID, nil +} + +// MarkRead will mark a message as read +func MarkRead(id string) error { + if !IsUnread(id) { + return nil + } + + _, err := sqlf.Update("mailbox"). + Set("Read", 1). + Where("ID = ?", id). + ExecAndClose(context.Background(), db) + + if err == nil { + logger.Log().Debugf("[db] marked message %s as read", id) + } + + BroadcastMailboxStats() + + return err +} + +// MarkAllRead will mark all messages as read +func MarkAllRead() error { + var ( + start = time.Now() + total = CountUnread() + ) + + _, err := sqlf.Update("mailbox"). + Set("Read", 1). + Where("Read = ?", 0). + ExecAndClose(context.Background(), db) + if err != nil { + return err + } + + elapsed := time.Since(start) + logger.Log().Debugf("[db] marked %d messages as read in %s", total, elapsed) + + BroadcastMailboxStats() + + dbLastAction = time.Now() + + return nil +} + +// MarkAllUnread will mark all messages as unread +func MarkAllUnread() error { + var ( + start = time.Now() + total = CountRead() + ) + + _, err := sqlf.Update("mailbox"). + Set("Read", 0). + Where("Read = ?", 1). + ExecAndClose(context.Background(), db) + if err != nil { + return err + } + + elapsed := time.Since(start) + logger.Log().Debugf("[db] marked %d messages as unread in %s", total, elapsed) + + BroadcastMailboxStats() + + dbLastAction = time.Now() + + return nil +} + +// MarkUnread will mark a message as unread +func MarkUnread(id string) error { + if IsUnread(id) { + return nil + } + + _, err := sqlf.Update("mailbox"). + Set("Read", 0). + Where("ID = ?", id). + ExecAndClose(context.Background(), db) + + if err == nil { + logger.Log().Debugf("[db] marked message %s as unread", id) + } + + dbLastAction = time.Now() + + BroadcastMailboxStats() + + return err +} + +// DeleteOneMessage will delete a single message from a mailbox +func DeleteOneMessage(id string) error { + m, err := GetMessage(id) + if err != nil { + return err + } + // begin a transaction to ensure both the message + // and data are deleted successfully + tx, err := db.BeginTx(context.Background(), nil) + if err != nil { + return err + } + + // roll back if it fails + defer tx.Rollback() + + _, err = tx.Exec("DELETE FROM mailbox WHERE ID = ?", id) + if err != nil { + return err + } + + _, err = tx.Exec("DELETE FROM mailbox_data WHERE ID = ?", id) + if err != nil { + return err + } + + err = tx.Commit() + + if err == nil { + logger.Log().Debugf("[db] deleted message %s", id) + } + + if err := DeleteAllMessageTags(id); err != nil { + return err + } + + dbLastAction = time.Now() + addDeletedSize(int64(m.Size)) + + logMessagesDeleted(1) + + BroadcastMailboxStats() + + return err +} + +// DeleteAllMessages will delete all messages from a mailbox +func DeleteAllMessages() error { + var ( + start = time.Now() + total int + ) + + _ = sqlf.From("mailbox"). + Select("COUNT(*)").To(&total). + QueryRowAndClose(nil, db) + + // begin a transaction to ensure both the message + // summaries and data are deleted successfully + tx, err := db.BeginTx(context.Background(), nil) + if err != nil { + return err + } + + // roll back if it fails + defer tx.Rollback() + + _, err = tx.Exec("DELETE FROM mailbox") + if err != nil { + return err + } + + _, err = tx.Exec("DELETE FROM mailbox_data") + if err != nil { + return err + } + + _, err = tx.Exec("DELETE FROM tags") + if err != nil { + return err + } + + _, err = tx.Exec("DELETE FROM message_tags") + if err != nil { + return err + } + + if err := tx.Commit(); err != nil { + return err + } + + elapsed := time.Since(start) + logger.Log().Debugf("[db] deleted %d messages in %s", total, elapsed) + + vacuumDb() + + dbLastAction = time.Now() + if err := SettingPut("DeletedSize", "0"); err != nil { + logger.Log().Warnf("[db] %s", err.Error()) + } + + logMessagesDeleted(total) + + websockets.Broadcast("prune", nil) + BroadcastMailboxStats() + + return err +} diff --git a/internal/storage/database_test.go b/internal/storage/messages_test.go similarity index 100% rename from internal/storage/database_test.go rename to internal/storage/messages_test.go diff --git a/internal/storage/migrationTasks.go b/internal/storage/migrationTasks.go deleted file mode 100644 index 756a76220..000000000 --- a/internal/storage/migrationTasks.go +++ /dev/null @@ -1,73 +0,0 @@ -package storage - -// These functions are used to migrate data formats/structure on startup. - -import ( - "database/sql" - "encoding/json" - - "github.com/axllent/mailpit/internal/logger" - "github.com/leporo/sqlf" -) - -func dataMigrations() { - migrateTagsToManyMany() -} - -// Migrate tags to ManyMany structure -// Migration task implemented 12/2023 -// Can be removed end 06/2024 and Tags column & index dropped from mailbox -func migrateTagsToManyMany() { - toConvert := make(map[string][]string) - q := sqlf. - Select("ID, Tags"). - From("mailbox"). - Where("Tags != ?", "[]"). - Where("Tags IS NOT NULL") - - if err := q.QueryAndClose(nil, db, func(row *sql.Rows) { - var id string - var jsonTags string - if err := row.Scan(&id, &jsonTags); err != nil { - logger.Log().Errorf("[migration] %s", err.Error()) - return - } - - tags := []string{} - - if err := json.Unmarshal([]byte(jsonTags), &tags); err != nil { - logger.Log().Errorf("[json] %s", err.Error()) - return - } - - toConvert[id] = tags - }); err != nil { - logger.Log().Errorf("[migration] %s", err.Error()) - } - - if len(toConvert) > 0 { - logger.Log().Infof("[migration] converting %d message tags", len(toConvert)) - for id, tags := range toConvert { - if err := SetMessageTags(id, tags); err != nil { - logger.Log().Errorf("[migration] %s", err.Error()) - } else { - if _, err := sqlf.Update("mailbox"). - Set("Tags", nil). - Where("ID = ?", id). - ExecAndClose(nil, db); err != nil { - logger.Log().Errorf("[migration] %s", err.Error()) - } - } - } - - logger.Log().Info("[migration] tags conversion complete") - } - - // set all legacy `[]` tags to NULL - if _, err := sqlf.Update("mailbox"). - Set("Tags", nil). - Where("Tags = ?", "[]"). - ExecAndClose(nil, db); err != nil { - logger.Log().Errorf("[migration] %s", err.Error()) - } -} diff --git a/internal/storage/migrations.go b/internal/storage/migrations.go index 8eb4a1095..7da482336 100644 --- a/internal/storage/migrations.go +++ b/internal/storage/migrations.go @@ -1,6 +1,13 @@ package storage -import "github.com/GuiaBolso/darwin" +import ( + "database/sql" + "encoding/json" + + "github.com/GuiaBolso/darwin" + "github.com/axllent/mailpit/internal/logger" + "github.com/leporo/sqlf" +) var ( dbMigrations = []darwin.Migration{ @@ -111,3 +118,66 @@ func dbApplyMigrations() error { return d.Migrate() } + +// These functions are used to migrate data formats/structure on startup. +func dataMigrations() { + migrateTagsToManyMany() +} + +// Migrate tags to ManyMany structure +// Migration task implemented 12/2023 +// Can be removed end 06/2024 and Tags column & index dropped from mailbox +func migrateTagsToManyMany() { + toConvert := make(map[string][]string) + q := sqlf. + Select("ID, Tags"). + From("mailbox"). + Where("Tags != ?", "[]"). + Where("Tags IS NOT NULL") + + if err := q.QueryAndClose(nil, db, func(row *sql.Rows) { + var id string + var jsonTags string + if err := row.Scan(&id, &jsonTags); err != nil { + logger.Log().Errorf("[migration] %s", err.Error()) + return + } + + tags := []string{} + + if err := json.Unmarshal([]byte(jsonTags), &tags); err != nil { + logger.Log().Errorf("[json] %s", err.Error()) + return + } + + toConvert[id] = tags + }); err != nil { + logger.Log().Errorf("[migration] %s", err.Error()) + } + + if len(toConvert) > 0 { + logger.Log().Infof("[migration] converting %d message tags", len(toConvert)) + for id, tags := range toConvert { + if err := SetMessageTags(id, tags); err != nil { + logger.Log().Errorf("[migration] %s", err.Error()) + } else { + if _, err := sqlf.Update("mailbox"). + Set("Tags", nil). + Where("ID = ?", id). + ExecAndClose(nil, db); err != nil { + logger.Log().Errorf("[migration] %s", err.Error()) + } + } + } + + logger.Log().Info("[migration] tags conversion complete") + } + + // set all legacy `[]` tags to NULL + if _, err := sqlf.Update("mailbox"). + Set("Tags", nil). + Where("Tags = ?", "[]"). + ExecAndClose(nil, db); err != nil { + logger.Log().Errorf("[migration] %s", err.Error()) + } +} From 5458b1044f0f0d429e3ede31fd3ff1574d16c2d4 Mon Sep 17 00:00:00 2001 From: Ralph Slooten Date: Sat, 17 Feb 2024 22:48:59 +1300 Subject: [PATCH 05/11] Docker: Add edge Docker images for latest unreleased features --- .github/workflows/build-docker-edge.yml | 32 +++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/build-docker-edge.yml diff --git a/.github/workflows/build-docker-edge.yml b/.github/workflows/build-docker-edge.yml new file mode 100644 index 000000000..cb578d713 --- /dev/null +++ b/.github/workflows/build-docker-edge.yml @@ -0,0 +1,32 @@ +on: + push: + branches: [ develop ] + +name: Build docker edge images +jobs: + docker: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + platforms: linux/386,linux/amd64,linux/arm64 + push: true + tags: | + axllent/mailpit:edge From f067b76c5822cce1836aabeabee270ca64cbe901 Mon Sep 17 00:00:00 2001 From: Ralph Slooten Date: Sat, 17 Feb 2024 23:19:32 +1300 Subject: [PATCH 06/11] Update cron logic --- internal/storage/cron.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/storage/cron.go b/internal/storage/cron.go index 8309d186d..5a7bc608d 100644 --- a/internal/storage/cron.go +++ b/internal/storage/cron.go @@ -3,6 +3,7 @@ package storage import ( "context" "database/sql" + "math" "strings" "time" @@ -21,7 +22,7 @@ func dbCron() { sinceLastDbAction := currentTime.Sub(dbLastAction) // only run the database has been idle for 5 minutes - if sinceLastDbAction.Minutes() >= 5 { + if math.Floor(sinceLastDbAction.Minutes()) == 5 { deletedSize := getDeletedSize() if deletedSize > 0 { From f548bbb874754fb71f9129a231ffea28501d888b Mon Sep 17 00:00:00 2001 From: Ralph Slooten Date: Sat, 24 Feb 2024 23:10:48 +1300 Subject: [PATCH 07/11] Feature: Optional POP3 server (#249) Originally requested in #72 --- Dockerfile | 2 +- cmd/root.go | 17 ++ config/config.go | 55 ++++++ internal/auth/auth.go | 21 +++ internal/storage/messages.go | 6 +- server/pop3/functions.go | 76 +++++++++ server/pop3/pop3.go | 314 +++++++++++++++++++++++++++++++++++ server/server.go | 3 + 8 files changed, 491 insertions(+), 3 deletions(-) create mode 100644 server/pop3/functions.go create mode 100644 server/pop3/pop3.go diff --git a/Dockerfile b/Dockerfile index aff301b05..13e7517b0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,6 +16,6 @@ COPY --from=builder /mailpit /mailpit RUN apk add --no-cache tzdata -EXPOSE 1025/tcp 8025/tcp +EXPOSE 1025/tcp 1110/tcp 8025/tcp ENTRYPOINT ["/mailpit"] diff --git a/cmd/root.go b/cmd/root.go index f9629786c..e517deec2 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -110,6 +110,12 @@ func init() { rootCmd.Flags().StringVar(&config.SMTPRelayConfigFile, "smtp-relay-config", config.SMTPRelayConfigFile, "SMTP configuration file to allow releasing messages") rootCmd.Flags().BoolVar(&config.SMTPRelayAllIncoming, "smtp-relay-all", config.SMTPRelayAllIncoming, "Relay all incoming messages via external SMTP server (caution!)") + + rootCmd.Flags().StringVar(&config.POP3Listen, "pop3", config.POP3Listen, "POP3 server bind interface and port") + rootCmd.Flags().StringVar(&config.POP3AuthFile, "pop3-auth-file", config.POP3AuthFile, "A password file for POP3 server authentication (enables POP3 server)") + rootCmd.Flags().StringVar(&config.POP3TLSCert, "pop3-tls-cert", config.POP3TLSCert, "Optional TLS certificate for POP3 server - requires pop3-tls-key") + rootCmd.Flags().StringVar(&config.POP3TLSKey, "pop3-tls-key", config.POP3TLSKey, "Optional TLS key for POP3 server - requires pop3-tls-cert") + rootCmd.Flags().StringVar(&config.WebhookURL, "webhook-url", config.WebhookURL, "Send a webhook request for new messages") rootCmd.Flags().IntVar(&webhook.RateLimit, "webhook-limit", webhook.RateLimit, "Limit webhook requests per second") @@ -195,6 +201,17 @@ func initConfigFromEnv() { config.SMTPRelayAllIncoming = true } + // POP3 + if len(os.Getenv("MP_POP3_BIND_ADDR")) > 0 { + config.POP3Listen = os.Getenv("MP_POP3_BIND_ADDR") + } + config.POP3AuthFile = os.Getenv("MP_POP3_AUTH_FILE") + if err := auth.SetPOP3Auth(os.Getenv("MP_POP3_AUTH")); err != nil { + logger.Log().Errorf(err.Error()) + } + config.POP3TLSCert = os.Getenv("MP_POP3_TLS_CERT") + config.POP3TLSKey = os.Getenv("MP_POP3_TLS_KEY") + // Webhook if len(os.Getenv("MP_WEBHOOK_URL")) > 0 { config.WebhookURL = os.Getenv("MP_WEBHOOK_URL") diff --git a/config/config.go b/config/config.go index 9b5ad8cf9..6e4868003 100644 --- a/config/config.go +++ b/config/config.go @@ -4,6 +4,7 @@ package config import ( "errors" "fmt" + "net" "net/url" "os" "path" @@ -112,6 +113,18 @@ var ( // Use with extreme caution! SMTPRelayAllIncoming = false + // POP3Listen address - if set then Mailpit will start the POP3 server and listen on this address + POP3Listen = "[::]:1110" + + // POP3AuthFile for POP3 authentication + POP3AuthFile string + + // POP3TLSCert TLS certificate + POP3TLSCert string + + // POP3TLSKey TLS certificate key + POP3TLSKey string + // EnableSpamAssassin must be either : or "postmark" EnableSpamAssassin string @@ -201,6 +214,7 @@ func VerifyConfig() error { if UITLSCert != "" { UITLSCert = filepath.Clean(UITLSCert) + UITLSKey = filepath.Clean(UITLSKey) if !isFile(UITLSCert) { return fmt.Errorf("[ui] TLS certificate not found: %s", UITLSCert) @@ -217,6 +231,7 @@ func VerifyConfig() error { if SMTPTLSCert != "" { SMTPTLSCert = filepath.Clean(SMTPTLSCert) + SMTPTLSKey = filepath.Clean(SMTPTLSKey) if !isFile(SMTPTLSCert) { return fmt.Errorf("[smtp] TLS certificate not found: %s", SMTPTLSCert) @@ -258,6 +273,46 @@ func VerifyConfig() error { return errors.New("[smtp] authentication requires TLS encryption, run with `--smtp-auth-allow-insecure` to allow insecure authentication") } + // POP3 server + if POP3TLSCert != "" { + POP3TLSCert = filepath.Clean(POP3TLSCert) + POP3TLSKey = filepath.Clean(POP3TLSKey) + + if !isFile(POP3TLSCert) { + return fmt.Errorf("[pop3] TLS certificate not found: %s", POP3TLSCert) + } + + if !isFile(POP3TLSKey) { + return fmt.Errorf("[pop3] TLS key not found: %s", POP3TLSKey) + } + } + if POP3TLSCert != "" && POP3TLSKey == "" || POP3TLSCert == "" && POP3TLSKey != "" { + return errors.New("[pop3] You must provide both a POP3 TLS certificate and a key") + } + if POP3Listen != "" { + _, err := net.ResolveTCPAddr("tcp", POP3Listen) + if err != nil { + return fmt.Errorf("[pop3] %s", err.Error()) + } + } + if POP3AuthFile != "" { + POP3AuthFile = filepath.Clean(POP3AuthFile) + + if !isFile(POP3AuthFile) { + return fmt.Errorf("[pop3] password file not found: %s", POP3AuthFile) + } + + b, err := os.ReadFile(POP3AuthFile) + if err != nil { + return err + } + + if err := auth.SetPOP3Auth(string(b)); err != nil { + return err + } + } + + // Web root validWebrootRe := regexp.MustCompile(`[^0-9a-zA-Z\/\-\_\.@]`) if validWebrootRe.MatchString(Webroot) { return fmt.Errorf("invalid characters in Webroot (%s). Valid chars include: [a-z A-Z 0-9 _ . - / @]", Webroot) diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 5bd9a9ddc..5225573e4 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -13,6 +13,8 @@ var ( UICredentials *htpasswd.File // SMTPCredentials passwords SMTPCredentials *htpasswd.File + // POP3Credentials passwords + POP3Credentials *htpasswd.File ) // SetUIAuth will set Basic Auth credentials required for the UI & API @@ -53,6 +55,25 @@ func SetSMTPAuth(s string) error { return nil } +// SetPOP3Auth will set POP3 server credentials +func SetPOP3Auth(s string) error { + var err error + + credentials := credentialsFromString(s) + if len(credentials) == 0 { + return nil + } + + r := strings.NewReader(strings.Join(credentials, "\n")) + + POP3Credentials, err = htpasswd.NewFromReader(r, htpasswd.DefaultSystems, nil) + if err != nil { + return err + } + + return nil +} + func credentialsFromString(s string) []string { // split string by any whitespace character re := regexp.MustCompile(`\s+`) diff --git a/internal/storage/messages.go b/internal/storage/messages.go index baa003682..d69a117b8 100644 --- a/internal/storage/messages.go +++ b/internal/storage/messages.go @@ -513,10 +513,12 @@ func MarkUnread(id string) error { // DeleteOneMessage will delete a single message from a mailbox func DeleteOneMessage(id string) error { - m, err := GetMessage(id) + m, err := GetMessageRaw(id) if err != nil { return err } + + size := len(m) // begin a transaction to ensure both the message // and data are deleted successfully tx, err := db.BeginTx(context.Background(), nil) @@ -548,7 +550,7 @@ func DeleteOneMessage(id string) error { } dbLastAction = time.Now() - addDeletedSize(int64(m.Size)) + addDeletedSize(int64(size)) logMessagesDeleted(1) diff --git a/server/pop3/functions.go b/server/pop3/functions.go new file mode 100644 index 000000000..0bd62af4d --- /dev/null +++ b/server/pop3/functions.go @@ -0,0 +1,76 @@ +package pop3 + +import ( + "errors" + "fmt" + "net" + "strings" + + "github.com/axllent/mailpit/internal/auth" + "github.com/axllent/mailpit/internal/logger" + "github.com/axllent/mailpit/internal/storage" +) + +func authUser(username, password string) bool { + return auth.POP3Credentials.Match(username, password) +} + +// Send a response with debug logging +func sendResponse(c net.Conn, m string) { + fmt.Fprintf(c, "%s\r\n", m) + logger.Log().Debugf("[pop3] response: %s", m) +} + +// Send a response without debug logging (for data) +func sendData(c net.Conn, m string) { + fmt.Fprintf(c, "%s\r\n", m) +} + +func getMessages() ([]message, error) { + messages := []message{} + list, err := storage.List(0, 100) + if err != nil { + return messages, err + } + + for _, m := range list { + msg := message{} + msg.ID = m.ID + msg.Size = m.Size + messages = append(messages, msg) + } + + return messages, nil +} + +// POP3 TOP command returns the headers, followed by the next x lines +func getTop(id string, nr int) (string, string, error) { + var header, body string + raw, err := storage.GetMessageRaw(id) + if err != nil { + return header, body, errors.New("-ERR no such message") + } + + parts := strings.SplitN(string(raw), "\r\n\r\n", 2) + header = parts[0] + lines := []string{} + if nr > 0 && len(parts) == 2 { + lines = strings.SplitN(parts[1], "\r\n", nr) + } + + return header, strings.Join(lines, "\r\n"), nil +} + +// cuts the line into command and arguments +func getCommand(line string) (string, []string) { + line = strings.Trim(line, "\r \n") + cmd := strings.Split(line, " ") + return cmd[0], cmd[1:] +} + +func getSafeArg(args []string, nr int) (string, error) { + if nr < len(args) { + return args[nr], nil + } + return "", errors.New("Out of range") +} diff --git a/server/pop3/pop3.go b/server/pop3/pop3.go new file mode 100644 index 000000000..43bf339e1 --- /dev/null +++ b/server/pop3/pop3.go @@ -0,0 +1,314 @@ +// Package pop3 is a simple POP3 server for Mailpit. +// By default it is disabled unless password credentials have been loaded. +// +// References: https://github.com/r0stig/golang-pop3 | https://github.com/inbucket/inbucket +// See RFC: https://datatracker.ietf.org/doc/html/rfc1939 +package pop3 + +import ( + "bufio" + "crypto/tls" + "fmt" + "net" + "strconv" + "strings" + "time" + + "github.com/axllent/mailpit/config" + "github.com/axllent/mailpit/internal/auth" + "github.com/axllent/mailpit/internal/logger" + "github.com/axllent/mailpit/internal/storage" + "github.com/axllent/mailpit/server/websockets" +) + +const ( + // UNAUTHORIZED state + UNAUTHORIZED = 1 + // TRANSACTION state + TRANSACTION = 2 + // UPDATE state + UPDATE = 3 +) + +// Run will start the pop3 server if enabled +func Run() { + if auth.POP3Credentials == nil || config.POP3Listen == "" { + // POP3 server is disabled without authentication + return + } + + var listener net.Listener + var err error + + if config.POP3TLSCert != "" { + cer, err := tls.LoadX509KeyPair(config.POP3TLSCert, config.POP3TLSKey) + if err != nil { + logger.Log().Errorf("[pop3] %s", err.Error()) + return + } + + tlsConfig := &tls.Config{ + Certificates: []tls.Certificate{cer}, + MinVersion: tls.VersionTLS12, + } + + listener, err = tls.Listen("tcp", config.POP3Listen, tlsConfig) + } else { + // unencrypted + listener, err = net.Listen("tcp", config.POP3Listen) + } + + if err != nil { + logger.Log().Errorf("[pop3] %s", err.Error()) + return + } + + logger.Log().Infof("[pop3] starting on %s", config.POP3Listen) + + for { + conn, err := listener.Accept() + if err != nil { + continue + } + + // run as goroutine + go handleClient(conn) + } +} + +type message struct { + ID string + Size int +} + +func handleClient(conn net.Conn) { + + var ( + user = "" + state = 1 + toDelete = []string{} + ) + + defer func() { + if state == UPDATE { + for _, id := range toDelete { + _ = storage.DeleteOneMessage(id) + } + if len(toDelete) > 0 { + // update web UI to remove deleted messages + websockets.Broadcast("prune", nil) + } + } + + if err := conn.Close(); err != nil { + logger.Log().Errorf("[pop3] %s", err.Error()) + } + }() + + reader := bufio.NewReader(conn) + + messages := []message{} + + // State + // 1 = Unauthorized + // 2 = Transaction mode + // 3 = update mode + + logger.Log().Debugf("[pop3] connection opened by %s", conn.RemoteAddr().String()) + + // First welcome the new connection + sendResponse(conn, "+OK Mailpit POP3 server") + + timeoutDuration := 30 * time.Second + + for { + // POP3 server enforced a timeout of 30 seconds + if err := conn.SetDeadline(time.Now().Add(timeoutDuration)); err != nil { + logger.Log().Errorf("[pop3] %s", err.Error()) + return + } + + // Reads a line from the client + rawLine, err := reader.ReadString('\n') + if err != nil { + logger.Log().Errorf("[pop3] %s", err.Error()) + return + } + + // Parses the command + cmd, args := getCommand(rawLine) + + logger.Log().Debugf("[pop3] received: %s (%s)", strings.TrimSpace(rawLine), conn.RemoteAddr().String()) + + if cmd == "CAPA" { + // List our capabilities per RFC2449 + sendResponse(conn, "+OK Capability list follows") + sendResponse(conn, "TOP") + sendResponse(conn, "USER") + sendResponse(conn, "UIDL") + sendResponse(conn, "IMPLEMENTATION Mailpit") + sendResponse(conn, ".") + continue + } else if cmd == "USER" && state == UNAUTHORIZED { + if len(args) != 1 { + sendResponse(conn, "-ERR must supply a user") + return + } + // always true - stash for PASS + sendResponse(conn, "+OK") + user = args[0] + + } else if cmd == "PASS" && state == UNAUTHORIZED { + if len(args) != 1 { + sendResponse(conn, "-ERR must supply a password") + return + } + + pass := args[0] + if authUser(user, pass) { + sendResponse(conn, "+OK signed in") + messages, err = getMessages() + if err != nil { + logger.Log().Errorf("[pop3] %s", err.Error()) + } + state = 2 + } else { + sendResponse(conn, "-ERR invalid password") + logger.Log().Warnf("[pop3] failed login: %s", user) + } + + } else if cmd == "STAT" && state == TRANSACTION { + totalSize := 0 + for _, m := range messages { + totalSize = totalSize + m.Size + } + + sendResponse(conn, fmt.Sprintf("+OK %d %d", len(messages), totalSize)) + + } else if cmd == "LIST" && state == TRANSACTION { + totalSize := 0 + for _, m := range messages { + totalSize = totalSize + m.Size + } + sendData(conn, fmt.Sprintf("+OK %d messages (%d octets)", len(messages), totalSize)) + + // print all sizes + for row, m := range messages { + sendData(conn, fmt.Sprintf("%d %d", row+1, m.Size)) + } + // end + sendData(conn, ".") + + } else if cmd == "UIDL" && state == TRANSACTION { + totalSize := 0 + for _, m := range messages { + totalSize = totalSize + m.Size + } + + sendData(conn, "+OK unique-id listing follows") + + // print all message IDS + for row, m := range messages { + sendData(conn, fmt.Sprintf("%d %s", row+1, m.ID)) + } + // end + sendData(conn, ".") + + } else if cmd == "RETR" && state == TRANSACTION { + if len(args) != 1 { + sendResponse(conn, "-ERR no such message") + return + } + + nr, err := strconv.Atoi(args[0]) + if err != nil { + sendResponse(conn, "-ERR no such message") + return + } + + if nr < 1 || nr > len(messages) { + sendResponse(conn, "-ERR no such message") + return + } + + m := messages[nr-1] + raw, err := storage.GetMessageRaw(m.ID) + if err != nil { + sendResponse(conn, "-ERR no such message") + return + } + + size := len(raw) + sendData(conn, fmt.Sprintf("+OK %d octets", size)) + sendData(conn, string(raw)) + sendData(conn, ".") + + } else if cmd == "TOP" && state == TRANSACTION { + arg, err := getSafeArg(args, 0) + if err != nil { + sendResponse(conn, "-ERR TOP requires two arguments") + return + } + nr, err := strconv.Atoi(arg) + if err != nil { + sendResponse(conn, "-ERR TOP requires two arguments") + return + } + + if nr < 1 || nr > len(messages) { + sendResponse(conn, "-ERR no such message") + return + } + arg2, err := getSafeArg(args, 1) + if err != nil { + sendResponse(conn, "-ERR TOP requires two arguments") + return + } + + lines, err := strconv.Atoi(arg2) + if err != nil { + sendResponse(conn, "-ERR TOP requires two arguments") + return + } + + m := messages[nr-1] + headers, body, err := getTop(m.ID, lines) + + sendData(conn, "+OK Top of message follows") + sendData(conn, headers+"\r\n") + sendData(conn, body) + sendData(conn, ".") + + } else if cmd == "NOOP" && state == TRANSACTION { + sendData(conn, "+OK") + } else if cmd == "DELE" && state == TRANSACTION { + arg, _ := getSafeArg(args, 0) + nr, err := strconv.Atoi(arg) + if err != nil { + logger.Log().Warnf("[pop3] -ERR invalid DELETE integer: %s", arg) + sendResponse(conn, "-ERR invalid integer") + return + } + + if nr < 1 || nr > len(messages) { + logger.Log().Warnf("[pop3] -ERR no such message") + sendResponse(conn, "-ERR no such message") + return + } + toDelete = append(toDelete, messages[nr-1].ID) + + sendResponse(conn, "+OK") + + } else if cmd == "RSET" && state == TRANSACTION { + toDelete = []string{} + sendData(conn, "+OK") + + } else if cmd == "QUIT" { + state = UPDATE + return + } else { + logger.Log().Warnf("[pop3] -ERR %s not implemented", cmd) + sendResponse(conn, fmt.Sprintf("-ERR %s not implemented", cmd)) + } + } +} diff --git a/server/server.go b/server/server.go index 54158389f..4d0c9d17d 100644 --- a/server/server.go +++ b/server/server.go @@ -22,6 +22,7 @@ import ( "github.com/axllent/mailpit/internal/storage" "github.com/axllent/mailpit/server/apiv1" "github.com/axllent/mailpit/server/handlers" + "github.com/axllent/mailpit/server/pop3" "github.com/axllent/mailpit/server/websockets" "github.com/gorilla/mux" ) @@ -48,6 +49,8 @@ func Listen() { go websockets.MessageHub.Run() + go pop3.Run() + r := apiRoutes() // kubernetes probes From e8c306b7ab1c06a0a0a41b83a1767da504b48085 Mon Sep 17 00:00:00 2001 From: Ralph Slooten Date: Sat, 24 Feb 2024 23:10:58 +1300 Subject: [PATCH 08/11] Update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 938684bae..26b6e5198 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ via either HTTPS or `localhost` only) including an optional allowlist of accepted recipients - Fast SMTP processing & storing - approximately 70-100 emails per second depending on CPU, network speed & email size, easily handling tens of thousands of emails +- Optional [POP3 server](https://mailpit.axllent.org/docs/configuration/pop3/) to download captured message directly into your email client - Configurable automatic email pruning (default keeps the most recent 500 emails) - A simple [REST API](https://mailpit.axllent.org/docs/api-v1/) for integration testing - Optional [webhook](https://mailpit.axllent.org/docs/integration/webhook/) for received messages From e55d4aab599107f00f598e329222967a17b8ef31 Mon Sep 17 00:00:00 2001 From: Ralph Slooten Date: Sat, 24 Feb 2024 23:16:04 +1300 Subject: [PATCH 09/11] Chore: Update Go dependencies --- go.mod | 18 +++++++----------- go.sum | 46 ++++++++++++++-------------------------------- 2 files changed, 21 insertions(+), 43 deletions(-) diff --git a/go.mod b/go.mod index 948104677..6849066cf 100644 --- a/go.mod +++ b/go.mod @@ -4,14 +4,14 @@ go 1.20 require ( github.com/GuiaBolso/darwin v0.0.0-20191218124601-fd6d2aa3d244 - github.com/PuerkitoBio/goquery v1.8.1 + github.com/PuerkitoBio/goquery v1.9.0 github.com/axllent/semver v0.0.1 github.com/disintegration/imaging v1.6.2 github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47 github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.1 - github.com/jhillyerd/enmime v1.1.0 - github.com/klauspost/compress v1.17.6 + github.com/jhillyerd/enmime v1.2.0 + github.com/klauspost/compress v1.17.7 github.com/leporo/sqlf v1.4.0 github.com/lithammer/shortuuid/v4 v4.0.0 github.com/mhale/smtpd v0.8.2 @@ -25,7 +25,7 @@ require ( golang.org/x/text v0.14.0 golang.org/x/time v0.5.0 gopkg.in/yaml.v3 v3.0.1 - modernc.org/sqlite v1.28.0 + modernc.org/sqlite v1.29.1 ) require ( @@ -38,9 +38,9 @@ require ( github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/css v1.0.1 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 // indirect - github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kr/pretty v0.3.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect @@ -55,17 +55,13 @@ require ( github.com/vanng822/css v1.0.1 // indirect golang.org/x/crypto v0.19.0 // indirect golang.org/x/image v0.15.0 // indirect - golang.org/x/mod v0.15.0 // indirect golang.org/x/sys v0.17.0 // indirect - golang.org/x/tools v0.17.0 // indirect + golang.org/x/tools v0.18.0 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect - lukechampine.com/uint128 v1.3.0 // indirect - modernc.org/cc/v3 v3.41.0 // indirect - modernc.org/ccgo/v3 v3.16.15 // indirect + modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect modernc.org/libc v1.41.0 // indirect modernc.org/mathutil v1.6.0 // indirect modernc.org/memory v1.7.2 // indirect - modernc.org/opt v0.1.3 // indirect modernc.org/strutil v1.2.0 // indirect modernc.org/token v1.1.0 // indirect ) diff --git a/go.sum b/go.sum index 2d7f0d6ea..27488c654 100644 --- a/go.sum +++ b/go.sum @@ -5,10 +5,9 @@ github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5/go.mod h1:exZ0C/1e github.com/GuiaBolso/darwin v0.0.0-20191218124601-fd6d2aa3d244 h1:dqzm54OhCqY8RinR/cx+Ppb0y56Ds5I3wwWhx4XybDg= github.com/GuiaBolso/darwin v0.0.0-20191218124601-fd6d2aa3d244/go.mod h1:3sqgkckuISJ5rs1EpOp6vCvwOUKe/z9vPmyuIlq8Q/A= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= -github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM= -github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= +github.com/PuerkitoBio/goquery v1.9.0 h1:zgjKkdpRY9T97Q5DCtcXwfqkcylSFIVCocZmn2huTp8= +github.com/PuerkitoBio/goquery v1.9.0/go.mod h1:cW1n6TmIMDoORQU5IU/P1T3tGFunOeXEpGP2WHRwkbY= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= -github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= github.com/axllent/semver v0.0.1 h1:QqF+KSGxgj8QZzSXAvKFqjGWE5792ksOnQhludToK8E= @@ -53,7 +52,6 @@ github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47 h1:k4Tw0nt6lwro3Uin8eqoET7MDA4JnT8YgbCjc/g5E3k= github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -65,16 +63,16 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 h1:iCHtR9CQyktQ5+f3dMVZfwD2KWJUgm7M0gdL9NGr8KA= github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= -github.com/jhillyerd/enmime v1.1.0 h1:ubaIzg68VY7CMCe2YbHe6nkRvU9vujixTkNz3EBvZOw= -github.com/jhillyerd/enmime v1.1.0/go.mod h1:FRFuUPCLh8PByQv+8xRcLO9QHqaqTqreYhopv5eyk4I= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= -github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/jhillyerd/enmime v1.2.0 h1:dIu1IPEymQgoT2dzuB//ttA/xcV40NMPpQtmd4wslHk= +github.com/jhillyerd/enmime v1.2.0/go.mod h1:FRFuUPCLh8PByQv+8xRcLO9QHqaqTqreYhopv5eyk4I= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -154,29 +152,24 @@ golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -192,7 +185,6 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= @@ -204,8 +196,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= +golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -215,27 +207,17 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo= -lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc/v3 v3.41.0 h1:QoR1Sn3YWlmA1T4vLaKZfawdVtSiGx8H+cEojbC7v1Q= -modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y= -modernc.org/ccgo/v3 v3.16.15 h1:KbDR3ZAVU+wiLyMESPtbtE/Add4elztFyfsWoNTgxS0= -modernc.org/ccgo/v3 v3.16.15/go.mod h1:yT7B+/E2m43tmMOT51GMoM98/MtHIcQQSleGnddkUNI= -modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= -modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk= modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= -modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sqlite v1.28.0 h1:Zx+LyDDmXczNnEQdvPuEfcFVA2ZPyaD7UCZDjef3BHQ= -modernc.org/sqlite v1.28.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0= +modernc.org/sqlite v1.29.1 h1:19GY2qvWB4VPw0HppFlZCPAbmxFU41r+qjKZQdQ1ryA= +modernc.org/sqlite v1.29.1/go.mod h1:hG41jCYxOAOoO6BRK66AdRlmOcDzXf7qnwlwjUIOqa0= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= -modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY= From 9892375366c697b98cd9af4f92f1674133834999 Mon Sep 17 00:00:00 2001 From: Ralph Slooten Date: Sat, 24 Feb 2024 23:20:27 +1300 Subject: [PATCH 10/11] Chore: Update node dependencies --- package-lock.json | 1171 +++++++++++++++++++++++++++------------------ 1 file changed, 695 insertions(+), 476 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0b136d325..04e7ed1cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,12 +66,13 @@ "version": "1.7.2", "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-1.7.2.tgz", "integrity": "sha512-i5GE2Dk5ekdlK1TR7SugY4LWRrKSfb5T1Qn4unpIMbfxoeGKERKQ59HG3iYewacGD10SR7UzevfPnh6my4tNmQ==", - "dev": true + "dev": true, + "peer": true }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.0.tgz", - "integrity": "sha512-fGFDEctNh0CcSwsiRPxiaqX0P5rq+AqE0SRhYGZ4PX46Lg1FNR6oCxJghf8YgY0WQEgQuh3lErUFE4KxLeRmmw==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.1.tgz", + "integrity": "sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==", "cpu": [ "ppc64" ], @@ -85,9 +86,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.0.tgz", - "integrity": "sha512-3bMAfInvByLHfJwYPJRlpTeaQA75n8C/QKpEaiS4HrFWFiJlNI0vzq/zCjBrhAYcPyVPG7Eo9dMrcQXuqmNk5g==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.1.tgz", + "integrity": "sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==", "cpu": [ "arm" ], @@ -101,9 +102,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.0.tgz", - "integrity": "sha512-aVpnM4lURNkp0D3qPoAzSG92VXStYmoVPOgXveAUoQBWRSuQzt51yvSju29J6AHPmwY1BjH49uR29oyfH1ra8Q==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.1.tgz", + "integrity": "sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==", "cpu": [ "arm64" ], @@ -117,9 +118,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.0.tgz", - "integrity": "sha512-uK7wAnlRvjkCPzh8jJ+QejFyrP8ObKuR5cBIsQZ+qbMunwR8sbd8krmMbxTLSrDhiPZaJYKQAU5Y3iMDcZPhyQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.1.tgz", + "integrity": "sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==", "cpu": [ "x64" ], @@ -133,9 +134,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.0.tgz", - "integrity": "sha512-AjEcivGAlPs3UAcJedMa9qYg9eSfU6FnGHJjT8s346HSKkrcWlYezGE8VaO2xKfvvlZkgAhyvl06OJOxiMgOYQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.1.tgz", + "integrity": "sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==", "cpu": [ "arm64" ], @@ -149,9 +150,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.0.tgz", - "integrity": "sha512-bsgTPoyYDnPv8ER0HqnJggXK6RyFy4PH4rtsId0V7Efa90u2+EifxytE9pZnsDgExgkARy24WUQGv9irVbTvIw==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.1.tgz", + "integrity": "sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==", "cpu": [ "x64" ], @@ -165,9 +166,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.0.tgz", - "integrity": "sha512-kQ7jYdlKS335mpGbMW5tEe3IrQFIok9r84EM3PXB8qBFJPSc6dpWfrtsC/y1pyrz82xfUIn5ZrnSHQQsd6jebQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.1.tgz", + "integrity": "sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==", "cpu": [ "arm64" ], @@ -181,9 +182,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.0.tgz", - "integrity": "sha512-uG8B0WSepMRsBNVXAQcHf9+Ko/Tr+XqmK7Ptel9HVmnykupXdS4J7ovSQUIi0tQGIndhbqWLaIL/qO/cWhXKyQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.1.tgz", + "integrity": "sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==", "cpu": [ "x64" ], @@ -197,9 +198,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.0.tgz", - "integrity": "sha512-2ezuhdiZw8vuHf1HKSf4TIk80naTbP9At7sOqZmdVwvvMyuoDiZB49YZKLsLOfKIr77+I40dWpHVeY5JHpIEIg==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.1.tgz", + "integrity": "sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==", "cpu": [ "arm" ], @@ -213,9 +214,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.0.tgz", - "integrity": "sha512-uTtyYAP5veqi2z9b6Gr0NUoNv9F/rOzI8tOD5jKcCvRUn7T60Bb+42NDBCWNhMjkQzI0qqwXkQGo1SY41G52nw==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.1.tgz", + "integrity": "sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==", "cpu": [ "arm64" ], @@ -229,9 +230,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.0.tgz", - "integrity": "sha512-c88wwtfs8tTffPaoJ+SQn3y+lKtgTzyjkD8NgsyCtCmtoIC8RDL7PrJU05an/e9VuAke6eJqGkoMhJK1RY6z4w==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.1.tgz", + "integrity": "sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==", "cpu": [ "ia32" ], @@ -245,9 +246,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.0.tgz", - "integrity": "sha512-lR2rr/128/6svngnVta6JN4gxSXle/yZEZL3o4XZ6esOqhyR4wsKyfu6qXAL04S4S5CgGfG+GYZnjFd4YiG3Aw==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.1.tgz", + "integrity": "sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==", "cpu": [ "loong64" ], @@ -261,9 +262,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.0.tgz", - "integrity": "sha512-9Sycc+1uUsDnJCelDf6ZNqgZQoK1mJvFtqf2MUz4ujTxGhvCWw+4chYfDLPepMEvVL9PDwn6HrXad5yOrNzIsQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.1.tgz", + "integrity": "sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==", "cpu": [ "mips64el" ], @@ -277,9 +278,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.0.tgz", - "integrity": "sha512-CoWSaaAXOZd+CjbUTdXIJE/t7Oz+4g90A3VBCHLbfuc5yUQU/nFDLOzQsN0cdxgXd97lYW/psIIBdjzQIwTBGw==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.1.tgz", + "integrity": "sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==", "cpu": [ "ppc64" ], @@ -293,9 +294,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.0.tgz", - "integrity": "sha512-mlb1hg/eYRJUpv8h/x+4ShgoNLL8wgZ64SUr26KwglTYnwAWjkhR2GpoKftDbPOCnodA9t4Y/b68H4J9XmmPzA==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.1.tgz", + "integrity": "sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==", "cpu": [ "riscv64" ], @@ -309,9 +310,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.0.tgz", - "integrity": "sha512-fgf9ubb53xSnOBqyvWEY6ukBNRl1mVX1srPNu06B6mNsNK20JfH6xV6jECzrQ69/VMiTLvHMicQR/PgTOgqJUQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.1.tgz", + "integrity": "sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==", "cpu": [ "s390x" ], @@ -325,9 +326,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.0.tgz", - "integrity": "sha512-H9Eu6MGse++204XZcYsse1yFHmRXEWgadk2N58O/xd50P9EvFMLJTQLg+lB4E1cF2xhLZU5luSWtGTb0l9UeSg==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz", + "integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==", "cpu": [ "x64" ], @@ -341,9 +342,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.0.tgz", - "integrity": "sha512-lCT675rTN1v8Fo+RGrE5KjSnfY0x9Og4RN7t7lVrN3vMSjy34/+3na0q7RIfWDAj0e0rCh0OL+P88lu3Rt21MQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.1.tgz", + "integrity": "sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==", "cpu": [ "x64" ], @@ -357,9 +358,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.0.tgz", - "integrity": "sha512-HKoUGXz/TOVXKQ+67NhxyHv+aDSZf44QpWLa3I1lLvAwGq8x1k0T+e2HHSRvxWhfJrFxaaqre1+YyzQ99KixoA==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.1.tgz", + "integrity": "sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==", "cpu": [ "x64" ], @@ -373,9 +374,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.0.tgz", - "integrity": "sha512-GDwAqgHQm1mVoPppGsoq4WJwT3vhnz/2N62CzhvApFD1eJyTroob30FPpOZabN+FgCjhG+AgcZyOPIkR8dfD7g==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.1.tgz", + "integrity": "sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==", "cpu": [ "x64" ], @@ -389,9 +390,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.0.tgz", - "integrity": "sha512-0vYsP8aC4TvMlOQYozoksiaxjlvUcQrac+muDqj1Fxy6jh9l9CZJzj7zmh8JGfiV49cYLTorFLxg7593pGldwQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.1.tgz", + "integrity": "sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==", "cpu": [ "arm64" ], @@ -405,9 +406,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.0.tgz", - "integrity": "sha512-p98u4rIgfh4gdpV00IqknBD5pC84LCub+4a3MO+zjqvU5MVXOc3hqR2UgT2jI2nh3h8s9EQxmOsVI3tyzv1iFg==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.1.tgz", + "integrity": "sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==", "cpu": [ "ia32" ], @@ -421,9 +422,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.0.tgz", - "integrity": "sha512-NgJnesu1RtWihtTtXGFMU5YSE6JyyHPMxCwBZK7a6/8d31GuSo9l0Ss7w1Jw5QnKUawG6UEehs883kcXf5fYwg==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz", + "integrity": "sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==", "cpu": [ "x64" ], @@ -436,14 +437,6 @@ "node": ">=12" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", - "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==", - "engines": { - "node": ">=14" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", @@ -472,12 +465,12 @@ } }, "node_modules/@swagger-api/apidom-ast": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ast/-/apidom-ast-0.94.0.tgz", - "integrity": "sha512-blHBtP/2Qc8Cxd37VC83FjWzpsxLNwbrRlwK/IBwopOV7bxwuzO2SFe/32Dj+RBhfhvjdNQZw/yjekulZC5/9w==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ast/-/apidom-ast-0.95.0.tgz", + "integrity": "sha512-hYv4gED2aG/4eZXloenPaS2EW9hEewfkm9GCJ+3zchYWNctHgcq5O/LHQfYzvlsldNoNWSFEVtjb9v2rs8qA0g==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-error": "^0.94.0", + "@swagger-api/apidom-error": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", @@ -485,13 +478,13 @@ } }, "node_modules/@swagger-api/apidom-core": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-core/-/apidom-core-0.94.0.tgz", - "integrity": "sha512-OR0fZ8AD5qut+7Qr3dLbeWfOmkV2NjHS/bQdd1V+pNfA1P1Azi+hetXhFr68BCV6sKPvG9IfoFGx2uIfOLCUKA==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-core/-/apidom-core-0.95.0.tgz", + "integrity": "sha512-SWnFJX8sUP2cAgH1c62bOpQZm2ye0Dbgrgd+NZ8umSWtkz9rFLrSvBgy8QobaDMDvmQo9Kv60srnP3tvu5A9oQ==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.94.0", - "@swagger-api/apidom-error": "^0.94.0", + "@swagger-api/apidom-ast": "^0.95.0", + "@swagger-api/apidom-error": "^0.95.0", "@types/ramda": "~0.29.6", "minim": "~0.23.8", "ramda": "~0.29.1", @@ -501,36 +494,36 @@ } }, "node_modules/@swagger-api/apidom-error": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-error/-/apidom-error-0.94.0.tgz", - "integrity": "sha512-E9x34fT8YSoJ5s1MGNnBWxB5sB6BugYDrfBCT7SG7NysNKkn+gtqJroW07w7mNN17Mc1ssx/z0JjU10F3tZtTA==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-error/-/apidom-error-0.95.0.tgz", + "integrity": "sha512-yh8TZZrtqR60g91ed/lu1KRDF2Z+Vv82dpf859TU1xJL7mhcPQG7aptc129cfUkla/+d9edNJDHNsnWUQPw7+A==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7" } }, "node_modules/@swagger-api/apidom-json-pointer": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-json-pointer/-/apidom-json-pointer-0.94.0.tgz", - "integrity": "sha512-DGBJRVpw5UtFS+0InNZsiv24nTovtN0uZou4eK5kt24IdxrECBYdyP01seL8d52hLReUaoaUeoEigrwDcxosTQ==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-json-pointer/-/apidom-json-pointer-0.95.0.tgz", + "integrity": "sha512-aqszOa4UenYC5B7MlcU0tkL4yQJ0OSJhUS0uBpKJatao9mZZ0yRv8eB2TIMeAN0MkuDfyYphkKdmAVgIxZ9SeQ==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-error": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-error": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, "node_modules/@swagger-api/apidom-ns-api-design-systems": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-api-design-systems/-/apidom-ns-api-design-systems-0.94.0.tgz", - "integrity": "sha512-ULOueL2npma+JPSBXCDcb4+OEid6wZIb4ujCCo2F/zrgFG6hHt/W0F15yXh1W+qv9CFa5c/sAf1vU625APMQYQ==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-api-design-systems/-/apidom-ns-api-design-systems-0.95.0.tgz", + "integrity": "sha512-fkLwhp+MSIZXr5Fu1oOGuQDTguLIDv6OOKthXYqWnfh/UVpdZgaClXxxDkXaW6EnIiPujtj5j4i52/y5z+fBew==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-error": "^0.94.0", - "@swagger-api/apidom-ns-openapi-3-1": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-error": "^0.95.0", + "@swagger-api/apidom-ns-openapi-3-1": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", @@ -538,28 +531,28 @@ } }, "node_modules/@swagger-api/apidom-ns-asyncapi-2": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-asyncapi-2/-/apidom-ns-asyncapi-2-0.94.0.tgz", - "integrity": "sha512-heNdqH/gsdx+o0ev6EFcH8BtjoMnrJTi8rhOnma18dVFmtUna964siqWGfT98Ft7DTfPIur3g6e6m5wGowRoKQ==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-asyncapi-2/-/apidom-ns-asyncapi-2-0.95.0.tgz", + "integrity": "sha512-WuETyax2c2wRJporR5tdcPgyhwxH/2H2UxydZMuk6cp/ix4784tcourpXdEKDH9X15kE8qnQTWT5KMQmw6R1og==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-ns-json-schema-draft-7": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-ns-json-schema-draft-7": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", - "stampit": "^4.3.2" + "ts-mixer": "^6.0.3" } }, "node_modules/@swagger-api/apidom-ns-json-schema-draft-4": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-4/-/apidom-ns-json-schema-draft-4-0.94.0.tgz", - "integrity": "sha512-Q3ExAtywZuoIhk87yK9Vomm/jDWshqDsf5m2X4k5TZeoCL8anvU0X6xaOPTqt0AelLHSNK4D0wO29V3okxPIcg==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-4/-/apidom-ns-json-schema-draft-4-0.95.0.tgz", + "integrity": "sha512-JtePOEMfyGCyqWuzW+IAoCjaXJfQT/GVqcQSB/tHltU8yFOKygEnguV1eGeu22HvIk1UlE9K55XZ8SVu76pO5w==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.94.0", - "@swagger-api/apidom-core": "^0.94.0", + "@swagger-api/apidom-ast": "^0.95.0", + "@swagger-api/apidom-core": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", @@ -567,15 +560,15 @@ } }, "node_modules/@swagger-api/apidom-ns-json-schema-draft-6": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-6/-/apidom-ns-json-schema-draft-6-0.94.0.tgz", - "integrity": "sha512-anTa6Y1foQ/CkOTQWqCgUzpvCPVmKUs0YKM2oRZynVbBRBzHdEybTawHaYtwJq9zinHSEYsqMq1QEDi5kNcziQ==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-6/-/apidom-ns-json-schema-draft-6-0.95.0.tgz", + "integrity": "sha512-KPtt6Dp7UOGm/MCYe2s8VsNR9usmk52Wj0FX6hkb4x8Mc6+RFvIM4grZuHuo+kgpaGC5NPC86LMsaB2joy3MfQ==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-error": "^0.94.0", - "@swagger-api/apidom-ns-json-schema-draft-4": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-error": "^0.95.0", + "@swagger-api/apidom-ns-json-schema-draft-4": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", @@ -583,15 +576,15 @@ } }, "node_modules/@swagger-api/apidom-ns-json-schema-draft-7": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-7/-/apidom-ns-json-schema-draft-7-0.94.0.tgz", - "integrity": "sha512-GAXFo3o0Y1p7eUHiJ4bxCvYH0h9/dHhLoSBdE+boU9hdb2LxFqaAcp3YYCiVwvyGcZe7kdKE0+WDAFysKyLHeA==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-7/-/apidom-ns-json-schema-draft-7-0.95.0.tgz", + "integrity": "sha512-J7zrSmw308cTkZBjEN2RFyejFVNUEcLZGbo6Pfh3Is4BTBnStAc0/sHumLOPx1r1asJNXFul9AxPnMZxtMKzfQ==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-error": "^0.94.0", - "@swagger-api/apidom-ns-json-schema-draft-6": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-error": "^0.95.0", + "@swagger-api/apidom-ns-json-schema-draft-6": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", @@ -599,15 +592,15 @@ } }, "node_modules/@swagger-api/apidom-ns-openapi-2": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-2/-/apidom-ns-openapi-2-0.94.0.tgz", - "integrity": "sha512-jtrYrNvuQweQ+voaBdglWsAQhxR+FpzoMm/qX0+mws5jQg73JcTUEJmGzgmXGMQKGoxCimM2i98d1CWnZpYi6g==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-2/-/apidom-ns-openapi-2-0.95.0.tgz", + "integrity": "sha512-kag5DA32gptTtMd6fl0sKz0G9V7Ys1HA/eGlsPQVIdG2XYNn0DI+9Xek/D2cajuXJkdt907Ja+7ySGIoFvq49w==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-error": "^0.94.0", - "@swagger-api/apidom-ns-json-schema-draft-4": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-error": "^0.95.0", + "@swagger-api/apidom-ns-json-schema-draft-4": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", @@ -615,14 +608,14 @@ } }, "node_modules/@swagger-api/apidom-ns-openapi-3-0": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-0/-/apidom-ns-openapi-3-0-0.94.0.tgz", - "integrity": "sha512-JcPhaPjIoywy6to0MU+59v0UW6Dg+A2iwxOtzZwa+HryQhPC5jHOQ8ABrOvSCqXOslMJKNOgUGH5bcDpF8M3ug==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-0/-/apidom-ns-openapi-3-0-0.95.0.tgz", + "integrity": "sha512-IAsnRx/ViUXVBZqivTG6C91roY48QlnuVejQps/gBzxHNkeb2OBalF+9BCXG0C8mj0fxqouNnz1clfpgOP+sGQ==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-error": "^0.94.0", - "@swagger-api/apidom-ns-json-schema-draft-4": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-error": "^0.95.0", + "@swagger-api/apidom-ns-json-schema-draft-4": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", @@ -630,14 +623,14 @@ } }, "node_modules/@swagger-api/apidom-ns-openapi-3-1": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-1/-/apidom-ns-openapi-3-1-0.94.0.tgz", - "integrity": "sha512-Ja+01FIMUmemu4c2Egz/Nti9zp+joE+Wc8+ZrdfCQw4ola+Y4+zWu4EwaRBIhoWGc9Vb5283bOmsgdxPLblUfA==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-1/-/apidom-ns-openapi-3-1-0.95.0.tgz", + "integrity": "sha512-oPVelaDpHSSZtLXMA13SwZa+3KTeO7qtaqs1XQD3EYYZbyRoNl74xIHeDCKEi94MnzpwnjIW81mFI8u2vmW5dA==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.94.0", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-ns-openapi-3-0": "^0.94.0", + "@swagger-api/apidom-ast": "^0.95.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-ns-openapi-3-0": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", @@ -645,14 +638,14 @@ } }, "node_modules/@swagger-api/apidom-ns-workflows-1": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-workflows-1/-/apidom-ns-workflows-1-0.94.0.tgz", - "integrity": "sha512-tEpyhm637pAhAP2KS2xcBcu09FpUUxhYD+oVVQpAzUDzFANHx/PWSmnVPMMwamykNne+IRGj19gGBVrrWJex7Q==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-workflows-1/-/apidom-ns-workflows-1-0.95.0.tgz", + "integrity": "sha512-YQZl0Mm2ELjEG6uJtxEbKKRXsZO0ftAWdLwFmIPbIPfesGilOYJFCe8vEcKKwP3lLq8A4pyn3VCsF457JXiL5Q==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-ns-openapi-3-1": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-ns-openapi-3-1": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", @@ -660,75 +653,75 @@ } }, "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-json": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-json/-/apidom-parser-adapter-api-design-systems-json-0.94.0.tgz", - "integrity": "sha512-cW/OiGb+ZIp2eGbjpjBU3S/6w/ewFEm6yP27SyWRHaR8JV6pzTkCpuB/22vY2yLH3bt2C/XO64nVetP7LsnWzQ==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-json/-/apidom-parser-adapter-api-design-systems-json-0.95.0.tgz", + "integrity": "sha512-rWmtf29bHnRNoE561nE3uPqpxnMqgDBnRq+veYyVRsIhg1AtpDpgl4nYJUzZ2Tg9Zn5Y/WBuZLeBhj06xVCgPg==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-ns-api-design-systems": "^0.94.0", - "@swagger-api/apidom-parser-adapter-json": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-ns-api-design-systems": "^0.95.0", + "@swagger-api/apidom-parser-adapter-json": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-api-design-systems-yaml": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-yaml/-/apidom-parser-adapter-api-design-systems-yaml-0.94.0.tgz", - "integrity": "sha512-viB6WUGoS9x8ZCT87L+xh/C7mmXJ0Ed3CmpE3EGecLybE7eMcGpdUi6GHrj+32IoucsFXQJXnHJriInnoW+fiQ==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-api-design-systems-yaml/-/apidom-parser-adapter-api-design-systems-yaml-0.95.0.tgz", + "integrity": "sha512-5GRO2Fc+q5w3iNo0QBsge4n/WNr3IY2SRvrQKDHrXVF+tG6PFoKh+EXAOxzgUrcCy2A9R/bj2V+4xcdtZvxdxw==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-ns-api-design-systems": "^0.94.0", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-ns-api-design-systems": "^0.95.0", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-json-2": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-json-2/-/apidom-parser-adapter-asyncapi-json-2-0.94.0.tgz", - "integrity": "sha512-0Nr7YXcdP8MbWqLN6mb6L4SIu0OAIYzCjVINDzN8N1LchSYLTpboZ82ZA52djuaJTzdKwoJEb8yWpWk0pb1TkQ==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-json-2/-/apidom-parser-adapter-asyncapi-json-2-0.95.0.tgz", + "integrity": "sha512-bd1zc3s50J7o7CYz8TMqco/Vs8HxpbMAYgiCFaKe6kbGjQtjnOFI9qcs+PkwhPrD6ici/B1IXrcPKhHGlTtwFw==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-ns-asyncapi-2": "^0.94.0", - "@swagger-api/apidom-parser-adapter-json": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-ns-asyncapi-2": "^0.95.0", + "@swagger-api/apidom-parser-adapter-json": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2/-/apidom-parser-adapter-asyncapi-yaml-2-0.94.0.tgz", - "integrity": "sha512-z5k3D/f0fngDiVzfd9SXSOOwsDZe5chMMnQ92bA3SEPxlSanQw1hnjN1YzZUWZSdBBJg6ghg9oxyuUjAH9/Q5g==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-asyncapi-yaml-2/-/apidom-parser-adapter-asyncapi-yaml-2-0.95.0.tgz", + "integrity": "sha512-zSs9mGSWgufjLfg0P3qCj/wSvSf7rro3a5/wQ/lS4jpKuh1T0B+jHOS4kQZmXL32NJk/uSBGI4YLWodxaaOUCw==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-ns-asyncapi-2": "^0.94.0", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-ns-asyncapi-2": "^0.95.0", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-json": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-json/-/apidom-parser-adapter-json-0.94.0.tgz", - "integrity": "sha512-CWXspGilYU4kk6c96E/RBkeNw3HsTQzLTACJ3oAZCK0Gkt19x2Nhx7qlZFPoOxU/enxGmyo13VBq3xDnkoEg8g==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-json/-/apidom-parser-adapter-json-0.95.0.tgz", + "integrity": "sha512-KWFOfSCZNUyIRgU6+3xc2xQu4GlnGnh42LO25DSvbJmlWAaU/9sbW4FBBWF4Z3gIjw32nCj6AoGLdbjQvp8PtQ==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.94.0", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-error": "^0.94.0", + "@swagger-api/apidom-ast": "^0.95.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-error": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", @@ -738,135 +731,135 @@ } }, "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-2": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-2/-/apidom-parser-adapter-openapi-json-2-0.94.0.tgz", - "integrity": "sha512-sihZkkIwJNKKoE0fcizAVNtsgi//GMVSraWUEVFSV5qLz/ZXSwqWFH62rA3NzDy4NIKddO8L8jtvw+6xi0+IJQ==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-2/-/apidom-parser-adapter-openapi-json-2-0.95.0.tgz", + "integrity": "sha512-0MFlrN/6VnnSUv2xeRxRYQv72rbO019D1gh4t8QB93LfOfFD/k8HxiSkChJaJEbKq+dZfW9Hw/tWhCMROOHNYQ==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-ns-openapi-2": "^0.94.0", - "@swagger-api/apidom-parser-adapter-json": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-ns-openapi-2": "^0.95.0", + "@swagger-api/apidom-parser-adapter-json": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-0": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-0/-/apidom-parser-adapter-openapi-json-3-0-0.94.0.tgz", - "integrity": "sha512-4rQDyybeWQ0M/7P3mPrZF5HcTtadL0If81Uw59YLOzvBWtILcxOmpqHLSjEheEn2qTdb3zMilx88EK2XKQKzzA==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-0/-/apidom-parser-adapter-openapi-json-3-0-0.95.0.tgz", + "integrity": "sha512-i7seQZpAQSHnYmDh7304eZqus/iNq8csw2c/rvhveZAw8vVuJzTVv/euPdPHdMfrdilHsIS0ZIHtZOwNfQD3kw==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-ns-openapi-3-0": "^0.94.0", - "@swagger-api/apidom-parser-adapter-json": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-ns-openapi-3-0": "^0.95.0", + "@swagger-api/apidom-parser-adapter-json": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-openapi-json-3-1": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-1/-/apidom-parser-adapter-openapi-json-3-1-0.94.0.tgz", - "integrity": "sha512-rhQcRctbhjQ5UF3TxyKXJNs5eWTixv3TWFWrvzYRHAe0ioKIbG3Km1cU7zQhAdPY+ZMzA5aGCiLSsdh3p2eCyQ==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-json-3-1/-/apidom-parser-adapter-openapi-json-3-1-0.95.0.tgz", + "integrity": "sha512-PapPDHPuyRYidnVZUsHEc36vCuK0FSNE7DFtDfh2QTOKg37taKuPTq5DNG0Az4C2sHey1M3AdeZEJOQUcsmvAw==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-ns-openapi-3-1": "^0.94.0", - "@swagger-api/apidom-parser-adapter-json": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-ns-openapi-3-1": "^0.95.0", + "@swagger-api/apidom-parser-adapter-json": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-2": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-2/-/apidom-parser-adapter-openapi-yaml-2-0.94.0.tgz", - "integrity": "sha512-V8EWfNiQCxa4bFVbzD023M2A0hQlaNHNzBc2QszNLJNpp7Fk4WMgM87BuNvFdePdM6JLNWtV5e4qZHA6EGIryw==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-2/-/apidom-parser-adapter-openapi-yaml-2-0.95.0.tgz", + "integrity": "sha512-ntHZv5L1KiZMw2tVO+FAMzVGuZPKElT4LhS1aEYKlCwCVBIKGHVy1qXgrdo+MtKEK/+VtG8BvO8dE/W5hwO/9Q==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-ns-openapi-2": "^0.94.0", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-ns-openapi-2": "^0.95.0", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0/-/apidom-parser-adapter-openapi-yaml-3-0-0.94.0.tgz", - "integrity": "sha512-6v/xNVcQZpfj7Uh3w3K5qzrGeTbIzE8ZMup8uIBfzDmh4AK3bSTZpsL+RN4CG6xUBETMQGSWfK40cYAFdNr/4Q==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-0/-/apidom-parser-adapter-openapi-yaml-3-0-0.95.0.tgz", + "integrity": "sha512-IvP/jLhlUKXhd1bb4qTofyVQkEk9W7Ijg33st+ymNdZ3gmkwrCu/zdxzpHUA/+Z7P45UwjRh0WuYGJnevA4n7Q==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-ns-openapi-3-0": "^0.94.0", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-ns-openapi-3-0": "^0.95.0", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1/-/apidom-parser-adapter-openapi-yaml-3-1-0.94.0.tgz", - "integrity": "sha512-YoPFmLAFfa/n91P4Yjp8thTuwYljgpqcHcT47LAX9N/nZ6biuQQqXIJs03U30T//xx+rBLXlyemNQdG9xg9wNA==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-openapi-yaml-3-1/-/apidom-parser-adapter-openapi-yaml-3-1-0.95.0.tgz", + "integrity": "sha512-vWGB/9rKr/yG6+SLFhI4chT6WMmDqzJ77WICsuj6K1ZIb5cE6Ko1d37Lya8ghUvvh1xrtaF+XXZXprVwlpQx2A==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-ns-openapi-3-1": "^0.94.0", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-ns-openapi-3-1": "^0.95.0", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-workflows-json-1": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-workflows-json-1/-/apidom-parser-adapter-workflows-json-1-0.94.0.tgz", - "integrity": "sha512-EF1ws8PPW3HznZTA66RTPl2VWFupDujW42gPk+kTDY9oxH6tvho20jHnthO2tkTNSJwNfJn8+OjCFgAqIyd5ww==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-workflows-json-1/-/apidom-parser-adapter-workflows-json-1-0.95.0.tgz", + "integrity": "sha512-yyMMB55D+5BqInuFcr1xo8eJtXoA2PxtridCOL9FeAZptPmUSKQuUM2iHYJ4+Jxc3Rg+DjCONDB1WHfGHnWqnQ==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-ns-workflows-1": "^0.94.0", - "@swagger-api/apidom-parser-adapter-json": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-ns-workflows-1": "^0.95.0", + "@swagger-api/apidom-parser-adapter-json": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-workflows-yaml-1": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-workflows-yaml-1/-/apidom-parser-adapter-workflows-yaml-1-0.94.0.tgz", - "integrity": "sha512-bb570JPAqswNPh26k/YEtjdGz1SQNI8JOb/cHudF6/Rv+O1Z/EeEjas5EU6uCn9dvWG0OE9nkDMgQPl5CWrbgA==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-workflows-yaml-1/-/apidom-parser-adapter-workflows-yaml-1-0.95.0.tgz", + "integrity": "sha512-2/Lmb3vOAoQObwHdQJShjwvuT4i9hIMBHjplSXZLAFYSF65SN1YRCGwbJqKuC3W6mKB/lE3Fua19CFkRbw03Rg==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-ns-workflows-1": "^0.94.0", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-ns-workflows-1": "^0.95.0", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.0.0" } }, "node_modules/@swagger-api/apidom-parser-adapter-yaml-1-2": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-yaml-1-2/-/apidom-parser-adapter-yaml-1-2-0.94.0.tgz", - "integrity": "sha512-RHEcEP/ZCeRa5iRlwrHsP2ptpLsRY2zda5t41uJfVHb7c9+F/e+A8nJgHhwAgxVgOL6t1fIdVpjX9koyQApnOw==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-parser-adapter-yaml-1-2/-/apidom-parser-adapter-yaml-1-2-0.95.0.tgz", + "integrity": "sha512-gy0rsrbuK50InSMLyGVXvtWXb18qlxAUWSSc8kUk8gu9kthAytXyLmM/y9Pk/qKLxg+5O9xCqZVlPcTWc2vz0Q==", "optional": true, "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^0.94.0", - "@swagger-api/apidom-core": "^0.94.0", - "@swagger-api/apidom-error": "^0.94.0", + "@swagger-api/apidom-ast": "^0.95.0", + "@swagger-api/apidom-core": "^0.95.0", + "@swagger-api/apidom-error": "^0.95.0", "@types/ramda": "~0.29.6", "ramda": "~0.29.1", "ramda-adjunct": "^4.1.1", @@ -876,12 +869,12 @@ } }, "node_modules/@swagger-api/apidom-reference": { - "version": "0.94.0", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-reference/-/apidom-reference-0.94.0.tgz", - "integrity": "sha512-289mf9R+lfwK11aubFZSRgDPwu4lpwUwpBJXkJG4Rsuzn6rbYtehJ2PFH7/L5VI9cvq07wlzCwSiCrxbiT0+rA==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-reference/-/apidom-reference-0.95.0.tgz", + "integrity": "sha512-VAgt6t9SMaJ3Svxqlkptxe26mTKxhFdXZuHyFneLu+08Tb7AoE/kdLH3sO1iIVn+aiFTAkPTzWNn36OQqEHV/g==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^0.94.0", + "@swagger-api/apidom-core": "^0.95.0", "@types/ramda": "~0.29.6", "axios": "^1.4.0", "minimatch": "^7.4.3", @@ -891,27 +884,27 @@ "stampit": "^4.3.2" }, "optionalDependencies": { - "@swagger-api/apidom-error": "^0.94.0", - "@swagger-api/apidom-json-pointer": "^0.94.0", - "@swagger-api/apidom-ns-asyncapi-2": "^0.94.0", - "@swagger-api/apidom-ns-openapi-2": "^0.94.0", - "@swagger-api/apidom-ns-openapi-3-0": "^0.94.0", - "@swagger-api/apidom-ns-openapi-3-1": "^0.94.0", - "@swagger-api/apidom-ns-workflows-1": "^0.94.0", - "@swagger-api/apidom-parser-adapter-api-design-systems-json": "^0.94.0", - "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "^0.94.0", - "@swagger-api/apidom-parser-adapter-asyncapi-json-2": "^0.94.0", - "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "^0.94.0", - "@swagger-api/apidom-parser-adapter-json": "^0.94.0", - "@swagger-api/apidom-parser-adapter-openapi-json-2": "^0.94.0", - "@swagger-api/apidom-parser-adapter-openapi-json-3-0": "^0.94.0", - "@swagger-api/apidom-parser-adapter-openapi-json-3-1": "^0.94.0", - "@swagger-api/apidom-parser-adapter-openapi-yaml-2": "^0.94.0", - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": "^0.94.0", - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": "^0.94.0", - "@swagger-api/apidom-parser-adapter-workflows-json-1": "^0.94.0", - "@swagger-api/apidom-parser-adapter-workflows-yaml-1": "^0.94.0", - "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.94.0" + "@swagger-api/apidom-error": "^0.95.0", + "@swagger-api/apidom-json-pointer": "^0.95.0", + "@swagger-api/apidom-ns-asyncapi-2": "^0.95.0", + "@swagger-api/apidom-ns-openapi-2": "^0.95.0", + "@swagger-api/apidom-ns-openapi-3-0": "^0.95.0", + "@swagger-api/apidom-ns-openapi-3-1": "^0.95.0", + "@swagger-api/apidom-ns-workflows-1": "^0.95.0", + "@swagger-api/apidom-parser-adapter-api-design-systems-json": "^0.95.0", + "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "^0.95.0", + "@swagger-api/apidom-parser-adapter-asyncapi-json-2": "^0.95.0", + "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "^0.95.0", + "@swagger-api/apidom-parser-adapter-json": "^0.95.0", + "@swagger-api/apidom-parser-adapter-openapi-json-2": "^0.95.0", + "@swagger-api/apidom-parser-adapter-openapi-json-3-0": "^0.95.0", + "@swagger-api/apidom-parser-adapter-openapi-json-3-1": "^0.95.0", + "@swagger-api/apidom-parser-adapter-openapi-yaml-2": "^0.95.0", + "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": "^0.95.0", + "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": "^0.95.0", + "@swagger-api/apidom-parser-adapter-workflows-json-1": "^0.95.0", + "@swagger-api/apidom-parser-adapter-workflows-yaml-1": "^0.95.0", + "@swagger-api/apidom-parser-adapter-yaml-1-2": "^0.95.0" } }, "node_modules/@types/bootstrap": { @@ -943,36 +936,36 @@ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" }, "node_modules/@vue/compiler-core": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.18.tgz", - "integrity": "sha512-F7YK8lMK0iv6b9/Gdk15A67wM0KKZvxDxed0RR60C1z9tIJTKta+urs4j0RTN5XqHISzI3etN3mX0uHhjmoqjQ==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.19.tgz", + "integrity": "sha512-gj81785z0JNzRcU0Mq98E56e4ltO1yf8k5PQ+tV/7YHnbZkrM0fyFyuttnN8ngJZjbpofWE/m4qjKBiLl8Ju4w==", "dependencies": { "@babel/parser": "^7.23.9", - "@vue/shared": "3.4.18", + "@vue/shared": "3.4.19", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.0.2" } }, "node_modules/@vue/compiler-dom": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.18.tgz", - "integrity": "sha512-24Eb8lcMfInefvQ6YlEVS18w5Q66f4+uXWVA+yb7praKbyjHRNuKVWGuinfSSjM0ZIiPi++QWukhkgznBaqpEA==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.19.tgz", + "integrity": "sha512-vm6+cogWrshjqEHTzIDCp72DKtea8Ry/QVpQRYoyTIg9k7QZDX6D8+HGURjtmatfgM8xgCFtJJaOlCaRYRK3QA==", "dependencies": { - "@vue/compiler-core": "3.4.18", - "@vue/shared": "3.4.18" + "@vue/compiler-core": "3.4.19", + "@vue/shared": "3.4.19" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.18.tgz", - "integrity": "sha512-rG5tqtnzwrVpMqAQ7FHtvHaV70G6LLfJIWLYZB/jZ9m/hrnZmIQh+H3ewnC5onwe/ibljm9+ZupxeElzqCkTAw==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.19.tgz", + "integrity": "sha512-LQ3U4SN0DlvV0xhr1lUsgLCYlwQfUfetyPxkKYu7dkfvx7g3ojrGAkw0AERLOKYXuAGnqFsEuytkdcComei3Yg==", "dependencies": { "@babel/parser": "^7.23.9", - "@vue/compiler-core": "3.4.18", - "@vue/compiler-dom": "3.4.18", - "@vue/compiler-ssr": "3.4.18", - "@vue/shared": "3.4.18", + "@vue/compiler-core": "3.4.19", + "@vue/compiler-dom": "3.4.19", + "@vue/compiler-ssr": "3.4.19", + "@vue/shared": "3.4.19", "estree-walker": "^2.0.2", "magic-string": "^0.30.6", "postcss": "^8.4.33", @@ -980,62 +973,75 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.18.tgz", - "integrity": "sha512-hSlv20oUhPxo2UYUacHgGaxtqP0tvFo6ixxxD6JlXIkwzwoZ9eKK6PFQN4hNK/R13JlNyldwWt/fqGBKgWJ6nQ==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.19.tgz", + "integrity": "sha512-P0PLKC4+u4OMJ8sinba/5Z/iDT84uMRRlrWzadgLA69opCpI1gG4N55qDSC+dedwq2fJtzmGald05LWR5TFfLw==", "dependencies": { - "@vue/compiler-dom": "3.4.18", - "@vue/shared": "3.4.18" + "@vue/compiler-dom": "3.4.19", + "@vue/shared": "3.4.19" } }, "node_modules/@vue/devtools-api": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.1.tgz", - "integrity": "sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==" + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.1.tgz", + "integrity": "sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==" }, "node_modules/@vue/reactivity": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.18.tgz", - "integrity": "sha512-7uda2/I0jpLiRygprDo5Jxs2HJkOVXcOMlyVlY54yRLxoycBpwGJRwJT9EdGB4adnoqJDXVT2BilUAYwI7qvmg==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.19.tgz", + "integrity": "sha512-+VcwrQvLZgEclGZRHx4O2XhyEEcKaBi50WbxdVItEezUf4fqRh838Ix6amWTdX0CNb/b6t3Gkz3eOebfcSt+UA==", "dependencies": { - "@vue/shared": "3.4.18" + "@vue/shared": "3.4.19" } }, "node_modules/@vue/runtime-core": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.18.tgz", - "integrity": "sha512-7mU9diCa+4e+8/wZ7Udw5pwTH10A11sZ1nldmHOUKJnzCwvZxfJqAtw31mIf4T5H2FsLCSBQT3xgioA9vIjyDQ==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.19.tgz", + "integrity": "sha512-/Z3tFwOrerJB/oyutmJGoYbuoadphDcJAd5jOuJE86THNZji9pYjZroQ2NFsZkTxOq0GJbb+s2kxTYToDiyZzw==", "dependencies": { - "@vue/reactivity": "3.4.18", - "@vue/shared": "3.4.18" + "@vue/reactivity": "3.4.19", + "@vue/shared": "3.4.19" } }, "node_modules/@vue/runtime-dom": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.18.tgz", - "integrity": "sha512-2y1Mkzcw1niSfG7z3Qx+2ir9Gb4hdTkZe5p/I8x1aTIKQE0vY0tPAEUPhZm5tx6183gG3D/KwHG728UR0sIufA==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.19.tgz", + "integrity": "sha512-IyZzIDqfNCF0OyZOauL+F4yzjMPN2rPd8nhqPP2N1lBn3kYqJpPHHru+83Rkvo2lHz5mW+rEeIMEF9qY3PB94g==", "dependencies": { - "@vue/runtime-core": "3.4.18", - "@vue/shared": "3.4.18", + "@vue/runtime-core": "3.4.19", + "@vue/shared": "3.4.19", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.18.tgz", - "integrity": "sha512-YJd1wa7mzUN3NRqLEsrwEYWyO+PUBSROIGlCc3J/cvn7Zu6CxhNLgXa8Z4zZ5ja5/nviYO79J1InoPeXgwBTZA==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.19.tgz", + "integrity": "sha512-eAj2p0c429RZyyhtMRnttjcSToch+kTWxFPHlzGMkR28ZbF1PDlTcmGmlDxccBuqNd9iOQ7xPRPAGgPVj+YpQw==", "dependencies": { - "@vue/compiler-ssr": "3.4.18", - "@vue/shared": "3.4.18" + "@vue/compiler-ssr": "3.4.19", + "@vue/shared": "3.4.19" }, "peerDependencies": { - "vue": "3.4.18" + "vue": "3.4.19" } }, "node_modules/@vue/shared": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.18.tgz", - "integrity": "sha512-CxouGFxxaW5r1WbrSmWwck3No58rApXgRSBxrqgnY1K+jk20F6DrXJkHdH9n4HVT+/B6G2CAn213Uq3npWiy8Q==" + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz", + "integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } }, "node_modules/argparse": { "version": "2.0.1", @@ -1089,6 +1095,15 @@ } ] }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -1125,9 +1140,9 @@ } }, "node_modules/bootstrap": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.2.tgz", - "integrity": "sha512-D32nmNWiQHo94BKHLmOrdjlL05q1c8oxbtBphQFb9Z5to6eGRDCm0QgeaZ4zFBHzfg2++rqa2JkqCcxDy0sH0g==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", + "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", "funding": [ { "type": "github", @@ -1158,9 +1173,9 @@ ] }, "node_modules/bootstrap5-tags": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/bootstrap5-tags/-/bootstrap5-tags-1.6.16.tgz", - "integrity": "sha512-SH4pLDxeicMIdJ9aZLNUvDw89dyD0RUUmHVb8cDiKAtyH/1csa9/O23Y4WSezLZ2MpB7ZRUI4YFp4o0WwW6JVQ==" + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/bootstrap5-tags/-/bootstrap5-tags-1.7.1.tgz", + "integrity": "sha512-qBgtw8E4b+zNfNGPNZAaiC4oR2QSI2OWQYx523S03+ZFXPFUU7fJyMA4ynTYG2CE6hpy3e8HB5Lx9nWn1jrlNA==" }, "node_modules/brace-expansion": { "version": "2.0.1", @@ -1170,6 +1185,18 @@ "balanced-match": "^1.0.0" } }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -1197,17 +1224,19 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==", - "dev": true + "dev": true, + "peer": true }, "node_modules/call-bind": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz", - "integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "set-function-length": "^1.2.0" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -1216,6 +1245,30 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", @@ -1253,9 +1306,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.35.1.tgz", - "integrity": "sha512-zcIdi/CL3MWbBJYo5YCeVAAx+Sy9yJE9I3/u9LkFABwbeaPhTMRWraM8mYFp9jW5Z50hOy7FVzCc8dCrpZqtIQ==", + "version": "3.36.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.36.0.tgz", + "integrity": "sha512-cN28qmhRNgbMZZMc/RFu5w8pK9VJzpb2rJVR/lHuZJKwmXnoWOpXmMkxqBB514igkp1Hu8WGROsiOAzUcKdHOQ==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -1300,17 +1353,19 @@ } }, "node_modules/define-data-property": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.2.tgz", - "integrity": "sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.2", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/delayed-stream": { @@ -1350,6 +1405,17 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-errors": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", @@ -1359,9 +1425,9 @@ } }, "node_modules/esbuild": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.0.tgz", - "integrity": "sha512-6iwE3Y2RVYCME1jLpBqq7LQWK3MW6vjV2bZy6gt/WrqkY+WE74Spyc0ThAOYpMtITvnjX09CrC6ym7A/m9mebA==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz", + "integrity": "sha512-OJwEgrpWm/PCMsLVWXKqvcjme3bHNpOgN7Tb6cQnR5n0TPbQx1/Xrn7rqM+wn17bYeT6MGB5sn1Bh5YiGi70nA==", "dev": true, "hasInstallScript": true, "bin": { @@ -1371,29 +1437,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.0", - "@esbuild/android-arm": "0.20.0", - "@esbuild/android-arm64": "0.20.0", - "@esbuild/android-x64": "0.20.0", - "@esbuild/darwin-arm64": "0.20.0", - "@esbuild/darwin-x64": "0.20.0", - "@esbuild/freebsd-arm64": "0.20.0", - "@esbuild/freebsd-x64": "0.20.0", - "@esbuild/linux-arm": "0.20.0", - "@esbuild/linux-arm64": "0.20.0", - "@esbuild/linux-ia32": "0.20.0", - "@esbuild/linux-loong64": "0.20.0", - "@esbuild/linux-mips64el": "0.20.0", - "@esbuild/linux-ppc64": "0.20.0", - "@esbuild/linux-riscv64": "0.20.0", - "@esbuild/linux-s390x": "0.20.0", - "@esbuild/linux-x64": "0.20.0", - "@esbuild/netbsd-x64": "0.20.0", - "@esbuild/openbsd-x64": "0.20.0", - "@esbuild/sunos-x64": "0.20.0", - "@esbuild/win32-arm64": "0.20.0", - "@esbuild/win32-ia32": "0.20.0", - "@esbuild/win32-x64": "0.20.0" + "@esbuild/aix-ppc64": "0.20.1", + "@esbuild/android-arm": "0.20.1", + "@esbuild/android-arm64": "0.20.1", + "@esbuild/android-x64": "0.20.1", + "@esbuild/darwin-arm64": "0.20.1", + "@esbuild/darwin-x64": "0.20.1", + "@esbuild/freebsd-arm64": "0.20.1", + "@esbuild/freebsd-x64": "0.20.1", + "@esbuild/linux-arm": "0.20.1", + "@esbuild/linux-arm64": "0.20.1", + "@esbuild/linux-ia32": "0.20.1", + "@esbuild/linux-loong64": "0.20.1", + "@esbuild/linux-mips64el": "0.20.1", + "@esbuild/linux-ppc64": "0.20.1", + "@esbuild/linux-riscv64": "0.20.1", + "@esbuild/linux-s390x": "0.20.1", + "@esbuild/linux-x64": "0.20.1", + "@esbuild/netbsd-x64": "0.20.1", + "@esbuild/openbsd-x64": "0.20.1", + "@esbuild/sunos-x64": "0.20.1", + "@esbuild/win32-arm64": "0.20.1", + "@esbuild/win32-ia32": "0.20.1", + "@esbuild/win32-x64": "0.20.1" } }, "node_modules/esbuild-plugin-vue-next": { @@ -1410,16 +1476,17 @@ } }, "node_modules/esbuild-sass-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/esbuild-sass-plugin/-/esbuild-sass-plugin-3.0.0.tgz", - "integrity": "sha512-bwIzYBdI7mK0HghblwqGEYX44Hknvj6EBKXEI8e0hC+Xui5L8oUXFeJ4/PDldxYD++wIPuA6Lr4EAnNCtbv//A==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/esbuild-sass-plugin/-/esbuild-sass-plugin-3.1.0.tgz", + "integrity": "sha512-LX/PhMuA7KskPDT8yB10/o3C3fTKVWEzcfzGnGH0wqjZm3FEtm4d6dCxUn+252kuWZAgFOGzGOnBv1FpzClJrA==", "dev": true, "dependencies": { - "resolve": "^1.22.6", - "sass-embedded": "^1.70.0" + "resolve": "^1.22.8", + "sass": "^1.71.1" }, "peerDependencies": { - "esbuild": "^0.20.0" + "esbuild": "^0.20.1", + "sass-embedded": "^1.71.1" } }, "node_modules/estree-walker": { @@ -1441,6 +1508,18 @@ "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==" }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/follow-redirects": { "version": "1.15.5", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", @@ -1479,6 +1558,20 @@ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "optional": true }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -1511,6 +1604,18 @@ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", "optional": true }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -1527,25 +1632,26 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "peer": true, "engines": { "node": ">=8" } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -1571,9 +1677,9 @@ "dev": true }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", "dependencies": { "function-bind": "^1.1.2" }, @@ -1618,6 +1724,18 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "optional": true }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-core-module": { "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", @@ -1630,6 +1748,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", @@ -1830,9 +1978,9 @@ "optional": true }, "node_modules/node-abi": { - "version": "3.54.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.54.0.tgz", - "integrity": "sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.56.0.tgz", + "integrity": "sha512-fZjdhDOeRcaS+rcpve7XuwHBmktS1nS1gzgghwKUQQ8nTy2FdSDr6ZT8k6YhvlJeHmmQMYiT/IH9hfco5zeW2Q==", "optional": true, "dependencies": { "semver": "^7.3.5" @@ -1880,6 +2028,15 @@ "url": "https://opencollective.com/node-fetch" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -1908,6 +2065,18 @@ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/postcss": { "version": "8.4.35", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", @@ -2076,6 +2245,18 @@ "node": ">= 6" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", @@ -2111,6 +2292,7 @@ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, + "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -2135,11 +2317,29 @@ ], "optional": true }, + "node_modules/sass": { + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.71.1.tgz", + "integrity": "sha512-wovtnV2PxzteLlfNzbgm1tFXPLoZILYAMJtvoXXkD7/+1uP41eKkIt1ypWq5/q2uT94qHjXehEYfmjKOvjL9sg==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/sass-embedded": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.70.0.tgz", - "integrity": "sha512-1sVSh5MlSdktkwC2zG9WuaVR6j7AlDxadPmZBN0wP4GhznMQTvpwNIAFhAqgjwJYhwdWFOKEdIHSQK4V8K434Q==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.71.1.tgz", + "integrity": "sha512-nOmqErO1zd1wjvTbDscLZZ3fv5JPeQfaKuo0UCjYm7qPbpQcycp0l3nFZHxovjLjCetJ9IrLOADdznFYKV0f1A==", "dev": true, + "peer": true, "dependencies": { "@bufbuild/protobuf": "^1.0.0", "buffer-builder": "^0.2.0", @@ -2152,28 +2352,28 @@ "node": ">=16.0.0" }, "optionalDependencies": { - "sass-embedded-android-arm": "1.70.0", - "sass-embedded-android-arm64": "1.70.0", - "sass-embedded-android-ia32": "1.70.0", - "sass-embedded-android-x64": "1.70.0", - "sass-embedded-darwin-arm64": "1.70.0", - "sass-embedded-darwin-x64": "1.70.0", - "sass-embedded-linux-arm": "1.70.0", - "sass-embedded-linux-arm64": "1.70.0", - "sass-embedded-linux-ia32": "1.70.0", - "sass-embedded-linux-musl-arm": "1.70.0", - "sass-embedded-linux-musl-arm64": "1.70.0", - "sass-embedded-linux-musl-ia32": "1.70.0", - "sass-embedded-linux-musl-x64": "1.70.0", - "sass-embedded-linux-x64": "1.70.0", - "sass-embedded-win32-ia32": "1.70.0", - "sass-embedded-win32-x64": "1.70.0" + "sass-embedded-android-arm": "1.71.1", + "sass-embedded-android-arm64": "1.71.1", + "sass-embedded-android-ia32": "1.71.1", + "sass-embedded-android-x64": "1.71.1", + "sass-embedded-darwin-arm64": "1.71.1", + "sass-embedded-darwin-x64": "1.71.1", + "sass-embedded-linux-arm": "1.71.1", + "sass-embedded-linux-arm64": "1.71.1", + "sass-embedded-linux-ia32": "1.71.1", + "sass-embedded-linux-musl-arm": "1.71.1", + "sass-embedded-linux-musl-arm64": "1.71.1", + "sass-embedded-linux-musl-ia32": "1.71.1", + "sass-embedded-linux-musl-x64": "1.71.1", + "sass-embedded-linux-x64": "1.71.1", + "sass-embedded-win32-ia32": "1.71.1", + "sass-embedded-win32-x64": "1.71.1" } }, "node_modules/sass-embedded-android-arm": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.70.0.tgz", - "integrity": "sha512-Vog4Z+tsDYGv7m9sZisr/P6KvqDioCMu0cinexdnXhHXReo+X6CFe79yv/zA/Xfq5HtAAmFjGD6CO/nTjoydtw==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.71.1.tgz", + "integrity": "sha512-Pq6TlRg9lIYsZDo9XNQZnSg6grQKzBG3ssdv0W1SnYS1BzGKwbg8XnlUA/pVxK76BKEm8i+0DA4y8cZ8A3tmpw==", "cpu": [ "arm" ], @@ -2182,6 +2382,7 @@ "os": [ "android" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -2190,9 +2391,9 @@ } }, "node_modules/sass-embedded-android-arm64": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.70.0.tgz", - "integrity": "sha512-vMr7fruLUv/VvF7CPVF1z7Bc28a8K9Ps5nyN3UatOj+irxN1LbZIbeQua6neX2eFUsXvcg7hLZwvV3+T96Fhrw==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.71.1.tgz", + "integrity": "sha512-a7wJ1MM6sBwcM/8vIvvnwc9spoeNimNeXZpN9baSV4Ylthmr4GkTYYtf96Z/XYLdG5KBgYlxMs5T3OgqafdUMg==", "cpu": [ "arm64" ], @@ -2201,6 +2402,7 @@ "os": [ "android" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -2209,9 +2411,9 @@ } }, "node_modules/sass-embedded-android-ia32": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-android-ia32/-/sass-embedded-android-ia32-1.70.0.tgz", - "integrity": "sha512-RWEJ7sBGBCd101oSBPuePPU8yXb1iB/ME4sRhgI5xjjyIsldiuvX48saW25u1ZqCo2AVA0BTXfWpNJnhKB3b4Q==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-android-ia32/-/sass-embedded-android-ia32-1.71.1.tgz", + "integrity": "sha512-tn3WZNdKQtr/DSzl4cQIDZkTO3JuuMxPvM/T+U7gBFyhU62NyF5wvwBnuh+BN3iaMowfkSknzCZCjyJDwnkDjw==", "cpu": [ "ia32" ], @@ -2220,6 +2422,7 @@ "os": [ "android" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -2228,9 +2431,9 @@ } }, "node_modules/sass-embedded-android-x64": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.70.0.tgz", - "integrity": "sha512-u+ijV6AQR/84kjjGb3mp0aibPiXkFKqfmHxqYBMN7h2xV7EM70Yz054nVifaBr8nfC0E8aT/DurSI4nkkQ6Uvg==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.71.1.tgz", + "integrity": "sha512-l72Pqxfb/pArpOLyWsuL9s8ODWupRGATWTPwUT/GjVdSQJO/lQL5DopXb55Cwh2T7t2G10e+uXTEMKz0qngoWQ==", "cpu": [ "x64" ], @@ -2239,6 +2442,7 @@ "os": [ "android" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -2247,9 +2451,9 @@ } }, "node_modules/sass-embedded-darwin-arm64": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.70.0.tgz", - "integrity": "sha512-qMs08h0nwRA1B/Ieakcg/Y6lcCEnuBnPTNEkFkBlnfj3PFVPTb50wQvDr9JLpcjXWznlBxyFrz1nZM+pXDix7Q==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.71.1.tgz", + "integrity": "sha512-3eZDAcJBwoG0Kyasa/EbaKt1Jn2y0GHvCd0Oas/VtMsYL+/6abiCO1l8YltdxER4jvuHUKE2Ow7J6T6sC+vVQQ==", "cpu": [ "arm64" ], @@ -2258,6 +2462,7 @@ "os": [ "darwin" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -2266,9 +2471,9 @@ } }, "node_modules/sass-embedded-darwin-x64": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.70.0.tgz", - "integrity": "sha512-Vf8UQY3IBmsaz9L5DeJDjn19N//1n3rTquH69x29zPCd3zF2gnay38atxIZ+6h7VsZT3C6evm0y58JUJDWN1CA==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.71.1.tgz", + "integrity": "sha512-/9FtMPVdQalhsRCD9opNIlZqJKe7veCjWsdj0J9utbc2bNCTYswXNQtC/jWJTjE9/gQ0+w5zwg9+fQzltdYh1w==", "cpu": [ "x64" ], @@ -2277,6 +2482,7 @@ "os": [ "darwin" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -2285,9 +2491,9 @@ } }, "node_modules/sass-embedded-linux-arm": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.70.0.tgz", - "integrity": "sha512-U9e+k0XHwubeSIwsBYTNrTVH+0zF/ErSfuHfgTfuvlcKlhoGtFgAb7W8Qfe9FDF6TYTt0fJAJhSV2MdoExsgRA==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.71.1.tgz", + "integrity": "sha512-l7NEn0gji6GTN+p00DP2zZl9SE501Zy5obTA3beiD6+vQy7lCEC6vpNi/ZrlC6eRmgY2OKSBB2lfW7KSej9Hkg==", "cpu": [ "arm" ], @@ -2296,6 +2502,7 @@ "os": [ "linux" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -2304,9 +2511,9 @@ } }, "node_modules/sass-embedded-linux-arm64": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.70.0.tgz", - "integrity": "sha512-PzhBg5xlyXcZ8FgyjqAcVtfaq462l3KeEid2OxrsOzBQgdgJb0La1tAEOpP9jz7YOOTr9A96vm609W9fRLI2Iw==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.71.1.tgz", + "integrity": "sha512-zUSmqeqcgTb3VjZggk9a9xB2ZGaAe/TYAi/vYRPNLY/f7dZSrsa9Ejo+LUm2aNl6V8hFzMz7BpoKsaRQJnb9GQ==", "cpu": [ "arm64" ], @@ -2315,6 +2522,7 @@ "os": [ "linux" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -2323,9 +2531,9 @@ } }, "node_modules/sass-embedded-linux-ia32": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.70.0.tgz", - "integrity": "sha512-UOxTJywQRC/HzFQthlyNWJ07MX8EzKuTgH0N5T3XyXQTNuGeJQ8EPWY9fv1weLCjydVOEwm853F3djtUNmkCtg==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.71.1.tgz", + "integrity": "sha512-NvzSljfc/Kw9/0CSn91AsINV2nh8vxhFe2cKexPMwvAqv/etU84dJMfJejxPJ39PmMqT1KvC4G+Qt2+6Mpe7oQ==", "cpu": [ "ia32" ], @@ -2334,6 +2542,7 @@ "os": [ "linux" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -2342,9 +2551,9 @@ } }, "node_modules/sass-embedded-linux-musl-arm": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.70.0.tgz", - "integrity": "sha512-8zudDFpAoNrQDujNYBKkq8nwl4i0jMmXcysO9Ou0llrzdY7Keok2z1aS3IbZy7AvUXtGaeYSHUi5lXdOalJ/QQ==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.71.1.tgz", + "integrity": "sha512-1O37K5EgSeQjCBizIF9xdZJw3mh5XYHOnsB4+65CLZg4ac84ragjFv9d9rYhwGs9QSgg1MoOv7VWnEIxQ8Pp9Q==", "cpu": [ "arm" ], @@ -2353,14 +2562,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } }, "node_modules/sass-embedded-linux-musl-arm64": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.70.0.tgz", - "integrity": "sha512-DJl1AV9W7T3SHzXFqAtyjPZy4O2g4AC6QctY5/aM42DTY/xpWOmwUBgsDzDoRbNqP7qDl+GtHLlggrLWCBP9fg==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.71.1.tgz", + "integrity": "sha512-Agtf6BcYQ0mt+jVDcRcN7bDPrMAQOWMeX15NTlQH1rO8voObLo6ThVl2NUkiZyyVmu7a6YOrCxpGBVAK1cLGOg==", "cpu": [ "arm64" ], @@ -2369,14 +2579,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } }, "node_modules/sass-embedded-linux-musl-ia32": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-ia32/-/sass-embedded-linux-musl-ia32-1.70.0.tgz", - "integrity": "sha512-CcAvT3KPc7cCJfTu1E0HzsAjE/dPQsKaXQD/nsBXNZo081R+lLR2u22wpXM2pnzMNJETRV/pDwozHoYEcPkPqQ==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-ia32/-/sass-embedded-linux-musl-ia32-1.71.1.tgz", + "integrity": "sha512-Cd5sJkt70bSlYEXUSj9mPMKZLzDL8LGcBKUIfQRrcBKjmzD2Va2eLq4Zati9Xzt54unuDp4bAUUTyvQmjLzFmA==", "cpu": [ "ia32" ], @@ -2385,14 +2596,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } }, "node_modules/sass-embedded-linux-musl-x64": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.70.0.tgz", - "integrity": "sha512-g3i9PKmqTxuyrM1Yeju1s4Fj6fzAGyyfzw/LiZZtq0ZZGhJXJMVvEDog/OxQ37eYxWqq9XHFTW2PphMvukVK0g==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.71.1.tgz", + "integrity": "sha512-uVfYms/lf4QVSvtQXkSm+Bq3wVsvkRMI30ca82rRwpwebxSaTbUr+uLnskh8QvbyfsbMyrzZQU0SCrO3uCua1A==", "cpu": [ "x64" ], @@ -2401,14 +2613,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } }, "node_modules/sass-embedded-linux-x64": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.70.0.tgz", - "integrity": "sha512-F9F2CA7C6z/ROfF0U/jtYWknbDe9S/TJoCJ5TlHafwS+SrZE1A+Czf2MWJ+8mc2NFiRjYzYxt4Ad29cuc6rrhw==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.71.1.tgz", + "integrity": "sha512-7BXniYic16+MQx0InyH8OXburLPGMRYRWf0l/t/fRkNkUHWFl7NQPAX0yvj73c/PKOdaYEUY6isNB4OGUGtZHQ==", "cpu": [ "x64" ], @@ -2417,6 +2630,7 @@ "os": [ "linux" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -2425,9 +2639,9 @@ } }, "node_modules/sass-embedded-win32-ia32": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.70.0.tgz", - "integrity": "sha512-TITx2QwJouhMwA0CAjCmnTNeCDL9g2fkLe9z+5rf39OdmcX9CEBrY4CNaO5REnMpgoa+o82u272ZR3oWrsUs8Q==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.71.1.tgz", + "integrity": "sha512-ZDhL6hvekeKDkZ1wUj6wN0thrB/7wOO8HaQoagk+pKaHoa0Py7OLR/m9mQM8S13mZpUQduNsznmXV1fOss4GOg==", "cpu": [ "ia32" ], @@ -2436,6 +2650,7 @@ "os": [ "win32" ], + "peer": true, "bin": { "sass": "dart-sass/sass.bat" }, @@ -2444,9 +2659,9 @@ } }, "node_modules/sass-embedded-win32-x64": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.70.0.tgz", - "integrity": "sha512-rPe8WUdARhlfgIhGcCTGbTNgd6OppcmjtBrxUNoGs3AENSREQCpaNv5d+HBOMhGUfYgXIHUSiipilFUhLWpsrQ==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.71.1.tgz", + "integrity": "sha512-ecWP1TFUA9ujOuOTJfWC1iZsSZOdQy5OxIEHqoERxunyjwzkiTxfN8J7Y4bNQ5uwb4K0brxWyIM8Fq+UgDqcZA==", "cpu": [ "arm64", "x64" @@ -2456,6 +2671,7 @@ "os": [ "win32" ], + "peer": true, "bin": { "sass": "dart-sass/sass.bat" }, @@ -2601,6 +2817,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -2624,9 +2841,9 @@ } }, "node_modules/swagger-client": { - "version": "3.25.0", - "resolved": "https://registry.npmjs.org/swagger-client/-/swagger-client-3.25.0.tgz", - "integrity": "sha512-p143zWkIhgyh2E5+3HPFMlCw3WkV9RbX9HyftfBdiccCbOlmHdcJC0XEJZxcm+ZA+80DORs0F30/mzk7sx4iwA==", + "version": "3.25.3", + "resolved": "https://registry.npmjs.org/swagger-client/-/swagger-client-3.25.3.tgz", + "integrity": "sha512-DUQ1zBgs+SDRTL+w2F2KDoneA9rkwpq9oF2Gex0HzGdlWP/4mEClFgp6ulMgcdSS2mC+B7thnvuT6aF1AwKbqw==", "dependencies": { "@babel/runtime-corejs3": "^7.22.15", "@swagger-api/apidom-core": ">=0.90.0 <1.0.0", @@ -2640,10 +2857,9 @@ "is-plain-object": "^5.0.0", "js-yaml": "^4.1.0", "node-abort-controller": "^3.1.1", - "node-fetch-commonjs": "^3.3.1", + "node-fetch-commonjs": "^3.3.2", "qs": "^6.10.2", - "traverse": "~0.6.6", - "undici": "^5.24.0" + "traverse": "~0.6.6" } }, "node_modules/tar-fs": { @@ -2674,6 +2890,18 @@ "node": ">=6" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/traverse": { "version": "0.6.8", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.8.tgz", @@ -2717,9 +2945,9 @@ } }, "node_modules/ts-mixer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz", - "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ==" + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz", + "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==" }, "node_modules/ts-toolbelt": { "version": "9.6.0", @@ -2730,7 +2958,8 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true + "dev": true, + "peer": true }, "node_modules/tunnel-agent": { "version": "0.6.0", @@ -2745,24 +2974,13 @@ } }, "node_modules/types-ramda": { - "version": "0.29.7", - "resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.29.7.tgz", - "integrity": "sha512-8KBxZGJwUF3MpRkkJauSpvfHXk8Ssq15QXGuCBTDGeKd9PfheokkC3wAKRV3djej9O31Qa5M7Owsg8hF0GjtAw==", + "version": "0.29.8", + "resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.29.8.tgz", + "integrity": "sha512-+RTOlcwl1hEdNV1xfug3ofG6rny0hqQsFuBmS88vD4Lrh8Iys14IPlUH9QaGjCY46iCZgEDuCTLMLH/pOOsGKg==", "dependencies": { "ts-toolbelt": "^9.6.0" } }, - "node_modules/undici": { - "version": "5.28.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", - "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, - "engines": { - "node": ">=14.0" - } - }, "node_modules/unraw": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unraw/-/unraw-3.0.0.tgz", @@ -2778,18 +2996,19 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true + "dev": true, + "peer": true }, "node_modules/vue": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.18.tgz", - "integrity": "sha512-0zLRYamFRe0wF4q2L3O24KQzLyLpL64ye1RUToOgOxuWZsb/FhaNRdGmeozdtVYLz6tl94OXLaK7/WQIrVCw1A==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.19.tgz", + "integrity": "sha512-W/7Fc9KUkajFU8dBeDluM4sRGc/aa4YJnOYck8dkjgZoXtVsn3OeTGni66FV1l3+nvPA7VBFYtPioaGKUmEADw==", "dependencies": { - "@vue/compiler-dom": "3.4.18", - "@vue/compiler-sfc": "3.4.18", - "@vue/runtime-dom": "3.4.18", - "@vue/server-renderer": "3.4.18", - "@vue/shared": "3.4.18" + "@vue/compiler-dom": "3.4.19", + "@vue/compiler-sfc": "3.4.19", + "@vue/runtime-dom": "3.4.19", + "@vue/server-renderer": "3.4.19", + "@vue/shared": "3.4.19" }, "peerDependencies": { "typescript": "*" @@ -2809,11 +3028,11 @@ } }, "node_modules/vue-router": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.2.5.tgz", - "integrity": "sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.0.tgz", + "integrity": "sha512-dqUcs8tUeG+ssgWhcPbjHvazML16Oga5w34uCUmsk7i0BcnskoLGwjpa15fqMr2Fa5JgVBrdL2MEgqz6XZ/6IQ==", "dependencies": { - "@vue/devtools-api": "^6.5.0" + "@vue/devtools-api": "^6.5.1" }, "funding": { "url": "https://github.com/sponsors/posva" @@ -2823,9 +3042,9 @@ } }, "node_modules/web-streams-polyfill": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz", - "integrity": "sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", "engines": { "node": ">= 8" } From 7cb71ad5bf14fb44e7e2ed62ba545af85b127513 Mon Sep 17 00:00:00 2001 From: Ralph Slooten Date: Sat, 24 Feb 2024 23:26:57 +1300 Subject: [PATCH 11/11] Release v1.14.0 --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfd047c61..0782736b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ Notable changes to Mailpit will be documented in this file. +## [v1.14.0] + +### Chore +- Update node dependencies +- Update Go dependencies +- Refactor storage library +- Security improvements (gosec) +- Switch to short uuid format for database IDs +- Better handling of automatic database compression (vacuuming) after deleting messages + +### Docker +- Add edge Docker images for latest unreleased features + +### Feature +- Optional POP3 server ([#249](https://github.com/axllent/mailpit/issues/249)) + + ## [v1.13.3] ### API