diff --git a/api/certificate/acme_user.go b/api/certificate/acme_user.go index 13431dd9d..9a8d8c8b0 100644 --- a/api/certificate/acme_user.go +++ b/api/certificate/acme_user.go @@ -13,7 +13,7 @@ import ( func GetAcmeUser(c *gin.Context) { u := query.AcmeUser - id := cast.ToInt(c.Param("id")) + id := cast.ToUint64(c.Param("id")) user, err := u.FirstByID(id) if err != nil { api.ErrHandler(c, err) @@ -79,7 +79,7 @@ func RecoverAcmeUser(c *gin.Context) { } func RegisterAcmeUser(c *gin.Context) { - id := cast.ToInt(c.Param("id")) + id := cast.ToUint64(c.Param("id")) u := query.AcmeUser user, err := u.FirstByID(id) if err != nil { diff --git a/api/certificate/certificate.go b/api/certificate/certificate.go index f333cfc9b..40031cac9 100644 --- a/api/certificate/certificate.go +++ b/api/certificate/certificate.go @@ -71,7 +71,7 @@ func GetCertList(c *gin.Context) { func GetCert(c *gin.Context) { q := query.Cert - certModel, err := q.FirstByID(cast.ToInt(c.Param("id"))) + certModel, err := q.FirstByID(cast.ToUint64(c.Param("id"))) if err != nil { api.ErrHandler(c, err) @@ -89,9 +89,9 @@ type certJson struct { SSLCertificateKey string `json:"ssl_certificate_key" binding:"omitempty,privatekey"` KeyType certcrypto.KeyType `json:"key_type" binding:"omitempty,auto_cert_key_type"` ChallengeMethod string `json:"challenge_method"` - DnsCredentialID int `json:"dns_credential_id"` - ACMEUserID int `json:"acme_user_id"` - SyncNodeIds []int `json:"sync_node_ids"` + DnsCredentialID uint64 `json:"dns_credential_id"` + ACMEUserID uint64 `json:"acme_user_id"` + SyncNodeIds []uint64 `json:"sync_node_ids"` } func AddCert(c *gin.Context) { @@ -141,7 +141,7 @@ func AddCert(c *gin.Context) { } func ModifyCert(c *gin.Context) { - id := cast.ToInt(c.Param("id")) + id := cast.ToUint64(c.Param("id")) var json certJson diff --git a/api/certificate/dns_credential.go b/api/certificate/dns_credential.go index 0fec35f4d..189d11aaa 100644 --- a/api/certificate/dns_credential.go +++ b/api/certificate/dns_credential.go @@ -12,7 +12,7 @@ import ( ) func GetDnsCredential(c *gin.Context) { - id := cast.ToInt(c.Param("id")) + id := cast.ToUint64(c.Param("id")) d := query.DnsCredential @@ -70,7 +70,7 @@ func AddDnsCredential(c *gin.Context) { } func EditDnsCredential(c *gin.Context) { - id := cast.ToInt(c.Param("id")) + id := cast.ToUint64(c.Param("id")) var json DnsCredentialManageJson if !api.BindAndValid(c, &json) { diff --git a/api/cluster/environment.go b/api/cluster/environment.go index ca9f5310d..9bcddaad2 100644 --- a/api/cluster/environment.go +++ b/api/cluster/environment.go @@ -15,7 +15,7 @@ import ( ) func GetEnvironment(c *gin.Context) { - id := cast.ToInt(c.Param("id")) + id := cast.ToUint64(c.Param("id")) envQuery := query.Environment @@ -67,7 +67,7 @@ func EditEnvironment(c *gin.Context) { } func DeleteEnvironment(c *gin.Context) { - id := cast.ToInt(c.Param("id")) + id := cast.ToUint64(c.Param("id")) envQuery := query.Environment env, err := envQuery.FirstByID(id) diff --git a/api/cluster/router.go b/api/cluster/router.go index 8c61c79cf..70b4babcd 100644 --- a/api/cluster/router.go +++ b/api/cluster/router.go @@ -6,7 +6,7 @@ func InitRouter(r *gin.RouterGroup) { // Environment r.GET("environments", GetEnvironmentList) r.POST("environments/load_from_settings", LoadEnvironmentFromSettings) - envGroup := r.Group("environment") + envGroup := r.Group("environments") { envGroup.GET("/:id", GetEnvironment) envGroup.POST("", AddEnvironment) diff --git a/api/config/add.go b/api/config/add.go index 167a8e801..7b83cc8a4 100644 --- a/api/config/add.go +++ b/api/config/add.go @@ -17,11 +17,11 @@ import ( func AddConfig(c *gin.Context) { var json struct { - Name string `json:"name" binding:"required"` - NewFilepath string `json:"new_filepath" binding:"required"` - Content string `json:"content"` - Overwrite bool `json:"overwrite"` - SyncNodeIds []int `json:"sync_node_ids"` + Name string `json:"name" binding:"required"` + NewFilepath string `json:"new_filepath" binding:"required"` + Content string `json:"content"` + Overwrite bool `json:"overwrite"` + SyncNodeIds []uint64 `json:"sync_node_ids"` } if !api.BindAndValid(c, &json) { diff --git a/api/config/get.go b/api/config/get.go index 2d47f6213..a38758d60 100644 --- a/api/config/get.go +++ b/api/config/get.go @@ -14,8 +14,8 @@ import ( type APIConfigResp struct { config.Config - SyncNodeIds []int `json:"sync_node_ids" gorm:"serializer:json"` - SyncOverwrite bool `json:"sync_overwrite"` + SyncNodeIds []uint64 `json:"sync_node_ids" gorm:"serializer:json"` + SyncOverwrite bool `json:"sync_overwrite"` } func GetConfig(c *gin.Context) { diff --git a/api/config/modify.go b/api/config/modify.go index 190281d76..ed7298d57 100644 --- a/api/config/modify.go +++ b/api/config/modify.go @@ -21,12 +21,12 @@ type EditConfigJson struct { func EditConfig(c *gin.Context) { name := c.Param("name") var json struct { - Name string `json:"name" binding:"required"` - Filepath string `json:"filepath" binding:"required"` - NewFilepath string `json:"new_filepath" binding:"required"` - Content string `json:"content"` - SyncOverwrite bool `json:"sync_overwrite"` - SyncNodeIds []int `json:"sync_node_ids"` + Name string `json:"name" binding:"required"` + Filepath string `json:"filepath" binding:"required"` + NewFilepath string `json:"new_filepath" binding:"required"` + Content string `json:"content"` + SyncOverwrite bool `json:"sync_overwrite"` + SyncNodeIds []uint64 `json:"sync_node_ids"` } if !api.BindAndValid(c, &json) { return diff --git a/api/config/rename.go b/api/config/rename.go index fb78dd77d..fa1facac0 100644 --- a/api/config/rename.go +++ b/api/config/rename.go @@ -14,10 +14,10 @@ import ( func Rename(c *gin.Context) { var json struct { - BasePath string `json:"base_path"` - OrigName string `json:"orig_name"` - NewName string `json:"new_name"` - SyncNodeIds []int `json:"sync_node_ids" gorm:"serializer:json"` + BasePath string `json:"base_path"` + OrigName string `json:"orig_name"` + NewName string `json:"new_name"` + SyncNodeIds []uint64 `json:"sync_node_ids" gorm:"serializer:json"` } if !api.BindAndValid(c, &json) { return diff --git a/api/config/router.go b/api/config/router.go index f182b27cd..2031a237a 100644 --- a/api/config/router.go +++ b/api/config/router.go @@ -9,9 +9,9 @@ func InitRouter(r *gin.RouterGroup) { r.GET("config_base_path", GetBasePath) r.GET("configs", GetConfigs) - r.GET("config/*name", GetConfig) - r.POST("config", AddConfig) - r.POST("config/*name", EditConfig) + r.GET("configs/*name", GetConfig) + r.POST("configs", AddConfig) + r.POST("configs/*name", EditConfig) o := r.Group("", middleware.RequireSecureSession()) { diff --git a/api/notification/notification.go b/api/notification/notification.go index f0c023042..cc5298c40 100644 --- a/api/notification/notification.go +++ b/api/notification/notification.go @@ -13,7 +13,7 @@ import ( func Get(c *gin.Context) { n := query.Notification - id := cast.ToInt(c.Param("id")) + id := cast.ToUint64(c.Param("id")) data, err := n.FirstByID(id) diff --git a/api/notification/router.go b/api/notification/router.go index 13d6c256a..87c3d166c 100644 --- a/api/notification/router.go +++ b/api/notification/router.go @@ -4,7 +4,7 @@ import "github.com/gin-gonic/gin" func InitRouter(r *gin.RouterGroup) { r.GET("notifications", GetList) - r.GET("notification/:id", Get) - r.DELETE("notification/:id", Destroy) + r.GET("notifications/:id", Get) + r.DELETE("notifications/:id", Destroy) r.DELETE("notifications", DestroyAll) } diff --git a/api/sites/auto_cert.go b/api/sites/auto_cert.go index 9348f2058..74b39d85d 100644 --- a/api/sites/auto_cert.go +++ b/api/sites/auto_cert.go @@ -13,7 +13,7 @@ func AddDomainToAutoCert(c *gin.Context) { name := c.Param("name") var json struct { - DnsCredentialID int `json:"dns_credential_id"` + DnsCredentialID uint64 `json:"dns_credential_id"` ChallengeMethod string `json:"challenge_method"` Domains []string `json:"domains"` KeyType certcrypto.KeyType `json:"key_type"` diff --git a/api/sites/category.go b/api/sites/category.go index d8ded05d6..8f3ed9ba5 100644 --- a/api/sites/category.go +++ b/api/sites/category.go @@ -7,7 +7,7 @@ import ( ) func GetCategory(c *gin.Context) { - + cosy.Core[model.SiteCategory](c).Get() } func GetCategoryList(c *gin.Context) { diff --git a/api/sites/domain.go b/api/sites/domain.go deleted file mode 100644 index 9fbd80ac8..000000000 --- a/api/sites/domain.go +++ /dev/null @@ -1,322 +0,0 @@ -package sites - -import ( - "github.com/0xJacky/Nginx-UI/api" - "github.com/0xJacky/Nginx-UI/internal/cert" - "github.com/0xJacky/Nginx-UI/internal/helper" - "github.com/0xJacky/Nginx-UI/internal/nginx" - "github.com/0xJacky/Nginx-UI/model" - "github.com/0xJacky/Nginx-UI/query" - "github.com/gin-gonic/gin" - "github.com/sashabaranov/go-openai" - "github.com/uozi-tech/cosy/logger" - "net/http" - "os" -) - -func GetSite(c *gin.Context) { - rewriteName, ok := c.Get("rewriteConfigFileName") - name := c.Param("name") - - // for modify filename - if ok { - name = rewriteName.(string) - } - - path := nginx.GetConfPath("sites-available", name) - file, err := os.Stat(path) - if os.IsNotExist(err) { - c.JSON(http.StatusNotFound, gin.H{ - "message": "file not found", - }) - return - } - - enabled := true - if _, err := os.Stat(nginx.GetConfPath("sites-enabled", name)); os.IsNotExist(err) { - enabled = false - } - - g := query.ChatGPTLog - chatgpt, err := g.Where(g.Name.Eq(path)).FirstOrCreate() - if err != nil { - api.ErrHandler(c, err) - return - } - - if chatgpt.Content == nil { - chatgpt.Content = make([]openai.ChatCompletionMessage, 0) - } - - s := query.Site - site, err := s.Where(s.Path.Eq(path)).FirstOrInit() - if err != nil { - api.ErrHandler(c, err) - return - } - - certModel, err := model.FirstCert(name) - if err != nil { - logger.Warn(err) - } - - if site.Advanced { - origContent, err := os.ReadFile(path) - if err != nil { - api.ErrHandler(c, err) - return - } - - c.JSON(http.StatusOK, Site{ - ModifiedAt: file.ModTime(), - Advanced: site.Advanced, - Enabled: enabled, - Name: name, - Config: string(origContent), - AutoCert: certModel.AutoCert == model.AutoCertEnabled, - ChatGPTMessages: chatgpt.Content, - Filepath: path, - }) - return - } - - nginxConfig, err := nginx.ParseNgxConfig(path) - if err != nil { - api.ErrHandler(c, err) - return - } - - certInfoMap := make(map[int][]*cert.Info) - for serverIdx, server := range nginxConfig.Servers { - for _, directive := range server.Directives { - if directive.Directive == "ssl_certificate" { - pubKey, err := cert.GetCertInfo(directive.Params) - if err != nil { - logger.Error("Failed to get certificate information", err) - continue - } - certInfoMap[serverIdx] = append(certInfoMap[serverIdx], pubKey) - } - } - } - - c.JSON(http.StatusOK, Site{ - ModifiedAt: file.ModTime(), - Advanced: site.Advanced, - Enabled: enabled, - Name: name, - Config: nginxConfig.FmtCode(), - Tokenized: nginxConfig, - AutoCert: certModel.AutoCert == model.AutoCertEnabled, - CertInfo: certInfoMap, - ChatGPTMessages: chatgpt.Content, - Filepath: path, - }) -} - -func SaveSite(c *gin.Context) { - name := c.Param("name") - - if name == "" { - c.JSON(http.StatusNotAcceptable, gin.H{ - "message": "param name is empty", - }) - return - } - - var json struct { - Name string `json:"name" binding:"required"` - Content string `json:"content" binding:"required"` - Overwrite bool `json:"overwrite"` - } - - if !api.BindAndValid(c, &json) { - return - } - - path := nginx.GetConfPath("sites-available", name) - - if !json.Overwrite && helper.FileExists(path) { - c.JSON(http.StatusNotAcceptable, gin.H{ - "message": "File exists", - }) - return - } - - err := os.WriteFile(path, []byte(json.Content), 0644) - if err != nil { - api.ErrHandler(c, err) - return - } - enabledConfigFilePath := nginx.GetConfPath("sites-enabled", name) - // rename the config file if needed - if name != json.Name { - newPath := nginx.GetConfPath("sites-available", json.Name) - s := query.Site - _, err = s.Where(s.Path.Eq(path)).Update(s.Path, newPath) - - // check if dst file exists, do not rename - if helper.FileExists(newPath) { - c.JSON(http.StatusNotAcceptable, gin.H{ - "message": "File exists", - }) - return - } - // recreate a soft link - if helper.FileExists(enabledConfigFilePath) { - _ = os.Remove(enabledConfigFilePath) - enabledConfigFilePath = nginx.GetConfPath("sites-enabled", json.Name) - err = os.Symlink(newPath, enabledConfigFilePath) - - if err != nil { - api.ErrHandler(c, err) - return - } - } - - err = os.Rename(path, newPath) - if err != nil { - api.ErrHandler(c, err) - return - } - - name = json.Name - c.Set("rewriteConfigFileName", name) - } - - enabledConfigFilePath = nginx.GetConfPath("sites-enabled", name) - if helper.FileExists(enabledConfigFilePath) { - // Test nginx configuration - output := nginx.TestConf() - - if nginx.GetLogLevel(output) > nginx.Warn { - c.JSON(http.StatusInternalServerError, gin.H{ - "message": output, - }) - return - } - - output = nginx.Reload() - - if nginx.GetLogLevel(output) > nginx.Warn { - c.JSON(http.StatusInternalServerError, gin.H{ - "message": output, - }) - return - } - } - - GetSite(c) -} - -func EnableSite(c *gin.Context) { - configFilePath := nginx.GetConfPath("sites-available", c.Param("name")) - enabledConfigFilePath := nginx.GetConfPath("sites-enabled", c.Param("name")) - - _, err := os.Stat(configFilePath) - - if err != nil { - api.ErrHandler(c, err) - return - } - - if _, err = os.Stat(enabledConfigFilePath); os.IsNotExist(err) { - err = os.Symlink(configFilePath, enabledConfigFilePath) - - if err != nil { - api.ErrHandler(c, err) - return - } - } - - // Test nginx config, if not pass, then disable the site. - output := nginx.TestConf() - if nginx.GetLogLevel(output) > nginx.Warn { - _ = os.Remove(enabledConfigFilePath) - c.JSON(http.StatusInternalServerError, gin.H{ - "message": output, - }) - return - } - - output = nginx.Reload() - - if nginx.GetLogLevel(output) > nginx.Warn { - c.JSON(http.StatusInternalServerError, gin.H{ - "message": output, - }) - return - } - - c.JSON(http.StatusOK, gin.H{ - "message": "ok", - }) -} - -func DisableSite(c *gin.Context) { - enabledConfigFilePath := nginx.GetConfPath("sites-enabled", c.Param("name")) - _, err := os.Stat(enabledConfigFilePath) - if err != nil { - api.ErrHandler(c, err) - return - } - - err = os.Remove(enabledConfigFilePath) - if err != nil { - api.ErrHandler(c, err) - return - } - - // delete auto cert record - certModel := model.Cert{Filename: c.Param("name")} - err = certModel.Remove() - if err != nil { - api.ErrHandler(c, err) - return - } - - output := nginx.Reload() - if nginx.GetLogLevel(output) > nginx.Warn { - c.JSON(http.StatusInternalServerError, gin.H{ - "message": output, - }) - return - } - - c.JSON(http.StatusOK, gin.H{ - "message": "ok", - }) -} - -func DeleteSite(c *gin.Context) { - var err error - name := c.Param("name") - availablePath := nginx.GetConfPath("sites-available", name) - enabledPath := nginx.GetConfPath("sites-enabled", name) - if _, err = os.Stat(availablePath); os.IsNotExist(err) { - c.JSON(http.StatusNotFound, gin.H{ - "message": "site not found", - }) - return - } - - if _, err = os.Stat(enabledPath); err == nil { - c.JSON(http.StatusNotAcceptable, gin.H{ - "message": "site is enabled", - }) - return - } - - certModel := model.Cert{Filename: name} - _ = certModel.Remove() - - err = os.Remove(availablePath) - if err != nil { - api.ErrHandler(c, err) - return - } - - c.JSON(http.StatusOK, gin.H{ - "message": "ok", - }) -} diff --git a/api/sites/duplicate.go b/api/sites/duplicate.go index 577a288b6..20c580d7c 100644 --- a/api/sites/duplicate.go +++ b/api/sites/duplicate.go @@ -2,15 +2,14 @@ package sites import ( "github.com/0xJacky/Nginx-UI/api" - "github.com/0xJacky/Nginx-UI/internal/helper" - "github.com/0xJacky/Nginx-UI/internal/nginx" + "github.com/0xJacky/Nginx-UI/internal/site" "github.com/gin-gonic/gin" "net/http" ) func DuplicateSite(c *gin.Context) { // Source name - name := c.Param("name") + src := c.Param("name") // Destination name var json struct { @@ -21,24 +20,13 @@ func DuplicateSite(c *gin.Context) { return } - src := nginx.GetConfPath("sites-available", name) - dst := nginx.GetConfPath("sites-available", json.Name) - - if helper.FileExists(dst) { - c.JSON(http.StatusNotAcceptable, gin.H{ - "message": "File exists", - }) - return - } - - _, err := helper.CopyFile(src, dst) - + err := site.Duplicate(src, json.Name) if err != nil { api.ErrHandler(c, err) return } c.JSON(http.StatusOK, gin.H{ - "dst": dst, + "message": "ok", }) } diff --git a/api/sites/list.go b/api/sites/list.go index 1cb29c93e..2973b3635 100644 --- a/api/sites/list.go +++ b/api/sites/list.go @@ -4,9 +4,14 @@ import ( "github.com/0xJacky/Nginx-UI/api" "github.com/0xJacky/Nginx-UI/internal/config" "github.com/0xJacky/Nginx-UI/internal/nginx" + "github.com/0xJacky/Nginx-UI/model" + "github.com/0xJacky/Nginx-UI/query" "github.com/gin-gonic/gin" + "github.com/samber/lo" + "github.com/spf13/cast" "net/http" "os" + "path/filepath" "strings" ) @@ -15,6 +20,7 @@ func GetSiteList(c *gin.Context) { enabled := c.Query("enabled") orderBy := c.Query("order_by") sort := c.DefaultQuery("sort", "desc") + querySiteCategoryId := cast.ToUint64(c.Query("site_category_id")) configFiles, err := os.ReadDir(nginx.GetConfPath("sites-available")) if err != nil { @@ -28,6 +34,20 @@ func GetSiteList(c *gin.Context) { return } + s := query.Site + sTx := s.Preload(s.SiteCategory) + if querySiteCategoryId != 0 { + sTx.Where(s.SiteCategoryID.Eq(querySiteCategoryId)) + } + sites, err := sTx.Find() + if err != nil { + api.ErrHandler(c, err) + return + } + sitesMap := lo.SliceToMap(sites, func(item *model.Site) (string, *model.Site) { + return filepath.Base(item.Path), item + }) + enabledConfigMap := make(map[string]bool) for i := range enabledConfig { enabledConfigMap[enabledConfig[i].Name()] = true @@ -38,28 +58,46 @@ func GetSiteList(c *gin.Context) { for i := range configFiles { file := configFiles[i] fileInfo, _ := file.Info() - if !file.IsDir() { - // name filter - if name != "" && !strings.Contains(file.Name(), name) { + if file.IsDir() { + continue + } + // name filter + if name != "" && !strings.Contains(file.Name(), name) { + continue + } + // status filter + if enabled != "" { + if enabled == "true" && !enabledConfigMap[file.Name()] { continue } - // status filter - if enabled != "" { - if enabled == "true" && !enabledConfigMap[file.Name()] { - continue - } - if enabled == "false" && enabledConfigMap[file.Name()] { - continue - } + if enabled == "false" && enabledConfigMap[file.Name()] { + continue } - configs = append(configs, config.Config{ - Name: file.Name(), - ModifiedAt: fileInfo.ModTime(), - Size: fileInfo.Size(), - IsDir: fileInfo.IsDir(), - Enabled: enabledConfigMap[file.Name()], - }) } + var ( + siteCategoryId uint64 + siteCategory *model.SiteCategory + ) + + if site, ok := sitesMap[file.Name()]; ok { + siteCategoryId = site.SiteCategoryID + siteCategory = site.SiteCategory + } + + // site category filter + if querySiteCategoryId != 0 && siteCategoryId != querySiteCategoryId { + continue + } + + configs = append(configs, config.Config{ + Name: file.Name(), + ModifiedAt: fileInfo.ModTime(), + Size: fileInfo.Size(), + IsDir: fileInfo.IsDir(), + Enabled: enabledConfigMap[file.Name()], + SiteCategoryID: siteCategoryId, + SiteCategory: siteCategory, + }) } configs = config.Sort(orderBy, sort, configs) diff --git a/api/sites/router.go b/api/sites/router.go index a604e77c6..95af9680a 100644 --- a/api/sites/router.go +++ b/api/sites/router.go @@ -3,23 +3,32 @@ package sites import "github.com/gin-gonic/gin" func InitRouter(r *gin.RouterGroup) { - r.GET("domains", GetSiteList) - r.GET("domain/:name", GetSite) - r.POST("domain/:name", SaveSite) - r.POST("domain/:name/enable", EnableSite) - r.POST("domain/:name/disable", DisableSite) - r.POST("domain/:name/advance", DomainEditByAdvancedMode) - r.DELETE("domain/:name", DeleteSite) - r.POST("domain/:name/duplicate", DuplicateSite) + r.GET("sites", GetSiteList) + r.GET("sites/:name", GetSite) + r.PUT("sites", BatchUpdateSites) + r.POST("sites/:name/advance", DomainEditByAdvancedMode) r.POST("auto_cert/:name", AddDomainToAutoCert) r.DELETE("auto_cert/:name", RemoveDomainFromAutoCert) + + // rename site + r.POST("sites/:name/rename", RenameSite) + // enable site + r.POST("sites/:name/enable", EnableSite) + // disable site + r.POST("sites/:name/disable", DisableSite) + // save site + r.POST("sites/:name", SaveSite) + // delete site + r.DELETE("sites/:name", DeleteSite) + // duplicate site + r.POST("sites/:name/duplicate", DuplicateSite) } func InitCategoryRouter(r *gin.RouterGroup) { r.GET("site_categories", GetCategoryList) - r.GET("site_category/:id", GetCategory) - r.POST("site_category", AddCategory) - r.PUT("site_category/:id", ModifyCategory) - r.DELETE("site_category/:id", DeleteCategory) - r.POST("site_category/:id/recover", RecoverCategory) + r.GET("site_categories/:id", GetCategory) + r.POST("site_categories", AddCategory) + r.POST("site_categories/:id", ModifyCategory) + r.DELETE("site_categories/:id", DeleteCategory) + r.POST("site_categories/:id/recover", RecoverCategory) } diff --git a/api/sites/site.go b/api/sites/site.go new file mode 100644 index 000000000..f0fe25991 --- /dev/null +++ b/api/sites/site.go @@ -0,0 +1,216 @@ +package sites + +import ( + "github.com/0xJacky/Nginx-UI/api" + "github.com/0xJacky/Nginx-UI/internal/cert" + "github.com/0xJacky/Nginx-UI/internal/nginx" + "github.com/0xJacky/Nginx-UI/internal/site" + "github.com/0xJacky/Nginx-UI/model" + "github.com/0xJacky/Nginx-UI/query" + "github.com/gin-gonic/gin" + "github.com/sashabaranov/go-openai" + "github.com/uozi-tech/cosy" + "github.com/uozi-tech/cosy/logger" + "gorm.io/gorm/clause" + "net/http" + "os" +) + +func GetSite(c *gin.Context) { + name := c.Param("name") + + path := nginx.GetConfPath("sites-available", name) + file, err := os.Stat(path) + if os.IsNotExist(err) { + c.JSON(http.StatusNotFound, gin.H{ + "message": "file not found", + }) + return + } + + enabled := true + if _, err := os.Stat(nginx.GetConfPath("sites-enabled", name)); os.IsNotExist(err) { + enabled = false + } + + g := query.ChatGPTLog + chatgpt, err := g.Where(g.Name.Eq(path)).FirstOrCreate() + if err != nil { + api.ErrHandler(c, err) + return + } + + if chatgpt.Content == nil { + chatgpt.Content = make([]openai.ChatCompletionMessage, 0) + } + + s := query.Site + siteModel, err := s.Where(s.Path.Eq(path)).FirstOrCreate() + if err != nil { + api.ErrHandler(c, err) + return + } + + certModel, err := model.FirstCert(name) + if err != nil { + logger.Warn(err) + } + + if siteModel.Advanced { + origContent, err := os.ReadFile(path) + if err != nil { + api.ErrHandler(c, err) + return + } + + c.JSON(http.StatusOK, Site{ + ModifiedAt: file.ModTime(), + Site: siteModel, + Enabled: enabled, + Name: name, + Config: string(origContent), + AutoCert: certModel.AutoCert == model.AutoCertEnabled, + ChatGPTMessages: chatgpt.Content, + Filepath: path, + }) + return + } + + nginxConfig, err := nginx.ParseNgxConfig(path) + if err != nil { + api.ErrHandler(c, err) + return + } + + certInfoMap := make(map[int][]*cert.Info) + for serverIdx, server := range nginxConfig.Servers { + for _, directive := range server.Directives { + if directive.Directive == "ssl_certificate" { + pubKey, err := cert.GetCertInfo(directive.Params) + if err != nil { + logger.Error("Failed to get certificate information", err) + continue + } + certInfoMap[serverIdx] = append(certInfoMap[serverIdx], pubKey) + } + } + } + + c.JSON(http.StatusOK, Site{ + Site: siteModel, + ModifiedAt: file.ModTime(), + Enabled: enabled, + Name: name, + Config: nginxConfig.FmtCode(), + Tokenized: nginxConfig, + AutoCert: certModel.AutoCert == model.AutoCertEnabled, + CertInfo: certInfoMap, + ChatGPTMessages: chatgpt.Content, + Filepath: path, + }) +} + +func SaveSite(c *gin.Context) { + name := c.Param("name") + + var json struct { + Content string `json:"content" binding:"required"` + SiteCategoryID uint64 `json:"site_category_id"` + SyncNodeIDs []uint64 `json:"sync_node_ids"` + Overwrite bool `json:"overwrite"` + } + + if !api.BindAndValid(c, &json) { + return + } + + err := site.Save(name, json.Content, json.Overwrite, json.SiteCategoryID, json.SyncNodeIDs) + if err != nil { + api.ErrHandler(c, err) + return + } + + GetSite(c) +} + +func RenameSite(c *gin.Context) { + oldName := c.Param("name") + var json struct { + NewName string `json:"new_name"` + } + if !cosy.BindAndValid(c, &json) { + return + } + + err := site.Rename(oldName, json.NewName) + if err != nil { + api.ErrHandler(c, err) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "ok", + }) +} + +func EnableSite(c *gin.Context) { + err := site.Enable(c.Param("name")) + if err != nil { + api.ErrHandler(c, err) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "ok", + }) +} + +func DisableSite(c *gin.Context) { + err := site.Disable(c.Param("name")) + if err != nil { + api.ErrHandler(c, err) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "ok", + }) +} + +func DeleteSite(c *gin.Context) { + err := site.Delete(c.Param("name")) + if err != nil { + api.ErrHandler(c, err) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "ok", + }) +} + +func BatchUpdateSites(c *gin.Context) { + cosy.Core[model.Site](c).SetValidRules(gin.H{ + "site_category_id": "required", + }).SetItemKey("path"). + BeforeExecuteHook(func(ctx *cosy.Ctx[model.Site]) { + effectedPath := make([]string, len(ctx.BatchEffectedIDs)) + var sites []*model.Site + for i, name := range ctx.BatchEffectedIDs { + path := nginx.GetConfPath("sites-available", name) + effectedPath[i] = path + sites = append(sites, &model.Site{ + Path: path, + }) + } + s := query.Site + err := s.Clauses(clause.OnConflict{ + DoNothing: true, + }).Create(sites...) + if err != nil { + ctx.AbortWithError(err) + return + } + ctx.BatchEffectedIDs = effectedPath + }).BatchModify() +} diff --git a/api/sites/sites.go b/api/sites/type.go similarity index 92% rename from api/sites/sites.go rename to api/sites/type.go index b29db44a4..4b8e3f118 100644 --- a/api/sites/sites.go +++ b/api/sites/type.go @@ -3,15 +3,16 @@ package sites import ( "github.com/0xJacky/Nginx-UI/internal/cert" "github.com/0xJacky/Nginx-UI/internal/nginx" + "github.com/0xJacky/Nginx-UI/model" "github.com/sashabaranov/go-openai" "time" ) type Site struct { + *model.Site + Name string `json:"name"` ModifiedAt time.Time `json:"modified_at"` - Advanced bool `json:"advanced"` Enabled bool `json:"enabled"` - Name string `json:"name"` Config string `json:"config"` AutoCert bool `json:"auto_cert"` ChatGPTMessages []openai.ChatCompletionMessage `json:"chatgpt_messages,omitempty"` diff --git a/api/streams/router.go b/api/streams/router.go index 52a2fc6bd..4d0ce2dd9 100644 --- a/api/streams/router.go +++ b/api/streams/router.go @@ -4,11 +4,11 @@ import "github.com/gin-gonic/gin" func InitRouter(r *gin.RouterGroup) { r.GET("streams", GetStreams) - r.GET("stream/:name", GetStream) - r.POST("stream/:name", SaveStream) - r.POST("stream/:name/enable", EnableStream) - r.POST("stream/:name/disable", DisableStream) - r.POST("stream/:name/advance", AdvancedEdit) - r.DELETE("stream/:name", DeleteStream) - r.POST("stream/:name/duplicate", Duplicate) + r.GET("streams/:name", GetStream) + r.POST("streams/:name", SaveStream) + r.POST("streams/:name/enable", EnableStream) + r.POST("streams/:name/disable", DisableStream) + r.POST("streams/:name/advance", AdvancedEdit) + r.DELETE("streams/:name", DeleteStream) + r.POST("streams/:name/duplicate", Duplicate) } diff --git a/api/template/router.go b/api/template/router.go index 0b58073af..a135a6bcb 100644 --- a/api/template/router.go +++ b/api/template/router.go @@ -3,9 +3,9 @@ package template import "github.com/gin-gonic/gin" func InitRouter(r *gin.RouterGroup) { - r.GET("template", GetTemplate) - r.GET("template/configs", GetTemplateConfList) - r.GET("template/blocks", GetTemplateBlockList) - r.GET("template/block/:name", GetTemplateBlock) - r.POST("template/block/:name", GetTemplateBlock) + r.GET("templates", GetTemplate) + r.GET("templates/configs", GetTemplateConfList) + r.GET("templates/blocks", GetTemplateBlockList) + r.GET("templates/block/:name", GetTemplateBlock) + r.POST("templates/block/:name", GetTemplateBlock) } diff --git a/api/user/passkey.go b/api/user/passkey.go index 9df1d6327..55bb1e8e6 100644 --- a/api/user/passkey.go +++ b/api/user/passkey.go @@ -23,7 +23,7 @@ import ( const passkeyTimeout = 30 * time.Second -func buildCachePasskeyRegKey(id int) string { +func buildCachePasskeyRegKey(id uint64) string { return fmt.Sprintf("passkey-reg-%d", id) } @@ -130,7 +130,7 @@ func FinishPasskeyLogin(c *gin.Context) { LastUsedAt: time.Now().Unix(), }) - outUser, err = u.FirstByID(cast.ToInt(string(userHandle))) + outUser, err = u.FirstByID(cast.ToUint64(string(userHandle))) return outUser, err }, *sessionData, c.Request) if err != nil { diff --git a/api/user/router.go b/api/user/router.go index a53f34ded..47704b3f5 100644 --- a/api/user/router.go +++ b/api/user/router.go @@ -19,11 +19,11 @@ func InitAuthRouter(r *gin.RouterGroup) { func InitManageUserRouter(r *gin.RouterGroup) { r.GET("users", GetUsers) - r.GET("user/:id", GetUser) - r.POST("user", AddUser) - r.POST("user/:id", EditUser) - r.DELETE("user/:id", DeleteUser) - r.PATCH("user/:id", RecoverUser) + r.GET("users/:id", GetUser) + r.POST("users", AddUser) + r.POST("users/:id", EditUser) + r.DELETE("users/:id", DeleteUser) + r.PATCH("users/:id", RecoverUser) } func InitUserRouter(r *gin.RouterGroup) { diff --git a/api/user/user.go b/api/user/user.go index bfbe9ecc9..f8e7a5bcc 100644 --- a/api/user/user.go +++ b/api/user/user.go @@ -17,7 +17,7 @@ func GetUsers(c *gin.Context) { } func GetUser(c *gin.Context) { - id := cast.ToInt(c.Param("id")) + id := cast.ToUint64(c.Param("id")) u := query.User @@ -69,7 +69,7 @@ func AddUser(c *gin.Context) { } func EditUser(c *gin.Context) { - userId := cast.ToInt(c.Param("id")) + userId := cast.ToUint64(c.Param("id")) if settings.NodeSettings.Demo && userId == 1 { c.JSON(http.StatusNotAcceptable, gin.H{ diff --git a/app/.eslint-auto-import.mjs b/app/.eslint-auto-import.mjs new file mode 100644 index 000000000..d09af3145 --- /dev/null +++ b/app/.eslint-auto-import.mjs @@ -0,0 +1,95 @@ +export default { + "globals": { + "$gettext": true, + "$ngettext": true, + "$npgettext": true, + "$pgettext": true, + "Component": true, + "ComponentPublicInstance": true, + "ComputedRef": true, + "DirectiveBinding": true, + "EffectScope": true, + "ExtractDefaultPropTypes": true, + "ExtractPropTypes": true, + "ExtractPublicPropTypes": true, + "InjectionKey": true, + "MaybeRef": true, + "MaybeRefOrGetter": true, + "PropType": true, + "Ref": true, + "VNode": true, + "WritableComputedRef": true, + "acceptHMRUpdate": true, + "computed": true, + "createApp": true, + "createPinia": true, + "customRef": true, + "defineAsyncComponent": true, + "defineComponent": true, + "defineStore": true, + "effectScope": true, + "getActivePinia": true, + "getCurrentInstance": true, + "getCurrentScope": true, + "h": true, + "inject": true, + "isProxy": true, + "isReactive": true, + "isReadonly": true, + "isRef": true, + "mapActions": true, + "mapGetters": true, + "mapState": true, + "mapStores": true, + "mapWritableState": true, + "markRaw": true, + "nextTick": true, + "onActivated": true, + "onBeforeMount": true, + "onBeforeRouteLeave": true, + "onBeforeRouteUpdate": true, + "onBeforeUnmount": true, + "onBeforeUpdate": true, + "onDeactivated": true, + "onErrorCaptured": true, + "onMounted": true, + "onRenderTracked": true, + "onRenderTriggered": true, + "onScopeDispose": true, + "onServerPrefetch": true, + "onUnmounted": true, + "onUpdated": true, + "onWatcherCleanup": true, + "provide": true, + "reactive": true, + "readonly": true, + "ref": true, + "resolveComponent": true, + "setActivePinia": true, + "setMapStoreSuffix": true, + "shallowReactive": true, + "shallowReadonly": true, + "shallowRef": true, + "storeToRefs": true, + "toRaw": true, + "toRef": true, + "toRefs": true, + "toValue": true, + "triggerRef": true, + "unref": true, + "useAttrs": true, + "useCssModule": true, + "useCssVars": true, + "useId": true, + "useLink": true, + "useModel": true, + "useRoute": true, + "useRouter": true, + "useSlots": true, + "useTemplateRef": true, + "watch": true, + "watchEffect": true, + "watchPostEffect": true, + "watchSyncEffect": true + } +} diff --git a/app/components.d.ts b/app/components.d.ts index 42e75225c..89bb9ba5c 100644 --- a/app/components.d.ts +++ b/app/components.d.ts @@ -49,6 +49,8 @@ declare module 'vue' { APopconfirm: typeof import('ant-design-vue/es')['Popconfirm'] APopover: typeof import('ant-design-vue/es')['Popover'] AProgress: typeof import('ant-design-vue/es')['Progress'] + ARadioButton: typeof import('ant-design-vue/es')['RadioButton'] + ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup'] AResult: typeof import('ant-design-vue/es')['Result'] ARow: typeof import('ant-design-vue/es')['Row'] ASelect: typeof import('ant-design-vue/es')['Select'] diff --git a/app/eslint.config.mjs b/app/eslint.config.mjs index e593f06a6..c6ffbe03b 100644 --- a/app/eslint.config.mjs +++ b/app/eslint.config.mjs @@ -1,10 +1,14 @@ import createConfig from '@antfu/eslint-config' import sonarjs from 'eslint-plugin-sonarjs' +import autoImport from './.eslint-auto-import.mjs' export default createConfig( { stylistic: true, - ignores: ['**/version.json', 'tsconfig.json', 'tsconfig.node.json'], + ignores: ['**/version.json', 'tsconfig.json', 'tsconfig.node.json', '.eslint-auto-import.mjs'], + languageOptions: { + globals: autoImport.globals, + }, }, sonarjs.configs.recommended, { diff --git a/app/package.json b/app/package.json index 0b17c51ef..6b5674b45 100644 --- a/app/package.json +++ b/app/package.json @@ -39,6 +39,7 @@ "reconnecting-websocket": "^4.4.0", "sortablejs": "^1.15.3", "universal-cookie": "^7.2.1", + "unocss": "^0.63.6", "vite-plugin-build-id": "0.4.2", "vue": "^3.5.12", "vue-dompurify-html": "^5.1.0", @@ -51,6 +52,12 @@ }, "devDependencies": { "@antfu/eslint-config": "^3.8.0", + "@iconify-json/fa": "1.1.5", + "@iconify-json/tabler": "1.1.95", + "@iconify/tools": "3.0.5", + "@iconify/types": "^2.0.0", + "@iconify/utils": "^2.1.33", + "@iconify/vue": "4.1.1", "@simplewebauthn/types": "^11.0.0", "@types/lodash": "^4.17.12", "@types/nprogress": "^0.2.3", diff --git a/app/pnpm-lock.yaml b/app/pnpm-lock.yaml index 6215f307c..5dee75a99 100644 --- a/app/pnpm-lock.yaml +++ b/app/pnpm-lock.yaml @@ -86,6 +86,9 @@ importers: universal-cookie: specifier: ^7.2.1 version: 7.2.1 + unocss: + specifier: ^0.63.6 + version: 0.63.6(postcss@8.4.47)(rollup@4.24.0)(typescript@5.6.3)(vite@5.4.10(@types/node@22.7.9)(less@4.2.0)) vite-plugin-build-id: specifier: 0.4.2 version: 0.4.2 @@ -117,6 +120,24 @@ importers: '@antfu/eslint-config': specifier: ^3.8.0 version: 3.8.0(@typescript-eslint/utils@8.11.0(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3))(@vue/compiler-sfc@3.5.12)(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@iconify-json/fa': + specifier: 1.1.5 + version: 1.1.5 + '@iconify-json/tabler': + specifier: 1.1.95 + version: 1.1.95 + '@iconify/tools': + specifier: 3.0.5 + version: 3.0.5 + '@iconify/types': + specifier: ^2.0.0 + version: 2.0.0 + '@iconify/utils': + specifier: ^2.1.33 + version: 2.1.33 + '@iconify/vue': + specifier: 4.1.1 + version: 4.1.1(vue@3.5.12(typescript@5.6.3)) '@simplewebauthn/types': specifier: ^11.0.0 version: 11.0.0 @@ -954,138 +975,282 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.23.1': + resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.21.5': resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} engines: {node: '>=12'} cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.23.1': + resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.21.5': resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} cpu: [arm] os: [android] + '@esbuild/android-arm@0.23.1': + resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.21.5': resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} cpu: [x64] os: [android] + '@esbuild/android-x64@0.23.1': + resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.21.5': resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.23.1': + resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.21.5': resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.23.1': + resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.21.5': resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.23.1': + resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.21.5': resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.23.1': + resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.21.5': resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.23.1': + resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.21.5': resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.23.1': + resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.21.5': resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.23.1': + resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.21.5': resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.23.1': + resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.21.5': resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.23.1': + resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.21.5': resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.23.1': + resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.21.5': resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.23.1': + resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.21.5': resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.23.1': + resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.21.5': resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.23.1': + resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-x64@0.21.5': resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.23.1': + resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.23.1': + resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.21.5': resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.23.1': + resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/sunos-x64@0.21.5': resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.23.1': + resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.21.5': resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.23.1': + resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.21.5': resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} engines: {node: '>=12'} cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.23.1': + resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.21.5': resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} engines: {node: '>=12'} cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.23.1': + resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-plugin-eslint-comments@4.4.0': resolution: {integrity: sha512-yljsWl5Qv3IkIRmJ38h3NrHXFCm4EUl55M8doGTF6hvzvFF8kRpextgSrg2dwHev9lzBZyafCr9RelGIyQm6fw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1158,6 +1323,26 @@ packages: resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} engines: {node: '>=18.18'} + '@iconify-json/fa@1.1.5': + resolution: {integrity: sha512-a6iC7FArLDb02hYKrgQWdn5fCCtXxWhw9mkqXbKLvuta4DdZuZdaSbDoA4GuZx1t+0cD7/epF8I9tkrNvyzrrA==} + + '@iconify-json/tabler@1.1.95': + resolution: {integrity: sha512-Qg+VpKgSImpA9g2ger17cWIBvirlixUplTXshu/miegBCfaicYEyyX2pCilCJEuujeNVh47+ySD7CoBJS2f6pQ==} + + '@iconify/tools@3.0.5': + resolution: {integrity: sha512-NYhdaOK/pPTInlNRQHP1iaOMQtu6XfIjhYh8KBUqAiKlmSWwjWYT4bm8RpNgtgEmYAYrm2PY28A2OGBP35pA1w==} + + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + + '@iconify/utils@2.1.33': + resolution: {integrity: sha512-jP9h6v/g0BIZx0p7XGJJVtkVnydtbgTgt9mVNcGDYwaa7UhdHdI9dvoq+gKj9sijMSJKxUPEG2JyjsgXjxL7Kw==} + + '@iconify/vue@4.1.1': + resolution: {integrity: sha512-RL85Bm/DAe8y6rT6pux7D2FJSiUEM/TPfyK7GrbAOfTSwrhvwJW+S5yijdGcmtXouA8MtuH9C7l4hiSE4mLMjg==} + peerDependencies: + vue: '>=3' + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -1211,6 +1396,9 @@ packages: resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@polka/url@1.0.0-next.28': + resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} + '@rollup/pluginutils@5.1.3': resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} engines: {node: '>=14.0.0'} @@ -1326,6 +1514,9 @@ packages: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} + '@types/cheerio@0.22.35': + resolution: {integrity: sha512-yD57BchKRvTV+JD53UZ6PD8KWY5g5rvvMLRnZR3EQBCZXiDT/HR+pKpMzFGlWNhFrXlo7VPZXtKvIEwZkAWOIA==} + '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} @@ -1374,12 +1565,18 @@ packages: '@types/sortablejs@1.15.8': resolution: {integrity: sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==} + '@types/tar@6.1.13': + resolution: {integrity: sha512-IznnlmU5f4WcGTh2ltRu/Ijpmk8wiWXfF0VA4s+HPjHZgvFggk1YaIkbo5krX/zUCzWF8N/l4+W/LNxnvAJ8nw==} + '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} '@types/web-bluetooth@0.0.20': resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + '@types/yauzl@2.10.3': + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + '@typescript-eslint/eslint-plugin@7.16.1': resolution: {integrity: sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A==} engines: {node: ^18.18.0 || >=20.0.0} @@ -1485,6 +1682,86 @@ packages: resolution: {integrity: sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@unocss/astro@0.63.6': + resolution: {integrity: sha512-5Fjlv6dpQo6o2PUAcEv8p24G8rn8Op79xLFofq2V+iA/Q32G9/UsxTLOpj+yc+q0YdJrFfDCT2X/3pvVY8Db5g==} + peerDependencies: + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + peerDependenciesMeta: + vite: + optional: true + + '@unocss/cli@0.63.6': + resolution: {integrity: sha512-OZb8hO0x4nCJjFd3Gq3km78YnyMAdq282D+BLiDE6IhQ5WHCVL7fyhfgIVL6xwxISDVxiyITwNb72ky0MEutPg==} + engines: {node: '>=14'} + hasBin: true + + '@unocss/config@0.63.6': + resolution: {integrity: sha512-+4Lt5uTwRgu1z7vhOUzDf+mL+BQYdaa/Z8NMT2Fiqb37tcjEKvmwaUHdfE22Vif1luDgC6xqFsn6qqFtOxhoWQ==} + engines: {node: '>=14'} + + '@unocss/core@0.63.6': + resolution: {integrity: sha512-Q4QPgJ271Up89+vIqqOKgtdCKkFpHqvHN8W1LUlKPqtYnOvVYaOIVNAZowaIdEhPuc83yLc6Tg2+7riK18QKEw==} + + '@unocss/extractor-arbitrary-variants@0.63.6': + resolution: {integrity: sha512-HJX0oAa9uzwKYoU8CoJdP1gxjuqFmOLxyZmITjStAmZNZpIxlz2wz4VrHmqml2dkvx/mifGGGc/GxZpQ36D12Q==} + + '@unocss/inspector@0.63.6': + resolution: {integrity: sha512-DQDJnhtzdHIQXD2vCdj5ytFnHfQCWJGPmrHJHXxzkTYn8nIovV1roVl1ITLxkDIIYK9bdYneg2imQN5JCZhHmQ==} + + '@unocss/postcss@0.63.6': + resolution: {integrity: sha512-XI6U1jMwbQoSHVWpZZu3Cxp3t1PVj5VOj+IYtz7xmcWP9GVK+eyETo/xyB0l4muD4emXfSrhNDrFYzSyIyF5cg==} + engines: {node: '>=14'} + peerDependencies: + postcss: ^8.4.21 + + '@unocss/preset-attributify@0.63.6': + resolution: {integrity: sha512-sHH17mfl/THHLxCLAHqPdUniCNMFjAxBHFDZYgGi83azuarF2evI5Mtc3Qsj3nzoSQwTPmK2VY3XYUUrpPDGWQ==} + + '@unocss/preset-icons@0.63.6': + resolution: {integrity: sha512-fRU44wXABnMPT/9zhKBNSUeDJlOxJhUJP9W3FSRnc+ktjAifJIj0xpUKtEqxL46QMq825Bsj2yDSquzP+XYGnQ==} + + '@unocss/preset-mini@0.63.6': + resolution: {integrity: sha512-pZDZbSuxabHSwPIy3zCgQ4MNdVCSHvOvZecreH+v96R1oOhquiwU8WiSbkxvZiKiLQJd7JUVW87E1pAzr5ZGGQ==} + + '@unocss/preset-tagify@0.63.6': + resolution: {integrity: sha512-3lKhk4MW3RqJBwIvBXHj0H0/kHkFlKtCIBQFiBcCJh8TXOID8IZ0iVjuGwdlk63VTizI/wnsNDOVpj6YcjRRlw==} + + '@unocss/preset-typography@0.63.6': + resolution: {integrity: sha512-AXmBVnbV54gUIv5kbywjZek9ZlKRwJfBDVMtWOcLOjN3AHirGx1W2oq2UzNkfYZ2leof/Y2BocxeTwGCCRhqDQ==} + + '@unocss/preset-uno@0.63.6': + resolution: {integrity: sha512-67PbHyVgAe9Rz0Rhyl3zBibFuGmqQMRPMkRjNYrwmmtNydpQYsXbfnDs0p8mZFp6uO2o3Jkh7urqEtixHHvq0Q==} + + '@unocss/preset-web-fonts@0.63.6': + resolution: {integrity: sha512-ko1aHDax0u5CQi1BXggv6uW5Vq/LQRWwzOxqBFTh1JlGHPZTw4CdVJkYnlpt3WEW+FPUzZYjhKmMmQY7KtOTng==} + + '@unocss/preset-wind@0.63.6': + resolution: {integrity: sha512-W3oZ2TXSqStNE+X++kcspRTF2Szu2ej6NW5Kiyy6WQn/+ZD77AF4VtvzHtzFVZ2QKpEIovGBpU5tywooHbB7hw==} + + '@unocss/reset@0.63.6': + resolution: {integrity: sha512-gq73RSZj54MOloqrivkoMPXCqNG2WpIyBT1AYlF76uKxEEbUD41E8uBUhLSKs7gFgF01yQJLRaIuyN1yw09pbQ==} + + '@unocss/rule-utils@0.63.6': + resolution: {integrity: sha512-moeDEq5d9mB8gSYeoqHMkXWWekaFFdhg7QCuwwCbxCc+NPMOgGkmfAoafz+y2tdvK7pEuT191RWOiHQ0MkA5oQ==} + engines: {node: '>=14'} + + '@unocss/transformer-attributify-jsx@0.63.6': + resolution: {integrity: sha512-/RU09MF+hJK7cFbLJ+8vloCGyhn6Oys8R6gey0auB0+nw/ucUXoLQKWgUqo9taQlLuYOiehdkYjQSdWn5lyA/Q==} + + '@unocss/transformer-compile-class@0.63.6': + resolution: {integrity: sha512-zzAqs8adnTUOLA88RgcToadcrz9gjxrZk6IrcmMqMmWqk0MOWNQHIN0RzKa/yaw4QhO2xuGyIz4/WHyXuCXMQg==} + + '@unocss/transformer-directives@0.63.6': + resolution: {integrity: sha512-XcNOwLRbfrJSU6YXyLgiMzAigSzjIdvHwS3lLCZ2n6DWuLmTuXBfvVtRxeJ+aflNkhpQNKONCClC4s6I2r53uw==} + + '@unocss/transformer-variant-group@0.63.6': + resolution: {integrity: sha512-ebYSjZnZrtcJYjmAEDwGVwPuaQ9EVWKNDDJFFSusP8k/6PjJoHDh0qkj+hdPPDhYn81yzJQalU1eSUSlfC30VA==} + + '@unocss/vite@0.63.6': + resolution: {integrity: sha512-gxK3gtvYQH5S/qtuvsY4M0S+KJPZnYrOQI/Gopufx+b2qgmwZ/TSAe66gWeKYfe3DfQsmA3PPh/GXpkK+/FnHg==} + peerDependencies: + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + '@vitejs/plugin-vue-jsx@4.0.1': resolution: {integrity: sha512-7mg9HFGnFHMEwCdB6AY83cVK4A6sCqnrjFYF4WIlebYAQVVJ/sC/CiTruVdrRlhrFoeZ8rlMxY9wYpPTIRhhAg==} engines: {node: ^18.0.0 || >=20.0.0} @@ -1851,10 +2128,19 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} + bundle-require@5.0.0: + resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: '>=0.18' + bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -1867,6 +2153,10 @@ packages: magicast: optional: true + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + call-bind@1.0.7: resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} engines: {node: '>= 0.4'} @@ -1896,6 +2186,13 @@ packages: character-entities@2.0.2: resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + cheerio-select@2.1.0: + resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} + + cheerio@1.0.0: + resolution: {integrity: sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==} + engines: {node: '>=18.17'} + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -1935,6 +2232,9 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -2022,6 +2322,10 @@ packages: resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + css-tree@3.0.0: + resolution: {integrity: sha512-o88DVQ6GzsABn1+6+zo2ct801dBO5OASVyxbbvA2W20ue2puSh/VOuqUj90eUeMSX/xqGqBmOKiRQN7tJOuBXw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + css-what@6.1.0: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} @@ -2165,6 +2469,9 @@ packages: resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} engines: {node: '>=12'} + duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -2177,6 +2484,12 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + encoding-sniffer@0.2.0: + resolution: {integrity: sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + enhanced-resolve@5.17.1: resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} engines: {node: '>=10.13.0'} @@ -2238,6 +2551,11 @@ packages: engines: {node: '>=12'} hasBin: true + esbuild@0.23.1: + resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -2510,6 +2828,11 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} + extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -2526,6 +2849,17 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + + fdir@6.4.2: + resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -2617,6 +2951,10 @@ packages: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + get-stream@8.0.1: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} @@ -2692,6 +3030,10 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} @@ -2743,6 +3085,9 @@ packages: resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} engines: {node: '>=8'} + htmlparser2@9.1.0: + resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} + human-signals@5.0.0: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} @@ -2764,6 +3109,9 @@ packages: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} + importx@0.4.4: + resolution: {integrity: sha512-Lo1pukzAREqrBnnHC+tj+lreMTAvyxtkKsMxLY8H15M/bvLl54p3YuoTI70Tz7Il0AsgSlD7Lrk/FaApRcBL7w==} + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -2932,6 +3280,10 @@ packages: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true + jiti@2.0.0-beta.3: + resolution: {integrity: sha512-pmfRbVRs/7khFrSAYnSiJ8C0D5GvzkE4Ey2pAvUcJsw1ly/p+7ut27jbJrjY79BpAJQJ4gXYFtK6d1Aub+9baQ==} + hasBin: true + jiti@2.3.3: resolution: {integrity: sha512-EX4oNDwcXSivPrw2qKH2LB5PoFxEvgtv2JgwW0bU858HoLQ+kutSvjLMUqBd0PeJYEinLWhoI9Ol0eYMqj/wNQ==} hasBin: true @@ -2998,6 +3350,9 @@ packages: knitwork@1.1.0: resolution: {integrity: sha512-oHnmiBUVHz1V+URE77PNot2lv3QiYU2zQf1JjOVkMt3YDKGbu8NAFr+c4mcNOhdsGrB/VpVbRwPwhiXrPhxQbw==} + kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + language-subtag-registry@0.3.23: resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} @@ -3025,6 +3380,14 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + load-tsconfig@0.2.5: + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + local-pkg@0.4.3: + resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} + engines: {node: '>=14'} + local-pkg@0.5.0: resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} engines: {node: '>=14'} @@ -3128,6 +3491,9 @@ packages: mdn-data@2.0.30: resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + mdn-data@2.10.0: + resolution: {integrity: sha512-qq7C3EtK3yJXMwz1zAab65pjl+UhohqMOctTgcqjLOWABqmwj+me02LSsCuEUxnst9X1lCBpoE0WArGKgdGDzw==} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -3269,6 +3635,10 @@ packages: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} + minipass@4.2.8: + resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} + engines: {node: '>=8'} + minipass@5.0.0: resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} engines: {node: '>=8'} @@ -3293,6 +3663,10 @@ packages: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} + mrmime@2.0.0: + resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} + engines: {node: '>=10'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -3397,6 +3771,9 @@ packages: resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} engines: {node: '>= 0.4'} + ofetch@1.4.1: + resolution: {integrity: sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==} + ohash@1.1.4: resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==} @@ -3463,9 +3840,18 @@ packages: parse5-htmlparser2-tree-adapter@6.0.1: resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} + parse5-htmlparser2-tree-adapter@7.1.0: + resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} + + parse5-parser-stream@7.1.2: + resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} + parse5@6.0.1: resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + parse5@7.2.0: + resolution: {integrity: sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==} + path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} @@ -3503,6 +3889,9 @@ packages: pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + perfect-debounce@1.0.0: resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} @@ -3623,6 +4012,9 @@ packages: prr@1.0.1: resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -3817,6 +4209,10 @@ packages: simple-get@4.0.1: resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + sirv@2.0.4: + resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} + engines: {node: '>= 10'} + sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} @@ -4027,6 +4423,10 @@ packages: tinyexec@0.3.1: resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} + tinyglobby@0.2.9: + resolution: {integrity: sha512-8or1+BGEdk1Zkkw2ii16qSS7uVrQJPre5A9o/XkWPATkk23FZh/15BKFxPnlTy6vkljZxLqYCzzBMj30ZrSvjw==} + engines: {node: '>=12.0.0'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -4035,6 +4435,10 @@ packages: resolution: {integrity: sha512-khrZo4buq4qVmsGzS5yQjKe/WsFvV8fGfOjDQN0q4iy9FjRfPWRgTFrU8u1R2iu/SfWLhY9WnCi4Jhdrcbtg+g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + ts-api-utils@1.3.0: resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} @@ -4050,6 +4454,11 @@ packages: tslib@2.8.0: resolution: {integrity: sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==} + tsx@4.19.1: + resolution: {integrity: sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==} + engines: {node: '>=18.0.0'} + hasBin: true + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -4102,6 +4511,9 @@ packages: unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + unconfig@0.5.5: + resolution: {integrity: sha512-VQZ5PT9HDX+qag0XdgQi8tJepPhXiR/yVOkn707gJDKo31lGjRilPREiQJ9Z6zd/Ugpv6ZvO5VxVIcatldYcNQ==} + uncrypto@0.1.3: resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} @@ -4111,6 +4523,10 @@ packages: undici-types@6.19.8: resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + undici@6.20.1: + resolution: {integrity: sha512-AjQF1QsmqfJys+LXfGTNum+qw4S88CojRInG/6t31W/1fk6G59s92bnAvGz5Cmur+kQv2SURXEvvudLmbrE8QA==} + engines: {node: '>=18.17'} + unicode-canonical-property-names-ecmascript@2.0.1: resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} engines: {node: '>=4'} @@ -4149,6 +4565,18 @@ packages: universal-cookie@7.2.1: resolution: {integrity: sha512-GEKneQ0sz8qbobkYM5s9elAx6l7GQDNVl3Siqmc7bt/YccyyXWDPn+fht3J1qMcaLwPrzkty3i+dNfPGP2/9hA==} + unocss@0.63.6: + resolution: {integrity: sha512-OKJJKEFWVz+Lsf3JdOgRiRtL+QOUQRBov89taUcCPFPZtrhP6pPVFCZHD9qMvY4IChMX7dzalQax3ZXJ3hbtkQ==} + engines: {node: '>=14'} + peerDependencies: + '@unocss/webpack': 0.63.6 + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + peerDependenciesMeta: + '@unocss/webpack': + optional: true + vite: + optional: true + unplugin-auto-import@0.18.3: resolution: {integrity: sha512-q3FUtGQjYA2e+kb1WumyiQMjHM27MrTQ05QfVwtLRVhyYe+KF6TblBYaEX9L6Z0EibsqaXAiW+RFfkcQpfaXzg==} engines: {node: '>=14'} @@ -4270,6 +4698,9 @@ packages: peerDependencies: eslint: '>=6.0.0' + vue-flow-layout@0.0.5: + resolution: {integrity: sha512-lZlqQ/Se1trGMtBMneZDWaiQiQBuxU8ivZ+KpJMem5zKROFpzuPq9KqyWABbSYbxq0qhqZs1I4DBwrY041rtOA==} + vue-router@4.4.5: resolution: {integrity: sha512-4fKZygS8cH1yCyuabAXGUAsyi1b2/o/OKgu/RUb+znIYOxPRxdkytJEx+0wGcpBE1pX6vUgh5jwWOKRGvuA/7Q==} peerDependencies: @@ -4331,6 +4762,14 @@ packages: webpack-virtual-modules@0.6.2: resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} @@ -4397,6 +4836,9 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -5421,72 +5863,144 @@ snapshots: '@esbuild/aix-ppc64@0.21.5': optional: true + '@esbuild/aix-ppc64@0.23.1': + optional: true + '@esbuild/android-arm64@0.21.5': optional: true + '@esbuild/android-arm64@0.23.1': + optional: true + '@esbuild/android-arm@0.21.5': optional: true + '@esbuild/android-arm@0.23.1': + optional: true + '@esbuild/android-x64@0.21.5': optional: true + '@esbuild/android-x64@0.23.1': + optional: true + '@esbuild/darwin-arm64@0.21.5': optional: true + '@esbuild/darwin-arm64@0.23.1': + optional: true + '@esbuild/darwin-x64@0.21.5': optional: true + '@esbuild/darwin-x64@0.23.1': + optional: true + '@esbuild/freebsd-arm64@0.21.5': optional: true + '@esbuild/freebsd-arm64@0.23.1': + optional: true + '@esbuild/freebsd-x64@0.21.5': optional: true + '@esbuild/freebsd-x64@0.23.1': + optional: true + '@esbuild/linux-arm64@0.21.5': optional: true + '@esbuild/linux-arm64@0.23.1': + optional: true + '@esbuild/linux-arm@0.21.5': optional: true + '@esbuild/linux-arm@0.23.1': + optional: true + '@esbuild/linux-ia32@0.21.5': optional: true + '@esbuild/linux-ia32@0.23.1': + optional: true + '@esbuild/linux-loong64@0.21.5': optional: true + '@esbuild/linux-loong64@0.23.1': + optional: true + '@esbuild/linux-mips64el@0.21.5': optional: true + '@esbuild/linux-mips64el@0.23.1': + optional: true + '@esbuild/linux-ppc64@0.21.5': optional: true + '@esbuild/linux-ppc64@0.23.1': + optional: true + '@esbuild/linux-riscv64@0.21.5': optional: true + '@esbuild/linux-riscv64@0.23.1': + optional: true + '@esbuild/linux-s390x@0.21.5': optional: true + '@esbuild/linux-s390x@0.23.1': + optional: true + '@esbuild/linux-x64@0.21.5': optional: true + '@esbuild/linux-x64@0.23.1': + optional: true + '@esbuild/netbsd-x64@0.21.5': optional: true + '@esbuild/netbsd-x64@0.23.1': + optional: true + + '@esbuild/openbsd-arm64@0.23.1': + optional: true + '@esbuild/openbsd-x64@0.21.5': optional: true + '@esbuild/openbsd-x64@0.23.1': + optional: true + '@esbuild/sunos-x64@0.21.5': optional: true + '@esbuild/sunos-x64@0.23.1': + optional: true + '@esbuild/win32-arm64@0.21.5': optional: true + '@esbuild/win32-arm64@0.23.1': + optional: true + '@esbuild/win32-ia32@0.21.5': optional: true + '@esbuild/win32-ia32@0.23.1': + optional: true + '@esbuild/win32-x64@0.21.5': optional: true + '@esbuild/win32-x64@0.23.1': + optional: true + '@eslint-community/eslint-plugin-eslint-comments@4.4.0(eslint@9.13.0(jiti@2.3.3))': dependencies: escape-string-regexp: 4.0.0 @@ -5558,6 +6072,48 @@ snapshots: '@humanwhocodes/retry@0.3.1': {} + '@iconify-json/fa@1.1.5': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify-json/tabler@1.1.95': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify/tools@3.0.5': + dependencies: + '@iconify/types': 2.0.0 + '@iconify/utils': 2.1.33 + '@types/cheerio': 0.22.35 + '@types/tar': 6.1.13 + cheerio: 1.0.0 + extract-zip: 2.0.1 + local-pkg: 0.4.3 + pathe: 1.1.2 + svgo: 3.3.2 + tar: 6.2.1 + transitivePeerDependencies: + - supports-color + + '@iconify/types@2.0.0': {} + + '@iconify/utils@2.1.33': + dependencies: + '@antfu/install-pkg': 0.4.1 + '@antfu/utils': 0.7.10 + '@iconify/types': 2.0.0 + debug: 4.3.7 + kolorist: 1.8.0 + local-pkg: 0.5.0 + mlly: 1.7.2 + transitivePeerDependencies: + - supports-color + + '@iconify/vue@4.1.1(vue@3.5.12(typescript@5.6.3))': + dependencies: + '@iconify/types': 2.0.0 + vue: 3.5.12(typescript@5.6.3) + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -5652,6 +6208,8 @@ snapshots: '@pkgr/core@0.1.1': {} + '@polka/url@1.0.0-next.28': {} + '@rollup/pluginutils@5.1.3(rollup@4.24.0)': dependencies: '@types/estree': 1.0.6 @@ -5737,6 +6295,10 @@ snapshots: '@trysound/sax@0.2.0': {} + '@types/cheerio@0.22.35': + dependencies: + '@types/node': 22.7.9 + '@types/cookie@0.6.0': {} '@types/debug@4.1.12': @@ -5780,10 +6342,20 @@ snapshots: '@types/sortablejs@1.15.8': {} + '@types/tar@6.1.13': + dependencies: + '@types/node': 22.7.9 + minipass: 4.2.8 + '@types/unist@3.0.3': {} '@types/web-bluetooth@0.0.20': {} + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 22.7.9 + optional: true + '@typescript-eslint/eslint-plugin@7.16.1(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3))(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.2)': dependencies: '@eslint-community/regexpp': 4.11.1 @@ -5933,6 +6505,157 @@ snapshots: '@typescript-eslint/types': 8.11.0 eslint-visitor-keys: 3.4.3 + '@unocss/astro@0.63.6(rollup@4.24.0)(typescript@5.6.3)(vite@5.4.10(@types/node@22.7.9)(less@4.2.0))': + dependencies: + '@unocss/core': 0.63.6 + '@unocss/reset': 0.63.6 + '@unocss/vite': 0.63.6(rollup@4.24.0)(typescript@5.6.3)(vite@5.4.10(@types/node@22.7.9)(less@4.2.0)) + optionalDependencies: + vite: 5.4.10(@types/node@22.7.9)(less@4.2.0) + transitivePeerDependencies: + - rollup + - supports-color + - typescript + + '@unocss/cli@0.63.6(rollup@4.24.0)': + dependencies: + '@ampproject/remapping': 2.3.0 + '@rollup/pluginutils': 5.1.3(rollup@4.24.0) + '@unocss/config': 0.63.6 + '@unocss/core': 0.63.6 + '@unocss/preset-uno': 0.63.6 + cac: 6.7.14 + chokidar: 3.6.0 + colorette: 2.0.20 + consola: 3.2.3 + magic-string: 0.30.12 + pathe: 1.1.2 + perfect-debounce: 1.0.0 + tinyglobby: 0.2.9 + transitivePeerDependencies: + - rollup + - supports-color + + '@unocss/config@0.63.6': + dependencies: + '@unocss/core': 0.63.6 + unconfig: 0.5.5 + transitivePeerDependencies: + - supports-color + + '@unocss/core@0.63.6': {} + + '@unocss/extractor-arbitrary-variants@0.63.6': + dependencies: + '@unocss/core': 0.63.6 + + '@unocss/inspector@0.63.6(typescript@5.6.3)': + dependencies: + '@unocss/core': 0.63.6 + '@unocss/rule-utils': 0.63.6 + gzip-size: 6.0.0 + sirv: 2.0.4 + vue-flow-layout: 0.0.5(typescript@5.6.3) + transitivePeerDependencies: + - typescript + + '@unocss/postcss@0.63.6(postcss@8.4.47)': + dependencies: + '@unocss/config': 0.63.6 + '@unocss/core': 0.63.6 + '@unocss/rule-utils': 0.63.6 + css-tree: 3.0.0 + postcss: 8.4.47 + tinyglobby: 0.2.9 + transitivePeerDependencies: + - supports-color + + '@unocss/preset-attributify@0.63.6': + dependencies: + '@unocss/core': 0.63.6 + + '@unocss/preset-icons@0.63.6': + dependencies: + '@iconify/utils': 2.1.33 + '@unocss/core': 0.63.6 + ofetch: 1.4.1 + transitivePeerDependencies: + - supports-color + + '@unocss/preset-mini@0.63.6': + dependencies: + '@unocss/core': 0.63.6 + '@unocss/extractor-arbitrary-variants': 0.63.6 + '@unocss/rule-utils': 0.63.6 + + '@unocss/preset-tagify@0.63.6': + dependencies: + '@unocss/core': 0.63.6 + + '@unocss/preset-typography@0.63.6': + dependencies: + '@unocss/core': 0.63.6 + '@unocss/preset-mini': 0.63.6 + + '@unocss/preset-uno@0.63.6': + dependencies: + '@unocss/core': 0.63.6 + '@unocss/preset-mini': 0.63.6 + '@unocss/preset-wind': 0.63.6 + '@unocss/rule-utils': 0.63.6 + + '@unocss/preset-web-fonts@0.63.6': + dependencies: + '@unocss/core': 0.63.6 + ofetch: 1.4.1 + + '@unocss/preset-wind@0.63.6': + dependencies: + '@unocss/core': 0.63.6 + '@unocss/preset-mini': 0.63.6 + '@unocss/rule-utils': 0.63.6 + + '@unocss/reset@0.63.6': {} + + '@unocss/rule-utils@0.63.6': + dependencies: + '@unocss/core': 0.63.6 + magic-string: 0.30.12 + + '@unocss/transformer-attributify-jsx@0.63.6': + dependencies: + '@unocss/core': 0.63.6 + + '@unocss/transformer-compile-class@0.63.6': + dependencies: + '@unocss/core': 0.63.6 + + '@unocss/transformer-directives@0.63.6': + dependencies: + '@unocss/core': 0.63.6 + '@unocss/rule-utils': 0.63.6 + css-tree: 3.0.0 + + '@unocss/transformer-variant-group@0.63.6': + dependencies: + '@unocss/core': 0.63.6 + + '@unocss/vite@0.63.6(rollup@4.24.0)(typescript@5.6.3)(vite@5.4.10(@types/node@22.7.9)(less@4.2.0))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@rollup/pluginutils': 5.1.3(rollup@4.24.0) + '@unocss/config': 0.63.6 + '@unocss/core': 0.63.6 + '@unocss/inspector': 0.63.6(typescript@5.6.3) + chokidar: 3.6.0 + magic-string: 0.30.12 + tinyglobby: 0.2.9 + vite: 5.4.10(@types/node@22.7.9)(less@4.2.0) + transitivePeerDependencies: + - rollup + - supports-color + - typescript + '@vitejs/plugin-vue-jsx@4.0.1(vite@5.4.10(@types/node@22.7.9)(less@4.2.0))(vue@3.5.12(typescript@5.6.3))': dependencies: '@babel/core': 7.25.9 @@ -6388,8 +7111,15 @@ snapshots: node-releases: 2.0.18 update-browserslist-db: 1.1.1(browserslist@4.24.2) + buffer-crc32@0.2.13: {} + builtin-modules@3.3.0: {} + bundle-require@5.0.0(esbuild@0.21.5): + dependencies: + esbuild: 0.21.5 + load-tsconfig: 0.2.5 + bytes@3.1.2: {} c12@1.11.2: @@ -6407,6 +7137,8 @@ snapshots: pkg-types: 1.2.1 rc9: 2.1.2 + cac@6.7.14: {} + call-bind@1.0.7: dependencies: es-define-property: 1.0.0 @@ -6436,6 +7168,29 @@ snapshots: character-entities@2.0.2: {} + cheerio-select@2.1.0: + dependencies: + boolbase: 1.0.0 + css-select: 5.1.0 + css-what: 6.1.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.1.0 + + cheerio@1.0.0: + dependencies: + cheerio-select: 2.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + domutils: 3.1.0 + encoding-sniffer: 0.2.0 + htmlparser2: 9.1.0 + parse5: 7.2.0 + parse5-htmlparser2-tree-adapter: 7.1.0 + parse5-parser-stream: 7.1.2 + undici: 6.20.1 + whatwg-mimetype: 4.0.0 + chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -6480,6 +7235,8 @@ snapshots: color-name@1.1.4: {} + colorette@2.0.20: {} + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -6560,6 +7317,11 @@ snapshots: mdn-data: 2.0.30 source-map-js: 1.2.1 + css-tree@3.0.0: + dependencies: + mdn-data: 2.10.0 + source-map-js: 1.2.1 + css-what@6.1.0: {} cssesc@3.0.0: {} @@ -6703,6 +7465,8 @@ snapshots: dotenv@16.4.5: {} + duplexer@0.1.2: {} + eastasianwidth@0.2.0: {} electron-to-chromium@1.5.43: {} @@ -6711,6 +7475,15 @@ snapshots: emoji-regex@9.2.2: {} + encoding-sniffer@0.2.0: + dependencies: + iconv-lite: 0.6.3 + whatwg-encoding: 3.1.1 + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + enhanced-resolve@5.17.1: dependencies: graceful-fs: 4.2.11 @@ -6861,6 +7634,33 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 + esbuild@0.23.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.23.1 + '@esbuild/android-arm': 0.23.1 + '@esbuild/android-arm64': 0.23.1 + '@esbuild/android-x64': 0.23.1 + '@esbuild/darwin-arm64': 0.23.1 + '@esbuild/darwin-x64': 0.23.1 + '@esbuild/freebsd-arm64': 0.23.1 + '@esbuild/freebsd-x64': 0.23.1 + '@esbuild/linux-arm': 0.23.1 + '@esbuild/linux-arm64': 0.23.1 + '@esbuild/linux-ia32': 0.23.1 + '@esbuild/linux-loong64': 0.23.1 + '@esbuild/linux-mips64el': 0.23.1 + '@esbuild/linux-ppc64': 0.23.1 + '@esbuild/linux-riscv64': 0.23.1 + '@esbuild/linux-s390x': 0.23.1 + '@esbuild/linux-x64': 0.23.1 + '@esbuild/netbsd-x64': 0.23.1 + '@esbuild/openbsd-arm64': 0.23.1 + '@esbuild/openbsd-x64': 0.23.1 + '@esbuild/sunos-x64': 0.23.1 + '@esbuild/win32-arm64': 0.23.1 + '@esbuild/win32-ia32': 0.23.1 + '@esbuild/win32-x64': 0.23.1 + escalade@3.2.0: {} escape-string-regexp@1.0.5: {} @@ -7285,6 +8085,16 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 + extract-zip@2.0.1: + dependencies: + debug: 4.3.7 + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + fast-deep-equal@3.1.3: {} fast-glob@3.3.2: @@ -7303,6 +8113,14 @@ snapshots: dependencies: reusify: 1.0.4 + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + + fdir@6.4.2(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -7387,6 +8205,10 @@ snapshots: has-symbols: 1.0.3 hasown: 2.0.2 + get-stream@5.2.0: + dependencies: + pump: 3.0.2 + get-stream@8.0.1: {} get-symbol-description@1.0.2: @@ -7489,6 +8311,10 @@ snapshots: graphemer@1.4.0: {} + gzip-size@6.0.0: + dependencies: + duplexer: 0.1.2 + has-bigints@1.0.2: {} has-flag@3.0.0: {} @@ -7523,12 +8349,18 @@ snapshots: html-tags@3.3.1: {} + htmlparser2@9.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.1.0 + entities: 4.5.0 + human-signals@5.0.0: {} iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 - optional: true ignore@5.3.2: {} @@ -7540,6 +8372,18 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 + importx@0.4.4: + dependencies: + bundle-require: 5.0.0(esbuild@0.21.5) + debug: 4.3.7 + esbuild: 0.21.5 + jiti: 2.0.0-beta.3 + jiti-v1: jiti@1.21.6 + pathe: 1.1.2 + tsx: 4.19.1 + transitivePeerDependencies: + - supports-color + imurmurhash@0.1.4: {} indent-string@4.0.0: {} @@ -7704,6 +8548,8 @@ snapshots: jiti@1.21.6: {} + jiti@2.0.0-beta.3: {} + jiti@2.3.3: {} js-tokens@4.0.0: {} @@ -7756,6 +8602,8 @@ snapshots: knitwork@1.1.0: {} + kolorist@1.8.0: {} + language-subtag-registry@0.3.23: {} language-tags@1.0.9: @@ -7787,6 +8635,10 @@ snapshots: lines-and-columns@1.2.4: {} + load-tsconfig@0.2.5: {} + + local-pkg@0.4.3: {} + local-pkg@0.5.0: dependencies: mlly: 1.7.2 @@ -7949,6 +8801,8 @@ snapshots: mdn-data@2.0.30: {} + mdn-data@2.10.0: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -8186,6 +9040,8 @@ snapshots: dependencies: yallist: 4.0.0 + minipass@4.2.8: {} + minipass@5.0.0: {} minipass@7.1.2: {} @@ -8206,6 +9062,8 @@ snapshots: mri@1.2.0: {} + mrmime@2.0.0: {} + ms@2.1.3: {} muggle-string@0.4.1: {} @@ -8311,6 +9169,12 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.0.0 + ofetch@1.4.1: + dependencies: + destr: 2.0.3 + node-fetch-native: 1.6.4 + ufo: 1.5.4 + ohash@1.1.4: {} once@1.4.0: @@ -8378,8 +9242,21 @@ snapshots: dependencies: parse5: 6.0.1 + parse5-htmlparser2-tree-adapter@7.1.0: + dependencies: + domhandler: 5.0.3 + parse5: 7.2.0 + + parse5-parser-stream@7.1.2: + dependencies: + parse5: 7.2.0 + parse5@6.0.1: {} + parse5@7.2.0: + dependencies: + entities: 4.5.0 + path-browserify@1.0.1: {} path-exists@4.0.0: {} @@ -8403,6 +9280,8 @@ snapshots: pathe@1.1.2: {} + pend@1.2.0: {} + perfect-debounce@1.0.0: {} picocolors@1.1.1: {} @@ -8503,6 +9382,11 @@ snapshots: prr@1.0.1: optional: true + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + punycode@2.3.1: {} queue-microtask@1.2.3: {} @@ -8665,8 +9549,7 @@ snapshots: es-errors: 1.3.0 is-regex: 1.1.4 - safer-buffer@2.1.2: - optional: true + safer-buffer@2.1.2: {} sax@1.4.1: optional: true @@ -8735,6 +9618,12 @@ snapshots: once: 1.4.0 simple-concat: 1.0.1 + sirv@2.0.4: + dependencies: + '@polka/url': 1.0.0-next.28 + mrmime: 2.0.0 + totalist: 3.0.1 + sisteransi@1.0.5: {} slash@3.0.0: {} @@ -8988,6 +9877,11 @@ snapshots: tinyexec@0.3.1: {} + tinyglobby@0.2.9: + dependencies: + fdir: 6.4.2(picomatch@4.0.2) + picomatch: 4.0.2 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -8996,6 +9890,8 @@ snapshots: dependencies: eslint-visitor-keys: 3.4.3 + totalist@3.0.1: {} + ts-api-utils@1.3.0(typescript@5.6.2): dependencies: typescript: 5.6.2 @@ -9015,6 +9911,13 @@ snapshots: tslib@2.8.0: {} + tsx@4.19.1: + dependencies: + esbuild: 0.23.1 + get-tsconfig: 4.8.1 + optionalDependencies: + fsevents: 2.3.3 + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -9072,6 +9975,14 @@ snapshots: has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 + unconfig@0.5.5: + dependencies: + '@antfu/utils': 0.7.10 + defu: 6.1.4 + importx: 0.4.4 + transitivePeerDependencies: + - supports-color + uncrypto@0.1.3: {} unctx@2.3.1: @@ -9085,6 +9996,8 @@ snapshots: undici-types@6.19.8: {} + undici@6.20.1: {} + unicode-canonical-property-names-ecmascript@2.0.1: {} unicode-match-property-ecmascript@2.0.0: @@ -9141,6 +10054,33 @@ snapshots: '@types/cookie': 0.6.0 cookie: 0.7.2 + unocss@0.63.6(postcss@8.4.47)(rollup@4.24.0)(typescript@5.6.3)(vite@5.4.10(@types/node@22.7.9)(less@4.2.0)): + dependencies: + '@unocss/astro': 0.63.6(rollup@4.24.0)(typescript@5.6.3)(vite@5.4.10(@types/node@22.7.9)(less@4.2.0)) + '@unocss/cli': 0.63.6(rollup@4.24.0) + '@unocss/core': 0.63.6 + '@unocss/postcss': 0.63.6(postcss@8.4.47) + '@unocss/preset-attributify': 0.63.6 + '@unocss/preset-icons': 0.63.6 + '@unocss/preset-mini': 0.63.6 + '@unocss/preset-tagify': 0.63.6 + '@unocss/preset-typography': 0.63.6 + '@unocss/preset-uno': 0.63.6 + '@unocss/preset-web-fonts': 0.63.6 + '@unocss/preset-wind': 0.63.6 + '@unocss/transformer-attributify-jsx': 0.63.6 + '@unocss/transformer-compile-class': 0.63.6 + '@unocss/transformer-directives': 0.63.6 + '@unocss/transformer-variant-group': 0.63.6 + '@unocss/vite': 0.63.6(rollup@4.24.0)(typescript@5.6.3)(vite@5.4.10(@types/node@22.7.9)(less@4.2.0)) + optionalDependencies: + vite: 5.4.10(@types/node@22.7.9)(less@4.2.0) + transitivePeerDependencies: + - postcss + - rollup + - supports-color + - typescript + unplugin-auto-import@0.18.3(@nuxt/kit@3.13.2(rollup@4.24.0))(@vueuse/core@11.1.0(vue@3.5.12(typescript@5.6.3)))(rollup@4.24.0): dependencies: '@antfu/utils': 0.7.10 @@ -9269,6 +10209,12 @@ snapshots: transitivePeerDependencies: - supports-color + vue-flow-layout@0.0.5(typescript@5.6.3): + dependencies: + vue: 3.5.12(typescript@5.6.3) + transitivePeerDependencies: + - typescript + vue-router@4.4.5(vue@3.5.12(typescript@5.6.3)): dependencies: '@vue/devtools-api': 6.6.4 @@ -9337,6 +10283,12 @@ snapshots: webpack-virtual-modules@0.6.2: {} + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + which-boxed-primitive@1.0.2: dependencies: is-bigint: 1.0.4 @@ -9423,6 +10375,11 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + yocto-queue@0.1.0: {} zwitch@2.0.4: {} diff --git a/app/postcss.config.cjs b/app/postcss.config.cjs deleted file mode 100644 index 33ad091d2..000000000 --- a/app/postcss.config.cjs +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -} diff --git a/app/src/api/acme_user.ts b/app/src/api/acme_user.ts index 76a7885ab..242ee53ef 100644 --- a/app/src/api/acme_user.ts +++ b/app/src/api/acme_user.ts @@ -11,7 +11,7 @@ export interface AcmeUser extends ModelBase { class ACMEUserCurd extends Curd { constructor() { - super('acme_user', 'acme_users') + super('acme_users') } public async register(id: number) { diff --git a/app/src/api/cert.ts b/app/src/api/cert.ts index c38ab6eea..3693f9146 100644 --- a/app/src/api/cert.ts +++ b/app/src/api/cert.ts @@ -37,6 +37,6 @@ export interface CertificateResult { key_type: PrivateKeyType } -const cert: Curd = new Curd('/cert') +const cert: Curd = new Curd('/certs') export default cert diff --git a/app/src/api/config.ts b/app/src/api/config.ts index 567448a29..b43c65ef9 100644 --- a/app/src/api/config.ts +++ b/app/src/api/config.ts @@ -14,7 +14,7 @@ export interface Config { class ConfigCurd extends Curd { constructor() { - super('/config') + super('/configs') } get_base_path() { diff --git a/app/src/api/curd.ts b/app/src/api/curd.ts index 33187ec23..c2af9d88e 100644 --- a/app/src/api/curd.ts +++ b/app/src/api/curd.ts @@ -15,28 +15,31 @@ export interface Pagination { export interface GetListResponse { data: T[] - pagination: Pagination + pagination?: Pagination } class Curd { protected readonly baseUrl: string - protected readonly plural: string get_list = this._get_list.bind(this) get = this._get.bind(this) save = this._save.bind(this) + import = this._import.bind(this) + import_check = this._import_check.bind(this) destroy = this._destroy.bind(this) recover = this._recover.bind(this) update_order = this._update_order.bind(this) + batch_save = this._batch_save.bind(this) + batch_destroy = this._batch_destroy.bind(this) + batch_recover = this._batch_recover.bind(this) - constructor(baseUrl: string, plural: string | null = null) { + constructor(baseUrl: string) { this.baseUrl = baseUrl - this.plural = plural ?? `${this.baseUrl}s` } // eslint-disable-next-line ts/no-explicit-any _get_list(params: any = null): Promise> { - return http.get(this.plural, { params }) + return http.get(this.baseUrl, { params }) } // eslint-disable-next-line ts/no-explicit-any @@ -45,10 +48,25 @@ class Curd { } // eslint-disable-next-line ts/no-explicit-any - _save(id: any = null, data: any = undefined, config: any = undefined): Promise { + _save(id: any = null, data: any = {}, config: any = undefined): Promise { return http.post(this.baseUrl + (id ? `/${id}` : ''), data, config) } + // eslint-disable-next-line ts/no-explicit-any + _import_check(formData: FormData, config: any = {}): Promise { + return http.post(`${this.baseUrl}/import_check`, formData, { + headers: { + 'Content-Type': 'multipart/form-data;charset=UTF-8', + }, + ...config, + }) + } + + // eslint-disable-next-line ts/no-explicit-any + _import(data: any, config: any = {}): Promise { + return http.post(`${this.baseUrl}/import`, data, config) + } + // eslint-disable-next-line ts/no-explicit-any _destroy(id: any = null, params: any = {}) { return http.delete(`${this.baseUrl}/${id}`, { params }) @@ -59,12 +77,34 @@ class Curd { return http.patch(`${this.baseUrl}/${id}`) } - _update_order(data: { - target_id: number - direction: number - affected_ids: number[] - }) { - return http.post(`${this.plural}/order`, data) + _update_order(data: { target_id: number, direction: number, affected_ids: number[] }) { + return http.post(`${this.baseUrl}/order`, data) + } + + // eslint-disable-next-line ts/no-explicit-any + _batch_save(ids: any, data: any) { + return http.put(this.baseUrl, { + ids, + data, + }) + } + + // eslint-disable-next-line ts/no-explicit-any + _batch_destroy(ids?: (string | number)[], params: any = {}) { + return http.delete(this.baseUrl, { + params, + data: { + ids, + }, + }) + } + + _batch_recover(ids?: (string | number)[]) { + return http.patch(this.baseUrl, { + data: { + ids, + }, + }) } } diff --git a/app/src/api/dns_credential.ts b/app/src/api/dns_credential.ts index 7596b8cda..c06313be2 100644 --- a/app/src/api/dns_credential.ts +++ b/app/src/api/dns_credential.ts @@ -17,6 +17,6 @@ export interface DnsCredential extends ModelBase { } } -const dns_credential: Curd = new Curd('/dns_credential') +const dns_credential: Curd = new Curd('/dns_credentials') export default dns_credential diff --git a/app/src/api/environment.ts b/app/src/api/environment.ts index 5897c9dfd..47163a515 100644 --- a/app/src/api/environment.ts +++ b/app/src/api/environment.ts @@ -18,11 +18,11 @@ export interface Node { class EnvironmentCurd extends Curd { constructor() { - super('/environment') + super('/environments') } load_from_settings() { - return http.post(`${this.plural}/load_from_settings`) + return http.post(`${this.baseUrl}/load_from_settings`) } } diff --git a/app/src/api/notification.ts b/app/src/api/notification.ts index 0c9f27161..8ae96be97 100644 --- a/app/src/api/notification.ts +++ b/app/src/api/notification.ts @@ -10,10 +10,10 @@ export interface Notification extends ModelBase { class NotificationCurd extends Curd { public clear() { - return http.delete(this.plural) + return http.delete(this.baseUrl) } } -const notification = new NotificationCurd('/notification') +const notification = new NotificationCurd('/notifications') export default notification diff --git a/app/src/api/domain.ts b/app/src/api/site.ts similarity index 80% rename from app/src/api/domain.ts rename to app/src/api/site.ts index 94e7d77dc..c4ae6f8ef 100644 --- a/app/src/api/domain.ts +++ b/app/src/api/site.ts @@ -1,6 +1,7 @@ import type { CertificateInfo } from '@/api/cert' import type { NgxConfig } from '@/api/ngx' import type { ChatComplicationMessage } from '@/api/openai' +import type { SiteCategory } from '@/api/site_category' import type { PrivateKeyType } from '@/constants' import Curd from '@/api/curd' import http from '@/lib/http' @@ -16,6 +17,9 @@ export interface Site { chatgpt_messages: ChatComplicationMessage[] tokenized?: NgxConfig cert_info?: Record + site_category_id: number + site_category?: SiteCategory + sync_node_ids: number[] } export interface AutoCertRequest { @@ -25,7 +29,7 @@ export interface AutoCertRequest { key_type: PrivateKeyType } -class Domain extends Curd { +class SiteCurd extends Curd { // eslint-disable-next-line ts/no-explicit-any enable(name: string, config?: any) { return http.post(`${this.baseUrl}/${name}/enable`, undefined, config) @@ -35,6 +39,10 @@ class Domain extends Curd { return http.post(`${this.baseUrl}/${name}/disable`) } + rename(oldName: string, newName: string) { + return http.post(`${this.baseUrl}/${oldName}/rename`, { new_name: newName }) + } + get_template() { return http.get('template') } @@ -56,6 +64,6 @@ class Domain extends Curd { } } -const domain = new Domain('/domain') +const site = new SiteCurd('/sites') -export default domain +export default site diff --git a/app/src/api/site_category.ts b/app/src/api/site_category.ts new file mode 100644 index 000000000..228a562f4 --- /dev/null +++ b/app/src/api/site_category.ts @@ -0,0 +1,11 @@ +import type { ModelBase } from '@/api/curd' +import Curd from '@/api/curd' + +export interface SiteCategory extends ModelBase { + name: string + sync_node_ids: number[] +} + +const site_category = new Curd('site_categories') + +export default site_category diff --git a/app/src/api/stream.ts b/app/src/api/stream.ts index e618b4d6a..6516d0f6a 100644 --- a/app/src/api/stream.ts +++ b/app/src/api/stream.ts @@ -33,6 +33,6 @@ class StreamCurd extends Curd { } } -const stream = new StreamCurd('/stream') +const stream = new StreamCurd('/streams') export default stream diff --git a/app/src/api/template.ts b/app/src/api/template.ts index 4cd4eafa6..187a44e61 100644 --- a/app/src/api/template.ts +++ b/app/src/api/template.ts @@ -23,26 +23,26 @@ export interface Template extends NgxServer { class TemplateApi extends Curd - + diff --git a/app/src/components/StdDesign/StdDataDisplay/StdCurd.vue b/app/src/components/StdDesign/StdDataDisplay/StdCurd.vue index 62016a532..38892a3ee 100644 --- a/app/src/components/StdDesign/StdDataDisplay/StdCurd.vue +++ b/app/src/components/StdDesign/StdDataDisplay/StdCurd.vue @@ -1,8 +1,8 @@